Ask your WordPress questions! Pay money and get answers fast! (more info)

Restrict Woocommerce shipping based on product category

  • SOLVED

Hi All,

Need to restrict shipping of one product category to Local Delivery and Local Pickup:

* store is located in 'FL' Florida

* store has two product categories with different shipping:

- Apples (6 sub-cats) can ship to any of 34 states (including FL) via UPS, or local delvery and local pickup

- Oranges (3 sub-cats) are restricted to local delivery and local in-store pickup

* using Local Delivery tab to restrict delivery to: 33623, 33630, 33633 zip codes

* store ships to 34 states via UPS Shipping extension

- using this method to restrict states on Checkout page, [[LINK href="http://speakinginbytes.com/2013/12/ship-continental-us/" target=_blank"]]http://speakinginbytes.com/2013/12/ship-continental-us/
[[/LINK]]
<strong>Question:</strong> how to configure the following with code for functions.php or another suitable method?

<strong>1. on Checkout page</strong>:

- orders for Oranges category and sub-cats must automatically be restricted to local delivery and local pickup

- orders for both Oranges and Apples (all sub-cats for both) must be restricted to local delivery and local pickup

<strong>2: Messages on Checkout page</strong>:

- orders with Oranges should show this message: "Cannot ship Oranges, local delivery and in-store pickup only"

- orders with Oranges and Apples: "Cannot ship Oranges, local delivery and in-store pickup only. Remove Oranges from your order to have Apples shipped to you"


You must <strong>provide step-by-step directions</strong> (do this, then that) not big-picture theory.

Answers (4)

2014-10-07

Bob answers:

Here is some code which should go into your theme's functions.php file

It has two functions 1st is to check if cart has product with orange category or not. it will be used in another function
**Note I am assuming you do not have many categories **

**We need to change value of categories at this line**
<em> if (( $_categoryid === 17 ) || ( $_categoryid === 18 ) || ( $_categoryid === 19 )) {</em>


we need to unset extra shipping method. we don't know right now which shipping methods are there. we need access to your website
according to available method we will unset un-necessary methods via following code
<em>unset( $available_methods['flat_rate'] ); </em>

please provide access or more details to solve your problem



// a function to check if the cart has product from organge and it's sub category id
function cart_has_product_with_orange_cats() {
//Check to see if user has product in cart
global $woocommerce;

//assigns a default negative value
// categories targeted 17, 18, 19

$product_in_cart = false;

// start of the loop that fetches the cart items

foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
$terms = get_the_terms( $_product->id, 'product_cat' );

// second level loop search, in case some items have several categories
foreach ($terms as $term) {
$_categoryid = $term->term_id;
}

if (( $_categoryid === 17 ) || ( $_categoryid === 18 ) || ( $_categoryid === 19 )) {
//category is in cart!
$product_in_cart = true;
}

}

return $product_in_cart;
}

// add filter and function to hide method
add_filter( 'woocommerce_available_shipping_methods', 'hide_shipping_if_cat_is_orange' , 10, 1 );
function hide_shipping_if_cat_is_orange( $available_methods ){
if ( cart_has_product_with_orange_cats() ) {
// remove the rate you want
unset( $available_methods['flat_rate'] );
}
// return the available methods without the one you unset.
return $available_methods;
}



Once we achieve this we can think for notification.


Toss F. comments:

You may be close:

1. all shipping methods disappeared

2. Cart shows following error message:

<strong>Warning:</strong> call_user_func_array() expects parameter 1 to be a valid callback, function 'hide_shipping_if_cat_is_oranges' not found or invalid function name in <strong>/home/fruitie/public_html/wp-includes/plugin.php</strong> on line <strong>192</strong>


<strong><em>Answers to your questions:</em></strong>

* only two (2) categories with many sub-categories in each

* three (3) shipping methods: UPS, Local Pickup, Local Delivery

* "Oranges" category and sub-cats should unset "UPS shipping"





Bob comments:

We need an internal names of shipping methods.
can you provide access.

We also need an id of categories.


Toss F. comments:

Sending you a PM.


Bob comments:

Please watch this video I have created for you.
[[LINK href="https://www.youtube.com/watch?v=akuS8V61xys&feature=youtu.be"]]https://www.youtube.com/watch?v=akuS8V61xys&feature=youtu.be[[/LINK]]

Add this code to your functions.php and remove old code provided by me.
<strong>Don't forget to change category ids in code. In below example it is 569 and 570</strong>
// a function to check if the cart has product from organge and it's sub category id
function cart_has_product_with_orange_cats() {
//Check to see if user has product in cart
global $woocommerce;
//assigns a default negative value
$product_in_cart = false;

// start of the loop that fetches the cart items
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {

$_product = $values['data'];
$terms = get_the_terms( $_product->id, 'product_cat' );
// second level loop search, in case some items have several categories
if($terms){
foreach ($terms as $term) {
$_categoryid = $term->term_id;

if (( $_categoryid === 569 ) || ( $_categoryid === 570 ) ) {
//category is in cart!
$product_in_cart = true;

}
}

}
}
return $product_in_cart;
}



// add filter and function to hide method
add_filter( 'woocommerce_available_shipping_methods', 'custom_shipping_methods' , 10, 1 );
function custom_shipping_methods( $available_methods ){


if ( cart_has_product_with_orange_cats() ) {

foreach($available_methods as $key => $method){
if( $key == 'local_delivery' || $key == 'local_pickup'){
continue;
}
unset($available_methods[$key]);
}
// remove the rate you want
}

// return the available methods without the one you unset.
return $available_methods;

}


Bob comments:

have you tried above solution? please confirm so we can proceed with other changes.


Toss F. comments:

Done and workng fine. Okay to proceed.


Bob comments:

Thank You Toss I am working on it.


Bob comments:

Can we add some language which give both instructions to user? It would be easy for me to write a code.

Like "Cannot ship Oranges, local delivery and in-store pickup only. If you have Apples in your cart and want to shipped to you then please remove oranges."

Here is code to print message for user
Please add this code into your theme's functions.php file

add_action( 'woocommerce_before_checkout_form' , 'orange_product_notices' );
add_action('woocommerce_before_cart_table','orange_product_notices');
function orange_product_notices() {
global $woocommerce;
if(cart_has_product_with_orange_cats()){
wc_print_notice( "Cannot ship Oranges, local delivery and in-store pickup only. If you have Apples in your cart and want to shipped to you then please remove oranges.", $notice_type = 'notice' );
}
}


Toss F. comments:

Can a div be added to the message so it can be styled?

<div id="cart-message" or something like that?


Bob comments:

You can just simply change this line wc_print_notice( "Cannot ship Oranges, local delivery and in-store pickup only. If you have Apples in your cart and want to shipped to you then please remove oranges.", $notice_type = 'notice' );

just add like echo ' <div>your message</div>';

2014-10-07

Fahad Murtaza answers:

For removing certain shipping methods, here is how you do it


add_filter( 'woocommerce_package_rates', 'hide_all_shipping_when_cat' , 10, 2 );
function hide_all_shipping_when_cat(){
if(is_product_category( 'oranges' )){
unset( $rates['free_shipping'] );
// Unset all shipping methods you want with their names
}
}


And for cart's conditional messages, here is how you can get it done.

http://www.woothemes.com/products/cart-notices/


Toss F. comments:

Your code removed all shipping options, including when "oranges" category was not in Cart.


Fahad Murtaza comments:

I never said it was the complete solution. Did you use it as is?

2014-10-07

Maryke Janse van Rensburg answers:

Have you tried shipping classes? http://docs.woothemes.com/document/product-shipping-classes/

2014-10-07

Gabriel Reguly answers:

Hi Toss,

At $20 value you can only expect big picture solutions, for real code the prize is way too low.

Cheers,
Gabriel