基于 WooCommerce 产品当前库存值的自定义库存字段计算

Custom stock field calculation based on current stock value of WooCommerce Product

我正在努力改善我的库存管理并直接从 WooCommerce 进行(这样就没有必要使用外部 CSV 文件计算)

我需要知道每种产品我需要订购多少(缺货)。 为了确定这一点,我使用 _stock 原始值和 2 个自定义字段进行计算:

_missing_stock : 缺货数量/我需要订购多少库存

_ref_stock : 参考库存数量(手动设置,仓库所需库存数量)

所以:缺失股票 = 参考股票 - 股票价值


目的是根据已设置的Reference Stock和产品的Current Stock自动计算更新Missing Stock值。 由于产品库存随着购买而减少,因此我可以快速查看每种产品需要订购的库存量。

基于 Product regular price calculation based on 2 custom fields in Woocommerce 3 答案代码,它有一些相似之处,我已经设法创建了自定义字段并且到目前为止。

但是我无法弄清楚如何最终自动更新 _missing_stock 值。

这是我想出的代码,当然(也可能)不完全正确。

// Adding and displaying additional Stock custom fields
add_action( 'woocommerce_product_options_stock_status', 'additional_product_stock_option_fields', 50 );
function additional_product_stock_option_fields() {
    $domain = "woocommerce";
    global $post;

    echo '</div><div class="options_group stock show_if_simple show_if_external show_if_composite">';

    woocommerce_wp_text_input( array(
        'id'            => '_ref_stock',
        'label'         => __("Reference Stock", $domain ),
        'placeholder'   => '',
        'description'   => __("Amount of desired target stock in warehouse )", $domain ),
        'desc_tip'      => true,
    ) );


    woocommerce_wp_text_input( array(
        'id'            => '_missing_stock',
        'label'         => __("Missing Stock", $domain ) . ' ('. get_woocommerce_currency_symbol() . ')',
        'placeholder'   => '',
        'description'   => __("Amount of stock that needs to be ordered", $domain ),
        'desc_tip'      => true,
    ) );

    echo '<input type="hidden" name="_custom_stock_nonce" value="' . wp_create_nonce() . '">';

}

// Utility function that save "Reference Stock" and "missing_stock" custom fields values
function saving_ref_stock_and_missing_stock( $product ) {
    // Security check
    if ( isset($_POST['_custom_stock_nonce']) && ! wp_verify_nonce($_POST['_custom_stock_nonce']) ) {
        return;
    }

    // Save "Reference Stock" and "missing_stock" custom fields values
    if( isset($_POST['_ref_stock']) && isset($_POST['_missing_stock']) ) {
        $product->update_meta_data('_ref_stock', sanitize_text_field( (float) $_POST['_ref_stock'] ) );
        $product->update_meta_data('_missing_stock', sanitize_text_field( (float) $_POST['_missing_stock'] ) );
    }
}

// Utility function: Calculate and save product "missing stock" custom field from the "Reference Stock" custom field and the "Stock" field
function calculate_and_save_new_product_stock( $product ) {

// Check if product stock management is enabled
 if ( !$product->managing_stock() ) {
    // Calculate and save the missing stock
    if( isset($_POST['_ref_stock']) && isset($_POST['_missing_stock'])
    && $_POST['_ref_stock'] > 0 && $_POST['_missing_stock'] > 0 ) {

        // Catch the stock data
        $ref_stock    = (float) $_POST['_ref_stock'];
        $missing_stock = (float) $_POST['_missing_stock'];
        $current_stock   = (float) $product->get_stock_quantity();

        // Calculating missing stock
        $missing_stock  = $ref_stock - $current_stock;

     
        }
    }
}

// Saving and calculating Stock values
add_action( 'woocommerce_admin_process_product_object', 'update_product_meta_data', 100, 1 );
function update_product_meta_data( $product ) {

    // Saving "Reference Stock" and "missing_stock" custom fields values
    saving_ref_stock_and_missing_stock( $product ); // <== To be removed if not used with the first function

    // Calculate and save Missing Stock from the "Reference Stock" and the "Stock" custom fields
    calculate_and_save_new_product_missing_stock( $product );
}

在此先感谢您的关注和建议。

您已经在使用和改编的代码比您的问题稍微广泛一些,因此下面是一个简化版本。

当您要在后台保存调整以确定自定义字段的值时,您确实可以使用 woocommerce_admin_process_product_object

但是下单后当库存发生调整时,您自定义字段的值不会自动调整。

为此,您可以使用 woocommerce_product_set_stock 操作挂钩。

此代码是为 'simple' 产品编写的,但如果需要可以轻松扩展到其他类型的产品。

通过在代码中添加的注释标签进行解释

// Adding and displaying additional custom fields
function action_woocommerce_product_options_stock_status() {
    $domain = 'woocommerce';
    
    echo '</div><div class="options_group">';
    
    woocommerce_wp_text_input( array(
        'id'                 => '_ref_stock',
        'label'              => __( 'Reference Stock', $domain ),
        'placeholder'        => '',
        'description'        => __( 'Amount of desired target stock in warehouse', $domain ),
        'desc_tip'           => true,
    ));

    woocommerce_wp_text_input( array(
        'id'                 => '_missing_stock',
        'label'              => __( 'Missing Stock', $domain ),
        'placeholder'        => '',
        'description'        => __( 'Amount of stock that needs to be ordered', $domain ),
        'desc_tip'           => true,
        'custom_attributes'  => array( 'readonly' => 'readonly' ),
    ));
}
add_action( 'woocommerce_product_options_stock_status', 'action_woocommerce_product_options_stock_status', 10, 1 );

// Save custom field
function action_woocommerce_admin_process_product_object( $product ) {
    // Isset
    if ( isset( $_POST['_ref_stock'] ) ) {
        // ID & value
        $ref_stock_id = '_ref_stock';
        $ref_stock_val = sanitize_text_field( $_POST['_ref_stock'] );
        
        // Update ref stock
        $product->update_meta_data( $ref_stock_id, $ref_stock_val );
        
        // Get stock quantity
        $current_stock = (float) $product->get_stock_quantity();

        // NOT empty
        if ( ! empty ( $current_stock ) ) {
            // ID
            $missing_stock_id = '_missing_stock';
            
            // Calculating missing stock
            $missing_stock_val = $ref_stock_val - $current_stock;
            
            // Update missing stock
            $product->update_meta_data( $missing_stock_id, $missing_stock_val );
        }
    }
}
add_action( 'woocommerce_admin_process_product_object', 'action_woocommerce_admin_process_product_object', 10, 1 );

// When the stock changed
function action_woocommerce_product_set_stock ( $product_with_stock ) {
    global $pagenow;

    // Exit
    if ( is_admin() && $pagenow === 'post.php' )
        return;
    
    // Get meta
    $ref_stock_val = $product_with_stock->get_meta( '_ref_stock' );
    
    // NOT empty
    if ( ! empty ( $ref_stock_val ) ) {
        // Get stock quantity
        $current_stock = (float) $product_with_stock->get_stock_quantity();

        // NOT empty
        if ( ! empty ( $current_stock ) ) {
            // ID
            $missing_stock_id = '_missing_stock';
            
            // Calculating missing stock
            $missing_stock_val = $ref_stock_val - $current_stock;
            
            // Update missing stock
            $product_with_stock->update_meta_data( $missing_stock_id, $missing_stock_val );
            
            // Save
            $product_with_stock->save();
        }       
    }
}
add_action( 'woocommerce_product_set_stock', 'action_woocommerce_product_set_stock', 10, 1 );