-
Notifications
You must be signed in to change notification settings - Fork 10.7k
Description
I'm attempting to write a filter that modifies the price suffix depending on if the viewing user is in a taxable zone (i.e. saying if the price is with or without tax). This should work for all types of products (I'm testing with variable products which have no price ranges, i.e. all variations are the same price):
/**
* Show "incl./excl. VAT" label for taxable prices
*
* @param string $html
* @param \WC_Product $wc_product
* @param string $price
* @param number $qty
* @return string
*/
function add_tax_labels_to_price ( $html, $wc_product, $price, $qty )
{
if ( wc_tax_enabled() && 'taxable' === $wc_product->get_tax_status() )
{
if ( '' === $price ) {
$price = $wc_product->get_price();
}
$price = floatval( $price );
$price_incl_tax = wc_get_price_including_tax( $wc_product, array( 'qty' => $qty, 'price' => $price ) );
$price_excl_tax = wc_get_price_excluding_tax( $wc_product, array( 'qty' => $qty, 'price' => $price ) );
// Since all prices are including tax already, I've made it so the message only shows when it's excluded
if ( $price >= $price_excl_tax )
{
$suffix = ''; // _x( '(incl. %s)', 'Price suffix: including Tax/VAT', 'mywebsite' );
}
else
{
$suffix = _x( '(excl. %s)', 'Price suffix: excluding Tax/VAT', 'mywebsite' );
}
// Add the tax/VAT abbr.
$suffix = sprintf( $suffix, WC()->countries->tax_or_vat() );
if ( ! empty( $suffix ) )
{
$html = ' <small class="price-suffix">' . wp_kses_post( $suffix ) . '</small>';
}
else
{
$html = '';
}
}
return $html;
}
add_filter( 'woocommerce_get_price_suffix', __NAMESPACE__ . '\\add_tax_labels_to_price', PHP_INT_MAX, 4 );I'm finding that both the prices with/without tax are the same (this is after clearing the transients). My viewing user has a billing and shipping address set to a country outside the taxable zones, and all prices are entered inclusive of tax in the store. The default is to show prices with tax, using the store's location (within one of the taxable zones) as the tax base, unless the viewing user has a shipping address filled in.
I originally had only two tax rates but have now updated it to a full EU VAT standard rates table here: https://gist.github.com/lvl99/2c843df32b9ce3c7fe9a5f40439adb4f
The test product should have value of 500 incl. VAT and 416.67 excl. VAT (using FR address with tax rate of 20%, and US address when outside EU taxable zone).
The behaviour I expected is that the wc_get_price_including_tax and wc_get_price_excluding_tax would do as function names claim. It seems wc_get_price_excluding_tax works OK but wc_get_price_including_tax seems to be location-aware and returns a price excluding tax if the viewing user is outside the taxable zone (regarding return values: wc_get_price_excluding_tax returns 416.6667 🤘, whereas wc_get_price_including_tax returns 416.67).
I've tested when the viewing user is within a taxable zone that wc_get_price_including_tax works correctly (I get a value of 500) and wc_get_price_excluding_tax returns the same value as above (416.6667 🤘).
Here's debug results with viewing user outside taxable zone:

And here's debug results with viewing user inside taxable zone:

One hackish workaround I did was to modify the expression checking the price, as I noticed that the $price value that flows through the woocommerce_get_price_suffix filter is the full original price of the product (in my shop's case including tax) regardless of taxable zone (e.g. 500), but this is not the actual price value which is being outputted via the get_price_html function (the value is both 500 when viewing as user in FR and in US). Since wc_get_price_including_tax is location-aware (as in, it seems to get the price value which is affected by if the user is in/out of the taxable zone) and $wc_product->get_price() gets the raw price value, I can make a not-so-great-but-works-ok assumption that the value returned by wc_get_price_including_tax will be representative of the output price and adjust the suffix message to be relative to that:
/**
* Show "incl./excl. VAT" label for taxable prices
*
* @param string $html
* @param \WC_Product $wc_product
* @param string $price
* @param number $qty
* @return string
*/
function add_tax_labels_to_price ( $html, $wc_product, $price, $qty )
{
if ( wc_tax_enabled() && 'taxable' === $wc_product->get_tax_status() )
{
if ( '' === $price )
{
$price = $wc_product->get_price();
}
$price = floatval( $price );
$price_incl_tax = wc_get_price_including_tax( $wc_product, array( 'qty' => $qty, 'price' => $price ) );
$price_excl_tax = wc_get_price_excluding_tax( $wc_product, array( 'qty' => $qty, 'price' => $price ) );
// Modified this check to rely on difference between location-aware $price_incl_tax vs raw unfiltered $price
if ( $price_incl_tax < $price )
{
$suffix = _x( '(excl. %s)', 'Price suffix: excluding Tax/VAT', 'mywebsite' );
}
else
{
$suffix = ''; // _x( '(incl. %s)', 'Price suffix: including Tax/VAT', 'mywebsite' );
}
if ( ! empty( $suffix ) )
{
// Add the tax/VAT abbr.
$suffix = sprintf( $suffix, WC()->countries->tax_or_vat() );
$html = ' <small class="price-suffix">' . wp_kses_post( $suffix ) . '</small>';
}
else
{
$html = '';
}
}
return $html;
}
add_filter( 'woocommerce_get_price_suffix', __NAMESPACE__ . '\\add_tax_labels_to_price', PHP_INT_MAX, 4 );So I'm assuming that wc_get_price_including_tax is not working correctly? Am I wrong to assume that it should always produce the price of the product including tax? Looking at the function now it seems that it specifically removes the tax from the price if the viewing user is outside the taxable zones. Isn't that misleading?
Prerequisites
- I have searched for similar issues in both open and closed tickets and cannot find a duplicate
- The issue still exists against the latest
masterbranch of WooCommerce on Github (this is not the same version as on WordPress.org!) - I have attempted to find the simplest possible steps to reproduce the issue
- I have included a failing test as a pull request (Optional)
Steps to reproduce the issue
- Set up shop tax config to enter prices including tax and to show prices including tax
- Set up shop tax rates as per https://gist.github.com/lvl99/2c843df32b9ce3c7fe9a5f40439adb4f
- Incorporate
add_tax_labels_to_pricefunction into theme (be aware that I use namespaces, maybe you don't) - Create a variable product with one variation priced at 500
- Modify viewing user billing/shipping address to be outside taxable zone (e.g. US)
- View product price (should be "416.67 (excl. VAT)")
- Modify viewing user billing/shipping address to be inside taxable zone (e.g. FR)
- View product price (should be 500)
Expected/actual behavior
- When I use
wc_get_price_including_taxit should give me the price of the product including tax, regardless of the viewing user's location. - When I use the filter
woocommerce_get_price_suffixI expect the$pricebeing fed through to be the price which is being displayed, i.e. the output price inget_price_html
Isolating the problem
- This bug happens with only WooCommerce plugin active
- This bug happens with a default WordPress theme active, or Storefront
- I can reproduce this bug consistently using the steps above