Question

I have created one virtual product in my Magento2 website. Now, I want to add it programmatically to the existing customer orders on some occasions with its custom price and name.

Can someone please guide step by step to achieve this?

Thanks,

Was it helpful?

Solution

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());
  } 
}

OTHER TIPS

As per as, Magento you cannot add a new item to an order after that order is placed before. You must have to add your item before it cart has been placed.

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top