VAT Based on User Role

Often you need to charge VAT or Dutch BTW for customers only and not for your vendors or companies shopping at your website. So how do you make sure that users with the role business see no VAT and customers or private persons do see VAT?

User Role Check

To check for specific role and apply a rule to it you can use this code:

## The (repetitive) conditional function based on your "special" user roles 
function is_special_user_role(){
  if ( ! is_user_logged_in() ) return false;

  $user = wp_get_current_user(); // current user
  $user_roles = $user->roles; // It's always an array (as a user can have many roles)

  // HERE your defined user roles
  $defined_user_roles = array( 'company' );

  if ( count( array_intersect( $user_roles, $defined_user_roles ) ) > 0 ) 
  return true;
  else return false; // ==> Added update here
}

VAT Exemption Check

Now, to check if a user role is tax exempt and then turn off VAT/BTW for that user role we can add this action hook:

## Function that will check for user role and turn off VAT/tax for that role
add_action( 'template_redirect', 'wc_diff_rate_for_user', 1 );
function wc_diff_rate_for_user() {
    // check for the user role and set the customer object to have no VAT
    if ( is_special_user_role() )
        WC()->customer->set_is_vat_exempt( true ); // Updated HERE
}

NB If you just need a display excl. vat and do not really need the user to be tax exempt this is not the setup you are looking for.

VAT Price Suffix

Function that removes the price suffix based on role. So with it you could hide the including tax title for certain user roles:

Function that removes the price suffix (inc. Tax) from variable products based on role
 add_filter( 'woocommerce_get_price_suffix', 'wc_get_price_suffix_filter', 10, 2 );
 function wc_get_price_suffix_filter( $price_display_suffix, $item ) {
     // check for the user role return blank if it matches
     if ( is_special_user_role() )
         $price_display_suffix = '';
 return $price_display_suffix;
 }

NB https://stackoverflow.com/a/46678453/460885

NBB Great resource https://gist.github.com/jasperf/0568154ca7b4f8a8551b41d5d0a26b0e

Display Product Excluding VAT

So what if your products are all inclusive VAT? How do you then display the price for a certain user role excluding VAT? Well, you can add a price suffix at wp-admin/admin.php?page=wc-settings&tab=tax

Prijs Excl BTW {price_excluding_tax}

And then you work out a why to hide the price including VAT with CSS or otherwise. With CSS is is kind of hard as there are no unique classes for the basic price display nor for the discounted price display. For the discounted price this could work:

ins {

    visibility: hidden;
}

The same for del for the price itself, but would not remove the divs.

NB https://docs.woocommerce.com/document/setting-up-taxes-in-woocommerce/#section-10

Price Display Incl. & Excl. VAT at the same time

Another option would be code to load it separately in the product single template or with a shortcode. Here is a way to show the price with and without taxes and that at the same time.

function edit_price_display() {
     global $product;
     $price = $product->price;
     $price_incl_tax = $price + round($price * ( 21 / 100 ), 2);
     $price_incl_tax = number_format($price_incl_tax, 2, ",", ".");
     $price = number_format($price, 2, ",", ".");
     $display_price = '';     $display_price .= '€ ' . $price_incl_tax .' incl BTW';
     $display_price .= '
';
     $display_price .= '€ ' . $price .' excl BTW';
     $display_price .= '';
     echo $display_price;
 }
 add_filter('woocommerce_get_price_html', 'edit_price_display', 10, 2);

And to only show in on the product single page we could use

function edit_price_display($price, $instance) {
     global $product;
  if(is_singular('product')) {     
  $price = $product->price;
  $price_incl_tax = $price + round($price * ( 21 / 100 ), 2);
  $price_incl_tax = number_format($price_incl_tax, 2, ",", ".");     
  $price = number_format($price, 2, ",", ".");     
  $display_price = '<span class="price">';     
  $display_price .= '<span class="amount">€ ' . $price_incl_tax .'<small class="woocommerce-price-suffix"> incl BTW</small></span>';     
  $display_price .= '<br>';     $display_price .= '<span class="amount">€ ' . $price .'<small class="woocommerce-price-suffix"> excl BTW</small></span>';     
  $display_price .= '</span>';     
  echo $display_price; } else {     echo $price;     }
 }
 add_filter('woocommerce_get_price_html', 'edit_price_display', 10, 2);

NB Code may be malformatted. Check source for code with proper html tags!

NBB We could also then filter with another conditional by role. See further down for an example using just that.

Source Thomas Schmidt

WooCommerce Different Tax Rate by Role

As suggested by WooCommerce themselves we can use the woocommerce_product_tax_class filter to use a different tax rate for a user:

<?php
 /**
 Apply a different tax rate based on the user role.
 */
 function wc_diff_rate_for_user( $tax_class, $product ) {
 if ( is_user_logged_in() && current_user_can( 'administrator' ) ) {
     $tax_class = 'Zero Rate';
 }
 return $tax_class;
 }
 add_filter( 'woocommerce_product_tax_class', 'wc_diff_rate_for_user', 1, 2 ); 

The administrator role used here as you can see and $tax_class is set to zero.

NB https://docs.woocommerce.com/document/setting-up-taxes-in-woocommerce/#section-19

Product Page Display Excl. VAT by Role

If you would like to only show the price excluding VAT or a user role and still have the user pay VAT in the end you can use the following code