Skip to content

Commit 126c383

Browse files
committed
Merge remote-tracking branch 'origin/2.4-develop' into ACP2E-3432
2 parents 4d0e1ca + 0ba9eef commit 126c383

File tree

137 files changed

+5626
-1036
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

137 files changed

+5626
-1036
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright 2024 Adobe
5+
* All Rights Reserved.
6+
*/
7+
-->
8+
9+
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
11+
<test name="StorefrontVerifyDiscountOnDynamicBundleProductDifferentCartRulesTest">
12+
<annotations>
13+
<features value="Bundle"/>
14+
<stories value="Discount on dynamic bundle products with different Cart Rules"/>
15+
<title value="Verify dynamic bundle product prices with different Cart Rules on storefront"/>
16+
<description value="Verify discount on dynamic-priced Bundle Product when associated Products are assigned to Categories with different Cart Rules"/>
17+
<severity value="MAJOR"/>
18+
<testCaseId value="AC-4709"/>
19+
</annotations>
20+
<before>
21+
<createData entity="SimpleSubCategory" stepKey="createFirstCategory"/>
22+
<createData entity="SimpleSubCategory" stepKey="createSecondCategory"/>
23+
<!--Create two simple product-->
24+
<createData entity="ApiSimpleProduct" stepKey="simpleProduct1">
25+
<requiredEntity createDataKey="createFirstCategory"/>
26+
<field key="price">99.99</field>
27+
</createData>
28+
<createData entity="ApiSimpleProduct" stepKey="simpleProduct2">
29+
<requiredEntity createDataKey="createSecondCategory"/>
30+
<field key="price">34.49</field>
31+
</createData>
32+
<!--Create Bundle product-->
33+
<createData entity="ApiBundleProductPriceViewRange" stepKey="createBundleProduct">
34+
<requiredEntity createDataKey="createFirstCategory"/>
35+
</createData>
36+
<createData entity="MultipleSelectOption" stepKey="createBundleOption1">
37+
<requiredEntity createDataKey="createBundleProduct"/>
38+
<field key="required">true</field>
39+
</createData>
40+
<createData entity="ApiBundleLink" stepKey="linkOptionToProduct">
41+
<requiredEntity createDataKey="createBundleProduct"/>
42+
<requiredEntity createDataKey="createBundleOption1"/>
43+
<requiredEntity createDataKey="simpleProduct1"/>
44+
</createData>
45+
<createData entity="ApiBundleLink" stepKey="linkOptionToProduct2">
46+
<requiredEntity createDataKey="createBundleProduct"/>
47+
<requiredEntity createDataKey="createBundleOption1"/>
48+
<requiredEntity createDataKey="simpleProduct2"/>
49+
</createData>
50+
</before>
51+
<after>
52+
<deleteData createDataKey="createFirstCategory" stepKey="deleteFirstCategory"/>
53+
<deleteData createDataKey="createSecondCategory" stepKey="deleteSecondCategory"/>
54+
<deleteData createDataKey="simpleProduct1" stepKey="deleteSimpleProduct1"/>
55+
<deleteData createDataKey="simpleProduct2" stepKey="deleteSimpleProduct2"/>
56+
<deleteData createDataKey="createBundleProduct" stepKey="deleteBundleProduct"/>
57+
<actionGroup ref="DeleteCartPriceRuleByName" stepKey="deleteCartPriceRule">
58+
<argument name="ruleName" value="{{CustomSalesRuleWithNoCouponCode.name}}"/>
59+
</actionGroup>
60+
<actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/>
61+
</after>
62+
<actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/>
63+
<!-- Create cart price rule -->
64+
<actionGroup ref="AdminCreateCartPriceRuleActionGroup" stepKey="createCartPriceRule">
65+
<argument name="ruleName" value="CustomSalesRuleWithNoCouponCode"/>
66+
</actionGroup>
67+
<!-- Search and go to cart price rule page -->
68+
<actionGroup ref="AdminFilterCartPriceRuleActionGroup" stepKey="filterCreatedCartPriceRule">
69+
<argument name="ruleName" value="CustomSalesRuleWithNoCouponCode.name"/>
70+
</actionGroup>
71+
<actionGroup ref="AdminCreateCustomConditionInCartPriceRuleActionGroup" stepKey="createCustomCondition"/>
72+
<actionGroup ref="AssertCartPriceRuleSuccessSaveMessageActionGroup" stepKey="saveAndAssertCartPriceRuleSuccessSaveMessage"/>
73+
<!-- Open Bundle Product page on storefront-->
74+
<actionGroup ref="StorefrontOpenProductPageActionGroup" stepKey="openBundleProductPage">
75+
<argument name="productUrl" value="$createBundleProduct.custom_attributes[url_key]$"/>
76+
</actionGroup>
77+
<!-- Click on customize And Add To Cart Button -->
78+
<actionGroup ref="StorefrontSelectCustomizeAndAddToTheCartButtonActionGroup" stepKey="clickOnCustomizeAndAddToCartButton"/>
79+
<!-- Select Two Products, enter the quantity and add product to the cart -->
80+
<selectOption selector="{{StorefrontBundledSection.multiSelectOption}}" parameterArray="[$$simpleProduct1.name$$ +$99.99, $$simpleProduct2.name$$ +$34.49]" stepKey="selectOptions"/>
81+
<actionGroup ref="StorefrontEnterProductQuantityAndAddToTheCartActionGroup" stepKey="enterProductQuantityAndAddToTheCart">
82+
<argument name="quantity" value="1"/>
83+
</actionGroup>
84+
<!-- Go to shopping cart page -->
85+
<actionGroup ref="StorefrontCartPageOpenActionGroup" stepKey="openShoppingCartPage"/>
86+
<actionGroup ref="AssertStorefrontCartDiscountActionGroup" stepKey="seeDiscountTotal">
87+
<argument name="discount" value="13.45"/>
88+
</actionGroup>
89+
<!-- Search and go to cart price rule page and remove condition-->
90+
<actionGroup ref="AdminOpenCartPriceRulesPageActionGroup" stepKey="goToCartPriceRulePage"/>
91+
<actionGroup ref="AdminFilterCartPriceRuleActionGroup" stepKey="filterCartPriceRule">
92+
<argument name="ruleName" value="CustomSalesRuleWithNoCouponCode.name"/>
93+
</actionGroup>
94+
<scrollTo selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" stepKey="scrollToConditionsHeader"/>
95+
<conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" visible="true" stepKey="clickToExpandConditions"/>
96+
<waitForElementClickable selector="{{AdminCartPriceRulesFormSection.removeCondition('1--1')}}" stepKey="waitForRemoveToBeClickable"/>
97+
<click selector="{{AdminCartPriceRulesFormSection.removeCondition('1--1')}}" stepKey="removeCondition"/>
98+
<actionGroup ref="AssertCartPriceRuleSuccessSaveMessageActionGroup" stepKey="saveCartPriceRuleSuccessSaveMessage"/>
99+
<!-- Go to shopping cart page -->
100+
<actionGroup ref="StorefrontCartPageOpenActionGroup" stepKey="goToShoppingCartPage"/>
101+
<actionGroup ref="AssertStorefrontCartDiscountActionGroup" stepKey="checkDiscount">
102+
<argument name="discount" value="13.45"/>
103+
</actionGroup>
104+
<!-- Assign category 1 to simple product 2 and unAssign category2 -->
105+
<actionGroup ref="AdminProductPageOpenByIdActionGroup" stepKey="OpenSimpleProductPage">
106+
<argument name="productId" value="$$simpleProduct2.id$$"/>
107+
</actionGroup>
108+
<waitForPageLoad stepKey="waitForProductPageLoad"/>
109+
<actionGroup ref="AdminUnassignCategoryOnProductAndSaveActionGroup" stepKey="unAssignCategoryTwo">
110+
<argument name="categoryName" value="$$createSecondCategory.name$$"/>
111+
</actionGroup>
112+
<createData entity="AssignProductToCategory" stepKey="assignCategoryOne">
113+
<requiredEntity createDataKey="createFirstCategory"/>
114+
<requiredEntity createDataKey="simpleProduct2"/>
115+
</createData>
116+
<!-- Search and go to cart price rule page and add condition in action tab -->
117+
<actionGroup ref="AdminOpenCartPriceRulesPageActionGroup" stepKey="againOpenCartPriceRulePage"/>
118+
<actionGroup ref="AdminFilterCartPriceRuleActionGroup" stepKey="againFilterCartPriceRule">
119+
<argument name="ruleName" value="CustomSalesRuleWithNoCouponCode.name"/>
120+
</actionGroup>
121+
<actionGroup ref="AdminCreateCustomConditionInActionTabInCartPriceRuleActionGroup" stepKey="createConditionInActionsTab"/>
122+
<actionGroup ref="AssertCartPriceRuleSuccessSaveMessageActionGroup" stepKey="saveCartPriceRule"/>
123+
<actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex">
124+
<argument name="indices" value="catalogsearch_fulltext catalog_category_product catalog_product_price catalogrule_rule"/>
125+
</actionGroup>
126+
<actionGroup ref="CliCacheCleanActionGroup" stepKey="cleanCache">
127+
<argument name="tags" value="config full_page"/>
128+
</actionGroup>
129+
<!-- Go to shopping cart page -->
130+
<actionGroup ref="StorefrontCartPageOpenActionGroup" stepKey="againGoToShoppingCartPage"/>
131+
<waitForElementNotVisible selector="{{CheckoutCartSummarySection.discountLabel}}" stepKey="discountIsNotApplied"/>
132+
</test>
133+
</tests>

app/code/Magento/Catalog/Model/ResourceModel/Category/Collection.php

Lines changed: 52 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22
/**
3-
* Copyright © Magento, Inc. All rights reserved.
4-
* See COPYING.txt for license details.
3+
* Copyright 2011 Adobe
4+
* All Rights Reserved.
55
*/
66
namespace Magento\Catalog\Model\ResourceModel\Category;
77

@@ -337,16 +337,63 @@ public function loadProductCount($items, $countRegular = true, $countAnchor = tr
337337
$categoryIds = array_keys($anchor);
338338
$countSelect = $this->getProductsCountQuery($categoryIds, (bool)$websiteId);
339339
$categoryProductsCount = $this->_conn->fetchPairs($countSelect);
340+
$countFromCategoryTable = $this->getCountFromCategoryTable($categoryIds, (int)$websiteId);
341+
340342
foreach ($anchor as $item) {
341-
$productsCount = isset($categoryProductsCount[$item->getId()])
342-
? (int)$categoryProductsCount[$item->getId()]
343-
: $this->getProductsCountFromCategoryTable($item, $websiteId);
343+
$productsCount = 0;
344+
if (isset($categoryProductsCount[$item->getId()])) {
345+
$productsCount = (int)$categoryProductsCount[$item->getId()];
346+
} elseif (isset($countFromCategoryTable[$item->getId()])) {
347+
$productsCount = (int)$countFromCategoryTable[$item->getId()];
348+
}
344349
$item->setProductCount($productsCount);
345350
}
346351
}
347352
return $this;
348353
}
349354

355+
/**
356+
* Get products number for each category with bulk query
357+
*
358+
* @param array $categoryIds
359+
* @param int $websiteId
360+
* @return array
361+
*/
362+
private function getCountFromCategoryTable(
363+
array $categoryIds,
364+
int $websiteId
365+
) : array {
366+
$subSelect = clone $this->_conn->select();
367+
$subSelect->from(['ce2' => $this->getTable('catalog_category_entity')], 'ce2.entity_id')
368+
->where("ce2.path LIKE CONCAT(ce.path, '/%')");
369+
370+
$select = clone $this->_conn->select();
371+
$select->from(
372+
['ce' => $this->getTable('catalog_category_entity')],
373+
'ce.entity_id'
374+
);
375+
$joinCondition = new \Zend_Db_Expr("ce.entity_id=cp.category_id OR cp.category_id IN ({$subSelect})");
376+
$select->joinLeft(
377+
['cp' => $this->getProductTable()],
378+
$joinCondition,
379+
'COUNT(DISTINCT cp.product_id) AS product_count'
380+
);
381+
if ($websiteId) {
382+
$select->join(
383+
['w' => $this->getProductWebsiteTable()],
384+
'cp.product_id = w.product_id',
385+
[]
386+
)->where(
387+
'w.website_id = ?',
388+
$websiteId
389+
);
390+
}
391+
$select->where('ce.entity_id IN(?)', $categoryIds);
392+
$select->group('ce.entity_id');
393+
394+
return $this->_conn->fetchPairs($select);
395+
}
396+
350397
/**
351398
* Add category path filter
352399
*
@@ -519,45 +566,6 @@ public function getProductTable()
519566
return $this->_productTable;
520567
}
521568

522-
/**
523-
* Get products count using catalog_category_entity table
524-
*
525-
* @param Category $item
526-
* @param string $websiteId
527-
* @return int
528-
*/
529-
private function getProductsCountFromCategoryTable(Category $item, string $websiteId): int
530-
{
531-
$productCount = 0;
532-
533-
if ($item->getAllChildren()) {
534-
$bind = ['entity_id' => $item->getId(), 'c_path' => $item->getPath() . '/%'];
535-
$select = $this->_conn->select();
536-
$select->from(
537-
['main_table' => $this->getProductTable()],
538-
new \Zend_Db_Expr('COUNT(DISTINCT main_table.product_id)')
539-
)->joinInner(
540-
['e' => $this->getTable('catalog_category_entity')],
541-
'main_table.category_id=e.entity_id',
542-
[]
543-
)->where(
544-
'(e.entity_id = :entity_id OR e.path LIKE :c_path)'
545-
);
546-
if ($websiteId) {
547-
$select->join(
548-
['w' => $this->getProductWebsiteTable()],
549-
'main_table.product_id = w.product_id',
550-
[]
551-
)->where(
552-
'w.website_id = ?',
553-
$websiteId
554-
);
555-
}
556-
$productCount = (int)$this->_conn->fetchOne($select, $bind);
557-
}
558-
return $productCount;
559-
}
560-
561569
/**
562570
* Get query for retrieve count of products per category
563571
*

app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<!--
33
/**
4-
* Copyright © Magento, Inc. All rights reserved.
5-
* See COPYING.txt for license details.
4+
* Copyright 2024 Adobe
5+
* All Rights Reserved.
66
*/
77
-->
88

@@ -325,6 +325,19 @@
325325
<requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity>
326326
<requiredEntity type="custom_attribute">CustomAttributeProductAttribute</requiredEntity>
327327
</entity>
328+
<entity name="ApiSimpleOne1" type="product2">
329+
<data key="name" unique="suffix">Api Simple Product</data>
330+
<data key="sku" unique="suffix">api-simple-product</data>
331+
<data key="urlKey" unique="suffix">api-simple-product</data>
332+
<data key="type_id">simple</data>
333+
<data key="attribute_set_id">4</data>
334+
<data key="visibility">4</data>
335+
<data key="price">1</data>
336+
<data key="status">1</data>
337+
<data key="quantity">1</data>
338+
<requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity>
339+
<requiredEntity type="custom_attribute">CustomAttributeProductAttribute</requiredEntity>
340+
</entity>
328341
<entity name="ApiSimpleProductWithCategory" type="product2" extends="ApiSimpleOne">
329342
<requiredEntity type="custom_attribute">CustomAttributeCategoryIds</requiredEntity>
330343
</entity>
@@ -357,6 +370,19 @@
357370
<requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity>
358371
<requiredEntity type="custom_attribute">CustomAttributeProductAttribute</requiredEntity>
359372
</entity>
373+
<entity name="ApiSimpleTwo1" type="product2">
374+
<data key="name" unique="suffix">Api Simple Product Two</data>
375+
<data key="sku" unique="suffix">api-simple-product-two</data>
376+
<data key="urlKey" unique="suffix">api-simple-product-two</data>
377+
<data key="type_id">simple</data>
378+
<data key="attribute_set_id">4</data>
379+
<data key="visibility">4</data>
380+
<data key="price">1</data>
381+
<data key="status">1</data>
382+
<data key="quantity">1</data>
383+
<requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity>
384+
<requiredEntity type="custom_attribute">CustomAttributeProductAttribute</requiredEntity>
385+
</entity>
360386
<entity name="ApiSimpleProductWithPrice50" type="product2" extends="ApiSimpleOne">
361387
<data key="price">50</data>
362388
</entity>

app/code/Magento/Catalog/Test/Mftf/Test/StorefrontCheckCustomOptionPriceDifferentCurrencyTest.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
/**
44
* Copyright © Magento, Inc. All rights reserved.
55
* See COPYING.txt for license details.
6+
* Copyright 2024 Adobe
7+
* All Rights Reserved.
68
*/
79
-->
810
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
@@ -50,6 +52,12 @@
5052
</actionGroup>
5153
<actionGroup ref="AssertStorefrontCustomOptionCheckboxByPriceActionGroup" stepKey="checkPriceProductOptionUSD">
5254
<argument name="price" value="12.3"/>
55+
</actionGroup>
56+
<actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindexConfig">
57+
<argument name="indices" value=""/>
58+
</actionGroup>
59+
<actionGroup ref="CliCacheCleanActionGroup" stepKey="cleanFullPageCache">
60+
<argument name="tags" value="config full_page"/>
5361
</actionGroup>
5462
<actionGroup ref="StorefrontSwitchCurrencyActionGroup" stepKey="switchEURCurrency">
5563
<argument name="currency" value="EUR"/>

0 commit comments

Comments
 (0)