Skip links

Reduce Product Stock Quantities Conditionally

When you turn the option “Manage Stock” on for your WooCommerce products (or variations), then every time an order is made, stock quantity of the products from the order is going to be automatically decreased.

But sometimes you don’t need that, or just need it for specific order statuses or payment methods. In this tutorial I will show you how you can do that.

Let’s begin with a filter hook woocommerce_can_reduce_order_stock which returns either true or false depending whether product stock quantity can be decreased or not. But the amazing part is that this hook also has a second argument which is WC_Order object and it allows us to make any kind of conditions!

It is as simple as that:

add_filter( 'woocommerce_can_reduce_order_stock', 'wpdev_can_reduce_stock', 25, 2 );
function wpdev_can_reduce_stock( $can_reduce, $order ) {
	
	if( Any kind of condition here ) {
		$can_reduce = false; // or true
	}
	
	return $can_reduce; // the default value
	
}

Now let’s take a look at more practical examples.

Examples

Don’t reduce product stock for orders with a specific custom field

add_filter( 'woocommerce_can_reduce_order_stock', 'wpdev_can_reduce_stock', 25, 2 );
function wpdev_can_reduce_stock( $can_reduce, $order ) {
	
	if( 'META VALUE' === $order->get_meta( 'META KEY' ) ) {
		$can_reduce = false;
	}
	return $can_reduce;
	
}

Don’t reduce product stock if a specific product is in the order

In this example please keep in mind that the product stock quanity will remain untouched for all products in the order.

add_filter( 'woocommerce_can_reduce_order_stock', function( $can_reduce, $order ) {

	$is_product_in_order = false;
	// get all order items
	$items = $order->get_items();
	if( $items ) {
		foreach ( $items as $item_id => $item ) {
			if( 'SPECIFIC PRODUCT ID' == $item->get_product_id() ) {
				$is_product_in_order = true;
				break;
			}
		}
	}

	return $is_product_in_order ? false : $can_reduce;
}, 25, 2 );

As you probably remember, products are stored in orders as order items.

Don’t reduce product stock for specific payment methods and specific order statuses

This example is more practical one, I assume. Our goal here is to not decrease product stock quantities if order have been made without actual payment. So for example if “Cash on delivery” payment method was selected. Here we are stick to a specific order statuses:

  • processing – order has been made by a customer, in this case the product stock quantities remain unchanged.
  • completed – order has been approved by a shop manager in WooCommerce admin, now we are ready to decrease stock quantities. We will need one more action hook here which will be fired when order status is changed – woocommerce_order_status_changed.
add_filter( 'woocommerce_can_reduce_order_stock', 'wpdev_no_stock_changes_for_cod', 25, 2 );
function wpdev_no_stock_changes_for_cod( $reduce_stock, $order ) {

	if( $order->has_status( 'processing' ) && 'cod' === $order->get_payment_method() ) {
		$reduce_stock = false;
	}
	return $reduce_stock;

}

add_action( 'woocommerce_order_status_changed', 'wpdev_reduce_stock_completed_orders', 20, 4 );
function wpdev_reduce_stock_completed_orders( $order_id, $old_status, $new_status, $order ){

	// do nothing if this order was not not with cash on delivery payment method
	if( 'cod' !== $order->get_payment_method() ) {
		return;
	}

	// do nothing if it is not changing order status to "completed"
	if ( 'completed' !== $new_status ){
		return;
	}

	// reduce stock levels manually
	wc_reduce_stock_levels( $order_id );

}

In case you would like to sync product stock quantities between products on different WooCommerce stores, then I recommend you to look at  this  plugin.

Print Friendly, PDF & Email

Author

Leave a comment

This website uses cookies to improve your web experience.
DON’T MISS OUT!
Subscribe To Newsletter
Be the first to get latest updates and exclusive content straight to your email inbox.
Stay Updated
Give it a try, you can unsubscribe anytime.
close-link