Black Friday & Cyber Monday SUPER SALE ALL WEEK:
Grab 40% OFF on plugins
Days
Hours
Minutes
Seconds

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

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 WooCommerce 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

Share It:

Subscribe
Notify of
23 Comments
Newest
Oldest
Inline Feedbacks
View all comments
Aaron
3 years ago

Excellent. I would like the code “order status as Completed based on payment method” but the code snippet didn’t work for me. Any recommendation or suggestion? also I would like (if possible) that 2 payment methods are shown as processing, and the rest as completed. Best regards

3 years ago

this code can i use for ccavanue payment getaway as well?

3 years ago

automatically change order from complete to custom order status set time ,if ordered product attribute conational usage = 30days , order status change after 30 day

3 years ago

Hi,
I love it, thank you very much!
I’m gettging this PHP warning in debug.log:

 PHP Notice: data was called <strong>incorrectly</strong>. Order properties should not be accessed directly. Backtrace: edit_post, wp_update_post, wp_insert_post, do_action(‘save_post’), WP_Hook->do_action, WP_Hook->apply_filters, WC_Admin_Meta_Boxes->save_meta_boxes, do_action(‘woocommerce_process_shop_order_meta’), WP_Hook->do_action, WP_Hook->apply_filters, WC_Meta_Box_Order_Data::save, WC_Order->save, WC_Order->status_transition, do_action(‘woocommerce_order_status_changed’), WP_Hook->do_action, WP_Hook->apply_filters, ke_auto_complete_virtual, WC_Order->update_status, WC_Order->save, WC_Order->status_transition, do_action(‘woocommerce_order_status_changed’), WP_Hook->do_action, WP_Hook->apply_filters, ke_auto_complete_virtual, WC_Abstract_Legacy_Order->__get, wc_doing_it_wrong Please see <a href=”https://wordpress.org/support/article/debugging-in-wordpress/”>Debugging in WordPress</a> for more information. (This message was added in version 3.0.) in /home/XXX/public_html/wp-includes/functions.php on line 5311

Does this code sample need to be updated to the latest version?

3 years ago
Reply to  Daniel S

I think $order->data[‘status’] should probably be changed to $order->get_status().

Jason J
3 years ago
Reply to  Ben D

I think $order->get_product_from_item( $item ) will also need to be changed to $item->get_product().
The WC_Abstract_Legacy_Order::get_product_from_item function is deprecated since version 4.4.0.

how can i change the order status to completed after approve in the payment confirmation I want to change the order status to completed after press the button approve in the payment confirmation is it a code like this? Put it on and it doesn’t work. Or at what step did you make a mistake? 1) Start as => on-hold status 2) When someone transfers money to => Checking payment 3) When approved in payment confirmation, the payment change => Processing. I want to press the button approve in the payment confirmation and chage to completed status how can i… Read more »

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