0

I've been trying to create an order programatically in Magento 2.3 and the order is created but my code dies and I get the error : "Unique constraint violation found".

What do I need to add or change? Here is my code (I´ll remove objectmanager when it´s working):

    $store=$this->_storeManager->getStore();

    $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
    $cartManagementInterface = $objectManager->get('\Magento\Quote\Api\CartManagementInterface');
    $cartRepositoryInterface = $objectManager->get('\Magento\Quote\Api\CartRepositoryInterface');

    $cart_id = $cartManagementInterface->createEmptyCart();
    $quote = $cartRepositoryInterface->get($cart_id);

    //$quote=$this->quote->create(); //Create object of quote
    $quote->setStore($store); //set store for which you create quote
    // if you have allready buyer id then you can load customer directly
    $customer= $this->customerRepository->get($orderData["email"]);
    $quote->setCurrency();
    $quote->assignCustomer($customer); //Assign quote to customer

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

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

    $quote->getShippingAddress()->addData($orderData['shipping_address']);

    $this->shippingRate
        ->setCode('freeshipping_freeshipping')
        ->getPrice(1);

    // Collect Rates and Set Shipping & Payment Method

    $shippingAddress=$quote->getShippingAddress();
    $shippingAddress->setCollectShippingRates(true)
        ->collectShippingRates()
        ->setShippingMethod('freeshipping_freeshipping'); //shipping method

    $quote->getShippingAddress()->addShippingRate($this->shippingRate);

    $quote->setPaymentMethod('cashondelivery'); //payment method
    $quote->setInventoryProcessed(true); //not effetc inventory
    $quote->save(); //Now Save quote and your quote is ready

    // Set Sales Order Payment
    $quote->getPayment()->importData(['method' => 'cashondelivery']);

    // Collect Totals & Save Quote
    $quote->collectTotals()->save();

    // Create Order From Quote

    $cartManagementInterface = $objectManager->get('\Magento\Quote\Api\CartManagementInterface');

    $order = $cartManagementInterface->placeOrder($quote->getId());

    //give a result back
    if($order->getEntityId()){
        $result['order_id'] = $order->getEntityId();
    }else{
        $result=['error'=>1,'msg'=>'Your custom message'];
    }

    return $result;
1

I encountered the exact same problem. It was down to the syntax used of certain parts of the process.

Take a look at this.

https://github.com/DominicWatts/Faker/blob/master/Helper/Order.php#L60-L143

    public function createOrder($storeId = 1)
    {
        // bypass Area code not set
        $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance();
        $this->cartManagementInterface = $this->_objectManager->create(CartManagementInterface::class);
        try {
            $store = $this->storeManagerInterface->getStore($storeId);
        } catch (\Exception $e) {
            $this->logger->critical($e);
            return;
        }
        $websiteId = $store->getWebsiteId();
        $customerIds = $this->getRandomCustomerId($websiteId);
        if (empty($customerIds)) {
            new \Exception(__('Please add some customers for this store first'));
        }
        $customer = $this->getCustomerById($customerIds[0]);
        if (!$customer) {
            new \Exception(__('Problem loading customer'));
        }
        $cartId = $this->cartManagementInterface->createEmptyCart(); //Create empty cart
        $quote = $this->cartRepositoryInterface->get($cartId); // load empty cart quote
        $quote->setStore($store);
        $quote->setCurrency();
        $quote->assignCustomer($customer);
        $productIds = $this->getRandomProductId(rand(1, 10));
        if (empty($productIds)) {
            new \Exception(__('Please add some produts for this store first'));
        }
        foreach ($productIds as $productId) {
            $product = $this->getProductById($productId);
            $product->setStore($store);
            $product->setPrice($this->faker->randomFloat(4, 0, 100));
            $quote->addProduct($product, (int) (rand(1, 2)));
        }
        $billingAddress = $this->addressFactory->create()->load($customer->getDefaultBilling());
        $shippingAddress = $this->addressFactory->create()->load($customer->getDefaultShipping());
        $quote->getBillingAddress()->addData($billingAddress->getData());
        $quote->getShippingAddress()->addData($shippingAddress->getData());
        $shippingAddress = $quote->getShippingAddress();
        $shippingAddress->setCollectShippingRates(true)
            ->collectShippingRates()
            ->setShippingMethod('flatrate_flatrate');
        $quote->setPaymentMethod('checkmo');
        $quote->setInventoryProcessed(false);
        $quote->getPayment()->importData(['method' => 'checkmo']);
        try {
            $this->cartRepositoryInterface->save($quote);
        } catch (\Exception $e) {
            $this->logger->critical($e);
            return;
        }
        $quote->collectTotals();
        $quote = $this->cartRepositoryInterface->get($quote->getId());
        try {
            $orderId = $this->cartManagementInterface->placeOrder($quote->getId());
            $this->generateInvoice($orderId);
            if ($this->getRandomTrueOrFalse()) {
                $this->generateShipment($orderId);
            }
            return $orderId;
        } catch (\Exception $e) {
            $this->logger->critical($e);
        }
    }

Very similar to your approach so maybe we followed the same guidelines. There is some extra stuff in with regards to loading customer and generating shipment. Also I used object manager to bypass error as this is used within console script. You don't need those parts. But hopefully you can follow what I did.

  • Thank you so much @Dominic! I´m gonna give it a try – Gonzalo Gutiérrez Jun 12 at 20:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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