https://rudrastyh.com/woocommerce/reduce-product-stock-conditionally.html
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.
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
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 );
}