Search the site:

How to automatically Complete WooCommerce orders when they go to the Processing status

Every e-commerce site requires tracking and managing orders which can be quite a daunting task for the administrator, considering the number of orders that an average high-traffic e-commerce website receives per day. When it comes to WooCommerce, an order gets created as soon as the Checkout process is completed (Check out the WooCommerce order status flow below).

According to where the order is in the payment-to-delivery chain, it gets assigned a status. These statuses are set and/or changed by WooCommerce, the Payment Gateway and the store-owner/administrator depending on where the order lies.

Before we take a look at the flow of order in WooCommerce, let’s define what order status is in Woocommerce for the benefit of the newbies.

What is Order Status in WooCommerce?

The order status is a representation of the current state in which an order made by customer is. The order status in Woocommerce changes as the order is been processed unto the delivery stage or refund in the case where there is an issue with the product/services and where the store owner has agreed to refund to the customer. For example, when a customer  Place an order on a certain product, immediately the next order status in the sequence will be set, which is the “Pending Payment”. The pending payment is set by default in Woocommerce.

Now, let’s take a look at the flow chart for better understanding.

Woocommerce Order Status Flow Chart

Woocommerce Order Status Flow Chart
Source: https://docs.woocommerce.com/document/managing-orders/

As illustrated, after payment for an order is successfully completed, its status is set to “Processing” until the store owner manually changes it to “Completed”. This is an overhead task for the store owner or the administrator, especially in cases where the sales volume is high. One way to make this process efficient is to automatically complete WooCommerce orders when they go to the Processing status. Let’s see how we can do that using code snippet.

Complete List of Order Status in WooCommerce

  • Pending payment: This come up by default when the order has been placed but no payment has been made.
  • Failed: This indicates that the payment did not go through and was rejected.
  • Processing: This indicates that the payment went through and was received by store owners and it can now be processed for shipping and delivery.
  • Completed: This indicates that everything went well and the order has now been fulfilled and completed.
  • On hold: This indicates a state where the order requires confirmation from the store owner.
  • Cancelled: An order status “Cancelled” doesn’t require any further action. The cancellation can either be from the admin or the customer at some point.
  • Refunded: The order has been refunded, no further action is required

Now that we better understand what order status is and its function, let’s see why it can be a good idea to update it.

Automatically set the WooCommerce order status as Completed based on the payment method

In most cases, you would need to do this only after the payment has been successfully made, and this is only possible when the user has not selected the Cash-on-Delivery option. The code below, when inserted in the functions.php file of your child theme, will automatically set the status of the order as Completed whenever a payment has been successfully made. Hence, in all cases except when the user selects the Cash-on-Delivery option, the order status will automatically change to Completed.

add_action('woocommerce_order_status_changed', 'ts_auto_complete_by_payment_method');

function ts_auto_complete_by_payment_method($order_id)
{
  
  if ( ! $order_id ) {
        return;
  }

  global $product;
  $order = wc_get_order( $order_id );
  
  if ($order->data['status'] == 'processing') {
        $payment_method=$order->get_payment_method();
        if ($payment_method!="cod")
        {
            $order->update_status( 'completed' );
        }
      
  }
  
}

 

Here, you will use the woocommerce_order_status_changed hook to call a function when the status of an order is changed. After checking whether the order has the Processing status, only if the payment method is not Cash-on-Delivery, the order status will be changed to Completed. WooCommerce has four default payment methods viz. Direct Bank Transfer (bacs), Check payments (cheque), Cash on Delivery (cod) and PayPal (paypal). Depending on which payment method you are specifying the condition for, you would need to use the appropriate ID e.g. “bacs”, “cheque”, “cod”, “paypal”.

Automatically set the WooCommerce order status as Completed for virtual products

Another case where you would want the order status to complete automatically is when the product or products in the order are virtual products. Virtual products are products that are either not tangible or are downloadable. An example of this would be a store membership subscription or coupon that offers discounts to those who have bought the subscription.

automatically Complete WooCommerce orders when they go to the Processing status - Virtual Product Example - Store Membership
Example of a Virtual Product

A store membership subscription may not have a tangible form but instead an expiry date. Downloadable products such as software or even electronic movie tickets are virtual products too, as they do not have an offline presence or form. With most virtual products, there is never an option of “Cash-on-Delivery”. Payments are made on the spot, and hence it would be safe to not include the condition of checking for payment methods used, but instead only add a condition to check if all the products in the order are virtual products.

add_action('woocommerce_order_status_changed', 'ts_auto_complete_virtual');

function ts_auto_complete_virtual($order_id)
{
  
  if ( ! $order_id ) {
        return;
  }
  
  global $product;
  $order = wc_get_order( $order_id );
  
  if ($order->data['status'] == 'processing') {
    
    $virtual_order = null;

    if ( count( $order->get_items() ) > 0 ) {

      foreach( $order->get_items() as $item ) {

        if ( 'line_item' == $item['type'] ) {

          $_product = $order->get_product_from_item( $item );

          if ( ! $_product->is_virtual() ) {
            // once we find one non-virtual product, break out of the loop
            $virtual_order = false;
            break;
          } 
          else {
            $virtual_order = true;
          }
       }
     }
   }

    // if all are virtual products, mark as completed
    if ( $virtual_order ) {
      $order->update_status( 'completed' );
    }
  }	
}

Here, we use the same hook to call our function ts_auto_complete_virtual. After checking if the order is in a Processing status, you need to go through each item in the order to see if it’s a virtual product.

Conclusion

A typical Woocommerce order has a lot of items associated with it such as products, shipping, fees etc. Here, line_item refers to the product. Only the products need to be fetched one by one to check if they are virtual. If even one item is not a virtual product, the status of the order will not be marked as Completed.

Depending on your requirements, however, and using the first code snippet in this post, you may add more conditions to mark the order status as Completed. For example, if you wish to mark Order Status as Completed even for non-virtual products (if the payment for these products is done), then you can do so by adding a check on the payment method after it checks for whether it’s a virtual product. Through this code snippet, however, the status of the order will be set as Completed only if all products in the order are virtual products.

Browse more in: Code Snippets, WooCommerce How Tos, WooCommerce Tutorials
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

20 Comments
Oldest
Newest
Inline Feedbacks
View all comments
Maged Mohamed
2 years ago

Hi there,

Can this work with the free orders ? Which in this case the order total is 0 and all the payment gateways are hidden so in this case can it work to update the order from processing to completed ?

Anubha Bhat
Anubha Bhat
2 years ago
Reply to  Maged Mohamed

Yes.

Luigi
Luigi
2 years ago

can we use this code to work after we update an order (in progress mode) from backend?

jose
jose
2 years ago

What about the status on hold also get completed?

Marek Tandler
Marek Tandler
2 years ago

Hello, i could ask to create the same script but depending on the chosen shipping method?Thanks lot

Andrius
2 years ago

Hi, the snippet works, but when testing I received two emails – one for order being processed and then immediately ‘completed’. How can I prevent the ‘processing’ email being sent?

from purchased

Subscribe for more offers

20
0
Would love your thoughts, please comment.x
()
x