Ad

Update WooCommerce Order Status If Product Custom Field Is Set

I need to automatically set a certain order status (different than processing) when getting a new order.

This is achieved by this function:

add_action('woocommerce_thankyou','change_order_status');

function change_order_status( $order_id ) { 
 
    if ( ! $order_id ) { return; }  
        
    $order = wc_get_order( $order_id );
        
    if( 'processing'== $order->get_status() ) {
        $order->update_status( 'wc-custom-status' );
    }   
}

This totally works. Now I only need this to happen when a product has a customization.


The way to customize a product is filling an input field before adding to cart. The input is attached to the item data:

// Add custom cart item data
add_filter( 'woocommerce_add_cart_item_data', 'add_custom_cart_item_data', 10, 2 );
function add_custom_cart_item_data( $cart_item_data, $product_id ){
    if( isset($_POST['custom_text']) ) {
        $cart_item_data['custom_text'] = sanitize_text_field( $_POST['custom_text'] );
        $cart_item_data['unique_key'] = md5( microtime().rand() ); // Make each item unique
    }
    return $cart_item_data;
}

Then the custom text is retrieved and displayed in cart and in the order data using this:

// Display custom cart item data on cart and checkout
add_filter( 'woocommerce_get_item_data', 'display_custom_cart_item_data', 10, 2 );
function display_custom_cart_item_data( $cart_item_data, $cart_item ) {
    if ( !empty( $cart_item['custom_text'] ) ){
        $cart_item_data[] = array(
        'name' => __('Customization', 'woocommerce'),
        'value' => $cart_item['custom_text'] // Already sanitized field
    );
    }
    return $cart_item_data;
}

// Save and display custom item data everywhere on orders and email notifications
add_action( 'woocommerce_checkout_create_order_line_item', 'add_product_custom_field_as_order_item_meta', 10, 4 );

function add_product_custom_field_as_order_item_meta( $item, $cart_item_key, $values, $order ) {

    if ( isset($values['custom_text']) ) {
    $item->update_meta_data('Add on', $values['custom_text'] );
    }

}

I'm trying using the if ( isset($values['custom_text']) ) part as a trigger of the function to change the order status only if the product add on is set and other similar methods (like if ( !empty( $cart_item['custom_text'] ) ) but I'm not sure this is the way to go:

add_action('woocommerce_thankyou','change_order_status');
function change_order_status( $order_id ) {  
    if ( ! $order_id ) {return;}  
    
    $order = wc_get_order( $order_id );
    
    if ( isset($values['custom_text']) ) {
    
        if( 'processing'== $order->get_status() ) {
            $order->update_status( 'wc-custom-status' );
        }
        
    }
    
}

This above does nothing. Am I anywhere near it with this approach?

EDIT: I tried this too

add_action('woocommerce_thankyou','change_order_status');   
function change_order_status( $order_id ) {         
    if ( ! $order_id ) {return;}                
    
    $order = wc_get_order( $order_id );                 
    
    foreach ( $order->get_items() as $item_id => $item ) {                      
        $allmeta = $item->get_meta_data();                  
        
        if ( isset($values['custom_text']) ) {                          
            if( 'processing'== $order->get_status() ) {                     
                $order->update_status( 'wc-custom-status' );
            }                           
        }
    }
}
Ad

Answer

Your code contains some unnecessary steps as well as some shortcomings

  • For example, the woocommerce_add_cart_item_data hook contains 3 arguments versus 2

So you get:

// Add custom cart item data
function filter_add_cart_item_data( $cart_item_data, $product_id, $variation_id ) { 
    // Isset and NOT empty
    if ( isset ( $_POST[ 'custom_text' ] ) && ! empty ( $_POST[ 'custom_text' ] ) ) {
        $cart_item_data['custom_text'] = sanitize_text_field( $_POST['custom_text'] );
    }
    
    return $cart_item_data; 
}
add_filter( 'woocommerce_add_cart_item_data', 'filter_add_cart_item_data', 10, 3 );

// Display custom cart item data on cart and checkout
function filter_woocommerce_get_item_data( $cart_data, $cart_item = null ) {
    if ( isset ( $cart_item['custom_text'] ) ) {
        $cart_data[] = array(
            'name'  => __( 'Customization', 'woocommerce' ),
            'value' => $cart_item['custom_text']
        );
    }

    return $cart_data;
}
add_filter( 'woocommerce_get_item_data', 'filter_woocommerce_get_item_data', 10, 2 );

// Add the information as meta data so that it can be seen as part of the order
// Save and display custom item data everywhere on orders and email notifications
function action_woocommerce_checkout_create_order_line_item( $item, $cart_item_key, $values, $order ) {
    if ( isset ( $values['custom_text'] ) ) {
        $item->update_meta_data( 'custom_text', $values['custom_text'] );
    }
}
add_action( 'woocommerce_checkout_create_order_line_item', 'action_woocommerce_checkout_create_order_line_item', 10, 4 );

// On thankyou page
function action_woocommerce_thankyou( $order_id ) {
    // Get $order object
    $order = wc_get_order( $order_id );
    
    // Is a WC_Order
    if ( is_a( $order, 'WC_Order' ) ) {
        // Only when the current order status is 'processing'
        if ( $order->get_status() == 'processing' ) {
            // Loop trough
            foreach ( $order->get_items() as $item ) {
                // Get meta
                $value = $item->get_meta( 'custom_text' );

                // NOT empty
                if ( ! empty ( $value ) ) {
                    // Update status (change to desired status)
                    $order->update_status( 'cancelled' );

                    // Stop loop
                    break;
                }
            }
        }
    }
}
add_action( 'woocommerce_thankyou', 'action_woocommerce_thankyou', 10, 1 );

Currently it is just checking if the value exists, to compare it effectively

Change

// NOT empty
if ( ! empty ( $value ) ) {
    // Update status
    $order->update_status( 'cancelled' );

    // Stop loop
    break;
}

To

// Compare
if ( $value == 'some value' ) ) {
    // Update status
    $order->update_status( 'cancelled' );

    // Stop loop
    break;
}
Ad
source: stackoverflow.com
Ad