skip to Main Content

Im trying to add a line item when I update an order in the backend and it matches the status update of "enquiry" but no item is added.

I tried both get_status and has_status but I cant get it to work. Any ideas on why this isn’t working?

Code:

add_action( 'woocommerce_order_status_changed', 'add_free_products', 20, 4 );
function add_free_products( $order_id, $order ){
 if ( ! $order_id )
        return;

    // Getting an instance of the order object
    $order = wc_get_order( $order_id );

    if( $order->get_status() == 'enquiry' ) {
       $product_id = '155185';
        $product = wc_get_product( $product_id );
        $order->add_product( $product);
        $order->save();
    }
}

2

Answers


  1. For a custom order status you could use the woocommerce_order_status_' . $status_transition['to'] action hook, where you will replace $status_transition[to] by enquiry

    So you get:

    function action_woocommerce_order_status_enquiry( $order_id, $order ) {
        // Product ID
        $product_id = 155185;
        
        // Get product
        $product = wc_get_product( $product_id );
        
        // Add an order line item + quantity
        $order->add_product( $product, 1 );
        
        // Calculate totals and SAVE order data
        $order->calculate_totals();
    }
    add_action( 'woocommerce_order_status_enquiry', 'action_woocommerce_order_status_enquiry', 10, 2 );
    
    Login or Signup to reply.
  2. There are some mistakes and missing things, Use the following instead:

    add_action( 'woocommerce_order_status_changed', 'add_free_product_on_order_enquiry_status', 20, 4 );
    function add_free_product_on_order_enquiry_status( $order_id, $old_status, $new_status, $order ){
        if ( "enquiry" === $new_status ) {
            $product_id = '155185';
            $product = wc_get_product( $product_id );
            $order->add_product( $product );
            $order->calculate_totals(); // calculate taxes, totals and save (method includes save() method)
            // $order->save();
        }
    }
    

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


    Addition 1

    You could also flag this action with custom meta data, to avoid adding multiple products if you change order status multiple times with the following:

    add_action( 'woocommerce_order_status_changed', 'add_free_product_on_order_enquiry_status', 20, 4 );
    function add_free_product_on_order_enquiry_status( $order_id, $old_status, $new_status, $order ){
        if ( "enquiry" === $new_status && ! $order->get_meta('_free_product_added') ) {
            $product_id = '155185';
            $product = wc_get_product( $product_id );
            $order->add_product( $product );
            $order->update_meta_data('_free_product_added', 'yes'); // Flag the order
            $order->calculate_totals(); // calculate taxes, totals and save (method includes save() method)
        }
    }
    

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


    Addition 2 – Check if the product has been already added to the order (avoiding adding the product multiple times):

    function order_has_specific_product( $product_id, $order ) {
        // Loop through order items to check if a product is on the current order
        foreach ( $order->get_items() as $item ) {
            if ( in_array( $product_id, array($item->get_product_id(), $item->get_variation_id()) ) ) {
                return true;
            }
        }
        return false;
    }
    
    add_action( 'woocommerce_order_status_changed', 'add_free_product_on_order_enquiry_status', 20, 4 );
    function add_free_product_on_order_enquiry_status( $order_id, $old_status, $new_status, $order ){
        $product_id = '155185'; // Free product to be added only once
    
        if ( "enquiry" === $new_status && ! order_has_specific_product( $product_id, $order ) ) {
            $product = wc_get_product( $product_id );
            $order->add_product( $product );
            $order->calculate_totals(); // calculate taxes, totals and save (method includes save() method)
        }
    }
    

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

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