Instantly share code, notes, and snippets.

Embed
What would you like to do?
Programatically create an order in Magento 2.1
<?php
/**
* @author Frank Clark
*/
namespace Vendor\Namespace\Model\Subscription\Order;
class Create
{
public function __construct(
\Magento\Framework\App\Helper\Context $context,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Catalog\Model\Product $product,
\Magento\Quote\Model\QuoteFactory $quote,
\Magento\Quote\Model\QuoteManagement $quoteManagement,
\Magento\Customer\Model\CustomerFactory $customerFactory,
\Magento\Customer\Api\CustomerRepositoryInterface $customerRepository,
\Magento\Sales\Model\Service\OrderService $orderService,
\Magento\Quote\Api\CartRepositoryInterface $cartRepositoryInterface,
\Magento\Quote\Api\CartManagementInterface $cartManagementInterface
) {
$this->_storeManager = $storeManager;
$this->_product = $product;
$this->quote = $quote;
$this->quoteManagement = $quoteManagement;
$this->customerFactory = $customerFactory;
$this->customerRepository = $customerRepository;
$this->orderService = $orderService;
$this->cartRepositoryInterface = $cartRepositoryInterface;
$this->cartManagementInterface = $cartManagementInterface;
}
/**
* Create Order On Your Store
*
* @param array $orderData
* @return array
*
*/
public function createOrder($orderData) {
//init the store id and website id @todo pass from array
$store = $this->_storeManager->getStore();
$websiteId = $this->_storeManager->getStore()->getWebsiteId();
//init the customer
$customer=$this->customerFactory->create();
$customer->setWebsiteId($websiteId);
$customer->loadByEmail($orderData['email']);// load customet by email address
//check the customer
if(!$customer->getEntityId()){
//If not avilable then create this customer
$customer->setWebsiteId($websiteId)
->setStore($store)
->setFirstname($orderData['shipping_address']['firstname'])
->setLastname($orderData['shipping_address']['lastname'])
->setEmail($orderData['email'])
->setPassword($orderData['email']);
$customer->save();
}
//init the quote
$quote=$this->quote->create();
$quote->setStore($store);
// if you have already buyer id then you can load customer directly
$customer= $this->customerRepository->getById($customer->getEntityId());
$quote->setCurrency();
$this->cartRepositoryInterface->save($quote);
$quote->assignCustomer($customer); //Assign quote to customer
//add items in quote
foreach($orderData['items'] as $item){
$product=$this->_product->load($item['product_id']);
$product->setPrice(22);
$quote->addProduct(
$product,
intval($item['qty'])
);
}
//Set Address to quote @todo add section in order data for seperate billing and handle it
$quote->getBillingAddress()->addData($orderData['shipping_address']);
$quote->getShippingAddress()->addData($orderData['shipping_address']);
// Collect Rates and Set Shipping & Payment Method
$shippingAddress = $quote->getShippingAddress();
//@todo set in order data
$shippingAddress->setCollectShippingRates(true)
->collectShippingRates()
->setShippingMethod('flatrate_flatrate'); //shipping method
$quote->setPaymentMethod('checkmo'); //payment method
//@todo insert a variable to affect the invetory
$quote->setInventoryProcessed(false);
// Set sales order payment
$quote->getPayment()->importData(['method' => 'checkmo']);
//$quote->save();
$this->cartRepositoryInterface->save($quote);
// Collect total and saeve
$quote->collectTotals();
// Submit the quote and create the order
$quote = $this->cartRepositoryInterface->get($quote->getId());
$order = $this->cartManagementInterface->submit($quote);
//do not send the email
$order->setEmailSent(0);
//give a result back
if($order->getEntityId()){
$result['order_id'] = $order->getEntityId();
}else{
$result=['error'=>1,'msg'=>'Your custom message'];
}
return $result;
}
}
?>
@nimila

This comment has been minimized.

nimila commented Aug 30, 2016

Hi Frank,

Thank you for your code. It saved my time a lot.. but when I tried the code "Cart %1 does not contain item %2" has gone but facing other issues now..

  1. Multiple products are not getting added, only first product in the loop will get added.
  2. Product price will be 0.00 always.
  3. Shipping method is not getting saved.

Can you please guide me to resolve the issue.

@godriccao

This comment has been minimized.

godriccao commented Sep 1, 2016

Hi nimila and Frank,

I got the same problems with yours and I managed to solve them. The full code piece is at here.
Here are my explanation to my solution:

1.Multiple products are not getting added, only first product in the loop will get added.

Instead of using \Magento\Catalog\Model\Product in __construct parameter, I used \Magento\Catalog\Model\ProductFactory. Then I create product object by doing $product=$this->_product->create()->load($item['product_id']);. Here is the snippet that add products to quote:

        //add items in quote
        foreach($orderData['items'] as $item){
            $product=$this->_product->create()->load($item['product_id']);
                $quote->addProduct(
                    $product,
                    intval($item['qty'])
                );
        }

2.Product price will be 0.00 always.

I'm not saving the order by $this->cartRepositoryInterface->save($quote);. Instead, I used $quote->save();. (In fact my code is a little different. I used the following code to create a $cart, which is the interface of $quote:

$cart_id = $this->cartManagementInterface->createEmptyCart();
$cart = $this->cartRepogitoryInterface->get($cart_id);

3.Shipping method is not getting saved.

I find my flatrate_flatrate shipping method is saved properly with Frank's code. But when I want to use freeshipping_freeshipping, I have to give the __construct a \Magento\Quote\Model\Quote\Address\Rate $shippingRate parameter and added some code like this:

        // Collect Rates and Set Shipping & Payment Method
        $this->shippingRate
            ->setCode('freeshipping_freeshipping')
            ->getPrice(1);
        $shippingAddress = $cart->getShippingAddress();
        //@todo set in order data
        $shippingAddress->setCollectShippingRates(true)
            ->collectShippingRates()
            ->setShippingMethod('flatrate_flatrate'); //shipping method
        $cart->getShippingAddress()->addShippingRate($this->rate);
        $cart->setPaymentMethod('checkmo'); //payment method
@shinichi2510

This comment has been minimized.

shinichi2510 commented Nov 15, 2016

It's does not work with Table rate - Weight and Destination. Please give me an advice?
Thanks

@alaaghribi

This comment has been minimized.

alaaghribi commented Dec 13, 2016

How can we call the function from phtml file ?

@wenjiawenjia

This comment has been minimized.

wenjiawenjia commented Jan 3, 2017

@godriccao Thanks a lot! Life saver.

@abhisheks4

This comment has been minimized.

abhisheks4 commented Feb 24, 2017

@TheFrankman,

I am using this code and order is creating but order total is 0 (zero).

`<?php

namespace Vendor\Module\Model\ReOrder;

class ReOrder extends \Magento\Framework\Model\AbstractModel
{
public function __construct(
\Magento\Framework\App\Helper\Context $context,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Catalog\Model\ProductFactory $product,
\Magento\Quote\Model\QuoteFactory $quote,
\Magento\Quote\Model\QuoteManagement $quoteManagement,
\Magento\Customer\Model\CustomerFactory $customerFactory,
\Magento\Customer\Api\CustomerRepositoryInterface $customerRepository,
\Magento\Sales\Model\Service\OrderService $orderService,
\Magento\Quote\Api\CartRepositoryInterface $cartRepositoryInterface,
\Magento\Quote\Api\CartManagementInterface $cartManagementInterface,
\DocResearch\Customer\Block\Customer\LastOrder $lastorder
) {
$this->_storeManager = $storeManager;
$this->_product = $product;
$this->quote = $quote;
$this->quoteManagement = $quoteManagement;
$this->customerFactory = $customerFactory;
$this->customerRepository = $customerRepository;
$this->orderService = $orderService;
$this->cartRepositoryInterface = $cartRepositoryInterface;
$this->cartManagementInterface = $cartManagementInterface;
$this->lastorder = $lastorder;

}

public function createOrder($orderData = null) {

	$_orderDetails = $this->lastorder->getOrders();
		$orderData = array();
		foreach ($_orderDetails as $_order){
		$lid = $_order->getId();
         $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
         $order = $objectManager->create('Magento\Sales\Model\Order')->load($lid);
         $storeManager = $objectManager->get('Magento\Store\Model\StoreManagerInterface'); 
         $store = $storeManager->getStore();
         $mediaUrl = $store->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA);
         $items = $order->getAllItems();
      /*  foreach($items as $k => $i){
		echo "<pre>".$lid; print_r($i->getData()); die();
        $_product =  $this->_product->create()->load($i->getProductId());
		$orderData['items'][$k]['product_id'] = $i->getProductId();
		$orderData['items'][$k]['qty'] = $i->getData('qty_ordered');
		}*/
		$shippingAddress = $_order->getShippingAddress();  
		$orderData['shipping_address']['firstname'] = $shippingAddress->getFirstname();
		$orderData['shipping_address']['lastname'] = $shippingAddress->getLastname();
		$orderData['shipping_address']['street'] = $shippingAddress->getStreet();
		$orderData['shipping_address']['city'] = $shippingAddress->getCity();
		$orderData['shipping_address']['region'] = $shippingAddress->getRegion();
		$orderData['shipping_address']['region_id'] = $shippingAddress->getRegion_id();
		$orderData['shipping_address']['postcode'] = $shippingAddress->getPostcode();
		$orderData['shipping_address']['telephone'] = $shippingAddress->getTelephone();
		$orderData['shipping_address']['fax'] = $shippingAddress->getFax();
		$orderData['shipping_address']['country_id'] = $shippingAddress->getCountry_id();
		$orderData['shipping_address']['save_in_address_book'] = $shippingAddress->getCity();
		$orderData['email'] = $shippingAddress->getEmail();
		$orderData['shipping_method'] = $_order->getShippingMethod();
		$orderData['payment_method'] = $_order->getPayment()->getMethod();
		}
	
	//init the store id and website id @todo pass from array
    $store = $this->_storeManager->getStore();
    $websiteId = $this->_storeManager->getStore()->getWebsiteId();
    //init the customer
    $customer=$this->customerFactory->create();
    $customer->setWebsiteId($websiteId);
    $customer->loadByEmail($orderData['email']);// load customet by email address
    //check the customer
    if(!$customer->getEntityId()){
        //If not avilable then create this customer
        $customer->setWebsiteId($websiteId)
            ->setStore($store)
            ->setFirstname($orderData['shipping_address']['firstname'])
            ->setLastname($orderData['shipping_address']['lastname'])
            ->setEmail($orderData['email'])
            ->setPassword($orderData['email']);
        $customer->save();
    }
    //init the quote
    $quote=$this->quote->create();
    $quote->setStore($store);
    // if you have already buyer id then you can load customer directly
    $customer= $this->customerRepository->getById($customer->getEntityId());
    $quote->setCurrency();
    $this->cartRepositoryInterface->save($quote);
    $quote->assignCustomer($customer); //Assign quote to customer
    //add items in quote
	
	foreach($items as $key => $value){
        $product =  $this->_product->create()->load($value->getProductId());
		$product->setPrice(29.0000);
		//echo '<pre>';print_r($product->getPrice());
		$quote->addProduct(
            $product,
            intval($value->getQtyOrdered())
        );
	}
	
	 $itemsq = $quote->getAllItems();
	 
	  // foreach($itemsq as $k => $i){
	 // //echo "<pre>"; print_r($i->getData('price')); die();
        // $_product =  $this->_product->create()->load($i->getProductId());
		// $i->setCustomPrice(29.0000);
		// $i->setOriginalCustomPrice(29.0000);
		// $i->setPrice(29.0000);
		// $i->setOrginalCustomPrice(29.0000);
		// $i->setBasePrice(29.0000);
		// $i->setBaseOriginalPrice(29.0000);
		 // }
	
    //Set Address to quote @todo add section in order data for seperate billing and handle it
    $quote->getBillingAddress()->addData($orderData['shipping_address']);
    $quote->getShippingAddress()->addData($orderData['shipping_address']);
    // Collect Rates and Set Shipping & Payment Method
    $shippingAddress = $quote->getShippingAddress();
    //@todo set in order data
    $shippingAddress->setCollectShippingRates(true)
        ->collectShippingRates()
        ->setShippingMethod($orderData['shipping_method']); //shipping method
    $quote->setPaymentMethod($orderData['payment_method']); //payment method
    //@todo insert a variable to affect the invetory
    $quote->setInventoryProcessed(false);
    // Set sales order payment
    $quote->getPayment()->importData(['method' => $orderData['payment_method']]);
    //$quote->save();
	 

	
    $this->cartRepositoryInterface->save($quote);

    // Collect total and saeve
    $quote->collectTotals();
    // Submit the quote and create the order
    $quote = $this->cartRepositoryInterface->get($quote->getId());
    $order = $this->cartManagementInterface->submit($quote);
    //do not send the email
    $order->setEmailSent(0);

	
	if(empty($order->getEntityId())) {
		return false;
	}
	return $order->getEntityId();
}

}`
@parththummar

This comment has been minimized.

parththummar commented Jul 5, 2017

Creates order but all prices sets to 0 after adding line $this->cartRepositoryInterface->save($quote); after $quote->setCurrency();

@parththummar

This comment has been minimized.

parththummar commented Jul 5, 2017

@godriccao your solution works, thanks a lot.

@barjas

This comment has been minimized.

barjas commented Aug 25, 2017

@godriccao , shipment is not getting saved

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment