We found that we sometimes run out of stock/inventory due to orders pending payment. In our case, when the customer cancels PayPal payment, or doesn't pay through Bank Deposit.

Is there a way to "release" those stock/inventory after a specified amount of time, automatically, without us having to check regularly for orders pending payment and cancelling manually?

We realize there are extensions that do this, but was wondering if there's a built-in way in Magento to do it.

3 Answers 3


I would not delete the order but just cancel them and with a cronjob (either a script or Magento extension) you can do this. Run it daily to clean up the orders. Results are logged to var/logs/cancelorders.log for reference.

$collection = Mage::getModel('sales/order')->getCollection()
    ->addFieldToFilter('updated_at', Mage::getModel('core/date')->gmtDate(null, time()-86400)) // only clean yesterdays orders so user has time to restart transaction
    ->addFieldToFilter('state', 'pending_payment');

foreach ($collection as $order)
   try {
      Mage::log("Canceled {$order->getIncrementId()}", Zend_Log::INFO, 'cancelorders.log', true);
   } catch(Exception $e){
      Mage::log("Could not cancel order {$order->getIncrementId()}: {$e}", Zend_Log::WARN, 'cancelorders.log', true);
  • Hmmm using something similar and works - only not if customer goes back and forth in checkout within several minutes. In this case you would have to check it "on the fly" and before getting stock cancel previous existing orders ... seems like a difficult case. Have fun in vegas.
    – snh_nl
    Commented Mar 24, 2019 at 13:21

There is no built in way of doing this. You can simply create a cron that calls the following code (or something similar).

$olderThan = 21;//21 days
$date = date('Y-m-d', mktime(0,0,0, date('m'), date('d') - $olderThan, date('Y')));
//get orders with no update in the last 21 days
$orders = Mage::getModel('sales/order')->getCollection()
    ->addFieldToFilter('state', 'pending_payment')
    ->addFieldToFilter('updated_at', array('lt'=>$date)); //you can use created_at instead of updated_at.
foreach ($orders as $order){

I also read a Magento tutorial about this issue on Inchoo.net

You can get some useful instructions from it:


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.