![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/old/app/code/Cnc/Catalog/Console/ |
<?php /** * Copyright (c) 2020 Kaliop Digital Commerce (https://digitalcommerce.kaliop.com) All Rights Reserved. * https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) * Cnc * Arkadiusz Tokarczyk <[email protected]> <[email protected]> */ namespace Cnc\Catalog\Console; use Cnc\Catalog\Model\ResourceModel\DataFactory as SourceDataFactory; use Cnc\SerialNumber\Api\Data\SerialNumberInterface; use Cnc\SerialNumber\Api\IsSerialNumberEnabledForProductInterface; use Cnc\SerialNumber\Api\SerialNumberRepositoryInterface; use Cnc\SerialNumber\Helper\SerialNumber; use Cnc\SerialNumber\Model\Source\SerialNumber\Status; use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Model\ResourceModel\Product; use Magento\Framework\App\ResourceConnection; use Magento\Framework\Api\SearchCriteriaBuilderFactory; use Magento\InventoryApi\Api\Data\SourceItemInterface; use Magento\InventoryApi\Api\SourceItemRepositoryInterface; use Magento\InventoryImportExport\Model\Import\SourcesFactory as Importer; use Magento\Setup\Exception; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; class ImportProductStock extends Command { const LIMIT = 'limit'; const CLEAR_STOCKS = 'clear-stock-data'; /** * @var SourceDataFactory */ private $sourceDataFactory; /** * @var Importer */ private $importer; /** * @var ResourceConnection */ private $resource; /** * @var IsSerialNumberEnabledForProductInterface */ private $isSerialNumberEnabledForProduct; /** * @var SearchCriteriaBuilderFactory */ private $searchCriteriaBuilderFactory; /** * @var SourceItemRepositoryInterface */ private $sourceItemRepository; /** * @var SerialNumber */ private $helper; /** * @var Product */ private $resourceProduct; /** * @var SerialNumberRepositoryInterface */ private $serialNumberRepository; /** * ImportProductStock constructor. * @param SourceDataFactory $sourceDataFactory * @param Importer $importer * @param ResourceConnection $resource * @param IsSerialNumberEnabledForProductInterface $isSerialNumberEnabledForProduct * @param SearchCriteriaBuilderFactory $searchCriteriaBuilderFactory * @param SourceItemRepositoryInterface $sourceItemRepository * @param SerialNumber $helper * @param Product $resourceProduct * @param SerialNumberRepositoryInterface $serialNumberRepository * @param string|null $name */ public function __construct( SourceDataFactory $sourceDataFactory, Importer $importer, ResourceConnection $resource, IsSerialNumberEnabledForProductInterface $isSerialNumberEnabledForProduct, SearchCriteriaBuilderFactory $searchCriteriaBuilderFactory, SourceItemRepositoryInterface $sourceItemRepository, SerialNumber $helper, Product $resourceProduct, SerialNumberRepositoryInterface $serialNumberRepository, string $name = null ) { parent::__construct($name); $this->sourceDataFactory = $sourceDataFactory; $this->importer = $importer; $this->resource = $resource; $this->isSerialNumberEnabledForProduct = $isSerialNumberEnabledForProduct; $this->searchCriteriaBuilderFactory = $searchCriteriaBuilderFactory; $this->sourceItemRepository = $sourceItemRepository; $this->helper = $helper; $this->resourceProduct = $resourceProduct; $this->serialNumberRepository = $serialNumberRepository; } /** * @inheritDoc */ protected function configure() { $this->setName('catalog:products:stock-import'); $this->setDescription('Stock import for source'); $this->addOption( self::LIMIT, null, InputOption::VALUE_OPTIONAL, 'Use limit in case of too many data' ); $this->addOption( self::CLEAR_STOCKS, null, InputOption::VALUE_OPTIONAL, 'Clear stocks temp table and stock info. WARNING! This will remove all stock info for Available sources.' ); parent::configure(); } /** * @param InputInterface $input * @param OutputInterface $output * @return int|void */ protected function execute(InputInterface $input, OutputInterface $output) { if ($input->getOption(self::CLEAR_STOCKS)) { $this->clearImportTable(); $this->clearStockItems(); } else { $output->writeln("Preparing stock data for import..."); $connection = $this->resource->getConnection(); $select = $connection->select() ->from($connection->getTableName('cnc_stock_import')) ->where('is_imported = 0'); if ($input->getOption(self::LIMIT) > 0) { $select->limit($input->getOption('limit')); } $data = $connection->fetchAssoc($select); $importData = []; $stockIdToUpdate = []; if (!empty($data)) { foreach ($data as $stockItem) { $importData[] = [ 'source_code' => $stockItem['source_code'], 'sku' => $stockItem['sku'], 'quantity' => $stockItem['qty'] ]; $stockIdToUpdate[] = $stockItem['cnc_stock_id']; } try { $sourceModel = $this->sourceDataFactory->create(['data' => [$importData]]); $stock = $this->importer->create(['importData' => $sourceModel]); $stock->importData(); $output->writeln('Import S/N: ' . count($importData)); $i = 0; foreach ($importData as $data) { try { $i++; $output->write($i % 100 == 0 ? $i : '.'); $sku = $data['sku']; $sourceCode = $data['source_code']; if ($this->isSerialNumberEnabledForProduct->execute($sku)) { $serialNumbers = $this->getSerialNumbers($sku, $sourceCode); $currentQty = count($serialNumbers); $newQty = $data['quantity']; $diffQty = $newQty - $currentQty; if ($diffQty > 0) { $this->helper->createSerialNumbers( (int)$this->resourceProduct->getIdBySku($sku), (string)$sku, (string)$sourceCode, (int)$diffQty ); } elseif ($diffQty < 0) { $this->helper->blockSerialNumbers((string)$sku, $sourceCode, (int)abs($diffQty)); } } } catch (\Exception $e) { $output->writeln($e->getMessage()); } } $connection->update( $connection->getTableName('cnc_stock_import'), ['is_imported' => 1, 'import_date' => date('Y-m-d H:i:s')], sprintf('cnc_stock_id IN (%s)', implode(',', $stockIdToUpdate)) ); } catch (Exception $exception) { $output->writeln($exception->getMessage()); } } else { $output->writeln('Nothing to import.'); } } } /** * Truncate import table. */ private function clearImportTable() { $connection = $this->resource->getConnection(); $connection->truncateTable($connection->getTableName('cnc_stock_import')); } /** * Truncate inventory table */ private function clearStockItems() { $connection = $this->resource->getConnection(); $connection->truncateTable($connection->getTableName('inventory_source_item')); } /** * @param string $sku * @return array */ private function getSerialNumbers(string $sku, string $sourceCode): array { $searchCriteriaBuilder = $this->searchCriteriaBuilderFactory->create(); $searchCriteria = $searchCriteriaBuilder ->addFilter(SerialNumberInterface::SKU, $sku) ->addFilter(SerialNumberInterface::SOURCE_CODE, $sourceCode) ->create(); return $this->serialNumberRepository->getList($searchCriteria)->getItems(); } }