I am adding a WooCommerce cart fee like so :
add_action('woocommerce_cart_calculate_fees', function($cart) {
$cart->add_fee(__('Popust za vjernost'), -10, 0);
});
I thought adding a 0 as the third argument would set the tax to 0 but WooCommerce still adds tax to the fee.
How can I set the tax to 0?
Overwriting cores files is not a solution, as it can affect other processes and you will lose your changes each time you will update WooCommerce.
Using WC_Cart
add_fee()
method with a negative amount, is a tweak to add a discount. In that case, the "taxable" optional 3rd argument doesn't work, and taxes are always applied. This has been reported to WooCommerce many times and the response was that WC_Cart
add_fee()
method was not made for discounts.
WC_Cart
add_fee()
method 4 available arguments:/**
* Add additional fee to the cart.
*
* This method should be called on a callback attached to the
* woocommerce_cart_calculate_fees action during cart/checkout. Fees do not
* persist.
*
* @uses WC_Cart_Fees::add_fee
* @param string $name Unique name for the fee. Multiple fees of the same name cannot be added.
* @param float $amount Fee amount (do not enter negative amounts).
* @param bool $taxable Is the fee taxable? (default: false).
* @param string $tax_class The tax class for the fee if taxable. A blank string is standard tax class. (default: '').
*/
WC()->cart->add_fee( $name, $amount, $taxable, $tax_class );
The following code will enable "taxable" when using a negative amount, allowing to add a discount without taxes when the "taxable" argument is set to false
:
// Adjust cart total amount
add_filter( 'woocommerce_cart_get_total', 'filter_cart_get_total', 10, 1 );
function filter_cart_get_total( $total ) {
$tax_amount = 0;
foreach( WC()->cart->get_fees() as $fee ) {
if( ! $fee->taxable && $fee->tax < 0 ) {
$tax_amount -= $fee->tax;
}
}
if( $tax_amount != 0 ) {
$total += $tax_amount;
}
return $total;
}
// Adjust Fee taxes (array of tax totals)
add_filter( 'woocommerce_cart_get_fee_taxes', 'filter_cart_get_fee_taxes', 10, 1 );
function filter_cart_get_fee_taxes( $fee_taxes ) {
$fee_taxes = array();
foreach( WC()->cart->get_fees() as $fee ) {
if( $fee->taxable ) {
foreach( $fee->tax_data as $tax_key => $tax_amount ) {
if( isset($fee_taxes[$tax_key]) ) {
$fee_taxes[$tax_key] += $tax_amount;
} else {
$fee_taxes[$tax_key] = $tax_amount;
}
}
}
}
return $fee_taxes;
}
// Displayed fees: Remove taxes from non taxable fees with negative amount
add_filter( 'woocommerce_cart_totals_fee_html', 'filter_cart_totals_fee_html', 10, 2 );
function filter_cart_totals_fee_html( $fee_html, $fee ) {
if( ! $fee->taxable && $fee->tax < 0 ) {
return wc_price( $fee->total );
}
return $fee_html;
}
// Adjust Order fee item(s) for negative non taxable fees
add_action( 'woocommerce_checkout_create_order_fee_item', 'alter_checkout_create_order_fee_item', 10, 4 );
function alter_checkout_create_order_fee_item( $item, $fee_key, $fee, $order ) {
if ( ! $fee->taxable && $fee->tax < 0 ) {
$item->set_taxes(['total' => []]);
$item->set_total_tax(0);
}
}
Code goes in functions.php file of your child theme (or in a plugin).
Add_fee()
:Below, we add a discount without taxes using a negative amount:
add_action( 'woocommerce_cart_calculate_fees', 'add_discount_without_tax' );
function add_discount_without_tax( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Add a NON taxable DISCOUNT (negative amount, "taxable" argument set to "false")
$cart->add_fee(__('Discount (no tax)'), -10, false);
};
This time it works, taxes are not applied and when order is submitted, same thing.
Code goes in functions.php file of your child theme (or in a plugin).