Reputation: 13
In Woocommerce, I am trying to auto complete processing orders based on their total amount.
For the moment I have this code that is auto-completing all orders with processing status:
add_action( 'init', 'auto_update_orders_status_from_processing_to_completed' );
function auto_update_orders_status_from_processing_to_completed(){
// Get all current "processing" customer orders
$processing_orders = wc_get_orders( $args = array(
'numberposts' => -1,
'post_status' => 'wc-processing',
) );
if(!empty($processing_orders))
foreach($processing_orders as $order)
$order->update_status( 'completed' );
}
How can I make this code work only for orders that have a total amount less than $50
?
Upvotes: 1
Views: 623
Reputation: 253814
Instead of using the init
hook, you should try to use one of the following functions, that will auto-complete processing orders that have a total amount less than $50 (for example):
1) Using woocommerce_order_status_processing
action hook (the best choice):
add_action( 'woocommerce_order_status_processing', 'auto_complete_processing_orders_based_on_total', 20, 4 );
function auto_complete_processing_orders_based_on_total( $order_id, $order ){
// HERE define the max total order amount
$max_total_limit = 50;
if ( $order->get_total() < $max_total_limit ) {
$order->update_status( 'completed' );
}
}
Code goes in function.php file of your active child theme (active theme). Tested and works.
2) Using woocommerce_thankyou
action hook (good alternative if your orders are always in processing status):
add_action( 'woocommerce_thankyou', 'thankyou_auto_complete_processing_orders_based_on_total', 90, 1 );
function thankyou_auto_complete_processing_orders_based_on_total( $order_id ){
if( ! $order = wc_get_order( $order_id ) ){
return;
}
// HERE define the max total order amount
$max_total_limit = 50;
if( $order->has_status('processing') && $order->get_total() < $max_total_limit ){
$order->update_status( 'completed' );
}
}
Code goes in function.php file of your active child theme (active theme). Tested and works.
A) The lightest and efficient way with a direct SQL query using init
hook (the best way):
add_action( 'init', 'sql_auto_complete_processing_orders_based_on_total' );
function sql_auto_complete_processing_orders_based_on_total(){
// HERE define the max total order amount
$max_total_limit = 50;
global $wpdb;
// Very light bulk update direct SQL query
$orders_ids = $wpdb->query("
UPDATE {$wpdb->prefix}posts as a
JOIN {$wpdb->prefix}postmeta AS b ON a.ID = b.post_id
SET a.post_status = 'wc-completed'
WHERE a.post_status = 'wc-processing'
AND b.meta_key = '_order_total' AND b.meta_value < '$max_total_limit'
");
}
Code goes in function.php file of your active child theme (active theme). Tested and works.
B) Based on your code using init
hook (Very heavy, but more compatible with future database structure changes in woocommerce, if it happen one day):
add_action( 'init', 'init_thankyou_auto_complete_processing_orders_based_on_total' );
function init_thankyou_auto_complete_processing_orders_based_on_total(){
// HERE define the max total order amount
$max_total_limit = 50;
// Get all processing orders
$orders = wc_get_orders( array( 'limit' => -1, 'status' => 'processing') );
if( sizeof($orders) > 0 ) {
// loop through processing orders
foreach( $orders as $order ) {
if( $order->get_total() < $max_total_limit ) {
$order->update_status( 'completed' );
}
}
}
}
Code goes in function.php file of your active child theme (active theme). Tested and works.
Related: WooCommerce: Auto complete paid Orders (depending on Payment methods)
Upvotes: 1