-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add taxation guide #1606
Add taxation guide #1606
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❤️ 💯
|
||
Tax rates are associated with a tax category and a zone. If an order's `tax_address` (usually the shipping address) falls within a zone with tax rates, those rates will apply to all line items and shipments with respectively matching tax categories. | ||
|
||
When a tax rate gets applied to a line item, two things happen: A tax adjustment is created on the line item, and the line item's `additional_tax_total` and `included_tax_total` are changed to reflect the newly created adjustments. The amounts are then added to the order's `*_tax_total` fields. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the difference between additional_tax_total
and included_tax_total
? Perhaps link down to the lower section? Or does the more conceptual, introductory section "Sales tax vs. Value-Added Tax" belong higher up in this document?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I'll move this section down.
|
||
### Tax Rates | ||
|
||
A tax rate is essentially a percentage amount charged based on the net price. Tax rates also contain other important information. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the phrase "net price" merits further explanation. Does that include item-level adjustments? Order-level adjustments?
With Value-Added Tax (VAT), as found in Europe, but also in many other parts of the world, the prices of products and line items need to be shown *including* the consumption tax. When a product is exported, the price of that product has to change: It will be lower, because there is no included tax anymore. | ||
|
||
*** | ||
Most taxes can be considered one of these two types. For instance, in Australia customers pay a Goods and Services Tax (GST). This is basically equivalent to VAT in Europe. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We probably shouldn't be giving out tax advice:
For instance, in Australia customers pay a Goods and Services Tax (GST). This is basically equivalent to VAT in Europe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't consider that "tax advice", this is common knowledge (and is actually a verbatim copy of Spree's taxation guide :) ).
|
||
To model these behaviours in Solidus, use the `included_in_price` boolean on the `Spree::TaxRate` model. If `included_in_price` is set to `true`, Solidus will assume VAT-style taxation for this tax rate, if it is set to `false`, it will assume Sales tax style taxation. | ||
|
||
In some cases you may need to charge one type of tax for orders falling within one zone and another type of tax for orders falling within a different zone. There are even some rare situations where you may need to charge both types of tax in the same zone. Solidus supports all of these scenarios. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Solidus supports" extra space
In some cases you may need to charge one type of tax for orders falling within one zone and another type of tax for orders falling within a different zone. There are even some rare situations where you may need to charge both types of tax in the same zone. Solidus supports all of these scenarios. | ||
|
||
*** | ||
Taxation within the United States can get exceptionally complex, with different states, counties and even cities having different taxation rates. If you are shipping interstate within the United States, we would strongly advise you to use the [Solidus Avatax](https://github.com/solidusio/solidus_avatax) extension so that you get correct tax rates. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd also like to see here a link to the open issue @jordan-brough is working on in #1252 to suggest that there is more than one solution to this, and it is under active development.
|
||
## Prices in the backend | ||
|
||
In the Solidus admin backend, prices will be shown and entered with or without VAT, depending on the configuration value `Spree::Config.admin_vat_country_iso`. This has to be set to the two-letter ISO code of the country your admin thinks in. For a store that mostly sells to Germany, this would be set to `DE`. The effect of this is that now all prices in the backend will assume to have the German VAT rate included. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe there are open issues which talk about adding more robust pricing management in the admin. Perhaps more links to those issues to suggest further active development?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I do link to files in Solidus' master branch, I wouldn't want to link to issues. These guides are for people who I hope run stable versions of Solidus, and issues have a tendency of becoming out-of-date (thanks for the linking the VAT Roadmap, I had pretty much forgotten about that).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The purpose of this is that the admin does not have to handle net prices, no? So maybe explaining this helps to better understand this admin_vat_country_iso
thing.
|
||
Let's say you need to charge 5% additional ("Sales") tax for all items that ship to New York and 6% on clothing items that ship to Pennsylvania. This will mean you need to construct two different zones: one zone containing just the state of New York and another zone consisting of the single state of Pennsylvania. | ||
|
||
Here's another hypothetical scenario. You would like to charge 10% tax on all electronic items and 5% tax on everything else. This tax should apply to all countries in the European Union (EU). In this case you would construct just a single zone consisting of all the countries in the EU. To differentiate between "electronic" items and "other" items, use tax categories. Now setup two tax rates with the "EU" zone, and their respective tax categories. The fact that you want to charge two different rates depending on the type of good does not mean you need two zones.## Examples |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
##Examples
at the end of the line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought EU was VAT only? This example seems to contradict that?
|
||
Sales tax is the default tax type for any tax rate in Solidus. | ||
|
||
Let's say you need to charge 5% additional ("Sales") tax for all items that ship to New York and 6% on clothing items that ship to Pennsylvania. This will mean you need to construct two different zones: one zone containing just the state of New York and another zone consisting of the single state of Pennsylvania. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I appreciate the effort here, you've previously mentioned everyone in the US should not use these mechanisms to collect taxes, and instead use Solidus Avatax. Adding these examples seems to contradict that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a technical document, and describes what's possible. Something like US sales tax is possible, and that's what the documentation tells you. Zipcode-level taxation is not possible, but there might be stores that do not require it... Maybe.
@@ -0,0 +1,112 @@ | |||
## Getting Started with Solidus |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does not belong in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True that, will rebase.
10af632
to
b4ab98c
Compare
I've re-ordered the guide so that the VAT/Sales tax differentiation is explained in the beginning, then Solidus' taxation system is explained, then the pricing system. I've also removed some confusing/repeating paragraphs. |
b4ab98c
to
2cb3279
Compare
|
||
When a customer first browses your store, we do not know which jurisdiction she lives in. We will, therefore, have to make an assumption about her whereabouts. This assumption is the `cart_tax_country_iso` property on the `Spree::Store` model - meaning that you can assume your customers to be from different countries depending on which store she browses. | ||
|
||
This way, you can have, for example, two different stores for France and Germany (`my-shop.com/fr` and `my-shop.com/de`), where each shows different prices to accustom for the different VAT rates in either country. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be
to account for the different VAT rates in either country
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes
where each shows different prices to accustom for the different VAT rates in either country
where each store shows different prices to account different VAT rates in either country
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should mention the introduction about "Prices have to be displayed including VAT to the customer" requirement from above here, so the reader has a better understanding why this whole cart_tax_country_iso
is actually needed?
Maybe:
"Remember the requirement to display the prices including vat from above? This is how you comply to this..."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Woot! Martin, many thanks for writing all this down! This is great work, although I think we can clarify some topics by being a little more descriptive and try to use more short sentences and "easier language". The topic is hard enough :)
But really 💯 👍 🍌 🍨
|
||
Solidus represents taxes for an order's items by using `Spree::TaxCategory` and `Spree::TaxRate`. | ||
|
||
Tax rates are associated with a tax category and a zone. If an order's `tax_address` (usually the shipping address) falls within a zone with tax rates, those rates will apply to all line items and shipments with respectively matching tax categories. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sentence is a bit hard to read. Maybe:
If an order's tax_address falls within a zone its tax rates will apply to all line items and shipments with respectively matching tax categories.
|
||
### Sales tax vs. Value-Added Tax | ||
|
||
In e-Commerce, the type of tax we care most about is consumption tax, of which two main models are found: Sales Tax and Value Added Tax (VAT). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On our website we say eCommerce
|
||
In e-Commerce, the type of tax we care most about is consumption tax, of which two main models are found: Sales Tax and Value Added Tax (VAT). | ||
|
||
The Sales tax policies found in the USA are *additional* taxes. They do not change the amount of a line item, but are added just before calculating the order total. For Sales tax, the prices for items do not change when adding them to an order. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They do not change the amount of a line item, but are added just before calculating the order total. For Sales tax, the prices for items do not change when adding them to an order.
You basically saying the same thing twice. Maybe:
For Sales Tax the item prices do not change when adding them to an order. Instead they are added on top of the item price just before calculating the order total.
|
||
With Value-Added Tax (VAT), as found in Europe, but also in many other parts of the world, the prices of products and line items need to be shown *including* the consumption tax. When a product is exported, the price of that product has to change: It will be lower, because there is no included tax anymore. | ||
|
||
Most taxes can be considered one of these two types. For instance, in Australia customers pay a Goods and Services Tax (GST). This is basically equivalent to VAT in Europe. See the example section at the bottom for examples. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See the example section at the bottom for examples.
See the example section at the bottom.
Most taxes can be considered one of these two types. For instance, in Australia customers pay a Goods and Services Tax (GST). This is basically equivalent to VAT in Europe. See the example section at the bottom for examples. | ||
|
||
*** | ||
Sales tax within the United States can get exceptionally complex, with different states, counties and even cities having different taxation rates. If you are shipping interstate within the United States, we would strongly advise you to use the [Solidus Avatax](https://github.com/solidusio/solidus_avatax) extension so that you get correct tax rates. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should not advocate one taxation service over the other. There are more options then just Avatax.
|
||
### Sales Tax | ||
|
||
Let's say you need to charge 5% additional ("Sales") tax for all items that ship to New York and 6% on clothing items that ship to Pennsylvania. This will mean you need to construct two different zones: one zone containing just the state of New York and another zone consisting of the single state of Pennsylvania. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe additionally explain the need of both rates have to be linked to the "Clothing" tax category?
|
||
Let's say you need to charge 5% additional ("Sales") tax for all items that ship to New York and 6% on clothing items that ship to Pennsylvania. This will mean you need to construct two different zones: one zone containing just the state of New York and another zone consisting of the single state of Pennsylvania. | ||
|
||
## Examples |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These "Examples" are for Examples -> Sales Tax right? Then the heading needs to be #### Examples
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can just remove the heading, because you are continuing the examples section from above, no?
|
||
If the customer purchases a single clothing item for $17.99 and they live in the United States (which is within the North America zone we defined) they are required to pay sales tax. | ||
|
||
The sales tax calculation is $17.99 x 5% for a total tax of $0.8995, which is rounded up to two decimal places, to $0.90. This tax amount is then applied to the line item as an adjustment. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This tax amount is then applied to the line item as an adjustment.
This tax amount is then applied to the line item as an adjustment and added on top of the order total.
|
||
Many jurisdictions have what is commonly referred to as a Value Added Tax (VAT). In these cases the tax is typically already included in the price. This means that no additional tax needs to be applied during checkout. | ||
|
||
When tax is included in the price there the adjustments to the line items do not affect the order total (unlike the sales tax case). Stores are, however, usually required to show the amount of tax the user paid. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When tax is included in the price there the adjustments to the line items do not affect the order total
When tax is included in the price then the adjustments do not affect the order total
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stores are, however, usually required to show the amount of tax the user paid.
Stores are, however, usually required to show the amount of tax the user paid. That's why Solidus lists all adjustments below the item total on the checkout summary page.
|
||
### Different tax rates by tax category for the same zone | ||
|
||
Here's another hypothetical scenario. You would like to charge 10% tax on all electronic items and 5% tax on everything else. This tax should apply to all countries in the European Union (EU). In this case you would construct just a single zone consisting of all the countries in the EU. To differentiate between "electronic" items and "other" items, use tax categories. Now setup two tax rates with the "EU" zone, and their respective tax categories. The fact that you want to charge two different rates depending on the type of good does not mean you need two zones. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's another hypothetical scenario
Aren't you explaining a MOSS scenario here? So, this is not hypothetical at all, no?
2cb3279
to
c44fb9d
Compare
|
||
Most tax jurisdictions base the tax on the shipping address of where the order is being shipped to. So in these cases the shipping address is used when determining the tax zone. Solidus does, however, allow you to use the billing address instead. | ||
|
||
To determine tax based on billing address instead of shipping address you will need to set the `Spree::Config[:tax_using_ship_address]` preference to `false`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a good use case for this? Or is it just for like... digital goods or something? I would say bringing attention to it might not be worth it here unless its something we want to be keeping long term.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I haven't heard of a single instance where anyone set this to false
. I'll remove it from the guide and send a PR deprecating it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As this is correct for most use cases, it is possible that someone want / need to charge taxes on the billing address level. I don't think that removing this, only because we don't really know, is a good option as a world wide used ecommerce framework.
And since we have this option we should mention it here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've asked a number of times (at SolidusConf, in the Slack channel...). I've tried finding out where it comes from, and found this commit: spree/spree@d3ee561 - there's no explanation as to why it got introduced.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I said, we don't know ;)
As this is actually no huge burden https://github.com/solidusio/solidus/search?utf8=✓&q=tax_using_ship_address I think keeping it does no harm, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So apparently there is edge cases in the US where for some orders, depending on where the stock location is, and depending on where the customer is located, the billing address is used. See this blog post (I did not understand when it actually happens).
However, this configuration option is global. I'm still for killing it; in case you need that behaviour globally, it's easy to override Spree::Order#tax_address
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added it back in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left one comment, but otherwise I'd be good to merge as is, though I generally agree with Thomas' requests as well.
c44fb9d
to
8e9fdbc
Compare
This is a re-do of the Spree Taxation guide, adjusted for the changes in Solidus 1.3 and up. It explains how to setup your store for VAT-style taxation as well as Sales tax. Because of how VAT-style taxation influences prices, this document also explains how the price selector/pricing options mechanism works.
8e9fdbc
to
9204853
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great!
I think this is ready to merge and Thomas' requests have been adequately addressed.
This adds a guide for pricing and taxation, two related and difficult to grasp areas. It should be merged after #1598.