skip to Main Content

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;
}

2

Answers


  1. I have fixed the issue in two parts.

    1. First I get the current language using polylang function

    2. Then I pass it two custom function, which populates the desired sequence

      //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() ) {
              $language_code = pll_current_language(); // Detect current language
              $new_order_id = generate_woo_order_sequence($language_code);
      
              return $new_order_id;
          }
      
          return $order_id;
      }
      
      // Generate the sequence with language code passed
      function generate_woo_order_sequence($language_code) {
          $year = date('Y');
          $option_name = "wc_custom_series_{$language_code}";
      
          // Reset if year has changed
          $stored_year = get_option($option_name . "_year", -1);
          if ($year > $stored_year) {
              update_option($option_name, 1);
              update_option($option_name . "_year", $year);
          }
      
          $current_number = get_option($option_name, 1);
          update_option($option_name, $current_number + 1);
      
          return strtoupper($language_code) . '-' . $year . '-' . str_pad($current_number, 3, '0', STR_PAD_LEFT);
      }
      

    Note: I have considered prefix with leading zeros upto 3 digits.

    For e.g., EN-2024-001 will be the first order number for new order placed after this code integration.

    Login or Signup to reply.
  2. 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 database.

    The following code will set as order metadata the order number, sequentially by language code, year, and incremental number (on 2 digits. 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
        $lang   = strtoupper(pll_current_language()); // Get current language
        $data   = get_option('wc_sequential_order_number'); // Get order number sequencial helper registered data
    
        $number = isset($data[$year][$lang]) ? intval($data[$year][$lang]) + 1 : 1;
        $data[$year][$lang] = $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', $lang, $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.

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