0

I'm trying to add a 50% discount to all shipping classes in cart other than the highest shipping class.

If I have 3 products in the cart, each with its own shipping class pricing like P1=$150; P2=$200; P3=$300. Expected sum of shipping costs would be: (P1/50%)+(P2/50%)+P3(most expensive)= $475

Products with ID1, ID2, ID3 should not be discounted even if their shipping class is less expensive than others in the cart. Shipping for those products should always be fully charged.

First I tried to add a discount to a single shipping class using the shipping class slug, my question can be found here [question]: Shipping cost discount based on a shipping classes in Woocommerce

But I don't know how to retrieve the highest (most expensive) shipping class in a cart and discount all other shipping classes by 50%, because each time there may be a different shipping class (with different slug) in a cart that is most expensive.

I've been researching WooCommerce API documentation found here https://docs.woocommerce.com/wc-apidocs/class-WC_Shipping_Method.html but I can't tell which method would be helpful in my case.

It's a very similar request to this unanswered question Woocommerce shipping - multiple item discount with different prices per class

Is there a method to discount all shipping class prices on cart other than the most expensive one?

Mario83
  • 143
  • 15

1 Answers1

1

This is probably not the best way to do it, but it works. Since I couldn't get the shipping class costs in a smarter way, I used a shipping class description field as a value. So if the cost for the class "medium" is 80, my description is also 80.

Assuming you only use one shipping method "flat rate" this is the code that works.

add_filter('woocommerce_package_rates', 'shipping_costs_discounted_based_on_shipping_class', 10, 2);
function shipping_costs_discounted_based_on_shipping_class( $rates, $package ){
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
    return $rates;
    $shipping           = new \WC_Shipping();
    $shipping_classes   = $shipping->get_shipping_classes();
    $all_shipping_costs = array();

    foreach( $package['contents'] as $cart_item ) {
        foreach($shipping_classes as $shipping_class) {
            if( $cart_item['data']->get_shipping_class() == $shipping_class->slug )
            array_push($all_shipping_costs, $shipping_class->description);
        }
    }
    $max_value=max($all_shipping_costs);
    $new_rate=$max_value + (array_sum($all_shipping_costs)-$max_value)*0.50;
    foreach ( $rates as $rate_key => $rate ){
            if( 'flat_rate' === $rate->method_id  ){
            $rates[$rate_key]->cost = $new_rate;
            }
        }

    return $rates;

}

Once again, this is a working solution, but not the best one.

NOTE: Shipping Class Description fields in the backend need to have exact same value as shipping costs field!