diff --git a/vendor/magento/module-inventory-configurable-product/Plugin/CatalogInventory/UpdateLegacyStockItemForNewConfigurableProduct.php b/vendor/magento/module-inventory-configurable-product/Plugin/CatalogInventory/UpdateLegacyStockItemForNewConfigurableProduct.php new file mode 100644 index 00000000000..0069c8e5de8 --- /dev/null +++ b/vendor/magento/module-inventory-configurable-product/Plugin/CatalogInventory/UpdateLegacyStockItemForNewConfigurableProduct.php @@ -0,0 +1,178 @@ +request = $request; + $this->serializer = $serializer; + $this->getProductTypeById = $getProductTypeById; + $this->configurableType = $configurableType; + $this->getSkusByProductIds = $getSkusByProductIds; + $this->areProductsSalable = $areProductsSalable; + $this->updateLegacyStockItems = $updateLegacyStockItems; + } + + /** + * Updates stock item for new configurable product based on variation's qty + * + * @param ItemResourceModel $subject + * @param ItemResourceModel $result + * @param StockItem $stockItem + * @return ItemResourceModel + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterSave(ItemResourceModel $subject, ItemResourceModel $result, StockItem $stockItem) + { + if ($stockItem->isObjectNew() && + $stockItem->getIsInStock() && + $this->getProductTypeById->execute($stockItem->getProductId()) === Configurable::TYPE_CODE + ) { + $configurableMatrix = $this->request->getParam('configurable-matrix-serialized'); + if (!empty($configurableMatrix) && $configurableMatrix !== '[]') { + $this->updateStatus($stockItem, $this->hasStockStatusFromVariationMatrix($configurableMatrix)); + } else { + $childrenIds = $this->configurableType->getChildrenIds($stockItem->getProductId()); + $childrenIds = array_shift($childrenIds); + if (!empty($childrenIds)) { + $this->updateStatus($stockItem, $this->hasStockStatusFromChildren($childrenIds)); + } + } + } + + return $result; + } + + /** + * Updates Configurable stock status based on the variations + * + * @param StockItem $stockItem + * @param bool $isInStock + * @return void + */ + private function updateStatus(StockItem $stockItem, bool $isInStock): void + { + if ($stockItem->getIsInStock() == $isInStock) { + return; + } + $stockItemData = [ + StockItemModel::IS_IN_STOCK => $isInStock, + StockItemModel::STOCK_STATUS_CHANGED_AUTO => 1 + ]; + $this->updateLegacyStockItems->execute([$stockItem->getProductId()], $stockItemData); + } + + /** + * Get stock status based on qty of the variation-matrix from request + * + * @param string $configurableMatrix + * @return bool + */ + private function hasStockStatusFromVariationMatrix(string $configurableMatrix): bool + { + $configurableMatrix = $this->serializer->unserialize($configurableMatrix); + foreach ($configurableMatrix as $item) { + if (!empty($item['qty'])) { + return true; + } elseif (!empty($item['quantity_per_source'])) { + foreach ($item['quantity_per_source'] as $source) { + if (!empty($source['quantity_per_source'])) { + return true; + } + } + } + } + + return false; + } + + /** + * Checks if configurable has salable options + * + * @param array $childrenIds + * @return bool + */ + private function hasStockStatusFromChildren(array $childrenIds): bool + { + $skus = $this->getSkusByProductIds->execute($childrenIds); + $areSalableResults = $this->areProductsSalable->execute($skus, Stock::DEFAULT_STOCK_ID); + foreach ($areSalableResults as $productSalable) { + if ($productSalable->isSalable() === true) { + return true; + } + } + + return false; + } +} diff --git a/vendor/magento/module-inventory-configurable-product/Plugin/CatalogInventory/UpdateLegacyStockStatusForConfigurableProduct.php b/vendor/magento/module-inventory-configurable-product/Plugin/CatalogInventory/UpdateLegacyStockStatusForConfigurableProduct.php new file mode 100644 index 00000000000..4bfd3fb71cb --- /dev/null +++ b/vendor/magento/module-inventory-configurable-product/Plugin/CatalogInventory/UpdateLegacyStockStatusForConfigurableProduct.php @@ -0,0 +1,146 @@ +getProductTypeById = $getProductTypeById; + $this->setDataToLegacyStockStatus = $setDataToLegacyStockStatus; + $this->getSkusByProductIds = $getSkusByProductIds; + $this->configurableType = $configurableType; + $this->areProductsSalable = $areProductsSalable; + $this->getLegacyStockItem = $getLegacyStockItem; + } + + /** + * Update source item for legacy stock of a configurable product + * + * @param ItemResourceModel $subject + * @param ItemResourceModel $result + * @param StockItem $stockItem + * @return ItemResourceModel + * @throws Exception + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterSave(ItemResourceModel $subject, ItemResourceModel $result, StockItem $stockItem) + { + if ($stockItem->getIsInStock() && + $this->getProductTypeById->execute($stockItem->getProductId()) === Configurable::TYPE_CODE + ) { + $productSku = $this->getSkusByProductIds + ->execute([$stockItem->getProductId()])[$stockItem->getProductId()]; + + if ($stockItem->getStockStatusChangedAuto() || + ($this->stockStatusChange($productSku) && $this->hasChildrenInStock($stockItem->getProductId())) + ) { + $this->setDataToLegacyStockStatus->execute( + $productSku, + (float) $stockItem->getQty(), + Stock::STOCK_IN_STOCK + ); + } + } + + return $result; + } + + /** + * Checks if configurable product stock item status was changed + * + * @param string $sku + * @return bool + */ + private function stockStatusChange(string $sku): bool + { + return $this->getLegacyStockItem->execute($sku)->getIsInStock() == Stock::STOCK_OUT_OF_STOCK; + } + + /** + * Checks if configurable has salable options + * + * @param int $productId + * @return bool + */ + private function hasChildrenInStock(int $productId): bool + { + $childrenIds = $this->configurableType->getChildrenIds($productId); + if (empty($childrenIds)) { + return false; + } + $skus = $this->getSkusByProductIds->execute(array_shift($childrenIds)); + $areSalableResults = $this->areProductsSalable->execute($skus, Stock::DEFAULT_STOCK_ID); + foreach ($areSalableResults as $productSalable) { + if ($productSalable->isSalable() === true) { + return true; + } + } + + return false; + } +} \ No newline at end of file diff --git a/vendor/magento/module-inventory-configurable-product/etc/di.xml b/vendor/magento/module-inventory-configurable-product/etc/di.xml index 7b32be4f885..cfe1b00afbc 100644 --- a/vendor/magento/module-inventory-configurable-product/etc/di.xml +++ b/vendor/magento/module-inventory-configurable-product/etc/di.xml @@ -40,4 +40,13 @@ + + + + +