1

I am using sales_order_save_after event to change order status. It's working fine for all order status except STATE_COMPLETE. when i set the order status STATE_COMPLETE to make order Complete but it changed to Closed instead of being Complete. Other order States is working fine. The issue only happening when i try to use STATE_COMPLETE.

public function execute(\Magento\Framework\Event\Observer $observer)
{
    $order = $observer->getEvent()->getOrder();
       if($order->getState() != 'complete') {
            $order->setState(\Magento\Sales\Model\Order::STATE_COMPLETE)->setStatus(\Magento\Sales\Model\Order::STATE_COMPLETE);
            $order->save();
       }
}

This is what i'm doing

Can anyone help me out to make order status to "Complete" via observer ?

2
  • Please post your code. Jul 26, 2019 at 6:15
  • @KhoaTruongDinh updated my post.
    – Nayem323
    Jul 26, 2019 at 6:24

3 Answers 3

2

Ok, so the problem was when i set STATE_COMPLETE Magento make the order closed. But if i set STATE_PROCESSING or STATE_PENDING with status Complete then order status show complete but when i view the order details there it show processing/pending. So i tried to figure out when magento make order status complete and it is when a invoice is generated.

So i use checkout_submit_all_after event and create an invoice through my observer. When i create invoice through my observer magento make the order completed because the invoice is generated.

Here's the observer code -

class CheckoutSubmitAllAfter implements ObserverInterface{

protected $_invoiceService;
protected $_transactionFactory;

public function __construct(
  \Magento\Sales\Model\Service\InvoiceService $invoiceService,
  \Magento\Framework\DB\TransactionFactory $transactionFactory
) {
   $this->_invoiceService = $invoiceService;
   $this->_transactionFactory = $transactionFactory;
}

public function execute(\Magento\Framework\Event\Observer $observer)
{
    $order = $observer->getEvent()->getOrder();

    try {
        if(!$order->canInvoice()) {
            return null;
        }
        if(!$order->getState() == 'new') {
            return null;
        }

        $invoice = $this->_invoiceService->prepareInvoice($order);
        $invoice->setRequestedCaptureCase(\Magento\Sales\Model\Order\Invoice::CAPTURE_ONLINE);
        $invoice->register();

        $transaction = $this->_transactionFactory->create()
          ->addObject($invoice)
          ->addObject($invoice->getOrder());

        $transaction->save();

    } catch (\Exception $e) {
        $order->addStatusHistoryComment('Exception message: '.$e->getMessage(), false);
        $order->save();
        return null;
    }
}}
2
  • where did you set order status to 'complete'?
    – huykon225
    Aug 19, 2021 at 8:08
  • You don't have to set it. It will be complete automatically.
    – Nayem323
    Aug 20, 2021 at 5:27
1

Please try following code:

use \Magento\Sales\Model\Order;

public function execute(\Magento\Framework\Event\Observer $observer)
{
    $order = $observer->getEvent()->getOrder();

    if($order->getState() != Order::STATE_COMPLETE) {

        $orderState = Order::STATE_COMPLETE;

        // set order status to COMPLETE
        $order->setState($orderState)->setStatus(Order::STATE_COMPLETE);

        // Save order
        $order->save();
    }
}

Hope it Works!

5
  • Not working order status showing closed
    – Nayem323
    Jul 26, 2019 at 8:13
  • @RaselUddin can you change order status to complete by manually for any single order and check what status it displays.
    – KKR
    Jul 26, 2019 at 9:53
  • If i manually change it show complete
    – Nayem323
    Jul 26, 2019 at 9:58
  • @RaselUddin can you please check order status in backend Stores->Settings->Order Status.
    – KKR
    Jul 26, 2019 at 10:02
  • yes everything is fine there. Please see i answered my ques how i solved it.
    – Nayem323
    Jul 26, 2019 at 10:18
1

Please take note that invoking the the save method of the order would trigger a state check which might explain why you are experiencing the issue.

Magento 2 has a separate class for checking the order state.

In the Magento\Sales\Model\ResourceModel\Order class you will find the save method invoking state check

public function save(\Magento\Framework\Model\AbstractModel $object)
    {
        /** @var \Magento\Sales\Model\Order $object */
        $this->stateHandler->check($object);
        return parent::save($object);
    }

The stateHandler is an instance of Magento\Sales\Model\ResourceModel\Order\Handler\State

I would recommend that you have a look that the method "check" to trace the logic flow.

You could either override the method check or create a plugin aroundCheck to change the state logic flow

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.