WooCommerce Sequential Order Numbers April 02 2012

Update 5/25/2012 – While this free version of the plugin will always remain available, I now offer an officially supported “Pro” version which can be purchased from the WooCommerce shop: Sequential Order Numbers Pro. The Pro version has additional features including: start the order numbers at any particular number, set a custom number prefix/suffix with date pattern substitutions, set an order number length, exclude free orders from the order number sequence, and more. The Pro version is fully compatible with the free version, so if you are current free user, or want to test it out, you can always upgrade to the Pro.

With the recent release of WooCommerce 1.5.3 and a convenient new filter called woocommerce_order_number it’s now possible to extend WooCommerce to support incrementing order numbers. This article describes the approach taken for my WooCommerce Sequential Order Numbers plugin.

Implementation

WooCommerce order records are stored in the WordPress posts table, and the post id is used as the order number. This is a very simple and natural implementation, but it also means that as blog posts and pages are added to a site the order numbers will jump up correspondingly. Your very first order could easily have an order number in the hundreds. Granted, this is merely a cosmetic issue, and one that only a site operator would notice, but still some owners prefer to have sequential order numbers.

The solution I settled upon was to add a new post meta record, which I named _order_number to hold a sequential order number independent of the post id. I set this order number with a hook on the core wp_insert_post action which is called on every post insert, like so:

if ( $post->post_type == 'shop_order' ) {

  $order_number = get_post_meta( $post_id, '_order_number', true );

  if ( $order_number == "" ) {

    // attempt the query up to 3 times for a much higher success rate if it fails (due to Deadlock)

    $success = false;

    for ( $i = 0; $i < 3 && ! $success; $i++ ) {

      // this seems to me like the safest way to avoid order number clashes
      $success = $wpdb->query($wpdb->prepare('INSERT INTO '.$wpdb->postmeta.' (post_id,meta_key,meta_value) SELECT '.$post_id.',"_order_number",if(max(cast(meta_value as UNSIGNED)) is null,1,max(cast(meta_value as UNSIGNED))+1) from '.$wpdb->postmeta.' where meta_key="_order_number"'));

    }

  }

}

I decided to set the order number equal to the largest existing order number + 1, in one query, in order to try and avoid two simultaneous orders being assigned the same number (called a “clash”). The one risk is that two simultaneous orders will cause a deadlock and neither will be assigned an order number, which would be annoying but not necessarily the end of the world, it could be easily fixed by manually assigning an order number in the database if need be. In a test I performed of 20,000 orders inserted two at a time as quickly as possible, I had a failure rate of .39%, so I don’t think this should be a concern for the average store, though don’t get mad at me if you encounter it, you have been warned.

The other important piece of code is the function attached to the new woocommerce_order_number filter, which actually returns the sequential order number. This function looks like the following:

function get_order_number( $order_number, $order ) {

  if ( isset($order->order_custom_fields['_order_number'] ) ) {

    return '#'.$order->order_custom_fields['_order_number'][0];

  }

  return $order_number;
}

That’s pretty much it for the interesting code, and handles the custom order number everywhere on the frontend of the website, along with the HTML emails. Displaying the custom order number in the admin required overriding a bit more functionality than I would have liked, but if the new order_number() function which is used in the frontend is added to the admin in a future WooCommerce release I’ll be able to simplify this plugin quite a bit.

Installation

When this plugin is installed, any existing orders are assigned their current id as their custom order number. This means that if the most recent order is #501, the next order placed after the installation of this plugin will be #502, and from then on the numbers will be sequential. If this plugin is installed prior to any orders being placed, the first order number will be #1.

To install, go to Plugins > Add New, in your WordPress admin, and search for ‘WooCommerce Sequential Order Numbers’, or download from the WordPress.org plugin page.

The post WooCommerce Sequential Order Numbers appeared first on SkyVerge.