0

I'm currently working on a module that involves the programmatic cancellation of orders. To cancel orders, I am using $this->orderManagement->cancel($orderId); in my code. This appears to be working correctly as the order status and state change to 'canceled' and the products within the order also seem to be getting canceled appropriately.

However, I have noticed a discrepancy when it comes to the triggering of the sales_order_item_cancel event. When I manually cancel an order by clicking on the 'cancel' button in the order view, this event is invoked, which is what I expect.

The problem arises when an order is canceled programmatically using my module, as this event does not seem to get triggered. This is causing issues since this event is required by other modules to carry out their operations when an order is canceled.

Looking into the source code, I can see that the $this->orderManagement->cancel($orderId); call should trigger the cancel method in \Magento\Sales\Model\Order\Item, which includes the dispatch of the sales_order_item_cancel event $this->_eventManager->dispatch('sales_order_item_cancel', ['item' => $this]);.

This leaves me puzzled as to why this event isn't triggered the same way when orders are canceled programmatically as compared to when they are manually canceled from the admin panel. All the more confusing is that the rest of the cancellation process seems to work as expected, including the restocking of items.

Has anyone else encountered this issue or have any insight on why this might be happening? Any help would be greatly appreciated!

Here is my controller:

<?php
namespace Makey\OrderCancel\Controller\Index;

use Magento\Framework\App\Action\Context;
use Magento\Framework\App\CsrfAwareActionInterface;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\App\Request\InvalidRequestException;
use Magento\Checkout\Model\Session;
use Magento\Sales\Api\OrderManagementInterface;
use Magento\Sales\Api\OrderRepositoryInterface;
use Magento\Framework\Event\ManagerInterface;
use \Psr\Log\LoggerInterface;

class Cancel extends \Magento\Framework\App\Action\Action implements CsrfAwareActionInterface
{

    /**
     * @var Session
     */
    protected $checkoutSession;

    /**
     * @var OrderManagementInterface
     */
    protected $orderManagement;

    protected $orderRepository;
    /**
     * @var logger
     */
    private  $logger;

    /**
     * @var CollectionFactory
     */
    protected $orderCollectionFactory;

    protected $eventManager;

    /**
     * @param Context $context
     * @param OrderManagementInterface $orderManagement
     * @param OrderSender $orderSender
     */
    private $state;

    public function __construct(
        Context $context,
        Session $checkoutSession,
        OrderManagementInterface $orderManagement,
        LoggerInterface $logger,
        OrderRepositoryInterface $orderRepository,
        ManagerInterface $eventManager,
        \Magento\Framework\App\State $state
    ){
        $this->checkoutSession = $checkoutSession;
        $this->orderManagement = $orderManagement;
        $this->orderRepository = $orderRepository;
        $this->logger = $logger;
        $this->eventManager = $eventManager;
        $this->state = $state;
        parent::__construct($context);
    }
    public function execute()
    {
        try {
            $postValue = $this->getRequest()->getPostValue();
            $orderId = $postValue['OrderId'];

            if ($orderId) {
                $order = $this->orderRepository->get($orderId);

                if (!empty($order)) {
//                    $this->orderManagement->cancel($orderId);

                    $this->state->emulateAreaCode(
                        'adminhtml',
                        [$this->orderManagement, 'cancel'],
                        [$orderId]
                    );

                    echo 'OK!';
                } else {
                    $this->logger->info('Order ' . $orderId . ' was not found');
                }
            }

        } catch (\Exception $e) {
            echo 'NOT OK! \n';
            $this->logger->critical($e->getMessage());
            echo $e->getMessage();
        }
    }

    public function createCsrfValidationException(RequestInterface $request): ? InvalidRequestException
    {
        return null;
    }
    public function validateForCsrf(RequestInterface $request): ? bool
    {
        return true;
    }
}

Thank you.

2 Answers 2

1

I have created an Observer for this event sales_order_item_cancel and also create a controller to cancel the product but it is working

So, I think of two possible reasons that

  1. Creating issue with area or scope you have set
  2. Issue with observer code throwing error - sometime error get supress that cause in observer

Thanks

1
  • Thank you @Nilesh for your suggestions. As per your guidance, I tried setting the area by emulating the 'adminhtml' area code. However, the sales_order_item_cancel event still did not trigger. I've included the entire controller code in my initial post. If there are any differences in your working solution, could you please share it? I appreciate your help.
    – makey
    Commented Jun 3, 2023 at 15:36
0

After investigating the issue, I found that the discrepancy was due to the difference in context between the frontend and the admin area, as @Nilesh Dubey suggested. My module was operating in the "frontend" area to receive the POST requests from outside. It was also triggering the sales_order_item_cancel event in this same area. However, another module only listened for the sales_order_item_cancel event in the "admin" area.

Changing the context of the area was not feasible since the area was already set, and attempts to emulate the "admin" area with $this->state->emulateAreaCode() were unsuccessful.

To solve this, I used a workaround. I created my own events.xml file and added a listener for the sales_order_item_cancel event. This allowed the event to be triggered in the desired context.

Thank you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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