skip to Main Content

I am using Change Woocommerce Order Status based on Shipping Method code and it works beautifully for re-assigning my custom order status "awaiting-pickup" in WooCommerce based on shipping method string.

Here is my code:

add_action( 'woocommerce_thankyou', 'shipping_method_update_order_status', 10, 1 );
    function shipping_method_update_order_status( $order_id ) {
        if ( ! $order_id ) return;
    
        $search = 'local_pickup'; // The needle to search in the shipping method ID
    
        // Get an instance of the WC_Order object
        $order = wc_get_order( $order_id );
    
        // Get the WC_Order_Item_Shipping object data
        foreach($order->get_shipping_methods() as $shipping_item ){
            // When "pickup" method is used, we change the order to "awaiting-pickup" status
            if( strpos( $shipping_item->get_method_title(), $search ) !== false ){
                $order->update_status('awaiting-pickup');
                $order->save();
                break;
            }
        }
    }

I need help extending this to apply a few different rules based on other shipping methods like for ‘free_shipping’ and ‘flat_rate’ that I would like to reassign as ‘awaiting-delivery’ too.

$search = 'flat_rate' OR 'free_shipping';
$order->update_status('awaiting-delivery');

The shipping instances are structured like so:

'local_pickup:2'
'local_pickup:5'
'local_pickup:7'
'local_pickup:10'

'flat_rate:3'
'flat_rate:6'
'flat_rate:9'

'free_shipping:11'
'free_shipping:12'
'free_shipping:13'

Every time I create a new shipping zone extra shipping instances that are attached to that zone will have new numbers attached the method type. Ultimately I need something that use the following logic:

IF      'local_pickup' IN string
THEN    $order->update_status('awaiting-pickup');
ELSEIF  'flat_rate' OR 'free_shipping' IN string
THEN    $order->update_status('awaiting-delivery');
END

2

Answers


  1. Update 2

    As you are using the real shipping method Id in here, you don’t need to search for a string. Then it will be more simple to make it work for multiple shipping methods Ids as follows:

    add_action( 'woocommerce_thankyou', 'shipping_method_update_order_status', 10, 1 );
    function shipping_method_update_order_status( $order_id ) {
        if ( ! $order_id ) return;
        
        // Here define your shipping methods Ids
        $shipping_methods_ids_1 = array('local_pickup');
        $shipping_methods_ids_2 = array('flat_rate', 'free_shipping');
    
        // Get an instance of the WC_Order object
        $order = wc_get_order( $order_id );
    
        // Get the WC_Order_Item_Shipping object data
        foreach($order->get_shipping_methods() as $shipping_item ){
            // For testing to check the shipping method slug (uncomment the line below):
            // echo '<pre>'. print_r( $shipping_item->get_method_id(), true ) . '</pre>';
    
            // When "Local pickup" method is used, we change the order to "awaiting-pickup" status
            if( in_array( $shipping_item->get_method_id(), $shipping_methods_ids_1 ) && ! $order->has_status('awaiting-pickup') ){
                $order->update_status('awaiting-pickup'); // Already use internally save() method
                break; // stop the loop
            }
            // When 'Flat rate' or 'Free shipping' methods are used, we change the order to "awaiting-delivery" status
            elseif( in_array( $shipping_item->get_method_id(), $shipping_methods_ids_2 ) && ! $order->has_status('awaiting-delivery') ){
                $order->update_status('awaiting-delivery'); // Already use internally save() method
                break; // stop the loop
            }
        }
    }
    

    Code goes in functions.php file of the active child theme (or active theme). It should works.

    Login or Signup to reply.
  2. Assuming new orders are always given the status of PROCESSING, then this is how I would do it:

    add_action('woocommerce_order_status_changed', 'jds_auto_change_status_by_shipping_method');
        function jds_auto_change_status_by_shipping_method($order_id) {
            // If the status of an order is changed to PROCESSING and the shipping method contains specific text then change the status.
            if ( ! $order_id ) {
                return;
            }
            global $product;
            $order = wc_get_order( $order_id );
            if ($order->data['status'] == 'processing') { // if order status is processing
                $shipping_method = $order->get_shipping_method();
                if ( strpos($shipping_method, 'local_pickup') !== false ) { // if shipping method CONTAINS
                    $order->update_status('awaiting-pickup'); // change status
                } else if ( strpos($shipping_method, 'flat_rate') !== false ) { // if shipping method CONTAINS
                    $order->update_status('awaiting-delivery'); // change status
                } else if ( strpos($shipping_method, 'free_shipping') !== false ) { // if shipping method CONTAINS
                    $order->update_status('awaiting-delivery'); // change status
                }
            }   
        }
    

    I will note that the $shipping_method returns the Human Readable text that the customer sees on the website when they checkout so you may need to adjust local_pickup to match the exact text the customer sees (like ‘Local Pickup’).

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search