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

Taxes being combined incorrectly #4318

Closed
radar opened this issue Feb 10, 2014 · 40 comments
Closed

Taxes being combined incorrectly #4318

radar opened this issue Feb 10, 2014 · 40 comments

Comments

@radar
Copy link
Contributor

radar commented Feb 10, 2014

/cc @jdurand

Related to #3830, particularly 7a1bf53's deduced_total_by_rate method.

I'm seeing an issue here where a line item will go up to its tax category and apply all rates for that tax category, regardless if they match or not. This means I'm seeing US rates applying for EU items, which seems bad.

I'm pretty close to reverting that commit now, but I don't want to do it when I'm in this much of a jetlagged state.

@radar
Copy link
Contributor Author

radar commented Feb 10, 2014

@jdurand: I don't understand under what conditions two tax rates can apply to the same item. Can you please explain that?

@jdurand
Copy link
Contributor

jdurand commented Feb 10, 2014

In Canada (and probably other countries), federal and provincial taxes are calculated separately (some provinces ave harmonized sales taxes (HST)). A typical Quebec receipt goes like this :

    Item 1                               5,00 $
    Item 2                               5,00 $
    Subtotal                            10,00 $
    GST (9.975%)                         1,00 $
    QST (5%)                             0,50 $
    Total                               11,50 $

So in this case I have 2 tax rates matching my "Goods & Services" tax category.

Can you clarify "a line item will go up to its tax category and apply all rates for that tax category, regardless if they match or not", because I can't figure in what scenario a line_item would apply only one of it's matching tax rates.

I'll take another look at it tomorrow after a few espressos.

@radar
Copy link
Contributor Author

radar commented Feb 10, 2014

Ah, yeah that sounds familiar. I think cities like NYC in the US have taxes like that too

My case was that I had a "Clothing" tax category which had two rates: one for EU and one for the US. When I bought a product and specified my address to be in Finland, I was expecting only the EU tax rate to be applied. What happened instead was that both the US and Finland rates were combined and then that amount was applied. That made the tax amount incorrect.

I think what needs to happen in that method is a zone check right here that compares the tax rate's zone with that of the line item's order's tax_zone. If the zones don't match, then the tax rates should not be combined.

@vkvelho
Copy link
Contributor

vkvelho commented Feb 10, 2014

Also the tax_zone instance method of an Order doesn't return the real tax zone in some cases. I know this is not the same issue, but I think it can be(come) part of the problems with the tax calculations.

What I'm talking about:
https://www.evernote.com/shard/s156/sh/11119776-7617-4893-b4a1-78f614379e83/711fcf0f79d8f84daf3fe0d4ebe98cac

@vkvelho
Copy link
Contributor

vkvelho commented Feb 10, 2014

I wonder if there should be a tax_zones method (in plural) for an Order. That would allow nested tax zones and for example the compute_line_item method could check if the order's tax zones really include the tax rate that it is going to process. Does that make any sense?

@radar
Copy link
Contributor Author

radar commented Feb 10, 2014

@vkvelho I think that's a configuration issue more than anything. If Finland has it's own VAT rate separate from the rest of the EU, then that should be in its own zone and you should have tax rates for that specific zone.

According to this document on vero.fi you would have the following setup:

  • Zone: Finland
    • Tax Category: Standard
      • Tax Rate: 21%
    • Tax Category: Food Stuff / Animal Feed / Restaurant & Catering Services
      • Tax Rate: 13%
    • Tax Category: Reduced
      • Tax Rate: 9%

I think how we have the default data setup currently is bad and we should fix that. All the countries that are currently in the EU_VAT zone should be in their own zones and have their correct tax rates configured.

@vkvelho
Copy link
Contributor

vkvelho commented Feb 10, 2014

EDIT: @radar Oups, I read your answer correctly right after my answer. Finland should not have it's own VAT rate separate from the rest of the EU. I just followed your Shipping Methods documentation and created a zone for a Finland-only shipping carrier.

@radar Ah, right! So the Zones should be always thought as tax zones and therefore I have to duplicate the same rates for the both zones, the EU_VAT and the Finland. Yeah, that'll work for now, but in my opinion it's not the best approach and it can lead to unnecessary complex configuration and duplication of tax rates and shipping methods. I'd rather restrict a shipping method to a zone that is not a tax zone. Just a zone that defines an area.

Oh, and definitely do NOT change the EU_VAT zone to separate zones for every country. For example all the retail sales from Finland to any other country in EU_VAT zone are made using the tax rates of Finland. Only if the sales are higher than xxxxx euros / year / destination country, the sales tax rates of the order's destination address should be used.

@radar
Copy link
Contributor Author

radar commented Feb 11, 2014

You can have a zone for Finland which is used by the tax rates to calculate Finland-specific tax, AND you can have a zone for the EU which is used to calculate the correct shipping methods for those countries within the zone. The tax calculation is done through order.tax_zone. That uses the shipping address by default, but can be configured to use the billing address by setting Spree::Config[:tax_using_ship_address] to false from its default of true.

The shipping calculation is done with this code within Spree::Stock::Estimator which uses ship_method.include? to find the applicable zone, using order.ship_address for that zone.

There I believe if you set up zones like this, it will work:

  • Zone: Finland
    • Countries: [Finland]
    • Tax Category: Standard
      • Tax Rate: 21%
    • Tax Category: Food Stuff / Animal Feed / Restaurant & Catering Services
      • Tax Rate: 13%
    • Tax Category: Reduced
      • Tax Rate: 9%
  • Zone: EU
    • Countries: [EU countries including Finland]
    • Shipping Method: $9 EU-Wide Shipping (or whatever)

@jdurand
Copy link
Contributor

jdurand commented Feb 11, 2014

@radar a zone check is missing indeed. Appart from that, and from what I read here, this taxation system seems to work as expected.
I'll do that right now and submit a pull request.

PS: Do you ever sleep?

@radar
Copy link
Contributor Author

radar commented Feb 11, 2014

Ok, I've done more work on this today and I am pretty damn close to getting it done.

I am pretty confident that this code here is incorrect:

@combined_taxes = @rate.amount+@rate2.amount
@price_wo_taxes = @order.item_total/(1+@combined_taxes)

The item total here is $19.99, but the first tax rate on the item is a 10% inclusive tax, which works out to be:

>> 19.99 - (19.99 / 1.10)
=> 1.81727272727273

Then the second rate, the 5% inclusive tax, is calculated:

>> 19.99 - (19.99 / 1.05)
=> 0.951904761904764

The totals of these are 2.769177489177494.

The way that that code doing it is combining the two rates so that a single calculation of 15% takes place, which comes out to be 2.607391304347825, a difference of 0.1617861848296691. In this instance, 16 cents less sales tax than is necessary is being collected. A trivial difference for small amounts, which only gets bigger as the amounts get bigger (obv.)

Therefore I think this code should be calculating the 10% rate and then the 5% rate, then using that rate for the assertion later on in the tests.

Let me know if I am crazy or not.

PS: Yes I do sleep, but I am in Australia and last week I was in London, so it has appeared for at least the last couple of weeks that I have not.

@radar
Copy link
Contributor Author

radar commented Feb 11, 2014

I've got work on my relevant-taxes branch which will fix these bugs. Let me fix the code in the tax_rate_spec.rb file and I'll submit a PR and ask for your feedback.

@jdurand
Copy link
Contributor

jdurand commented Feb 11, 2014

Actually you need to do the reverse calculation with the combined tax rates to find the price before taxes and then calculate each tax amount based the price before taxes :

19.99 / (1 + 0.1 + 0.05)
=> 17.382608696

17.38 * 0.05 = 0.869 (0.87 $)
17.38 * 0.10 = 1.738 (1.74 $)

17.38 + 0.87 + 1.74
=> 19.99

@radar
Copy link
Contributor Author

radar commented Feb 11, 2014

Aha! I will correct the test for reals then in that case.

@jdurand
Copy link
Contributor

jdurand commented Feb 11, 2014

Refer this issue in your pull request and I'll gladly take a look at it with my experience with weird tax regulations.

FYI, I don't know if we were the only people in the world doing this none sense, but before January 1st 2013, the QST (Quebec sales tax) was actually calculated on the Price + GST (Canadian general sales tax) :
http://www.revenuquebec.ca/en/entreprise/taxes/tvq_tps/modifications-regime-tvq.aspx

Taxception...

@radar
Copy link
Contributor Author

radar commented Feb 11, 2014

The branch is the relevant-taxes branch at radar/spree. You can see it here: https://github.com/radar/spree/tree/relevant-taxes

@jdurand
Copy link
Contributor

jdurand commented Feb 11, 2014

Yep, storing the amount pre tax will scale easier for others if they have to develop something non standard like what I mentioned in my last comment.

It will also make it easier when writing custom sales reports.

💯

@radar
Copy link
Contributor Author

radar commented Feb 11, 2014

Alrighty. That only took me a day. I honestly thought it would take me longer. All the tests are happy and I will now write up the PR. The PR itself has been a WIP since Tuesday last week... but that doesn't really count for much since I was only working on it in bits and pieces here and there before doing client work all week. Today's the first day I've been able to knuckle down on just this and get it done.

And it looks like it's done.

@vkvelho
Copy link
Contributor

vkvelho commented Feb 11, 2014

@radar I think we're still not at the same page here, but I'm quite confident to have a work-around by duplicating the tax rates from the EU_VAT zone into Finland zone. In my opinion it would be still better that users could create zones for whatever purpose (like restricting a shipping method to specific geographic area) without affecting tax rate calculations.

Another happy bedtime story about tax calculations:
Not sure how does it work in other countries, but in Finland the tax rate of shipping method can change depending on the products of the shipment. If the package contains only books the tax category for the shipping method could be also Books (VAT 8%). If it was full of electronics, the category should be Standard (VAT 24%). Now, because the shipping cost includes the VAT and the price is always the the same for the customers, the merchant gets more money from every shipment where the tax rate is less than the Standard 24%. Is it worth of it? For some stores it definitely is and I guess I'll have to do that with Spree in the future too. How? I have no idea yet, but I'd love to hear if that feels like a mission impossible to you.

(To be precise, if the package contains books, food and electronics, the shipping method could have three tax rates shared according to relation of different products prices. That's the perfect way, but it feels a bit too complicated request for now. Taxception indeed. :))

@jdurand
Copy link
Contributor

jdurand commented Feb 11, 2014

@vkvelho that's messed up ;-)

@peterberkenbosch
Copy link
Member

Had the idea that we solved it like that.. Looking better again later

On 11 Feb 2014, at 19:04, Ilkka Sopanen notifications@github.com wrote:

@radar I think we're still not at the same page here, but I'm quite confident to have a work-around by duplicating the tax rates from the EU_VAT zone into Finland zone. In my opinion it would be still better that users could create zones for whatever purpose (like restricting a shipping method to specific geographic area) without affecting tax rate calculations.

Another happy bedtime story about tax calculations:
Not sure how does it work in other countries, but in Finland the tax rate of shipping method can change depending on the products of the shipment. If the package contains only books the tax category for the shipping method could be also Books (VAT 8%). If it was full of electronics, the category should be Standard (VAT 24%). Now, because the shipping cost includes the VAT and the price is always the the same for the customers, the merchant gets more money from every shipment where the tax rate is less than the Standard 24%. Is it worth of it? For some stores it definitely is and I guess I'll have to do that with Spree in the future too. How? I have no idea yet, but I'd love to hear if that feels like a mission impossible to you.

(To be precise, if the package contains books, food and electronics, the shipping method could have three tax rates shared according to relation of different products prices. That's the perfect way, but it feels a bit too complicated request for now. Taxception indeed. :))


Reply to this email directly or view it on GitHub.

@radar
Copy link
Contributor Author

radar commented Feb 11, 2014

@vkvelho [citation needed]

I was hoping that the shipping would be a "Service" and therefore you would charge all shipments as the same VAT rate. The rate for the shipment (imo) shouldn't depend on the items inside that shipment as it makes the logic extremely complex for calculating shipping rates. If you can show me where there's a documented case of this being required then I would gladly take a stab at implementing this in a future version of Spree. It just seems quite mad to be doing it like that.

@radar
Copy link
Contributor Author

radar commented Feb 11, 2014

I asked on Twitter and got some responses there. That's for the UK VAT and I would assume EU countries work the same way.

@vkvelho
Copy link
Contributor

vkvelho commented Feb 11, 2014

@radar It's not a must-have requirement and it's perfectly legal to use the standard VAT for every shipment. However that splitted tax thing for shipping costs is what Finnish Tax Administration (vero.fi) says and that's what the local ecommerce stores do if possible. It's the key feature for some small ecommerce platforms, because not every store allows that.

The Finnish Tax Administration's customer service says that the delivery costs can be thought as part of the products price and therefore they can be taxed accordingly.

@radar
Copy link
Contributor Author

radar commented Feb 11, 2014

Can you show me where on vero.fi it does that? I just need to leave a comment in the code for that, that's all.

Just got a reply moritzs on Twitter who says that the higher VAT rate of all the items is used.

@vkvelho
Copy link
Contributor

vkvelho commented Feb 11, 2014

I'm quite sure we have to ask the answer in English from the Finnish Tax Administration if necessary, because vero.fi especially in English is... how to put it nice... "incomplete". I can't find the answer even in Finnish and I'm not surprised if it's not available there. I can assure that this splitted tax thing is correct information though.

@radar
Copy link
Contributor Author

radar commented Feb 12, 2014

I've been informed by @GeekOnCoffee today that Avatax could be a solution to our problems here. To be investigated at a later stage.

@vkvelho
Copy link
Contributor

vkvelho commented Feb 12, 2014

@radar I checked out the Avatax last year. To me it felt an overkill and unnecessary dependency to 3rd party service to accomplish something this simple. I think it's more useful service for stores in US where it seems that the tax rates can vary a lot for different orders. In EU we're be able to sell with one zone and tax rate to all the other countries in EU_VAT zone (as long as sales don't exceed something like 35 000 euros / year / foreign country).

I want to make myself clear again: Spree does perfectly legal and ok job with the current tax rates for the shipping costs in Finland and in other EU countries too, I guess. Finnish store admins just have to choose the most expensive tax category of all the products they sell in their Spree storefront. They'll pay taxes more than enough, but it's not a juridical problem, because in that case the shipping costs are thought as an service, which is not part of the product's price.

What I'd like to see coming in Spree though, is some extra tax categories for the shipping methods. In our case the tax category list for a shipping method could look like this:

  • Standard
  • Food
  • Books
  • Cart's highest rate
  • Split by cart items price

Cart's highest rate is a lot easier to implement and it saves money in many cases.

Some others options could be:

  • Split by cart items quantity
  • Split by cart items weight
  • Cart's lowest rate (not sure if this can be used anywhere)

@radar
Copy link
Contributor Author

radar commented Feb 13, 2014

@vkvelho (in no particular order)

Good to hear that Spree is doing a great job already with the taxes. We've wanted to get a "good enough" system in place that makes most people happy and I think we've accomplished that. There's certain minorities which of course won't be happy, like basically anybody in the US who cares about exact taxing.

US Tax law is by far the most screwed up / maddening. Here's the tax rates just around the city of Denver in Colorado:

screen shot 2014-02-14 at 9 28 19 am

And here's the results of me clicking around on TaxCloud's map in the general region of Washington DC:

screen shot 2014-02-14 at 9 29 25 am

Just utter sheer madness. Spree will never, ever, ever support these ridiculous tax rules and therefore in the case of our big clients we will always recommend that they use Avatax or TaxCloud to get the correct tax. Let those other people deal with the madness.

For these reasons with our bigger clients, we've been recommending them to use Avatax and it might just end up that the extension will be maintained by one of those big clients' teams. Bonobos already has an extension for it but I am not sure how compatible it is with the latest Spree branches. I would love it if they would continue maintaining that extension for the long-term. It will not be a core part of Spree, at least in the foreseeable future. We have plenty of work to do already, thanks :)

It's also worth noting that there is another service called TaxCloud which offers the same service, except just for the US.


What I'd like to see coming in Spree though, is some extra tax categories for the shipping methods. In our case the tax category list for a shipping method could look like this:

Standard
Food
Books
Cart's highest rate
Split by cart items price

Cart's highest rate is a lot easier to implement and it saves money in many cases.

Some others options could be:

Split by cart items quantity
Split by cart items weight
Cart's lowest rate (not sure if this can be used anywhere)

What you're asking for there is basically a rules engine for tax rates and we've already got a pretty complex rules engine within Promotions and I personally don't feel like maintaining Yet Another Rules System just to appease the tax law in a small handful of countries. If you want uber-accurate taxes, use Avatax or something similar. Spree will not be implementing a rules engine for taxes because it's a ridiculous waste of our time when other people are doing it better than we ever could.

Shipping methods now already support tax categories and because they're linked to a zone it's just a small hop, step and a jump to calculating the applicable tax rate for the shipping rate, which is what my recent work accomplishes. You can specify whatever tax rate you want for shipments.

Being able to apply the "Cart's highest rate" and "Split by cart items price" is going to require a ton of work which, frankly, is a Dragon's Den with a gigantic "Here Be Dragons" sign and therefore I am extremely reluctant to do anything like that.

Avatax or TaxCloud are the way to go.


In Australia, a shipment is considered a service and is taxed as such. If the shipping of $100 worth of items is going to cost $5 then the tax included in that shipment is going to be $0.45 (10% GST).

I was really surprised that Finland has such weird tax laws, but I guess everyone's entitled to their own opinions :P


Regarding the $35,000 limit: $35,000 isn't really all that much. You sell 350 $100 items (700 $50 items, 1400 $25 items, etc.) and you've busted it and need to change your tax rates completely. imo, it's better to account for the different tax rates just in case you tip over that $35,000 limit and have to change everything.

Best to go with the big tax rates imo.

@vkvelho
Copy link
Contributor

vkvelho commented Feb 14, 2014

Being able to apply the "Cart's highest rate" and "Split by cart items price" is going to require a ton of work ...

Maybe I underestimated the effort of having the cheapest tax category chosen on the fly.

I was really surprised that Finland has such weird tax laws, but I guess everyone's entitled to their own opinions :P

I guess you mean the splitted taxes of shipping costs now. I'm not sure how does that work in other EU countries, but apart from that we all have the same tax laws in EU_VAT zone (afaik). I'm fairly sure there are a lots of countries where at least the "cart's highest rate" for the shipping costs could be used, but people don't know that. You know, it seems the information isn't available/searchable even in the websites or other official material of the tax administrations. It's quite a river of lost taxes if every store eligible made the change.

Regarding the $35,000 limit: $35,000 isn't really all that much. You sell 350 $100 items (700 $50 items, 1400 $25 items, etc.) and you've busted it and need to change your tax rates completely. imo, it's better to account for the different tax rates just in case you tip over that $35,000 limit and have to change everything.

Everything, huh? In my opinion we can just create a new zone for the sold-over-the-limit country and populate the new zone with the VATs of that specific country. If we'll be there some day, we'll discuss that with our @local-tax-lawyer.

Best to go with the big tax rates imo.

Yup. This splitted tax for shipping was meant to be just a side note, but it got enormous wings. A great discussion though and thank you for your effort.

@JDutil JDutil added the taxes label Jul 18, 2014
@spreebot spreebot removed the Taxes label Jan 9, 2015
@JDutil
Copy link
Member

JDutil commented Jan 9, 2015

close:stalled

@spreebot
Copy link

spreebot commented Jan 9, 2015

This issue has been open for 14 days without actionable information or activity and will be marked as “stalled” and closed. Please re-open with the information requested.

Don't get discouraged that your issue has been closed, Spree is a busy project and gets a lot of issues so we need your help to make sure this issue contains all the information required. Please review our guidelines on how to submit an issue.

@radar
Copy link
Contributor Author

radar commented Jan 11, 2015

IMO it's ridiculous to be closing this issue.

Tax calculation is a serious problem and if stores get it wrong they can face huge penalties from their local tax agencies. Spree needs to endeavour to calculate taxes correctly.

Secondly, this issue clearly comes with steps to reproduce the problem and therefore, in my opinion, it should be investigated thoroughly and a fix should be attempted.

On 10 Jan 2015, at 06:07, Jeff Dutil notifications@github.com wrote:

close:stalled


Reply to this email directly or view it on GitHub.

@gmacdougall
Copy link

@jordan-brough @athal7 and I are going to be talking about taxes this week with the goal of coming up with a proper taxation solution to be developed in the near future.

@JDutil
Copy link
Member

JDutil commented Jan 12, 2015

Apparently I misunderstood and/or misread the issue when closing.

@JDutil JDutil reopened this Jan 12, 2015
@peterberkenbosch
Copy link
Member

Cool @gmacdougall, let me know if you need any help on that, if even some sample rules we have here in the Netherlands.

@BDQ
Copy link
Member

BDQ commented Jan 14, 2015

I think this issue certainly falls under the label of stalled, and should be closed under the new guidelines IMO. Closing an issue is purely to keep the issue triage / management sustainable, a closed issue certainly does not mean it won't be fixed.

I think a new pull request should be the next step if resolving this issue.

@BDQ BDQ closed this as completed Jan 14, 2015
@spreebot spreebot removed the reopened label Jan 14, 2015
@GeekOnCoffee
Copy link
Contributor

A closed issue does mean it won't be fixed, because it will be forgotten about... I can't find the new guidelines, so maybe they include some way of revisiting this, but it seems unlikely... the stalled label should be enough to keep issue triage and management sustainable, because you don't have to look at them when doing triage...

it's an issue that's been verified and well documented, and should be left open, rather than somebody opening a new one when they run into this same issue and having to do all the research over again.

Just my 2¢

@cbrunsdon
Copy link
Member

@BDQ can you please re-open this? Its actively being worked on by multiple companies and isn't affecting our triage of new PR's in the least.

We can understand why Jeff closed it, but also appreciated it when he re-examined and re-opened it.

@JDutil
Copy link
Member

JDutil commented Jan 14, 2015

I really think it would be beneficial to have a new issue created for this that breaks down the problem concisely. Reading through this thread it's confusing as to what the actual problem is, whether it was addressed or not, and if this isn't actually a feature request rather than a bug.

@cbrunsdon
Copy link
Member

@JDutil thats cool by me, I'm sure nobody would complain about starting up a new issue with the relevant compressed data and referencing this one.

Even a meta-issue tracking separate tax issues (rounding, accuracy, taxes-on-promotions) might be handy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants