Like many other users when followed this tutorial, I ran into the following problem
If I change the status of the order afterwards to completed then this happen, the custom stock is added back with the difference between the adjusted number and the original number.
How can I prevent this?
p.s. I contacted the tutorial writer several times for this months ago, unfortunately without any response
Code from the tutorial
/**
* Simple product setting.
*/
function ace_add_stock_inventory_multiplier_setting() {
?><div class='options_group'><?php
woocommerce_wp_text_input( array(
'id' => '_stock_multiplier',
'label' => __( 'Inventory reduction per quantity sold', 'woocommerce' ),
'desc_tip' => 'true',
'description' => __( 'Enter the quantity multiplier used for reducing stock levels when purchased.', 'woocommerce' ),
'type' => 'number',
'custom_attributes' => array(
'min' => '1',
'step' => '1',
),
) );
?></div><?php
}
add_action( 'woocommerce_product_options_inventory_product_data', 'ace_add_stock_inventory_multiplier_setting' );
/**
* Add variable setting.
*
* @param $loop
* @param $variation_data
* @param $variation
*/
function ace_add_variation_stock_inventory_multiplier_setting( $loop, $variation_data, $variation ) {
$variation = wc_get_product( $variation );
woocommerce_wp_text_input( array(
'id' => "stock_multiplier{$loop}",
'name' => "stock_multiplier[{$loop}]",
'value' => $variation->get_meta( '_stock_multiplier' ),
'label' => __( 'Inventory reduction per quantity sold', 'woocommerce' ),
'desc_tip' => 'true',
'description' => __( 'Enter the quantity multiplier used for reducing stock levels when purchased.', 'woocommerce' ),
'type' => 'number',
'custom_attributes' => array(
'min' => '1',
'step' => '1',
),
) );
}
add_action( 'woocommerce_variation_options_pricing', 'ace_add_variation_stock_inventory_multiplier_setting', 50, 3 );
/**
* Save the custom fields.
*
* @param WC_Product $product
*/
function ace_save_custom_stock_reduction_setting( $product ) {
if ( ! empty( $_POST['_stock_multiplier'] ) ) {
$product->update_meta_data( '_stock_multiplier', absint( $_POST['_stock_multiplier'] ) );
}
}
add_action( 'woocommerce_admin_process_product_object', 'ace_save_custom_stock_reduction_setting' );
/**
* Save custom variable fields.
*
* @param int $variation_id
* @param $i
*/
function ace_save_variable_custom_stock_reduction_setting( $variation_id, $i ) {
$variation = wc_get_product( $variation_id );
if ( ! empty( $_POST['stock_multiplier'] ) && ! empty( $_POST['stock_multiplier'][ $i ] ) ) {
$variation->update_meta_data( '_stock_multiplier', absint( $_POST['stock_multiplier'][ $i ] ) );
$variation->save();
}
}
add_action( 'woocommerce_save_product_variation', 'ace_save_variable_custom_stock_reduction_setting', 10, 2 );
/**
* Reduce with custom stock quantity based on the settings.
*
* @param $quantity
* @param $order
* @param $item
* @return mixed
*/
function ace_custom_stock_reduction( $quantity, $order, $item ) {
/** @var WC_Order_Item_Product $product */
$multiplier = $item->get_product()->get_meta( '_stock_multiplier' );
if ( empty( $multiplier ) && $item->get_product()->is_type( 'variation' ) ) {
$product = wc_get_product( $item->get_product()->get_parent_id() );
$multiplier = $product->get_meta( '_stock_multiplier' );
}
if ( ! empty( $multiplier ) ) {
$quantity = $multiplier * $quantity;
}
return $quantity;
}
add_filter( 'woocommerce_order_item_quantity', 'ace_custom_stock_reduction', 10, 3 );
What I first tried, unfortunately a dirty solution, without the desired result
/**
* Reduce with custom stock quantity based on the settings.
*
* @param $quantity
* @param $order
* @param $item
* @return $quantity
*/
function dvpi_custom_stock_reduction( $quantity, $order, $item ) {
/** @var WC_Order_Item_Product $product */
$multiplier = $item->get_product()->get_meta( '_stock_multiplier' );
if ( ! empty( $multiplier ) ) {
// Get product (parent) id
$product_id = $item->get_product_id();
// Get product object
$product = wc_get_product( $product_id );
// Get product stock
$product_stock = $product->get_stock_quantity();
// Calculate the reduce
$reduce = $multiplier * $quantity;
// Update stock
wc_update_product_stock( $product, $product_stock - $reduce );
// 0 because we do not use the standard behavior
$quantity = 0;
}
return $quantity;
}
add_filter( 'woocommerce_order_item_quantity', 'dvpi_custom_stock_reduction', 10, 3 );
The solution is to add an extra hook, namely woocommerce_prevent_adjust_line_item_product_stock
.
In this way, we check whether the condition of the $multiplier
is met and we prevent it from being adjusted.
/**
* Prevent adjust line item
*
* @param $prevent
* @param $item
* @param $quantity
*/
function prevent_adjust_line_item ( $prevent, $item, $quantity ) {
// Get multiplier
$multiplier = $item->get_product()->get_meta( '_stock_multiplier' );
// Empty & product is type variation
if ( empty( $multiplier ) && $item->get_product()->is_type( 'variation' ) ) {
$product = wc_get_product( $item->get_product()->get_parent_id() );
$multiplier = $product->get_meta( '_stock_multiplier' );
}
// NOT empty
if ( ! empty( $multiplier ) ) {
$prevent = true;
}
return $prevent;
}
add_filter( 'woocommerce_prevent_adjust_line_item_product_stock', 'prevent_adjust_line_item', 10, 3 );