diff --git a/vendor/magento/module-sales/Model/ResourceModel/Order/Handler/State.php b/vendor/magento/module-sales/Model/ResourceModel/Order/Handler/State.php index 47395b17afe..51c45ed5e5a 100644 --- a/vendor/magento/module-sales/Model/ResourceModel/Order/Handler/State.php +++ b/vendor/magento/module-sales/Model/ResourceModel/Order/Handler/State.php @@ -38,11 +38,64 @@ class State ) { $order->setState(Order::STATE_CLOSED) ->setStatus($order->getConfig()->getStateDefaultStatus(Order::STATE_CLOSED)); - } elseif ($currentState === Order::STATE_PROCESSING && !$order->canShip()) { + } elseif ($currentState === Order::STATE_PROCESSING + && (!$order->canShip() || $this->isPartiallyRefundedOrderShipped($order)) + ) { $order->setState(Order::STATE_COMPLETE) ->setStatus($order->getConfig()->getStateDefaultStatus(Order::STATE_COMPLETE)); + } elseif ($order->getIsVirtual() && $order->getStatus() === Order::STATE_CLOSED) { + $order->setState(Order::STATE_CLOSED); } } return $this; } + + /** + * Check if all items are remaining items after partially refunded are shipped + * + * @param Order $order + * @return bool + */ + public function isPartiallyRefundedOrderShipped(Order $order): bool + { + $isPartiallyRefundedOrderShipped = false; + if ($this->getShippedItems($order) > 0 + && $order->getTotalQtyOrdered() <= $this->getRefundedItems($order) + $this->getShippedItems($order)) { + $isPartiallyRefundedOrderShipped = true; + } + + return $isPartiallyRefundedOrderShipped; + } + + /** + * Get all refunded items number + * + * @param Order $order + * @return int + */ + private function getRefundedItems(Order $order): int + { + $numOfRefundedItems = 0; + foreach ($order->getAllItems() as $item) { + if ($item->getProductType() == 'simple') { + $numOfRefundedItems += (int)$item->getQtyRefunded(); + } + } + return $numOfRefundedItems; + } + + /** + * Get all shipped items number + * + * @param Order $order + * @return int + */ + private function getShippedItems(Order $order): int + { + $numOfShippedItems = 0; + foreach ($order->getAllItems() as $item) { + $numOfShippedItems += (int)$item->getQtyShipped(); + } + return $numOfShippedItems; + } }