3

I've been using some well documented code to programatically create Woocommerce orders. Working great. Reference here: https://quadlayers.com/add-products-woocommerce/

However I'd be keen to know if it's possible to define the order_id (or is that the post_id?) whilst creating my WC orders via a script. I run this code on my shop, which currently imports orders into Woocommerce from a marketplace online where orders already have an Order number and I'd be keen to cut out the cross-referencing via this hack, and pass along the existing Order number to WC.

Here's a rough idea of what I have;

$insert_marketplace_order_id = 1234567890;

$order = wc_create_order();
$order->set_order_id($insert_marketplace_order_id);
$order->set_date_created($date_here);
$order-> etc. etc.
$order->save();

I've obviously searched around, unfortunately the existence of a plugin - which seems to be all Google knows about it - doesn't help.

I would have though 'set_order_id' would do the trick, but perhaps there's an issue with where I'm placing it. Any other ideas?

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
Callum
  • 554
  • 2
  • 7
  • 18

1 Answers1

3

In WooCommerce, the order Id is the post Id, so you can't insert an external reference Id as you are trying to do. WooCommerce orders are a custom post type and order Id (the post Id) is generated from last post Id used in wp_posts database table…

Now you can set instead an Order number using the filter hook woocommerce_order_number, to set your own order reference number as order number, which is not the WooCommerce Order Id (post Id).

So your code will be:

$insert_marketplace_order_id = 1234567890;

$order = new WC_Order();
$order->set_date_created($date_here);

// $order-> etc. etc.

$order->update_meta_data('_order_number', $insert_marketplace_order_id); // <== Here
$order->save();

Then you will add the following hooked function to be able to get and display the correct order number:

add_filter( 'woocommerce_order_number', 'wc_set_order_number', 10, 2 );
function wc_set_order_number( $order_id, $order ) {

    // Get the order number (custom meta data)
    $order_number = $order->get_meta('_order_number'); 

    return empty($order_number) ? $order_id : $order_number;
}

Code goes in functions.php file of the active child theme (or active theme).

Now when using the WC_Order method get_order_number() WooCommerce will get/display the correct order number.

Note: As you don't use any arguments with wc_create_order() function is better to use $order = new WC_Order(); instead, which gives an empty WC_Order instance object without using save() method 2 times (so much lighter).

Related: Dynamic custom order numbers based on payment method

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • Loic, you most wonderful Aztec. You always come to the rescue. Not only a complete answer but very interesting you point out the lightweight $order = new WC_Order(); function. I will make the edit and let you know how it goes. Thank you so much. This looks great. Have a wonderful day! – Callum Nov 18 '20 at 17:45
  • If you look to [`wc_create_order()` function source code](https://github.com/woocommerce/woocommerce/blob/4.7.0/includes/wc-core-functions.php#L76-L139), you will see that it uses `new WC_Order()`and the method `save()`. Thats why… – LoicTheAztec Nov 18 '20 at 17:51