Question

Created a custom form where customer and product details filled with status of Active/Not active So for now I want to create an event and observer to place order programmatically when status is Active from admin panel, place order on the bases of customer, product

Was it helpful?

Solution

Created custom event for this

events.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="trigger_order_place">
        <observer name="vtn_order_success" instance="Vtn\Investment\Observer\Orderplace" />
    </event>
</config>

Here I am getting data dynamically for place order programatically, you can use static values or get your data as per your collection observer -> Orderplace.php

<?php
namespace Vtn\Investment\Observer;

use \Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;

class Orderplace implements ObserverInterface
{
    /**
    * @param Magento\Store\Model\StoreManagerInterface $storeManager,
    * @param Magento\Customer\Model\CustomerFactory $customerFactory,
    * @param Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
    * @param Magento\Customer\Api\CustomerRepositoryInterface $customerRepository,
    * @param Magento\Quote\Model\QuoteFactory $quote,
    * @param Magento\Quote\Model\QuoteManagement $quoteManagement,
    * @param Magento\Sales\Model\Order\Email\Sender\OrderSender $orderSender,
    * @param Magento\Sales\Model\Order $orderCollectionFactory,
    * @param Vtn\Investment\Model\InvestmentFactory $investmentFactory
    */

    public function __construct(
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Customer\Model\CustomerFactory $customerFactory,
        \Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
        \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository,
        \Magento\Quote\Model\QuoteFactory $quote,
        \Magento\Quote\Model\QuoteManagement $quoteManagement,
        \Magento\Sales\Model\Order\Email\Sender\OrderSender $orderSender,
        \Magento\Sales\Model\Order $orderCollectionFactory,
        \Vtn\Investment\Model\InvestmentFactory $investmentFactory
    ){
        $this->storeManager = $storeManager;
        $this->customerFactory = $customerFactory;
        $this->productRepository = $productRepository;
        $this->customerRepository = $customerRepository;
        $this->quote = $quote;
        $this->quoteManagement = $quoteManagement;
        $this->orderSender = $orderSender;
        $this->orderCollectionFactory = $orderCollectionFactory;
        $this->investmentFactory = $investmentFactory;
    }

    public function execute(Observer $observer)
    {
        $collection = $observer->getEvent()->getCollection();
        $collectionData = $collection->getData();
        $Approve = $collection->getActive();
        $investmentId = $collection->getId();
        $customerId = $collection->getCustomerId();
        $vtnOrderId = $collection->getOrderId();
        $customerModel = $this->customerRepository->getById($customerId);
        $currency = $this->storeManager->getStore()->getCurrentCurrency();

        // cencel order if investment discard
        if($Approve == '0' && $vtnOrderId != ''){
            $order = $this->orderCollectionFactory->load($vtnOrderId);
            $order->cancel()->save();

            $productInvest = $this->investmentFactory->create()->getCollection()->addFieldToFilter('id', $investmentId);
            foreach($productInvest as $data){
                $models = $this->investmentFactory->create()->load($data->getId());
                $models->setOrderId(''); 
                $models->save();
            }
        }

        // create order when user approve investment request
        if($Approve == '1' && $vtnOrderId == ''){            
            foreach ($customerModel->getAddresses() as $address) {
                $orderInfo =[
                    'currency_id'  => $currency,
                    'email'        => $collection->getCustomerEmail(),
                    'address' =>[
                        'firstname' => $address->getFirstname(),
                        'lastname' => $address->getLastname(),
                        'prefix' => $address->getPrefix(),
                        'suffix' => $address->getSuffix(),
                        'street' => $address->getStreet(),
                        'city' => $address->getCity(),
                        'country_id' => $address->getCountryId(),
                        'region' => $address->getRegion(),
                        'region_id' => $address->getRegionId(),
                        'postcode' => $address->getPostcode(),
                        'telephone' => $address->getTelephone(),
                        'fax' => $address->getFax(),
                        'save_in_address_book' => 1
                    ],
                    'items'=>
                        [
                            ['product_id'=> $collection->getProductId(),'qty'=>1],
                        ]
                ];
            }
            $store = $this->storeManager->getStore();
            $storeId = $store->getStoreId();
            $websiteId = $this->storeManager->getStore()->getWebsiteId();
            $customer = $this->customerFactory->create();
            $customer->setWebsiteId($websiteId);
            $customer->loadByEmail($orderInfo['email']);// load customet by email address
            
            $quote=$this->quote->create(); //Create object of quote
            $quote->setStore($store); //set store for our quote
            $customer= $this->customerRepository->getById($customer->getId());
            $quote->setCurrency();
            $quote->assignCustomer($customer); //Assign quote to customer
    
            //add items in quote
            foreach($orderInfo['items'] as $item){
                $product=$this->productRepository->getById($item['product_id']);
                if(!empty($item['super_attribute']) ) {
                    /* for configurable product */
                    $buyRequest = new \Magento\Framework\DataObject($item);
                    $quote->addProduct($product,$buyRequest);
                } else {
                    /* for simple product */
                    $quote->addProduct($product,intval($item['qty']));
                }
            }
    
            //Set Billing and shipping Address to quote
            $quote->getBillingAddress()->addData($orderInfo['address']);
            $quote->getShippingAddress()->addData($orderInfo['address']);
    
            // set shipping method
            $shippingAddress=$quote->getShippingAddress();
            $shippingAddress->setCollectShippingRates(true)
                            ->collectShippingRates()
                            ->setShippingMethod('freeshipping_freeshipping'); 
                            //shipping method, please verify free shipping must be enable
            $quote->setPaymentMethod('checkmo'); 
            //payment method, please verify checkmo must be enable from admin
            $quote->setInventoryProcessed(false); 
            //decrease item stock equal to qty
            $quote->save();  //quote save 
            // Set Sales Order Payment, We have taken check/money order
            $quote->getPayment()->importData(['method' => 'checkmo']);
    
            // Collect Quote Totals & Save
            $quote->collectTotals()->save();
            // Create Order From Quote Object
            $order = $this->quoteManagement->submit($quote);
            /* for send order email to customer email id */
            $this->orderSender->send($order);
            /* get order real id from order */
            $orderId = $order->getIncrementId();

            // Investment order column to yes 
            $order = $this->orderCollectionFactory->load($orderId);
            $order->setInvestmentOrder(1);
            $order->save();

            // save order id in vtn_investment_req table
            $productInvest = $this->investmentFactory->create()->getCollection()->addFieldToFilter('id', $investmentId);
            foreach($productInvest as $data){
                $models = $this->investmentFactory->create()->load($data->getId());
                $models->setOrderId($orderId); 
                $models->save();
            }

            if($orderId){
                $result['success']= $orderId;
            }else{
                $result=['error'=>true,'msg'=>'Something Went Wrong During Order Placement'];
            }
            return $result;
        }
        return $this;
    }
}

Controller where event is dispatch Save.php

public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Framework\View\Result\PageFactory $resultPageFactory,
        \Vtn\Investment\Model\InvestmentFactory $investmentFactory,
        EventManager $eventManager
    )
    {
        $this->resultPageFactory = $resultPageFactory;
        $this->investmentFactory = $investmentFactory;
        $this->eventManager = $eventManager;
        parent::__construct($context);
    }

    public function execute()
    {
        $resultRedirect = $this->resultRedirectFactory->create();
        $data = $this->getRequest()->getPostValue();
        $id = $data['id'];
        
        if($data)
        {
                $id = $data['id'];
                $investment = $this->investmentFactory->create()->load($id);
                $data = array_filter($data, function($value) {return $value !== ''; });
                $collection = $investment->setData($data);

                // dispatch custom event for order place
                $this->eventManager->dispatch('trigger_order_place',['collection' => $collection]);

                $investment->save();
                $this->messageManager->addSuccess(__('Successfully saved the item.'));
                $this->_objectManager->get('Magento\Backend\Model\Session')->setFormData(false);
                return $resultRedirect->setPath('*/*/');
            }

OTHER TIPS

1)Create event.xml file:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="sales_order_place_after">
        <observer name="neo_ordercomment_observer_orderneo" instance="vendor\module\Observer\Orderneo" />
    </event>
</config>

2)Create PlaceOrder.php file in Observer directory:

<?php

namespace Vendor\Module\Observer;

class PlaceOrder implements \Magento\Framework\Event\ObserverInterface
{
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $order= $observer->getData('order');
        $comment = $this->getRequest()->getParams('comment');
        print_r("Catched event succssfully !"); exit;
    }
}

May be these articles can help you, as I think you have built a custom module already to fill the customer and product details, I know you asked for event, but if its custom module, you will have to create your own event using dispatch event:

https://webkul.com/blog/create-quote-and-order-programmatically-in-magento2/

https://www.mageplaza.com/devdocs/magento-2-create-order-programmatically.html

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top