Question

I have an order which has the grand total that I need to fix because one of my products prices is incorrect, to do that I need to change the order item price and recollect order total, is there a way I can do this programmatically?

Here's how I load my order:

$order = $this->objectManager->create('\Magento\Sales\Model\Order')->load($orderId);
Was it helpful?

Solution

The solution will like below

$orderId = 'put_your_order_id';
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$quoteToOrder = $objectManager->create('Magento\Quote\Model\Quote\Item\ToOrderItem');
$order = $objectManager->create('Magento\Sales\Model\Order')->load($orderId);
$quote = $objectManager->create('\Magento\Quote\Model\Quote')->load($order->getQuoteId());

First we need to update the order quote.

foreach ($items as $quoteItem) {
    $origOrderItem = $order->getItemByQuoteItemId($quoteItem->getId());
    $orderItemId = $origOrderItem->getItemId();
    //update quote item according your need 
}
$quote->collectTotals();
$quote->save();

Then update the order

foreach ($items as $quoteItem) {
    $orderItem = $quoteToOrder->convert($quoteItem);
    $origOrderItemNew = $order->getItemByQuoteItemId($quoteItem->getId());

    if ($origOrderItemNew) {
        $origOrderItemNew->addData($orderItem->getData());
    } else {
        if ($quoteItem->getParentItem()) {
            $orderItem->setParentItem(
                $order->getItemByQuoteItemId($orderItem->getParentItem()->getId())
            );
        }
        $order->addItem($orderItem);
    }
}
$order->setSubtotal($quote->getSubtotal())
      ->setBaseSubtotal($quote->getBaseSubtotal())
      ->setGrandTotal($quote->getGrandTotal())
      ->setBaseGrandTotal($quote->getBaseGrandTotal());
$quote->save();
$order->save();
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top