Modify orders in your Magento 2 store without canceling them!
You can easily edit, add items, shipping, order data, as well for order details.
Load your order, quote and items need to modify.
Init construct :
Remove items from quote and order:
Add new item to quote and order:
You can easily edit, add items, shipping, order data, as well for order details.
Load your order, quote and items need to modify.
Init construct :
public function __construct( Action\Context $context, \Magento\Sales\Model\OrderFactory $orderFactory, \Magento\Quote\Model\Quote\Item\ToOrderItem $toOrderItem, \Magento\Quote\Model\QuoteFactory $quoteFactory, \Magento\Sales\Model\Order\ItemRepository $orderItemRepository, \Magento\Sales\Model\Order\Email\Sender\OrderSender $sender, \Magento\Catalog\Model\ProductRepository $productRepository, \Magento\Quote\Api\CartRepositoryInterface $quoteRepository ) { parent::__construct($context); $this->orderFactory = $orderFactory; $this->toOrderItem = $toOrderItem; $this->quoteFactory = $quoteFactory; $this->orderItemRepository = $orderItemRepository; $this->sender = $sender; $this->productRepository = $productRepository; $this->quoteRepository = $quoteRepository; }Load order, quote and specify items/products
$orderId = 100;//order id = 100 $itemRemoves = ['100'=> true];//item id= 100 $itemQtys = ['1001'=> 1,'1002'=>2];//item ids 1001 with qty=1, 1002 with qty=2 $newProductQty = ['1003'=> 3,'1004'=>4];// product id 1003 with qty=3, 1004 with qty=4 $order = $this->orderFactory->create()->load($orderId); $quote = $this->quoteFactory->create()->load($order->getQuoteId());Edit/Update/Add New need to same with quote and orders.
Remove items from quote and order:
foreach ($itemRemoves as $id => $value){ if($value){ foreach ($quote->getAllVisibleItems() as $quoteItem) { if ($id == $quoteItem->getId()){ $quoteItem->delete(); $quote->collectTotals(); foreach ($order->getItemsCollection() as $orderItem){ if($orderItem->getQuoteItemId() == $id){ $this->orderItemRepository->deleteById($orderItem->getId()); } } } } unset($itemQtys[$id]); } }Update Items from quote and convert to order:
foreach ($itemQtys as $id => $qty){ if($qty> 0){ $item = $quote->getItemById($id); if(!$item) return; $taxAmount = $item->getTaxPercent() * $qty * ($item->getProduct()->getPrice()/100); $rowTotalInclTax = $item->getPrice() * $qty + $taxAmount; $item ->setQty($qty) ->setTaxAmount($taxAmount) ->setRowTotalInclTax($rowTotalInclTax); $existData = $order->getItemByQuoteItemId($item->getId()); if(!$existData) continue; $orderItem = $this->toOrderItem->convert($item); $existData->addData($orderItem->getData()); } }
Add new item to quote and order:
foreach ($newProductQty as $productId => $qty){ if($qty> 0){ $product = $this->productRepository->getById($productId); if(!$product) return; $params = [ 'product' => $productId, 'qty' => $qty ]; $request = new \Magento\Framework\DataObject(); $request->setData($params); $quote->addProduct($product, $request); $quote->collectTotals(); foreach ($quote->getAllVisibleItems() as $item){ if($productId == $item->getProduct()->getId()){ /** * collect item price */ $item->save(); $existData = $order->getItemByQuoteItemId($item->getId()); $orderItem = $this->toOrderItem->convert($item); if ($existData) { $existData->addData($orderItem->getData()); }else{ /** * add new product to */ if ($item->getParentItem()) { $item->setParentItem( $order->getItemByQuoteItemId($item->getParentItem()->getId()) ); } $order->addItem($orderItem); } } } } }Re-Calculate order totals:
/** * collect shipping amount */ $quote->getShippingAddress()->requestShippingRates(); $itemTax = 0; $subTotal = 0; foreach ($order->getAllVisibleItems() as $item){ $itemTax += $item->getTaxAmount(); $subTotal += $item->getRowTotalInclTax() - $item->getTaxAmount(); } $order->setSubtotal($subTotal) ->setBaseSubtotal($subTotal) ->setShippingAmount($quote->getShippingAddress()->getShippingAmount()) ->setBaseShippingAmount($quote->getShippingAddress()->getBaseShippingAmount()) ->setShippingTaxAmount($quote->getShippingAddress()->getShippingTaxAmount()) ->setBaseShippingTaxAmount($quote->getShippingAddress()->getBaseShippingTaxAmount()) ->setTaxAmount($quote->getShippingAddress()->getShippingTaxAmount() + $itemTax) ->setBaseTaxAmount($quote->getShippingAddress()->getShippingTaxAmount() + $itemTax) ->setGrandTotal($subTotal + $quote->getShippingAddress()->getShippingAmount() + $quote->getShippingAddress()->getShippingTaxAmount() + $itemTax) ->setBaseGrandTotal($subTotal + $quote->getShippingAddress()->getBaseShippingAmount() + $quote->getShippingAddress()->getBaseshippingTaxAmount() + $itemTax); $order->save();Finally, Send email again for customer with new order update
$this->sender->send($order);This is full code
public function __construct( Action\Context $context, \Magento\Sales\Model\OrderFactory $orderFactory, \Magento\Quote\Model\Quote\Item\ToOrderItem $toOrderItem, \Magento\Quote\Model\QuoteFactory $quoteFactory, \Magento\Sales\Model\Order\ItemRepository $orderItemRepository, \Magento\Sales\Model\Order\Email\Sender\OrderSender $sender, \Magento\Catalog\Model\ProductRepository $productRepository, \Magento\Quote\Api\CartRepositoryInterface $quoteRepository ) { parent::__construct($context); $this->orderFactory = $orderFactory; $this->toOrderItem = $toOrderItem; $this->quoteFactory = $quoteFactory; $this->orderItemRepository = $orderItemRepository; $this->sender = $sender; $this->productRepository = $productRepository; $this->quoteRepository = $quoteRepository; } /** * @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\ResultInterface|void */ public function execute() { $data = $this->getRequest()->getParams(); $orderId = (isset($data['order_id']))? $data['order_id'] : null; $itemRemoves = (isset($data['remove'])) ? array_filter($data['remove']) : []; $itemQtys = (isset($data['qty'])) ? array_filter($data['qty']) : []; $newProductQty = (isset($data['new_product_qty'])) ? array_filter($data['new_product_qty']) : []; if(!$orderId || (empty($itemQtys) && empty($itemRemoves) && empty($newProductQty))){ $this->messageManager->addErrorMessage('empty data update'); $url = $this->getUrl('sales/order/view',array('order_id'=> $orderId)); $this->_redirect($url); return; } $order = $this->orderFactory->create()->load($orderId); $quote = $this->quoteFactory->create()->load($order->getQuoteId()); try{ /** * remove items */ foreach ($itemRemoves as $id => $value){ if($value){ $this->removeItemFromOrder($order, $quote, $id); unset($itemQtys[$id]); } } /** * update items */ foreach ($itemQtys as $id => $qty){ if($qty> 0){ $this->updateItemFromOrder($order, $quote, $id, $qty); } } /** * add new items */ foreach ($newProductQty as $productId => $qty){ if($qty> 0){ $this->addNewItem($order, $quote, $productId, $qty); } } $this->collectQuoteOrder($quote, $order); if(isset($data['notify_customer'])){ $this->sender->send($order); } $this->messageManager->addSuccessMessage('Update Order Successfully!'); }catch(\Exception $e){ $this->messageManager->addErrorMessage($e->getMessage()); } $url = $this->getUrl('sales/order/view',array('order_id'=> $orderId)); $this->_redirect($url); } /** * @param \Magento\Sales\Model\Order $order * @param \Magento\Quote\Model\Quote $quote * @param $productId * @param $qty * @throws \Magento\Framework\Exception\LocalizedException * @throws \Magento\Framework\Exception\NoSuchEntityException */ public function addNewItem($order, $quote, $productId, $qty){ $product = $this->productRepository->getById($productId); if(!$product) return; $params = [ 'product' => $productId, 'qty' => $qty ]; $request = new \Magento\Framework\DataObject(); $request->setData($params); $quote->addProduct($product, $request); $quote->collectTotals(); foreach ($quote->getAllVisibleItems() as $item){ if($productId == $item->getProduct()->getId()){ /** * collect item price */ $item->save(); $existData = $order->getItemByQuoteItemId($item->getId()); $orderItem = $this->toOrderItem->convert($item); if ($existData) { $existData->addData($orderItem->getData()); }else{ /** * add new product to */ if ($item->getParentItem()) { $item->setParentItem( $order->getItemByQuoteItemId($item->getParentItem()->getId()) ); } $order->addItem($orderItem); } } } } /** * @param \Magento\Sales\Model\Order $order * @param \Magento\Quote\Model\Quote $quote * @param $id * @throws \Exception */ protected function removeItemFromOrder($order, $quote, $id){ foreach ($quote->getAllVisibleItems() as $quoteItem) { if ($id == $quoteItem->getId()){ $quoteItem->delete(); $quote->collectTotals(); foreach ($order->getItemsCollection() as $orderItem){ if($orderItem->getQuoteItemId() == $id){ $this->orderItemRepository->deleteById($orderItem->getId()); } } } } } /** * @param \Magento\Sales\Model\Order $order * @param \Magento\Quote\Model\Quote $quote * @param $id * @param $qty */ protected function updateItemFromOrder($order, $quote, $id, $qty){ $item = $quote->getItemById($id); if(!$item) return; $taxAmount = $item->getTaxPercent() * $qty * ($item->getProduct()->getPrice()/100); $rowTotalInclTax = $item->getPrice() * $qty + $taxAmount; $item ->setQty($qty) ->setTaxAmount($taxAmount) ->setRowTotalInclTax($rowTotalInclTax); $existData = $order->getItemByQuoteItemId($item->getId()); $orderItem = $this->toOrderItem->convert($item); $existData->addData($orderItem->getData()); } /** * @param \Magento\Quote\Model\Quote $quote * @param \Magento\Sales\Model\Order $order * @throws \Exception */ protected function collectQuoteOrder($quote, $order){ /** * collect shipping amount */ $quote->getShippingAddress()->requestShippingRates(); $itemTax = 0; $subTotal = 0; foreach ($order->getAllVisibleItems() as $item){ $itemTax += $item->getTaxAmount(); $subTotal += $item->getRowTotalInclTax() - $item->getTaxAmount(); } $order->setSubtotal($subTotal) ->setBaseSubtotal($subTotal) ->setShippingAmount($quote->getShippingAddress()->getShippingAmount()) ->setBaseShippingAmount($quote->getShippingAddress()->getBaseShippingAmount()) ->setShippingTaxAmount($quote->getShippingAddress()->getShippingTaxAmount()) ->setBaseShippingTaxAmount($quote->getShippingAddress()->getBaseShippingTaxAmount()) ->setTaxAmount($quote->getShippingAddress()->getShippingTaxAmount() + $itemTax) ->setBaseTaxAmount($quote->getShippingAddress()->getShippingTaxAmount() + $itemTax) ->setGrandTotal($subTotal + $quote->getShippingAddress()->getShippingAmount() + $quote->getShippingAddress()->getShippingTaxAmount() + $itemTax) ->setBaseGrandTotal($subTotal + $quote->getShippingAddress()->getBaseShippingAmount() + $quote->getShippingAddress()->getBaseshippingTaxAmount() + $itemTax); $order->save(); }Goodluk!
Hitesh Agrawal
7 Mar 2020Here You didn’t mentioned about cart rule how it will be modify
anuprasad
2 May 2020I am just new to magento. if i want to implement something like this to an existing installation, where should i start with ?
kavi
3 Jun 2020Kindly guide which file we need add this plz
jeanmarcos
19 Aug 2020brutal