AppendReservationsAfterOrderPlacementPlugin.php 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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\InventorySales\Plugin\Sales\OrderManagement;
  8. use Magento\InventoryCatalogApi\Model\GetProductTypesBySkusInterface;
  9. use Magento\InventoryConfigurationApi\Model\IsSourceItemManagementAllowedForProductTypeInterface;
  10. use Magento\Sales\Api\Data\OrderInterface;
  11. use Magento\Sales\Api\OrderManagementInterface;
  12. use Magento\InventorySalesApi\Api\PlaceReservationsForSalesEventInterface;
  13. use Magento\InventorySalesApi\Api\Data\SalesEventInterface;
  14. use Magento\InventorySalesApi\Api\Data\SalesEventInterfaceFactory;
  15. use Magento\InventoryCatalogApi\Model\GetSkusByProductIdsInterface;
  16. use Magento\Store\Api\WebsiteRepositoryInterface;
  17. use Magento\InventorySalesApi\Api\Data\SalesChannelInterfaceFactory;
  18. use Magento\InventorySalesApi\Api\Data\SalesChannelInterface;
  19. use Magento\InventorySalesApi\Api\Data\ItemToSellInterfaceFactory;
  20. use Magento\InventorySales\Model\CheckItemsQuantity;
  21. use Magento\InventorySalesApi\Model\StockByWebsiteIdResolverInterface;
  22. class AppendReservationsAfterOrderPlacementPlugin
  23. {
  24. /**
  25. * @var PlaceReservationsForSalesEventInterface
  26. */
  27. private $placeReservationsForSalesEvent;
  28. /**
  29. * @var GetSkusByProductIdsInterface
  30. */
  31. private $getSkusByProductIds;
  32. /**
  33. * @var WebsiteRepositoryInterface
  34. */
  35. private $websiteRepository;
  36. /**
  37. * @var SalesChannelInterfaceFactory
  38. */
  39. private $salesChannelFactory;
  40. /**
  41. * @var SalesEventInterfaceFactory
  42. */
  43. private $salesEventFactory;
  44. /**
  45. * @var ItemToSellInterfaceFactory
  46. */
  47. private $itemsToSellFactory;
  48. /**
  49. * @var CheckItemsQuantity
  50. */
  51. private $checkItemsQuantity;
  52. /**
  53. * @var StockByWebsiteIdResolverInterface
  54. */
  55. private $stockByWebsiteIdResolver;
  56. /**
  57. * @var GetProductTypesBySkusInterface
  58. */
  59. private $getProductTypesBySkus;
  60. /**
  61. * @var IsSourceItemManagementAllowedForProductTypeInterface
  62. */
  63. private $isSourceItemManagementAllowedForProductType;
  64. /**
  65. * @param PlaceReservationsForSalesEventInterface $placeReservationsForSalesEvent
  66. * @param GetSkusByProductIdsInterface $getSkusByProductIds
  67. * @param WebsiteRepositoryInterface $websiteRepository
  68. * @param SalesChannelInterfaceFactory $salesChannelFactory
  69. * @param SalesEventInterfaceFactory $salesEventFactory
  70. * @param ItemToSellInterfaceFactory $itemsToSellFactory
  71. * @param CheckItemsQuantity $checkItemsQuantity
  72. * @param StockByWebsiteIdResolverInterface $stockByWebsiteIdResolver
  73. * @param GetProductTypesBySkusInterface $getProductTypesBySkus
  74. * @param IsSourceItemManagementAllowedForProductTypeInterface $isSourceItemManagementAllowedForProductType
  75. */
  76. public function __construct(
  77. PlaceReservationsForSalesEventInterface $placeReservationsForSalesEvent,
  78. GetSkusByProductIdsInterface $getSkusByProductIds,
  79. WebsiteRepositoryInterface $websiteRepository,
  80. SalesChannelInterfaceFactory $salesChannelFactory,
  81. SalesEventInterfaceFactory $salesEventFactory,
  82. ItemToSellInterfaceFactory $itemsToSellFactory,
  83. CheckItemsQuantity $checkItemsQuantity,
  84. StockByWebsiteIdResolverInterface $stockByWebsiteIdResolver,
  85. GetProductTypesBySkusInterface $getProductTypesBySkus,
  86. IsSourceItemManagementAllowedForProductTypeInterface $isSourceItemManagementAllowedForProductType
  87. ) {
  88. $this->placeReservationsForSalesEvent = $placeReservationsForSalesEvent;
  89. $this->getSkusByProductIds = $getSkusByProductIds;
  90. $this->websiteRepository = $websiteRepository;
  91. $this->salesChannelFactory = $salesChannelFactory;
  92. $this->salesEventFactory = $salesEventFactory;
  93. $this->itemsToSellFactory = $itemsToSellFactory;
  94. $this->checkItemsQuantity = $checkItemsQuantity;
  95. $this->stockByWebsiteIdResolver = $stockByWebsiteIdResolver;
  96. $this->getProductTypesBySkus = $getProductTypesBySkus;
  97. $this->isSourceItemManagementAllowedForProductType = $isSourceItemManagementAllowedForProductType;
  98. }
  99. /**
  100. * @param OrderManagementInterface $subject
  101. * @param OrderInterface $order
  102. * @return OrderInterface
  103. * @SuppressWarnings(PHPMD.UnusedFormalParameter)
  104. */
  105. public function afterPlace(OrderManagementInterface $subject, OrderInterface $order) : OrderInterface
  106. {
  107. $itemsById = $itemsBySku = $itemsToSell = [];
  108. foreach ($order->getItems() as $item) {
  109. if (!isset($itemsById[$item->getProductId()])) {
  110. $itemsById[$item->getProductId()] = 0;
  111. }
  112. $itemsById[$item->getProductId()] += $item->getQtyOrdered();
  113. }
  114. $productSkus = $this->getSkusByProductIds->execute(array_keys($itemsById));
  115. $productTypes = $this->getProductTypesBySkus->execute($productSkus);
  116. foreach ($productSkus as $productId => $sku) {
  117. if (false === $this->isSourceItemManagementAllowedForProductType->execute($productTypes[$sku])) {
  118. continue;
  119. }
  120. $itemsBySku[$sku] = (float)$itemsById[$productId];
  121. $itemsToSell[] = $this->itemsToSellFactory->create([
  122. 'sku' => $sku,
  123. 'qty' => -(float)$itemsById[$productId]
  124. ]);
  125. }
  126. $websiteId = (int)$order->getStore()->getWebsiteId();
  127. $websiteCode = $this->websiteRepository->getById($websiteId)->getCode();
  128. $stockId = (int)$this->stockByWebsiteIdResolver->execute((int)$websiteId)->getStockId();
  129. $this->checkItemsQuantity->execute($itemsBySku, $stockId);
  130. /** @var SalesEventInterface $salesEvent */
  131. $salesEvent = $this->salesEventFactory->create([
  132. 'type' => SalesEventInterface::EVENT_ORDER_PLACED,
  133. 'objectType' => SalesEventInterface::OBJECT_TYPE_ORDER,
  134. 'objectId' => (string)$order->getEntityId()
  135. ]);
  136. $salesChannel = $this->salesChannelFactory->create([
  137. 'data' => [
  138. 'type' => SalesChannelInterface::TYPE_WEBSITE,
  139. 'code' => $websiteCode
  140. ]
  141. ]);
  142. $this->placeReservationsForSalesEvent->execute($itemsToSell, $salesChannel, $salesEvent);
  143. return $order;
  144. }
  145. }