Charge only the highest shipping class cost in WooCommerce

119 Views Asked by At

I am trying to get the shipping class associated with each line item for both simple and variable products, then find out which one has the highest cost and charge that only removing the rest of the shipping cost. It's for WooCommerce.

What I did-

  1. Added two zones
  2. Added two shipping class
  3. Added price for both classes in the method
  4. Set By class as the calculation method
  5. Set the shipping class in the product variations

Edit: code so far added.

add_filter('woocommerce_package_rates', 'custom_shipping_method_by_class', 10, 2);

function custom_shipping_method_by_class($rates, $package)
{
    $class_costs = array();

    foreach ($package['contents'] as $item) {
        $product_id = $item['product_id'];
        $product = wc_get_product($product_id);

        if ($product instanceof WC_Product_Variable) {
            foreach ($product->get_visible_children() as $variation_id) {
                $term = wp_get_post_terms($variation_id, 'product_shipping_class');

                if (!empty($term)) {
                    $term = reset($term);
                    $class_costs[$term->term_id] = max($class_costs[$term->term_id] ?? 0, $rates["{$term->term_id}:$variation_id"]->cost);

                    var_dump($class_costs); // I get 0 here although I the variation has the shipping class set and the class has an amount set too.
                }
            }
        } else {
            $term = wp_get_post_terms($product_id, 'product_shipping_class');

            if (!empty($term)) {
                $term = reset($term);
                $class_costs[$term->term_id] = max($class_costs[$term->term_id] ?? 0, $rates["{$term->term_id}:$product_id"]->cost);
            }
        }
    }

    foreach ($rates as $rate_key => $rate) {
        list($class_id, $product_id) = explode(':', $rate_key);

        if (!array_key_exists($class_id, $class_costs) || $class_costs[$class_id] !== $rate->cost) {
            unset($rates[$rate_key]);
        }
    }

    return $rates;
}
1

There are 1 best solutions below

3
On BEST ANSWER

You don't need any code as there is "Calculation type" setting option (select field) on each Flat rate, where you can select between "Per class: Charge shipping for each shipping class individually" or "Per order: Charge shipping for the most expensive shipping class":

enter image description here

See the Flat Rate shipping method WooCommerce documentation