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

Calculate tax with decimal precision and distribute proportionally across order items #13824

Merged
merged 9 commits into from Jul 4, 2023

Conversation

vvasiloi
Copy link
Contributor

@vvasiloi vvasiloi commented Apr 5, 2022

Q A
Branch? master
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Related tickets
License MIT

Attempt to solve the issue of decimal values being lost during tax calculation on item level which leads to a wrong tax total at the order level.

Issue reported by @ikamikaz3 via Slack (full thread):
image

@ikamikaz3
Copy link

Original author of the slack submission here.

Just tested this version of OrderItemsTaxesApplicator, works like a charm in my use case !

@CoderMaggie CoderMaggie added RFC Discussions about potential changes or new features. Bug Confirmed bugs or bugfixes. labels Apr 5, 2022
Copy link
Member

@lchrusciel lchrusciel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey folks!

thanks for bringing it up and the test that directly resolves the requested case.

However, I'm wondering what is the proper way of solving it from the taxation point of view. If I understood the current implementation the part that we are missing in each iteration is added to every 3rd element, which results in a slightly different tax percentage on these particular elements. On the other hand, we are having proper grand totals. I was thinking that moving the precision point could help us as well, but this solution seems to be more precise.

In the end, I don't have enough knowledge to make a call here. @CoderMaggie could you take a look into it from the PO perspective? Another option for me would be to dig into the tax calculation domain 😅

@ikamikaz3
Copy link

Hey folks!

thanks for bringing it up and the test that directly resolves the requested case.

However, I'm wondering what is the proper way of solving it from the taxation point of view. If I understood the current implementation the part that we are missing in each iteration is added to every 3rd element, which results in a slightly different tax percentage on these particular elements. On the other hand, we are having proper grand totals. I was thinking that moving the precision point could help us as well, but this solution seems to be more precise.

In the end, I don't have enough knowledge to make a call here. @CoderMaggie could you take a look into it from the PO perspective? Another option for me would be to dig into the tax calculation domain sweat_smile

In my case the issue was pretty simple, The DefaultCalculator removes the decimal part of the taxation amount resulting in the amount being off in the adjustement - missing 0,3333 in my example - which in the end makes the grand total being off aswell since it just fetch the adjustements recursively.

What I don't understand is how nobody had this issue before ? we saw with @vvasiloi that my use case is particular because :

  1. I have multiple order items based on the same variant with have a single quantity and a single unit.
  2. I can also have "default" order items which use the default behaviour of X quantity = X units. for those the base applicator does the job as expected.
  3. Both those order items "types" can be found in the same order.

Point number 1 seems to be the core issue here, and it's pretty easy to see why :
Imagine my order item's unit price is 19,70 or 1970 and I try to apply a 20% VAT to it. Using the default calculator and applicator, the result is 3,28 or 328 and it's then applied to my single unit as adjustement.
Now let's say we add the same order item again but not as another unit but rather a whole new order item.
Now I have 19,70 x 2 = 39,4 or 3940 and I try to apply the 20% VAT. Using the default calculator and applicator, both order items have their taxes calculated separately so again 328 is apply to each unit.
Then when I tried to get the taxTotal I would simply get 328x2 = 656 but if I calculate it manually : 3940−(3940 ÷ (1 +0,20)) = 656,666666667 which is rounded to 657 or 6,57 instead of 656.
The more items I had this way, the more decimal parts I lose and in the end the grand total of tax becomes way off.

Maybe it's explained better this way. :)

@vvasiloi
Copy link
Contributor Author

vvasiloi commented Apr 6, 2022

If I understood the current implementation the part that we are missing in each iteration is added to every 3rd element, which results in a slightly different tax percentage on these particular elements.

@lchrusciel not really, I just used Sylius\Component\Core\Distributor\ProportionalIntegerDistributor, which distributes the missing amount resulting from rounding to all items, cent by cent. Here's how the item-unit tax adjustment amounts look like in the test case:
image

@ikamikaz3
Copy link

@vvasiloi @lchrusciel

To add to the previous reply if I take my example again with the new implementation, I would have one tax adjustement amount at 328 and one at 329 giving me the correct 657.

@GSadee
Copy link
Member

GSadee commented Jun 16, 2023

Hi!
I've looked into this problem and I don't know if I'm missing something, but I'm unable to reproduce it. It may have been fixed in the meantime, although I can't find a specific PR.

In any case, reproducing even a specific scenario, with the suggested product price, tax rate amount and items quantity, the adjustment amounts are correct, I mean, they distribute according to the quantity so that the tax total is correct. Below are screenshots of my configuration:

Zrzut ekranu 2023-06-16 o 15 08 42 Zrzut ekranu 2023-06-16 o 15 11 15 Zrzut ekranu 2023-06-16 o 15 10 16

@GSadee GSadee added Potential Bug Potential bugs or bugfixes, that needs to be reproduced. and removed Bug Confirmed bugs or bugfixes. labels Jun 16, 2023
@vvasiloi
Copy link
Contributor Author

vvasiloi commented Jun 16, 2023

@GSadee Yes, you've missed the fact that the scenario to reproduce it is to have 20 order items, not 1 order item with 20 qty. See the test case.

@GSadee GSadee force-pushed the decimal-precision-tax branch 2 times, most recently from 42578d7 to bf0e2a9 Compare June 22, 2023 05:13
@probot-autolabeler probot-autolabeler bot added the Documentation Documentation related issues and PRs - requests, fixes, proposals. label Jun 22, 2023
@TheMilek TheMilek force-pushed the decimal-precision-tax branch 2 times, most recently from 6671ab0 to 47066dd Compare June 23, 2023 09:19
@GSadee GSadee marked this pull request as ready for review June 29, 2023 11:59
@GSadee GSadee requested a review from a team as a code owner June 29, 2023 11:59
@GSadee GSadee changed the title [WIP] Calculate tax with decimal precision and distribute proportionally across order items Calculate tax with decimal precision and distribute proportionally across order items Jun 29, 2023
@TheMilek TheMilek merged commit 816baef into Sylius:1.12 Jul 4, 2023
25 checks passed
@TheMilek
Copy link
Member

TheMilek commented Jul 4, 2023

Thanks, Victor! 🥇

@vvasiloi
Copy link
Contributor Author

vvasiloi commented Jul 4, 2023

Thank you for finishing this!

jakubtobiasz added a commit that referenced this pull request Aug 10, 2023
…(GSadee)

This PR was merged into the 1.13 branch.

Discussion
----------

| Q               | A                                                            |
|-----------------|--------------------------------------------------------------|
| Branch?         | 1.13|
| Bug fix?        | no                                                      |
| New feature?    | no                                                      |
| BC breaks?      | no                                                      |
| Deprecations?   | yes <!-- don't forget to update the UPGRADE-*.md file --> |
| Related tickets | #13824 and #15184 |
| License         | MIT                                                          |

<!--
 - Bug fixes must be submitted against the 1.12 branch
 - Features and deprecations must be submitted against the 1.13 branch
 - Make sure that the correct base branch is set

 To be sure you are not breaking any Backward Compatibilities, check the documentation:
 https://docs.sylius.com/en/latest/book/organization/backward-compatibility-promise.html
-->


Commits
-------
  Trigger deprecations in taxes applicators
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Documentation Documentation related issues and PRs - requests, fixes, proposals. Potential Bug Potential bugs or bugfixes, that needs to be reproduced. RFC Discussions about potential changes or new features.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants