diff --git a/app/code/Magento/CatalogInventory/Model/Stock/StockItemRepository.php b/app/code/Magento/CatalogInventory/Model/Stock/StockItemRepository.php index e5154a10f0a19046dca627576b5594afaa0e79a0..a675709e504b26f0b6fe4d9a4347fc74fbef8809 100644 --- a/app/code/Magento/CatalogInventory/Model/Stock/StockItemRepository.php +++ b/app/code/Magento/CatalogInventory/Model/Stock/StockItemRepository.php @@ -145,7 +145,7 @@ class StockItemRepository implements StockItemRepositoryInterface /** * @inheritdoc */ - public function save(\Magento\CatalogInventory\Api\Data\StockItemInterface $stockItem) + public function save(StockItemInterface $stockItem) { try { /** @var \Magento\Catalog\Model\Product $product */ @@ -161,10 +161,7 @@ class StockItemRepository implements StockItemRepositoryInterface $typeId = $product->getTypeId() ?: $product->getTypeInstance()->getTypeId(); $isQty = $this->stockConfiguration->isQty($typeId); if ($isQty) { - $isInStock = $this->stockStateProvider->verifyStock($stockItem); - if ($stockItem->getManageStock() && !$isInStock) { - $stockItem->setIsInStock(false)->setStockStatusChangedAutomaticallyFlag(true); - } + $this->changeIsInStockIfNecessary($stockItem); // if qty is below notify qty, update the low stock date to today date otherwise set null $stockItem->setLowStockDate(null); if ($this->stockStateProvider->verifyNotification($stockItem)) { @@ -260,4 +257,27 @@ class StockItemRepository implements StockItemRepositoryInterface } return $this->stockRegistryStorage; } + + /** + * Change is_in_stock value if necessary. + * + * @param StockItemInterface $stockItem + * + * @return void + */ + private function changeIsInStockIfNecessary(StockItemInterface $stockItem) + { + $isInStock = $this->stockStateProvider->verifyStock($stockItem); + if ($stockItem->getManageStock() && !$isInStock) { + $stockItem->setIsInStock(false)->setStockStatusChangedAutomaticallyFlag(true); + } + + if ($stockItem->getManageStock() + && $isInStock + && !$stockItem->getIsInStock() + && $stockItem->getOrigData(\Magento\CatalogInventory\Api\Data\StockItemInterface::QTY) == 0 + ) { + $stockItem->setIsInStock(true)->setStockStatusChangedAutomaticallyFlag(true); + } + } } diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemRepositoryTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemRepositoryTest.php index 293874bb32b9f36a78fce06d05652f8e322b0a5d..6b1770ff7d4036be93347f36db41bc3dc7c7a5a5 100644 --- a/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemRepositoryTest.php +++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemRepositoryTest.php @@ -276,7 +276,7 @@ class StockItemRepositoryTest extends \PHPUnit\Framework\TestCase ->method('verifyStock') ->with($this->stockItemMock) ->willReturn(false); - $this->stockItemMock->expects($this->once())->method('getManageStock')->willReturn(true); + $this->stockItemMock->expects($this->exactly(2))->method('getManageStock')->willReturn(true); $this->stockItemMock->expects($this->once())->method('setIsInStock')->with(false)->willReturnSelf(); $this->stockItemMock->expects($this->once()) ->method('setStockStatusChangedAutomaticallyFlag') diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php index 99a1e9309f6e99f551f1ab05db91abbbc597a25f..078a83bcf6314aea7122f872a059d297d61a2d0d 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php @@ -549,4 +549,36 @@ class ProductTest extends \PHPUnit\Framework\TestCase } } } + + /** + * @magentoDataFixture Magento/Catalog/_files/product_simple_out_of_stock.php + */ + public function testSaveWithDifferentQty() + { + //if save (out of stock product with qty 0) with new qty > 0 it should become in stock. + //if set out of stock for product with qty > 0 it should become out of stock + $product = $this->productRepository->get('simple-out-of-stock'); + $stockItem = $product->getExtensionAttributes()->getStockItem(); + $this->assertEquals(false, $stockItem->getIsInStock()); + $stockData = [ + 'qty' => 5, + 'is_in_stock' => 0, + ]; + $product->setStockData($stockData); + $product->save(); + + $product = $this->productRepository->get('simple-out-of-stock'); + $stockItem = $product->getExtensionAttributes()->getStockItem(); + $this->assertEquals(true, $stockItem->getIsInStock()); + $stockData = [ + 'qty' => 3, + 'is_in_stock' => 0, + ]; + $product->setStockData($stockData); + $product->save(); + + $product = $this->productRepository->get('simple-out-of-stock'); + $stockItem = $product->getExtensionAttributes()->getStockItem(); + $this->assertEquals(false, $stockItem->getIsInStock()); + } } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_out_of_stock.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_out_of_stock.php new file mode 100644 index 0000000000000000000000000000000000000000..729ea2ab982b79a028afb561816ae5c5abaa287f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_out_of_stock.php @@ -0,0 +1,51 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +\Magento\TestFramework\Helper\Bootstrap::getInstance()->reinitialize(); + +/** @var \Magento\TestFramework\ObjectManager $objectManager */ +$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + +/** @var \Magento\Catalog\Api\CategoryLinkManagementInterface $categoryLinkManagement */ +$categoryLinkManagement = $objectManager->get(\Magento\Catalog\Api\CategoryLinkManagementInterface::class); + +/** @var $product \Magento\Catalog\Model\Product */ +$product = $objectManager->create(\Magento\Catalog\Model\Product::class); +$product->isObjectNew(true); +$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE) + ->setId(1) + ->setAttributeSetId(4) + ->setWebsiteIds([1]) + ->setName('Simple Product') + ->setSku('simple-out-of-stock') + ->setPrice(10) + ->setWeight(1) + ->setShortDescription("Short description") + ->setTaxClassId(0) + ->setDescription('Description with <b>html tag</b>') + ->setMetaTitle('meta title') + ->setMetaKeyword('meta keyword') + ->setMetaDescription('meta description') + ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) + ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) + ->setStockData( + [ + 'use_config_manage_stock' => 1, + 'qty' => 0, + 'is_qty_decimal' => 0, + 'is_in_stock' => 0, + ] + )->setCanSaveCustomOptions(true) + ->setHasOptions(true); + +/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepositoryFactory */ +$productRepository = $objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); +$productRepository->save($product); + +$categoryLinkManagement->assignProductToCategories( + $product->getSku(), + [2] +); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_out_of_stock_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_out_of_stock_rollback.php new file mode 100644 index 0000000000000000000000000000000000000000..2bb2858687ff71ddef02343fb696ae09559c8e0a --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_out_of_stock_rollback.php @@ -0,0 +1,25 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +use Magento\Framework\Exception\NoSuchEntityException; + +\Magento\TestFramework\Helper\Bootstrap::getInstance()->getInstance()->reinitialize(); + +/** @var \Magento\Framework\Registry $registry */ +$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(\Magento\Framework\Registry::class); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ +$productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->get(\Magento\Catalog\Api\ProductRepositoryInterface::class); +try { + $product = $productRepository->get('simple-out-of-stock', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { +} +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/ByStockItemRepositoryTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/ByStockItemRepositoryTest.php index ae67d3fa1eddc1edbe4f4f01fe6e6ddcb892f9b1..dfe21a61c866b046c61150e8346a32cdfb7a6b3b 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/ByStockItemRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/ByStockItemRepositoryTest.php @@ -40,7 +40,7 @@ class ByStockItemRepositoryTest extends \PHPUnit\Framework\TestCase private $stockItemData = [ StockItemInterface::QTY => 555, StockItemInterface::MANAGE_STOCK => true, - StockItemInterface::IS_IN_STOCK => false, + StockItemInterface::IS_IN_STOCK => true, ]; public function setUp() diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductModel/ByQuantityAndStockStatusTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductModel/ByQuantityAndStockStatusTest.php index 6864b9a345602ad74e034057ca72aa1ed8b73862..ec5dc7c5b0ce77abdeb7175b71f32be61a8f4522 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductModel/ByQuantityAndStockStatusTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductModel/ByQuantityAndStockStatusTest.php @@ -53,7 +53,7 @@ class ByQuantityAndStockStatusTest extends \PHPUnit\Framework\TestCase private $stockItemData = [ StockItemInterface::QTY => 555, StockItemInterface::MANAGE_STOCK => true, - StockItemInterface::IS_IN_STOCK => false, + StockItemInterface::IS_IN_STOCK => true, ]; public function setUp() diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductModel/ByStockDataTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductModel/ByStockDataTest.php index eae20bda1a94a0a7e35f9f3452ec29b014bf6e0a..7638936c34a6a67d1783375131a3f6708b66a6b8 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductModel/ByStockDataTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductModel/ByStockDataTest.php @@ -53,7 +53,7 @@ class ByStockDataTest extends \PHPUnit\Framework\TestCase private $stockItemData = [ StockItemInterface::QTY => 555, StockItemInterface::MANAGE_STOCK => true, - StockItemInterface::IS_IN_STOCK => false, + StockItemInterface::IS_IN_STOCK => true, ]; public function setUp() diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductModel/ByStockItemTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductModel/ByStockItemTest.php index 25b9817bcf572426c3f95be11ec1fada601c22ff..d5dae31b89158b27dd25713cbd03cb290c321eb5 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductModel/ByStockItemTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductModel/ByStockItemTest.php @@ -59,7 +59,7 @@ class ByStockItemTest extends \PHPUnit\Framework\TestCase private $stockItemData = [ StockItemInterface::QTY => 555, StockItemInterface::MANAGE_STOCK => true, - StockItemInterface::IS_IN_STOCK => false, + StockItemInterface::IS_IN_STOCK => true, ]; public function setUp() diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductRepository/ByQuantityAndStockStatusTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductRepository/ByQuantityAndStockStatusTest.php index 6269d7a20f4fc23b4af583a9e41e98fafdffcea9..fc1d787df531d5cd69941d2835a80fe96ee5129a 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductRepository/ByQuantityAndStockStatusTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductRepository/ByQuantityAndStockStatusTest.php @@ -59,7 +59,7 @@ class ByQuantityAndStockStatusTest extends \PHPUnit\Framework\TestCase private $stockItemData = [ StockItemInterface::QTY => 555, StockItemInterface::MANAGE_STOCK => true, - StockItemInterface::IS_IN_STOCK => false, + StockItemInterface::IS_IN_STOCK => true, ]; public function setUp() diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductRepository/ByStockDataTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductRepository/ByStockDataTest.php index fa7cc39f7584fe74d8be02143a97d54819497dd8..9050aaf6c8855c7327c924a9144c52480e69e5b4 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductRepository/ByStockDataTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductRepository/ByStockDataTest.php @@ -59,7 +59,7 @@ class ByStockDataTest extends \PHPUnit\Framework\TestCase private $stockItemData = [ StockItemInterface::QTY => 555, StockItemInterface::MANAGE_STOCK => true, - StockItemInterface::IS_IN_STOCK => false, + StockItemInterface::IS_IN_STOCK => true, ]; public function setUp() diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductRepository/ByStockItemTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductRepository/ByStockItemTest.php index 857457325c75544f868b22c5f393341da9b725d2..1884a46e2168025b99880f6917084d8ee0aba250 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductRepository/ByStockItemTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductRepository/ByStockItemTest.php @@ -70,7 +70,7 @@ class ByStockItemTest extends \PHPUnit\Framework\TestCase private $stockItemData = [ StockItemInterface::QTY => 555, StockItemInterface::MANAGE_STOCK => true, - StockItemInterface::IS_IN_STOCK => false, + StockItemInterface::IS_IN_STOCK => true, ]; public function setUp() diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductUpdate/ByProductModel/ByStockItemTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductUpdate/ByProductModel/ByStockItemTest.php index 2a4b7937f7163f7edbce864868da256f1f08bc28..5a726170a0128459cdb293e795c007871fabfbfb 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductUpdate/ByProductModel/ByStockItemTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductUpdate/ByProductModel/ByStockItemTest.php @@ -42,7 +42,7 @@ class ByStockItemTest extends \PHPUnit\Framework\TestCase private $stockItemData = [ StockItemInterface::QTY => 555, StockItemInterface::MANAGE_STOCK => true, - StockItemInterface::IS_IN_STOCK => false, + StockItemInterface::IS_IN_STOCK => true, ]; public function setUp() diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductUpdate/ByProductRepository/ByStockItemTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductUpdate/ByProductRepository/ByStockItemTest.php index 81871d3398c1e0e433e0d5b27569979cc48c4e05..3053b8d6acff6dd2e30ec90d3592d7b05482c067 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductUpdate/ByProductRepository/ByStockItemTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductUpdate/ByProductRepository/ByStockItemTest.php @@ -48,7 +48,7 @@ class ByStockItemTest extends \PHPUnit\Framework\TestCase private $stockItemData = [ StockItemInterface::QTY => 555, StockItemInterface::MANAGE_STOCK => true, - StockItemInterface::IS_IN_STOCK => false, + StockItemInterface::IS_IN_STOCK => true, ]; public function setUp() diff --git a/lib/internal/Magento/Framework/Data/AbstractSearchResult.php b/lib/internal/Magento/Framework/Data/AbstractSearchResult.php index f9272683005ce730e36603cd947b0a6bfe46e792..bcedf16e3f5be0727719a7e68ac75252e1877eb8 100644 --- a/lib/internal/Magento/Framework/Data/AbstractSearchResult.php +++ b/lib/internal/Magento/Framework/Data/AbstractSearchResult.php @@ -235,6 +235,7 @@ abstract class AbstractSearchResult extends AbstractDataObject implements Search if (is_array($data)) { foreach ($data as $row) { $item = $this->createDataObject(['data' => $row]); + $item->setOrigData(); $this->addItem($item); } }