如何在计算总计之前获得折扣金额以在 WooCommerce 中将购物车商品价格设置为零

How to get discount amount to set cart item prices to zero in WooCommerce before calculating totals

我正在使用 woocommerce_before_calculate_totals 将产品价格更新为 0(使用 set_price),效果很好,但我不知道购物车折扣金额(优惠券)是多少,我有知道这一点,因为我只想在购物车的总价为 100 美元或更多(优惠券折扣后)时更改价格。

当我使用 woocommerce_after_calculate_totals 时,我可以知道购物车的折扣金额 但我无法更改产品价格

我意识到当我同时使用两者时它可以正常工作,但我想知道是否有更好的方法来做到这一点。

function check_gift_status() {

    $gift_products = new WP_Query( array(
        'post_type'   => 'product',
        'post_status' => 'publish',
        'fields'      => 'ids',
        'posts_per_page' => -1,
        'tax_query'   => array(
            'relation' => 'AND',
            array(
                'taxonomy' => 'product_cat',
                'field'    => 'term_id',
                'terms'    => 405,
            )
        ),

    ) );
    $all_gift_products_ids = $gift_products->posts;

    $gift_product_price_limit = 100;


    $total = 0;
    foreach ( WC()->cart->cart_contents as $key => $item ) {
        $current_product_id = $item['product_id'];
        if(in_array($current_product_id, $all_gift_products_ids)) continue;
        $total += (float)$item['line_subtotal'];
    }
    
    
    $discount_excl_tax_total = WC()->cart->get_cart_discount_total();
    $discount_tax_total = WC()->cart->get_cart_discount_tax_total();
    $discount_total = $discount_excl_tax_total + $discount_tax_total;
    
    $total -= $discount_total; 

    return ($total >= $gift_product_price_limit);
}


add_action( 'woocommerce_before_calculate_totals', 'conditionally_change_cart_items_price', 10, 1 );
add_action( 'woocommerce_after_calculate_totals', 'conditionally_change_cart_items_price', 10, 1 );
function conditionally_change_cart_items_price( $cart_object ) {

    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;
    
    $gift_products = new WP_Query( array(
        'post_type'   => 'product',
        'post_status' => 'publish',
        'fields'      => 'ids',
        'posts_per_page' => -1,
        'tax_query'   => array(
            'relation' => 'AND',
            array(
                'taxonomy' => 'product_cat',
                'field'    => 'term_id',
                'terms'    => 405,
            )
        ),

    ) );
    $all_gift_products_ids = $gift_products->posts;

    if(check_gift_status()) {
        foreach ( $cart_object->get_cart() as $key => $val ) {
            $current_product = $val['data'];
            if(in_array($current_product->id, $all_gift_products_ids)) {
               $current_product->set_price( 0 );
            }
        }
    }
}

您可以从当前客户会话 (WC_Session) 中获取购物车总数。

在挂钩内 woocommerce_before_calculate_totals 使用 WC()->session->get('cart_totals'); 获取购物车总数。

您还可以通过 Wordpress has_term 功能检查产品是否属于特定产品类别。

In your code, you are subtracting both the discount tax and the discount amount. If the products are priced excluding taxes, perhaps you should only subtract the discount amount.

优化后的函数为:

// Set cart item prices to zero based on cart total.
add_action( 'woocommerce_before_calculate_totals', 'conditionally_change_cart_items_price', 99, 1 );
function conditionally_change_cart_items_price( $cart ) {

    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;
    
    // Defines the gift product category id.
    $gift_product_cat_id       = 405;

    // Set the threshold for applying prices to zero.
    $gift_product_price_limit  = 100;

    // Gets the total cart discount from the current customer session.
    $cart_totals               = WC()->session->get('cart_totals');
    $total_discount            = $cart_totals['discount_total'] + $cart_totals['discount_tax'];
    
    // Calculates the sum of the cart item prices that do not belong to the gift product category.
    $total = 0;
    foreach ( $cart->get_cart() as $cart_item ) {
        if ( ! has_term( $gift_product_cat_id, 'product_cat', $cart_item['product_id'] ) ) {
            $total += (float) $cart_item['line_subtotal'];
        }
    }

    // If the product subtotal (including discounts) is greater than or equal to the threshold, set the gift item prices to zero.
    if ( ( $total - $total_discount ) >= $gift_product_price_limit ) {
        foreach ( $cart->get_cart() as $cart_item ) {
            if ( has_term( $gift_product_cat_id, 'product_cat', $cart_item['product_id'] ) ) {
                $cart_item['data']->set_price( 0 );
            }
        }
    }

}

代码已经过测试并且可以工作。将它添加到您的活动主题 functions.php.