Automatically cancel pending orders older than 90 minutes

There are situations where you might with to automatically cancel orders older than 90 minutes. They stay in “pending_payment” state. This usually happen when the customer didn’t complete the checkout due any reason.
We created observer class “Inchoo_Order_Model_Observer” with public method “cancelPendingOrders“.
We are calling this method over cron script, take a look at our config.xml file below and everting will be clear.
In this method we filtered orders which have state “pending_payment” and older than 90 minutes. Also we set limit to 10 orders, because we want to process them in one loop.
Before save order we set new order state to “canceled_pendings“. All canceled orders will have new state “canceled_pendings“.
class Inchoo_Order_Model_Observer
{
public function cancelPendingOrders()
{
$orderCollection = Mage::getResourceModel('sales/order_collection');
$orderCollection
->addFieldToFilter('state', 'pending_payment')
->addFieldToFilter('created_at', array(
'lt' => new Zend_Db_Expr("DATE_ADD('".now()."', INTERVAL -'90:00' HOUR_MINUTE)")))
->getSelect()
->order('e.entity_id')
->limit(10)
;
$orders ="";
foreach($orderCollection->getItems() as $order)
{
$orderModel = Mage::getModel('sales/order');
$orderModel->load($order['entity_id']);
if(!$orderModel->canCancel())
continue;
$orderModel->cancel();
$orderModel->setStatus('canceled_pendings');
$orderModel->save();
}
}
}
Below you can see chunk of config.xml file where we set cron execution every 5 minutes.
<crontab>
<jobs>
<order_cancel_orders>
<schedule><cron_expr>*/5 * * * *</cron_expr></schedule>
<run><model>order/observer::cancelPendingOrders</model></run>
</order_cancel_orders>
</crontab>
</config>
That’s it 😉
45 comments
Hello,
Thank you for the nice post.
For Magento2 I found the nice extension http://shreejiinfosys.co.in/auto-cancel-order-magento-2.html
In cpanel the cron command will look like this only?- order/observer::cancelPendingOrders
How can this be implemented in 1.9.2 version. I am unable to cancel any pending_payment order as invoice has already generated. How to stop invoicing for pending_payment order and cancel them if required.
Stock quantity should be released on cancellation.
Thanks
AWesome! Now I don’t need to buy an extension worth $99.00 for this function. 😀
Nice tutorial! I really wanted this in my shop!
I will keep checking your blog for more of the tutorials.. please do update it.
Thank you for all ur post. It really helped me with my e-shop. Keep the great job
Regards
Thanks for this excellent tutorial. Just a quick heads up:
The snippet for the crontab is missing a closing jobs tag. 🙂
Hi! Would this work on magento 1.9? Does it re-stock items or just cancels the order? Thanks in advance.
HI,
How about sending an email to the order customer to notify that the order has been pending for too long before canceling the order? Any help with the email sending part of the code?
How to remove pending order?
is there anything like this (auto cancelled order) that work for offline accounting software?
@Artega : I have copied all files and enabled the plugin through backend too.
However my pending orders are not going to canceled orders state after every 10 mins (configured 10 mins as cron setting to test).
I am using version 1.7 . Is there anything else to be done besides copying the files and folders and enabling the plugin through backend?
This module is not working for 1.9.1.0 version
thanks for the code but when it cancels the order it doesn’t stock the items back into system.
Is there something you can guide me to please.
Regards
Hi,
We’ve been indded struggling for ages with orders that are left pending and polluting the backend while decreasing stock for items that will never be shipped!
So to address this problem, we have developped a community / free extension that makes automatic order cancellation so easier (I guess!).
I would be very happy to learn that Inchoo’s readers found a ready-to-use way to manage this automatic order cancellation and, dear Inchooers, please feel free to use, reuse, modify the source code or even discuss it!
You may find this extension here :
http://www.magentocommerce.com/magento-connect/soon-stockreleaser-annuler-automatiquement-les-commandes-impayees-6365.html
Have fun magentoing!
hi,
How to generate a cron, in Magento ?
Hi everybody ,
how to generate sms pending and cancel order after time Interval 15 min.
Everyone having problem
exception ‘PDOException’ with message ‘SQLSTATE[42S22]: Column not found: 1054 Unknown column ‘e.entity_id’ in ‘order clause”
as Longboard
just put entity_id instead of e.entity_id
Thanks, this has solved the previous issue (I am using 1.3.2.4) – I can see ‘ordermonitor_cron’ entries which are now successful. Despite this, I believe the script is cancelling the wrong orders rather than the ones with a status of ‘Pending Payment’. Please see below:
3 Oct 2011 15:38:27 | Canceled
Customer Not Notified
Payment expired.
3 Oct 2011 15:38:27 | Complete
Customer Not Notified
2 Oct 2011 23:08:44 | To be Processed
Customer Not Notified
0000 : The Authorisation was Successful.
The script appears to cancel ‘To be processed’ orders instead – first completing them then cancelling immediately afterwards. Is there something I’m doing wrong here?
You are probably using Magento 1.3 which is not compatible with initial release. Try latest version from here https://github.com/artega/OrderMonitor/zipball/v1.1.2 it should fix the problem for good. After you apply the update, go to module configuration and save settings again. Remember to test it in development enviroment first.
Ahh, now here I have several rows, either with a status of ‘pending’ and a message of NULL, or the more interesting one with a status of ‘error’ with the following message:
Invalid method Mage_Sales_Model_Order::addStatusHistoryComment(Array
(
[0] => Payment expired.
)
)
Chris, check cron_schedule table in your database whether there are any rows with ordermonitor_cron in job_code column. For example, execute
I’ve set it to ‘Yes’, and I’ve set up a script to log whenever the cron is running, which shows that it’s running every 15 minutes.
Really weird, don’t know why it isn’t working…
Chris, make sure your cron is working besides check module configuration in System->Configuration->Sales->OrderMonitor because pending payments are set to cancel after 60 minutes by default!
Johan, you have to put yourself in the queue, but seriously weblog in not the right place for that. You can find my personal email at github here https://github.com/artega/OrderMonitor/blob/master/AUTHORS … use it if you want to make an offer 😉
I’ve cancelled all the backlogged pending orders now, realised it was the better option!
I’ve installed your module and for some reason it still isn’t playing ball – I placed a pending order at 12.11pm and it hasn’t been cancelled as of yet.
Is there any way to track what is going wrong for me?
How much $ do you want to make it now ? 🙂
Johan, I will include that feature in next release.
Artega, thanks for the extension!
Is there anyway to use this code to add a new canceled state like “canceled – pending” too keep track of wich are canceled through the extension (and makes it possible to use that other canceled state like i asked before..)
/Johan
Chris, I suggest that you deal with old orders as soon as possible because if you delay, the problem will be bigger and it will bite you sooner or later. Avoiding the problem is NOT a solution 🙂
Thanks artega this seems like it’s just what I’m looking for.
One thing I was hoping to do though was to only cancel pending order which had occured on the current date (I have many backlogged pending orders which would drastically affect my stock count if they were now cancelled).
I assume I just need an extra filter in the cron – could you help with this?
For those of you who struggle with this issue, I created a custom module which works out of the box. The source is available here https://github.com/artega/OrderMonitor
You can download it from github at https://github.com/artega/OrderMonitor/zipball/v1.0.0
it is 404 page not found
please.
can you please re-upload this
Hi,
I have a question after reading this post.
Is it possible to create a new Order Status that are exactly like the Canceled state, but with another name, something like Canceled2 or whatever.
The reason i want this i because i want pending online payment orders to be “canceled2” until the payment is finished and the order status is moved forward to processing. This is because in low stock quantity situtation the item can look like its out of stock if the customer goes back to the store to choose another payment method.
Any hint if this is even possible would be appreciated!
Regards
Johan
config.xml
But some other error on execution:
exception ‘PDOException’ with message ‘SQLSTATE[42S22]: Column not found: 1054 Unknown column ‘e.entity_id’ in ‘order clause”
0.1.0
Corp_Order_Model
*/5 * * * *
order/observer::cancelPendingOrders
Yes I agree. I don’t know very much of config.xml. A step by step example would really help. I’m learning as i go.
I really really want this in my shop, but i don’t know where to put the code snippets..
Please do update the post with locations or full files to put into the code.
example of config.xml file is chunk of code, you have to add other elements, blocks, models, helpers and so on.
Author assumed that you know what is “config.xml” file and what it contains…..
Hi!!
The same as Joel happens to me, any help please??
Thank you!!
Can some one tell me what Im doing wrong?
app/etc/modules/ Inchoo_Order.xml
app/code/local/ Inchoo / Order/etc/config.xml
app/code/local/ Inchoo / Order /Model/ Observer.php
Any help would be greatly appreciated! 🙂
Hi Anton,
I corrected the post.
Thank you for comment, I made mistake. It should use php time.
Please, instead of
new Zend_Db_Expr(“DATE_ADD(now(), INTERVAL -’90:00′ HOUR_MINUTE)”)
put:
new Zend_Db_Expr(“DATE_ADD(‘”.now().”‘, INTERVAL -’90:00’ HOUR_MINUTE)”)
😉
Thank you Spelling Nazi for the note. The title is corrected.
maybe you should ‘automaticaly’, learn how to spell ‘automatically’…
Cool. But this might just fail if mysql and magento are set to different (default) timezone?