I recently tried to modify all my shipping rates with hook to apply discount.

Here’s my code :

```
add_filter( 'woocommerce_package_rates', 'woocommerce_package_rates' );
function woocommerce_package_rates( $rates ) {
$user_id = get_current_user_id();
if ( ! wc_memberships_is_user_active_member( $user_id, 'silver' ) ) { return $rates; }
$discount_amount = 30; // 30%
foreach($rates as $key => $rate ) {
$rates[$key]->cost = $rates[$key]->cost - ( $rates[$key]->cost * ( $discount_amount/100 ) );
}
return $rates;
}
```

But one more step is the tax ! I got wrong tax.

For example I have my shipping rate who cost `3$`

. With the discount, it’s now `2,10$`

.

I buy one item for `2$`

and the shipping `2.10$`

.

I got 1$ for the tax (as the 3$ shipping cost. look like he doesn’t take the changes) and normally it’s `0.82$`

.

What do I need to get the correct tax calculation?

## Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

### Solution 1

**Update:** related to tax cost calculation for the shipping methods

There is some little errors on your code and you have missed the tax calculation discount. I have revisited your code a bit, you should try this:

```
add_filter( 'woocommerce_package_rates', 'conditional_shipping_discount', 10, 2 );
function conditional_shipping_discount( $rates, $packages ) {
$user_id = get_current_user_id();
if ( ! wc_memberships_is_user_active_member( $user_id, 'silver' ) ) return $rates;
$percent = 30; // 30%
$discount = 1 - ($percent / 100);
foreach($rates as $rate_key => $rate_values ) {
// Get original cost
$original_cost = $rates[$rate_id]->cost;
// Calculate the discounted rate cost
$new_cost = $original_cost * $discount;
// Set the discounted rate cost
$rates[$rate_key]->cost = number_format(new_cost, 2);
// calculate the conversion rate (for taxes)
$conversion_rate = $new_cost / $original_cost;
// Taxes rate cost (if enabled)
$taxes = array();
foreach ($rate->taxes as $key => $tax){
if( $tax > 0 ){ // set the new tax cost
// set the new line tax cost in the taxes array
$taxes[$key] = number_format( $tax * $conversion_rate, 2 );
}
}
// Set the new taxes costs
$rates[$rate_key]->taxes = $taxes
}
return $rates;
}
```

*Code goes in function.php file of your active child theme (or theme) or also in any plugin file.*

This code is tested and works.

You should need to refresh the shipping caches:

- First this code is already saved on your function.php file.
- In Shipping settings, enter in a Shipping Zone and disable a
**Shipping Method**and "save". Then re-enable that**Shipping Method**and "save".**You are done.**

### Solution 2

Below code @LoicTheAztec without mistakes:

```
add_filter( 'woocommerce_package_rates', 'conditional_shipping_discount', 10, 2 );
function conditional_shipping_discount( $rates, $packages ) {
$user_id = get_current_user_id();
if ( ! wc_memberships_is_user_active_member( $user_id, 'silver' ) ) return $rates;
$percent = 30; // 30%
$discount = 1 - ($percent / 100);
foreach($rates as $rate_key => $rate_values ) {
// Get original cost
$original_cost = $rates[$rate_key]->cost;
// Calculate the discounted rate cost
$new_cost = $original_cost * $discount;
// Set the discounted rate cost
$rates[$rate_key]->cost = number_format($new_cost, 2);
// calculate the conversion rate (for taxes)
$conversion_rate = $new_cost / $original_cost;
// Taxes rate cost (if enabled)
$taxes = array();
foreach ($rates[$rate_key]->taxes as $key => $tax){
if( $tax > 0 ){ // set the new tax cost
// set the new line tax cost in the taxes array
$taxes[$key] = number_format( $tax * $conversion_rate, 2 );
}
}
// Set the new taxes costs
$rates[$rate_key]->taxes = $taxes;
}
return $rates;
}
```

### Solution 3

The problem with the answers above is that you’re calculating the tax based on the calculations already made for the original cost. What if, for example, a plugin is calculating the tax based on the shipping cost? For example, 10% if $100 or above, 20% if $200 or above, 0% if less than $100.

If the original cost was $150 and you’re applying a $60 discount, the discounted cost would be $90 and no tax would apply in the aforementioned scenario. So we need a way to modify the cost **before the tax is calculated**. This way we don’t have to recalculate the tax ourselves and we reduce bugs like the example in the first paragraph.

For one of my plugins I’m using the `woocommerce_shipping_method_add_rate_args`

filter, which is called by \WC_Shipping_Method::add_rate(). This method is called everytime a \WC_Shipping_Method instance adds a rate.

This filter will accept an array as its first argument, which is the rate data. This array has a ‘cost’ entry which is what we want to modify. Keep in mind that this can be a scalar (apparently, a numeric string) or an array. Just check if it’s an array when dealing with this:

```
add_filter('woocommerce_shipping_method_add_rate_args', function(array $rateArguments) : array {
// Total up the cost. Taken from the WooCommerce source code. woocommerce/includes/abstracts/abstract-wc-shipping-method.php
$totalCost = is_array( $rateArguments['cost'] ) ? array_sum( $rateArguments['cost'] ) : $rateArguments['cost'];
$rateArguments['cost'] = 'here the final cost';
return $rateArguments;
});
```

**Note: Use and implement solution 1 because this method fully tested our system.Thank you 🙂**

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0