phpwordpresswoocommercetaxonomy-terms

Discount cart item price excluding a category and its children in WooCommerce


The fact is that the customer asks for a 50% discount for "Local Pickup" - I have already done this (I found a code here on StackOverFlow that applies a discount on all goods), but there is one more condition - this discount should not be applied to two categories goods. Sorry for Russian image;)

I tried to go through each product in the list of orders, and check whether it belongs to a certain category or not through various operators (is_category, in_category, has_term), but it didn't work. What am I doing wrong? (id = 37 is the id of the Premium rolls category)

add_action( 'woocommerce_before_calculate_totals', 'custom_cart_item_price', 10, 1 );
function custom_cart_item_price( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;
    
    $category_id = 37; // premium-rolls id
    $cats = hml_get_category_gender_line( $category_id );
    
    foreach ( $cart->get_cart() as $cart_item ){
        if (!has_term($cats, 'product_cat', $value['product_id'] )){
            $price = $cart_item['data']->get_price(); // Get the product price
            $new_price = $price-$price*50/100; // the calculation
            $cart_item['data']->set_price( $new_price ); // Set the new price
        }
        
    }
}

function hml_get_category_gender_line( $cat_parent ){
    // get_term_children() accepts integer ID only
    $line = get_term_children( (int) $cat_parent, 'product_cat');
    $line[] = $cat_parent;

    return $line;
}

Solution

  • Updated

    There are some mistakes in your code. The code below will apply a discounted price on cart items from specific product category (and its children):

    add_action( 'woocommerce_before_calculate_totals', 'custom_cart_item_price', 10, 1 );
    function custom_cart_item_price( $cart ) {
        if ( is_admin() && ! defined( 'DOING_AJAX' ) )
            return;
    
        if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
            return;
        
        $parent_id = 37; // premium-rolls id
        $taxonomy  = 'product_cat';
        
        foreach ( $cart->get_cart() as $cart_item ){
            $product_id = $cart_item['product_id'];
            $terms_ids  = get_term_children( $parent_id, $taxonomy, $product_id ); // get children terms ids array
            array_unshift( $terms_ids, $parent_id );  // insert parent term id to children terms ids array
            
            if ( ! has_term( $terms_ids, $taxonomy, $product_id ) ){
                $new_price = $cart_item['data']->get_price() / 2; // Get 50% of the initial product price
                $cart_item['data']->set_price( $new_price ); // Set the new price
            }
        }
    }
    

    Code goes in functions.php file of the active child theme (or active theme). It should works.