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']); } } }