Skip to content

Commit 2b7cb2e

Browse files
Merge branch 'develop' into L3-PR-2023-09-06
2 parents bd65183 + 8e0a981 commit 2b7cb2e

File tree

14 files changed

+523
-33
lines changed

14 files changed

+523
-33
lines changed

InventoryAdminUi/Test/Mftf/Data/MsiProductData.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@
128128
<data key="notifyQuantity">1</data>
129129
<data key="attribute_set_id">4</data>
130130
<data key="visibility">4</data>
131+
<requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity>
131132
</entity>
132133
<entity name="SimpleMsiProductWithSKU01234" type="product">
133134
<data key="name" unique="suffix">Simple MSI Product </data>
@@ -141,5 +142,6 @@
141142
<data key="notifyQuantity">1</data>
142143
<data key="attribute_set_id">4</data>
143144
<data key="visibility">4</data>
145+
<requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity>
144146
</entity>
145147
</entities>

InventoryAdminUi/Test/Mftf/Test/AdminMassActionUnAssignAllProductSourcesFromSimpleProductTest.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,10 @@
5454
<createData entity="SimpleProduct" stepKey="createFirstSimpleProduct">
5555
<requiredEntity createDataKey="createCategory"/>
5656
</createData>
57-
<createData entity="SimpleProduct" stepKey="createSecondSimpleProduct">
57+
<createData entity="SimpleMsiProductWithSKU1234" stepKey="createSecondSimpleProduct">
5858
<requiredEntity createDataKey="createCategory"/>
5959
</createData>
60-
<createData entity="SimpleProduct" stepKey="createThirdSimpleProduct">
60+
<createData entity="SimpleMsiProductWithSKU01234" stepKey="createThirdSimpleProduct">
6161
<requiredEntity createDataKey="createCategory"/>
6262
</createData>
6363
<createData entity="SimpleProduct" stepKey="createFourthSimpleProduct">

InventoryAdminUi/Test/Mftf/Test/AdminValidateInventorySourcesShouldUnassigned.xml

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

99
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
1010
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
11-
<test name="AdminValidateInventorySourcesShouldUnassigned">
11+
<test name="AdminValidateInventorySourcesShouldUnassigned" deprecated="This test is a duplicate. Here is the test that does the same a little bit more: AdminMassActionUnAssignAllProductSourcesFromSimpleProductTest.">
1212
<annotations>
1313
<features value="Unassign source from product"/>
1414
<stories value="Unassign source from product"/>
@@ -17,6 +17,11 @@
1717
<severity value="MAJOR"/>
1818
<testCaseId value="AC-2869"/>
1919
<group value="cloud"/>
20+
<group value="msi"/>
21+
<group value="multi_mode"/>
22+
<skip>
23+
<issueId value="DUPLICATE" />
24+
</skip>
2025
</annotations>
2126
<before>
2227
<!--Login to Admin-->

InventoryAdminUi/Test/Mftf/Test/GuestCustomerCreateOrderWithBundleProductSingleStockModeTest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@
120120
<argument name="selector" value="AdminProductGridFilterSection.skuFilter"/>
121121
<argument name="value" value="$$simpleProduct.sku$$"/>
122122
</actionGroup>
123-
<see selector="{{AdminProductGridSection.quantity('1')}}" userInput="1000.0000" stepKey="checkSimpleProductSourceQtyAfterPlaceOrder"/>
123+
<see selector="{{AdminProductGridSection.quantity('1')}}" userInput="{{SimpleProduct.quantity}}" stepKey="checkSimpleProductSourceQtyAfterPlaceOrder"/>
124124
<see selector="{{AdminProductGridSection.productSalableQty('1',_defaultStock.name)}}" userInput="995" stepKey="checkSimpleProductSalableQtyAfterPlaceOrder"/>
125125
</test>
126126
</tests>

InventoryCatalog/Plugin/InventoryApi/SynchronizeLegacyStockAfterDecrementStockPlugin.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Magento\InventoryCatalog\Model\ResourceModel\DecrementQtyForLegacyStock;
1919
use Magento\InventoryCatalog\Model\ResourceModel\SetDataToLegacyStockStatus;
2020
use Magento\InventoryCatalogApi\Model\GetProductIdsBySkusInterface;
21+
use Magento\InventoryCatalogApi\Api\DefaultSourceProviderInterface;
2122

2223
/**
2324
* Synchronization between legacy Stock Items and saved Source Items after decrement quantity of stock item
@@ -59,6 +60,11 @@ class SynchronizeLegacyStockAfterDecrementStockPlugin
5960
*/
6061
private $stockStateProvider;
6162

63+
/**
64+
* @var DefaultSourceProviderInterface
65+
*/
66+
private $defaultSourceProvider;
67+
6268
/**
6369
* @param DecrementQtyForLegacyStock $decrementQuantityForLegacyCatalogInventory
6470
* @param GetProductIdsBySkusInterface $getProductIdsBySkus
@@ -67,6 +73,7 @@ class SynchronizeLegacyStockAfterDecrementStockPlugin
6773
* @param StockItemCriteriaInterfaceFactory $legacyStockItemCriteriaFactory
6874
* @param StockItemRepositoryInterface $legacyStockItemRepository
6975
* @param StockStateProviderInterface $stockStateProvider
76+
* @param DefaultSourceProviderInterface $defaultSourceProvider
7077
*/
7178
public function __construct(
7279
DecrementQtyForLegacyStock $decrementQuantityForLegacyCatalogInventory,
@@ -75,7 +82,8 @@ public function __construct(
7582
SetDataToLegacyStockStatus $setDataToLegacyStockStatus,
7683
StockItemCriteriaInterfaceFactory $legacyStockItemCriteriaFactory,
7784
StockItemRepositoryInterface $legacyStockItemRepository,
78-
StockStateProviderInterface $stockStateProvider
85+
StockStateProviderInterface $stockStateProvider,
86+
DefaultSourceProviderInterface $defaultSourceProvider
7987
) {
8088
$this->decrementQuantityForLegacyCatalogInventory = $decrementQuantityForLegacyCatalogInventory;
8189
$this->getProductIdsBySkus = $getProductIdsBySkus;
@@ -84,9 +92,12 @@ public function __construct(
8492
$this->legacyStockItemCriteriaFactory = $legacyStockItemCriteriaFactory;
8593
$this->legacyStockItemRepository = $legacyStockItemRepository;
8694
$this->stockStateProvider = $stockStateProvider;
95+
$this->defaultSourceProvider = $defaultSourceProvider;
8796
}
8897

8998
/**
99+
* Manage salable quantity for `default` stock
100+
*
90101
* @param DecrementSourceItemQty $subject
91102
* @param void $result
92103
* @param SourceItemInterface[] $sourceItemDecrementData
@@ -99,6 +110,9 @@ public function afterExecute(DecrementSourceItemQty $subject, $result, array $so
99110
$this->decrementQuantityForLegacyCatalogInventory->execute($sourceItemDecrementData);
100111
$sourceItems = array_column($sourceItemDecrementData, 'source_item');
101112
foreach ($sourceItems as $sourceItem) {
113+
if ($sourceItem->getSourceCode() !== $this->defaultSourceProvider->getCode()) {
114+
continue;
115+
}
102116
$sku = $sourceItem->getSku();
103117
$productId = (int)$this->getProductIdsBySkus->execute([$sku])[$sku];
104118
$productIds[] = $productId;
Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\InventoryCatalog\Test\Unit\Plugin\InventoryApi;
9+
10+
use Magento\CatalogInventory\Api\Data\StockItemCollectionInterface;
11+
use Magento\CatalogInventory\Api\Data\StockItemInterface;
12+
use Magento\CatalogInventory\Api\StockItemCriteriaInterface;
13+
use Magento\CatalogInventory\Api\StockItemCriteriaInterfaceFactory;
14+
use Magento\CatalogInventory\Api\StockItemRepositoryInterface;
15+
use Magento\CatalogInventory\Model\Indexer\Stock\Processor;
16+
use Magento\CatalogInventory\Model\Spi\StockStateProviderInterface;
17+
use Magento\CatalogInventory\Model\Stock;
18+
use Magento\Inventory\Model\SourceItem\Command\DecrementSourceItemQty;
19+
use Magento\InventoryApi\Api\Data\SourceItemInterface;
20+
use Magento\InventoryCatalog\Model\ResourceModel\DecrementQtyForLegacyStock;
21+
use Magento\InventoryCatalog\Model\ResourceModel\SetDataToLegacyStockStatus;
22+
use Magento\InventoryCatalog\Plugin\InventoryApi\SynchronizeLegacyStockAfterDecrementStockPlugin;
23+
use Magento\InventoryCatalogApi\Api\DefaultSourceProviderInterface;
24+
use Magento\InventoryCatalogApi\Model\GetProductIdsBySkusInterface;
25+
use PHPUnit\Framework\MockObject\MockObject;
26+
use PHPUnit\Framework\TestCase;
27+
28+
/**
29+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
30+
*/
31+
class SynchronizeLegacyStockAfterDecrementStockPluginTest extends TestCase
32+
{
33+
/**
34+
* @var DecrementSourceItemQty|MockObject
35+
*/
36+
private $subjectMock;
37+
38+
/**
39+
* @var SourceItemInterface|MockObject
40+
*/
41+
private $sourceItemMock;
42+
43+
/**
44+
* @var SynchronizeLegacyStockAfterDecrementStockPlugin
45+
*/
46+
private $plugin;
47+
48+
/**
49+
* @var DecrementQtyForLegacyStock|MockObject
50+
*/
51+
private $decrementQuantityForLegacyCatalogInventoryMock;
52+
53+
/**
54+
* @var GetProductIdsBySkusInterface|MockObject
55+
*/
56+
private $getProductIdsBySkusMock;
57+
58+
/**
59+
* @var Processor|MockObject
60+
*/
61+
private $indexerProcessorMock;
62+
63+
/**
64+
* @var SetDataToLegacyStockStatus|MockObject
65+
*/
66+
private $setDataToLegacyStockStatusMock;
67+
68+
/**
69+
* @var StockItemCriteriaInterfaceFactory|MockObject
70+
*/
71+
private $legacyStockItemCriteriaFactoryMock;
72+
73+
/**
74+
* @var StockItemRepositoryInterface|MockObject
75+
*/
76+
private $legacyStockItemRepositoryMock;
77+
78+
/**
79+
* @var StockStateProviderInterface|MockObject
80+
*/
81+
private $stockStateProviderMock;
82+
83+
/**
84+
* @var DefaultSourceProviderInterface|MockObject
85+
*/
86+
private $defaultSourceProviderMock;
87+
88+
public function setUp(): void
89+
{
90+
$this->subjectMock = $this->getMockBuilder(DecrementSourceItemQty::class)
91+
->disableOriginalConstructor()
92+
->getMock();
93+
94+
$this->sourceItemMock = $this->getMockBuilder(SourceItemInterface::class)
95+
->disableOriginalConstructor()
96+
->getMock();
97+
98+
$this->decrementQuantityForLegacyCatalogInventoryMock = $this->getMockBuilder(DecrementQtyForLegacyStock::class)
99+
->disableOriginalConstructor()
100+
->getMock();
101+
102+
$this->getProductIdsBySkusMock = $this->getMockBuilder(GetProductIdsBySkusInterface::class)
103+
->disableOriginalConstructor()
104+
->getMock();
105+
106+
$this->indexerProcessorMock = $this->getMockBuilder(Processor::class)
107+
->disableOriginalConstructor()
108+
->getMock();
109+
110+
$this->setDataToLegacyStockStatusMock = $this->getMockBuilder(SetDataToLegacyStockStatus::class)
111+
->disableOriginalConstructor()
112+
->getMock();
113+
114+
$this->legacyStockItemCriteriaFactoryMock = $this->getMockBuilder(StockItemCriteriaInterfaceFactory::class)
115+
->disableOriginalConstructor()
116+
->getMock();
117+
118+
$this->legacyStockItemRepositoryMock = $this->getMockBuilder(StockItemRepositoryInterface::class)
119+
->disableOriginalConstructor()
120+
->getMock();
121+
122+
$this->stockStateProviderMock = $this->getMockBuilder(StockStateProviderInterface::class)
123+
->disableOriginalConstructor()
124+
->getMock();
125+
126+
$this->defaultSourceProviderMock = $this->getMockBuilder(DefaultSourceProviderInterface::class)
127+
->getMockForAbstractClass();
128+
129+
$this->plugin = new SynchronizeLegacyStockAfterDecrementStockPlugin(
130+
$this->decrementQuantityForLegacyCatalogInventoryMock,
131+
$this->getProductIdsBySkusMock,
132+
$this->indexerProcessorMock,
133+
$this->setDataToLegacyStockStatusMock,
134+
$this->legacyStockItemCriteriaFactoryMock,
135+
$this->legacyStockItemRepositoryMock,
136+
$this->stockStateProviderMock,
137+
$this->defaultSourceProviderMock
138+
);
139+
}
140+
141+
/**
142+
* Test to verify the change in salable quantity for `default` stock
143+
*
144+
* @param $sourceCode
145+
* @param $productId
146+
* @param $itemSku
147+
* @param $qty
148+
* @param $stockStatus
149+
* @dataProvider getDataProvider
150+
* @return void
151+
*/
152+
public function testAfterExecute($sourceCode, $productId, $itemSku, $qty, $stockStatus): void
153+
{
154+
$defaultSourceCode = 'default';
155+
$this->defaultSourceProviderMock->expects($this->atLeastOnce())->method('getCode')
156+
->willReturn($defaultSourceCode);
157+
$this->sourceItemMock->method('getSku')->willReturn($itemSku);
158+
$this->sourceItemMock->method('getSourceCode')->willReturn($sourceCode);
159+
$this->sourceItemMock->method('getQuantity')->willReturn((float)$qty);
160+
$this->sourceItemMock->method('getStatus')->willReturn($stockStatus);
161+
162+
if ($sourceCode !== $defaultSourceCode) {
163+
$this->sourceItemMock->expects($this->any())->method('getSku')->willReturn($itemSku);
164+
$this->getProductIdsBySkusMock->expects($this->never())->method('execute');
165+
} else {
166+
$this->sourceItemMock->expects($this->exactly(2))->method('getSku')->willReturn($itemSku);
167+
$this->getProductIdsBySkusMock->expects($this->once())->method('execute')
168+
->willReturn([$itemSku => $productId]);
169+
170+
$this->getProductIdsBySkusMock->expects($this->atLeastOnce())->method('execute')->with([$itemSku])
171+
->willReturn([$itemSku => $productId]);
172+
173+
$stockItemMock = $this->getMockBuilder(StockItemInterface::class)
174+
->onlyMethods(['getManageStock', 'setIsInStock', 'setQty'])
175+
->disableOriginalConstructor()
176+
->getMockForAbstractClass();
177+
$stockItemMock->expects($this->once())->method('getManageStock')->willReturn(true);
178+
$stockItemMock->expects($this->once())->method('setIsInStock')->willReturn($stockStatus);
179+
$stockItemMock->expects($this->once())->method('setQty')->willReturn($qty);
180+
181+
$this->sourceItemMock->expects($this->exactly(2))->method('getQuantity')->willReturn($qty);
182+
$stockItems = [
183+
$stockItemMock,
184+
];
185+
186+
$stockItemCollection = $this->createConfiguredMock(
187+
StockItemCollectionInterface::class,
188+
['getItems' => $stockItems]
189+
);
190+
$searchCriteria = $this->createMock(StockItemCriteriaInterface::class);
191+
$searchCriteria->expects($this->exactly(2))
192+
->method('addFilter')
193+
->withConsecutive(
194+
[StockItemInterface::PRODUCT_ID, StockItemInterface::PRODUCT_ID, $productId],
195+
[StockItemInterface::STOCK_ID, StockItemInterface::STOCK_ID, Stock::DEFAULT_STOCK_ID]
196+
)
197+
->willReturnSelf();
198+
$stockItemCollection->expects($this->once())->method('getTotalCount')->willReturn(1);
199+
$this->legacyStockItemRepositoryMock->method('getList')
200+
->willReturn($stockItemCollection);
201+
$this->legacyStockItemCriteriaFactoryMock->method('create')
202+
->willReturn($searchCriteria);
203+
204+
$this->stockStateProviderMock->expects($this->once())->method('verifyStock')
205+
->with($stockItemMock)
206+
->willReturn(true);
207+
208+
$this->setDataToLegacyStockStatusMock->expects($this->once())->method('execute')
209+
->with($itemSku, $qty, $stockStatus)
210+
->willReturnSelf();
211+
212+
$this->indexerProcessorMock->expects($this->once())
213+
->method('reindexList')
214+
->with([$productId])
215+
->willReturnSelf();
216+
}
217+
218+
$sourceItemDecrementData[] = [
219+
'source_item' => $this->sourceItemMock,
220+
'qty_to_decrement' => $qty
221+
];
222+
$this->plugin->afterExecute($this->subjectMock, null, $sourceItemDecrementData);
223+
}
224+
225+
/**
226+
* @return array[]
227+
*/
228+
public function getDataProvider(): array
229+
{
230+
return [
231+
['default', 1, 'SKU-1', 1.0, 1],
232+
['custom_source', 1, 'SKU-1', 1.0, 0]
233+
];
234+
}
235+
}

0 commit comments

Comments
 (0)