From 3259aa0fd52617f50f084408b8367fef620d9226 Mon Sep 17 00:00:00 2001 From: Maksym Novik Date: Sun, 14 Jun 2020 22:19:28 +0300 Subject: [PATCH 01/26] Composite products support for IsProductSaleable. --- .../IsBundleSaleableCondition.php | 77 +++++++++++++++++ InventoryBundleProduct/etc/di.xml | 10 +++ .../IsConfigurableProductSalable.php | 84 +++++++++++++++++++ InventoryConfigurableProduct/etc/di.xml | 10 +++ 4 files changed, 181 insertions(+) create mode 100644 InventoryBundleProduct/Model/IsProductSalableCondition/IsBundleSaleableCondition.php create mode 100644 InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductSalable.php diff --git a/InventoryBundleProduct/Model/IsProductSalableCondition/IsBundleSaleableCondition.php b/InventoryBundleProduct/Model/IsProductSalableCondition/IsBundleSaleableCondition.php new file mode 100644 index 000000000000..5430921c4b8f --- /dev/null +++ b/InventoryBundleProduct/Model/IsProductSalableCondition/IsBundleSaleableCondition.php @@ -0,0 +1,77 @@ +bundleProductType = $type; + $this->repository = $repository; + $this->getBundleProductStockStatus = $getBundleProductStockStatus; + } + + /** + * Is product salable for bundle product. + * + * @param string $sku + * @param int $stockId + * + * @return bool + */ + public function execute(string $sku, int $stockId): bool + { + $status = false; + try { + $product = $this->repository->get($sku); + if ($product->getTypeId() === Type::TYPE_CODE) { + /** @noinspection PhpParamsInspection */ + $options = $this->bundleProductType->getOptionsCollection($product); + $status = (int)$this->getBundleProductStockStatus->execute( + $product, + $options->getItems(), + $stockId + ); + } + } catch (LocalizedException $e) { + $status = false; + } + + return $status; + } +} diff --git a/InventoryBundleProduct/etc/di.xml b/InventoryBundleProduct/etc/di.xml index 622c345aecdb..5ee829f5782d 100644 --- a/InventoryBundleProduct/etc/di.xml +++ b/InventoryBundleProduct/etc/di.xml @@ -29,4 +29,14 @@ + + + + + true + Magento\InventoryBundleProduct\Model\IsProductSalableCondition\IsBundleSaleableCondition + + + + diff --git a/InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductSalable.php b/InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductSalable.php new file mode 100644 index 000000000000..05d5084f8088 --- /dev/null +++ b/InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductSalable.php @@ -0,0 +1,84 @@ +repository = $repository; + $this->areProductsSalable = $areProductsSalable; + $this->configurable = $configurable; + } + + /** + * Is configurable product salable. + * + * @param string $sku + * @param int $stockId + * + * @return bool + */ + public function execute(string $sku, int $stockId): bool + { + try { + $status = false; + $product = $this->repository->get($sku); + if ($product->getTypeId() === Configurable::TYPE_CODE) { + /** @noinspection PhpParamsInspection */ + $options = $this->configurable->getConfigurableOptions($product); + $skus = [[]]; + foreach ($options as $attribute) { + $skus[] = array_column($attribute, 'sku'); + } + $skus = array_merge(...$skus); + $results = $this->areProductsSalable->execute($skus, $stockId); + foreach ($results as $result) { + if ($result->isSalable()) { + $status = true; + break; + } + } + } + } catch (NoSuchEntityException $e) { + $status = false; + } + + return $status; + } +} diff --git a/InventoryConfigurableProduct/etc/di.xml b/InventoryConfigurableProduct/etc/di.xml index babb1c0177ce..c9a5084834e6 100644 --- a/InventoryConfigurableProduct/etc/di.xml +++ b/InventoryConfigurableProduct/etc/di.xml @@ -26,6 +26,16 @@ + + + + + true + Magento\InventoryConfigurableProduct\Model\IsProductSalableCondition\IsConfigurableProductSalable + + + + Magento\InventoryConfigurableProduct\Pricing\Price\Indexer\BaseStockStatusSelectProcessor From 5c05bdebdfe7c71ff6b8f251404ea2af6d6843d0 Mon Sep 17 00:00:00 2001 From: oleksandrkravchuk Date: Thu, 30 Jul 2020 18:51:18 +0200 Subject: [PATCH 02/26] Refactoring. Apply code review changes. --- .../IsBundleSaleableCondition.php | 29 ++--- InventoryBundleProduct/composer.json | 3 +- .../IsConfigurableProductSalable.php | 84 --------------- .../IsConfigurableProductSalablePlugin.php | 102 ++++++++++++++++++ InventoryConfigurableProduct/composer.json | 3 + InventoryConfigurableProduct/etc/di.xml | 9 +- 6 files changed, 125 insertions(+), 105 deletions(-) delete mode 100644 InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductSalable.php create mode 100644 InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalablePlugin.php diff --git a/InventoryBundleProduct/Model/IsProductSalableCondition/IsBundleSaleableCondition.php b/InventoryBundleProduct/Model/IsProductSalableCondition/IsBundleSaleableCondition.php index 5430921c4b8f..d8ed44c3cb4f 100644 --- a/InventoryBundleProduct/Model/IsProductSalableCondition/IsBundleSaleableCondition.php +++ b/InventoryBundleProduct/Model/IsProductSalableCondition/IsBundleSaleableCondition.php @@ -14,6 +14,9 @@ use Magento\InventoryBundleProduct\Model\GetBundleProductStockStatus; use Magento\InventorySalesApi\Api\IsProductSalableInterface; +/** + * Check if bundle product is salable with bundle options. + */ class IsBundleSaleableCondition implements IsProductSalableInterface { /** @@ -24,7 +27,7 @@ class IsBundleSaleableCondition implements IsProductSalableInterface /** * @var ProductRepositoryInterface */ - private $repository; + private $productRepository; /** * @var GetBundleProductStockStatus @@ -42,7 +45,7 @@ public function __construct( GetBundleProductStockStatus $getBundleProductStockStatus ) { $this->bundleProductType = $type; - $this->repository = $repository; + $this->productRepository = $repository; $this->getBundleProductStockStatus = $getBundleProductStockStatus; } @@ -56,18 +59,20 @@ public function __construct( */ public function execute(string $sku, int $stockId): bool { - $status = false; + $status = true; try { - $product = $this->repository->get($sku); - if ($product->getTypeId() === Type::TYPE_CODE) { - /** @noinspection PhpParamsInspection */ - $options = $this->bundleProductType->getOptionsCollection($product); - $status = (int)$this->getBundleProductStockStatus->execute( - $product, - $options->getItems(), - $stockId - ); + $product = $this->productRepository->get($sku); + if ($product->getTypeId() !== Type::TYPE_CODE) { + return $status; } + + /** @noinspection PhpParamsInspection */ + $options = $this->bundleProductType->getOptionsCollection($product); + $status = (int)$this->getBundleProductStockStatus->execute( + $product, + $options->getItems(), + $stockId + ); } catch (LocalizedException $e) { $status = false; } diff --git a/InventoryBundleProduct/composer.json b/InventoryBundleProduct/composer.json index 3c27572ebecc..d101f485dbf2 100644 --- a/InventoryBundleProduct/composer.json +++ b/InventoryBundleProduct/composer.json @@ -13,7 +13,8 @@ "magento/module-store": "*" }, "suggest": { - "magento/module-catalog-inventory": "*" + "magento/module-catalog-inventory": "*", + "magento/module-inventory-sales": "*" }, "type": "magento2-module", "license": [ diff --git a/InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductSalable.php b/InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductSalable.php deleted file mode 100644 index 05d5084f8088..000000000000 --- a/InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductSalable.php +++ /dev/null @@ -1,84 +0,0 @@ -repository = $repository; - $this->areProductsSalable = $areProductsSalable; - $this->configurable = $configurable; - } - - /** - * Is configurable product salable. - * - * @param string $sku - * @param int $stockId - * - * @return bool - */ - public function execute(string $sku, int $stockId): bool - { - try { - $status = false; - $product = $this->repository->get($sku); - if ($product->getTypeId() === Configurable::TYPE_CODE) { - /** @noinspection PhpParamsInspection */ - $options = $this->configurable->getConfigurableOptions($product); - $skus = [[]]; - foreach ($options as $attribute) { - $skus[] = array_column($attribute, 'sku'); - } - $skus = array_merge(...$skus); - $results = $this->areProductsSalable->execute($skus, $stockId); - foreach ($results as $result) { - if ($result->isSalable()) { - $status = true; - break; - } - } - } - } catch (NoSuchEntityException $e) { - $status = false; - } - - return $status; - } -} diff --git a/InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalablePlugin.php b/InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalablePlugin.php new file mode 100644 index 000000000000..3b9e15a9d80a --- /dev/null +++ b/InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalablePlugin.php @@ -0,0 +1,102 @@ +productRepository = $productRepository; + $this->areProductsSalable = $areProductsSalable; + $this->configurableProductType = $configurableProductType; + } + + /** + * Is configurable product salable. + * + * @param IsProductSalableConditionChain $subject + * @param bool $resultStatus + * @param string $sku + * @param int $stockId + * + * @return bool + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterExecute( + IsProductSalableConditionChain $subject, + bool $resultStatus, + string $sku, + int $stockId + ): bool { + if (!$resultStatus) { + return $resultStatus; + } + + try { + $product = $this->productRepository->get($sku); + if ($product->getTypeId() !== Configurable::TYPE_CODE) { + return $resultStatus; + } + + /** @noinspection PhpParamsInspection */ + $options = $this->configurableProductType->getConfigurableOptions($product); + $skus = [[]]; + foreach ($options as $attribute) { + $skus[] = array_column($attribute, 'sku'); + } + $skus = array_merge(...$skus); + $results = $this->areProductsSalable->execute($skus, $stockId); + foreach ($results as $result) { + if ($result->isSalable()) { + $resultStatus = true; + break; + } + } + + } catch (NoSuchEntityException $e) { + $resultStatus = false; + } + + return $resultStatus; + } +} diff --git a/InventoryConfigurableProduct/composer.json b/InventoryConfigurableProduct/composer.json index 5a3e350f7cb3..8d141bedc715 100644 --- a/InventoryConfigurableProduct/composer.json +++ b/InventoryConfigurableProduct/composer.json @@ -13,6 +13,9 @@ "magento/module-sales": "*", "magento/module-configurable-product": "*" }, + "suggest": { + "magento/module-inventory-sales": "*" + }, "type": "magento2-module", "license": [ "OSL-3.0", diff --git a/InventoryConfigurableProduct/etc/di.xml b/InventoryConfigurableProduct/etc/di.xml index c9a5084834e6..271a28a76e4d 100644 --- a/InventoryConfigurableProduct/etc/di.xml +++ b/InventoryConfigurableProduct/etc/di.xml @@ -27,14 +27,7 @@ - - - - true - Magento\InventoryConfigurableProduct\Model\IsProductSalableCondition\IsConfigurableProductSalable - - - + From 277444f93051ffdc773e7132efc02dbf4c99b2b6 Mon Sep 17 00:00:00 2001 From: oleksandrkravchuk Date: Thu, 30 Jul 2020 23:08:35 +0300 Subject: [PATCH 03/26] Fix static tests. --- InventoryConfigurableProduct/composer.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/InventoryConfigurableProduct/composer.json b/InventoryConfigurableProduct/composer.json index 8d141bedc715..bee13a97a54d 100644 --- a/InventoryConfigurableProduct/composer.json +++ b/InventoryConfigurableProduct/composer.json @@ -11,9 +11,7 @@ "magento/module-store": "*", "magento/module-catalog-inventory": "*", "magento/module-sales": "*", - "magento/module-configurable-product": "*" - }, - "suggest": { + "magento/module-configurable-product": "*", "magento/module-inventory-sales": "*" }, "type": "magento2-module", From 449903b84821202dfe1f5ce3e9aa19b8525973bd Mon Sep 17 00:00:00 2001 From: oleksandrkravchuk Date: Sun, 2 Aug 2020 15:49:09 +0200 Subject: [PATCH 04/26] Move product load after type discovery. --- .../IsBundleSaleableCondition.php | 16 +++++++++++++--- .../IsConfigurableProductSalablePlugin.php | 16 +++++++++++++--- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/InventoryBundleProduct/Model/IsProductSalableCondition/IsBundleSaleableCondition.php b/InventoryBundleProduct/Model/IsProductSalableCondition/IsBundleSaleableCondition.php index d8ed44c3cb4f..42f9b30d6616 100644 --- a/InventoryBundleProduct/Model/IsProductSalableCondition/IsBundleSaleableCondition.php +++ b/InventoryBundleProduct/Model/IsProductSalableCondition/IsBundleSaleableCondition.php @@ -12,6 +12,7 @@ use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Framework\Exception\LocalizedException; use Magento\InventoryBundleProduct\Model\GetBundleProductStockStatus; +use Magento\InventoryCatalogApi\Model\GetProductTypesBySkusInterface; use Magento\InventorySalesApi\Api\IsProductSalableInterface; /** @@ -34,19 +35,27 @@ class IsBundleSaleableCondition implements IsProductSalableInterface */ private $getBundleProductStockStatus; + /** + * @var GetProductTypesBySkusInterface + */ + private $getProductTypesBySkus; + /** * @param Type $type * @param ProductRepositoryInterface $repository * @param GetBundleProductStockStatus $getBundleProductStockStatus + * @param GetProductTypesBySkusInterface $getProductTypesBySkus */ public function __construct( Type $type, ProductRepositoryInterface $repository, - GetBundleProductStockStatus $getBundleProductStockStatus + GetBundleProductStockStatus $getBundleProductStockStatus, + GetProductTypesBySkusInterface $getProductTypesBySkus ) { $this->bundleProductType = $type; $this->productRepository = $repository; $this->getBundleProductStockStatus = $getBundleProductStockStatus; + $this->getProductTypesBySkus = $getProductTypesBySkus; } /** @@ -61,11 +70,12 @@ public function execute(string $sku, int $stockId): bool { $status = true; try { - $product = $this->productRepository->get($sku); - if ($product->getTypeId() !== Type::TYPE_CODE) { + $types = $this->getProductTypesBySkus->execute([$sku]); + if (!isset($types[$sku]) || $types[$sku] !== Type::TYPE_CODE) { return $status; } + $product = $this->productRepository->get($sku); /** @noinspection PhpParamsInspection */ $options = $this->bundleProductType->getOptionsCollection($product); $status = (int)$this->getBundleProductStockStatus->execute( diff --git a/InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalablePlugin.php b/InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalablePlugin.php index 3b9e15a9d80a..b2f5ab3078c6 100644 --- a/InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalablePlugin.php +++ b/InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalablePlugin.php @@ -11,6 +11,7 @@ use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\ConfigurableProduct\Model\Product\Type\Configurable; use Magento\Framework\Exception\NoSuchEntityException; +use Magento\InventoryCatalogApi\Model\GetProductTypesBySkusInterface; use Magento\InventorySales\Model\IsProductSalableCondition\IsProductSalableConditionChain; use Magento\InventorySalesApi\Api\AreProductsSalableInterface; @@ -34,20 +35,27 @@ class IsConfigurableProductSalablePlugin * @var Configurable */ private $configurableProductType; + /** + * @var GetProductTypesBySkusInterface + */ + private $getProductTypesBySkus; /** * @param ProductRepositoryInterface $productRepository * @param AreProductsSalableInterface $areProductsSalable * @param Configurable $configurableProductType + * @param GetProductTypesBySkusInterface $getProductTypesBySkus */ public function __construct( ProductRepositoryInterface $productRepository, AreProductsSalableInterface $areProductsSalable, - Configurable $configurableProductType + Configurable $configurableProductType, + GetProductTypesBySkusInterface $getProductTypesBySkus ) { $this->productRepository = $productRepository; $this->areProductsSalable = $areProductsSalable; $this->configurableProductType = $configurableProductType; + $this->getProductTypesBySkus = $getProductTypesBySkus; } /** @@ -73,11 +81,13 @@ public function afterExecute( } try { - $product = $this->productRepository->get($sku); - if ($product->getTypeId() !== Configurable::TYPE_CODE) { + $types = $this->getProductTypesBySkus->execute([$sku]); + + if (!isset($types[$sku]) || $types[$sku] !== Configurable::TYPE_CODE) { return $resultStatus; } + $product = $this->productRepository->get($sku); /** @noinspection PhpParamsInspection */ $options = $this->configurableProductType->getConfigurableOptions($product); $skus = [[]]; From a8fe881c73c437c27946d0445423c95b6c946e38 Mon Sep 17 00:00:00 2001 From: oleksandrkravchuk Date: Sun, 2 Aug 2020 23:13:00 +0200 Subject: [PATCH 05/26] Fix typo. --- .../IsProductSalableCondition/IsBundleSaleableCondition.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InventoryBundleProduct/Model/IsProductSalableCondition/IsBundleSaleableCondition.php b/InventoryBundleProduct/Model/IsProductSalableCondition/IsBundleSaleableCondition.php index 42f9b30d6616..64b4463eb682 100644 --- a/InventoryBundleProduct/Model/IsProductSalableCondition/IsBundleSaleableCondition.php +++ b/InventoryBundleProduct/Model/IsProductSalableCondition/IsBundleSaleableCondition.php @@ -78,7 +78,7 @@ public function execute(string $sku, int $stockId): bool $product = $this->productRepository->get($sku); /** @noinspection PhpParamsInspection */ $options = $this->bundleProductType->getOptionsCollection($product); - $status = (int)$this->getBundleProductStockStatus->execute( + $status = $this->getBundleProductStockStatus->execute( $product, $options->getItems(), $stockId From 07b8b9519727d3dc6e5cf3f5f19f9aaca8713b39 Mon Sep 17 00:00:00 2001 From: oleksandrkravchuk Date: Sat, 8 Aug 2020 19:00:46 +0200 Subject: [PATCH 06/26] Refactoring. Move bundle status check to plugin. Move configurable plugin to around. Both facts comes from fact for bundle and configurable produts, salability status is depends only on salability status of their children (and does not depend on the condition chain). --- .../IsBundleProductSalablePlugin.php} | 38 ++++++++++++++----- InventoryBundleProduct/etc/di.xml | 9 +---- .../AdaptAssignStatusToProductPlugin.php | 12 ++++++ .../IsConfigurableProductSalablePlugin.php | 30 ++++++++++----- .../IsProductSalableConditionChain.php | 2 +- 5 files changed, 63 insertions(+), 28 deletions(-) rename InventoryBundleProduct/{Model/IsProductSalableCondition/IsBundleSaleableCondition.php => Plugin/InventorySales/IsBundleProductSalablePlugin.php} (64%) diff --git a/InventoryBundleProduct/Model/IsProductSalableCondition/IsBundleSaleableCondition.php b/InventoryBundleProduct/Plugin/InventorySales/IsBundleProductSalablePlugin.php similarity index 64% rename from InventoryBundleProduct/Model/IsProductSalableCondition/IsBundleSaleableCondition.php rename to InventoryBundleProduct/Plugin/InventorySales/IsBundleProductSalablePlugin.php index 64b4463eb682..946d4585880a 100644 --- a/InventoryBundleProduct/Model/IsProductSalableCondition/IsBundleSaleableCondition.php +++ b/InventoryBundleProduct/Plugin/InventorySales/IsBundleProductSalablePlugin.php @@ -6,19 +6,20 @@ declare(strict_types=1); -namespace Magento\InventoryBundleProduct\Model\IsProductSalableCondition; +namespace Magento\InventoryBundleProduct\Plugin\InventorySales; use Magento\Bundle\Model\Product\Type; use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\LocalizedException; use Magento\InventoryBundleProduct\Model\GetBundleProductStockStatus; use Magento\InventoryCatalogApi\Model\GetProductTypesBySkusInterface; -use Magento\InventorySalesApi\Api\IsProductSalableInterface; +use Magento\InventorySales\Model\IsProductSalableCondition\IsProductSalableConditionChain; /** * Check if bundle product is salable with bundle options. */ -class IsBundleSaleableCondition implements IsProductSalableInterface +class IsBundleProductSalablePlugin { /** * @var Type @@ -59,23 +60,40 @@ public function __construct( } /** - * Is product salable for bundle product. - * + * @param IsProductSalableConditionChain $subject + * @param \Closure $proceed * @param string $sku * @param int $stockId * * @return bool + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function execute(string $sku, int $stockId): bool - { - $status = true; + public function aroundExecute( + IsProductSalableConditionChain $subject, + \Closure $proceed, + string $sku, + int $stockId + ): bool { try { $types = $this->getProductTypesBySkus->execute([$sku]); if (!isset($types[$sku]) || $types[$sku] !== Type::TYPE_CODE) { - return $status; + return $proceed($sku, $stockId); + } + + // @TODO VERY temporary solution untill https://github.com/magento/inventory/pull/3088 will be resolved + // Product salability MUST NOT BE CALLED during product load. + // Tests stabilization. + /** @var \Magento\Framework\Registry $registry */ + $registry = ObjectManager::getInstance()->get(\Magento\Framework\Registry::class); + $key = 'inventory_check_product' . $sku; + + if ($registry->registry($key)) { + $product = $registry->registry($key); + } else { + $product = $this->productRepository->get($sku); } - $product = $this->productRepository->get($sku); /** @noinspection PhpParamsInspection */ $options = $this->bundleProductType->getOptionsCollection($product); $status = $this->getBundleProductStockStatus->execute( diff --git a/InventoryBundleProduct/etc/di.xml b/InventoryBundleProduct/etc/di.xml index 5ee829f5782d..335a2ad0c9df 100644 --- a/InventoryBundleProduct/etc/di.xml +++ b/InventoryBundleProduct/etc/di.xml @@ -30,13 +30,6 @@ - - - - true - Magento\InventoryBundleProduct\Model\IsProductSalableCondition\IsBundleSaleableCondition - - - + diff --git a/InventoryCatalog/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php b/InventoryCatalog/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php index efc90a54218e..20c4c4a31955 100644 --- a/InventoryCatalog/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php +++ b/InventoryCatalog/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php @@ -9,6 +9,7 @@ use Magento\Catalog\Model\Product; use Magento\CatalogInventory\Helper\Stock; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\NoSuchEntityException; use Magento\InventoryCatalog\Model\GetStockIdForCurrentWebsite; use Magento\InventoryCatalogApi\Api\DefaultStockProviderInterface; @@ -78,6 +79,17 @@ public function beforeAssignStatusToProduct( } try { + // @TODO VERY temporary solution untill https://github.com/magento/inventory/pull/3088 will be resolved + // Product salability MUST NOT BE CALLED during product load. + // Tests stabilization. + /** @var \Magento\Framework\Registry $registry */ + $registry = ObjectManager::getInstance()->get(\Magento\Framework\Registry::class); + $key = 'inventory_check_product' . $product->getSku(); + if ($registry->registry($key)) { + $registry->unregister($key); + } + $registry->register($key, $product); + $this->getProductIdsBySkus->execute([$product->getSku()]); if (null === $status) { $stockId = $this->getStockIdForCurrentWebsite->execute(); diff --git a/InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalablePlugin.php b/InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalablePlugin.php index b2f5ab3078c6..fee336361aa5 100644 --- a/InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalablePlugin.php +++ b/InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalablePlugin.php @@ -8,8 +8,10 @@ namespace Magento\InventoryConfigurableProduct\Plugin\InventorySales; +use Closure; use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\ConfigurableProduct\Model\Product\Type\Configurable; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\NoSuchEntityException; use Magento\InventoryCatalogApi\Model\GetProductTypesBySkusInterface; use Magento\InventorySales\Model\IsProductSalableCondition\IsProductSalableConditionChain; @@ -35,6 +37,7 @@ class IsConfigurableProductSalablePlugin * @var Configurable */ private $configurableProductType; + /** * @var GetProductTypesBySkusInterface */ @@ -62,7 +65,7 @@ public function __construct( * Is configurable product salable. * * @param IsProductSalableConditionChain $subject - * @param bool $resultStatus + * @param Closure $proceed * @param string $sku * @param int $stockId * @@ -70,24 +73,33 @@ public function __construct( * * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function afterExecute( + public function aroundExecute( IsProductSalableConditionChain $subject, - bool $resultStatus, + Closure $proceed, string $sku, int $stockId ): bool { - if (!$resultStatus) { - return $resultStatus; - } - try { $types = $this->getProductTypesBySkus->execute([$sku]); if (!isset($types[$sku]) || $types[$sku] !== Configurable::TYPE_CODE) { - return $resultStatus; + return $proceed($sku, $stockId); } - $product = $this->productRepository->get($sku); + // @TODO VERY temporary solution untill https://github.com/magento/inventory/pull/3088 will be resolved + // Product salability MUST NOT BE CALLED during product load. + // Tests stabilization. + /** @var \Magento\Framework\Registry $registry */ + $registry = ObjectManager::getInstance()->get(\Magento\Framework\Registry::class); + $key = 'inventory_check_product' . $sku; + + if ($registry->registry($key)) { + $product = $registry->registry($key); + } else { + $product = $this->productRepository->get($sku); + } + + $resultStatus = false; /** @noinspection PhpParamsInspection */ $options = $this->configurableProductType->getConfigurableOptions($product); $skus = [[]]; diff --git a/InventorySales/Model/IsProductSalableCondition/IsProductSalableConditionChain.php b/InventorySales/Model/IsProductSalableCondition/IsProductSalableConditionChain.php index 0d7801542cb1..7d828125b1c2 100644 --- a/InventorySales/Model/IsProductSalableCondition/IsProductSalableConditionChain.php +++ b/InventorySales/Model/IsProductSalableCondition/IsProductSalableConditionChain.php @@ -117,6 +117,6 @@ public function execute(string $sku, int $stockId): bool return false; } - return false; + return true; } } From 75d2aa610b2d27073f0148b037ea75efb8f15189 Mon Sep 17 00:00:00 2001 From: oleksandrkravchuk Date: Thu, 13 Aug 2020 20:38:00 +0200 Subject: [PATCH 07/26] Fix static tests, fix integration tests, code review fixes, revert unneded changes. --- ...lablePlugin.php => IsBundleProductSalable.php} | 6 ++++-- InventoryBundleProduct/etc/di.xml | 2 +- .../Stock/AdaptAssignStatusToProductPlugin.php | 5 ++++- ...lugin.php => IsConfigurableProductSalable.php} | 4 ++-- InventoryConfigurableProduct/etc/di.xml | 2 +- .../IsProductSalableConditionChain.php | 15 +++++++++++++-- 6 files changed, 25 insertions(+), 9 deletions(-) rename InventoryBundleProduct/Plugin/InventorySales/{IsBundleProductSalablePlugin.php => IsBundleProductSalable.php} (94%) rename InventoryConfigurableProduct/Plugin/InventorySales/{IsConfigurableProductSalablePlugin.php => IsConfigurableProductSalable.php} (96%) diff --git a/InventoryBundleProduct/Plugin/InventorySales/IsBundleProductSalablePlugin.php b/InventoryBundleProduct/Plugin/InventorySales/IsBundleProductSalable.php similarity index 94% rename from InventoryBundleProduct/Plugin/InventorySales/IsBundleProductSalablePlugin.php rename to InventoryBundleProduct/Plugin/InventorySales/IsBundleProductSalable.php index 946d4585880a..b3713a1257d0 100644 --- a/InventoryBundleProduct/Plugin/InventorySales/IsBundleProductSalablePlugin.php +++ b/InventoryBundleProduct/Plugin/InventorySales/IsBundleProductSalable.php @@ -19,7 +19,7 @@ /** * Check if bundle product is salable with bundle options. */ -class IsBundleProductSalablePlugin +class IsBundleProductSalable { /** * @var Type @@ -60,6 +60,8 @@ public function __construct( } /** + * Get bundle product status based on child statuses. + * * @param IsProductSalableConditionChain $subject * @param \Closure $proceed * @param string $sku @@ -81,7 +83,7 @@ public function aroundExecute( return $proceed($sku, $stockId); } - // @TODO VERY temporary solution untill https://github.com/magento/inventory/pull/3088 will be resolved + // @TODO VERY temporary solution until https://github.com/magento/inventory/pull/3039 is resolved // Product salability MUST NOT BE CALLED during product load. // Tests stabilization. /** @var \Magento\Framework\Registry $registry */ diff --git a/InventoryBundleProduct/etc/di.xml b/InventoryBundleProduct/etc/di.xml index 335a2ad0c9df..665ab2b50cd6 100644 --- a/InventoryBundleProduct/etc/di.xml +++ b/InventoryBundleProduct/etc/di.xml @@ -30,6 +30,6 @@ - + diff --git a/InventoryCatalog/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php b/InventoryCatalog/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php index 20c4c4a31955..421c3a6e03c6 100644 --- a/InventoryCatalog/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php +++ b/InventoryCatalog/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php @@ -79,7 +79,7 @@ public function beforeAssignStatusToProduct( } try { - // @TODO VERY temporary solution untill https://github.com/magento/inventory/pull/3088 will be resolved + // @TODO VERY temporary solution until https://github.com/magento/inventory/pull/3039 is resolved // Product salability MUST NOT BE CALLED during product load. // Tests stabilization. /** @var \Magento\Framework\Registry $registry */ @@ -95,9 +95,12 @@ public function beforeAssignStatusToProduct( $stockId = $this->getStockIdForCurrentWebsite->execute(); $result = $this->areProductsSalable->execute([$product->getSku()], $stockId); $result = current($result); + $registry->unregister($key); return [$product, (int)$result->isSalable()]; } + $registry->unregister($key); } catch (NoSuchEntityException $e) { + $registry->unregister($key); return [$product, $status]; } return [$product, $status]; diff --git a/InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalablePlugin.php b/InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalable.php similarity index 96% rename from InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalablePlugin.php rename to InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalable.php index fee336361aa5..b9249a8a5170 100644 --- a/InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalablePlugin.php +++ b/InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalable.php @@ -21,7 +21,7 @@ * Check if configurable product is salable. * Moved from chain due to framework limitations (usage of 'AreProductsSalableInterface' provides cyclical dependency). */ -class IsConfigurableProductSalablePlugin +class IsConfigurableProductSalable { /** * @var ProductRepositoryInterface @@ -86,7 +86,7 @@ public function aroundExecute( return $proceed($sku, $stockId); } - // @TODO VERY temporary solution untill https://github.com/magento/inventory/pull/3088 will be resolved + // @TODO VERY temporary solution until https://github.com/magento/inventory/pull/3039 is resolved // Product salability MUST NOT BE CALLED during product load. // Tests stabilization. /** @var \Magento\Framework\Registry $registry */ diff --git a/InventoryConfigurableProduct/etc/di.xml b/InventoryConfigurableProduct/etc/di.xml index 271a28a76e4d..5164ebdb8efe 100644 --- a/InventoryConfigurableProduct/etc/di.xml +++ b/InventoryConfigurableProduct/etc/di.xml @@ -27,7 +27,7 @@ - + diff --git a/InventorySales/Model/IsProductSalableCondition/IsProductSalableConditionChain.php b/InventorySales/Model/IsProductSalableCondition/IsProductSalableConditionChain.php index 7d828125b1c2..a5b7b8aa1ba5 100644 --- a/InventorySales/Model/IsProductSalableCondition/IsProductSalableConditionChain.php +++ b/InventorySales/Model/IsProductSalableCondition/IsProductSalableConditionChain.php @@ -28,6 +28,8 @@ class IsProductSalableConditionChain implements IsProductSalableInterface /** * @param array $conditions + * + * @throws LocalizedException */ public function __construct( array $conditions @@ -36,9 +38,14 @@ public function __construct( } /** + * Vlidate and set conditions. + * * @param array $conditions + * + * @return void + * @throws LocalizedException */ - private function setConditions(array $conditions) + private function setConditions(array $conditions): void { $this->validateConditions($conditions); @@ -60,6 +67,8 @@ function ($item) { } /** + * Validate conditions instances. + * * @param array $conditions * @throws LocalizedException */ @@ -83,6 +92,8 @@ private function validateConditions(array $conditions) } /** + * Sort conditions by sort_order param. + * * @param array $conditions * @return array */ @@ -117,6 +128,6 @@ public function execute(string $sku, int $stockId): bool return false; } - return true; + return false; } } From 969d85d9eac2d863ab25dfcc8c0d3963386250cd Mon Sep 17 00:00:00 2001 From: Maksym Novik Date: Fri, 18 Sep 2020 19:11:58 +0300 Subject: [PATCH 08/26] Composite products support for IsProductSaleable. Fixed case when composite product has out of stock status. --- .../Plugin/InventorySales/IsBundleProductSalable.php | 6 ++++-- .../InventorySales/IsConfigurableProductSalable.php | 8 +++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/InventoryBundleProduct/Plugin/InventorySales/IsBundleProductSalable.php b/InventoryBundleProduct/Plugin/InventorySales/IsBundleProductSalable.php index b3713a1257d0..f9c4a7e95ecd 100644 --- a/InventoryBundleProduct/Plugin/InventorySales/IsBundleProductSalable.php +++ b/InventoryBundleProduct/Plugin/InventorySales/IsBundleProductSalable.php @@ -79,8 +79,10 @@ public function aroundExecute( ): bool { try { $types = $this->getProductTypesBySkus->execute([$sku]); - if (!isset($types[$sku]) || $types[$sku] !== Type::TYPE_CODE) { - return $proceed($sku, $stockId); + + $isProductSalable = $proceed($sku, $stockId); + if (!isset($types[$sku]) || $types[$sku] !== Type::TYPE_CODE || !$isProductSalable) { + return $isProductSalable; } // @TODO VERY temporary solution until https://github.com/magento/inventory/pull/3039 is resolved diff --git a/InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalable.php b/InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalable.php index b9249a8a5170..cebceb7c3f6c 100644 --- a/InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalable.php +++ b/InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalable.php @@ -82,8 +82,9 @@ public function aroundExecute( try { $types = $this->getProductTypesBySkus->execute([$sku]); - if (!isset($types[$sku]) || $types[$sku] !== Configurable::TYPE_CODE) { - return $proceed($sku, $stockId); + $isProductSalable = $proceed($sku, $stockId); + if (!isset($types[$sku]) || $types[$sku] !== Configurable::TYPE_CODE || !$isProductSalable) { + return $isProductSalable; } // @TODO VERY temporary solution until https://github.com/magento/inventory/pull/3039 is resolved @@ -100,7 +101,8 @@ public function aroundExecute( } $resultStatus = false; - /** @noinspection PhpParamsInspection */ + $product->unsetData('_cache_instance_used_product_attributes'); + $product->unsetData('_cache_instance_configurable_attributes'); $options = $this->configurableProductType->getConfigurableOptions($product); $skus = [[]]; foreach ($options as $attribute) { From 634edaada789fd7938bb54ff2d13220ff755bf7b Mon Sep 17 00:00:00 2001 From: Maksym Novik Date: Sun, 14 Jun 2020 22:19:28 +0300 Subject: [PATCH 09/26] Composite products support for IsProductSaleable. --- .../IsBundleSaleableCondition.php | 77 +++++++++++++++++ .../IsConfigurableProductSalable.php | 84 +++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 InventoryBundleProduct/Model/IsProductSalableCondition/IsBundleSaleableCondition.php create mode 100644 InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductSalable.php diff --git a/InventoryBundleProduct/Model/IsProductSalableCondition/IsBundleSaleableCondition.php b/InventoryBundleProduct/Model/IsProductSalableCondition/IsBundleSaleableCondition.php new file mode 100644 index 000000000000..5430921c4b8f --- /dev/null +++ b/InventoryBundleProduct/Model/IsProductSalableCondition/IsBundleSaleableCondition.php @@ -0,0 +1,77 @@ +bundleProductType = $type; + $this->repository = $repository; + $this->getBundleProductStockStatus = $getBundleProductStockStatus; + } + + /** + * Is product salable for bundle product. + * + * @param string $sku + * @param int $stockId + * + * @return bool + */ + public function execute(string $sku, int $stockId): bool + { + $status = false; + try { + $product = $this->repository->get($sku); + if ($product->getTypeId() === Type::TYPE_CODE) { + /** @noinspection PhpParamsInspection */ + $options = $this->bundleProductType->getOptionsCollection($product); + $status = (int)$this->getBundleProductStockStatus->execute( + $product, + $options->getItems(), + $stockId + ); + } + } catch (LocalizedException $e) { + $status = false; + } + + return $status; + } +} diff --git a/InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductSalable.php b/InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductSalable.php new file mode 100644 index 000000000000..05d5084f8088 --- /dev/null +++ b/InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductSalable.php @@ -0,0 +1,84 @@ +repository = $repository; + $this->areProductsSalable = $areProductsSalable; + $this->configurable = $configurable; + } + + /** + * Is configurable product salable. + * + * @param string $sku + * @param int $stockId + * + * @return bool + */ + public function execute(string $sku, int $stockId): bool + { + try { + $status = false; + $product = $this->repository->get($sku); + if ($product->getTypeId() === Configurable::TYPE_CODE) { + /** @noinspection PhpParamsInspection */ + $options = $this->configurable->getConfigurableOptions($product); + $skus = [[]]; + foreach ($options as $attribute) { + $skus[] = array_column($attribute, 'sku'); + } + $skus = array_merge(...$skus); + $results = $this->areProductsSalable->execute($skus, $stockId); + foreach ($results as $result) { + if ($result->isSalable()) { + $status = true; + break; + } + } + } + } catch (NoSuchEntityException $e) { + $status = false; + } + + return $status; + } +} From ed96f69a82b320601c2ad9c15f52bd9058030162 Mon Sep 17 00:00:00 2001 From: oleksandrkravchuk Date: Wed, 30 Sep 2020 14:35:10 +0300 Subject: [PATCH 10/26] magento/inventory#3140: Fix static tests. --- .../Stock/AdaptAssignStatusToProductPlugin.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/InventoryCatalog/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php b/InventoryCatalog/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php index 421c3a6e03c6..155468e17ded 100644 --- a/InventoryCatalog/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php +++ b/InventoryCatalog/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php @@ -78,13 +78,13 @@ public function beforeAssignStatusToProduct( return [$product, $status]; } + // @TODO VERY temporary solution until https://github.com/magento/inventory/pull/3039 is resolved + // Product salability MUST NOT BE CALLED during product load. + // Tests stabilization. + /** @var \Magento\Framework\Registry $registry */ + $registry = ObjectManager::getInstance()->get(\Magento\Framework\Registry::class); + $key = 'inventory_check_product' . $product->getSku(); try { - // @TODO VERY temporary solution until https://github.com/magento/inventory/pull/3039 is resolved - // Product salability MUST NOT BE CALLED during product load. - // Tests stabilization. - /** @var \Magento\Framework\Registry $registry */ - $registry = ObjectManager::getInstance()->get(\Magento\Framework\Registry::class); - $key = 'inventory_check_product' . $product->getSku(); if ($registry->registry($key)) { $registry->unregister($key); } From dff2271cde1008e458bc8c255e3b40952ca4c5aa Mon Sep 17 00:00:00 2001 From: Maksym Novik Date: Wed, 30 Sep 2020 16:05:44 +0300 Subject: [PATCH 11/26] Product salability improvements #3202. Updated TODOs --- .../Plugin/InventorySales/IsBundleProductSalable.php | 2 +- .../Helper/Stock/AdaptAssignStatusToProductPlugin.php | 2 +- .../Plugin/InventorySales/IsConfigurableProductSalable.php | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/InventoryBundleProduct/Plugin/InventorySales/IsBundleProductSalable.php b/InventoryBundleProduct/Plugin/InventorySales/IsBundleProductSalable.php index f9c4a7e95ecd..a519a4456a76 100644 --- a/InventoryBundleProduct/Plugin/InventorySales/IsBundleProductSalable.php +++ b/InventoryBundleProduct/Plugin/InventorySales/IsBundleProductSalable.php @@ -85,7 +85,7 @@ public function aroundExecute( return $isProductSalable; } - // @TODO VERY temporary solution until https://github.com/magento/inventory/pull/3039 is resolved + // TODO: remove in https://github.com/magento/inventory/issues/3201 // Product salability MUST NOT BE CALLED during product load. // Tests stabilization. /** @var \Magento\Framework\Registry $registry */ diff --git a/InventoryCatalog/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php b/InventoryCatalog/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php index 155468e17ded..ba54a8a82e64 100644 --- a/InventoryCatalog/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php +++ b/InventoryCatalog/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php @@ -78,7 +78,7 @@ public function beforeAssignStatusToProduct( return [$product, $status]; } - // @TODO VERY temporary solution until https://github.com/magento/inventory/pull/3039 is resolved + // TODO: remove in https://github.com/magento/inventory/issues/3201 // Product salability MUST NOT BE CALLED during product load. // Tests stabilization. /** @var \Magento\Framework\Registry $registry */ diff --git a/InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalable.php b/InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalable.php index cebceb7c3f6c..49922c0971b6 100644 --- a/InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalable.php +++ b/InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalable.php @@ -87,7 +87,7 @@ public function aroundExecute( return $isProductSalable; } - // @TODO VERY temporary solution until https://github.com/magento/inventory/pull/3039 is resolved + // TODO: remove in https://github.com/magento/inventory/issues/3201 // Product salability MUST NOT BE CALLED during product load. // Tests stabilization. /** @var \Magento\Framework\Registry $registry */ @@ -101,6 +101,7 @@ public function aroundExecute( } $resultStatus = false; + // TODO: remove in https://github.com/magento/inventory/issues/3201 $product->unsetData('_cache_instance_used_product_attributes'); $product->unsetData('_cache_instance_configurable_attributes'); $options = $this->configurableProductType->getConfigurableOptions($product); From b902536c81f0e77759769ab804c56c47046f8e15 Mon Sep 17 00:00:00 2001 From: oleksandrkravchuk Date: Fri, 2 Oct 2020 10:40:49 +0300 Subject: [PATCH 12/26] Product salability improvements #3202. Remove excess code. --- .../IsBundleSaleableCondition.php | 77 ----------------- .../IsConfigurableProductSalable.php | 84 ------------------- 2 files changed, 161 deletions(-) delete mode 100644 InventoryBundleProduct/Model/IsProductSalableCondition/IsBundleSaleableCondition.php delete mode 100644 InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductSalable.php diff --git a/InventoryBundleProduct/Model/IsProductSalableCondition/IsBundleSaleableCondition.php b/InventoryBundleProduct/Model/IsProductSalableCondition/IsBundleSaleableCondition.php deleted file mode 100644 index 5430921c4b8f..000000000000 --- a/InventoryBundleProduct/Model/IsProductSalableCondition/IsBundleSaleableCondition.php +++ /dev/null @@ -1,77 +0,0 @@ -bundleProductType = $type; - $this->repository = $repository; - $this->getBundleProductStockStatus = $getBundleProductStockStatus; - } - - /** - * Is product salable for bundle product. - * - * @param string $sku - * @param int $stockId - * - * @return bool - */ - public function execute(string $sku, int $stockId): bool - { - $status = false; - try { - $product = $this->repository->get($sku); - if ($product->getTypeId() === Type::TYPE_CODE) { - /** @noinspection PhpParamsInspection */ - $options = $this->bundleProductType->getOptionsCollection($product); - $status = (int)$this->getBundleProductStockStatus->execute( - $product, - $options->getItems(), - $stockId - ); - } - } catch (LocalizedException $e) { - $status = false; - } - - return $status; - } -} diff --git a/InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductSalable.php b/InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductSalable.php deleted file mode 100644 index 05d5084f8088..000000000000 --- a/InventoryConfigurableProduct/Model/IsProductSalableCondition/IsConfigurableProductSalable.php +++ /dev/null @@ -1,84 +0,0 @@ -repository = $repository; - $this->areProductsSalable = $areProductsSalable; - $this->configurable = $configurable; - } - - /** - * Is configurable product salable. - * - * @param string $sku - * @param int $stockId - * - * @return bool - */ - public function execute(string $sku, int $stockId): bool - { - try { - $status = false; - $product = $this->repository->get($sku); - if ($product->getTypeId() === Configurable::TYPE_CODE) { - /** @noinspection PhpParamsInspection */ - $options = $this->configurable->getConfigurableOptions($product); - $skus = [[]]; - foreach ($options as $attribute) { - $skus[] = array_column($attribute, 'sku'); - } - $skus = array_merge(...$skus); - $results = $this->areProductsSalable->execute($skus, $stockId); - foreach ($results as $result) { - if ($result->isSalable()) { - $status = true; - break; - } - } - } - } catch (NoSuchEntityException $e) { - $status = false; - } - - return $status; - } -} From b9e33c8f9374892438f30e824ed0a257a9a4722e Mon Sep 17 00:00:00 2001 From: Maksym Novik Date: Tue, 19 May 2020 21:59:31 +0300 Subject: [PATCH 13/26] Load product salability data on-demand #3201: Moved product salability calculation from observer to plugin method to be executed on demand. --- .../AdaptAssignStatusToProductPlugin.php | 96 -------------- InventoryBundleProduct/etc/di.xml | 6 - InventoryCatalog/Model/IsProductSalable.php | 67 ++++++++++ .../Model/Product/AfterGetIsSaleable.php | 49 ++++++++ .../Model/Product/Type/AfterGetIsSaleable.php | 43 +++++++ .../AdaptAssignStatusToProductPlugin.php | 108 ---------------- InventoryCatalog/etc/di.xml | 7 +- InventoryCatalog/etc/events.xml | 3 + .../AdaptAssignStatusToProductPlugin.php | 118 ------------------ .../etc/frontend/di.xml | 3 - 10 files changed, 168 insertions(+), 332 deletions(-) delete mode 100644 InventoryBundleProduct/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php create mode 100644 InventoryCatalog/Model/IsProductSalable.php create mode 100644 InventoryCatalog/Plugin/Catalog/Model/Product/AfterGetIsSaleable.php create mode 100644 InventoryCatalog/Plugin/Catalog/Model/Product/Type/AfterGetIsSaleable.php delete mode 100644 InventoryCatalog/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php delete mode 100644 InventoryConfigurableProduct/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php diff --git a/InventoryBundleProduct/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php b/InventoryBundleProduct/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php deleted file mode 100644 index 5e95a438df8a..000000000000 --- a/InventoryBundleProduct/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php +++ /dev/null @@ -1,96 +0,0 @@ -bundleProductType = $bundleProductType; - $this->getBundleProductStockStatus = $getBundleProductStockStatus; - $this->storeManager = $storeManager; - $this->stockResolver = $stockResolver; - } - - /** - * Process bundle product stock status, considering bundle selections. - * - * @param Stock $subject - * @param Product $product - * @param int|null $status - * @return array - * @throws LocalizedException - * @throws NoSuchEntityException - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function beforeAssignStatusToProduct( - Stock $subject, - Product $product, - $status = null - ): array { - if ($product->getTypeId() === Type::TYPE_CODE) { - $website = $this->storeManager->getWebsite(); - $stock = $this->stockResolver->execute(SalesChannelInterface::TYPE_WEBSITE, $website->getCode()); - $options = $this->bundleProductType->getOptionsCollection($product); - try { - $status = (int)$this->getBundleProductStockStatus->execute( - $product, - $options->getItems(), - $stock->getStockId() - ); - } catch (LocalizedException $e) { - $status = 0; - } - } - - return [$product, $status]; - } -} diff --git a/InventoryBundleProduct/etc/di.xml b/InventoryBundleProduct/etc/di.xml index 665ab2b50cd6..e4ace09948a9 100644 --- a/InventoryBundleProduct/etc/di.xml +++ b/InventoryBundleProduct/etc/di.xml @@ -26,10 +26,4 @@ - - - - - - diff --git a/InventoryCatalog/Model/IsProductSalable.php b/InventoryCatalog/Model/IsProductSalable.php new file mode 100644 index 000000000000..fdebd5a3790d --- /dev/null +++ b/InventoryCatalog/Model/IsProductSalable.php @@ -0,0 +1,67 @@ +getStockIdForCurrentWebsite = $getStockIdForCurrentWebsite; + $this->areProductsSalable = $areProductsSalable; + } + + /** + * @param Product $product + * + * @return bool + */ + public function execute(Product $product): bool + { + $salabilityStatus = false; + if ($product->getSku() !== null) { + $stockId = $this->getStockIdForCurrentWebsite->execute(); + if (isset($this->productStatusCache[$stockId][$product->getSku()])) { + return $this->productStatusCache[$stockId][$product->getSku()]; + } + + $stockId = $this->getStockIdForCurrentWebsite->execute(); + $result = current($this->areProductsSalable->execute([$product->getSku()], $stockId)); + $salabilityStatus = $result->isSalable(); + $this->productStatusCache[$stockId][$product->getSku()] = $salabilityStatus; + } + + return $salabilityStatus; + } +} diff --git a/InventoryCatalog/Plugin/Catalog/Model/Product/AfterGetIsSaleable.php b/InventoryCatalog/Plugin/Catalog/Model/Product/AfterGetIsSaleable.php new file mode 100644 index 000000000000..e2348e68916f --- /dev/null +++ b/InventoryCatalog/Plugin/Catalog/Model/Product/AfterGetIsSaleable.php @@ -0,0 +1,49 @@ +isProductSalable = $isProductSalable; + } + + /** + * @param Product $product + * + * @return bool + */ + public function aroundGetIsSalable(Product $product): bool + { + return $this->isProductSalable->execute($product); + } + + /** + * @param Product $product + * + * @return bool + */ + public function aroundIsSalable(Product $product): bool + { + return $this->isProductSalable->execute($product); + } +} diff --git a/InventoryCatalog/Plugin/Catalog/Model/Product/Type/AfterGetIsSaleable.php b/InventoryCatalog/Plugin/Catalog/Model/Product/Type/AfterGetIsSaleable.php new file mode 100644 index 000000000000..535a29656881 --- /dev/null +++ b/InventoryCatalog/Plugin/Catalog/Model/Product/Type/AfterGetIsSaleable.php @@ -0,0 +1,43 @@ +isProductSalable = $isProductSalable; + } + + /** + * @param AbstractType $subject + * @param callable $proceed + * @param Product $product + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * + * @return bool + */ + public function aroundIsSalable(AbstractType $subject, callable $proceed, $product): bool + { + return $this->isProductSalable->execute($product); + } +} diff --git a/InventoryCatalog/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php b/InventoryCatalog/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php deleted file mode 100644 index ba54a8a82e64..000000000000 --- a/InventoryCatalog/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php +++ /dev/null @@ -1,108 +0,0 @@ -getStockIdForCurrentWebsite = $getStockIdForCurrentWebsite; - $this->areProductsSalable = $areProductsSalable; - $this->defaultStockProvider = $defaultStockProvider; - $this->getProductIdsBySkus = $getProductIdsBySkus; - } - - /** - * Assign stock status to product considering multi stock environment. - * - * @param Stock $subject - * @param Product $product - * @param int|null $status - * @return array - * - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function beforeAssignStatusToProduct( - Stock $subject, - Product $product, - ?int $status = null - ): array { - if (null === $product->getSku()) { - return [$product, $status]; - } - - // TODO: remove in https://github.com/magento/inventory/issues/3201 - // Product salability MUST NOT BE CALLED during product load. - // Tests stabilization. - /** @var \Magento\Framework\Registry $registry */ - $registry = ObjectManager::getInstance()->get(\Magento\Framework\Registry::class); - $key = 'inventory_check_product' . $product->getSku(); - try { - if ($registry->registry($key)) { - $registry->unregister($key); - } - $registry->register($key, $product); - - $this->getProductIdsBySkus->execute([$product->getSku()]); - if (null === $status) { - $stockId = $this->getStockIdForCurrentWebsite->execute(); - $result = $this->areProductsSalable->execute([$product->getSku()], $stockId); - $result = current($result); - $registry->unregister($key); - return [$product, (int)$result->isSalable()]; - } - $registry->unregister($key); - } catch (NoSuchEntityException $e) { - $registry->unregister($key); - return [$product, $status]; - } - return [$product, $status]; - } -} diff --git a/InventoryCatalog/etc/di.xml b/InventoryCatalog/etc/di.xml index 7a598862cb68..77663a2f9279 100644 --- a/InventoryCatalog/etc/di.xml +++ b/InventoryCatalog/etc/di.xml @@ -53,7 +53,6 @@ - @@ -165,6 +164,12 @@ + + + + + + diff --git a/InventoryCatalog/etc/events.xml b/InventoryCatalog/etc/events.xml index 9ff6549b3633..62ffc7fc180e 100644 --- a/InventoryCatalog/etc/events.xml +++ b/InventoryCatalog/etc/events.xml @@ -6,6 +6,9 @@ */ --> + + + diff --git a/InventoryConfigurableProduct/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php b/InventoryConfigurableProduct/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php deleted file mode 100644 index a5eeda15305a..000000000000 --- a/InventoryConfigurableProduct/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php +++ /dev/null @@ -1,118 +0,0 @@ -configurable = $configurable; - $this->areProductsSalable = $areProductsSalable; - $this->storeManager = $storeManager; - $this->stockResolver = $stockResolver; - $this->getStockItemData = $getStockItemData; - } - - /** - * Process configurable product stock status, considering configurable options. - * - * @param Stock $subject - * @param Product $product - * @param int|null $status - * @return array - * - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function beforeAssignStatusToProduct( - Stock $subject, - Product $product, - $status = null - ): array { - if ($product->getTypeId() === Configurable::TYPE_CODE) { - $website = $this->storeManager->getWebsite(); - $stock = $this->stockResolver->execute(SalesChannelInterface::TYPE_WEBSITE, $website->getCode()); - $stockId = $stock->getStockId(); - try { - $stockItemData = $this->getStockItemData->execute($product->getSku(), $stockId); - } catch (NoSuchEntityException $exception) { - $stockItemData = null; - } - if (null !== $stockItemData) { - if (!((bool) $stockItemData[GetStockItemDataInterface::IS_SALABLE])) { - return [$product, $status]; - } - } - $options = $this->configurable->getConfigurableOptions($product); - $status = 0; - $skus = [[]]; - foreach ($options as $attribute) { - $skus[] = array_column($attribute, 'sku'); - } - $skus = array_merge(...$skus); - $results = $this->areProductsSalable->execute($skus, $stock->getStockId()); - foreach ($results as $result) { - if ($result->isSalable()) { - $status = 1; - break; - } - } - } - - return [$product, $status]; - } -} diff --git a/InventoryConfigurableProduct/etc/frontend/di.xml b/InventoryConfigurableProduct/etc/frontend/di.xml index e2e71d3e3cdf..68515ce01275 100644 --- a/InventoryConfigurableProduct/etc/frontend/di.xml +++ b/InventoryConfigurableProduct/etc/frontend/di.xml @@ -12,7 +12,4 @@ - - - From dbacea10cc99e874df95fa0a75ab7ccba40605e5 Mon Sep 17 00:00:00 2001 From: Maksym Novik Date: Wed, 20 May 2020 18:16:26 +0300 Subject: [PATCH 14/26] Load product salability data on-demand #3201. Moved plugins to isAvailable only. --- ...AfterGetIsSaleable.php => IsAvailable.php} | 14 +----- .../Model/Product/Type/AfterGetIsSaleable.php | 43 ------------------- InventoryCatalog/etc/di.xml | 5 +-- 3 files changed, 3 insertions(+), 59 deletions(-) rename InventoryCatalog/Plugin/Catalog/Model/Product/{AfterGetIsSaleable.php => IsAvailable.php} (71%) delete mode 100644 InventoryCatalog/Plugin/Catalog/Model/Product/Type/AfterGetIsSaleable.php diff --git a/InventoryCatalog/Plugin/Catalog/Model/Product/AfterGetIsSaleable.php b/InventoryCatalog/Plugin/Catalog/Model/Product/IsAvailable.php similarity index 71% rename from InventoryCatalog/Plugin/Catalog/Model/Product/AfterGetIsSaleable.php rename to InventoryCatalog/Plugin/Catalog/Model/Product/IsAvailable.php index e2348e68916f..59f208f500a1 100644 --- a/InventoryCatalog/Plugin/Catalog/Model/Product/AfterGetIsSaleable.php +++ b/InventoryCatalog/Plugin/Catalog/Model/Product/IsAvailable.php @@ -11,7 +11,7 @@ use Magento\Catalog\Model\Product; use Magento\InventoryCatalog\Model\IsProductSalable; -class AfterGetIsSaleable +class IsAvailable { /** * @var IsProductSalable @@ -32,17 +32,7 @@ public function __construct( * * @return bool */ - public function aroundGetIsSalable(Product $product): bool - { - return $this->isProductSalable->execute($product); - } - - /** - * @param Product $product - * - * @return bool - */ - public function aroundIsSalable(Product $product): bool + public function aroundIsAvailable(Product $product): bool { return $this->isProductSalable->execute($product); } diff --git a/InventoryCatalog/Plugin/Catalog/Model/Product/Type/AfterGetIsSaleable.php b/InventoryCatalog/Plugin/Catalog/Model/Product/Type/AfterGetIsSaleable.php deleted file mode 100644 index 535a29656881..000000000000 --- a/InventoryCatalog/Plugin/Catalog/Model/Product/Type/AfterGetIsSaleable.php +++ /dev/null @@ -1,43 +0,0 @@ -isProductSalable = $isProductSalable; - } - - /** - * @param AbstractType $subject - * @param callable $proceed - * @param Product $product - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - * - * @return bool - */ - public function aroundIsSalable(AbstractType $subject, callable $proceed, $product): bool - { - return $this->isProductSalable->execute($product); - } -} diff --git a/InventoryCatalog/etc/di.xml b/InventoryCatalog/etc/di.xml index 77663a2f9279..377a72dd4d7f 100644 --- a/InventoryCatalog/etc/di.xml +++ b/InventoryCatalog/etc/di.xml @@ -165,10 +165,7 @@ - - - - + From 05d5a9c28e8c3dbc7808b317c10762d02e26b123 Mon Sep 17 00:00:00 2001 From: nmalevanec Date: Fri, 22 May 2020 14:01:20 +0300 Subject: [PATCH 15/26] Load product salability data on-demand #3201. Fix tests. --- InventoryCatalog/Model/IsProductSalable.php | 33 ++++++++++++--------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/InventoryCatalog/Model/IsProductSalable.php b/InventoryCatalog/Model/IsProductSalable.php index fdebd5a3790d..79072897c318 100644 --- a/InventoryCatalog/Model/IsProductSalable.php +++ b/InventoryCatalog/Model/IsProductSalable.php @@ -9,9 +9,11 @@ namespace Magento\InventoryCatalog\Model; use Magento\Catalog\Model\Product; -use Magento\InventoryCatalogApi\Model\GetProductIdsBySkusInterface; use Magento\InventorySalesApi\Api\AreProductsSalableInterface; +/** + * Get salable product status service. + */ class IsProductSalable { /** @@ -32,7 +34,6 @@ class IsProductSalable /** * @param GetStockIdForCurrentWebsite $getStockIdForCurrentWebsite * @param AreProductsSalableInterface $areProductsSalable - * @param GetProductIdsBySkusInterface $getProductIdsBySkus */ public function __construct( GetStockIdForCurrentWebsite $getStockIdForCurrentWebsite, @@ -43,24 +44,28 @@ public function __construct( } /** - * @param Product $product + * Verify product salable status. * + * @param Product $product * @return bool */ public function execute(Product $product): bool { - $salabilityStatus = false; - if ($product->getSku() !== null) { - $stockId = $this->getStockIdForCurrentWebsite->execute(); - if (isset($this->productStatusCache[$stockId][$product->getSku()])) { - return $this->productStatusCache[$stockId][$product->getSku()]; - } - - $stockId = $this->getStockIdForCurrentWebsite->execute(); - $result = current($this->areProductsSalable->execute([$product->getSku()], $stockId)); - $salabilityStatus = $result->isSalable(); - $this->productStatusCache[$stockId][$product->getSku()] = $salabilityStatus; + if (null === $product->getSku()) { + return false; + } + if ($product->getData('is_salable') !== null) { + return (bool)$product->getData('is_salable'); } + $stockId = $this->getStockIdForCurrentWebsite->execute(); + if (isset($this->productStatusCache[$stockId][$product->getSku()])) { + return $this->productStatusCache[$stockId][$product->getSku()]; + } + + $stockId = $this->getStockIdForCurrentWebsite->execute(); + $result = current($this->areProductsSalable->execute([$product->getSku()], $stockId)); + $salabilityStatus = $result->isSalable(); + $this->productStatusCache[$stockId][$product->getSku()] = $salabilityStatus; return $salabilityStatus; } From a9772174284b9615efbd3da30ed1fe834da8585d Mon Sep 17 00:00:00 2001 From: Stanislav Idolov Date: Sat, 23 May 2020 17:53:28 +0300 Subject: [PATCH 16/26] Load product salability data on-demand #3201. Fixed is salable logic. --- ...{IsAvailable.php => IsAvailablePlugin.php} | 11 +++-- .../Catalog/Model/Product/IsSalablePlugin.php | 41 +++++++++++++++++++ InventoryCatalog/etc/di.xml | 3 +- .../StatusCondition.php | 36 ++++++++++++++++ InventorySales/etc/di.xml | 4 ++ 5 files changed, 91 insertions(+), 4 deletions(-) rename InventoryCatalog/Plugin/Catalog/Model/Product/{IsAvailable.php => IsAvailablePlugin.php} (76%) create mode 100644 InventoryCatalog/Plugin/Catalog/Model/Product/IsSalablePlugin.php create mode 100644 InventorySales/Model/IsProductSalableCondition/StatusCondition.php diff --git a/InventoryCatalog/Plugin/Catalog/Model/Product/IsAvailable.php b/InventoryCatalog/Plugin/Catalog/Model/Product/IsAvailablePlugin.php similarity index 76% rename from InventoryCatalog/Plugin/Catalog/Model/Product/IsAvailable.php rename to InventoryCatalog/Plugin/Catalog/Model/Product/IsAvailablePlugin.php index 59f208f500a1..7e024826844f 100644 --- a/InventoryCatalog/Plugin/Catalog/Model/Product/IsAvailable.php +++ b/InventoryCatalog/Plugin/Catalog/Model/Product/IsAvailablePlugin.php @@ -3,15 +3,16 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - declare(strict_types=1); namespace Magento\InventoryCatalog\Plugin\Catalog\Model\Product; use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Product\Type\Simple; use Magento\InventoryCatalog\Model\IsProductSalable; -class IsAvailable + +class IsAvailablePlugin { /** * @var IsProductSalable @@ -28,9 +29,13 @@ public function __construct( } /** - * @param Product $product + * Fetches is salable status from multi-stock. * + * @param Simple $subject + * @param \Closure $proceed + * @param Product $product * @return bool + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function aroundIsAvailable(Product $product): bool { diff --git a/InventoryCatalog/Plugin/Catalog/Model/Product/IsSalablePlugin.php b/InventoryCatalog/Plugin/Catalog/Model/Product/IsSalablePlugin.php new file mode 100644 index 000000000000..25913986e5cf --- /dev/null +++ b/InventoryCatalog/Plugin/Catalog/Model/Product/IsSalablePlugin.php @@ -0,0 +1,41 @@ +isProductSalable = $isProductSalable; + } + + /** + * Fetches is salable status from multi-stock. + * + * @param Product $product + * @return bool + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function aroundIsSalable(Product $product): bool + { + return $this->isProductSalable->execute($product); + } +} diff --git a/InventoryCatalog/etc/di.xml b/InventoryCatalog/etc/di.xml index 377a72dd4d7f..e3a8f71b1267 100644 --- a/InventoryCatalog/etc/di.xml +++ b/InventoryCatalog/etc/di.xml @@ -165,7 +165,8 @@ - + + diff --git a/InventorySales/Model/IsProductSalableCondition/StatusCondition.php b/InventorySales/Model/IsProductSalableCondition/StatusCondition.php new file mode 100644 index 000000000000..7057b2541339 --- /dev/null +++ b/InventorySales/Model/IsProductSalableCondition/StatusCondition.php @@ -0,0 +1,36 @@ +productRepository = $productRepository; + } + + /** + * @inheritdoc + */ + public function execute(string $sku, int $stockId): bool + { + $product = $this->productRepository->get($sku); + return $product->getStatus() === \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED; + } +} diff --git a/InventorySales/etc/di.xml b/InventorySales/etc/di.xml index b94a1e61023e..ae9e4febd404 100644 --- a/InventorySales/etc/di.xml +++ b/InventorySales/etc/di.xml @@ -57,6 +57,10 @@ + + true + Magento\InventorySales\Model\IsProductSalableCondition\StatusCondition + true Magento\InventorySales\Model\IsProductSalableCondition\IsSetInStockStatusForCompositeProductCondition From 77ed7467cc4050224e6b36391c13a59ec95c2cd5 Mon Sep 17 00:00:00 2001 From: Maksym Novik Date: Fri, 2 Oct 2020 12:44:16 +0300 Subject: [PATCH 17/26] Load product salability data on-demand #3201. --- InventoryCatalog/Model/IsProductSalable.php | 3 +- .../Model/Product/IsAvailablePlugin.php | 12 +++---- .../Catalog/Model/Product/IsSalablePlugin.php | 4 +-- .../StatusCondition.php | 36 ------------------- InventorySales/etc/di.xml | 4 --- 5 files changed, 10 insertions(+), 49 deletions(-) delete mode 100644 InventorySales/Model/IsProductSalableCondition/StatusCondition.php diff --git a/InventoryCatalog/Model/IsProductSalable.php b/InventoryCatalog/Model/IsProductSalable.php index 79072897c318..148006a0ef96 100644 --- a/InventoryCatalog/Model/IsProductSalable.php +++ b/InventoryCatalog/Model/IsProductSalable.php @@ -9,6 +9,7 @@ namespace Magento\InventoryCatalog\Model; use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Product\Attribute\Source\Status; use Magento\InventorySalesApi\Api\AreProductsSalableInterface; /** @@ -51,7 +52,7 @@ public function __construct( */ public function execute(Product $product): bool { - if (null === $product->getSku()) { + if (null === $product->getSku() || (int)$product->getStatus() === Status::STATUS_DISABLED) { return false; } if ($product->getData('is_salable') !== null) { diff --git a/InventoryCatalog/Plugin/Catalog/Model/Product/IsAvailablePlugin.php b/InventoryCatalog/Plugin/Catalog/Model/Product/IsAvailablePlugin.php index 7e024826844f..e4dda555376b 100644 --- a/InventoryCatalog/Plugin/Catalog/Model/Product/IsAvailablePlugin.php +++ b/InventoryCatalog/Plugin/Catalog/Model/Product/IsAvailablePlugin.php @@ -8,10 +8,11 @@ namespace Magento\InventoryCatalog\Plugin\Catalog\Model\Product; use Magento\Catalog\Model\Product; -use Magento\Catalog\Model\Product\Type\Simple; use Magento\InventoryCatalog\Model\IsProductSalable; - +/** + * Is product available in multi stock environment plugin. + */ class IsAvailablePlugin { /** @@ -31,14 +32,13 @@ public function __construct( /** * Fetches is salable status from multi-stock. * - * @param Simple $subject + * @param Product $subject * @param \Closure $proceed - * @param Product $product * @return bool * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundIsAvailable(Product $product): bool + public function aroundIsAvailable(Product $subject, \Closure $proceed): bool { - return $this->isProductSalable->execute($product); + return $this->isProductSalable->execute($subject); } } diff --git a/InventoryCatalog/Plugin/Catalog/Model/Product/IsSalablePlugin.php b/InventoryCatalog/Plugin/Catalog/Model/Product/IsSalablePlugin.php index 25913986e5cf..1c8b7a96a473 100644 --- a/InventoryCatalog/Plugin/Catalog/Model/Product/IsSalablePlugin.php +++ b/InventoryCatalog/Plugin/Catalog/Model/Product/IsSalablePlugin.php @@ -8,7 +8,6 @@ namespace Magento\InventoryCatalog\Plugin\Catalog\Model\Product; use Magento\Catalog\Model\Product; -use Magento\Catalog\Model\Product\Type\Simple; use Magento\InventoryCatalog\Model\IsProductSalable; class IsSalablePlugin @@ -31,10 +30,11 @@ public function __construct( * Fetches is salable status from multi-stock. * * @param Product $product + * @param \Closure $proceed * @return bool * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundIsSalable(Product $product): bool + public function aroundIsSalable(Product $product, \Closure $proceed): bool { return $this->isProductSalable->execute($product); } diff --git a/InventorySales/Model/IsProductSalableCondition/StatusCondition.php b/InventorySales/Model/IsProductSalableCondition/StatusCondition.php deleted file mode 100644 index 7057b2541339..000000000000 --- a/InventorySales/Model/IsProductSalableCondition/StatusCondition.php +++ /dev/null @@ -1,36 +0,0 @@ -productRepository = $productRepository; - } - - /** - * @inheritdoc - */ - public function execute(string $sku, int $stockId): bool - { - $product = $this->productRepository->get($sku); - return $product->getStatus() === \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED; - } -} diff --git a/InventorySales/etc/di.xml b/InventorySales/etc/di.xml index ae9e4febd404..b94a1e61023e 100644 --- a/InventorySales/etc/di.xml +++ b/InventorySales/etc/di.xml @@ -57,10 +57,6 @@ - - true - Magento\InventorySales\Model\IsProductSalableCondition\StatusCondition - true Magento\InventorySales\Model\IsProductSalableCondition\IsSetInStockStatusForCompositeProductCondition From 8765d0158a25ec95730a68d109a53bb37d2ecf0d Mon Sep 17 00:00:00 2001 From: Maksym Novik Date: Fri, 2 Oct 2020 18:42:45 +0300 Subject: [PATCH 18/26] Load product salability data on-demand #3201. Restored Bundles support plugin for IsProductSalableChain --- InventoryBundleProduct/etc/di.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/InventoryBundleProduct/etc/di.xml b/InventoryBundleProduct/etc/di.xml index e4ace09948a9..e9d615337e5a 100644 --- a/InventoryBundleProduct/etc/di.xml +++ b/InventoryBundleProduct/etc/di.xml @@ -26,4 +26,7 @@ + + + From 234001839db0ad2f2edc3e15961661de9544da47 Mon Sep 17 00:00:00 2001 From: oleksandrkravchuk Date: Fri, 23 Oct 2020 15:03:16 +0200 Subject: [PATCH 19/26] Load product salability data on-demand #3201. Tests fix and stabilizations. --- .../InventorySales/IsBundleProductSalable.php | 15 ++++----------- InventoryCatalog/Model/IsProductSalable.php | 2 +- .../IsConfigurableProductSalable.php | 17 ++--------------- 3 files changed, 7 insertions(+), 27 deletions(-) diff --git a/InventoryBundleProduct/Plugin/InventorySales/IsBundleProductSalable.php b/InventoryBundleProduct/Plugin/InventorySales/IsBundleProductSalable.php index a519a4456a76..b8f6155cdcc0 100644 --- a/InventoryBundleProduct/Plugin/InventorySales/IsBundleProductSalable.php +++ b/InventoryBundleProduct/Plugin/InventorySales/IsBundleProductSalable.php @@ -10,7 +10,6 @@ use Magento\Bundle\Model\Product\Type; use Magento\Catalog\Api\ProductRepositoryInterface; -use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\LocalizedException; use Magento\InventoryBundleProduct\Model\GetBundleProductStockStatus; use Magento\InventoryCatalogApi\Model\GetProductTypesBySkusInterface; @@ -85,17 +84,10 @@ public function aroundExecute( return $isProductSalable; } - // TODO: remove in https://github.com/magento/inventory/issues/3201 - // Product salability MUST NOT BE CALLED during product load. - // Tests stabilization. - /** @var \Magento\Framework\Registry $registry */ - $registry = ObjectManager::getInstance()->get(\Magento\Framework\Registry::class); - $key = 'inventory_check_product' . $sku; + $product = $this->productRepository->get($sku); - if ($registry->registry($key)) { - $product = $registry->registry($key); - } else { - $product = $this->productRepository->get($sku); + if ($product->hasData('all_items_salable')) { + return $product->getData('all_items_salable'); } /** @noinspection PhpParamsInspection */ @@ -105,6 +97,7 @@ public function aroundExecute( $options->getItems(), $stockId ); + $product->setData('all_items_salable', $status); } catch (LocalizedException $e) { $status = false; } diff --git a/InventoryCatalog/Model/IsProductSalable.php b/InventoryCatalog/Model/IsProductSalable.php index 148006a0ef96..e40d32f61fe0 100644 --- a/InventoryCatalog/Model/IsProductSalable.php +++ b/InventoryCatalog/Model/IsProductSalable.php @@ -52,7 +52,7 @@ public function __construct( */ public function execute(Product $product): bool { - if (null === $product->getSku() || (int)$product->getStatus() === Status::STATUS_DISABLED) { + if (null === $product->getSku() || !((int)$product->getStatus() === Status::STATUS_ENABLED)) { return false; } if ($product->getData('is_salable') !== null) { diff --git a/InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalable.php b/InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalable.php index 49922c0971b6..6d1a925ab8b0 100644 --- a/InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalable.php +++ b/InventoryConfigurableProduct/Plugin/InventorySales/IsConfigurableProductSalable.php @@ -87,23 +87,10 @@ public function aroundExecute( return $isProductSalable; } - // TODO: remove in https://github.com/magento/inventory/issues/3201 - // Product salability MUST NOT BE CALLED during product load. - // Tests stabilization. - /** @var \Magento\Framework\Registry $registry */ - $registry = ObjectManager::getInstance()->get(\Magento\Framework\Registry::class); - $key = 'inventory_check_product' . $sku; - - if ($registry->registry($key)) { - $product = $registry->registry($key); - } else { - $product = $this->productRepository->get($sku); - } + $product = $this->productRepository->get($sku); $resultStatus = false; - // TODO: remove in https://github.com/magento/inventory/issues/3201 - $product->unsetData('_cache_instance_used_product_attributes'); - $product->unsetData('_cache_instance_configurable_attributes'); + $options = $this->configurableProductType->getConfigurableOptions($product); $skus = [[]]; foreach ($options as $attribute) { From d106eb070906bf1246b42d870b3061cb48b4b582 Mon Sep 17 00:00:00 2001 From: oleksandrkravchuk Date: Fri, 23 Oct 2020 16:18:09 +0200 Subject: [PATCH 20/26] Load product salability data on-demand #3201. Tests fix and stabilizations. --- .../IsBundleProductSalable.php | 48 +++++++++++++++++++ InventoryBundleProduct/etc/frontend/di.xml | 12 +++++ InventoryBundleProduct/etc/graphql/di.xml | 12 +++++ InventoryCatalog/Model/IsProductSalable.php | 16 ++----- .../Catalog/Model/Product/IsSalablePlugin.php | 41 ---------------- InventoryCatalog/etc/di.xml | 1 - 6 files changed, 75 insertions(+), 55 deletions(-) create mode 100644 InventoryBundleProduct/Plugin/InventoryCatalog/IsBundleProductSalable.php create mode 100644 InventoryBundleProduct/etc/frontend/di.xml create mode 100644 InventoryBundleProduct/etc/graphql/di.xml delete mode 100644 InventoryCatalog/Plugin/Catalog/Model/Product/IsSalablePlugin.php diff --git a/InventoryBundleProduct/Plugin/InventoryCatalog/IsBundleProductSalable.php b/InventoryBundleProduct/Plugin/InventoryCatalog/IsBundleProductSalable.php new file mode 100644 index 000000000000..5dac2e049c00 --- /dev/null +++ b/InventoryBundleProduct/Plugin/InventoryCatalog/IsBundleProductSalable.php @@ -0,0 +1,48 @@ +getTypeId() !== Type::TYPE_CODE) { + return $proceed($product); + } + + if ($product->hasData('all_items_salable')) { + return $product->getData('all_items_salable'); + } + + $isSalable = $proceed($product); + $product->setData('all_items_salable', $isSalable); + + return $isSalable; + } +} diff --git a/InventoryBundleProduct/etc/frontend/di.xml b/InventoryBundleProduct/etc/frontend/di.xml new file mode 100644 index 000000000000..2717223aab13 --- /dev/null +++ b/InventoryBundleProduct/etc/frontend/di.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/InventoryBundleProduct/etc/graphql/di.xml b/InventoryBundleProduct/etc/graphql/di.xml new file mode 100644 index 000000000000..2717223aab13 --- /dev/null +++ b/InventoryBundleProduct/etc/graphql/di.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/InventoryCatalog/Model/IsProductSalable.php b/InventoryCatalog/Model/IsProductSalable.php index e40d32f61fe0..f57968ec2476 100644 --- a/InventoryCatalog/Model/IsProductSalable.php +++ b/InventoryCatalog/Model/IsProductSalable.php @@ -27,11 +27,6 @@ class IsProductSalable */ private $areProductsSalable; - /** - * @var array - */ - private $productStatusCache; - /** * @param GetStockIdForCurrentWebsite $getStockIdForCurrentWebsite * @param AreProductsSalableInterface $areProductsSalable @@ -58,16 +53,11 @@ public function execute(Product $product): bool if ($product->getData('is_salable') !== null) { return (bool)$product->getData('is_salable'); } - $stockId = $this->getStockIdForCurrentWebsite->execute(); - if (isset($this->productStatusCache[$stockId][$product->getSku()])) { - return $this->productStatusCache[$stockId][$product->getSku()]; - } - $stockId = $this->getStockIdForCurrentWebsite->execute(); $result = current($this->areProductsSalable->execute([$product->getSku()], $stockId)); - $salabilityStatus = $result->isSalable(); - $this->productStatusCache[$stockId][$product->getSku()] = $salabilityStatus; + $isSalable = $result->isSalable(); + $product->setData('is_salable', $isSalable); - return $salabilityStatus; + return $isSalable; } } diff --git a/InventoryCatalog/Plugin/Catalog/Model/Product/IsSalablePlugin.php b/InventoryCatalog/Plugin/Catalog/Model/Product/IsSalablePlugin.php deleted file mode 100644 index 1c8b7a96a473..000000000000 --- a/InventoryCatalog/Plugin/Catalog/Model/Product/IsSalablePlugin.php +++ /dev/null @@ -1,41 +0,0 @@ -isProductSalable = $isProductSalable; - } - - /** - * Fetches is salable status from multi-stock. - * - * @param Product $product - * @param \Closure $proceed - * @return bool - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function aroundIsSalable(Product $product, \Closure $proceed): bool - { - return $this->isProductSalable->execute($product); - } -} diff --git a/InventoryCatalog/etc/di.xml b/InventoryCatalog/etc/di.xml index e3a8f71b1267..45f92cbe1489 100644 --- a/InventoryCatalog/etc/di.xml +++ b/InventoryCatalog/etc/di.xml @@ -166,7 +166,6 @@ - From b22f0d2f1c254f7c7f197b1bae77635065cef3bd Mon Sep 17 00:00:00 2001 From: oleksandrkravchuk Date: Fri, 23 Oct 2020 16:33:52 +0200 Subject: [PATCH 21/26] Load product salability data on-demand #3201. Drop test of removed logic. --- .../Stock/AssignStatusToProductTest.php | 151 ------------------ 1 file changed, 151 deletions(-) delete mode 100644 InventoryCatalog/Test/Integration/CatalogInventory/Helper/Stock/AssignStatusToProductTest.php diff --git a/InventoryCatalog/Test/Integration/CatalogInventory/Helper/Stock/AssignStatusToProductTest.php b/InventoryCatalog/Test/Integration/CatalogInventory/Helper/Stock/AssignStatusToProductTest.php deleted file mode 100644 index 79b535cb86ce..000000000000 --- a/InventoryCatalog/Test/Integration/CatalogInventory/Helper/Stock/AssignStatusToProductTest.php +++ /dev/null @@ -1,151 +0,0 @@ -stockHelper = Bootstrap::getObjectManager()->get(Stock::class); - $this->productRepository = Bootstrap::getObjectManager()->get(ProductRepositoryInterface::class); - $this->storeManager = Bootstrap::getObjectManager()->get(StoreManagerInterface::class); - $this->storeCodeBefore = $this->storeManager->getStore()->getCode(); - } - - /** - * @magentoDataFixture Magento_InventoryApi::Test/_files/products.php - * @magentoDataFixture Magento_InventoryApi::Test/_files/sources.php - * @magentoDataFixture Magento_InventoryApi::Test/_files/stocks.php - * @magentoDataFixture Magento_InventoryApi::Test/_files/stock_source_links.php - * @magentoDataFixture Magento_InventoryApi::Test/_files/source_items.php - * @magentoDataFixture Magento_InventorySalesApi::Test/_files/websites_with_stores.php - * @magentoDataFixture Magento_InventorySalesApi::Test/_files/stock_website_sales_channels.php - * @magentoDataFixture Magento_InventoryIndexer::Test/_files/reindex_inventory.php - * @dataProvider assignStatusToProductDataProvider - * @param string $storeCode - * @param array $productsData - * - * @magentoDbIsolation disabled - */ - public function testAssignStatusToProductIfStatusParameterIsNotPassed(string $storeCode, array $productsData) - { - $this->storeManager->setCurrentStore($storeCode); - - foreach ($productsData as $sku => $expectedStatus) { - $product = $this->productRepository->get($sku); - /** @var Product $product */ - $this->stockHelper->assignStatusToProduct($product); - - self::assertEquals($expectedStatus, $product->isSalable()); - } - } - - /** - * @magentoDataFixture Magento_InventoryApi::Test/_files/products.php - * @magentoDataFixture Magento_InventoryApi::Test/_files/sources.php - * @magentoDataFixture Magento_InventoryApi::Test/_files/stocks.php - * @magentoDataFixture Magento_InventoryApi::Test/_files/stock_source_links.php - * @magentoDataFixture Magento_InventoryApi::Test/_files/source_items.php - * @magentoDataFixture Magento_InventorySalesApi::Test/_files/websites_with_stores.php - * @magentoDataFixture Magento_InventorySalesApi::Test/_files/stock_website_sales_channels.php - * @magentoDataFixture Magento_InventoryIndexer::Test/_files/reindex_inventory.php - * @dataProvider assignStatusToProductDataProvider - * @param string $storeCode - * @param array $productsData - * - * @magentoDbIsolation disabled - */ - public function testAssignStatusToProductIfStatusParameterIsPassed(string $storeCode, array $productsData) - { - $expectedStatus = 1; - $this->storeManager->setCurrentStore($storeCode); - - foreach (array_keys($productsData) as $sku) { - $product = $this->productRepository->get($sku); - /** @var Product $product */ - $this->stockHelper->assignStatusToProduct($product, $expectedStatus); - - self::assertEquals($expectedStatus, $product->isSalable()); - } - } - - /** - * @return array - */ - public function assignStatusToProductDataProvider(): array - { - return [ - 'eu_website' => [ - 'store_for_eu_website', - [ - 'SKU-1' => 1, - 'SKU-2' => 0, - 'SKU-3' => 0, - ], - ], - 'us_website' => [ - 'store_for_us_website', - [ - 'SKU-1' => 0, - 'SKU-2' => 1, - 'SKU-3' => 0, - ], - ], - 'global_website' => [ - 'store_for_global_website', - [ - 'SKU-1' => 1, - 'SKU-2' => 1, - 'SKU-3' => 0, - ], - ], - ]; - } - - /** - * @inheritdoc - */ - protected function tearDown(): void - { - $this->storeManager->setCurrentStore($this->storeCodeBefore); - - parent::tearDown(); - } -} From ed7f2a598cdcfa944e205376cd7e742a2dc91342 Mon Sep 17 00:00:00 2001 From: oleksandrkravchuk Date: Fri, 23 Oct 2020 19:59:07 +0200 Subject: [PATCH 22/26] Load product salability data on-demand #3201. Small refactoring. --- InventoryCatalog/Model/IsProductSalable.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InventoryCatalog/Model/IsProductSalable.php b/InventoryCatalog/Model/IsProductSalable.php index f57968ec2476..d13e483fe605 100644 --- a/InventoryCatalog/Model/IsProductSalable.php +++ b/InventoryCatalog/Model/IsProductSalable.php @@ -50,7 +50,7 @@ public function execute(Product $product): bool if (null === $product->getSku() || !((int)$product->getStatus() === Status::STATUS_ENABLED)) { return false; } - if ($product->getData('is_salable') !== null) { + if ($product->hasData('is_salable')) { return (bool)$product->getData('is_salable'); } $stockId = $this->getStockIdForCurrentWebsite->execute(); From d6125708bfdee6c3c7fc3fec1aeb15a49f635c1e Mon Sep 17 00:00:00 2001 From: OleksandrKravchuk Date: Sat, 24 Oct 2020 12:01:36 +0300 Subject: [PATCH 23/26] Load product salability data on-demand #3201. Fix Static Tests. --- InventoryBundleProduct/composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/InventoryBundleProduct/composer.json b/InventoryBundleProduct/composer.json index d101f485dbf2..42e208e20763 100644 --- a/InventoryBundleProduct/composer.json +++ b/InventoryBundleProduct/composer.json @@ -14,7 +14,8 @@ }, "suggest": { "magento/module-catalog-inventory": "*", - "magento/module-inventory-sales": "*" + "magento/module-inventory-sales": "*", + "magento/module-inventory-catalog": "*" }, "type": "magento2-module", "license": [ From 9ed24ae336baf10e8ba60186c2f23e56a896fd2b Mon Sep 17 00:00:00 2001 From: Maksym Novik Date: Wed, 18 Nov 2020 17:29:20 +0200 Subject: [PATCH 24/26] IsProductSalable/AreProdustsSalable composite products support. #3140 Load product salability data on-demand #3201. Fixed IsProductSalable for products with calculated SKUs --- InventoryCatalog/Model/IsProductSalable.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InventoryCatalog/Model/IsProductSalable.php b/InventoryCatalog/Model/IsProductSalable.php index d13e483fe605..9baabba2fb29 100644 --- a/InventoryCatalog/Model/IsProductSalable.php +++ b/InventoryCatalog/Model/IsProductSalable.php @@ -54,7 +54,7 @@ public function execute(Product $product): bool return (bool)$product->getData('is_salable'); } $stockId = $this->getStockIdForCurrentWebsite->execute(); - $result = current($this->areProductsSalable->execute([$product->getSku()], $stockId)); + $result = current($this->areProductsSalable->execute([$product->getData(Product::SKU)], $stockId)); $isSalable = $result->isSalable(); $product->setData('is_salable', $isSalable); From a122e9bb5e4fc0090db8f0c54ca8b641590a1add Mon Sep 17 00:00:00 2001 From: Maksym Novik Date: Mon, 4 Jan 2021 12:47:38 +0200 Subject: [PATCH 25/26] IsProductSalable/AreProdustsSalable composite products support. #3140 Load product salability data on-demand #3201. Removed abandoned test after covered class removal --- .../AdaptAssignStatusToProductPluginTest.php | 54 ------------------- 1 file changed, 54 deletions(-) delete mode 100644 InventoryConfigurableProduct/Test/Integration/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPluginTest.php diff --git a/InventoryConfigurableProduct/Test/Integration/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPluginTest.php b/InventoryConfigurableProduct/Test/Integration/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPluginTest.php deleted file mode 100644 index f4d2d3743b4d..000000000000 --- a/InventoryConfigurableProduct/Test/Integration/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPluginTest.php +++ /dev/null @@ -1,54 +0,0 @@ -subject = Bootstrap::getObjectManager()->get(AdaptAssignStatusToProductPlugin::class); - } - - /** - * Test that out of stock Configurable product with options, one of which is out of stock, stays Out of stock - * - * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable_12345.php - * @return void - */ - public function testBeforeAssignStatusToProduct(): void - { - $stock = Bootstrap::getObjectManager()->get(\Magento\CatalogInventory\Helper\Stock::class); - /** @var ProductRepositoryInterface $productRepository */ - $productRepository = Bootstrap::getObjectManager()->get(ProductRepositoryInterface::class); - - $configurable = $productRepository->get('12345'); - $configurable->setQuantityAndStockStatus(['is_in_stock' => false]); - $configurable->save(); - $option = $productRepository->get('simple_30'); - $option->setQuantityAndStockStatus(['is_in_stock' => false]); - $option->save(); - $result = $this->subject->beforeAssignStatusToProduct($stock, $configurable, null); - $this->assertEquals(null, $result[1]); - } -} From c3f1b3d1bc5fb019b2d54a789df15ae1622a47c7 Mon Sep 17 00:00:00 2001 From: Maksym Novik Date: Tue, 19 Jan 2021 14:41:53 +0200 Subject: [PATCH 26/26] IsProductSalable/AreProdustsSalable composite products support. #3140 Load product salability data on-demand #3201. Verify product statuses during salability calculation for composite products using default functionality. --- .../IsBundleProductSalable.php | 48 ------------------- InventoryBundleProduct/etc/frontend/di.xml | 12 ----- InventoryBundleProduct/etc/graphql/di.xml | 12 ----- .../Model/Product/IsAvailablePlugin.php | 12 ++--- 4 files changed, 6 insertions(+), 78 deletions(-) delete mode 100644 InventoryBundleProduct/Plugin/InventoryCatalog/IsBundleProductSalable.php delete mode 100644 InventoryBundleProduct/etc/frontend/di.xml delete mode 100644 InventoryBundleProduct/etc/graphql/di.xml diff --git a/InventoryBundleProduct/Plugin/InventoryCatalog/IsBundleProductSalable.php b/InventoryBundleProduct/Plugin/InventoryCatalog/IsBundleProductSalable.php deleted file mode 100644 index 5dac2e049c00..000000000000 --- a/InventoryBundleProduct/Plugin/InventoryCatalog/IsBundleProductSalable.php +++ /dev/null @@ -1,48 +0,0 @@ -getTypeId() !== Type::TYPE_CODE) { - return $proceed($product); - } - - if ($product->hasData('all_items_salable')) { - return $product->getData('all_items_salable'); - } - - $isSalable = $proceed($product); - $product->setData('all_items_salable', $isSalable); - - return $isSalable; - } -} diff --git a/InventoryBundleProduct/etc/frontend/di.xml b/InventoryBundleProduct/etc/frontend/di.xml deleted file mode 100644 index 2717223aab13..000000000000 --- a/InventoryBundleProduct/etc/frontend/di.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - diff --git a/InventoryBundleProduct/etc/graphql/di.xml b/InventoryBundleProduct/etc/graphql/di.xml deleted file mode 100644 index 2717223aab13..000000000000 --- a/InventoryBundleProduct/etc/graphql/di.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - diff --git a/InventoryCatalog/Plugin/Catalog/Model/Product/IsAvailablePlugin.php b/InventoryCatalog/Plugin/Catalog/Model/Product/IsAvailablePlugin.php index e4dda555376b..07e9aa05ca3e 100644 --- a/InventoryCatalog/Plugin/Catalog/Model/Product/IsAvailablePlugin.php +++ b/InventoryCatalog/Plugin/Catalog/Model/Product/IsAvailablePlugin.php @@ -30,15 +30,15 @@ public function __construct( } /** - * Fetches is salable status from multi-stock. + * Fetches is salable status from multi-stock and sets it to product is_salable flag. * - * @param Product $subject - * @param \Closure $proceed - * @return bool + * @param Product $product + * + * @return void * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundIsAvailable(Product $subject, \Closure $proceed): bool + public function beforeIsAvailable(Product $product): void { - return $this->isProductSalable->execute($subject); + $product->setData('is_salable', $this->isProductSalable->execute($product)); } }