2

The objective is to get/query/loop through all orders which have order_status "Processing", and if they have no items in backorder, update an advanced custom field 'internal_status' to value 'Ready to Pack'

Right now for a method of testing (to keep it simple and see if it's working) I am just trying to update the custom field whenever an order is passed to status "Completed" (no condition for "items in backorder" yet)

Based on Auto completed status for all existing processing orders in WooCommerce answer code, here is my code attempt:

function auto_update_orders_internal_status(){
     // 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)
        
   add_action('acf/save_post', 'update_internal_status_ready_to_pack');
            
}

add_action( 'woocommerce_order_status_completed', 'auto_update_orders_internal_status' );



function update_internal_status_ready_to_pack ( $order_id ) {
    
    $internalstatus = 'Ready to Pack';
    update_field( 'internal_status', $internalstatus, $order_id );

}

One thing I am aware I don't fully grasp here is the method of querying / getting all orders on "Processing status" and updating their corresponding fields.

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
Jaime Matos
  • 343
  • 1
  • 14

1 Answers1

2

You should try instead the following lightweight and effective way (with a custom function that uses a WPDB SQL query, to query all order Ids that have not backordered items):

/*
 * Custom function that query all orders without backordered items
 *
 * @param  bool|string $status  Order status can be defined (optional)
 * @return array
 */
function get_orders_ids_without_backordered_items( $status = false ) {
    global $wpdb;

    $post_status_query = $status ? "AND p.post_status = 'wc-" . str_replace('wc-', '', $status) . "'" : '';

    return (array) $wpdb->get_col( "
        SELECT p.ID
        FROM {$wpdb->prefix}posts p
        WHERE p.ID NOT IN (
            SELECT DISTINCT oi.order_id FROM {$wpdb->prefix}woocommerce_order_items oi
            INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta oim ON oi.order_item_id = oim.order_item_id
            WHERE oim.meta_key = 'Backordered'
        ) $post_status_query
    " );
}

// Update ACF 'internal_status' custom field on processing orders.
add_action( 'woocommerce_order_status_completed', 'auto_update_orders_internal_status', 10, 2 ); // Optional (to be removed if not necessary)
add_action( 'woocommerce_order_status_processing', 'auto_update_orders_internal_status', 10, 2 );
function auto_update_orders_internal_status( $order_id, $order ){
     // Get all "processing" orders without backordered items
    $orders_ids = get_orders_ids_without_backordered_items( 'processing' );
    if( ! empty($orders_ids) ) {
        foreach($orders_ids as $post_id) {
            $acf_value = 'Ready to Pack';
            if ( get_field( 'internal_status', $post_id ) !== $acf_value ) {
                update_field( 'internal_status', $acf_value, $post_id ); 
            }
        }
    }
}

Code goes in functions.php file of the active child theme (or active theme). The first function is tested and works. The 2nd function doesn't throw any error.

Related: Change order status for backordered items in Woocommerce

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • The 2nd function is applying changes, however It seems something is not right with the SQL query as this is making the custom field change on every single processing order, even those that consist only of backordered items get affected, so atm it is basically affecting all processing orders across the board no matter the state of their items. Something is finally working, however only half of it :') – Jaime Matos Mar 08 '21 at 11:20
  • now when I manually search the woocommerce_order_itemmeta table, looking at the correct Order item ID which is on backorder, I cannot find any Meta Key that is equal to "Backordered", even though the item is cleary on backorder and has the right inventory product settings, I am trying to investigate further – Jaime Matos Mar 08 '21 at 11:24
  • Ok I have figured out what was the problem: Having a product inventory settings set to manage stock -> "Allow backorders", has the product technically on backorder but it does not register the meta key "Backordered" in the woocommerce_order_itemmeta table. The product backorder setting must be "Allow, but notify customer" in order for "Backordered" meta key to show up in the woocommerce_order_itemmeta table and for the above query to work correctly. thank you Loic! – Jaime Matos Mar 08 '21 at 12:04
  • 1
    @JaimeMatos Good to know… I will add a note. – LoicTheAztec Mar 08 '21 at 12:09
  • I actually just came to realize that the above query does not work for the intended case because if a product stock will be updated to a positive value (so that the product finally has stock and wont be on backorder anymore) then the order internal status will never be updated to "Ready To Pack" because the order item meta "Backordered" won't change as it is defined at the time the order is placed and will not be updated. – Jaime Matos Mar 08 '21 at 15:06
  • The objective of querying "Processing" orders and changing their internal status field is to let admins know that an order finally has no items that are out of stock anymore (as stock has been updated in the meanwhile) Basically the intention was not go to query orders to check if there were items that were on backorder at the time of purchase, but if there currently still are items without stock (I realize that I did not make this very clear) – Jaime Matos Mar 08 '21 at 15:08
  • 1
    @JaimeMatos What you asking now is something different than your initial question ( where you asked to get orders without backordered items, to update a custom field). To manage realtime stock / orders as you are asking now is something different and I think much more complicated than you are thinking. You should have to ask a new question, better explaining things. Regards. – LoicTheAztec Mar 09 '21 at 00:45
  • thank you for your sincere feedback Loic, I have created a new question where I attempt to better describe it's purpose here https://stackoverflow.com/questions/66549313/frequently-check-all-orders-with-order-status-processing-for-backordered-items – Jaime Matos Mar 09 '21 at 15:00