Search code examples
phpwordpresswoocommercehook-woocommerceshipping-method

Exclude user role from custom shipping discount in Woocommerce


Based on Set custom shipping rates programmatically in Woocommerce 3 answer code, I modified it in order to add a discount on shipping rates for each seller.

add_filter( 'woocommerce_package_rates', 'custom_shipping_methods', 10, 2 );
function custom_shipping_methods( $rates, $package ) {
$reduction_cost_percentage = 30; // Discount percentage
foreach( WC()->cart->get_cart() as $cart_item  ){
    $in_cart_product_id = $cart_item['product_id'];
    $cart_seller_id = get_post_field('post_author', $in_cart_product_id);
    $cart_seller_meta = get_userdata($cart_seller_id);
    $cart_seller_roles = $cart_seller_meta->roles;
    if($cart_seller_roles[0] == 'seller'){
        foreach( $rates as $rate_key => $rate ){
            if( $rate->method_id != 'free_shipping'){
                $rates[$rate_key]->cost = $rates[$rate_key]->cost * ((100-$reduction_cost_percentage) / 100); 
                return $rates;
            }
        }
    }
  }
}

Now I want to exclude this discount from a certain role for example seller_2. How can I do this?


Solution

  • There are some mistakes and oversights in your code, try the following instead:

    add_filter( 'woocommerce_package_rates', 'custom_shipping_methods', 10, 2 );
    function custom_shipping_methods( $rates, $package ) {
        // Loop through cart items for the current package
        foreach( $package['contents'] as $cart_item ){
            $seller_id    = get_post_field('post_author', $cart_item['product_id']);
            $seller_data  = get_userdata($seller_id);
    
            // Excluding product 'seller' user role
            if ( ! empty($seller_data) && is_array($seller_data->roles) && in_array('seller', $seller_data->roles) ) {
                return $rates; // stop the loop and return normally the shipping rates
            }
        }
    
        $percentage    = 30; // <== Set your discount percentage
    
        $discount_rate = $percentage / 100;
    
        // Loop through shipping rates for the current package when seller user role is not found
        foreach( $rates as $rate_key => $rate ){
            // Not for free shipping
            if( $rate->method_id != 'free_shipping' ){
                // Change rate cost
                $rates[$rate_key]->cost = $rate->cost * $discount_rate;
    
                $taxes = array(); // Initializing
    
                // change taxes rate cost (if enabled)
                foreach ($rate->taxes as $key => $tax){
                    if( $tax > 0 ){
                        $taxes[$key] = $tax * $discount_rate;
                        $has_taxes = true;
                    }
                }
                // Change taxes cost
                if( $has_taxes ) {
                    $rates[$rate_key]->taxes = $taxes;
                }
            }
        }
        return $rates;
    }
    

    Code goes in function.php file of your active child theme (active theme). It should works.

    Clearing shipping caches:

    • You will need to empty your cart, to clear cached shipping data
    • Or In shipping settings, you can disable / save any shipping method, then enable back / save.