Skip to content
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

Tax infrastructure and default implementation (OCC-76) #33

Open
bleroy opened this issue May 3, 2019 · 15 comments
Open

Tax infrastructure and default implementation (OCC-76) #33

bleroy opened this issue May 3, 2019 · 15 comments
Labels
enhancement New feature or request

Comments

@bleroy
Copy link
Member

bleroy commented May 3, 2019

Oh boy that's a tough one :D

Taxation is super-duper-complicated. It has lots of details, local subtleties, and unless you're selling very, very locally, you can't afford to ignore it.

In the MVP, we'll implement extensible infrastructure, enabling tax services to act on and modify an order. That's reasonably simple.

We'll also include a default implementation, that will also be fairly simple(istic), but will likely require more work for the shop administrator. It will likely involve a way to map customers to regions, and then regions to tax rates. Open questions include whether we should import data, under what format.

Jira issue

@bleroy bleroy added the enhancement New feature or request label May 3, 2019
@bleroy bleroy added this to To do in Work in progress May 28, 2019
@sarahelsaig sarahelsaig added this to the MVP milestone Jul 31, 2022
@sarahelsaig
Copy link
Contributor

Not a simple topic, let's dig in deeper.

Kinds of Taxes

I think there are only two kinds that come up for e-commerce: VAT or sales tax, and customs.

While there are many accounting and legal differences between VAT and sales tax, for the purpose of a sales platform like OCC they behave identically, as a percentage cost added to the line item. It's typically a single rate, but some product classes (e.g. essential food or hygiene goods) may have different rates. Though unless you are extremely sure, just use the full rate. In e-commerce the tax is paid according to the purchaser's country/state or origin.

(Customs depend on the source and destination countries too. Local orders, or orders within a customs-union (e.g. the Schengen Zone in Europe or MERCOSUR in South-America) suffer no customs and many countries waive customs on small value shipments. For the rest, it's incredibly complicated with individual line item classes, the total value, and possibly various treaties can affect the result. Luckily customs is the importer's responsibility. While bigger sites offer informative estimates, it's not a requirement.)

Generic Implementation

As a general solution I think we should have an event, something like PreparingCartForCheckout that gets the ShoppingCartItem collection and updates it. There the line items could be updated individually, in an extensible way. (The same event could be useful for shipping too to add a shipping cost entry.) When accessing the cart this even would be triggered before returning the items.

I'm unsure how we should express the tax on line items. Another question is if the prices should be net or gross. As I understand, in the USA it's typical to show net prices. This is also common in VAT-using countries for shops that primarily sell to other businesses (for VAT write-off reasons).
I think we have to bite the bullet and replace Money.Amount.Value with separate NetValue and GrossValue properties, to avoid potentially costly confusion. Then choosing which to display would be a matter of configuration. What do you think? Additionally we should have a string TaxName property, it would be important in the future if we need invoice integration.

Default VAT Implementation

This heavily depends on the above, but it should be flexible because these rates do change as legislation evolves (so don't use pre-calculated tax rate tables).
As a start, we should add a feature that represents a local VAT implementation, with an admin menu where you can pick a single percentage. Then it would just apply it from the above mentioned event. This is enough if you only sell domestically.
A different feature for or international orders, we might need to use a VAT API that gets the current and up-to-date numbers. I'm not aware of a reliable free API for that. If anyone has need or preference for this in the MVP, please speak up!

Nothing is Set in Stone

This is just my recommendation, please chime in if I missed something crucial. Please don't start working on the issue until we have heard some other voices on the topic.

@Skrypt
Copy link
Contributor

Skrypt commented Aug 4, 2022

Luckily customs is the importer's responsibility

I agree.

As a start, we should add a feature that represents a local VAT implementation, with an admin menu where you can pick a single percentage.

Here in Quebec we have 2 sales taxes. We have one that is federal HST (harmonized sales tax) and one that is provincial QST (Quebec sales tax). This means that it is a compound tax that needs to be calculated in the right order.

http://www.calculconversion.com/sales-tax-calculator-gst-qst.html

Here you can see how it is calculated. So, I believe that taxes should be based on some rules. Maybe looking into some known e-commerce platform could help find how it should be integrated.

@sarahelsaig
Copy link
Contributor

Based on the linked tax calculator (from OCC's perspective) boils down to a 114.975% sales tax that applies to a region instead of the whole country. Do you have to pay QST if you import something into Quebec or just for local sales?

@sarahelsaig
Copy link
Contributor

Anyway, you make a good point about looking at some other e-commerce platforms. I will look into it soon. In the meantime if anyone can point me to specific relevant parts in an open source e-commerce project, please don't hesitate.

@UR-ScottShew
Copy link

UR-ScottShew commented Aug 4, 2022 via email

@Skrypt
Copy link
Contributor

Skrypt commented Aug 4, 2022

QST is for local sales but as you can see it is also charged by Newegg.ca

image

It always depends if you need to produce a tax report for that country/state and I believe that it is now encouraged.

GST(HST) = Goods and service tax (Harmonized sales tax) = VAT (Value added tax)
PST(QST) = Provincial sales tax (Quebec sales tax)

As you can see here they always have 2 taxes which are defined by GST and PST.

And I believe that some States in the USA also have city taxes and special jurisdiction taxes.

@Skrypt
Copy link
Contributor

Skrypt commented Aug 4, 2022

+1 for Avalara but you also need a simple table solution for small websites.

https://github.com/avadev/AvaTax-REST-V2-DotNet-SDK

@UR-ScottShew
Copy link

UR-ScottShew commented Aug 4, 2022 via email

@UR-ScottShew
Copy link

UR-ScottShew commented Aug 4, 2022 via email

@UR-ScottShew
Copy link

UR-ScottShew commented Aug 4, 2022 via email

@Skrypt
Copy link
Contributor

Skrypt commented Aug 4, 2022

I believe that big e-commerce companies have been recently encouraged to pay sales tax in different countries at least (Amazon). So, while a state cannot require it we still need to take it into consideration. Also, at that point, you would surely be using Avalara.

@sarahelsaig sarahelsaig pinned this issue Aug 8, 2022
@sarahelsaig
Copy link
Contributor

Avalara looks very interesting. Also I see an alternative, TaxJar (a Stripe company). Both have NuGet libraries. In either case you need full source and destination address, and line items with prices and tax codes. I guess the tax code would be the one you use for the product domestically, because how on earth would you know/maintain all the different tax codes for every country? We could add an optional field in ProductPart to store the product's tax code. As for the source address, that could be a site setting. So these are the info we should include in the abstraction (the equivalent of ITax in Nwazet) to cover every implementation. The result would be a collection of tax name and amount pairs. It has to be for each line item, because applying tax on just the total is not allowed everywhere.

As for the implementation without an external service, we could do something similar to the ZipCodeTaxPart.Rates, but use the whole address and the tax code to match against (either as a table of regex expressions or perhaps create a DSL with Irony). Then every item that matches would be applied.

@bleroy
Copy link
Member Author

bleroy commented Aug 18, 2022

Probably shouldn't use ProductPart, which is deliberately minimalist in terms of concerns it addresses. There should be a separate part that encapsulates tax concerns and only that.

@sarahelsaig
Copy link
Contributor

Good point, I agree.

@sarahelsaig sarahelsaig moved this from To do to Overview/Discussion in Tax infrastructure Aug 19, 2022
@sarahelsaig sarahelsaig added pinned This is kind of a big deal and removed enhancement New feature or request labels Aug 19, 2022
@sarahelsaig sarahelsaig removed this from the MVP milestone Aug 19, 2022
@Piedone Piedone added the enhancement New feature or request label Sep 18, 2022
@github-actions github-actions bot changed the title Tax infrastructure and default implementation Tax infrastructure and default implementation (OCC-76) Sep 18, 2022
@BenedekFarkas BenedekFarkas unpinned this issue Jan 10, 2023
@sarahelsaig sarahelsaig removed the pinned This is kind of a big deal label Dec 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Tax infrastructure
Overview/Discussion
Development

No branches or pull requests

5 participants