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

Woocommerce, count shipping cost in 2 way WordPress

  • SOLVED

Woocommerce, count shipping cost in 2 way

My client is selling items that are from 2 locations, some from his house, some from other place. Let’s say those are in category A and category B. Both A and B category offer it’s own free shipping when reaches total amount $1,000, But will count separately in 2 shipping cost base by <strong>each category</strong>, for example:

<strong>IN AN ORDER</strong>
Purchase $200 from category A will charge $50 for shipping,
Purchase $150 from category B will also charge $50 for shipping,
The total shipping cost for this order is $100.
If any items in it’s category reach $1,000 then free shipping, but still count in 2 shipping base by category.

<strong>SO, ANOTHER ORDER</strong>,
Purchase $300 from category A will charge $50 for shipping,
Purchase $1,100 from category B will get free shipping,
The total shipping cost for this order is $50.

<strong>Last, </strong>if $1,100 from category A and $1,200 from category B in an order will reach totally free shipping.

----------------------------------------------
I need a code will work on functions.php
I don't want it work with woocommerce shipping class.

I know it’s unusual, but my client needs this:)

Answers (2)

2015-01-10

John Cotton answers:

<blockquote>I need a code will work on functions.php
I don't want it work with woocommerce shipping class.</blockquote>

It would be interesting to know why that is since going the shipping class route would seem the best approach.

But you could try modifying an existing rate on the fly with something like this:

define( 'CAT_A_TERM_ID', 21 );
define( 'CAT_B_TERM_ID', 22 );

function adjust_shipping_cost( $rates, $package ) {
$totals = array( 'A' => 0, 'B' => 0 );

foreach( $package['contents'] as $item ) {
// You need to change this to match your taxonomy
$cats = wp_get_object_terms( $item['product_id'], 'YOUR_TAXONOMY' );

// Your logic here may need to be more complex if products can be in more than one category
foreach( $cats as $cat ) {
if( $cat->term_id = CAT_A_TERM_ID ) {
$totals['A'] += $item['line_total'];
break;
}
if( $cat->term_id = CAT_B_TERM_ID ) {
$totals['B'] += $item['line_total'];
break;
}
}
}

// Assuming you are using the free_shipping rate...you can adjust more rates here if you need to
$rates['free_shipping']->cost = 0;
if( $totals['A'] < 1000 ) $rates['free_shipping']->cost += 50;
if( $totals['B'] < 1000 ) $rates['free_shipping']->cost += 50;

return $rates;
}
add_filter( 'woocommerce_package_rates', 'adjust_shipping_cost', 10, 2 );


Bard comments:

Hi, I am appreciated:)
Two questions:

1. Are there only these variables need to change?
define( 'CAT_A_TERM_ID', <strong>21</strong> );
define( 'CAT_B_TERM_ID', <strong>22</strong> );
$cats = wp_get_object_terms( $item['product_id'], '<strong>YOUR_TAXONOMY</strong>' );

2. Do I need a free shipping rate to work with your code?

3. What is 10 and 2? should I change it?
add_filter( 'woocommerce_package_rates', 'adjust_shipping_cost', 10, 2 );


Bard comments:

Was 3 questions, sorry:)


John Cotton comments:

<blockquote>1. Are there only these variables need to change?
define( 'CAT_A_TERM_ID', 21 );
define( 'CAT_B_TERM_ID', 22 );
$cats = wp_get_object_terms( $item['product_id'], 'YOUR_TAXONOMY' );</blockquote>
Yes, you need to add your term ids in here.

<blockquote>2. Do I need a free shipping rate to work with your code?</blockquote>
No. You can use any shipping rate. My code is just an example.

<blockquote>3. What is 10 and 2? should I change it?</blockquote>
10 is the priority of the filter (default) and 2 is the number of parameters. You can change the 10 (although there is no reason to do so), but you need to leave the 2 as-is.


John Cotton comments:

You should read my code as an example. It's not very production-ready. (for example, hard-coding IDs is not a great idea but if you are not moving the plugin around, it will work.)


Bard comments:

Hi John,
I can see this works out something, but I can't make it work(coding is not that familiar to me).
What is the "YOUR_TAXONOMY" standing for? what exactly should I replace?
<blockquote>$cats = wp_get_object_terms( $item['product_id'], 'YOUR_TAXONOMY' );
</blockquote>
I replace a product ID on it and try adding to the cart, in the CART page, it reacts me this:

<blockquote>Fatal error: Unsupported operand types in /home/**/public_html/test/wp-content/plugins/woocommerce/includes/class-wc-shipping.php on line 315</blockquote>

This is an all new WordPress, run in 2012 theme.
Please let me know what can I do to keep your help going?


John Cotton comments:

<blockquote>What is the "YOUR_TAXONOMY" standing for? what exactly should I replace?</blockquote>
Whatever the taxonomy is that has category A and category B in it - for example 'product_cat' if you have used the standard Woocommerce product categories.

Are you using the latest version of Woocommerce? Should be 2.2.10


Bard comments:

I have "YOUR_TAXONOMY" replaced the product category name like this:
<blockquote>// You need to change this to match your taxonomy
$cats = wp_get_object_terms( $item['product_id'], 'locationA' );
$cats = wp_get_object_terms( $item['product_id'], 'locationB' );</blockquote>

Well, every time I change the code and try reload CART page, it shows like this:
<img src="http://i.gyazo.com/693ffcc43e8f1d148cba5fcfb42c3af6.png">
This is line 64:
<blockquote>$rates['free_shipping']->cost = 0;</blockquote>

And I reload it again:
The first error gone:
<img src="http://i.gyazo.com/51c6dd449edda0a6a6bbbbbf94c2fda6.png">

Yes, I am with Woocommerce 2.2.10 which installed from WP plugin panel.


Bard comments:

oops, please link the img address.
[[LINK href="http://i.gyazo.com/693ffcc43e8f1d148cba5fcfb42c3af6.png"]]http://i.gyazo.com/693ffcc43e8f1d148cba5fcfb42c3af6.png[[/LINK]]
[[LINK href="http://i.gyazo.com/51c6dd449edda0a6a6bbbbbf94c2fda6.png"]]http://i.gyazo.com/51c6dd449edda0a6a6bbbbbf94c2fda6.png[[/LINK]]


John Cotton comments:

Romel has changed my code incorrectly.

It should be this (I've added a floatval (it's currency after all...) in if that helps):


foreach( $cats as $cat ) {

if( $cat->term_id == CAT_A_TERM_ID ) {

$totals['A'] = floatval($item['line_total']);

}

if( $cat->term_id == CAT_B_TERM_ID ) {

$totals['B'] += floatval($item['line_total']);

}

}


These lines can be restored to the version I had:


if( $totals['A'] < 1000 ) $rates['free_shipping']->cost += 50;
if( $totals['B'] < 1000 ) $rates['free_shipping']->cost += 50;


John Cotton comments:

So the code should be


define( 'CAT_A_TERM_ID', 7 );
define( 'CAT_B_TERM_ID', 8 );


function adjust_shipping_cost( $rates, $package ) {
$totals = array( 'A' => 0, 'B' => 0 );

foreach( $package['contents'] as $item ) {
// You need to change this to match your taxonomy
$cats = wp_get_object_terms( $item['product_id'], 'product_cat' );

// Your logic here may need to be more complex if products can be in more than one category
foreach( $cats as $cat ) {
if( $cat->term_id = CAT_A_TERM_ID ) {
$totals['A'] += floatval($item['line_total']);
break;
}
if( $cat->term_id = CAT_B_TERM_ID ) {
$totals['B'] += floatval($item['line_total']);
break;
}
}
}

// Assuming you are using the free_shipping rate...you can adjust more rates here if you need to
$rates['free_shipping']->cost = 0;
if( $totals['A'] < 1000 ) $rates['free_shipping']->cost += 50;
if( $totals['B'] < 1000 ) $rates['free_shipping']->cost += 50;


return $rates;
}
add_filter( 'woocommerce_package_rates', 'adjust_shipping_cost', 10, 2 );


Bard comments:

Hi John,

Could you please explain what is difference by using(Yours):
foreach( $cats as $cat ) {
if( $cat->term_id == CAT_A_TERM_ID ) {
$totals['A'] = floatval($item['line_total']);
}
if( $cat->term_id == CAT_B_TERM_ID ) {
$totals['B'] += floatval($item['line_total']);
}
}


Instead of using(Romel's):
foreach( $cats as $cat ) {
if( $cat->term_id == CAT_A_TERM_ID ) {
$totals['A'] = $item['line_total'];
}
if( $cat->term_id == CAT_B_TERM_ID ) {
$totals['B'] = $item['line_total'];
}
}


And

Yours:
if( $totals['A'] < 1000 ) $rates['free_shipping']->cost += 50;
if( $totals['B'] < 1000 ) $rates['free_shipping']->cost += 50;


Instead of(Romel's)
if( $totals['A'] < 1000 ) $rates['free_shipping']->cost += 50;
if( $totals['B'] < 1000 ) $rates['free_shipping']->cost += 50;


Please, I like to know what differences in what situations?


Bard comments:

Sorry, was:
if( (intval($totals['A']) < 1000) && (intval($totals['A']) > 0) ){
$rates['free_shipping']->cost += 50;
}
if( (intval($totals['B']) < 1000) && (intval($totals['B']) > 0) ){
$rates['free_shipping']->cost += 50;
}

From Romel's


John Cotton comments:

floatval forces the value to be a floating number (rather than a string which is possibly what you were seeing). Also, Romel had an error in that he changed my += to just = which means each product item value wasn't being added but instead the last one being assigned.

By putting floatval in the addition loop, the intval conversion and checking for greater than 0 are unnecessary (which is why I never had them)


Bard comments:

Hi John,
I know you consider more of it, but it results wrong shipping(your latest update)