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', 'rudr_can_reduce_stock', 25, 2 );
function rudr_can_reduce_stock( $can_reduce, $order ) {
if( Any kind of condition here ) {
$can_reduce = false; // or true
}
return $can_reduce; // the default value
}
If you don’t know where to insert code snippets from this tutorial, please check this guide.
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', 'rudr_can_reduce_stock', 25, 2 );
function rudr_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', 'rudr_no_stock_changes_for_cod', 25, 2 );
function rudr_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', 'rudr_reduce_stock_completed_orders', 20, 4 );
function rudr_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 my plugin.

Misha Rudrastyh
Hey guys and welcome to my website. For more than 10 years I've been doing my best to share with you some superb WordPress guides and tips for free.
Need some developer help? Contact me