diff --git a/app/code/Magento/InventoryApi/Test/_files/products.php b/app/code/Magento/InventoryApi/Test/_files/products.php index 2a37fd7e69fc..4c04fdd9c642 100644 --- a/app/code/Magento/InventoryApi/Test/_files/products.php +++ b/app/code/Magento/InventoryApi/Test/_files/products.php @@ -14,6 +14,7 @@ $productFactory = $objectManager->get(ProductInterfaceFactory::class); /** @var ProductRepositoryInterface $productRepository */ $productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); for ($i = 1; $i <= 3; $i++) { $product = $productFactory->create(); diff --git a/app/code/Magento/InventorySales/Plugin/InventoryApi/BackorderStockStatusPlugin.php b/app/code/Magento/InventorySales/Plugin/InventoryApi/BackorderStockStatusPlugin.php new file mode 100644 index 000000000000..110a68270c5d --- /dev/null +++ b/app/code/Magento/InventorySales/Plugin/InventoryApi/BackorderStockStatusPlugin.php @@ -0,0 +1,82 @@ +stockItemRepository = $stockItemRepository; + $this->stockItemCriteriaFactory = $stockItemCriteriaFactory; + $this->productRepository = $productRepository; + } + + /** + * Return true status if backorders is enabled for the item + * + * @param IsProductInStockInterface $subject + * @param callable $proceed + * @param string $sku + * @param int $stockId + * @return bool + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function aroundExecute( + IsProductInStockInterface $subject, + callable $proceed, + string $sku, + int $stockId + ): bool { + $productData = $this->productRepository->get($sku); + $productId = $productData->getId(); + + $stockItemCriteria = $this->stockItemCriteriaFactory->create(); + $stockItemCriteria->setProductsFilter($productId); + $stockItemsCollection = $this->stockItemRepository->getList($stockItemCriteria); + + /** @var StockItemInterface $legacyStockItem */ + $legacyStockItem = current($stockItemsCollection->getItems()); + + if ($legacyStockItem->getBackorders() > 0) { + return true; + } + return $proceed($sku, $stockId); + } +} diff --git a/app/code/Magento/InventorySales/Test/Integration/IsBackorderedProductInStockTest.php b/app/code/Magento/InventorySales/Test/Integration/IsBackorderedProductInStockTest.php new file mode 100644 index 000000000000..18babb3e9f62 --- /dev/null +++ b/app/code/Magento/InventorySales/Test/Integration/IsBackorderedProductInStockTest.php @@ -0,0 +1,144 @@ +productRepository = Bootstrap::getObjectManager()->create(ProductRepositoryInterface::class); + $this->stockItemRepository = Bootstrap::getObjectManager()->create(StockItemRepositoryInterface::class); + $this->stockItemCriteriaFactory = Bootstrap::getObjectManager()->create( + StockItemCriteriaInterfaceFactory::class + ); + $this->sourceItemRepository = Bootstrap::getObjectManager()->create(SourceItemRepositoryInterface::class); + $this->searchCriteriaBuilder = Bootstrap::getObjectManager()->create(SearchCriteriaBuilder::class); + $this->sourceItemsSave = Bootstrap::getObjectManager()->create(SourceItemsSaveInterface::class); + $this->indexer = Bootstrap::getObjectManager()->create(IndexerInterface::class); + $this->indexer->load(StockItemIndexerInterface::INDEXER_ID); + $this->isProductInStock = Bootstrap::getObjectManager()->create(IsProductInStockInterface::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 testBackorderedZeroQtyProductIsInStock() + { + $product = $this->productRepository->get('SKU-2'); + $stockItemSearchCriteria = $this->stockItemCriteriaFactory->create(); + $stockItemSearchCriteria->setProductsFilter($product->getId()); + $stockItemsCollection = $this->stockItemRepository->getList($stockItemSearchCriteria); + + /** @var StockItemInterface $legacyStockItem */ + $legacyStockItem = current($stockItemsCollection->getItems()); + $legacyStockItem->setBackorders(1); + $legacyStockItem->setUseConfigBackorders(0); + $this->stockItemRepository->save($legacyStockItem); + + $sourceItem = $this->getSourceItemBySku('SKU-2'); + $this->changeSourceItemQty($sourceItem, -15); + + $this->assertTrue($this->isProductInStock->execute('SKU-2', 1)); + } + + /** + * @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 testZeroQtyProductIsOutOfStock() + { + $sourceItem = $this->getSourceItemBySku('SKU-2'); + $this->changeSourceItemQty($sourceItem, 0); + + $this->assertFalse($this->isProductInStock->execute('SKU-2', 1)); + } + + /** + * @param string $sku + * @return SourceItemInterface + */ + private function getSourceItemBySku(string $sku): SourceItemInterface + { + $sourceItemSearchCriteria = $this->searchCriteriaBuilder + ->addFilter('sku', $sku) + ->create(); + $sourceItemSearchResult = $this->sourceItemRepository->getList($sourceItemSearchCriteria); + + return current($sourceItemSearchResult->getItems()); + } + + /** + * @param SourceItemInterface $sourceItem + * @param float $qty + */ + private function changeSourceItemQty(SourceItemInterface $sourceItem, float $qty) + { + $sourceItem->setQuantity($qty); + $this->sourceItemsSave->execute([$sourceItem]); + $this->indexer->reindexRow(5); + } +} diff --git a/app/code/Magento/InventorySales/etc/di.xml b/app/code/Magento/InventorySales/etc/di.xml index f1f32c30f102..27aa6c3f1287 100644 --- a/app/code/Magento/InventorySales/etc/di.xml +++ b/app/code/Magento/InventorySales/etc/di.xml @@ -9,4 +9,7 @@ + + +