Appearance
How does it work
The Store Tax module has no template tags of its own: it works inside the cart, the checkout and the orders of the Store module, so you keep using the regular Store tags and variables (see the Cart tag and the Order tag). The settings and rules are described on the CP Overview page; this page explains how they work together.
What changes in the Store module
When the module is installed, it takes over the tax calculation of the Store module:
- Store settings: the Tax settings section (high, low and shipping percentage, tax type and default rate) is hidden from the Store settings. The Calculate tax, Tax calculation (inclusive/exclusive) and Tax default rate settings are still Store settings, they are edited on the settings page of this module. The high, low and shipping percentages of the Store are replaced by the tax rules.
- Product tax: the tax rate of every cart item and order item comes from the matching tax rule.
- Shipping tax: the shipping tax comes from the matching tax rule as well, for every shipping method.
- Checkout: the tax number of a business customer is validated in the personal details step, see VIES validation.
- Cart and order totals: when the EU reverse charge applies, the tax is removed from the cart and from an order that is recalculated in the CP, and
is_reverse_charge_euis set. - Order view in the CP: for an order with reverse charge, the Store shows the stored VIES result of the tax number.
- The global variable
{reinos_store_tax_module_installed}of the Store is1, so you can show the tax number field or tax info only when the module is installed.
When you uninstall the module
- All data of the module is removed: settings, tax rules, logs, the remembered VIES results and the VIES results stored with orders.
- The Store calculates the tax again with its own Tax settings, which are shown again in the Store settings. They still have the values from before the module was installed, so check them.
- Existing orders keep their stored tax amounts, tax details and
is_reverse_charge_euflag. The VIES result is no longer shown on the order.
The flow
1. Determine the country of the customer
The tax is based on the billing country (and billing state) of the cart or order. When no billing country is known yet (e.g. before the checkout):
- When a Default member field country is selected, the country code is read from that member field of the logged in member. For guests, or members with an empty field, the Default country is used.
- Otherwise the Default country is used. When it is set to "None", no tax is calculated until the customer entered a billing country.
The shipping country is not used. The country must be a 2-letter country code, like the Store saves it with {exp:reinos_store:country_list}.
2. Find the tax rule
The tax rules are checked from top to bottom; the first rule that matches is used:
- a Country rule matches when its country is the billing country;
- a Continent rule matches when the billing country is in that continent;
- a State rule matches when its state is the billing state (case-insensitive) and, for a US state or Canadian province, the billing country is the United States or Canada. A custom state ("Other") matches in every country;
- a Global rule matches every customer.
So a continent or global rule placed above a country rule "hides" that country rule. When no rule matches, the tax is 0%.
Then the Applies to option of that rule is checked against the customer type (see Business detection). When the rule does not apply to this type of customer, the tax is 0%: the module does not look further for another rule. With Log settings on "Everything" a [Rule] notice on the Logging page tells which rule did not apply.
3. Calculate the tax
- Products: the
tax_rateparameter of the product (loworhigh, see the add_to_cart tag) selects the Tax (low) or Tax (high) percentage of the rule. Without the parameter (or with any other value), the Tax default rate is used. The rate is recalculated whenever the cart is shown or updated, so a changed billing country changes the tax. - Shipping: the Tax (shipping) percentage of the rule is used.
- The Store calculates the amounts and shows them in
{cart:tax},{cart:tax_details}, the_plus_taxvariables, and later in the same variables of the order. The Info of the rule is stored on the cart and order items.
4. Business detection and VIES validation
A customer is a business for the Applies to option when the company name is filled in (By Name), or when both the company name and the tax number are filled in (By Name and TAX number). The tax number does not have to be valid for this.
In the checkout, the tax number is validated when Validate tax number is enabled, or when Reverse charge is enabled and the billing country is in the EU. It is only validated when the company name is filled in (regardless of the Business detection setting). An empty tax number gives an error only when Allow empty TAX number is disabled.
- EU numbers are checked on syntax and with the EU VIES service. Swiss and UK numbers are only checked on syntax. Numbers of other countries (e.g. Norway) are always invalid.
- An invalid number gives an error on the
customer_tax_nofield and the checkout stops. - When VIES can't be reached, the number is accepted on syntax only. The error is written to the log.
- The VIES result of a tax number is remembered for 60 days (the same number with other spaces, dots or case uses the same result). In that time VIES is not asked again for that number. An answer given while VIES was down is not remembered, so VIES is asked again on the next check.
5. EU reverse charge
When Reverse charge is enabled and the cart has a tax number, the module checks whether the reverse charge applies. It applies when:
- the customer filled in a company name;
- the number is valid in VIES;
- the VIES country of the number is in the EU (including Northern Ireland,
XI); - the VIES country of the number is not the Store country;
- the zip code and city in the VIES address match the billing zip code and city of the customer. When VIES returns no readable address for the number (e.g. for Germany and Spain), the address is not checked and a valid number is enough.
When it applies, the tax of the items and the shipping is set to 0, the _plus_tax values are set to the values without tax and {cart:is_reverse_charge_eu} is 1. When the order is created, these values are copied to the order ({order:is_reverse_charge_eu}). See Reverse charge VAT for EU store owners for the template variables.
When an order is edited in the CP with "recalculate totals", the Store recalculates the tax with the tax rules of the order's billing country and this module applies the reverse charge again. The VIES result is stored with the order then.
Limitations
- Address matching: the zip code and city are compared without spaces and case (
1234 ABmatches1234AB,Den HaagmatchesDEN HAAG), but otherwise they must be spelled the same as in VIES (e.g.The Haguedoesn't match'S-GRAVENHAGE). The address can only be read for Austria, Belgium, Croatia, Czech Republic, Denmark, Estonia, Finland, France, Greece, Italy, Netherlands, Poland, Portugal, Romania, Slovakia and Slovenia; for the other EU countries (e.g. Germany, Spain, Ireland, Sweden) the address is not checked. For Romania VIES has no zip code, so only the city is compared, and VIES writes it with a prefix (e.g.MUN. CLUJ-NAPOCA). For Greece the address is transliterated to Latin characters. - The company name is not compared with the name in VIES: it only has to be filled in. VIES has the legal name, which often differs from the name a customer uses, and some countries (e.g. Germany) don't return a name.
Common pitfalls
No tax is charged
- No billing country yet, no country in the member field (when a Default member field country is selected) and no Default country.
- No rule matches the country, or the first matching rule does not apply to this type of customer (e.g. a rule for private while the customer filled in a company name). The latter is logged as a
[Rule]notice when Log settings is "Everything". - The reverse charge was applied (check
{cart:is_reverse_charge_eu}). - Calculate tax is turned off.
The wrong rate is charged
- A continent or global rule is placed above the country rule; only the first match is used.
- The product has no or a wrong
tax_rateparameter, so the Tax default rate is used. - With Tax calculation "Inclusive", the price without tax is calculated once with the rate that applied when the product was added to the cart. When the country changes, the tax is added to that price, so the price including tax changes. Use "Exclusive" when you sell to countries with different rates.
The reverse charge is not applied
- Reverse charge is disabled.
- The customer did not fill in a company name.
- The zip code or city does not match the VIES address (spelling), see Limitations. Set Log settings to "Everything" and check the
[VIES]notices on the Logging page. - The tax number is not valid in VIES.
The checkout shows "invalid tax number"
- The number is invalid in VIES or has a wrong syntax (include the country prefix, e.g.
NL123456789B01). - The customer is from a country outside the EU (e.g. Norway) while Validate tax number is enabled: their number can't be validated. Leave the tax number empty (with Allow empty TAX number enabled).
- A previous result of a number is remembered for 60 days.
The tax details are empty
- The reverse charge applies:
{cart:tax_details}has no rows then (an order shows one 0% row). Use{if cart:is_reverse_charge_eu}to show a reverse charge notice instead.
