Search code examples
phpwordpresswoocommercestatusshipping-method

Change Woocommerce Order Status based on different Shipping Methods


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

Solution

  • 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.