2

Original code makes all prices set to the same, no matter what the VAT % is. So if a item cost 100$ with 25% VAT, it will cost 100$ with 80% VAT or even 0% VAT.

That works fine, however, some countries I would like to remove the VAT for.

Original code from this answer thread:

add_filter( 'woocommerce_adjust_non_base_location_prices', '__return_false' );

My code that is not working:

add_filter( 'woocommerce_adjust_non_base_location_prices', 'custom_eu_vat_number_country_codes' );
function custom_eu_vat_number_country_codes( $vat_countries ) {

// Which countries should it be applide to?
    $countries = array( 'AX', 'AT', 'BE', 'BA', 'HR', 'CZ', 'DK', 'FI', 'GR', 'HU', 'IS', 'IE', 'IT', 'LU', 'NL', 'PO', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE', 'CH', 'GB');

    // Avoiding errors on admin and on other pages
    if( is_admin() || WC()->cart->is_empty() )
        return $countries;

// Remove field $countries
if (($key = array_search($countries, $vat_countries)) !== false) {
    return false;
}
return $vat_countries;
}

What am I doing wrong?

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399

2 Answers2

1

The main function argument is not related to countries, it's a boolean value (true by default), see that on wc_get_price_excluding_tax() function code..

You need to get the customer billing country from WC_Customer Object (or the shipping country).

So your code should be:

add_filter( 'woocommerce_adjust_non_base_location_prices', 'custom_eu_vat_number_country_codes' );
function custom_eu_vat_number_country_codes( $boolean ) {
    // Avoiding errors on admin and on other pages
    if( is_admin() || WC()->cart->is_empty() )
        return $boolean;

    // Defined array of countries where the boolean value should be "false"
    $countries = array( 'AX', 'AT', 'BE', 'BA', 'HR', 'CZ', 'DK', 'FI', 'GR', 'HU', 'IS', 'IE', 'IT', 'LU', 'NL', 'PO', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE', 'CH', 'GB');

    // Remove field $countries
    if ( in_array( WC()->customer->get_billing_country(), $countries ) ) {
        $boolean = false;
    }
    return $boolean;
}

Code goes in functions.php file of your active child theme (or active theme). It should works (untested).

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • Make sense, I'll try it. thanks, it's giving me a syntax error on the $boolean = false; row? – Romeo Patrick Jun 03 '20 at 18:03
  • @RomeoPatrick My fault, there was a missing bracket in the if statement… Try it again. – LoicTheAztec Jun 03 '20 at 20:26
  • 1
    Worked like a charm. Thank you! – Romeo Patrick Jun 03 '20 at 20:30
  • Spent a while on the same issue. What bothers me with this approach is that the filter is rather a shop level rule (Do we adjust non-base location prices in this shop?), while the applied criteria is more about a certain customer (Should the customer pay VAT or not?). $customer->get_is_vat_exempt() seems more correct for this kind of customization, but it doesn't allow any filtering, and using set_is_vat_exempt() would save the value to the customer, which raises compatibility concerns. I'll go for the solution by @LoicTheAztec for that reason. – jgangso Feb 14 '22 at 07:36
0

Adding this a as separate answer although it's mostly based on @LoicTheAztec's answer.

The only difference is that the code checks customers shipping country (not billing country), since VAT follows the "destination principle", that is, VAT is calculated based on the country where the product/service is consumed. (the case for EU at least).

add_filter( 'woocommerce_adjust_non_base_location_prices', 'custom_eu_vat_number_country_codes' );
function custom_eu_vat_number_country_codes( $boolean ) {
    // Avoiding errors on admin and on other pages
    if( is_admin() || WC()->cart->is_empty() )
        return $boolean;

    // Defined array of countries where the boolean value should be "false"
    $countries = array( 'AX', 'AT', 'BE', 'BA', 'HR', 'CZ', 'DK', 'FI', 'GR', 'HU', 'IS', 'IE', 'IT', 'LU', 'NL', 'PO', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE', 'CH', 'GB');

    // Remove field $countries
    if ( in_array( WC()->customer->get_shipping_country(), $countries ) ) {
        $boolean = false;
    }
    return $boolean;
}
jgangso
  • 638
  • 10
  • 19