I am trying to achieve total number of canceled order when any of the placed order has been canceled by admin area. The problem i am facing that i am getting wrong number of canceled order by difference of 1. It means the order which has been just canceled in this event (order_cancel_after) is not being calculated.

Here is the code below. Any help would be greatly appreciated.

In etc/adminhtml/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="order_cancel_after">
        <observer name="order_cancel_placed_after" instance="My\MyModule\Observer\SalesOrderCancelAfter"/>

In Observer/SalesOrderCancelAfter.php


namespace My\MyModule\Observer;

use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Event\Observer;
use Magento\Sales\Model\Order;
use My\MyModule\Helper\Data;

class SalesOrderCancelAfter implements ObserverInterface

    protected $order;

    protected $helperData;

    public function __construct(
        Order $order,
        Data $helperData
        $this->order = $order;
        $this->helperData = $helperData;

    public function execute(Observer $observer)
        $order = $observer->getEvent()->getOrder();
        $customerEmail = $order->getCustomerEmail();

        /* To get the total number of canceled orders */
        $ordercollection  = $this->order->getCollection()
            ->addAttributeToFilter('customer_email', $customerEmail)
            ->addFieldToFilter('status', array('in' => array('canceled')));
        $totalcancelorder = $ordercollection->getSize();        

This is because the order that is in the cancelation process is not yet saved to the DB, so getting a collection will not include your order because the status in the database is not cancelled.

The easiest solution is manually add your order:

        /* To get the total number of canceled orders */
    $ordercollection  = $this->order->getCollection()
        ->addAttributeToFilter('customer_email', $customerEmail)
        ->addFieldToFilter('status', array('in' => array('canceled')));
    $totalcancelorder = $ordercollection->getSize();   

    if ($observer->getEvent()->getOrder()->getStatus() == 'canceled') {

or just add 1. $totalcancelorder = $ordercollection->getSize() + 1; because the status will always be 'cancelled' because that's how the event works.

| improve this answer | |
  • Thanks for your input. Seems correct to me. But i have a doubt here, should i use this if ($observer->getEvent()->getOrder() == 'canceled') or this if ($observer->getOrder() == 'canceled') – Shahzad H. May 22 '19 at 8:54
  • getOrder() == 'canceled' is 100% wrong. calling getEvent() before getOrder() is correct! is have written my code without testing. i've changed my answer. thanks for your feedback – Philipp Sander May 22 '19 at 8:56
  • Thanks for your valuable investigate. I will accept this answer. – Shahzad H. May 22 '19 at 9:06

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.