Skip to content

Commit 36f759e

Browse files
authored
Merge pull request #170 from magento-engcom/msi-add-reservation-to-stockItem-table
MSI: Update old StockItem and Stock Status DB table at the time of Reservation appended
2 parents 1ddb686 + 2e6976c commit 36f759e

File tree

5 files changed

+277
-0
lines changed

5 files changed

+277
-0
lines changed

app/code/Magento/InventoryApi/Test/_files/products.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,32 @@
1616
$productRepository = $objectManager->get(ProductRepositoryInterface::class);
1717
$productRepository->cleanCache();
1818

19+
$stockData = [
20+
'SKU-1' => [
21+
'qty' => 8.5,
22+
'is_in_stock' => true,
23+
'manage_stock' => true
24+
],
25+
'SKU-2' => [
26+
'qty' => 5,
27+
'is_in_stock' => true,
28+
'manage_stock' => true
29+
],
30+
'SKU-3' => [
31+
'qty' => 0,
32+
'is_in_stock' => false,
33+
'manage_stock' => true
34+
]
35+
];
36+
1937
for ($i = 1; $i <= 3; $i++) {
2038
$product = $productFactory->create();
2139
$product->setTypeId(Type::TYPE_SIMPLE)
2240
->setAttributeSetId(4)
2341
->setName('Simple Product ' . $i)
2442
->setSku('SKU-' . $i)
2543
->setPrice(10)
44+
->setStockData($stockData['SKU-' . $i])
2645
->setStatus(Status::STATUS_ENABLED);
2746
$productRepository->save($product);
2847
}

app/code/Magento/InventoryApi/Test/_files/products_rollback.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
* See COPYING.txt for license details.
55
*/
66
use Magento\Catalog\Api\ProductRepositoryInterface;
7+
use Magento\CatalogInventory\Api\StockStatusCriteriaInterfaceFactory;
8+
use Magento\CatalogInventory\Api\StockStatusRepositoryInterface;
79
use Magento\Framework\Registry;
810
use Magento\TestFramework\Helper\Bootstrap;
911

@@ -12,12 +14,25 @@
1214
$productRepository = $objectManager->create(ProductRepositoryInterface::class);
1315
/** @var Registry $registry */
1416
$registry = $objectManager->get(Registry::class);
17+
/** @var StockStatusRepositoryInterface $stockStatusRepository */
18+
$stockStatusRepository = $objectManager->create(StockStatusRepositoryInterface::class);
19+
/** @var StockStatusCriteriaInterfaceFactory $stockStatusCriteriaFactory */
20+
$stockStatusCriteriaFactory = $objectManager->create(StockStatusCriteriaInterfaceFactory::class);
1521

1622
$currentArea = $registry->registry('isSecureArea');
1723
$registry->unregister('isSecureArea');
1824
$registry->register('isSecureArea', true);
1925

2026
for ($i = 1; $i <= 3; $i++) {
27+
$product = $productRepository->get('SKU-' . $i);
28+
/** @var \Magento\CatalogInventory\Api\StockStatusCriteriaInterfaceFactory $stockStatusCriteriaFactory **/
29+
$criteria = $stockStatusCriteriaFactory->create();
30+
$criteria->setProductsFilter($product->getId());
31+
32+
$result = $stockStatusRepository->getList($criteria);
33+
$stockStatus = current($result->getItems());
34+
$stockStatusRepository->delete($stockStatus);
35+
2136
$productRepository->deleteById('SKU-' . $i);
2237
}
2338

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\InventoryCatalog\Plugin\Model;
8+
9+
use Magento\Framework\App\ResourceConnection;
10+
use Magento\InventoryApi\Api\Data\ReservationInterface;
11+
use Magento\InventoryApi\Api\ReservationsAppendInterface;
12+
use Magento\Catalog\Api\ProductRepositoryInterface;
13+
use Magento\CatalogInventory\Api\StockRegistryInterface;
14+
15+
/**
16+
* Plugin help to fill the legacy catalog inventory tables cataloginventory_stock_status and
17+
* cataloginventory_stock_item to don't break the backward compatible.
18+
*/
19+
class UpdateLegacyCatalogInventoryPlugin
20+
{
21+
22+
/**
23+
* @var ResourceConnection
24+
*/
25+
private $resourceConnection;
26+
27+
/**
28+
* @var ProductRepositoryInterface
29+
*/
30+
private $productRepository;
31+
32+
/**
33+
* @var \Magento\CatalogInventory\Api\StockRegistryInterface
34+
*/
35+
private $stockRegistry;
36+
37+
/**
38+
* @param ResourceConnection $resourceConnection
39+
* @param ProductRepositoryInterface $productRepository
40+
* @param StockRegistryInterface $stockRegistry
41+
*/
42+
public function __construct(
43+
ResourceConnection $resourceConnection,
44+
ProductRepositoryInterface $productRepository,
45+
StockRegistryInterface $stockRegistry
46+
) {
47+
$this->resourceConnection = $resourceConnection;
48+
$this->productRepository = $productRepository;
49+
$this->stockRegistry = $stockRegistry;
50+
}
51+
52+
/**
53+
* Plugin method to fill the legacy tables.
54+
*
55+
* @param ReservationsAppendInterface $subject
56+
* @param void $result
57+
* @param ReservationInterface[] $reservations
58+
*
59+
* @see ReservationsAppendInterface::execute
60+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
61+
* @return void
62+
*/
63+
public function afterExecute(ReservationsAppendInterface $subject, $result, array $reservations)
64+
{
65+
$this->updateStockItemAndStatusTable($reservations);
66+
return $result;
67+
}
68+
69+
/**
70+
* Updates cataloginventory_stock_item and cataloginventory_stock_status qty with reservation information.
71+
*
72+
* @param ReservationInterface[] $reservations
73+
* @return void
74+
*/
75+
private function updateStockItemAndStatusTable(array $reservations)
76+
{
77+
foreach ($reservations as $reservation) {
78+
$sku = $reservation->getSku();
79+
$stockItem = $this->stockRegistry->getStockItemBySku($sku);
80+
$stockItem->setQty($stockItem->getQty() + $reservation->getQuantity());
81+
$this->stockRegistry->updateStockItemBySku($sku, $stockItem);
82+
83+
$stockStatus = $this->stockRegistry->getStockStatus($stockItem->getProductId());
84+
$stockStatus->setQty($stockStatus->getQty() + $reservation->getQuantity());
85+
$stockStatus->save();
86+
}
87+
}
88+
}
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\InventoryCatalog\Test\Integration;
8+
9+
use Magento\Catalog\Api\ProductRepositoryInterface;
10+
use Magento\Catalog\Model\Product;
11+
use Magento\InventoryApi\Api\ReservationBuilderInterface;
12+
use Magento\InventoryApi\Api\ReservationsAppendInterface;
13+
use PHPUnit\Framework\TestCase;
14+
use Magento\TestFramework\Helper\Bootstrap;
15+
use Magento\CatalogInventory\Api\StockItemRepositoryInterface;
16+
use Magento\CatalogInventory\Api\StockItemCriteriaInterface;
17+
use Magento\CatalogInventory\Api\StockItemCriteriaInterfaceFactory;
18+
use Magento\CatalogInventory\Api\Data\StockItemCollectionInterface;
19+
use Magento\CatalogInventory\Api\Data\StockItemInterface;
20+
use Magento\InventoryApi\Api\GetProductQuantityInStockInterface;
21+
use Magento\Indexer\Model\Indexer;
22+
use Magento\Inventory\Indexer\SourceItem\SourceItemIndexer;
23+
24+
class UpdateLegacyCatalogInventoryPluginTest extends TestCase
25+
{
26+
/**
27+
* @var ReservationBuilderInterface
28+
*/
29+
private $reservationBuilder;
30+
31+
/**
32+
* @var ReservationsAppendInterface
33+
*/
34+
private $reservationsAppend;
35+
36+
/**
37+
* @var StockItemRepositoryInterface
38+
*/
39+
private $oldStockItemRepository;
40+
41+
/**
42+
* @var StockItemCriteriaInterfaceFactory
43+
*/
44+
private $stockItemCriteriaFactory;
45+
46+
/**
47+
* @var GetProductQuantityInStockInterface
48+
*/
49+
private $getProductQtyInStock;
50+
51+
/**
52+
* @var IndexerInterface
53+
*/
54+
private $indexer;
55+
56+
/**
57+
* @var ProductRepositoryInterface
58+
*/
59+
private $productRepository;
60+
61+
protected function setUp()
62+
{
63+
$this->reservationBuilder = Bootstrap::getObjectManager()->get(ReservationBuilderInterface::class);
64+
$this->reservationsAppend = Bootstrap::getObjectManager()->get(ReservationsAppendInterface::class);
65+
$this->oldStockItemRepository = Bootstrap::getObjectManager()->get(StockItemRepositoryInterface::class);
66+
$this->stockItemCriteriaFactory = Bootstrap::getObjectManager()->get(StockItemCriteriaInterfaceFactory::class);
67+
68+
$this->indexer = Bootstrap::getObjectManager()->get(Indexer::class);
69+
$this->indexer->load(SourceItemIndexer::INDEXER_ID);
70+
$this->getProductQtyInStock = Bootstrap::getObjectManager()->get(GetProductQuantityInStockInterface::class);
71+
$this->productRepository = Bootstrap::getObjectManager()->get(ProductRepositoryInterface::class);
72+
}
73+
74+
/**
75+
* @magentoDataFixture ../../../../app/code/Magento/InventoryApi/Test/_files/products.php
76+
* @magentoDataFixture ../../../../app/code/Magento/InventoryApi/Test/_files/sources.php
77+
* @magentoDataFixture ../../../../app/code/Magento/InventoryApi/Test/_files/stocks.php
78+
* @magentoDataFixture ../../../../app/code/Magento/InventoryApi/Test/_files/source_items.php
79+
* @magentoDataFixture ../../../../app/code/Magento/InventoryApi/Test/_files/stock_source_link.php
80+
*/
81+
public function testUpdateStockItemTable()
82+
{
83+
$reservationQuantity = -5;
84+
85+
/** @var Product $product */
86+
$product = $this->productRepository->get('SKU-1');
87+
88+
/** @var StockItemCriteriaInterface $criteria */
89+
$criteria = $this->stockItemCriteriaFactory->create();
90+
$criteria->setProductsFilter([$product->getId()]);
91+
92+
/** @var StockItemCollectionInterface $collectionBeforeChange */
93+
$collectionBeforeChange = $this->oldStockItemRepository->getList($criteria);
94+
/** @var StockItemInterface $oldStockItem */
95+
$oldStockItem = current($collectionBeforeChange->getItems());
96+
$initialQuantity = $oldStockItem->getQty();
97+
98+
$this->reservationsAppend->execute([
99+
$this->reservationBuilder->setStockId(1)->setSku('SKU-1')->setQuantity($reservationQuantity)->build()
100+
]);
101+
102+
/** @var StockItemCollectionInterface $collectionAfterChange */
103+
$collectionAfterChange = $this->oldStockItemRepository->getList($criteria);
104+
$oldStockItem = current($collectionAfterChange->getItems());
105+
$quantityAfterCheck = $oldStockItem->getQty();
106+
107+
$this->assertEquals($initialQuantity + $reservationQuantity, $quantityAfterCheck);
108+
}
109+
110+
/**
111+
* @magentoDataFixture ../../../../app/code/Magento/InventoryApi/Test/_files/products.php
112+
* @magentoDataFixture ../../../../app/code/Magento/InventoryApi/Test/_files/sources.php
113+
* @magentoDataFixture ../../../../app/code/Magento/InventoryApi/Test/_files/stocks.php
114+
* @magentoDataFixture ../../../../app/code/Magento/InventoryApi/Test/_files/source_items.php
115+
* @magentoDataFixture ../../../../app/code/Magento/InventoryApi/Test/_files/stock_source_link.php
116+
*/
117+
public function testThatReservationPlacedUpdatesBothOldAndNewStocks()
118+
{
119+
$this->productRepository = Bootstrap::getObjectManager()->get(ProductRepositoryInterface::class);
120+
$reservationQuantity = -5;
121+
122+
$this->indexer->reindexAll();
123+
$this->assertEquals(8.5, $this->getProductQtyInStock->execute('SKU-1', 10));
124+
125+
/** @var Product $product */
126+
$product = $this->productRepository->get('SKU-1');
127+
128+
/** @var StockItemCriteriaInterface $criteria */
129+
$criteria = $this->stockItemCriteriaFactory->create();
130+
$criteria->setProductsFilter([$product->getId()]);
131+
132+
/** @var StockItemCollectionInterface $collectionBeforeChange */
133+
$collectionBeforeChange = $this->oldStockItemRepository->getList($criteria);
134+
135+
/** @var StockItemInterface $oldStockItem */
136+
$oldStockItem = current($collectionBeforeChange->getItems());
137+
$initialQuantity = $oldStockItem->getQty();
138+
$this->assertEquals(8.5, $initialQuantity);
139+
140+
$this->reservationsAppend->execute([
141+
$this->reservationBuilder->setStockId(10)->setSku('SKU-1')->setQuantity($reservationQuantity)->build()
142+
]);
143+
144+
/** @var StockItemCollectionInterface $collectionAfterChange */
145+
$collectionAfterChange = $this->oldStockItemRepository->getList($criteria);
146+
$oldStockItem = current($collectionAfterChange->getItems());
147+
$quantityAfterCheck = $oldStockItem->getQty();
148+
149+
$this->assertEquals(8.5 - 5, $this->getProductQtyInStock->execute('SKU-1', 10));
150+
$this->assertEquals($this->getProductQtyInStock->execute('SKU-1', 10), $quantityAfterCheck);
151+
}
152+
}

app/code/Magento/InventoryCatalog/etc/di.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,7 @@
1414
<plugin name="prevent_assigned_to_sales_channels_stock_deleting"
1515
type="Magento\InventoryCatalog\Plugin\InventoryApi\StockRepository\PreventDeleting\AssignedToSalesChannelsStockPlugin"/>
1616
</type>
17+
<type name="Magento\InventoryApi\Api\ReservationsAppendInterface">
18+
<plugin name="update_legacy_catalog_inventory_plugin" type="Magento\InventoryCatalog\Plugin\Model\UpdateLegacyCatalogInventoryPlugin"/>
19+
</type>
1720
</config>

0 commit comments

Comments
 (0)