magento2-docker/dev/tests/integration/testsuite/Magento/Customer/Model/GroupExcludedWebsiteTest.php

456 lines
19 KiB
PHP
Executable File

<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);
namespace Magento\Customer\Model;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Catalog\Model\Indexer\Product\Price\Processor;
use Magento\Catalog\Model\Product;
use Magento\Catalog\Model\Product\Attribute\Source\Status as AttributeStatus;
use Magento\CatalogRule\Model\Indexer\Product\ProductRuleProcessor;
use Magento\Customer\Api\CustomerRepositoryInterface;
use Magento\Customer\Api\Data\CustomerInterface;
use Magento\Customer\Api\Data\CustomerInterfaceFactory;
use Magento\Customer\Api\Data\GroupInterfaceFactory;
use Magento\Customer\Api\GroupRepositoryInterface;
use Magento\Catalog\Model\ResourceModel\Layer\Filter\Price;
use Magento\CatalogRule\Model\Rule;
use Magento\Framework\Api\SearchCriteriaBuilder;
use Magento\Framework\DB\Adapter\AdapterInterface;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Indexer\IndexerRegistry;
use Magento\Indexer\Model\Indexer;
use Magento\Store\Api\StoreRepositoryInterface;
use Magento\Framework\App\ResourceConnection;
use Magento\CatalogRule\Model\ResourceModel\Rule as RuleResourceModel;
use Magento\Framework\ObjectManagerInterface;
use Magento\Store\Model\Group;
use Magento\Store\Model\ResourceModel\Group as StoreGroupResourceModel;
use Magento\Store\Model\ResourceModel\Store as StoreResourceModel;
use Magento\Store\Model\ResourceModel\Website as WebsiteResourceModel;
use Magento\Store\Model\Store;
use Magento\Store\Model\Website;
use Magento\TestFramework\Helper\Bootstrap;
use Magento\Framework\Registry;
use Magento\CatalogRule\Api\CatalogRuleRepositoryInterface;
use Magento\Framework\Stdlib\DateTime\DateTime;
use Magento\Indexer\Model\Indexer\Collection as IndexerCollection;
/**
* Checks excluding websites from customer group functionality that affects price and catalog rule indexes.
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class GroupExcludedWebsiteTest extends \PHPUnit\Framework\TestCase
{
private const GROUP_CODE = 'Aliens';
private const STORE_WEBSITE_CODE = 'customwebsite1';
private const STORE_GROUP_CODE = 'customstoregroup1';
private const STORE_CODE = 'customstoreview1';
private const PRODUCT_ID = 333;
private const CATEGORY_ID = 444;
private const CUSTOMER_EMAIL = 'first_last@example.com';
private const SKU = 'simplecustomproduct';
/** @var CustomerRepositoryInterface */
private $customerRepository;
/** @var ObjectManagerInterface */
private $objectManager;
/** @var CustomerInterfaceFactory */
private $customerFactory;
/** @var GroupRepositoryInterface */
private $groupRepository;
/** @var GroupInterfaceFactory */
private $groupFactory;
/** @var WebsiteResourceModel */
private $websiteResourceModel;
/** @var StoreGroupResourceModel */
private $storeGroupResourceModel;
/** @var StoreResourceModel */
private $storeResourceModel;
/** @var ProductRepositoryInterface */
private $productRepository;
/** @var ResourceConnection */
private $resourceConnection;
/** @var \Magento\Customer\Api\Data\GroupExtensionInterfaceFactory */
private $groupExtensionInterfaceFactory;
/** @var IndexerRegistry */
private $indexRegistry;
/**
* @inheritdoc
*/
protected function setUp(): void
{
$this->objectManager = Bootstrap::getObjectManager();
$this->customerRepository = $this->objectManager->create(CustomerRepositoryInterface::class);
$this->customerFactory = $this->objectManager->create(CustomerInterfaceFactory::class);
$this->groupRepository = $this->objectManager->create(GroupRepositoryInterface::class);
$this->groupFactory = $this->objectManager->create(GroupInterfaceFactory::class);
$this->websiteResourceModel = $this->objectManager->get(WebsiteResourceModel::class);
$this->storeGroupResourceModel = $this->objectManager->get(StoreGroupResourceModel::class);
$this->storeResourceModel = $this->objectManager->get(StoreResourceModel::class);
$this->productRepository = $this->objectManager->create(ProductRepositoryInterface::class);
$this->resourceConnection = $this->objectManager->get(ResourceConnection::class);
$this->groupExtensionInterfaceFactory = $this->objectManager
->get(\Magento\Customer\Api\Data\GroupExtensionInterfaceFactory::class);
$this->indexRegistry = $this->objectManager->create(IndexerRegistry::class);
}
/**
* @inheritdoc
*/
protected function tearDown(): void
{
$registry = $this->objectManager->get(Registry::class);
/** Marks area as secure so Product repository would allow product removal */
$isSecuredAreaSystemState = $registry->registry('isSecuredArea');
$registry->unregister('isSecureArea');
$registry->register('isSecureArea', true);
$storeRepository = $this->objectManager->get(StoreRepositoryInterface::class);
/** @var AdapterInterface $connection */
$connection = $this->resourceConnection->getConnection();
$productRepository = $this->objectManager->get(ProductRepositoryInterface::class);
/** @var \Magento\Store\Model\Store $store */
$store = $storeRepository->get(self::STORE_CODE);
$storeGroupId = $store->getStoreGroupId();
$websiteId = $store->getWebsiteId();
/** Remove product */
$product = $productRepository->getById(self::PRODUCT_ID);
if ($product->getId()) {
$productRepository->delete($product);
}
/** Remove customer */
/** @var CustomerInterface $customer */
$customer = $this->customerRepository->get(self::CUSTOMER_EMAIL, $websiteId);
$this->customerRepository->delete($customer);
/** Remove customer group */
$groupId = $this->findGroupIdWithCode(self::GROUP_CODE);
$group = $this->groupRepository->getById($groupId);
$this->groupRepository->delete($group);
/** Remove category */
/** @var $category \Magento\Catalog\Model\Category */
$category = $this->objectManager->create(\Magento\Catalog\Model\Category::class);
$category->load(self::CATEGORY_ID);
if ($category->getId()) {
$category->delete();
}
/** Remove store by code */
$storeCodes = [self::STORE_CODE];
$connection->delete(
$this->resourceConnection->getTableName('store'),
['code IN (?)' => $storeCodes]
);
/** Remove store group by id*/
$connection->delete(
$this->resourceConnection->getTableName('store_group'),
['group_id = ?' => $storeGroupId]
);
/** Remove website by id */
/** @var \Magento\Store\Model\Website $website */
$website = $this->objectManager->create(\Magento\Store\Model\Website::class);
$website->load((int)$websiteId);
$website->delete();
/** Remove catalog rule */
/** @var RuleResourceModel $catalogRuleResource */
$catalogRuleResource = $this->objectManager->create(RuleResourceModel::class);
$select = $connection->select();
$select->from($catalogRuleResource->getMainTable(), 'rule_id');
$select->where('name = ?', 'Test Catalog Rule With 50 Percent Off');
$ruleId = $connection->fetchOne($select);
/** @var CatalogRuleRepositoryInterface $ruleRepository */
$ruleRepository = $this->objectManager->create(CatalogRuleRepositoryInterface::class);
$ruleRepository->deleteById($ruleId);
/** @var IndexerCollection $indexerCollection */
$indexerCollection = $this->objectManager->get(IndexerCollection::class);
$indexerCollection->load();
foreach ($indexerCollection->getItems() as $indexer) {
/** @var Indexer $indexer */
$indexer->reindexAll();
}
/** Revert mark area secured */
$registry->unregister('isSecuredArea');
$registry->register('isSecuredArea', $isSecuredAreaSystemState);
}
/**
* Test excluding website from customer group
*
* @magentoDbIsolation disabled
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function testCustomerGroupExcludeWebsite(): void
{
/** Create website */
/** @var Website $website */
$website = $this->objectManager->create(Website::class);
$website->setName('custom website for customer group limitations test')
->setCode(self::STORE_WEBSITE_CODE);
$website->isObjectNew(true);
$this->websiteResourceModel->save($website);
/** Create store group */
/** @var Group $storeGroup */
$storeGroup = $this->objectManager->create(Group::class);
$storeGroup->setCode(self::STORE_GROUP_CODE)
->setName('custom store group for customer group limitations test')
->setWebsite($website);
$this->storeGroupResourceModel->save($storeGroup);
$website->setDefaultGroupId($storeGroup->getId());
$this->websiteResourceModel->save($website);
/** Create store */
/** @var Store $store */
$store = $this->objectManager->create(Store::class);
$store->setName('custom store for customer group limitations test')
->setCode(self::STORE_CODE)
->setGroup($storeGroup);
$store->setWebsite($website);
$this->storeResourceModel->save($store);
$storeId = $store->getId();
$storeGroup->setDefaultStoreId($storeId);
$websiteId = $store->getWebsiteId();
$this->storeGroupResourceModel->save($storeGroup);
/** Create a new customer group */
$group = $this->groupFactory->create()
->setId(null)
->setCode(self::GROUP_CODE)
->setTaxClassId(3);
$groupId = $this->groupRepository->save($group)->getId();
self::assertNotNull($groupId);
/** Create a new customer */
$firstname = 'First';
$lastname = 'Last';
$newCustomerEntity = $this->customerFactory->create()
->setGroupId($groupId)
->setStoreId($storeId)
->setEmail(self::CUSTOMER_EMAIL)
->setFirstname($firstname)
->setLastname($lastname)
->setWebsiteId($websiteId);
$this->customerRepository->save($newCustomerEntity);
/** Create new category */
/** @var \Magento\Catalog\Model\Category $category */
$category = $this->objectManager->create(\Magento\Catalog\Model\Category::class);
$category->isObjectNew(true);
$category->setId(self::CATEGORY_ID)
->setCreatedAt('2020-06-23 09:50:07')
->setName('Misc')
->setParentId(2)
->setPath('1/2/444')
->setLevel(2)
->setAvailableSortBy(['position', 'name'])
->setIsActive(true)
->setPosition(1)
->setStoreId($storeId)
->save();
/** Create product */
/** @var $product Product */
$product = $this->objectManager->create(Product::class);
$product->isObjectNew(true);
$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE)
->setId(self::PRODUCT_ID)
->setAttributeSetId(4)
->setName('Simple Product custom')
->setSku(self::SKU)
->setTaxClassId('none')
->setDescription('description')
->setShortDescription('short description')
->setOptionsContainer('container1')
->setMsrpDisplayActualPriceType(\Magento\Msrp\Model\Product\Attribute\Source\Type::TYPE_IN_CART)
->setPrice(10)
->setWeight(1)
->setMetaTitle('meta title')
->setMetaKeyword('meta keyword')
->setMetaDescription('meta description')
->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH)
->setStatus(AttributeStatus::STATUS_ENABLED)
->setWebsiteIds([$websiteId])
->setCategoryIds([self::CATEGORY_ID])
->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]);
$this->productRepository->save($product);
$product = $this->productRepository->get(self::SKU);
$productId = $product->getId();
/** Create catalog rule */
$catalogRule = $this->objectManager->create(Rule::class);
$catalogRule
->setIsActive(1)
->setName('Test Catalog Rule With 50 Percent Off')
->setCustomerGroupIds($groupId)
->setDiscountAmount(50)
->setWebsiteIds([$websiteId])
->setSimpleAction('by_percent')
->setStopRulesProcessing(false)
->setSortOrder(0)
->setSubIsEnable(0)
->setSubDiscountAmount(0)
->save();
$this->reindexPriceAndCatalogRule();
/** Check that there is no customer group excluded website in price or catalog rule indexes */
$this->checkNoExcludedWebsite((int)$websiteId, (int)$groupId, (int)$productId);
/** Exclude website from customer group */
$group = $this->groupRepository->getById($groupId);
$customerGroupExtensionAttributes = $this->groupExtensionInterfaceFactory->create();
$customerGroupExtensionAttributes->setExcludeWebsiteIds([$websiteId]);
$group->setExtensionAttributes($customerGroupExtensionAttributes);
$this->groupRepository->save($group);
$this->reindexPriceAndCatalogRule();
/** Check that excluding website from customer group affects catalog rule */
$resource = $resource = $this->objectManager->get(RuleResourceModel::class);
$date = $this->objectManager->get(DateTime::class);
$rules = $resource->getRulesFromProduct($date->gmtDate(), $websiteId, $groupId, $productId);
self::assertCount(0, $rules);
// check that excluded website is eliminated from catalogrule_group_website table
$connection = $this->resourceConnection->getConnection();
$selectCatalogRuleGroupWebsite = $connection->select();
$selectCatalogRuleGroupWebsite->from('catalogrule_group_website')
->where('customer_group_id = ?', $groupId);
$catalogRuleGroupWebsites = $connection->fetchAll($selectCatalogRuleGroupWebsite);
self::assertCount(0, $catalogRuleGroupWebsites);
/** Check that excluding website from customer group affects price index */
/** @var Price $catalogProductIndexPriceResource */
$catalogProductIndexPriceResource = $this->objectManager->create(Price::class);
$select = $connection->select();
$select->from($catalogProductIndexPriceResource->getMainTable());
$select->where('customer_group_id = ?', $groupId);
$prices = $connection->fetchAll($select);
self::assertCount(0, $prices);
/** Delete excluded website from customer group */
$group = $this->groupRepository->getById($groupId);
$customerGroupExtensionAttributes = $this->groupExtensionInterfaceFactory->create();
$customerGroupExtensionAttributes->setExcludeWebsiteIds([]);
$group->setExtensionAttributes($customerGroupExtensionAttributes);
$this->groupRepository->save($group);
$this->reindexPriceAndCatalogRule();
/** Check that there is no excluded website from customer group in price or catalog rule indexes */
$this->checkNoExcludedWebsite((int)$websiteId, (int)$groupId, (int)$productId);
}
/**
* Find the customer group with a given code.
*
* @param string $code
* @return int
* @throws LocalizedException
*/
private function findGroupIdWithCode(string $code): int
{
/** @var GroupRepositoryInterface $groupRepository */
$groupRepository = $this->objectManager->create(GroupRepositoryInterface::class);
/** @var SearchCriteriaBuilder $searchBuilder */
$searchBuilder = $this->objectManager->create(SearchCriteriaBuilder::class);
foreach ($groupRepository->getList($searchBuilder->create())->getItems() as $group) {
if ($group->getCode() === $code) {
return (int)$group->getId();
}
}
return -1;
}
/**
* Reindex product price and catalog rule indexes.
*
* @throws \Exception
*/
private function reindexPriceAndCatalogRule(): void
{
$priceIndexer = $this->indexRegistry->get(Processor::INDEXER_ID);
$priceIndexer->reindexAll();
$catalogRuleIndexer = $this->indexRegistry->get(ProductRuleProcessor::INDEXER_ID);
$catalogRuleIndexer->reindexAll();
}
/**
* Check that there is no customer group excluded website in price or catalog rule indexes.
*
* @param int $websiteId
* @param int $groupId
* @param int $productId
* @return void
* @throws LocalizedException
*/
private function checkNoExcludedWebsite(int $websiteId, int $groupId, int $productId): void
{
/** Check catalog rule */
$date = $this->objectManager->create(DateTime::class);
$dateTs = $date->gmtDate();
/** @var RuleResourceModel $resource */
$resource = $this->objectManager->create(RuleResourceModel::class);
$rules = $resource->getRulesFromProduct($dateTs, $websiteId, $groupId, $productId);
self::assertCount(1, $rules);
foreach ($rules as $rule) {
self::assertEquals($groupId, $rule['customer_group_id']);
self::assertEquals($websiteId, $rule['website_id']);
}
$connection = $this->resourceConnection->getConnection();
$selectCatalogRuleGroupWebsite = $connection->select();
$selectCatalogRuleGroupWebsite->from('catalogrule_group_website')
->where('customer_group_id = ?', $groupId);
$catalogRuleGroupWebsites = $connection->fetchAll($selectCatalogRuleGroupWebsite);
self::assertCount(1, $catalogRuleGroupWebsites);
foreach ($catalogRuleGroupWebsites as $catalogRuleGroupWebsite) {
self::assertEquals($groupId, $catalogRuleGroupWebsite['customer_group_id']);
self::assertEquals($websiteId, $catalogRuleGroupWebsite['website_id']);
}
/** Check price index */
/** @var Price $catalogProductIndexPriceResource */
$catalogProductIndexPriceResource = $this->objectManager->create(Price::class);
$select = $connection->select();
$select->from($catalogProductIndexPriceResource->getMainTable());
$select->where('customer_group_id = ?', $groupId);
$prices = $connection->fetchAll($select);
self::assertCount(1, $prices);
foreach ($prices as $price) {
self::assertEquals($groupId, $price['customer_group_id']);
self::assertEquals($websiteId, $price['website_id']);
}
}
}