We saw in an earlier post, how to change the order number by adding prefix or suffix to it. We got an interesting idea from one of our readers to add a date to the order number and reset the order IDs for each date. And that’s what we will learn in this post.
Since we want to reset the order numbers every 24 hours, it is necessary to have the date in the order id (order number). This will help us in identifying the orders for a date. The order ids are the post IDs stored in the wp_posts table. But we won’t be modifying anything in the database.
So, let’s start with adding the order creation date to the order number. To change the order number we will use the filter ‘woocommerce_order_number’ which is applied in the get_order_number() in the file includes/wc-abstract-order.php.
First, we will add the filter in our PHP file and define our function name. In this case, the function is change_woocommerce_order_number().
Now let’s change our order number so that it includes the order created date in the order number. The filter woocommerce_order_number has one parameter – order_id. We get the order object from order_id using wc_get_order(). From the order object we can get the date of creation using get_date_created() function.
We create the new order id by concatenating the $order_id, $order_date and $suffix. As this is a filter, we must return the $new_order_id.
This is our order page with the new order numbers –
As you can see, the date is added to the order number. But, the date also contains the time it was created on. If you don’t want the time in the order number, you can do this by using the date( $format ) function of WC_DateTime class. That’s because the function get_date_created() returns a WC_DateTime object. The date() function takes one parameter – $date_format. This date() is not the same as PHP date() function.
This is how our Orders page will look like –
Resetting Order Numbers every 24 hours
One of our readers also asked if we could reset the order numbers for each date. The idea is to start the order numbers from 1 for each date. We can do this using the ‘woocommerce_change_order_number‘ filter, but we won’t be changing the numbers in the database. The reason for this is that the order numbers are post IDs and changing the post ids would definitely be a bad idea.
So, what we will do is change the order numbers using our filter and display our custom order id on the admin side as well as to the customers. The upside of this is that your competitors won’t be able to guess the number of orders you have received till date based on the order id.
Let’s think about the logic we would need for this. We will first find all the orders for a given date and then we would assign the position/index of the order in the array as the order number. Sounds a bit complicated? Let’s try it.
Currently, our order number consists of Order ID, Date created, & a suffix. First, let’s query all the posts where the post_date is the date of creation of the order and post_type is shop_order.
SELECT ID FROM {$wpdb->prefix}posts WHERE post_date LIKE '%".$date_created."%' AND post_type='shop_order' ORDER BY ID
The above query will return all the orders from the given date. Now we want the position of the current order in the array.
In the above function, we get the results from the above query in the $result variable. We then loop over the $result array and check if the current order id is equal to the current ID in the array. If it is equal, we set the $count variable equal to the value of current index + 1 and break from the loop. Then we create our new order number which is the combination of the $count, $prefix, $date_created, & $suffix.
Now, you can see our WooCommerce Orders Admin page will display our new order numbers –
As you can see there are 4 orders on 28th October 2017 and the value was reset for the order on 30th October back to #1. The new order number will also be displayed on the order received page –
and on the Edit Order page –
Recommended Reading: WooCommerce Order Numbers Not Sequential, Skipping or Jumping? Here’s How to Overcome it |
Even the emails received by the customers will display this changed order number. But let me remind you that we didn’t make any changes in the database. The order IDs in the database remain unchanged.
This function might cause some problems if you permanently delete any of the orders because our function will reset the order numbers. For example, if you permanently delete your order #2 for any date, the order #3 will become #2, #4 will become #3 and so on. This is because we are not saving anything in the database, we are just creating the numbers based on the position of the order id in the array.
There won’t be any problems if the order is present in the trash, is refunded, cancelled or failed as we are not considering the order status.
This would be a good idea if you want to organize the orders by date and you will also be able to know the number of orders you received on a particular date. This filter runs for each order and we also have a loop inside our function. So, this may cause some marginal performance issues while loading the orders page based on the number of orders you have.
Hello, i put the snippets and work but why when i want to add new order from admin it returns Uncaught Error: Call to a member function format() on null?
great post,
I want to reset the Order ID to start from 1002. or something Is there a way to do it?
just the order id,
Please, help
This will help to fix the issue.
Open the mysql database in cpanel and run the query below.
Update wp_postmeta set meta_value = 0 where meta_key=’_order_number’
When purchasing, the PO number will start to 1
Hello Rashmi, thank you for the code.
I do have a question.
The code causes an error during checkout.
The error logs show this
CRITICAL Uncaught Error: Call to a member function get_date_created() on boolean in php/snippet-ops.php(361) : eval()’d code:19
change_woocommerce_order_number(0, Object(WC_Order))
As this only happens when I use the code, I was wondering if there would be a solution?
Looks like it hung on a Boolean value.
Any ideas?
Thank you
Jean Paul
Hi Jean,
It seems that the order on which you are calling the get_date_created() is returning false. Did you add this code in the functions.php file or somewhere else?
Can you show me the code that you added?
Hello Rashmi, I added the code with snippet plugin, so it goes into the functions. The code I added is add_filter( 'woocommerce_order_number', 'change_woocommerce_order_number' ); function change_woocommerce_order_number( $order_id ) { global $wpdb; $prefix = '/FAC/'; $suffix = '-' . get_woocommerce_currency(); $order = wc_get_order( $order_id ); $order_date = $order->get_date_created(); $date_created = $order_date->date( 'Y-m' ); $query = "SELECT ID FROM {$wpdb->prefix}posts WHERE post_date LIKE '%".$date_created."%' AND post_type='shop_order' ORDER BY ID "; $result = $wpdb->get_results( $query ); $count = 0; foreach( $result as $index => $id ) { if( strval($order_id) == $id->ID ) { $count = $index + 1; break; } } $new_order_id =… Read more »
Hi Jean,
I tried your code and it seems to be working fine on my side. Based on the error you are getting – change_woocommerce_order_number(0, Object(WC_Order)), it seems the order_id is coming as 0 in this case.
Can you once try to add it directly to functions.php instead of snippets plugin?
Hi Rashmi,
Did you get the code I used?
Jean Paul
Hi Rashmi, i did everything that you said, but my order number doesn’t changed. What can i do now?
Hi Juliana,
Can you show me your code so that I can check what went wrong? And where did you add the code?
Yes, segure! I put in functions.php add_filter( ‘woocommerce_order_number’, ‘change_woocommerce_order_number’ ); function change_woocommerce_order_number( $order_id ) { global $wpdb; $prefix = ‘#’; $order = wc_get_order( $order_id ); $order_date = $order->get_date_created(); $date_created = $order_date->date( ‘ymd’ ); $query = “SELECT ID FROM {$wpdb->prefix}posts WHERE post_date LIKE ‘%”.$date_created.”%’ AND post_type=’shop_order’ ORDER BY ID “; $result = $wpdb->get_results( $query ); $count = 0; foreach( $result as $index => $id ) { if( strval($order_id) == $id->ID ) { $count = $index + 1; break; } } $new_order_id =$prefix .$date_created. $count; return $new_order_id; } Now, when i finishes an order, it appears with this structure, but internally and… Read more »