getSourceSelectionResultFromInvoice = $getSourceSelectionResultFromInvoice; $this->sourceDeductionService = $sourceDeductionService; $this->sourceDeductionRequestsFromSourceSelectionFactory = $sourceDeductionRequestsFromSourceSelectionFactory; $this->salesEventFactory = $salesEventFactory; $this->itemToSellFactory = $itemToSellFactory; $this->placeReservationsForSalesEvent = $placeReservationsForSalesEvent; } /** * @param EventObserver $observer * @return void * @throws LocalizedException */ public function execute(EventObserver $observer) { /** @var \Magento\Sales\Model\Order\Invoice $invoice */ $invoice = $observer->getEvent()->getInvoice(); if (!$this->isValid($invoice)) { return; } $sourceSelectionResult = $this->getSourceSelectionResultFromInvoice->execute($invoice); /** @var SalesEventInterface $salesEvent */ $salesEvent = $this->salesEventFactory->create([ 'type' => SalesEventInterface::EVENT_INVOICE_CREATED, 'objectType' => SalesEventInterface::OBJECT_TYPE_ORDER, 'objectId' => $invoice->getOrderId(), ]); $sourceDeductionRequests = $this->sourceDeductionRequestsFromSourceSelectionFactory->create( $sourceSelectionResult, $salesEvent, (int)$invoice->getOrder()->getStore()->getWebsiteId() ); foreach ($sourceDeductionRequests as $sourceDeductionRequest) { $this->sourceDeductionService->execute($sourceDeductionRequest); $this->placeCompensatingReservation($sourceDeductionRequest); } } /** * Place compensating reservation after source deduction * * @param SourceDeductionRequestInterface $sourceDeductionRequest */ private function placeCompensatingReservation(SourceDeductionRequestInterface $sourceDeductionRequest): void { $items = []; foreach ($sourceDeductionRequest->getItems() as $item) { $items[] = $this->itemToSellFactory->create([ 'sku' => $item->getSku(), 'qty' => $item->getQty() ]); } $this->placeReservationsForSalesEvent->execute( $items, $sourceDeductionRequest->getSalesChannel(), $sourceDeductionRequest->getSalesEvent() ); } /** * @param InvoiceInterface $invoice * @return bool */ private function isValid(InvoiceInterface $invoice): bool { if ($invoice->getOrigData('entity_id')) { return false; } return $this->hasValidItems($invoice); } /** * @param InvoiceInterface $invoice * @return bool */ private function hasValidItems(InvoiceInterface $invoice): bool { foreach ($invoice->getItems() as $invoiceItem) { /** @var OrderItemInterface $orderItem */ $orderItem = $invoiceItem->getOrderItem(); if ($orderItem->getIsVirtual()) { return true; } } return false; } }