ProcessSourceItemsObserver.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. declare(strict_types=1);
  7. namespace Magento\InventoryCatalogAdminUi\Observer;
  8. use Magento\Catalog\Api\Data\ProductInterface;
  9. use Magento\Catalog\Controller\Adminhtml\Product\Save;
  10. use Magento\CatalogInventory\Api\Data\StockItemInterface;
  11. use Magento\Framework\Api\SearchCriteriaBuilder;
  12. use Magento\Framework\Api\SearchCriteriaBuilderFactory;
  13. use Magento\Framework\Event\ObserverInterface;
  14. use Magento\Framework\Event\Observer as EventObserver;
  15. use Magento\InventoryApi\Api\Data\SourceItemInterface;
  16. use Magento\InventoryApi\Api\SourceItemRepositoryInterface;
  17. use Magento\InventoryCatalogApi\Api\DefaultSourceProviderInterface;
  18. use Magento\InventoryCatalogApi\Model\IsSingleSourceModeInterface;
  19. use Magento\InventoryConfigurationApi\Model\IsSourceItemManagementAllowedForProductTypeInterface;
  20. /**
  21. * Save source product relations during product persistence via controller
  22. *
  23. * This needs to be handled in dedicated observer, because there is no pre-defined way of making several API calls for
  24. * Form submission handling
  25. */
  26. class ProcessSourceItemsObserver implements ObserverInterface
  27. {
  28. /**
  29. * @var IsSourceItemManagementAllowedForProductTypeInterface
  30. */
  31. private $isSourceItemManagementAllowedForProductType;
  32. /**
  33. * @var SourceItemsProcessor
  34. */
  35. private $sourceItemsProcessor;
  36. /**
  37. * @var IsSingleSourceModeInterface
  38. */
  39. private $isSingleSourceMode;
  40. /**
  41. * @var DefaultSourceProviderInterface
  42. */
  43. private $defaultSourceProvider;
  44. /**
  45. * @var SearchCriteriaBuilderFactory
  46. */
  47. private $searchCriteriaBuilderFactory;
  48. /**
  49. * @var SourceItemRepositoryInterface
  50. */
  51. private $sourceItemRepository;
  52. /**
  53. * @param IsSourceItemManagementAllowedForProductTypeInterface $isSourceItemManagementAllowedForProductType
  54. * @param SourceItemsProcessor $sourceItemsProcessor
  55. * @param IsSingleSourceModeInterface $isSingleSourceMode
  56. * @param DefaultSourceProviderInterface $defaultSourceProvider
  57. * @param SearchCriteriaBuilderFactory $searchCriteriaBuilderFactory
  58. * @param SourceItemRepositoryInterface $sourceItemRepository
  59. */
  60. public function __construct(
  61. IsSourceItemManagementAllowedForProductTypeInterface $isSourceItemManagementAllowedForProductType,
  62. SourceItemsProcessor $sourceItemsProcessor,
  63. IsSingleSourceModeInterface $isSingleSourceMode,
  64. DefaultSourceProviderInterface $defaultSourceProvider,
  65. SearchCriteriaBuilderFactory $searchCriteriaBuilderFactory,
  66. SourceItemRepositoryInterface $sourceItemRepository
  67. ) {
  68. $this->isSourceItemManagementAllowedForProductType = $isSourceItemManagementAllowedForProductType;
  69. $this->sourceItemsProcessor = $sourceItemsProcessor;
  70. $this->isSingleSourceMode = $isSingleSourceMode;
  71. $this->defaultSourceProvider = $defaultSourceProvider;
  72. $this->searchCriteriaBuilderFactory = $searchCriteriaBuilderFactory;
  73. $this->sourceItemRepository = $sourceItemRepository;
  74. }
  75. /**
  76. * Process source items during product saving via controller
  77. *
  78. * @param EventObserver $observer
  79. * @return void
  80. */
  81. public function execute(EventObserver $observer)
  82. {
  83. /** @var ProductInterface $product */
  84. $product = $observer->getEvent()->getProduct();
  85. if ($this->isSourceItemManagementAllowedForProductType->execute($product->getTypeId()) === false) {
  86. return;
  87. }
  88. /** @var Save $controller */
  89. $controller = $observer->getEvent()->getController();
  90. $productData = $controller->getRequest()->getParam('product', []);
  91. $singleSourceData = $productData['quantity_and_stock_status'] ?? [];
  92. if (!$this->isSingleSourceMode->execute()) {
  93. $sources = $controller->getRequest()->getParam('sources', []);
  94. $assignedSources = $sources['assigned_sources'] ?? [];
  95. $this->sourceItemsProcessor->process($productData['sku'], $assignedSources);
  96. } elseif (!empty($singleSourceData)) {
  97. /** @var StockItemInterface $stockItem */
  98. $stockItem = $product->getExtensionAttributes()->getStockItem();
  99. $qty = $singleSourceData['qty'] ?? (empty($stockItem) ? 0 : $stockItem->getQty());
  100. $isInStock = $singleSourceData['is_in_stock'] ?? (empty($stockItem) ? 1 : (int)$stockItem->getIsInStock());
  101. $defaultSourceData = [
  102. SourceItemInterface::SKU => $productData['sku'],
  103. SourceItemInterface::SOURCE_CODE => $this->defaultSourceProvider->getCode(),
  104. SourceItemInterface::QUANTITY => $qty,
  105. SourceItemInterface::STATUS => $isInStock
  106. ];
  107. $sourceItems = $this->getSourceItemsWithoutDefault($productData['sku']);
  108. $sourceItems[] = $defaultSourceData;
  109. $this->sourceItemsProcessor->process($productData['sku'], $sourceItems);
  110. }
  111. }
  112. /**
  113. * Get Source Items Data without Default Source by SKU
  114. *
  115. * @param string $sku
  116. * @return array
  117. */
  118. private function getSourceItemsWithoutDefault(string $sku): array
  119. {
  120. /** @var SearchCriteriaBuilder $searchCriteriaBuilder */
  121. $searchCriteriaBuilder = $this->searchCriteriaBuilderFactory->create();
  122. $searchCriteria = $searchCriteriaBuilder
  123. ->addFilter(SourceItemInterface::SKU, $sku)
  124. ->addFilter(SourceItemInterface::SOURCE_CODE, $this->defaultSourceProvider->getCode(), 'neq')
  125. ->create();
  126. $sourceItems = $this->sourceItemRepository->getList($searchCriteria)->getItems();
  127. $sourceItemData = [];
  128. if ($sourceItems) {
  129. foreach ($sourceItems as $sourceItem) {
  130. $sourceItemData[] = [
  131. SourceItemInterface::SKU => $sourceItem->getSku(),
  132. SourceItemInterface::SOURCE_CODE => $sourceItem->getSourceCode(),
  133. SourceItemInterface::QUANTITY => $sourceItem->getQuantity(),
  134. SourceItemInterface::STATUS => $sourceItem->getStatus()
  135. ];
  136. }
  137. }
  138. return $sourceItemData;
  139. }
  140. }