How to add new item (product) into existing order programmatically in Magento 2
After some goggling and with the help of some core modules I came up with following solution :
/**
* @var \Magento\Sales\Api\OrderRepositoryInterface
*/
protected $orderRepository;
/**
* @var \Magento\Catalog\Api\ProductRepositoryInterface
*/
protected $productRepository;
/**
* @var \Magento\Quote\Api\Data\CartItemInterfaceFactory
*/
protected $cartItemFactory;
/**
* @var \Magento\Quote\Api\CartRepositoryInterface
*/
protected $quoteRepository;
/**
* @var \Magento\Sales\Model\Order\ItemFactory
*/
protected $orderItemFactory;
public function __construct(
\Magento\Backend\App\Action\Context $context,
\Magento\Sales\Api\OrderRepositoryInterface $orderRepository,
\Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
\Magento\Quote\Api\Data\CartItemInterfaceFactory $cartItemFactory,
\Magento\Quote\Api\CartRepositoryInterface $quoteRepository,
\Magento\Sales\Model\Order\ItemFactory $orderItemFactory
) {
parent::__construct($context);
$this->productRepository = $productRepository;
$this->orderRepository = $orderRepository;
$this->cartItemFactory = $cartItemFactory;
$this->quoteRepository = $quoteRepository;
$this->orderItemFactory = $orderItemFactory;
}
public function execute()
{
$postData = $this->getRequest()->getPostValue();
$productSku = 'your-product-sku'; // Static Virtual Product created. You may also use static ID.
$product = $this->productRepository->get($productSku);
$order = $this->orderRepository->get($postData['order_id']);
$quote = $this->quoteRepository->get($order->getQuoteId());
try {
/* Add Quote Item Start */
$quoteItem = $this->cartItemFactory->create();
$quoteItem->setProduct($product);
$quoteItem->setCustomPrice($postData['custom_price']);
$quoteItem->setOriginalCustomPrice($postData['custom_price']);
$quoteItem->getProduct()->setIsSuperMode(true);
$quote->addItem($quoteItem);
$quote->collectTotals()->save();
/* Add Quote Item End */
/* Add Order Item Start */
$orderItem = $this->orderItemFactory->create();
$orderItem
->setStoreId($order->getStoreId())
->setQuoteItemId($quoteItem->getId())
->setProductId($product->getId())
->setProductType($product->getTypeId())
->setName($product->getName())
->setSku($product->getSku())
->setQtyOrdered(1)
->setPrice($postData['custom_price'])
->setBasePrice($postData['custom_price'])
->setOriginalPrice($postData['custom_price'])
->setBaseOriginalPrice($postData['custom_price'])
->setPriceInclTax($postData['custom_price'])
->setBasePriceInclTax($postData['custom_price'])
->setRowTotal($postData['custom_price'])
->setBaseRowTotal($postData['custom_price'])
->setRowTotalInclTax($postData['custom_price'])
->setBaseRowTotalInclTax($postData['custom_price'])
->setWeight(1)
->setIsVirtual(1);
$order->addItem($orderItem);
/* Add Order Item End */
/* Update relavant order totals Start */
$order->setBaseGrandTotal($order->getBaseGrandTotal() + $postData['custom_price']);
$order->setGrandTotal($order->getGrandTotal() + $postData['custom_price']);
$order->setBaseSubtotal($order->getBaseSubtotal() + $postData['custom_price']);
$order->setSubtotal($order->getSubtotal() + $postData['custom_price']);
$order->setBaseSubtotalInclTax($order->getBaseSubtotalInclTax() + $postData['custom_price']);
$order->setSubtotalInclTax($order->getSubtotalInclTax() + $postData['custom_price']);
$order->setTotalItemCount($order->getTotalItemCount() + 1);
$order->setTotalQtyOrdered($order->getTotalQtyOrdered() + 1);
$this->orderRepository->save($order);
/* Update relavant order totals End */
}
catch (\Exception $e) {
$this->messageManager->addError($e->getMessage());
}
}