Automatically Cancel Order After X Days If No Payment in Woocommerce

Automatically cancel order after X days if no payment in WooCommerce

Update 4

Note: in WooCommerce, there is already a function hooked in woocommerce_cancel_unpaid_orders action hook that cancel unpaid orders after 7 days.

I didn't find woocommerce_cancel_unpaid_submitted action hook, so I don't know if it exist and if it is triggered.

Now there is some mistakes in your code and you can better use wc_get_orders() which give you directly the correct array of WC_Order Objects instead…

Here are some different ways to make it (last ones are untested):

1) This last solution is tested and works When shop manager or administrator user roles browse the Admin orders list (only executed once a day):

add_action( 'restrict_manage_posts', 'cancel_unpaid_orders' );
function cancel_unpaid_orders() {
global $pagenow, $post_type;

// Enable the process to be executed daily when browsing Admin order list
if( 'shop_order' === $post_type && 'edit.php' === $pagenow
&& get_option( 'unpaid_orders_daily_process' ) < time() ) :

$days_delay = 5; // <=== SET the delay (number of days to wait before cancelation)

$one_day = 24 * 60 * 60;
$today = strtotime( date('Y-m-d') );

// Get unpaid orders (5 days old)
$unpaid_orders = (array) wc_get_orders( array(
'limit' => -1,
'status' => 'on-hold',
'date_created' => '<' . ( $today - ($days_delay * $one_day) ),
) );

if ( sizeof($unpaid_orders) > 0 ) {
$cancelled_text = __("The order was cancelled due to no payment from customer.", "woocommerce");

// Loop through orders
foreach ( $unpaid_orders as $unpaid_order ) {
$unpaid_order->update_status( 'cancelled', $cancelled_text );
}
}
// Schedule the process to the next day (executed once restriction)
update_option( 'unpaid_orders_daily_process', $today + $one_day );

endif;
}

Code goes in function.php file of your active child theme (or active theme).


2) This third solution is tested and works: The function is triggered when any order change to "processing" or "completed" status (only executed once a day):

// Triggered on orders status change to "processing" or "completed"
add_action( 'woocommerce_order_status_changed', 'daily_cancel_unpaid_orders', 10, 4 );
function daily_cancel_unpaid_orders( $order_id, $old_status, $new_status, $order ) {
// Enable the process to be executed daily
if( in_array( $new_status, array('processing', 'completed') )
&& get_option( 'unpaid_orders_daily_process' ) < time() ) :

$days_delay = 5; // <=== SET the delay (number of days to wait before cancelation)

$one_day = 24 * 60 * 60;
$today = strtotime( date('Y-m-d') );

// Get unpaid orders (5 days old)
$unpaid_orders = (array) wc_get_orders( array(
'limit' => -1,
'status' => 'on-hold',
'date_created' => '<' . ( $today - ($days_delay * $one_day) ),
) );

if ( sizeof($unpaid_orders) > 0 ) {
$cancelled_text = __("The order was cancelled due to no payment from customer.", "woocommerce");

// Loop through WC_Order Objects
foreach ( $unpaid_orders as $order ) {
$order->update_status( 'cancelled', $cancelled_text );
}
}
// Schedule the process to the next day (executed once restriction)
update_option( 'unpaid_orders_daily_process', $today + $one_day );

endif;
}

Code goes in function.php file of your active child theme (or active theme).


3) So you can try with woocommerce_cancel_unpaid_submitted action hook:

add_action( 'woocommerce_cancel_unpaid_submitted', 'cancel_unpaid_orders' );
function cancel_unpaid_orders() {
$days_delay = 5; // <=== SET the delay (number of days to wait before cancelation)

$one_day = 24 * 60 * 60;
$today = strtotime( date('Y-m-d') );

// Get unpaid orders (5 days old here)
$unpaid_orders = (array) wc_get_orders( array(
'limit' => -1,
'status' => 'on-hold',
'date_created' => '<' . ( $today - ($days_delay * $one_day) ),
) );

if ( sizeof($unpaid_orders) > 0 ) {
$cancelled_text = __("The order was cancelled due to no payment from customer.", "woocommerce");

// Loop through orders
foreach ( $unpaid_orders as $order ) {
$order->update_status( 'cancelled', $cancelled_text );
}
}
}

Code goes in function.php file of your active child theme (or active theme).

The function code should better works. For the hook I really don't know.


4) You can try also with woocommerce_cancel_unpaid_orders action hook instead.

Auto complete order woocommerce

The reference you picked is ok

https://woocommerce.com/document/automatically-complete-orders/

Just needed a small adjustment:

/**
* Auto Complete Processing WooCommerce orders on Thankyou Page
*/
add_action( 'woocommerce_thankyou', 'custom_woocommerce_auto_complete_order' );
function custom_woocommerce_auto_complete_order( $order_id ) {
if ( ! $order_id ) {
return;
}

$order = wc_get_order( $order_id );
if ( $order->has_status('processing') ) {
$order->update_status( 'completed' );
}

}

What we are doing with this adjustment is checking if the order has status processing before updating it to completed. This will avoid failed orders to be turned into completed.

Hope it works

Hide WooCommerce Subscriptions 'cancel' button after 90 days

function remove_cancel_button($actions, $subscription_id) {

// Gets the subscription object on subscription id
$subscription = new WC_Subscription($subscription_id);
$subscription_start_date = $subscription->get_date('start_date');
$subscription_start_date_obj = new \DateTime($subscription_start_date);

$now = new \DateTime();

if ($subscription_start_date_obj->diff($now)->days > 90) {
unset($actions['cancel']);
}

return $actions;
}

add_filter('wcs_view_subscription_actions', 'remove_cancel_button', 10, 2);

Tested OK



Related Topics



Leave a reply



Submit