Search Knowledge Base by Keyword

Waving off or discounting the shipping cost of a product, if certain other product is present in the cart

In this article, we will explain the solution to an interesting problem of WooCommerce product mutual dependency to calculate shipping cost and how WooCommerce Table Rate Shipping Pro can solve that.

Requirement : let’s begin the fun

  • If the user has ordered products only from product category “bulky”, each line item in the cart should be charged a delivery fee. These products cannot be mixed and require multiple deliveries.
  • If the user has ordered products only from product category “small”, only one line item in the cart should be charged a delivery fee. These are small products that are delivered together and should only be charged delivery for one item.
  • If the user has ordered products from product category “small” and “bulky” together, then all products from “bulky” category should be charged a delivery fee and all the products from category “small” should be shipped free.  small products can be delivered along with “bulky” products without additional cost.

Any guess how can we achieve this without touching the shipping method which calculates the shipping cost per line item?
First clue for you:
From WooCommerce 2.1 its possible to split the packages into multiple packages and shipping method’s will calculate the shipping cost for each package separately.
Did you solve it? Second clue for you:
This also provides a flexibility to enforce shipping method on the particular package.

Exactly you can split the packages into two packages. One package with all the products with shipping cost applicable and second package with all the products shipped free. Finally apply a free shipping method to the second package.

Code to achieve the same

add_filter( 'woocommerce_cart_shipping_packages', 'wf_category_package_split_packages' );
function wf_category_package_split_packages( $packages ) {
$packages = array();$bulky_items = array();$regular_items = array();$free_items = array();
$cost_items = array();
foreach ( WC()->cart->get_cart() as $item ) {
if ( $item['data']->needs_shipping() ) {
if ( wf_category_package_is_bulk_category($item['data']->id)) {
$bulky_items[] = $item;
} else {
$regular_items[] = $item;
}}}
if(!empty($bulky_items) && !empty($regular_items)){
//if both bulky and regular items available then entire regular items goes to Free shipping
$free_items = $regular_items;
$cost_items = $bulky_items;
}
elseif(empty($bulky_items) && !empty($regular_items) && count($regular_items) > 1)
{
//Except one regular item every thing else will be free shipping
$cost_items[] = array_shift($regular_items);
$free_items = $regular_items;
}
else
$cost_items = array_merge($bulky_items, $regular_items);
// Put inside packages
if ( $cost_items ) {
$packages[] = array(
'ship_via' => array( 'distance_rate_shipping' ),
'contents' => $cost_items,
'contents_cost' => array_sum( wp_list_pluck( $cost_items, 'line_total' ) ),
'applied_coupons' => WC()->cart->applied_coupons,
'destination' => array(
'country' => WC()->customer->get_shipping_country(),
'state' => WC()->customer->get_shipping_state(),
'postcode' => WC()->customer->get_shipping_postcode(),
'city' => WC()->customer->get_shipping_city(),
'address' => WC()->customer->get_shipping_address(),
'address_2' => WC()->customer->get_shipping_address_2()));
}
if ( $free_items ) {
$packages[] = array(
'ship_via' => array( 'free_shipping' ),
'contents' => $free_items,
'contents_cost' => array_sum( wp_list_pluck( $free_items, 'line_total' ) ),
'applied_coupons' => WC()->cart->applied_coupons,
'destination' => array(
'country' => WC()->customer->get_shipping_country(),
'state' => WC()->customer->get_shipping_state(),
'postcode' => WC()->customer->get_shipping_postcode(),
'city' => WC()->customer->get_shipping_city(),
'address' => WC()->customer->get_shipping_address(),
'address_2' => WC()->customer->get_shipping_address_2()));
}
return $packages;
}

Cart view after package split

Cart
Cart

Heavy item is packaged as Shipping Method#1 and calculated shipping cost. And small item packaged separate and free shipping.
Check out WooCommerce Shipping Plugins Store

Last Updated On September 21, 2018

2 thoughts on “Waving off or discounting the shipping cost of a product, if certain other product is present in the cart

  1. Sam says:

    How would you make this work with shipping classes instead of product categories?
    I have shipping class “no-free-shipping” that I need to charge for while the rest of the order ships free.
    Thanks in advance!

Comments are closed.