5

I'm trying to execute cron job after customer click place order button and redirect to success page. So the purpose of my job, if admin did not respond the order in 3 days, the order status will automatically canceled.

I have override the \Magento\Checkout\Controller\Onepage\Success in my module and use execute function to run my job via terminal.

<?php namespace Mymodule\Checkout\Controller\Onepage;

class Success extends \Magento\Checkout\Controller\Onepage\Success
{
    /**
     * Order success action
     *
     * @return \Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {
        exec('php bin/magento cron:run --group="custom"');
        return parent::execute();
    }
}

Here is crontab.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/crontab.xsd">
    <group id="custom_group">
        <job name="test_cronjob" instance="Mymodule\Checkout\Cron\CancelOrder" method="execute">
            <schedule>* * */3 * *</schedule>
        </job>
    </group>
</config>

Here is CancelOrder.php

<?php namespace Mymodule\Checkout\Cron;

class CancelOrder {
    protected $orderFactory;

    protected $checkoutSession;

    public function __construct(
        \Magento\Sales\Model\OrderFactory $orderFactory,
        \Magento\Checkout\Model\Session $checkoutSession
    ){
        $this->orderFactory = $orderFactory;
        $this->checkoutSession = $checkoutSession;
    }

    public function execute() {
        $orderId = $this->checkoutSession->getLastOrderId();
        if (!empty($orderId)) {
            $order = $this->orderFactory->create();
            $order->load($orderId);

            if ($order->getStatus() == 'pending') {
                $order->setState('canceled');
                $order->setStatus('canceled');

                $order->save();

                // send email to customer
            } else {
                return 0;
            }
        }
    }
}

When i try place order, the job is not executed. Is there something wrong with my code?

  • 1
    I will suggest you to use an observer. Observe, if the order successfully placed then execute a cron from config.xml. It much better than yours. – Tonmoy Feb 27 '17 at 11:39
  • Why not run cron each day and filter past 3 days orders if found cancel those orders. why do you want to run cron command in success ? – Priyank Feb 27 '17 at 12:31
7

From my understanding, you want to cancel the orders which are older than 3 days. In this case, we need to create the Cron job. So, we will compare the current date with the created date (take a look table sales_order, find the column created_at).

We should use Service Contracts Layer:

  • \Magento\Sales\Api\OrderRepositoryInterface $orderRepository and \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder are used for getting the order items.

  • \Magento\Sales\Api\OrderManagementInterface is used for canceling order.

Our Cron:

namespace Mymodule\Checkout\Cron;

class CancelOrder
{
    /**
     * @var \Magento\Sales\Api\OrderRepositoryInterface
     */
    protected $orderRepository;
    /**
     * @var \Magento\Framework\Api\SearchCriteriaBuilder
     */
    protected $searchCriteriaBuilder;

    /**
     * @var \Magento\Sales\Api\OrderManagementInterface
     */
    protected $orderManagement;

    /**
     * CancelOrder constructor.
     * @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository
     * @param \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder
     * @param \Magento\Sales\Api\OrderManagementInterface $orderManagement
     */
    public function __construct(
        \Magento\Sales\Api\OrderRepositoryInterface $orderRepository,
        \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder,
        \Magento\Sales\Api\OrderManagementInterface $orderManagement
    )
    {
        $this->orderRepository = $orderRepository;
        $this->searchCriteriaBuilder = $searchCriteriaBuilder;
        $this->orderManagement = $orderManagement;
    }

    public function execute()
    {
        $agoDate = '2016-11-07'; // For example date, your logic to calculate the date here
        $searchCriteria = $this->searchCriteriaBuilder
        ->addFilter(
            'created_at',
            $agoDate,
            'gt'
        )->addFilter(
           'status'
           'pending'
           'eq'
        )->create();

        $orders = $this->orderRepository->getList($searchCriteria);
        foreach ($orders->getItems() as $order) {
                $this->orderManagement->cancel($order->getEntityId()); // Cancel Order
        };

    }
}

You should set your Cron runs every minute: https://crontab.guru/

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/crontab.xsd">
    <group id="custom_group">
        <job name="test_cronjob" instance="Mymodule\Checkout\Cron\CancelOrder" method="execute">
            <schedule>* * * * *</schedule>
        </job>
    </group>
</config>

NOTE: You can test your custom Cron directly: https://magento.stackexchange.com/a/152812/33057

  • Thanks for your answer. May i know what is the meaning of 'gt' and 'eq' in addFilter section? – Seventh St Feb 28 '17 at 2:02
  • Ahh, greater than and equal. right. – Seventh St Feb 28 '17 at 2:05
  • Yeah, you're right! – Khoa TruongDinh Feb 28 '17 at 2:46
  • You also can test your Cron directly: magento.stackexchange.com/a/152812/33057 – Khoa TruongDinh Feb 28 '17 at 2:53
  • I still confused about how i run cron job automatically. Apparently i use terminal to run my group bin/magento cron:run --group="custom_group" – Seventh St Feb 28 '17 at 7:15
0

Create your own cron job that will automatically cancel orders older than 3 days filtered by order status.

  • I have created it.. Should i put them in my question? – Seventh St Feb 27 '17 at 12:05
  • Have you also setup your crontab to run Magento cron? Yes put more information with your code. – Jonathan Ribas Feb 27 '17 at 12:07
  • I have updated my question. – Seventh St Feb 27 '17 at 12:10
  • Forget Success rewrite and on your cron model filter for orders older than 3 days with status pending and then cancel them. – Jonathan Ribas Feb 27 '17 at 12:18

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.