我正在try 添加一个自定义股票设置字段到我的WooCommerce产品.产品页面将显示一个数字与库存的总和从两个"仓库".

我有一个工作代码,添加这样一个字段到简单的产品,一切工作完美.

不幸的是,我有一个问题的产品与产品变化.我有一个代码,在产品设置中添加了一个带有附加库存的字段,但产品页面只显示标准库存中的库存.

简单产品的工作代码:

// Adding a second stock level
add_action( 'woocommerce_product_options_stock', 'bbloomer_additional_stock_location_for_simple_products' );

function bbloomer_additional_stock_location_for_simple_products() {
    global $product_object;
    if ($product_object->get_type() === 'simple') {
        echo '<div class="show_if_simple">';
        woocommerce_wp_text_input(
            array(
                'id' => '_stock2',
                'value' => get_post_meta( $product_object->get_id(), '_stock2', true ),
                'label' => '2nd Stock Location',
                'data_type' => 'stock',
            )
        );
        echo '</div>';
    }
}

add_action( 'save_post_product', 'bbloomer_save_additional_stock_for_simple_products' );

function bbloomer_save_additional_stock_for_simple_products( $product_id ) {
    $product = wc_get_product( $product_id );
    if ( $product && $product->get_type() === 'simple' ) {
        if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
        if ( isset( $_POST['_stock2'] ) ) {
            update_post_meta( $product_id, '_stock2', sanitize_text_field( $_POST['_stock2'] ) );
        }
    }
}

add_filter( 'woocommerce_product_get_stock_quantity' , 'bbloomer_get_overall_stock_quantity', 9999, 2 );

function bbloomer_get_overall_stock_quantity( $value, $product ) {
    $value = (int) $value + (int) get_post_meta( $product->get_id(), '_stock2', true );
    return $value;
}

add_filter( 'woocommerce_product_get_stock_status' , 'bbloomer_get_overall_stock_status', 9999, 2 );

function bbloomer_get_overall_stock_status( $status, $product ) {
    if ( ! $product->managing_stock() ) return $status;
    $stock = (int) $product->get_stock_quantity() + (int) get_post_meta( $product->get_id(), '_stock2', true );
    $status = $stock && ( $stock > 0 ) ? 'instock' : 'outofstock';
    return $status;
}

add_filter( 'woocommerce_payment_complete_reduce_order_stock', 'bbloomer_maybe_reduce_second_stock', 9999, 2 );

function bbloomer_maybe_reduce_second_stock( $reduce, $order_id ) {
    $order = wc_get_order( $order_id );
    $atleastastock2change = false;
    foreach ( $order->get_items() as $item ) {   
        if ( ! $item->is_type( 'line_item' ) ) {
            continue;
        }
        $product = $item->get_product();
        $item_stock_reduced = $item->get_meta( '_reduced_stock', true );
        if ( $item_stock_reduced || ! $product || ! $product->managing_stock() ) {
            continue;
        }
        $qty = apply_filters( 'woocommerce_order_item_quantity', $item->get_quantity(), $order, $item );
        $stock1 = (int) get_post_meta( $product->get_id(), '_stock', true );
        if ( $qty <= $stock1 ) continue;
        $atleastastock2change = true;
    }
    if ( ! $atleastastock2change ) return $reduce;  
    foreach ( $order->get_items() as $item ) {   
        if ( ! $item->is_type( 'line_item' ) ) {
            continue;
        }
        $product = $item->get_product();
        $item_stock_reduced = $item->get_meta( '_reduced_stock', true );
        if ( $item_stock_reduced || ! $product || ! $product->managing_stock() ) {
            continue;
        }  
        $item_name = $product->get_formatted_name();
        $qty = apply_filters( 'woocommerce_order_item_quantity', $item->get_quantity(), $order, $item );
        $stock1 = (int) get_post_meta( $product->get_id(), '_stock', true );
        $stock2 = (int) get_post_meta( $product->get_id(), '_stock2', true );
        if ( $qty <= $stock1 ) {
            wc_update_product_stock( $product, $qty, 'decrease' );
            $order->add_order_note( sprintf( 'Reduced stock for item "%s"; Stock 1: "%s" to "%s".', $item_name, $stock1, $stock1 - $qty ) );
        } else {    
            $newstock2 = $stock2 - ( $qty - $stock1 );
            wc_update_product_stock( $product, $stock1, 'decrease' );
            update_post_meta( $product->get_id(), '_stock2', $newstock2 );
            $item->add_meta_data( '_reduced_stock', $qty, true );
            $item->save();          
            $order->add_order_note( sprintf( 'Reduced stock for item "%s"; Stock 1: "%s" to "0" and Stock 2: "%s" to "%s".', $item_name, $stock1, $stock2, $newstock2 ) );
        }
    }
    $order->get_data_store()->set_stock_reduced( $order_id, true );
    return false;
}

产品变更代码(不起作用):

// Dodanie drugiego stanu magazynowego - produkty wariantowe
add_action( 'woocommerce_variation_options_pricing', 'bbloomer_additional_stock_location_for_variable_variations', 10, 3 );
 
function bbloomer_additional_stock_location_for_variable_variations( $loop, $variation_data, $variation ) {
    woocommerce_wp_text_input(
        array(
            'id' => '_stock2_variable[' . $loop . ']',
            'value' => get_post_meta( $variation->ID, '_stock2_variable', true ),
            'label' => '2nd Stock Location',
            'data_type' => 'stock',
        )
    );
}
 
// Save additional stock for variable product variations
add_action( 'woocommerce_save_product_variation', 'bbloomer_save_additional_stock_for_variable_variations', 10, 2 );
 
function bbloomer_save_additional_stock_for_variable_variations( $variation_id, $i ) {
    if ( isset( $_POST['_stock2_variable'][$i] ) ) {
        update_post_meta( $variation_id, '_stock2_variable', sanitize_text_field( $_POST['_stock2_variable'][$i] ) );
    }
}
 
// Get overall stock quantity for variable products
add_filter( 'woocommerce_product_get_stock_quantity' , 'bbloomer_get_overall_stock_quantity_variable', 9999, 2 );
 
function bbloomer_get_overall_stock_quantity_variable( $value, $product ) {
    if ($product->get_type() === 'variable') {
        $variations = $product->get_available_variations();
        $stock2_total = 0;
        foreach ($variations as $variation) {
            $stock2_total += (int) get_post_meta( $variation['variation_id'], '_stock2_variable', true );
        }
        $value += $stock2_total;
    }
    return $value;
}
 
// Get overall stock status for variable products
add_filter( 'woocommerce_product_get_stock_status' , 'bbloomer_get_overall_stock_status_variable', 9999, 2 );
 
function bbloomer_get_overall_stock_status_variable( $status, $product ) {
    if ($product->get_type() === 'variable') {
        $variations = $product->get_available_variations();
        $stock2_total = 0;
        foreach ($variations as $variation) {
            $stock2_total += (int) get_post_meta( $variation['variation_id'], '_stock2_variable', true );
        }
        $stock = (int) $product->get_stock_quantity() + $stock2_total;
        $status = $stock && ( $stock > 0 ) ? 'instock' : 'outofstock';
    }
    return $status;
}
 
// Reduce second stock upon order completion for variable product variations
add_filter( 'woocommerce_payment_complete_reduce_order_stock', 'bbloomer_maybe_reduce_second_stock_variable', 9999, 2 );
 
function bbloomer_maybe_reduce_second_stock_variable( $reduce, $order_id ) {
    $order = wc_get_order( $order_id );
    foreach ( $order->get_items() as $item ) {  
        if ( ! $item->is_type( 'line_item' ) ) {
            continue;
        }
        $product = $item->get_product();
        if ( $product && $product->get_type() === 'variation' ) {
            $item_stock_reduced = $item->get_meta( '_reduced_stock_variable', true );
            if ( $item_stock_reduced || ! $product->managing_stock() ) {
                continue;
            }
            $qty = apply_filters( 'woocommerce_order_item_quantity', $item->get_quantity(), $order, $item );
            $stock1 = (int) get_post_meta( $product->get_id(), '_stock', true );
            if ( $qty <= $stock1 ) continue;
            $stock2 = (int) get_post_meta( $product->get_id(), '_stock2_variable', true );
            $new_stock2 = $stock2 - ( $qty - $stock1 );
            if ($new_stock2 < 0) {
                $new_stock2 = 0;
            }
            update_post_meta( $product->get_id(), '_stock2_variable', $new_stock2 );
            $item->add_meta_data( '_reduced_stock_variable', $qty, true );
            $item->save();          
            $order->add_order_note( sprintf( 'Reduced stock for variation "%s"; Stock 1: "%s" to "0" and Stock 2 (Variable): "%s" to "%s".', $item->get_name(), $stock1, $stock2, $new_stock2 ) );
        }
    }
    $order->get_data_store()->set_stock_reduced( $order_id, true );
    return false;
}

推荐答案

try 以下代码替换,它应该适用于所有产品:

add_action( 'woocommerce_product_options_stock', 'azt_add_product_2nd_stock' );
function azt_add_product_2nd_stock() {
    global $product_object;

    echo '<div class="hide_if_variable">';
    woocommerce_wp_text_input( array(
        'id'                => '_stock2',
        'value'             => wc_stock_amount( $product_object->get_meta( '_stock2' ) ?? 0 ),
        'label'             => __( 'Quantity (2nd Stock)', 'woocommerce' ),
        'desc_tip'          => true,
        'description'       => __( 'Set the stock quantity from the 2nd stock location', 'woocommerce' ),
        'type'              => 'number',
        'custom_attributes' => array( 'step' => 'any' ),
        'data_type'         => 'stock',
    ) );
    echo '</div>';
}

add_action( 'woocommerce_variation_options_pricing', 'azt_add_product_variation_2nd_stock', 10, 3 );
function azt_add_product_variation_2nd_stock( $loop, $variation_data, $variation ) {
    woocommerce_wp_text_input( array(
        'id'                => '_stock2['.$loop.']',
        'value'             => wc_stock_amount( get_post_meta($variation->ID, '_stock2', true) ),
        'label'             => __( 'Quantity (2nd Stock)', 'woocommerce' ),
        'desc_tip'          => true,
        'description'       => __( 'Set the stock quantity from the 2nd stock location', 'woocommerce' ),
        'type'              => 'number',
        'custom_attributes' => array( 'step' => 'any' ),
        'data_type'         => 'stock',
    ) );
}

add_action( 'woocommerce_admin_process_product_object', 'azt_save_product_2nd_stock' );
function azt_save_product_2nd_stock( $product ) {
    if ( ! $product->is_type('variable') && isset($_POST['_stock2']) ) {
        $product->update_meta_data( '_stock2', wc_stock_amount( wp_unslash($_POST['_stock2']) ) );
    }
}

add_action( 'woocommerce_admin_process_variation_object', 'azt_save_product_variation_2nd_stock', 10, 2 );
function azt_save_product_variation_2nd_stock( $variation, $i ) {
    if ( isset($_POST['_stock2'][$i]) ) {
        $variation->update_meta_data( '_stock2', wc_stock_amount( wp_unslash($_POST['_stock2'][$i]) ) );
    }
}

add_filter( 'woocommerce_product_get_stock_quantity' , 'azt_get_overall_stock_quantity', 9999, 2 );
add_filter( 'woocommerce_product_variation_get_stock_quantity' , 'azt_get_overall_stock_quantity', 9999, 2 );
function azt_get_overall_stock_quantity( $value, $product ) {
    return $value + (int) $product->get_meta('_stock2');
}

add_filter( 'woocommerce_product_get_stock_status' , 'azt_get_overall_stock_status', 9999, 2 );
add_filter( 'woocommerce_product_variation_get_stock_status' , 'azt_get_overall_stock_status', 9999, 2 );
function azt_get_overall_stock_status( $status, $product ) {
    if ( $product->managing_stock() ) {
        $stock  = (int) $product->get_stock_quantity() + (int) $product->get_meta('_stock2');
        $status = $stock && ( $stock > 0 ) ? 'instock' : 'outofstock';
    } 
    return $status;
}

add_filter( 'woocommerce_payment_complete_reduce_order_stock', 'azt_maybe_reduce_second_stock', 9999, 2 );
function azt_maybe_reduce_second_stock( $reduce, $order_id ) {
    $order = wc_get_order( $order_id );
    $flag  = false;
    foreach ( $order->get_items() as $item ) {   
        if ( $item->is_type( 'line_item' ) ) {
            $product       = $item->get_product();
            $reduced_stock = $item->get_meta('_reduced_stock', true );
            if ( $reduced_stock ||  ! $product->managing_stock() ) {
                continue;
            }
            $qty   = apply_filters( 'woocommerce_order_item_quantity', $item->get_quantity(), $order, $item );
            $stock = (int) $product->get_stock_quantity();
            if ( $qty <= $stock ) continue;
            $flag = true;
        }
    }

    if ( ! $flag ) {
        return $reduce;
    }

    foreach ( $order->get_items() as $item ) {   
        if ( $item->is_type( 'line_item' ) ) {
            $product = $item->get_product();
            $item_stock_reduced = $item->get_meta( '_reduced_stock', true );
            if ( $item_stock_reduced || ! $product || ! $product->managing_stock() ) {
                continue;
            }  
            $item_name = $product->get_formatted_name();
            $qty = apply_filters( 'woocommerce_order_item_quantity', $item->get_quantity(), $order, $item );
            $stock  = (int) $product->get_stock_quantity();
            $stock2 = (int) $product->get_meta('_stock2');
            if ( $qty <= $stock ) {
                wc_update_product_stock( $product, $qty, 'decrease' );
                $order->add_order_note( sprintf( 'Reduced stock for item "%s"; Stock 1: "%s" to "%s".', $item_name, $stock1, $stock1 - $qty ) );
            } else {    
                $new_stock2 = $stock2 - ( $qty - $stock );
                wc_update_product_stock( $product, $stock, 'decrease' );
                $product->update_meta_data('_stock2', $new_stock2);
                $product->save(); 
                $item->add_meta_data( '_reduced_stock', $qty, true );
                $item->save();          
                $order->add_order_note( sprintf( 'Reduced stock for item "%s"; Stock 1: "%s" to "0" and Stock 2: "%s" to "%s".', $item_name, $stock1, $stock2, $newstock2 ) );
            }
        }
    }
    $order->get_data_store()->set_stock_reduced( $order_id, true );
    return false;
}

它应该有用.

Php相关问答推荐

Laravel 10查询中的多个where子句

累加平面数组中数字子集的所有组合,以生成组合及其乘积的二维数组

在php中有没有办法比较两个包含相同枚举类型的枚举数组

从WooCommerce购物车和 checkout 页面自定义发货标签

使用WordPress wp_mail()的邮箱标题无效

在特定订单状态更改时自定义WooCommerce订单发货项目

在WooCommerce产品变体SKU字段旁边添加自定义输入字段

根据WooCommerce中的客户计费国家/地区更改产品价格

列出所有WooCommerce处理订单中的产品数量,SKU和品牌

如何在execute语句中使用存储过程参数?

将WooCommerce WC_Order对象与wp_Schedule_Event一起使用

在带有livewire 3的laravel中使用规则方法时,无法进行实时验证

Laravel路由到控制器传输变量解决方案需要

使用HPOS过滤WooCommerce中的订单列表

使用 PHP,我可以将 foreach 语句放入瞬态中吗?

如何显示所有数组数据而不仅仅是最后的结果

添加或删除优惠券后自动刷新 WooCommerce checkout 表单字段

基于WooCommerce中的产品变体自定义感谢页面跳转

PHP 中是否有 is_closure() 函数?

根据数组中的文本文件编号显示星级