phpwordpresswoocommercecart

Exclude product categories from custom dynamic pricing in Woocommerce


I am working on a dynamic pricing system on my Wordpress store. I have set it up so users who have certain roles (right now, subscriber or admin - for testing purposes) get a 15% discount (price*0.85). However, I need to also exclude specific product categories from the discount rule.

Right now I have:

function add_cart_item_data( $cart_item_data, $product_id, $variation_id ) {
    //if admin || subscriber
    $role = get_user_role(); /* I know that isn't the default get user role. I made a shortened version of it in functions.php because I used it a lot in other functions */
    if (in_array("admin", $role) || in_array("subscriber", $role)){

        $product = wc_get_product( $product_id );

        // ==> Start: Needed product category check HERE
        $price = $product->get_price();
        $cart_item_data['RefPrice'] = $price * 0.85;
        // ==> End of product category check
    }
    return $cart_item_data;
}
add_filter( 'woocommerce_add_cart_item_data', 'add_cart_item_data', 10, 2 );



function before_calculate_totals( $cart_obj ) {

    if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
        return;
    }
    // Iterate through each cart item
    foreach( $cart_obj->get_cart() as $key=>$value ) {
        if( isset( $value['RefPrice'] ) ) {
            $price = $value['RefPrice'];
            $value['data']->set_price( ( $price ) );
        }
    }
}
add_action( 'woocommerce_before_calculate_totals', 'before_calculate_totals', 10, 1 );

This is working to modify the price by * 0.85 for certain roles, but I've hit a brick wall trying to exclude a product category from it. The product category ID is 978 (or its name is "last minute gifts").

How can I add in this check for each cart item?


Solution

  • Updated… Here is the way to exclude product categories from your custom dynamic pricing making small changes in your 1st hooked function.

    It use has_term() WordPress conditional function to exclude product categories, this way:

    function get_user_roles(){
        global $current_user;
        return $current_user->roles;
    }
    
    add_filter( 'woocommerce_add_cart_item_data', 'add_cart_item_data', 10, 2 );
    function add_cart_item_data( $cart_item_data, $product_id ) {
        // For administrator or subscriber user roles
        if ( count( array_intersect(array('administrator', 'subscriber'), get_user_roles() ) ) > 1 ) {
    
            // Excluded product categories in this array (Can be IDs, slugs or names)
            $excl_cats = array( 978 );  
    
            $product = wc_get_product( $product_id );
            // Excluding product categories
    
            if( ! has_term( $excl_cats, 'product_cat', $product_id ) ){
                $cart_item_data['ref_price'] = $product->get_price() * 0.85;
    
                // Every add to cart action is set as a unique line item
                $cart_item_data['unique_key'] = md5( microtime().rand() );
            }
        }
        return $cart_item_data;
    }
    
    add_action( 'woocommerce_before_calculate_totals', 'before_calculate_totals', 10, 1 );
    function before_calculate_totals( $cart ) {
        if ( is_admin() && ! defined( 'DOING_AJAX' ) ) 
            return;
    
        if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
            return;
    
        // Loop through cart items
        foreach( $cart->get_cart() as $cart_item ) {
            if( isset( $cart_item['ref_price'] ) ) {
                $cart_item['data']->set_price( floatval($cart_item['ref_price']) );
            }
        }
    }
    

    Code goes in function.php file of your active child theme (or active theme).

    Tested and works