6

I want to observe every order state change and react depending on the old and new status. What is the best way to accomplish this in Magento 2?

It looks like there is the event sales_order_state_change_before but unfortunately it does not seem to fire on state changes. There is also a considerable list of other events which fire in some cases of order changes:
sales_order_invoice_pay
sales_order_payment_place_end
sales_order_payment_capture
sales_order_payment_pay
... just to name a few.

However I'm not exactly sure when which of above events fire and it definitely looks like they only fire in very special occasions. But I need a way which guaranteed covers all state changes and allows me to query the old and new status.
What is the best way to achieve this, am I missing an event or is there a better way than registering an observer?

10

As far as I know, we can use events: sales_order_save_after and sales_order_state_change_before. I refer sales_order_save_after event.

In our observer, we can get the state of order:

Observer/SalesOrderAfterSave.php

public function execute(\Magento\Framework\Event\Observer $observer)
{
    $order = $observer->getEvent()->getOrder();
    if ($order instanceof \Magento\Framework\Model\AbstractModel) {
       if($order->getState() == 'canceled' || $order->getState() == 'closed') {
            //Your code here
       }
    }
    return $this;
}

We can read more about observer : Magento 2 events list

NOTE: We should try with Plugin:

etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">

    <type name="Magento\Sales\Api\OrderRepositoryInterface">
        <plugin name="order_state_plugin"
                type="Company\Module\Model\Plugin\OrderStatePlugin"/>
    </type>

</config>

Plugin:

/**
 * @param \Magento\Sales\Api\OrderRepositoryInterface $subject
 * @param \Magento\Sales\Api\Data\OrderInterface $result
 * @return mixed
 * @throws \Exception
 */
public function afterSave(
    \Magento\Sales\Api\OrderRepositoryInterface $subject,
    $result
) {
    if($result->getState() == Order::STATE_COMPLETE) {
        ......
    }
    return $result;
}
  • This is better than the events I knew of so far but it is not firing when the customer creates the order with an initial "pending" state. I'm not sure if there are more cases where it is not triggered. By the way, do you know of a complete Magento 2 event list? Mine seems incomplete. – Jey DWork Jul 11 '16 at 15:15
  • 1
    Regarding the list, there is already a topic: magento.stackexchange.com/questions/87738/magento-2-events-list – Jey DWork Jul 11 '16 at 15:21
  • As far as I know, by default, Magento doesn't have pending state, it's a status. There are some default states: new, pending_payment, processing, complete, closed, canceled, holded, payment_review. We should take a look vendor/magento/module-sales/Model/Order.php – Khoa TruongDinh Jul 11 '16 at 15:28
  • You are completely right, the state I was referring to is new ("Pending" is what it says in the Backend). And I'm still having a hard time to react to newly placed orders by customers. sales_order_place_after is not firing and all my other attempts aren't as well. One should guess this is a basic task :/ – Jey DWork Jul 11 '16 at 19:24
  • Okay so that was really my bad. I forgot the different XML hierarchy in Magento 2 and my events.xml was still placed in /etc/adminhtml/ of my module. Moving it to /etc/ worked. Now sales_order_save_after also fires when customers create orders. And from my short testing now with other here mentioned events it is better in the sense that it provides more information about the order. sales_order_place_after for example doesn't know of the order's ID yet. So sales_order_save_after really seems to be the event I was looking for! – Jey DWork Jul 11 '16 at 20:01

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.