diff --git a/vendor/magento/module-inventory-catalog/Model/IsSingleSourceModeCache.php b/vendor/magento/module-inventory-catalog/Model/IsSingleSourceModeCache.php new file mode 100644 index 00000000000..f37456045e0 --- /dev/null +++ b/vendor/magento/module-inventory-catalog/Model/IsSingleSourceModeCache.php @@ -0,0 +1,46 @@ +isSingleSourceMode = $isSingleSourceMode; + } + + /** + * @inheritdoc + */ + public function execute(): bool + { + if ($this->cacheValue === null) { + $this->cacheValue = $this->isSingleSourceMode->execute(); + } + + return $this->cacheValue; + } +} diff --git a/vendor/magento/module-inventory-catalog/etc/di.xml b/vendor/magento/module-inventory-catalog/etc/di.xml index 7a598862cb6..dd5a114eb5f 100644 --- a/vendor/magento/module-inventory-catalog/etc/di.xml +++ b/vendor/magento/module-inventory-catalog/etc/di.xml @@ -12,7 +12,7 @@ - + resource = $resource; $this->stockIndexTableNameResolver = $stockIndexTableNameResolver; $this->defaultStockProvider = $defaultStockProvider; $this->getProductIdsBySkus = $getProductIdsBySkus; + $this->isSingleSourceMode = $isSingleSourceMode + ?: ObjectManager::getInstance()->get(IsSingleSourceModeInterface::class); + $this->isSourceItemManagementAllowedForSku = $isSourceItemManagementAllowedForSku + ?: ObjectManager::getInstance()->get(IsSourceItemManagementAllowedForSkuInterface::class); + } /** @@ -68,31 +91,77 @@ class GetStockItemData implements GetStockItemDataInterface if ($this->defaultStockProvider->getId() === $stockId) { $productId = current($this->getProductIdsBySkus->execute([$sku])); - $stockItemTableName = $this->resource->getTableName('cataloginventory_stock_status'); $select->from( - $stockItemTableName, + $this->resource->getTableName('cataloginventory_stock_status'), [ GetStockItemDataInterface::QUANTITY => 'qty', GetStockItemDataInterface::IS_SALABLE => 'stock_status', ] - )->where('product_id = ?', $productId); - - return $connection->fetchRow($select) ?: null; + )->where( + 'product_id = ?', + $productId + ); } else { - $stockItemTableName = $this->stockIndexTableNameResolver->execute($stockId); $select->from( - $stockItemTableName, + $this->stockIndexTableNameResolver->execute($stockId), [ GetStockItemDataInterface::QUANTITY => IndexStructure::QUANTITY, GetStockItemDataInterface::IS_SALABLE => IndexStructure::IS_SALABLE, ] - )->where(IndexStructure::SKU . ' = ?', $sku); + )->where( + IndexStructure::SKU . ' = ?', + $sku + ); + } - try { - return $connection->fetchRow($select) ?: null; - } catch (\Exception $e) { - throw new LocalizedException(__('Could not receive Stock Item data'), $e); + try { + $stockItemRow = $connection->fetchRow($select) ?: null; + /** + * Fallback to the legacy cataloginventory_stock_item table. + * Caused by data absence in legacy cataloginventory_stock_status table + * for disabled products assigned to the default stock. + */ + if ($stockItemRow === null) { + $stockItemRow = $this->getStockItemDataFromStockItemTable($sku, $stockId); } + } catch (\Exception $e) { + throw new LocalizedException(__('Could not receive Stock Item data'), $e); + } + + return $stockItemRow; + } + + /** + * Retrieve stock item data for product assigned to the default stock. + * + * @param string $sku + * @param int $stockId + * @return array|null + */ + private function getStockItemDataFromStockItemTable(string $sku, int $stockId): ?array + { + if ($this->defaultStockProvider->getId() !== $stockId + || $this->isSingleSourceMode->execute() + || !$this->isSourceItemManagementAllowedForSku->execute($sku) + ) { + return null; } + + $productId = current($this->getProductIdsBySkus->execute([$sku])); + $connection = $this->resource->getConnection(); + $select = $connection->select(); + + $select->from( + $this->resource->getTableName('cataloginventory_stock_item'), + [ + GetStockItemDataInterface::QUANTITY => 'qty', + GetStockItemDataInterface::IS_SALABLE => 'is_in_stock', + ] + )->where( + 'product_id = ?', + $productId + ); + + return $connection->fetchRow($select) ?: null; } }