防止调整订单项库存以减少 WooCommerce 中的自定义库存数量
Prevent adjust line item stock for custom stock quantity reduction in WooCommerce
像许多其他用户一样,在遵循这个 tutorial 时,我 运行 遇到了以下问题
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.
如何防止这种情况?
p.s。几个月前我曾多次联系过教程作者,不幸的是没有任何回应
教程中的代码
/**
* 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 );
我第一次尝试,不幸的是一个肮脏的解决方案,
没有想要的结果
/**
* 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 );
解决方法是多加一个钩子,即woocommerce_prevent_adjust_line_item_product_stock
.
这样,我们检查是否满足$multiplier
的条件,我们防止它被调整。
/**
* 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 );
像许多其他用户一样,在遵循这个 tutorial 时,我 运行 遇到了以下问题
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.
如何防止这种情况?
p.s。几个月前我曾多次联系过教程作者,不幸的是没有任何回应
教程中的代码
/**
* 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 );
我第一次尝试,不幸的是一个肮脏的解决方案, 没有想要的结果
/**
* 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 );
解决方法是多加一个钩子,即woocommerce_prevent_adjust_line_item_product_stock
.
这样,我们检查是否满足$multiplier
的条件,我们防止它被调整。
/**
* 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 );