VirtualSourceDeductionProcessor.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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\InventoryShipping\Observer;
  8. use Magento\Framework\Event\ObserverInterface;
  9. use Magento\Framework\Event\Observer as EventObserver;
  10. use Magento\Framework\Exception\LocalizedException;
  11. use Magento\InventorySalesApi\Api\Data\SalesEventInterface;
  12. use Magento\InventorySalesApi\Api\Data\SalesEventInterfaceFactory;
  13. use Magento\InventoryShipping\Model\GetSourceSelectionResultFromInvoice;
  14. use Magento\InventorySourceDeductionApi\Model\SourceDeductionRequestInterface;
  15. use Magento\InventorySourceDeductionApi\Model\SourceDeductionServiceInterface;
  16. use Magento\InventoryShipping\Model\SourceDeductionRequestsFromSourceSelectionFactory;
  17. use Magento\Sales\Api\Data\InvoiceInterface;
  18. use Magento\Sales\Api\Data\OrderItemInterface;
  19. use Magento\InventorySalesApi\Api\Data\ItemToSellInterfaceFactory;
  20. use Magento\InventorySalesApi\Api\PlaceReservationsForSalesEventInterface;
  21. /**
  22. * Class VirtualSourceDeductionProcessor
  23. */
  24. class VirtualSourceDeductionProcessor implements ObserverInterface
  25. {
  26. /**
  27. * @var GetSourceSelectionResultFromInvoice
  28. */
  29. private $getSourceSelectionResultFromInvoice;
  30. /**
  31. * @var SourceDeductionServiceInterface
  32. */
  33. private $sourceDeductionService;
  34. /**
  35. * @var SourceDeductionRequestsFromSourceSelectionFactory
  36. */
  37. private $sourceDeductionRequestsFromSourceSelectionFactory;
  38. /**
  39. * @var SalesEventInterfaceFactory
  40. */
  41. private $salesEventFactory;
  42. /**
  43. * @var ItemToSellInterfaceFactory
  44. */
  45. private $itemToSellFactory;
  46. /**
  47. * @var PlaceReservationsForSalesEventInterface
  48. */
  49. private $placeReservationsForSalesEvent;
  50. /**
  51. * @param GetSourceSelectionResultFromInvoice $getSourceSelectionResultFromInvoice
  52. * @param SourceDeductionServiceInterface $sourceDeductionService
  53. * @param SourceDeductionRequestsFromSourceSelectionFactory $sourceDeductionRequestsFromSourceSelectionFactory
  54. * @param SalesEventInterfaceFactory $salesEventFactory
  55. * @param ItemToSellInterfaceFactory $itemToSellFactory
  56. * @param PlaceReservationsForSalesEventInterface $placeReservationsForSalesEvent
  57. */
  58. public function __construct(
  59. GetSourceSelectionResultFromInvoice $getSourceSelectionResultFromInvoice,
  60. SourceDeductionServiceInterface $sourceDeductionService,
  61. SourceDeductionRequestsFromSourceSelectionFactory $sourceDeductionRequestsFromSourceSelectionFactory,
  62. SalesEventInterfaceFactory $salesEventFactory,
  63. ItemToSellInterfaceFactory $itemToSellFactory,
  64. PlaceReservationsForSalesEventInterface $placeReservationsForSalesEvent
  65. ) {
  66. $this->getSourceSelectionResultFromInvoice = $getSourceSelectionResultFromInvoice;
  67. $this->sourceDeductionService = $sourceDeductionService;
  68. $this->sourceDeductionRequestsFromSourceSelectionFactory = $sourceDeductionRequestsFromSourceSelectionFactory;
  69. $this->salesEventFactory = $salesEventFactory;
  70. $this->itemToSellFactory = $itemToSellFactory;
  71. $this->placeReservationsForSalesEvent = $placeReservationsForSalesEvent;
  72. }
  73. /**
  74. * @param EventObserver $observer
  75. * @return void
  76. * @throws LocalizedException
  77. */
  78. public function execute(EventObserver $observer)
  79. {
  80. /** @var \Magento\Sales\Model\Order\Invoice $invoice */
  81. $invoice = $observer->getEvent()->getInvoice();
  82. if (!$this->isValid($invoice)) {
  83. return;
  84. }
  85. $sourceSelectionResult = $this->getSourceSelectionResultFromInvoice->execute($invoice);
  86. /** @var SalesEventInterface $salesEvent */
  87. $salesEvent = $this->salesEventFactory->create([
  88. 'type' => SalesEventInterface::EVENT_INVOICE_CREATED,
  89. 'objectType' => SalesEventInterface::OBJECT_TYPE_ORDER,
  90. 'objectId' => $invoice->getOrderId(),
  91. ]);
  92. $sourceDeductionRequests = $this->sourceDeductionRequestsFromSourceSelectionFactory->create(
  93. $sourceSelectionResult,
  94. $salesEvent,
  95. (int)$invoice->getOrder()->getStore()->getWebsiteId()
  96. );
  97. foreach ($sourceDeductionRequests as $sourceDeductionRequest) {
  98. $this->sourceDeductionService->execute($sourceDeductionRequest);
  99. $this->placeCompensatingReservation($sourceDeductionRequest);
  100. }
  101. }
  102. /**
  103. * Place compensating reservation after source deduction
  104. *
  105. * @param SourceDeductionRequestInterface $sourceDeductionRequest
  106. */
  107. private function placeCompensatingReservation(SourceDeductionRequestInterface $sourceDeductionRequest): void
  108. {
  109. $items = [];
  110. foreach ($sourceDeductionRequest->getItems() as $item) {
  111. $items[] = $this->itemToSellFactory->create([
  112. 'sku' => $item->getSku(),
  113. 'qty' => $item->getQty()
  114. ]);
  115. }
  116. $this->placeReservationsForSalesEvent->execute(
  117. $items,
  118. $sourceDeductionRequest->getSalesChannel(),
  119. $sourceDeductionRequest->getSalesEvent()
  120. );
  121. }
  122. /**
  123. * @param InvoiceInterface $invoice
  124. * @return bool
  125. */
  126. private function isValid(InvoiceInterface $invoice): bool
  127. {
  128. if ($invoice->getOrigData('entity_id')) {
  129. return false;
  130. }
  131. return $this->hasValidItems($invoice);
  132. }
  133. /**
  134. * @param InvoiceInterface $invoice
  135. * @return bool
  136. */
  137. private function hasValidItems(InvoiceInterface $invoice): bool
  138. {
  139. foreach ($invoice->getItems() as $invoiceItem) {
  140. /** @var OrderItemInterface $orderItem */
  141. $orderItem = $invoiceItem->getOrderItem();
  142. if ($orderItem->getIsVirtual()) {
  143. return true;
  144. }
  145. }
  146. return false;
  147. }
  148. }