Skip to content

Instantly share code, notes, and snippets.

@TheFrankman
Created July 20, 2016 18:49
Show Gist options
  • Save TheFrankman/0f342e07500ba126297ff01d09b3aa07 to your computer and use it in GitHub Desktop.
Save TheFrankman/0f342e07500ba126297ff01d09b3aa07 to your computer and use it in GitHub Desktop.
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
Copy link

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
Copy link

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

@chi07
Copy link

chi07 commented Nov 15, 2016

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

@alaaghribi
Copy link

How can we call the function from phtml file ?

@wenjiawenjia
Copy link

@godriccao Thanks a lot! Life saver.

@abhisheks4
Copy link

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
Copy link

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

@parththummar
Copy link

@godriccao your solution works, thanks a lot.

@creative-git
Copy link

@godriccao , shipment is not getting saved

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