Here I am using Magento 2.1.6 and trying to create order programmatically.
public function __construct(
\Magento\Framework\App\Helper\Context $context,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Catalog\Model\ProductFactory $product,
\Magento\Framework\Data\Form\FormKey $formkey,
\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\Sales\Api\OrderRepositoryInterface $orderRepository,
\Magento\Sales\Model\Service\InvoiceService $invoiceService,
\Magento\Framework\DB\Transaction $transaction,
\Magento\Sales\Api\Data\OrderInterface $order,
\Magento\Framework\ObjectManagerInterface $objectmanager,
\Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productFactory,
\Magento\Quote\Api\CartRepositoryInterface $cartRepositoryInterface,
\Magento\Quote\Api\CartManagementInterface $cartManagementInterface,
\Magento\Quote\Model\Quote\Address\Rate $shippingRate
) {
$this->_storeManager = $storeManager;
$this->_productFactory = $product;
$this->_formkey = $formkey;
$this->quote = $quote;
$this->quoteManagement = $quoteManagement;
$this->customerFactory = $customerFactory;
$this->customerRepository = $customerRepository;
$this->orderService = $orderService;
$this->_orderRepository = $orderRepository;
$this->_invoiceService = $invoiceService;
$this->_transaction = $transaction;
$this->order = $order;
$this->_objectManager = $objectmanager;
$this->productFactory = $productFactory;
$this->cartRepositoryInterface = $cartRepositoryInterface;
$this->cartManagementInterface = $cartManagementInterface;
$this->shippingRate = $shippingRate;
parent::__construct($context);
}
Create New Order Function
public function createOrderNew($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
$cart_id = $this->cartManagementInterface->createEmptyCart();
$cart = $this->cartRepositoryInterface->get($cart_id);
$cart->setStore($store);
// if you have already buyer id then you can load customer directly
$customer= $this->customerRepository->getById($customer->getEntityId());
$cart->setCurrency();
$cart->assignCustomer($customer); //Assign quote to customer
$cart->save();
//add items in quote
ob_start();
foreach($orderData['items'] as $item){
foreach($item as $item) {
//echo $item['product_id'];
$product = $this->_productFactory->create()->load($item['product_id']);
$customOptions = $this->_objectManager->get('Magento\Catalog\Model\Product\Option')->getProductOptionCollection($product);
try {
// print_r($item); die();
$params = array('product' => $item['product_id'], 'qty' => $item['qty']);
if (array_key_exists('options', $item) && $item['options']) {
$params['options'] = json_decode(json_encode($item['options']), True);
}
if ($product->getTypeId() == 'configurable') {
$params['super_attribute'] = $item['super_attribute'];
} elseif ($product->getTypeId() == 'bundle') {
$params['bundle_option'] = $item['bundle_option'];
$params['bundle_option_qty'] = $item['bundle_option_qty'];
} elseif ($product->getTypeId() == 'grouped') {
$params['super_group'] = $item['super_group'];
}
$objParam = new \Magento\Framework\DataObject();
$objParam->setData($params);
$cart->addProduct($product, $objParam);
} catch (Exception $e) {
$response[$item['product_id']]= $e->getMessage();
}
unset($product);
}
}
$cart->save();
ob_flush();
$cart->getBillingAddress()->addData($orderData['shipping_address']);
$cart->getShippingAddress()->addData($orderData['shipping_address']);
// 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
//@todo insert a variable to affect the invetory
$cart->setInventoryProcessed(false);
// Set sales order payment
$cart->getPayment()->importData(['method' => 'checkmo']);
// Collect total and saeve
$cart->collectTotals();
// Submit the quote and create the order
$cart->save();
$cart = $this->cartRepositoryInterface->get($cart->getId());
$order_id = $this->cartManagementInterface->placeOrder($cart->getId());
if($orderData['status'] == 4) {
return $this->createInvoice($order_id);
}
return $order_id;
}
Array Of order Details
array(5) {
["currency_id"]=>
string(3) "USD"
["email"]=>
string(16) "xxx@gmail.com"
["shipping_address"]=>
array(10) {
["firstname"]=>
string(7) "xxx"
["lastname"]=>
string(10) "xxx"
["street"]=>
string(14) "xxx"
["city"]=>
string(10) "Manchester"
["country_id"]=>
string(2) "GB"
["region"]=>
string(10) "Lancashire"
["postcode"]=>
string(7) "M23 2GF"
["telephone"]=>
string(11) "xxx"
["fax"]=>
string(0) ""
["save_in_address_book"]=>
int(1)
}
["items"]=>
array(1) {
[0]=>
array(1) {
[0]=>
array(3) {
["product_id"]=>
string(4) "4694"
["qty"]=>
string(1) "1"
["options"]=>
array(1) {
[3658]=>
string(4) "test"
}
}
}
}
["status"]=>
string(1) "4"
}
I added Custom option for product
With this code Order created successfully. Products also assigned to properly but Custom Options are not as assigned to the products.
Looking For Help.
Add custom option to product then add it to cart
$customOptions = [];
$customOptions[] = [
'label' => __('custom option title'),
'value' => 'Value',
'print_value' => 'Print Value'
];
$product->addCustomOption('additional_options', serialize($customOptions));
$cart->addProduct($product, $objParam);
Add option to quote item
Rewrite Magento ToOrderItem class (add below lines to your di.xml) for adding custom option to order
<preference for="Magento\Quote\Model\Quote\Item\ToOrderItem" type="CustomCompany\CustomModule\Observer\AddOrderDeliveryDate"/>
AddOrderDeliveryDate.php
<?php
namespace CustomCompany\CustomModule\Observer;
use Magento\Framework\DataObject\Copy;
use Magento\Quote\Model\Quote\Item;
use Magento\Quote\Model\Quote\Address\Item as AddressItem;
use Magento\Sales\Api\Data\OrderItemInterfaceFactory as OrderItemFactory;
use Magento\Sales\Api\Data\OrderItemInterface;
class AddOrderDeliveryDate extends \Magento\Quote\Model\Quote\Item\ToOrderItem
{
/**
* @var Copy
*/
protected $objectCopyService;
/**
* @var OrderItemFactory
*/
protected $orderItemFactory;
/**
* @var \Magento\Framework\Api\DataObjectHelper
*/
protected $dataObjectHelper;
/**
* @param OrderItemFactory $orderItemFactory
* @param Copy $objectCopyService
* @param \Magento\Framework\Api\DataObjectHelper $dataObjectHelper
*/
public function __construct(
OrderItemFactory $orderItemFactory,
Copy $objectCopyService,
\Magento\Framework\Api\DataObjectHelper $dataObjectHelper
) {
$this->orderItemFactory = $orderItemFactory;
$this->objectCopyService = $objectCopyService;
$this->dataObjectHelper = $dataObjectHelper;
}
public function convert($item, $data = [])
{
$options = $item->getProductOrderOptions();
if (!$options) {
$options = $item->getProduct()->getTypeInstance()->getOrderOptions($item->getProduct());
}
$orderItemData = $this->objectCopyService->getDataFromFieldset(
'quote_convert_item',
'to_order_item',
$item
);
if (!$item->getNoDiscount()) {
$data = array_merge(
$data,
$this->objectCopyService->getDataFromFieldset(
'quote_convert_item',
'to_order_item_discount',
$item
)
);
}
$orderItem = $this->orderItemFactory->create();
$this->dataObjectHelper->populateWithArray(
$orderItem,
array_merge($orderItemData, $data),
'\Magento\Sales\Api\Data\OrderItemInterface'
);
/**Setting custom options to item **/
if($item->getOptionByCode('additional_options'))
$options['additional_options'] = unserialize($item->getOptionByCode('additional_options')->getValue());
$orderItem->setProductOptions($options);
if ($item->getParentItem()) {
$orderItem->setQtyOrdered(
$orderItemData[OrderItemInterface::QTY_ORDERED] * $item->getParentItem()->getQty()
);
}
return $orderItem;
}
}