diff --git a/vendor/magento/module-inventory-import-export/Plugin/Import/SourceItemImporter.php b/vendor/magento/module-inventory-import-export/Plugin/Import/SourceItemImporter.php index d1c9a3e02c83..02bda87de4d1 100644 --- a/vendor/magento/module-inventory-import-export/Plugin/Import/SourceItemImporter.php +++ b/vendor/magento/module-inventory-import-export/Plugin/Import/SourceItemImporter.php @@ -7,12 +7,24 @@ namespace Magento\InventoryImportExport\Plugin\Import; -use Magento\CatalogImportExport\Model\StockItemImporterInterface; -use Magento\InventoryApi\Api\Data\SourceItemInterfaceFactory; +use Magento\CatalogImportExport\Model\Import\Product\SkuProcessor; +use Magento\CatalogImportExport\Model\StockItemProcessorInterface; +use Magento\Framework\App\ResourceConnection; +use Magento\Framework\Exception\CouldNotSaveException; +use Magento\Framework\Exception\InputException; +use Magento\Framework\Validation\ValidationException; +use Magento\Inventory\Model\ResourceModel\SourceItem; use Magento\InventoryApi\Api\Data\SourceItemInterface; +use Magento\InventoryApi\Api\Data\SourceItemInterfaceFactory; use Magento\InventoryApi\Api\SourceItemsSaveInterface; use Magento\InventoryCatalogApi\Api\DefaultSourceProviderInterface; +use Magento\InventoryCatalogApi\Model\IsSingleSourceModeInterface; +/** + * Assigning products to default source + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class SourceItemImporter { /** @@ -36,57 +48,116 @@ class SourceItemImporter */ private $defaultSource; + /** + * @var IsSingleSourceModeInterface + */ + private $isSingleSourceMode; + + /** + * @var ResourceConnection + */ + private $resourceConnection; + + /** + * @var SkuProcessor + */ + private $skuProcessor; + /** * StockItemImporter constructor * * @param SourceItemsSaveInterface $sourceItemsSave * @param SourceItemInterfaceFactory $sourceItemFactory * @param DefaultSourceProviderInterface $defaultSourceProvider + * @param IsSingleSourceModeInterface $isSingleSourceMode + * @param ResourceConnection $resourceConnection + * @param SkuProcessor $skuProcessor */ public function __construct( SourceItemsSaveInterface $sourceItemsSave, SourceItemInterfaceFactory $sourceItemFactory, - DefaultSourceProviderInterface $defaultSourceProvider + DefaultSourceProviderInterface $defaultSourceProvider, + IsSingleSourceModeInterface $isSingleSourceMode, + ResourceConnection $resourceConnection, + SkuProcessor $skuProcessor ) { $this->sourceItemsSave = $sourceItemsSave; $this->sourceItemFactory = $sourceItemFactory; $this->defaultSource = $defaultSourceProvider; + $this->isSingleSourceMode = $isSingleSourceMode; + $this->resourceConnection = $resourceConnection; + $this->skuProcessor = $skuProcessor; } /** * After plugin Import to import Stock Data to Source Items * - * @param StockItemImporterInterface $subject - * @param null $result + * @param StockItemProcessorInterface $subject + * @param mixed $result * @param array $stockData - * @throws \Magento\Framework\Exception\CouldNotSaveException - * @throws \Magento\Framework\Exception\InputException - * @throws \Magento\Framework\Validation\ValidationException + * @param array $importedData * @return void - * @see StockItemImporterInterface::import() + * @throws CouldNotSaveException + * @throws InputException + * @throws ValidationException * * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function afterImport( - StockItemImporterInterface $subject, + public function afterProcess( + StockItemProcessorInterface $subject, $result, - array $stockData - ) { + array $stockData, + array $importedData + ): void { $sourceItems = []; + $skusHavingDefaultSource = $this->getSkusHavingDefaultSource(array_keys($stockData)); + foreach ($stockData as $sku => $stockDatum) { - $inStock = (isset($stockDatum['is_in_stock'])) ? intval($stockDatum['is_in_stock']) : 0; - $qty = (isset($stockDatum['qty'])) ? $stockDatum['qty'] : 0; - /** @var SourceItemInterface $sourceItem */ + $isNewSku = !array_key_exists(strtolower((string)$sku), $this->skuProcessor->getOldSkus()); + $isQtyExplicitlySet = $importedData[$sku]['qty'] ?? false; + + $inStock = $stockDatum['is_in_stock'] ?? 0; + $qty = $stockDatum['qty'] ?? 0; $sourceItem = $this->sourceItemFactory->create(); $sourceItem->setSku((string)$sku); $sourceItem->setSourceCode($this->defaultSource->getCode()); $sourceItem->setQuantity((float)$qty); - $sourceItem->setStatus($inStock); - $sourceItems[] = $sourceItem; + $sourceItem->setStatus((int)$inStock); + + //Prevent existing products to be assigned to `default` source, when `qty` is not explicitly set. + if ($isNewSku + || $isQtyExplicitlySet + || $this->isSingleSourceMode->execute() + || in_array($sourceItem->getSku(), $skusHavingDefaultSource, true)) { + $sourceItems[] = $sourceItem; + } } if (count($sourceItems) > 0) { /** SourceItemInterface[] $sourceItems */ $this->sourceItemsSave->execute($sourceItems); } } + + /** + * Fetch product's skus having assigned to `default` source. + * + * @param array $listSku + * @return array + */ + private function getSkusHavingDefaultSource(array $listSku): array + { + $connection = $this->resourceConnection->getConnection(); + $select = $connection->select()->from( + $this->resourceConnection->getTableName(SourceItem::TABLE_NAME_SOURCE_ITEM), + [SourceItemInterface::SKU] + )->where( + SourceItemInterface::SKU . ' IN (?)', + $listSku + )->where( + SourceItemInterface::SOURCE_CODE . ' = ?', + $this->defaultSource->getCode() + ); + + return $connection->fetchCol($select); + } } diff --git a/vendor/magento/module-inventory-import-export/etc/di.xml b/vendor/magento/module-inventory-import-export/etc/di.xml index 6f0657decfd3..7d031a68149f 100644 --- a/vendor/magento/module-inventory-import-export/etc/di.xml +++ b/vendor/magento/module-inventory-import-export/etc/di.xml @@ -27,9 +27,8 @@ - - - + +