Skip to content
Advertisement

Dynamic custom order numbers based on payment method

I have the following code in my functions.php file:

add_filter( 'woocommerce_order_number', 'change_woocommerce_order_number' );

function change_woocommerce_order_number( $order_id ) {
    $order = wc_get_order( $order_id );
    //$order->get_total();

    $method_of_payment = $order->get_payment_method();

    if (  $method_of_payment == 'cheque' ) {
        $prefix       = 'CHE';
        $suffix       = '';
        $new_order_id = $prefix . $order_id . $suffix;
        return $new_order_id;
    } else {
        return $order_id;
    }
}

The code works but I want it to permanently save the new order number. It should permanently make CHEXXXX (ex. CHE5783) the order number in the database if the user checked out using check payments. Right now this code only makes it temporary. It does not need to update previous order numbers, only new orders.

Advertisement

Answer

As the method WC_Order set_order_number() doesn’t exist, we will add a custom field (custom meta data) when an order is placed (on order creation). Then we will get that order custom meta data in woocommerce_order_number filter hook.

The code:

add_action( 'woocommerce_checkout_update_order_meta', 'save_the_order_number', 10, 2 );
function save_the_order_number( $order_id, $data ) {
    $order = wc_get_order( $order_id ); // The order Object

    if ( 'cheque' === $order->get_payment_method() ) {
        $prefix = 'CHE';
        $suffix = '';
    } else {
        $prefix = '';
        $suffix = '';
    }
    update_post_meta( $order_id, '_order_number', $prefix . $order_id . $suffix );
}

add_filter( 'woocommerce_order_number', 'set_order_number', 10, 2 );
function set_order_number( $order_id, $order ) {
    // Get the order number (custom meta data)
    $order_number = $order->get_meta('_order_number'); 
    
    // If the order number doesn't exist (we keep that for old orders, or manual orders)
    if ( empty($order_number) ) {
        if ( 'cheque' === $order->get_payment_method() ) {
            $prefix       = 'CHE';
            $suffix       = '';
            $order_number = $prefix . $order_id . $suffix;
        } else {
            $order_number = $order_id;
        }
    }
    return $order_number;
}

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


Now if you want to be able to edit the order number on admin order pages, use additionally the following code:

add_action( 'woocommerce_admin_order_data_after_billing_address', 'display_admin_order_order_number_custom_field' );
function display_admin_order_order_number_custom_field( $order ){
    echo '<div class="edit_order_number"><p class="form-field _order_number_field" style="width:100%;">
    <label for="_order_number">'. __("Order number", "woocommerce").':</label>
    <input type="text" id="_order_number" name="_order_number" value="'. $order->get_order_number() .'">
    </p></div>';
}

add_action( 'save_post_shop_order', 'save_admin_order_order_number_custom_field' );
function save_admin_order_order_number_custom_field( $post_id ) {
    // If this is an autosave, our form has not been submitted, so we don't want to do anything.
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
        return;
    }

    // Check the user's permissions.
    if ( ! current_user_can( 'edit_shop_order', $post_id ) ) {
        return;
    }

    // Make sure that 'shipping_date' is set.
    if ( isset( $_POST['_order_number'] ) ) {
        // Update custom field value
        update_post_meta( $post_id, '_order_number', sanitize_text_field( $_POST['_order_number'] ) );
    }
}

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

enter image description here

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement