Here's the scenario:
I ship trays of drinks using UPS. However, it becomes very difficult to pack 5 trays of drinks into boxes. So I would like to disable UPS shipping method and only display Flat Rate Shipping if a customer orders 5 or more trays of drinks. I have about 7 different drinks, but I can add these drinks to a shipping class to simplify the code.
I want to expand this code to include the quantity of products in a specific the class or perhaps the number of times a product in the shipping class appears. So if the cart has 5 or more of a product in this specific shipping class, it should remove the shipping methods I've specified under array.
How do I expand this code to also include quantity of products?
// If we find the shipping class & quantity of product in the shipping class is equal to or greater than 5.
add_filter( 'woocommerce_package_rates', 'hide_shipping_method_based_on_shipping_class', 10, 2 );
function hide_shipping_method_based_on_shipping_class( $rates, $package )
{
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Shipping Class To Find
$class = 182;
// Number Of Shipping Class Items In Cart
$amount = 5;
// Shipping Methods To Hide
$method_key_ids = array('wf_shipping_ups:07', 'wf_shipping_ups:08', 'wf_shipping_ups:11', 'wf_shipping_ups:54', 'wf_shipping_ups:65', 'wf_shipping_ups:70', 'wf_shipping_ups:74', 'free_shipping:2', 'request_shipping_quote');
// Checking In Cart Items
foreach( $package['contents'] as $item ) {
// If We Find The Shipping Class and Number of Items
if( $item['data']->get_shipping_class_id() == $class && count($package['contents']) >= $amount ){
foreach( $method_key_ids as $method_key_id ){
unset($rates[$method_key_id]); // Remove Targeted Methods
}
break; // Stop The Loop
}
}
return $rates;
}
Since I purchased the "WooCommerce UPS Shipping Plugin with Print Label" from PluginHive, I have access to their "Manage Shipping Methods" plugin which allows me to do the following:
Set multiple rules to exclude various shipping methods from various shipping classes. Break the sequence on first occurrence.
The rules I have set-up are as follows:
wf_shipping_ups:07, wf_shipping_ups:08, wf_shipping_ups:11, wf_shipping_ups:54, wf_shipping_ups:65, wf_shipping_ups:70, wf_shipping_ups:74, free_shipping:2, request_shipping_quote.
I've created a third class 182 in the above code for the products I want to target. It should be treated as class 151 only if less than 5 items of the class are added to the cart.
But it should be treated as Class 150 if 5 or more items are added to the cart.
That's my dilemma.
I figured out how to solve my problem. The code @LoicTheAztec assisted me with lets me unset shipping methods for a given shipping class if the product quantity in the cart is 5 or more.
What I need to do now is unset two other shipping methods (flat_rate:20 and flat_rate:21) which is causing the conflict, for the same shipping class (182) but this time for a product quantity in the cart of 4 or less (=<).
Then I can use the existing plugin to create the following rules:
Break on First Occurrence (Check)
wf_shipping_ups:07, wf_shipping_ups:08, wf_shipping_ups:11, wf_shipping_ups:54, wf_shipping_ups:65, wf_shipping_ups:70, wf_shipping_ups:74, free_shipping:2, request_shipping_quote.
Nothing - Because Both Codes Will Create The Logic
flat_rate:20, flat_rate:21.
This should resolve the conflict caused by the plugin.
The million dollar question is...can I somehow use @LoicTheAztec 's solution to set some sort of minimum quantity?
The following will hide specific defined shipping methods if total items from specific shipping class are 5 or more:
add_filter( 'woocommerce_package_rates', 'hide_shipping_method_based_on_shipping_class', 10, 2 );
function hide_shipping_method_based_on_shipping_class( $rates, $package ) {
$targeted_class_ids = array(182); // Shipping Class To Find
$allowed_max_qty = 4; // Max allowed quantity for the shipping class
$shipping_rates_ids = array( // Shipping Method rates Ids To Hide
'wf_shipping_ups:07',
'wf_shipping_ups:08',
'wf_shipping_ups:11',
'wf_shipping_ups:54',
'wf_shipping_ups:65',
'wf_shipping_ups:70',
'wf_shipping_ups:74',
'free_shipping:2',
'request_shipping_quote'
);
$related_total_qty = 0;
// Checking cart items for current package
foreach( $package['contents'] as $key => $cart_item ) {
if( in_array( $cart_item['data']->get_shipping_class_id(), $targeted_class_ids ) ){
$related_total_qty += $cart_item['quantity'];
}
}
// When total allowed quantity is more than allowed (for items from defined shipping classes)
if ( $related_total_qty > $allowed_max_qty ) {
// Hide related defined shipping methods
foreach( $shipping_rates_ids as $shipping_rate_id ) {
if( isset($rates[$shipping_rate_id]) ) {
unset($rates[$shipping_rate_id]); // Remove Targeted Methods
}
}
}
return $rates;
}
Code goes in functions.php file of your active child theme (or active theme). Untested it should works.
Refresh the shipping caches:
- This code is already saved on your functions.php file.
- In a shipping zone settings, disable / save any shipping method, then enable back / save.
You are done and you can test it.
Replace:
$related_total_qty += $cart_item['quantity'];
by
$related_total_qty++;