diff --git a/app/code/Magento/InventoryCatalog/Model/ResourceModel/SetDataToLegacyStockStatus.php b/app/code/Magento/InventoryCatalog/Model/ResourceModel/SetDataToLegacyStockStatus.php
deleted file mode 100644
index c0a5cd110284..000000000000
--- a/app/code/Magento/InventoryCatalog/Model/ResourceModel/SetDataToLegacyStockStatus.php
+++ /dev/null
@@ -1,68 +0,0 @@
-resourceConnection = $resourceConnection;
- $this->getProductIdsBySkus = $getProductIdsBySkus;
- }
-
- /**
- * @param string $sku
- * @param float $quantity
- * @param int $status
- * @return void
- */
- public function execute(string $sku, float $quantity, int $status)
- {
- $productIds = $this->getProductIdsBySkus->execute([$sku]);
-
- if (isset($productIds[$sku])) {
- $productId = $productIds[$sku];
-
- $connection = $this->resourceConnection->getConnection();
- $connection->update(
- $this->resourceConnection->getTableName('cataloginventory_stock_status'),
- [
- StockStatusInterface::QTY => $quantity,
- StockStatusInterface::STOCK_STATUS => $status,
- ],
- [
- StockStatusInterface::PRODUCT_ID . ' = ?' => $productId,
- 'website_id = ?' => 0,
- ]
- );
- }
- }
-}
diff --git a/app/code/Magento/InventoryCatalog/Model/SourceItem/SourceItemsSave.php b/app/code/Magento/InventoryCatalog/Model/SourceItem/SourceItemsSave.php
new file mode 100644
index 000000000000..6918445ce1e1
--- /dev/null
+++ b/app/code/Magento/InventoryCatalog/Model/SourceItem/SourceItemsSave.php
@@ -0,0 +1,74 @@
+sourceItemsValidator = $sourceItemsValidator;
+ $this->saveMultiple = $saveMultiple;
+ $this->logger = $logger;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function execute(array $sourceItems)
+ {
+ if (empty($sourceItems)) {
+ throw new InputException(__('Input data is empty'));
+ }
+
+ $validationResult = $this->sourceItemsValidator->validate($sourceItems);
+ if (!$validationResult->isValid()) {
+ throw new ValidationException(__('Validation Failed'), null, 0, $validationResult);
+ }
+
+ try {
+ $this->saveMultiple->execute($sourceItems);
+ } catch (\Exception $e) {
+ $this->logger->error($e->getMessage());
+ throw new CouldNotSaveException(__('Could not save Source Item'), $e);
+ }
+ }
+}
diff --git a/app/code/Magento/InventoryCatalog/Plugin/InventoryApi/SetDataToLegacyCatalogInventoryAtSourceItemsSavePlugin.php b/app/code/Magento/InventoryCatalog/Plugin/InventoryApi/SetDataToLegacyCatalogInventoryAtSourceItemsSavePlugin.php
index d18e6a14deca..e7eca12d4fe1 100644
--- a/app/code/Magento/InventoryCatalog/Plugin/InventoryApi/SetDataToLegacyCatalogInventoryAtSourceItemsSavePlugin.php
+++ b/app/code/Magento/InventoryCatalog/Plugin/InventoryApi/SetDataToLegacyCatalogInventoryAtSourceItemsSavePlugin.php
@@ -7,17 +7,27 @@
namespace Magento\InventoryCatalog\Plugin\InventoryApi;
+use Magento\CatalogInventory\Api\Data\StockItemInterface;
+use Magento\CatalogInventory\Api\StockItemRepositoryInterface;
+use Magento\CatalogInventory\Api\StockItemCriteriaInterfaceFactory;
+use Magento\CatalogInventory\Model\Indexer\Stock\Processor;
+use Magento\CatalogInventory\Model\Spi\StockStateProviderInterface;
+use Magento\CatalogInventory\Model\Stock;
+use Magento\Framework\Exception\InputException;
use Magento\InventoryApi\Api\Data\SourceItemInterface;
use Magento\InventoryApi\Api\SourceItemsSaveInterface;
use Magento\InventoryCatalogApi\Api\DefaultSourceProviderInterface;
+use Magento\InventoryCatalogApi\Model\GetProductIdsBySkusInterface;
+use Magento\InventoryCatalogApi\Model\GetProductTypesBySkusInterface;
use Magento\InventoryCatalog\Model\ResourceModel\SetDataToLegacyStockItem;
-use Magento\InventoryCatalog\Model\ResourceModel\SetDataToLegacyStockStatus;
-use Magento\InventorySalesApi\Api\IsProductSalableInterface;
-use Magento\InventoryCatalogApi\Api\DefaultStockProviderInterface;
+use Magento\InventoryConfigurationApi\Model\IsSourceItemManagementAllowedForProductTypeInterface;
/**
* Set Qty and status for legacy CatalogInventory Stock Status and Stock Item DB tables,
* if corresponding MSI SourceItem assigned to Default Source has been saved
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ * TODO: https://github.com/magento-engcom/msi/pull/1082/
*/
class SetDataToLegacyCatalogInventoryAtSourceItemsSavePlugin
{
@@ -32,39 +42,71 @@ class SetDataToLegacyCatalogInventoryAtSourceItemsSavePlugin
private $setDataToLegacyStockItem;
/**
- * @var SetDataToLegacyStockStatus
+ * @var StockItemCriteriaInterfaceFactory
*/
- private $setDataToLegacyStockStatus;
+ private $legacyStockItemCriteriaFactory;
/**
- * @var IsProductSalableInterface
+ * @var StockItemRepositoryInterface
*/
- private $isProductSalable;
+ private $legacyStockItemRepository;
/**
- * @var DefaultStockProviderInterface
+ * @var GetProductIdsBySkusInterface
*/
- private $defaultStockProvider;
+ private $getProductIdsBySkus;
+
+ /**
+ * @var StockStateProviderInterface
+ */
+ private $stockStateProvider;
+
+ /**
+ * @var Processor
+ */
+ private $indexerProcessor;
+
+ /**
+ * @var IsSourceItemManagementAllowedForProductTypeInterface
+ */
+ private $isSourceItemsAllowedForProductType;
+
+ /**
+ * @var GetProductTypesBySkusInterface
+ */
+ private $getProductTypeBySku;
/**
* @param DefaultSourceProviderInterface $defaultSourceProvider
* @param SetDataToLegacyStockItem $setDataToLegacyStockItem
- * @param SetDataToLegacyStockStatus $setDataToLegacyStockStatus
- * @param IsProductSalableInterface $isProductSalable
- * @param DefaultStockProviderInterface $defaultStockProvider
+ * @param StockItemCriteriaInterfaceFactory $legacyStockItemCriteriaFactory
+ * @param StockItemRepositoryInterface $legacyStockItemRepository
+ * @param GetProductIdsBySkusInterface $getProductIdsBySkus
+ * @param StockStateProviderInterface $stockStateProvider
+ * @param Processor $indexerProcessor
+ * @param IsSourceItemManagementAllowedForProductTypeInterface $isSourceItemsAllowedForProductType
+ * @param GetProductTypesBySkusInterface $getProductTypeBySku
*/
public function __construct(
DefaultSourceProviderInterface $defaultSourceProvider,
SetDataToLegacyStockItem $setDataToLegacyStockItem,
- SetDataToLegacyStockStatus $setDataToLegacyStockStatus,
- IsProductSalableInterface $isProductSalable,
- DefaultStockProviderInterface $defaultStockProvider
+ StockItemCriteriaInterfaceFactory $legacyStockItemCriteriaFactory,
+ StockItemRepositoryInterface $legacyStockItemRepository,
+ GetProductIdsBySkusInterface $getProductIdsBySkus,
+ StockStateProviderInterface $stockStateProvider,
+ Processor $indexerProcessor,
+ IsSourceItemManagementAllowedForProductTypeInterface $isSourceItemsAllowedForProductType,
+ GetProductTypesBySkusInterface $getProductTypeBySku
) {
$this->defaultSourceProvider = $defaultSourceProvider;
$this->setDataToLegacyStockItem = $setDataToLegacyStockItem;
- $this->setDataToLegacyStockStatus = $setDataToLegacyStockStatus;
- $this->isProductSalable = $isProductSalable;
- $this->defaultStockProvider = $defaultStockProvider;
+ $this->legacyStockItemCriteriaFactory = $legacyStockItemCriteriaFactory;
+ $this->legacyStockItemRepository = $legacyStockItemRepository;
+ $this->getProductIdsBySkus = $getProductIdsBySkus;
+ $this->stockStateProvider = $stockStateProvider;
+ $this->indexerProcessor = $indexerProcessor;
+ $this->isSourceItemsAllowedForProductType = $isSourceItemsAllowedForProductType;
+ $this->getProductTypeBySku = $getProductTypeBySku;
}
/**
@@ -72,35 +114,77 @@ public function __construct(
* @param void $result
* @param SourceItemInterface[] $sourceItems
* @return void
- * @see SourceItemsSaveInterface::execute
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
- public function afterExecute(SourceItemsSaveInterface $subject, $result, array $sourceItems)
+ public function afterExecute(SourceItemsSaveInterface $subject, $result, array $sourceItems): void
{
+ $productIds = [];
foreach ($sourceItems as $sourceItem) {
if ($sourceItem->getSourceCode() !== $this->defaultSourceProvider->getCode()) {
continue;
}
+
+ $sku = $sourceItem->getSku();
+
+ try {
+ $productId = (int)$this->getProductIdsBySkus->execute([$sku])[$sku];
+ } catch (InputException $e) {
+ // Saving source item data for not existed product
+ continue;
+ }
+
+ $typeId = $this->getProductTypeBySku->execute([$sku])[$sku];
+ if (false === $this->isSourceItemsAllowedForProductType->execute($typeId)) {
+ continue;
+ }
+
+ $legacyStockItem = $this->getLegacyStockItem($productId);
+ if (null === $legacyStockItem) {
+ continue;
+ }
+
+ $isInStock = (int)$sourceItem->getStatus();
+
+ if ($legacyStockItem->getManageStock()) {
+ $legacyStockItem->setIsInStock($isInStock);
+ $legacyStockItem->setQty((float)$sourceItem->getQuantity());
+
+ if (false === $this->stockStateProvider->verifyStock($legacyStockItem)) {
+ $isInStock = 0;
+ }
+ }
+
$this->setDataToLegacyStockItem->execute(
$sourceItem->getSku(),
(float)$sourceItem->getQuantity(),
- (int)$sourceItem->getStatus()
- );
- $this->setDataToLegacyStockStatus->execute(
- $sourceItem->getSku(),
- (float)$sourceItem->getQuantity(),
- (int)$sourceItem->getStatus()
- );
- /**
- * We need to call setDataToLegacyStockStatus second time because we don't have On Save re-indexation
- * as cataloginventory_stock_item table updated with plane SQL queries
- * Thus, initially we put the raw data there, and after that persist the calculated value
- */
- $this->setDataToLegacyStockStatus->execute(
- $sourceItem->getSku(),
- (float)$sourceItem->getQuantity(),
- (int)$this->isProductSalable->execute($sourceItem->getSku(), $this->defaultStockProvider->getId())
+ $isInStock
);
+ $productIds[] = $productId;
}
+
+ if ($productIds) {
+ $this->indexerProcessor->reindexList($productIds);
+ }
+ }
+
+ /**
+ * @param int $productId
+ * @return null|StockItemInterface
+ */
+ private function getLegacyStockItem(int $productId): ?StockItemInterface
+ {
+ $searchCriteria = $this->legacyStockItemCriteriaFactory->create();
+
+ $searchCriteria->addFilter(StockItemInterface::PRODUCT_ID, StockItemInterface::PRODUCT_ID, $productId);
+ $searchCriteria->addFilter(StockItemInterface::STOCK_ID, StockItemInterface::STOCK_ID, Stock::DEFAULT_STOCK_ID);
+
+ $stockItemCollection = $this->legacyStockItemRepository->getList($searchCriteria);
+ if ($stockItemCollection->getTotalCount() === 0) {
+ return null;
+ }
+
+ $stockItems = $stockItemCollection->getItems();
+ $stockItem = reset($stockItems);
+ return $stockItem;
}
}
diff --git a/app/code/Magento/InventoryCatalog/Plugin/InventoryApi/SetToZeroLegacyCatalogInventoryAtSourceItemsDeletePlugin.php b/app/code/Magento/InventoryCatalog/Plugin/InventoryApi/SetToZeroLegacyCatalogInventoryAtSourceItemsDeletePlugin.php
index 7e51af2e6474..79812e026052 100644
--- a/app/code/Magento/InventoryCatalog/Plugin/InventoryApi/SetToZeroLegacyCatalogInventoryAtSourceItemsDeletePlugin.php
+++ b/app/code/Magento/InventoryCatalog/Plugin/InventoryApi/SetToZeroLegacyCatalogInventoryAtSourceItemsDeletePlugin.php
@@ -7,13 +7,15 @@
namespace Magento\InventoryCatalog\Plugin\InventoryApi;
-use Magento\CatalogInventory\Model\Stock\Status;
+use Magento\CatalogInventory\Model\Indexer\Stock\Processor;
+use Magento\Framework\Exception\InputException;
use Magento\InventoryApi\Api\Data\SourceItemInterface;
use Magento\InventoryApi\Api\SourceItemsDeleteInterface;
use Magento\InventoryCatalogApi\Api\DefaultSourceProviderInterface;
+use Magento\InventoryCatalogApi\Model\GetProductIdsBySkusInterface;
+use Magento\InventoryCatalogApi\Model\GetProductTypesBySkusInterface;
use Magento\InventoryCatalog\Model\ResourceModel\SetDataToLegacyStockItem;
-use Magento\InventoryCatalog\Model\ResourceModel\SetDataToLegacyStockStatus;
-use Psr\Log\LoggerInterface;
+use Magento\InventoryConfigurationApi\Model\IsSourceItemManagementAllowedForProductTypeInterface;
/**
* Set to zero Qty and status to ‘Out of Stock’ for legacy CatalogInventory Stock Status and Stock Item DB tables,
@@ -32,23 +34,47 @@ class SetToZeroLegacyCatalogInventoryAtSourceItemsDeletePlugin
private $setDataToLegacyStockItem;
/**
- * @var SetDataToLegacyStockStatus
+ * @var GetProductIdsBySkusInterface
*/
- private $setDataToLegacyStockStatus;
+ private $getProductIdsBySkus;
+
+ /**
+ * @var Processor
+ */
+ private $indexerProcessor;
+
+ /**
+ * @var IsSourceItemManagementAllowedForProductTypeInterface
+ */
+ private $isSourceItemsAllowedForProductType;
+
+ /**
+ * @var GetProductTypesBySkusInterface
+ */
+ private $getProductTypeBySku;
/**
* @param DefaultSourceProviderInterface $defaultSourceProvider
* @param SetDataToLegacyStockItem $setDataToLegacyStockItem
- * @param SetDataToLegacyStockStatus $setDataToLegacyStockStatus
+ * @param GetProductIdsBySkusInterface $getProductIdsBySkus
+ * @param Processor $indexerProcessor
+ * @param IsSourceItemManagementAllowedForProductTypeInterface $isSourceItemsAllowedForProductType
+ * @param GetProductTypesBySkusInterface $getProductTypeBySku
*/
public function __construct(
DefaultSourceProviderInterface $defaultSourceProvider,
SetDataToLegacyStockItem $setDataToLegacyStockItem,
- SetDataToLegacyStockStatus $setDataToLegacyStockStatus
+ GetProductIdsBySkusInterface $getProductIdsBySkus,
+ Processor $indexerProcessor,
+ IsSourceItemManagementAllowedForProductTypeInterface $isSourceItemsAllowedForProductType,
+ GetProductTypesBySkusInterface $getProductTypeBySku
) {
$this->defaultSourceProvider = $defaultSourceProvider;
$this->setDataToLegacyStockItem = $setDataToLegacyStockItem;
- $this->setDataToLegacyStockStatus = $setDataToLegacyStockStatus;
+ $this->getProductIdsBySkus = $getProductIdsBySkus;
+ $this->indexerProcessor = $indexerProcessor;
+ $this->isSourceItemsAllowedForProductType = $isSourceItemsAllowedForProductType;
+ $this->getProductTypeBySku = $getProductTypeBySku;
}
/**
@@ -56,17 +82,36 @@ public function __construct(
* @param void $result
* @param SourceItemInterface[] $sourceItems
* @return void
- * @see SourceItemsDeleteInterface::execute
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function afterExecute(SourceItemsDeleteInterface $subject, $result, array $sourceItems)
{
+ $productIds = [];
foreach ($sourceItems as $sourceItem) {
if ($sourceItem->getSourceCode() !== $this->defaultSourceProvider->getCode()) {
continue;
}
+
+ $sku = $sourceItem->getSku();
+
+ try {
+ $productId = (int)$this->getProductIdsBySkus->execute([$sku])[$sku];
+ } catch (InputException $e) {
+ // Delete source item data for not existed product
+ continue;
+ }
+
+ $typeId = $this->getProductTypeBySku->execute([$sku])[$sku];
+ if (false === $this->isSourceItemsAllowedForProductType->execute($typeId)) {
+ continue;
+ }
+
$this->setDataToLegacyStockItem->execute($sourceItem->getSku(), 0, 0);
- $this->setDataToLegacyStockStatus->execute($sourceItem->getSku(), 0, Status::STATUS_OUT_OF_STOCK);
+ $productIds[] = $productId;
+ }
+
+ if ($productIds) {
+ $this->indexerProcessor->reindexList($productIds);
}
}
}
diff --git a/app/code/Magento/InventoryCatalog/composer.json b/app/code/Magento/InventoryCatalog/composer.json
index 5ce3ebe14067..f18c5ab0e3b4 100644
--- a/app/code/Magento/InventoryCatalog/composer.json
+++ b/app/code/Magento/InventoryCatalog/composer.json
@@ -6,6 +6,7 @@
"magento/framework": "*",
"magento/module-catalog": "*",
"magento/module-catalog-inventory": "*",
+ "magento/module-inventory": "*",
"magento/module-inventory-api": "*",
"magento/module-inventory-catalog-api": "*",
"magento/module-store": "*",
diff --git a/app/code/Magento/InventoryCatalog/etc/di.xml b/app/code/Magento/InventoryCatalog/etc/di.xml
index 7eb0d9dc511a..2c1e3b77ac2e 100644
--- a/app/code/Magento/InventoryCatalog/etc/di.xml
+++ b/app/code/Magento/InventoryCatalog/etc/di.xml
@@ -65,4 +65,12 @@
Magento\Inventory\Model\ResourceModel\SourceItem::TABLE_NAME_SOURCE_ITEM
+
+
+ Magento\InventoryCatalog\Model\SourceItem\SourceItemsSave
+
+
+
+
+
diff --git a/app/code/Magento/InventoryConfiguration/Model/GetStockItemConfiguration.php b/app/code/Magento/InventoryConfiguration/Model/GetStockItemConfiguration.php
index f71fb11619a1..daa1bf94e169 100644
--- a/app/code/Magento/InventoryConfiguration/Model/GetStockItemConfiguration.php
+++ b/app/code/Magento/InventoryConfiguration/Model/GetStockItemConfiguration.php
@@ -10,7 +10,7 @@
use Magento\CatalogInventory\Api\StockItemRepositoryInterface;
use Magento\CatalogInventory\Api\Data\StockItemInterface;
use Magento\CatalogInventory\Api\StockItemCriteriaInterfaceFactory;
-use Magento\InventoryCatalogApi\Api\DefaultStockProviderInterface;
+use Magento\CatalogInventory\Model\Stock;
use Magento\InventoryCatalogApi\Model\GetProductIdsBySkusInterface;
use Magento\InventoryConfigurationApi\Api\GetStockItemConfigurationInterface;
use Magento\InventorySales\Model\GetStockItemDataInterface;
@@ -46,33 +46,25 @@ class GetStockItemConfiguration implements GetStockItemConfigurationInterface
*/
private $stockItemConfigurationFactory;
- /**
- * @var DefaultStockProviderInterface
- */
- private $defaultStockProvider;
-
/**
* @param GetStockItemDataInterface $getStockItemData
* @param StockItemCriteriaInterfaceFactory $legacyStockItemCriteriaFactory
* @param StockItemRepositoryInterface $legacyStockItemRepository
* @param GetProductIdsBySkusInterface $getProductIdsBySkus
* @param StockItemConfigurationFactory $stockItemConfigurationFactory
- * @param DefaultStockProviderInterface $defaultStockProvider
*/
public function __construct(
GetStockItemDataInterface $getStockItemData,
StockItemCriteriaInterfaceFactory $legacyStockItemCriteriaFactory,
StockItemRepositoryInterface $legacyStockItemRepository,
GetProductIdsBySkusInterface $getProductIdsBySkus,
- StockItemConfigurationFactory $stockItemConfigurationFactory,
- DefaultStockProviderInterface $defaultStockProvider
+ StockItemConfigurationFactory $stockItemConfigurationFactory
) {
$this->getStockItemData = $getStockItemData;
$this->legacyStockItemCriteriaFactory = $legacyStockItemCriteriaFactory;
$this->legacyStockItemRepository = $legacyStockItemRepository;
$this->getProductIdsBySkus = $getProductIdsBySkus;
$this->stockItemConfigurationFactory = $stockItemConfigurationFactory;
- $this->defaultStockProvider = $defaultStockProvider;
}
/**
@@ -105,10 +97,8 @@ private function getLegacyStockItem(string $sku): StockItemInterface
$productId = $this->getProductIdsBySkus->execute([$sku])[$sku];
$searchCriteria->addFilter(StockItemInterface::PRODUCT_ID, StockItemInterface::PRODUCT_ID, $productId);
- // TODO We use $legacyStockId until we have proper multi-stock item configuration
- $legacyStockId = $this->defaultStockProvider->getId();
-
- $searchCriteria->addFilter(StockItemInterface::STOCK_ID, StockItemInterface::STOCK_ID, $legacyStockId);
+ // TODO We use Stock::DEFAULT_STOCK_ID until we have proper multi-stock item configuration
+ $searchCriteria->addFilter(StockItemInterface::STOCK_ID, StockItemInterface::STOCK_ID, Stock::DEFAULT_STOCK_ID);
$stockItemCollection = $this->legacyStockItemRepository->getList($searchCriteria);
if ($stockItemCollection->getTotalCount() === 0) {