Most countries have some kind of sales tax applied to goods being purchased.
In the UK for example, the current VAT rates are zero (0%), reduced (5%) and standard (20%). Here are rates in other EU countries
A tax is modeled as a type of Adjustment (#29) (
The text was updated successfully, but these errors were encountered:
Note: It might make more sense to calculate the tax-inclusive price once at write-time rather than dynamically at read-time for perf reasons.
Whenever the price or taxCategory of a ProductVariant is changed, the tax-inclusive prices are calculated and saved to the DB.
After playing around with the initial implementation, it looks like it will not be flexible enough to account for differing tax zones.
I'll now have to look into a zone system (see https://docs.sylius.com/en/1.2/book/customers/addresses/zones.html) which can then be used for configuring both tax adjustments and shipping adjustments.
For an example of how complex tax rules can get (and the need for user-defined zones), check out this example from the Shopify docs:
Customer Tax Category
Researching this a bit further, and there is more complexity we need to support: different types of customer might be liable to different rates of tax. For example, a business customer in another EU country would be charged 0% VAT whereas a consumer would be charged regular VAT.
The use-cases are well described in this Sylius issue: Sylius/Sylius#8047
Therefore the current naive implemetation will need a complete redesign to account for:
Relates to #31 #26 #29 This merge introduces the basis of what seems to be a workable tax & promotions system. There is still more to do, most importantly solving the problem of how the admin can set the gross price of a ProductVariant, as well as working out how the typical range of promotion actions can be implemented (buy 1 get 1 free, money off order etc). However, this work can now be continued on the master branch.
The above merge implements a workable taxation system implementing the requirements above.
Net vs Gross prices problem
There remains one major deficiency though: currently all ProductVariant prices are considered net (before tax) values. Taxes are then calculated based on the applicable rate. This is simple and flexible, but in the real world this is not always desirable. Consider:
A UK-based shop sells rocks primarily to the UK market. They wish to sell Rock A at a (gross) price of 99p. With standard UK VAT at 20%, there is no way to achieve this:
Thus the closest possible gross prices are either £0.98 or £1.00.
For some companies, this will be a deal-breaker because they may want to set gross prices based on marketing or other factors, and be able to offer those exact gross prices to customers.
I can see 2 possible solutions to this problem:
I think the second option is the better one here. The next question is then: where to store the fact that the prices include tax?
Relates to #31, aims to solve the "net vs gross prices" problem outlined therein. Next step is to get the tax calculations working correctly for Orders when tax is included in price.
When the ProductVariant has tax-inclusive prices. Relates to #31
Note on EU VAT calculation
In discussion with a merchant, the following rule came to light:
However, if that customer ships the order to the EU, then VAT is charged.
Likewise, if a customer has a EU billing address and ships and order outside the EU, VAT is charged.
This suggests that we need a configurable function which determines under which circumstances taxes should be applied, based on billing address, shipping address, and perhaps other factors. See
Note on VAT on Shipping
The same merchant says that if the order contains only zero-rate goods, then no VAT is charged on the shipping. As soon as a 20% product is added to the order, then the shipping should also include 20% VAT. Need to look into this and verify the actual applicable law.