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,

Était-ce utile?

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

Autres conseils

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à magento.stackexchange
scroll top