diff --git a/app/code/Magento/InventoryApi/Test/_files/products.php b/app/code/Magento/InventoryApi/Test/_files/products.php index 4c04fdd9c642..08ce6888fd95 100644 --- a/app/code/Magento/InventoryApi/Test/_files/products.php +++ b/app/code/Magento/InventoryApi/Test/_files/products.php @@ -16,6 +16,24 @@ $productRepository = $objectManager->get(ProductRepositoryInterface::class); $productRepository->cleanCache(); +$stockData = [ + 'SKU-1' => [ + 'qty' => 8.5, + 'is_in_stock' => true, + 'manage_stock' => true + ], + 'SKU-2' => [ + 'qty' => 5, + 'is_in_stock' => true, + 'manage_stock' => true + ], + 'SKU-3' => [ + 'qty' => 0, + 'is_in_stock' => false, + 'manage_stock' => true + ] +]; + for ($i = 1; $i <= 3; $i++) { $product = $productFactory->create(); $product->setTypeId(Type::TYPE_SIMPLE) @@ -23,6 +41,7 @@ ->setName('Simple Product ' . $i) ->setSku('SKU-' . $i) ->setPrice(10) + ->setStockData($stockData['SKU-' . $i]) ->setStatus(Status::STATUS_ENABLED); $productRepository->save($product); } diff --git a/app/code/Magento/InventoryApi/Test/_files/products_rollback.php b/app/code/Magento/InventoryApi/Test/_files/products_rollback.php index 021e40448a00..06de7fe3b82c 100644 --- a/app/code/Magento/InventoryApi/Test/_files/products_rollback.php +++ b/app/code/Magento/InventoryApi/Test/_files/products_rollback.php @@ -4,6 +4,8 @@ * See COPYING.txt for license details. */ use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\CatalogInventory\Api\StockStatusCriteriaInterfaceFactory; +use Magento\CatalogInventory\Api\StockStatusRepositoryInterface; use Magento\Framework\Registry; use Magento\TestFramework\Helper\Bootstrap; @@ -12,12 +14,25 @@ $productRepository = $objectManager->create(ProductRepositoryInterface::class); /** @var Registry $registry */ $registry = $objectManager->get(Registry::class); +/** @var StockStatusRepositoryInterface $stockStatusRepository */ +$stockStatusRepository = $objectManager->create(StockStatusRepositoryInterface::class); +/** @var StockStatusCriteriaInterfaceFactory $stockStatusCriteriaFactory */ +$stockStatusCriteriaFactory = $objectManager->create(StockStatusCriteriaInterfaceFactory::class); $currentArea = $registry->registry('isSecureArea'); $registry->unregister('isSecureArea'); $registry->register('isSecureArea', true); for ($i = 1; $i <= 3; $i++) { + $product = $productRepository->get('SKU-' . $i); + /** @var \Magento\CatalogInventory\Api\StockStatusCriteriaInterfaceFactory $stockStatusCriteriaFactory **/ + $criteria = $stockStatusCriteriaFactory->create(); + $criteria->setProductsFilter($product->getId()); + + $result = $stockStatusRepository->getList($criteria); + $stockStatus = current($result->getItems()); + $stockStatusRepository->delete($stockStatus); + $productRepository->deleteById('SKU-' . $i); } diff --git a/app/code/Magento/InventoryCatalog/Plugin/Model/UpdateLegacyCatalogInventoryPlugin.php b/app/code/Magento/InventoryCatalog/Plugin/Model/UpdateLegacyCatalogInventoryPlugin.php new file mode 100644 index 000000000000..ba6de0ccac19 --- /dev/null +++ b/app/code/Magento/InventoryCatalog/Plugin/Model/UpdateLegacyCatalogInventoryPlugin.php @@ -0,0 +1,88 @@ +resourceConnection = $resourceConnection; + $this->productRepository = $productRepository; + $this->stockRegistry = $stockRegistry; + } + + /** + * Plugin method to fill the legacy tables. + * + * @param ReservationsAppendInterface $subject + * @param void $result + * @param ReservationInterface[] $reservations + * + * @see ReservationsAppendInterface::execute + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * @return void + */ + public function afterExecute(ReservationsAppendInterface $subject, $result, array $reservations) + { + $this->updateStockItemAndStatusTable($reservations); + return $result; + } + + /** + * Updates cataloginventory_stock_item and cataloginventory_stock_status qty with reservation information. + * + * @param ReservationInterface[] $reservations + * @return void + */ + private function updateStockItemAndStatusTable(array $reservations) + { + foreach ($reservations as $reservation) { + $sku = $reservation->getSku(); + $stockItem = $this->stockRegistry->getStockItemBySku($sku); + $stockItem->setQty($stockItem->getQty() + $reservation->getQuantity()); + $this->stockRegistry->updateStockItemBySku($sku, $stockItem); + + $stockStatus = $this->stockRegistry->getStockStatus($stockItem->getProductId()); + $stockStatus->setQty($stockStatus->getQty() + $reservation->getQuantity()); + $stockStatus->save(); + } + } +} diff --git a/app/code/Magento/InventoryCatalog/Test/Integration/UpdateLegacyCatalogInventoryPluginTest.php b/app/code/Magento/InventoryCatalog/Test/Integration/UpdateLegacyCatalogInventoryPluginTest.php new file mode 100644 index 000000000000..d1be1262f809 --- /dev/null +++ b/app/code/Magento/InventoryCatalog/Test/Integration/UpdateLegacyCatalogInventoryPluginTest.php @@ -0,0 +1,152 @@ +reservationBuilder = Bootstrap::getObjectManager()->get(ReservationBuilderInterface::class); + $this->reservationsAppend = Bootstrap::getObjectManager()->get(ReservationsAppendInterface::class); + $this->oldStockItemRepository = Bootstrap::getObjectManager()->get(StockItemRepositoryInterface::class); + $this->stockItemCriteriaFactory = Bootstrap::getObjectManager()->get(StockItemCriteriaInterfaceFactory::class); + + $this->indexer = Bootstrap::getObjectManager()->get(Indexer::class); + $this->indexer->load(SourceItemIndexer::INDEXER_ID); + $this->getProductQtyInStock = Bootstrap::getObjectManager()->get(GetProductQuantityInStockInterface::class); + $this->productRepository = Bootstrap::getObjectManager()->get(ProductRepositoryInterface::class); + } + + /** + * @magentoDataFixture ../../../../app/code/Magento/InventoryApi/Test/_files/products.php + * @magentoDataFixture ../../../../app/code/Magento/InventoryApi/Test/_files/sources.php + * @magentoDataFixture ../../../../app/code/Magento/InventoryApi/Test/_files/stocks.php + * @magentoDataFixture ../../../../app/code/Magento/InventoryApi/Test/_files/source_items.php + * @magentoDataFixture ../../../../app/code/Magento/InventoryApi/Test/_files/stock_source_link.php + */ + public function testUpdateStockItemTable() + { + $reservationQuantity = -5; + + /** @var Product $product */ + $product = $this->productRepository->get('SKU-1'); + + /** @var StockItemCriteriaInterface $criteria */ + $criteria = $this->stockItemCriteriaFactory->create(); + $criteria->setProductsFilter([$product->getId()]); + + /** @var StockItemCollectionInterface $collectionBeforeChange */ + $collectionBeforeChange = $this->oldStockItemRepository->getList($criteria); + /** @var StockItemInterface $oldStockItem */ + $oldStockItem = current($collectionBeforeChange->getItems()); + $initialQuantity = $oldStockItem->getQty(); + + $this->reservationsAppend->execute([ + $this->reservationBuilder->setStockId(1)->setSku('SKU-1')->setQuantity($reservationQuantity)->build() + ]); + + /** @var StockItemCollectionInterface $collectionAfterChange */ + $collectionAfterChange = $this->oldStockItemRepository->getList($criteria); + $oldStockItem = current($collectionAfterChange->getItems()); + $quantityAfterCheck = $oldStockItem->getQty(); + + $this->assertEquals($initialQuantity + $reservationQuantity, $quantityAfterCheck); + } + + /** + * @magentoDataFixture ../../../../app/code/Magento/InventoryApi/Test/_files/products.php + * @magentoDataFixture ../../../../app/code/Magento/InventoryApi/Test/_files/sources.php + * @magentoDataFixture ../../../../app/code/Magento/InventoryApi/Test/_files/stocks.php + * @magentoDataFixture ../../../../app/code/Magento/InventoryApi/Test/_files/source_items.php + * @magentoDataFixture ../../../../app/code/Magento/InventoryApi/Test/_files/stock_source_link.php + */ + public function testThatReservationPlacedUpdatesBothOldAndNewStocks() + { + $this->productRepository = Bootstrap::getObjectManager()->get(ProductRepositoryInterface::class); + $reservationQuantity = -5; + + $this->indexer->reindexAll(); + $this->assertEquals(8.5, $this->getProductQtyInStock->execute('SKU-1', 10)); + + /** @var Product $product */ + $product = $this->productRepository->get('SKU-1'); + + /** @var StockItemCriteriaInterface $criteria */ + $criteria = $this->stockItemCriteriaFactory->create(); + $criteria->setProductsFilter([$product->getId()]); + + /** @var StockItemCollectionInterface $collectionBeforeChange */ + $collectionBeforeChange = $this->oldStockItemRepository->getList($criteria); + + /** @var StockItemInterface $oldStockItem */ + $oldStockItem = current($collectionBeforeChange->getItems()); + $initialQuantity = $oldStockItem->getQty(); + $this->assertEquals(8.5, $initialQuantity); + + $this->reservationsAppend->execute([ + $this->reservationBuilder->setStockId(10)->setSku('SKU-1')->setQuantity($reservationQuantity)->build() + ]); + + /** @var StockItemCollectionInterface $collectionAfterChange */ + $collectionAfterChange = $this->oldStockItemRepository->getList($criteria); + $oldStockItem = current($collectionAfterChange->getItems()); + $quantityAfterCheck = $oldStockItem->getQty(); + + $this->assertEquals(8.5 - 5, $this->getProductQtyInStock->execute('SKU-1', 10)); + $this->assertEquals($this->getProductQtyInStock->execute('SKU-1', 10), $quantityAfterCheck); + } +} diff --git a/app/code/Magento/InventoryCatalog/etc/di.xml b/app/code/Magento/InventoryCatalog/etc/di.xml index d7e40373206c..d394c22bdea2 100644 --- a/app/code/Magento/InventoryCatalog/etc/di.xml +++ b/app/code/Magento/InventoryCatalog/etc/di.xml @@ -14,4 +14,7 @@ + + +