Search code examples
phpwordpresswoocommerceorderspolylang

Set in WooCommerce a sequential order number with country and year prefix


I need some advice on how to proceed with the following implementation. For my site in multiple languages ​​that uses Polylang as a plugin, I would need to have separate and consecutive numbering for the orders. For example:

  • Italian: IT-2024-01, IT-2024-02, IT-2024-03
  • German: DE-2024-01, DE-2024-02, DE-2024-03.

Right now, I just used this snippet for the Italian:

/**
 * Orders Prefix
 */

add_filter( 'woocommerce_order_number', 'change_woocommerce_order_number' );

function change_woocommerce_order_number( $order_id ) {
    $order = wc_get_order( $order_id );
    
    if ( $order && $order->get_date_created() ) {
        $order_year = $order->get_date_created()->format( 'Y' );
        $prefix = 'IT-' . $order_year . '-';
        $new_order_id = $prefix . $order_id;
        return $new_order_id;
    }
    
    return $order_id;
}


Solution

  • This requires to be done when the order is created after checkout, setting the order number as custom metadata, to keep a lightweight process each time the order number is read from the database.

    The following code will set as order metadata the order number, sequentially by country code, year, and incremental number (on 2 digits, or you can define the desired number of digits).

    // Set and save the order number as metadata
    add_filter( 'woocommerce_checkout_create_order', 'save_order_number_metadata' );
    function save_order_number_metadata( $order ) {
        $digits  = 2; // Number of desired digits for the number part
        $year    = date('Y', time()); // Get the current year
        $country = $order->get_billing_country(); // Get the billing country
        $data    = get_option('wc_sequential_order_number'); // Get order number sequencial helper registered data
    
        $number = isset($data[$year][$country]) ? intval($data[$year][$country]) + 1 : 1;
        $data[$year][$country] = $number;
    
        // Update order number sequencial helper registered data
        update_option('wc_sequential_order_number', $data);
    
        // Add order number as custom metadata
        $order->add_meta_data('_order_number', sprintf('%s-%s-%s', $country, $year, str_pad($number, $digits, '0', STR_PAD_LEFT)), true);
    }
    
    // Read the order number from metadata
    add_filter( 'woocommerce_order_number', 'define_order_number', 10, 2 );
    function define_order_number( $order_id, $order ) {
        if ( $order_number = $order->get_meta('_order_number') ) {
            $order_id = $order_number;
        }
        return $order_id;
    }
    

    Code goes in functions.php file of your child theme (or in a plugin). Tested and works.


    For orders created manually, it requires something different, as the language code is not yet defined.