0

I am in a process of creating orders programatically in Magento 2. below is my code:

<?php
namespace Eight65media\MpowerSync\Helper;
use \Magento\Framework\App\Helper\AbstractHelper;
class Data extends AbstractHelper{

protected $scopeConfig;
protected $loggerInterface;

public function __construct(
    \Psr\Log\LoggerInterface $loggerInterface,
    \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
    \Magento\Framework\App\Helper\Context $context,
    \Magento\Store\Model\StoreManagerInterface $storeManager,
    \Magento\Catalog\Model\Product $product,
    \Magento\Catalog\Model\ProductFactory $productFactory,
    \Magento\Quote\Api\CartRepositoryInterface $cartRepositoryInterface,
    \Magento\Quote\Api\CartManagementInterface $cartManagementInterface,
    \Magento\Customer\Model\CustomerFactory $customerFactory,
    \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository,
    \Magento\Sales\Model\Order $order
) {

    $this->logger = $loggerInterface;
    $this->_scopeConfig = $scopeConfig;
    $this->_productFactory = $productFactory;
    $this->_storeManager = $storeManager;
    $this->_product = $product;
    $this->cartRepositoryInterface = $cartRepositoryInterface;
    $this->cartManagementInterface = $cartManagementInterface;
    $this->customerFactory = $customerFactory;
    $this->customerRepository = $customerRepository;
    $this->order = $order;
}    


public function createMageOrder($orderData) {
    $store=$this->_storeManager->getStore();
    $websiteId = $this->_storeManager->getStore()->getWebsiteId();
    $customer=$this->customerFactory->create();
    $customer->setWebsiteId($websiteId);
    $customer->loadByEmail($orderData['email']);// load customet by email address
    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();
    }

    $cartId = $this->cartManagementInterface->createEmptyCart(); //Create empty cart
    $quote = $this->cartRepositoryInterface->get($cartId); // load empty cart quote
    $quote->setStore($store);
    // if you have allready buyer id then you can load customer directly 
    $customer= $this->customerRepository->getById($customer->getEntityId());
    $quote->setCurrency();
    $quote->assignCustomer($customer); //Assign quote to customer

    //add items in quote
    foreach($orderData['items'] as $item){
        echo "+ ".$item['product_id']."</br>";
        $product = $this->_product->load($item['product_id']);
        //$product->setPrice($item['price']);
        $quote->addProduct($product, intval($item['qty']));
    }

    //Set Address to quote
    $quote->getBillingAddress()->addData($orderData['shipping_address']);
    $quote->getShippingAddress()->addData($orderData['shipping_address']);

    // Collect Rates and Set Shipping & Payment Method

    $shippingAddress=$quote->getShippingAddress();
    $shippingAddress->setCollectShippingRates(true)
                    ->collectShippingRates()
                    ->setShippingMethod('freeshipping_freeshipping'); //shipping method
    $quote->setPaymentMethod('checkmo'); //payment method
    $quote->setInventoryProcessed(false); //not effetc inventory

    // Set Sales Order Payment
    $quote->getPayment()->importData(['method' => 'checkmo']);
    $quote->save(); //Now Save quote and your quote is ready

    // Collect Totals
    $quote->collectTotals();

    // Create Order From Quote
    $quote = $this->cartRepositoryInterface->get($quote->getId());
    $orderId = $this->cartManagementInterface->placeOrder($quote->getId());
    $order = $this->order->load($orderId);

    $order->setEmailSent(0);
    $increment_id = $order->getRealOrderId();
    if($order->getEntityId()){
        $result['order_id']= $order->getRealOrderId();
    }else{
        $result=['error'=>1,'msg'=>'Your custom message'];
    }
    echo $result['order_id'];
    //return $result;
}//end of function create order
}

Below is my sample data set:

$tempOrder=[
 'currency_id'  => 'USD',
 'email'        => '[email protected]', //buyer email id
 'shipping_address' =>[
        'firstname'    => 'mujiko', //address Details
        'lastname'     => 'jikimo',
        'street' => 'xxxxx',
        'city' => 'xxxxx',
        'country_id' => 'US',
        'region' => '12',
        'postcode' => '43244',
        'telephone' => '52332',
        'fax' => '32423',
        'save_in_address_book' => 1
             ],
       'items'=> [ //array of product which order you want to create
                  ['product_id'=>'1','qty'=>4],
                  ['product_id'=>'10','qty'=>3]

                ]
    ];

What my issue is order, is creating, but the products are not adding properly.
Only 1 product is adding to the order, but first product added to the order with the second product price and qty of the product will be a total products in order. Ex:

['product_id'=>'1','qty'=>4],
['product_id'=>'10','qty'=>3]

From above product array name of the product_id 1 - Product 1, price 10.00

Name of the product_id 10 - product 2, price 20.00

In my order the product is save as product 1 with price of Product 2(20) qty is 7

Any help highly appreciate and almost 3 days tried in several ways and still fail.
Please help me.

1 Answer 1

2

Explanation:
This happens because, in $quote->addProduct($product, intval($item['qty']));. $product is always the same instance of the Product model.

Solution:

Replace this in the constructor \Magento\Catalog\Model\Product $product with \Magento\Catalog\Model\ProductFactory $productFactory.
Replace this $this->_product = $product; with $this->_productFactory = $productFactory; and add the member $_productFactory to the class.
Now in the createMageOrder method replace

$product = $this->_product->load($item['product_id']);

with

$product = $this->_productFactory->create()->load($item['product_id']);

Better solution.
Because the load method is deprecated you should use repositories.

So replace in your constructor \Magento\Catalog\Model\Product $product with \Magento\Catalog\Api\ProductRepositoryInterface $productRepository and $this->_product = $product; with $this->_productRepository = $productRepository;. Also declare the member $_productRepository to the class.

Now in the method createMageOrder replace

$product = $this->_product->load($item['product_id']);
$quote->addProduct($product, intval($item['qty']));

with

try {
    $product = $this->_productRepository->getById($item['product_id']);
    $quote->addProduct($product, intval($item['qty']));
} catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
    //it means the product does not exist;
    //you can choose to continue without this product or stop the order creation completely here
}
1
  • thank you for you explained answer.saved my day
    – Mujahidh
    Commented Mar 14, 2019 at 8:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.