![]() 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/Setup/Patch/Data/ |
<?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]> */ namespace Cnc\Catalog\Setup\Patch\Data; use Magento\Framework\Api\DataObjectHelper; use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Framework\App\RequestInterface; use Magento\Framework\Exception\CouldNotDeleteException; use Magento\Framework\Exception\CouldNotSaveException; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Setup\Patch\DataPatchInterface; use Magento\Framework\Validation\ValidationException; use Magento\InventoryAdminUi\Model\Stock\StockSaveProcessor; use Magento\InventoryApi\Api\Data\SourceInterfaceFactory; use Magento\InventoryApi\Api\Data\StockInterface; use Magento\InventoryApi\Api\Data\StockInterfaceFactory; use Magento\InventoryApi\Api\Data\StockSourceLinkInterface; use Magento\InventoryApi\Api\Data\StockSourceLinkInterfaceFactory; use Magento\InventoryApi\Api\GetStockSourceLinksInterface; use Magento\InventoryApi\Api\SourceRepositoryInterface; use Magento\InventoryApi\Api\StockRepositoryInterface; use Magento\InventoryApi\Api\StockSourceLinksDeleteInterface; use Magento\InventoryApi\Api\StockSourceLinksSaveInterface; use Magento\InventorySalesApi\Api\Data\SalesChannelInterface; use Magento\InventorySalesApi\Api\Data\SalesChannelInterfaceFactory; use Psr\Log\LoggerInterface; class ConfigureMSIStocks implements DataPatchInterface { const SOURCE_CONFIG = [ 'fr' => [ 'code' => 'cnc_fr', 'name' => 'FR', 'postCode' => 75001, 'country' => 'FR' ], 'us' => [ 'code' => 'cnc_usa', 'name' => 'USA', 'postCode' => 33101, 'country' => 'US' ], ]; const STOCK_CONFIG = [ 'us' => [ 'name' => 'CNC Stock Prio USA', 'websites' => ['cnc_us'], 'sources' => [ 0 => [ 'position' => 1, 'priority' => 3, 'name' => 'USA', 'record_id' => 'cnc_usa', 'source_code' => 'cnc_usa' ], 1 => [ 'position' => 2, 'priority' => 4, 'name' => 'FR', 'record_id' => 'cnc_fr', 'source_code' => 'cnc_fr' ] ] ], 'fr' => [ 'name' => 'CNC Stock Prio FR', 'websites' => ['cnc_eu', 'cnc_gb'], 'sources' => [ 0 => [ 'position' => 1, 'priority' => 3, 'name' => 'FR', 'record_id' => 'cnc_fr', 'source_code' => 'cnc_fr' ], 1 => [ 'position' => 2, 'priority' => 4, 'name' => 'USA', 'record_id' => 'cnc_usa', 'source_code' => 'cnc_usa' ] ] ], ]; /** * @var StockInterfaceFactory */ private $stockFactory; /** * @var SourceInterfaceFactory */ private $sourceFactory; /** * @var SourceRepositoryInterface */ private $sourceRepository; /** * @var StockSaveProcessor */ private $stockSaveProcessor; /** * @var SalesChannelInterfaceFactory */ private $salesChannelFactory; /** * @var StockRepositoryInterface */ private $stockRepository; /** * @var GetStockSourceLinksInterface */ private $getStockSourceLinks; /** * @var SearchCriteriaBuilder */ private $searchCriteriaBuilder; /** * @var StockSourceLinkInterfaceFactory */ private $stockSourceLinkFactory; /** * @var DataObjectHelper */ private $dataObjectHelper; /** * @var StockSourceLinksSaveInterface */ private $stockSourceLinksSave; /** * @var StockSourceLinksDeleteInterface */ private $stockSourceLinksDelete; /** * @var RequestInterface */ private $request; /** * @var LoggerInterface */ private $logger; /** * ConfigureMSIStocks constructor. * @param SourceInterfaceFactory $sourceFactory * @param SourceRepositoryInterface $sourceRepository * @param RequestInterface $request * @param StockSaveProcessor $stockSaveProcessor * @param StockInterfaceFactory $stockFactory * @param SalesChannelInterfaceFactory $salesChannelFactory * @param StockRepositoryInterface $stockRepository * @param GetStockSourceLinksInterface $getStockSourceLinks * @param SearchCriteriaBuilder $searchCriteriaBuilder * @param StockSourceLinkInterfaceFactory $stockSourceLinkFactory * @param StockSourceLinksSaveInterface $stockSourceLinksSave * @param StockSourceLinksDeleteInterface $stockSourceLinksDelete * @param DataObjectHelper $dataObjectHelper * @param LoggerInterface $logger */ public function __construct( SourceInterfaceFactory $sourceFactory, SourceRepositoryInterface $sourceRepository, RequestInterface $request, StockSaveProcessor $stockSaveProcessor, StockInterfaceFactory $stockFactory, SalesChannelInterfaceFactory $salesChannelFactory, StockRepositoryInterface $stockRepository, GetStockSourceLinksInterface $getStockSourceLinks, SearchCriteriaBuilder $searchCriteriaBuilder, StockSourceLinkInterfaceFactory $stockSourceLinkFactory, StockSourceLinksSaveInterface $stockSourceLinksSave, StockSourceLinksDeleteInterface $stockSourceLinksDelete, DataObjectHelper $dataObjectHelper, LoggerInterface $logger ) { $this->sourceFactory = $sourceFactory; $this->sourceRepository = $sourceRepository; $this->logger = $logger; $this->request = $request; $this->stockSaveProcessor = $stockSaveProcessor; $this->stockFactory = $stockFactory; $this->salesChannelFactory = $salesChannelFactory; $this->stockRepository = $stockRepository; $this->getStockSourceLinks = $getStockSourceLinks; $this->searchCriteriaBuilder = $searchCriteriaBuilder; $this->stockSourceLinkFactory = $stockSourceLinkFactory; $this->dataObjectHelper = $dataObjectHelper; $this->stockSourceLinksSave = $stockSourceLinksSave; $this->stockSourceLinksDelete = $stockSourceLinksDelete; } /** * @return ConfigureMSIStocks|void * @throws CouldNotDeleteException * @throws CouldNotSaveException * @throws ValidationException */ public function apply() { //1. Add 2 new sources (FR + USA) foreach (self::SOURCE_CONFIG as $sourceData) { try { $source = $this->sourceRepository->get($sourceData['code']); if ($source->getSourceCode() == $sourceData['code']) { $source->setPostcode($sourceData['postCode']); $source->setName($sourceData['name']); $source->setCountryId($sourceData['country']); } } catch (NoSuchEntityException $e) { $source = $this->sourceFactory->create(); $source->setSourceCode($sourceData['code']); $source->setPostcode($sourceData['postCode']); $source->setName($sourceData['name']); $source->setCountryId($sourceData['country']); $this->sourceRepository->save($source); } } //2. Add Stocks for sources foreach (self::STOCK_CONFIG as $stockData) { $stockParams = []; $stockParams['general'] = []; $stockParams['sales_channels'] = []; $stockParams['sources'] = []; $stockParams['sources']['assigned_sources'] = []; $stockParams['assign_sources_grid'] = []; $stockParams['general']['name'] = $stockData['name']; $stockParams['sales_channels']['website'] = $stockData['websites']; foreach ($stockData['sources'] as $id => $data) { $stockParams['sources']['assigned_sources'][$id] = [ 'source_code' => $data['source_code'], 'name' => $data['name'], 'position' => $data['position'], 'priority' => $data['priority'], 'record_id' => $data['record_id'], ]; $stockParams['assign_sources_grid'][$id] = ['source_code' => $data['source_code']]; } $stockId = $this->processStockSave($stockParams); $this->processStockLinkSave($stockId, $stockParams); } } /** * @return array|string[] */ public static function getDependencies(): array { return []; } /** * @return array|string[] */ public function getAliases(): array { return []; } /** * @param $stockParams * @return int * @throws CouldNotSaveException * @throws ValidationException */ private function processStockSave($stockParams): int { $stock = $this->stockFactory->create(); $this->dataObjectHelper->populateWithArray($stock, $stockParams['general'], StockInterface::class); $extensionAttributes = $stock->getExtensionAttributes(); $assignedSalesChannels = $extensionAttributes->getSalesChannels(); if (null !== $assignedSalesChannels) { foreach ($assignedSalesChannels as $key => $assignedSalesChannel) { if ($assignedSalesChannel->getType() === SalesChannelInterface::TYPE_WEBSITE) { unset($assignedSalesChannels[$key]); } } } if (isset($stockParams['sales_channels'][SalesChannelInterface::TYPE_WEBSITE]) && is_array($stockParams['sales_channels'][SalesChannelInterface::TYPE_WEBSITE]) ) { foreach ($stockParams['sales_channels'][SalesChannelInterface::TYPE_WEBSITE] as $websiteCode) { $assignedSalesChannels[] = $this->createSalesChannelByWebsiteCode($websiteCode); } } $extensionAttributes->setSalesChannels($assignedSalesChannels); return $this->stockRepository->save($stock); } /** * Create the sales channel by given website code * * @param string $websiteCode * @return SalesChannelInterface */ private function createSalesChannelByWebsiteCode(string $websiteCode): SalesChannelInterface { $salesChannel = $this->salesChannelFactory->create(); $salesChannel->setCode($websiteCode); $salesChannel->setType(SalesChannelInterface::TYPE_WEBSITE); return $salesChannel; } /** * @param int $stockId * @param $stockData * @throws CouldNotDeleteException * @throws CouldNotSaveException * @throws ValidationException */ private function processStockLinkSave(int $stockId, $stockData) { $assignedSources = isset($stockData['sources']['assigned_sources']) && is_array($stockData['sources']['assigned_sources']) ? $this->prepareAssignedSources($stockData['sources']['assigned_sources']) : []; $linksForDelete = $this->getAssignedLinks($stockId); $linksForSave = []; foreach ($assignedSources as $linkData) { $sourceCode = $linkData[StockSourceLinkInterface::SOURCE_CODE]; if (isset($linksForDelete[$sourceCode])) { $link = $linksForDelete[$sourceCode]; } else { /** @var StockSourceLinkInterface $link */ $link = $this->stockSourceLinkFactory->create(); } $linkData[StockSourceLinkInterface::STOCK_ID] = $stockId; $this->dataObjectHelper->populateWithArray($link, $linkData, StockSourceLinkInterface::class); $linksForSave[] = $link; unset($linksForDelete[$sourceCode]); } if (count($linksForSave) > 0) { $this->stockSourceLinksSave->execute($linksForSave); } if (count($linksForDelete) > 0) { $this->stockSourceLinksDelete->execute($linksForDelete); } } /** * Convert built-in UI component property position into priority * * @param array $assignedSources * @return array */ private function prepareAssignedSources(array $assignedSources): array { foreach ($assignedSources as $key => $source) { if (empty($source['priority'])) { $source['priority'] = (int)$source['position']; $assignedSources[$key] = $source; } } return $assignedSources; } /** * Retrieves links that are assigned to $stockId * * @param int $stockId * @return StockSourceLinkInterface[] */ private function getAssignedLinks(int $stockId): array { $searchCriteria = $this->searchCriteriaBuilder ->addFilter(StockSourceLinkInterface::STOCK_ID, $stockId) ->create(); $result = []; foreach ($this->getStockSourceLinks->execute($searchCriteria)->getItems() as $link) { $result[$link->getSourceCode()] = $link; } return $result; } }