diff --git a/vendor/magento/module-inventory-sales/Observer/SalesInventory/DeductSourceItemQuantityOnRefundObserver.php b/vendor/magento/module-inventory-sales/Observer/SalesInventory/DeductSourceItemQuantityOnRefundObserver.php deleted file mode 100644 index f080682..0000000 --- a/vendor/magento/module-inventory-sales/Observer/SalesInventory/DeductSourceItemQuantityOnRefundObserver.php +++ /dev/null @@ -1,144 +0,0 @@ -getSkuFromOrderItem = $getSkuFromOrderItem; - $this->itemsToRefundFactory = $itemsToRefundFactory; - $this->isSourceItemManagementAllowedForProductType = $isSourceItemManagementAllowedForProductType; - $this->getProductTypesBySkus = $getProductTypesBySkus; - $this->deductSourceItemQuantityOnRefund = $deductSourceItemQuantityOnRefund; - $this->orderRepository = $orderRepository; - } - - /** - * @param Observer $observer - * @return void - */ - public function execute(Observer $observer) - { - /* @var $creditmemo \Magento\Sales\Model\Order\Creditmemo */ - $creditmemo = $observer->getEvent()->getCreditmemo(); - $order = $this->orderRepository->get($creditmemo->getOrderId()); - $itemsToRefund = $refundedOrderItemIds = []; - /** @var CreditmemoItem $item */ - foreach ($creditmemo->getItems() as $item) { - /** @var OrderItemInterface $orderItem */ - $orderItem = $item->getOrderItem(); - $sku = $this->getSkuFromOrderItem->execute($orderItem); - - if ($this->isValidItem($sku, $item)) { - $refundedOrderItemIds[] = $item->getOrderItemId(); - $qty = (float)$item->getQty(); - $processedQty = $orderItem->getQtyInvoiced() - $orderItem->getQtyRefunded() + $qty; - $itemsToRefund[$sku] = [ - 'qty' => ($itemsToRefund[$sku]['qty'] ?? 0) + $qty, - 'processedQty' => ($itemsToRefund[$sku]['processedQty'] ?? 0) + (float)$processedQty - ]; - } - } - - $itemsToDeductFromSource = []; - foreach ($itemsToRefund as $sku => $data) { - $itemsToDeductFromSource[] = $this->itemsToRefundFactory->create([ - 'sku' => $sku, - 'qty' => $data['qty'], - 'processedQty' => $data['processedQty'] - ]); - } - - if (!empty($itemsToDeductFromSource)) { - $this->deductSourceItemQuantityOnRefund->execute( - $order, - $itemsToDeductFromSource, - $refundedOrderItemIds - ); - } - } - - /** - * @param string $sku - * @param CreditmemoItem $item - * @return bool - */ - private function isValidItem(string $sku, CreditmemoItem $item): bool - { - /** @var OrderItemInterface $orderItem */ - $orderItem = $item->getOrderItem(); - // Since simple products which are the part of a grouped product are saved in the database - // (table sales_order_item) with product type grouped, we manually change the type of - // product from grouped to simple which support source management. - $typeId = $orderItem->getProductType() === 'grouped' ? 'simple' : $orderItem->getProductType(); - - $productType = $typeId ?: $this->getProductTypesBySkus->execute( - [$sku] - )[$sku]; - - return $this->isSourceItemManagementAllowedForProductType->execute($productType) - && $item->getQty() > 0 - && !$item->getBackToStock(); - } -} diff --git a/vendor/magento/module-inventory-sales/Plugin/Sales/OrderManagement/DeductSourceItemQuantityOnRefundPlugin.php b/vendor/magento/module-inventory-sales/Plugin/Sales/OrderManagement/DeductSourceItemQuantityOnRefundPlugin.php new file mode 100644 index 0000000..f9b27f8 --- /dev/null +++ b/vendor/magento/module-inventory-sales/Plugin/Sales/OrderManagement/DeductSourceItemQuantityOnRefundPlugin.php @@ -0,0 +1,170 @@ +getSkuFromOrderItem = $getSkuFromOrderItem; + $this->itemsToRefundFactory = $itemsToRefundFactory; + $this->isSourceItemManagementAllowedForProductType = $isSourceItemManagementAllowedForProductType; + $this->getProductTypesBySkus = $getProductTypesBySkus; + $this->deductSourceItemQuantityOnRefund = $deductSourceItemQuantityOnRefund; + $this->orderRepository = $orderRepository; + } + + /** + * On Credit Memo create, issues the reservation compensation record. + * + * Before saving the credit memo, validates if the credit memo object was created or updated. + * If the credit memo was updates, we should not compensate the reservation. + * + * @param CreditmemoRepositoryInterface $subject + * @param callable $proceed + * @param CreditmemoInterface $entity + * @return mixed + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function aroundSave( + CreditmemoRepositoryInterface $subject, + callable $proceed, + CreditmemoInterface $entity + ) + { + $isNewCreditMemo = !(bool)$entity->getEntityId(); + $result = $proceed($entity); + + if ($isNewCreditMemo) { + $this->compensateReservation($entity); + } + + return $result; + } + + /** + * @param CreditmemoInterface $creditMemo + * @return void + */ + private function compensateReservation(CreditmemoInterface $creditMemo): void + { + $order = $this->orderRepository->get($creditMemo->getOrderId()); + $itemsToRefund = $refundedOrderItemIds = []; + /** @var CreditmemoItem $item */ + foreach ($creditMemo->getItems() as $item) { + /** @var OrderItemInterface $orderItem */ + $orderItem = $item->getOrderItem(); + $sku = $this->getSkuFromOrderItem->execute($orderItem); + + if ($this->isValidItem($sku, $item)) { + $refundedOrderItemIds[] = $item->getOrderItemId(); + $qty = (float)$item->getQty(); + $processedQty = $orderItem->getQtyInvoiced() - $orderItem->getQtyRefunded() + $qty; + $itemsToRefund[$sku] = [ + 'qty' => ($itemsToRefund[$sku]['qty'] ?? 0) + $qty, + 'processedQty' => ($itemsToRefund[$sku]['processedQty'] ?? 0) + (float)$processedQty + ]; + } + } + + $itemsToDeductFromSource = []; + foreach ($itemsToRefund as $sku => $data) { + $itemsToDeductFromSource[] = $this->itemsToRefundFactory->create([ + 'sku' => $sku, + 'qty' => $data['qty'], + 'processedQty' => $data['processedQty'] + ]); + } + + if (!empty($itemsToDeductFromSource)) { + $this->deductSourceItemQuantityOnRefund->execute( + $order, + $itemsToDeductFromSource, + $refundedOrderItemIds + ); + } + } + + /** + * @param string $sku + * @param CreditmemoItem $item + * @return bool + */ + private function isValidItem(string $sku, CreditmemoItem $item): bool + { + /** @var OrderItemInterface $orderItem */ + $orderItem = $item->getOrderItem(); + // Since simple products which are the part of a grouped product are saved in the database + // (table sales_order_item) with product type grouped, we manually change the type of + // product from grouped to simple which support source management. + $typeId = $orderItem->getProductType() === 'grouped' ? 'simple' : $orderItem->getProductType(); + + $productType = $typeId ?: $this->getProductTypesBySkus->execute( + [$sku] + )[$sku]; + + return $this->isSourceItemManagementAllowedForProductType->execute($productType) + && $item->getQty() > 0 + && !$item->getBackToStock(); + } +} diff --git a/vendor/magento/module-inventory-sales/etc/di.xml b/vendor/magento/module-inventory-sales/etc/di.xml index b94a1e6..19faa0c 100644 --- a/vendor/magento/module-inventory-sales/etc/di.xml +++ b/vendor/magento/module-inventory-sales/etc/di.xml @@ -169,6 +169,9 @@ + + + diff --git a/vendor/magento/module-inventory-sales/etc/events.xml b/vendor/magento/module-inventory-sales/etc/events.xml index 63cfbda..568e903 100644 --- a/vendor/magento/module-inventory-sales/etc/events.xml +++ b/vendor/magento/module-inventory-sales/etc/events.xml @@ -12,10 +12,6 @@ - - - -