Skip to content

Commit 1d2a097

Browse files
Merge branch '2.4-develop' into AC-15635
2 parents 37654bd + cbca039 commit 1d2a097

File tree

41 files changed

+2019
-607
lines changed

Some content is hidden

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

41 files changed

+2019
-607
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
/**
3+
* Copyright 2025 Adobe
4+
* All Rights Reserved.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Bundle\Model\ResourceModel\Indexer;
9+
10+
use Zend_Db_Expr;
11+
12+
class OptionQtyExpressionProvider
13+
{
14+
/**
15+
* Get expression for calculating available quantity for bundle option.
16+
*
17+
* @return Zend_Db_Expr
18+
*/
19+
public function getExpression(): Zend_Db_Expr
20+
{
21+
return new Zend_Db_Expr('i.qty - cisi.min_qty');
22+
}
23+
}

app/code/Magento/Bundle/Model/ResourceModel/Indexer/Stock.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
namespace Magento\Bundle\Model\ResourceModel\Indexer;
99

10+
use Magento\Bundle\Model\Product\Type;
1011
use Magento\Catalog\Model\ResourceModel\Indexer\ActiveTableSwitcher;
1112
use Magento\CatalogInventory\Model\Indexer\Stock\Action\Full;
1213
use Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\DefaultStock;
@@ -45,6 +46,7 @@ class Stock extends DefaultStock
4546
* @param ActiveTableSwitcher $activeTableSwitcher
4647
* @param StockStatusSelectBuilder $stockStatusSelectBuilder
4748
* @param BundleOptionStockDataSelectBuilder $bundleOptionStockDataSelectBuilder
49+
* @param OptionQtyExpressionProvider $optionQtyExpressionProvider
4850
* @param string $connectionName
4951
*/
5052
public function __construct(
@@ -55,10 +57,14 @@ public function __construct(
5557
ActiveTableSwitcher $activeTableSwitcher,
5658
StockStatusSelectBuilder $stockStatusSelectBuilder,
5759
BundleOptionStockDataSelectBuilder $bundleOptionStockDataSelectBuilder,
60+
private readonly OptionQtyExpressionProvider $optionQtyExpressionProvider,
5861
$connectionName = null
5962
) {
6063
parent::__construct($context, $tableStrategy, $eavConfig, $scopeConfig, $connectionName);
6164

65+
$this->_typeId = Type::TYPE_CODE;
66+
$this->_isComposite = true;
67+
6268
$this->activeTableSwitcher = $activeTableSwitcher;
6369
$this->stockStatusSelectBuilder = $stockStatusSelectBuilder;
6470
$this->bundleOptionStockDataSelectBuilder = $bundleOptionStockDataSelectBuilder;
@@ -198,11 +204,14 @@ protected function _cleanBundleOptionStockData()
198204
private function getOptionsStatusExpression(): \Zend_Db_Expr
199205
{
200206
$connection = $this->getConnection();
207+
208+
$qtyExpr = $this->optionQtyExpressionProvider->getExpression();
201209
$isAvailableExpr = $connection->getCheckSql(
202-
'bs.selection_can_change_qty = 0 AND bs.selection_qty > i.qty',
210+
'bs.selection_can_change_qty = 0 AND bs.selection_qty > ' . $qtyExpr,
203211
'0',
204212
'i.stock_status'
205213
);
214+
206215
if ($this->stockConfiguration->getBackorders()) {
207216
$backordersExpr = $connection->getCheckSql(
208217
'cisi.use_config_backorders = 0 AND cisi.backorders = 0',
@@ -216,6 +225,7 @@ private function getOptionsStatusExpression(): \Zend_Db_Expr
216225
$isAvailableExpr
217226
);
218227
}
228+
219229
if ($this->stockConfiguration->getManageStock()) {
220230
$statusExpr = $connection->getCheckSql(
221231
'cisi.use_config_manage_stock = 0 AND cisi.manage_stock = 0',
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright 2025 Adobe
5+
* All Rights Reserved.
6+
*/
7+
-->
8+
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
9+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
10+
<test name="StorefrontValidatePriceTest">
11+
<annotations>
12+
<features value="Catalog"/>
13+
<stories value="Validate Price in frontend product search and product details pages"/>
14+
<title value="Product price validation"/>
15+
<description value="This test case verifies price in frontend product search and product details pages based on catalog price scope"/>
16+
<severity value="MAJOR"/>
17+
<testCaseId value="AC-3183"/>
18+
<group value="catalog"/>
19+
</annotations>
20+
<before>
21+
<!-- Precondition 2:Create Customer with allowed remote shopping assistance-->
22+
<createData entity="Simple_US_Customer_Assistance_Allowed" stepKey="createCustomer"/>
23+
<!-- Precondition 4:Create Simple Product -->
24+
<createData entity="_defaultProduct" stepKey="createProduct">
25+
<field key="price">100</field>
26+
</createData>
27+
<actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin1"/>
28+
<!-- Precondition 1:Create website-->
29+
<actionGroup ref="AdminCreateWebsiteActionGroup" stepKey="createWebsite">
30+
<argument name="newWebsiteName" value="{{customWebsite.name}}"/>
31+
<argument name="websiteCode" value="{{customWebsite.code}}"/>
32+
</actionGroup>
33+
<!-- Create second store -->
34+
<actionGroup ref="CreateCustomStoreActionGroup" stepKey="createCustomStore">
35+
<argument name="website" value="{{customWebsite.name}}"/>
36+
<argument name="store" value="{{customStoreGroup.name}}"/>
37+
<argument name="rootCategory" value="Default Category"/>
38+
</actionGroup>
39+
<!-- Create second store view -->
40+
<actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createCustomStoreView">
41+
<argument name="StoreGroup" value="customStoreGroup"/>
42+
<argument name="customStore" value="customStoreEN"/>
43+
</actionGroup>
44+
<!--Open customer edit page-->
45+
<actionGroup ref="AdminOpenCustomerEditPageActionGroup" stepKey="openCustomerEditPage">
46+
<argument name="customerId" value="$createCustomer.id$"/>
47+
</actionGroup>
48+
<!--Navigate to "Account Information" tab-->
49+
<actionGroup ref="AdminOpenAccountInformationTabFromCustomerEditPageActionGroup" stepKey="openAccountInformationEditPage"/>
50+
<!-- Precondition 3:Assign customer to custom website-->
51+
<actionGroup ref="AdminUpdateCustomerWebsiteInCustomerInformationPageActionGroup" stepKey="updateCustomerWebsite">
52+
<argument name="websiteName" value="{{customWebsite.name}}"/>
53+
</actionGroup>
54+
<!--Verify that changes are saved successfully-->
55+
<actionGroup ref="AdminSaveCustomerAndAssertSuccessMessage" stepKey="assertThatChangesAreSavedSuccessfully"/>
56+
</before>
57+
<after>
58+
<!-- Logout from customer, delete product, customer, website -->
59+
<actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogout"/>
60+
<deleteData createDataKey="createProduct" stepKey="deleteProduct"/>
61+
<deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/>
62+
<actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="deleteWebsite">
63+
<argument name="websiteName" value="{{customWebsite.name}}"/>
64+
</actionGroup>
65+
</after>
66+
<!-- Step-1: Set catalog price scope to website -->
67+
<actionGroup ref="AdminSetCatalogPriceToWebsiteActionGroup" stepKey="setPriceScopeWebsite"/>
68+
<!-- Step 2: Reindex and cache clear -->
69+
<actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex">
70+
<argument name="indices" value=""/>
71+
</actionGroup>
72+
<actionGroup ref="CliCacheFlushActionGroup" stepKey="cleanCache">
73+
<argument name="tags" value=""/>
74+
</actionGroup>
75+
<!-- Step 3: Open created product and assign to website-->
76+
<actionGroup ref="AdminProductPageOpenByIdActionGroup" stepKey="openProductEdit">
77+
<argument name="productId" value="$createProduct.id$"/>
78+
</actionGroup>
79+
<actionGroup ref="AdminAssignProductInWebsiteActionGroup" stepKey="assignProductToSecondWebsite">
80+
<argument name="website" value="{{customWebsite.name}}"/>
81+
</actionGroup>
82+
<actionGroup ref="SaveProductFormActionGroup" stepKey="saveTheProduct"/>
83+
<!-- Step 4: Edit product and change the price in default scope-->
84+
<actionGroup ref="AdminProductPageOpenByIdActionGroup" stepKey="openTheProductEdit">
85+
<argument name="productId" value="$createProduct.id$"/>
86+
</actionGroup>
87+
<actionGroup ref="SwitchToTheNewStoreViewActionGroup" stepKey="switchDefaultStoreView">
88+
<argument name="storeViewName" value="'Default Store View'"/>
89+
</actionGroup>
90+
<waitForElementVisible selector="{{AdminProductFormSection.productPrice}}" stepKey="waitForProductPriceField"/>
91+
<uncheckOption selector="{{AdminProductFormSection.productPriceUseDefault}}" stepKey="uncheckPriceDefaultValue"/>
92+
<fillField selector="{{AdminProductFormSection.productPrice}}" userInput="150" stepKey="fillSimpleProductPrice"/>
93+
<actionGroup ref="SaveProductFormActionGroup" stepKey="saveProductPrice"/>
94+
<!-- Step 5: Edit product and change the price in custom website-->
95+
<actionGroup ref="SwitchToTheNewStoreViewActionGroup" stepKey="changeScopeToStoreView2">
96+
<argument name="storeViewName" value="{{customStoreEN.name}}"/>
97+
</actionGroup>
98+
<waitForElementVisible selector="{{AdminProductFormSection.productPrice}}" stepKey="waitForTheProductPriceField"/>
99+
<uncheckOption selector="{{AdminProductFormSection.productPriceUseDefault}}" stepKey="uncheckThePriceDefaultValue"/>
100+
<fillField selector="{{AdminProductFormSection.productPrice}}" userInput="200" stepKey="fillTheSimpleProductPrice"/>
101+
<!--Save product-->
102+
<actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/>
103+
<!--Step6: From admin login as customer to storefront and verify website scope product price is displayed in catalog search results page and product details page -->
104+
<actionGroup ref="AdminLoginAsCustomerLoginFromCustomerPageActionGroup" stepKey="loginAsCustomerFromCustomerPage">
105+
<argument name="customerId" value="$$createCustomer.id$$"/>
106+
</actionGroup>
107+
<actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchByProductName">
108+
<argument name="phrase" value="$createProduct.name$"/>
109+
</actionGroup>
110+
<waitForPageLoad stepKey="waitForSearchResultsPage" />
111+
<waitForText selector="{{StorefrontCategoryMainSection.productPrice}}" userInput="$200.00" stepKey="seeWebsiteScopeProductPriceInSearchResultsPage"/>
112+
<actionGroup ref="StorefrontOpenProductPageActionGroup" stepKey="openProductPage">
113+
<argument name="productUrl" value="$createProduct.custom_attributes[url_key]$"/>
114+
</actionGroup>
115+
<waitForText userInput="$200.00" selector="{{StorefrontProductInfoMainSection.price}}" stepKey="seeWebsiteScopeProductPrice"/>
116+
<!-- Step 7: Set catalog price scope to website -->
117+
<actionGroup ref="AdminSetDefaultCatalogPriceActionGroup" stepKey="setScopeGlobal"/>
118+
<!-- Step 8: Reindex and cache clear -->
119+
<actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindexing">
120+
<argument name="indices" value=""/>
121+
</actionGroup>
122+
<actionGroup ref="CliCacheFlushActionGroup" stepKey="cacheClean">
123+
<argument name="tags" value=""/>
124+
</actionGroup>
125+
<!--Step 9: Login as customer to storefront and verify global scope product price is displayed in catalog search results page and product details page -->
126+
<actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="searchByProductName">
127+
<argument name="phrase" value="$createProduct.name$"/>
128+
</actionGroup>
129+
<waitForPageLoad stepKey="waitSearchResult"/>
130+
<waitForText selector="{{StorefrontCategoryMainSection.productPrice}}" userInput="$100.00" stepKey="seeGlobalPrice"/>
131+
<actionGroup ref="StorefrontOpenProductPageActionGroup" stepKey="openTheProductPage">
132+
<argument name="productUrl" value="$createProduct.custom_attributes[url_key]$"/>
133+
</actionGroup>
134+
<waitForPageLoad stepKey="waitForTheProductPageToOpen"/>
135+
<waitForText userInput="$100.00" selector="{{StorefrontProductInfoMainSection.price}}" stepKey="seeTheGlobalPrice"/>
136+
</test>
137+
</tests>

app/code/Magento/CatalogInventory/Model/Adminhtml/Stock/Item.php

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@
1818
* Catalog Inventory Stock Model for adminhtml area
1919
* @method \Magento\CatalogInventory\Api\Data\StockItemExtensionInterface getExtensionAttributes()
2020
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
21+
* @SuppressWarnings(PHPMD.CookieAndSessionMisuse)
2122
* @api
2223
* @since 100.0.2
2324
*
2425
* @deprecated 100.3.0 Replaced with Multi Source Inventory
26+
* @see Nothing
2527
* @link https://developer.adobe.com/commerce/webapi/rest/inventory/index.html
2628
* @link https://developer.adobe.com/commerce/webapi/rest/inventory/inventory-api-reference.html
2729
*/
@@ -77,7 +79,9 @@ public function __construct(
7779
$resourceCollection,
7880
$data
7981
);
80-
82+
if (!empty($data)) {
83+
$this->setOrigData();
84+
}
8185
$this->groupManagement = $groupManagement;
8286
}
8387

@@ -115,6 +119,8 @@ protected function _hasDefaultNotificationMessage()
115119
}
116120

117121
/**
122+
* Check if model is used in admin area
123+
*
118124
* @return bool
119125
*/
120126
public function hasAdminArea()
@@ -123,6 +129,8 @@ public function hasAdminArea()
123129
}
124130

125131
/**
132+
* Flg to show default notification message
133+
*
126134
* @return bool
127135
* @SuppressWarnings(PHPMD.BooleanGetMethodName)
128136
*/
@@ -143,4 +151,15 @@ public function getIdentities()
143151

144152
return $tags;
145153
}
154+
155+
/**
156+
* @inheritDoc
157+
*/
158+
public function afterLoad()
159+
{
160+
parent::afterLoad();
161+
$this->setOrigData();
162+
163+
return $this;
164+
}
146165
}

app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest/QuickSearchProductByAttributeNotSearchableUsedInLayeredNavigationTest.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@
7070
<argument name="useInLayeredNavigationValue" value="Filterable (no results)"/>
7171
</actionGroup>
7272
<actionGroup ref="AdminProductAttributeSaveActionGroup" stepKey="saveMultiSelectAttribute"/>
73+
<!-- Run reindex to index invalidated indices after changes to the attribute -->
74+
<actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex">
75+
<argument name="indices" value=""/>
76+
</actionGroup>
7377

7478
<!-- Perform search with attribute value -->
7579
<actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="goToFrontPage"/>

app/code/Magento/CatalogSearch/etc/search_request.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@
2020
<queryReference clause="must" ref="visibility"/>
2121
</query>
2222
<query xsi:type="matchQuery" value="$search_term$" name="search">
23-
<match field="name" matchCondition="match_phrase_prefix"/>
23+
<match field="*"/>
2424
</query>
2525
<query xsi:type="matchQuery" value="$search_term$" name="partial_search">
26+
<match field="*"/>
2627
<match field="name" matchCondition="match_phrase_prefix"/>
2728
<match field="sku" matchCondition="match_phrase_prefix"/>
2829
</query>

app/code/Magento/Cms/Test/Mftf/ActionGroup/CreateNewPageWithWidgetActionGroup.xml

Lines changed: 0 additions & 45 deletions
This file was deleted.

app/code/Magento/Cms/Test/Mftf/class-file-naming-allowlist

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ AdminAddImageToCMSBlockContent
22
AssertBlockContent
33
AssignBlockToCMSPage
44
CreateNewPageWithBasicValues
5-
CreateNewPageWithWidget
65
FillOutBlockContent
76
FillOutCMSPageContent
87
deleteBlock

0 commit comments

Comments
 (0)