1
votes

In WooCommerce I would like to exclude certain products in the shopping cart from calculating the shipping cost, based on certain conditions. After trying various ways an Googling for hours, I can't find any way to calculate the shipping cost only over the remaining products.

The webshop uses many shipping classes for various types of product. The shipping cost for the various classes are being add up. When a certain amount of specific products is ordered, those products will be shipped for free, but for the other products in the cart the shipping cost still need to be calculated, even if they belong to the same shipping class as the product that is shipped for free.

What I tried

My first idea was to use the woocommerce_package_rates filter and remove the shipping cost of the matching products. But that turned out to be very complex, as I could not calculate the actual shipping cost for those products. Additionally, there might be other products in the cart available with the same shipping class.

Then I thought the solution might be to update the shipping class for the product instance in the cart to a Free Shipping class, using the set_shipping_class_id() method on the cart-data after adding an action to the woocommerce_before_calculate_totals hook:

add_action('woocommerce_before_calculate_totals', 'updateShippingClasses', 30, 1);
function updateShippingClasses($rates) {

    if (is_admin() && !defined('DOING_AJAX')) {
        return;
    }

    foreach (WC()->cart->get_cart() as $cart_item) {
        if (my_condition) {
            $cart_item['data']->set_shipping_class_id(1947); // The Free Shipping class ID.
        }
    }
}

It adds the "changed" shipping_class_id value to the object, but it's not used to calculate the shipping cost: the original values still remain.

On the internet I found many similar questions, but every time it was about making the shipping completely free or update the class for the product itself. But in my case, that is not the solution.

I adopted various solutions for these issues, using the above mentioned hooks, as well as the woocommerce_shipping_rate_cost, but with none of them I achieved what I am looking for.

Is there any way to programmatically exclude some products from calculating the shipping cost, but still calculate the shipping cost of the remaining products in the cart?

1
I tried to keep it short, as I thought my question was pretty long already. That is why I only mentioned the hooks and actions I used. I will update my post. Please note that I am not even looking for a coding service. In my search for a solution I found similar questions many times, and working solutions for that, but never for calculating the shipping cost over a part of the cart contents. I think it can be very useful for other WooCommerce users/programmers as well who could face this in the future.Colydon

1 Answers

1
votes

In your case woocommerce_cart_shipping_packages hook is the right hook to be used for shipping costs based on shipping class change based on specific conditions like:

add_action('woocommerce_cart_shipping_packages', 'alter_item_shipping_class_for_shipping_cost_change' );
function alter_item_shipping_class_for_shipping_cost_change( $shipping_packages ) {
    foreach ( $shipping_packages as $key => $package ) {
        foreach ( $package['contents'] as $cart_item_key => $cart_item ) {
            if ( true ) {
                $package['contents'][$cart_item_key]['data']->set_shipping_class_id(1947);
            }
        }
    }
    return $shipping_packages;
}

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