Skip to content

Conversation

feliixx
Copy link
Collaborator

@feliixx feliixx commented Aug 1, 2025

When computing taxes, Stripe uses the 'commercial round' strategy, meaning that
0.5 will be rounded to 1 (when rounding to an integer) as stated here:
https://docs.stripe.com/billing/taxes/tax-rates#rounding

Localstripe behaves differently, because to achieve rounding it casts the
resulting float to an int with the line:

'amount': int(amount * self.percentage / 100.0)

But casting to an int doesn't use the same rounding strategy, indeed the
Python documentation says:

For floating-point numbers, this truncates towards zero.

So this effectively rounds 0.5 to 0, which is different from Stripe behavior.

This actually cause some computation differences for some combinations of tax
rate and amount, so let's update _tax_amount rounding strategy to use the same
one as Stripe.

WARNING: This is a breaking change as it will change the computed total of an
invoice in some scenarios.


Side note: I made sure that this change doesn't break our internal 11* test suit

When computing taxes, Stripe uses the 'commercial round' strategy, meaning that
0.5 will be rounded to 1 (when rounding to an integer) as stated here:
https://docs.stripe.com/billing/taxes/tax-rates#rounding

Localstripe behaves differently, because to achieve rounding it casts the
resulting `float` to an `int` with the line:

`'amount': int(amount * self.percentage / 100.0)`

But casting to an `int` doesn't use the same rounding strategy, indeed the
Python documentation says:

> For floating-point numbers, this truncates towards zero.

So this effectively rounds 0.5 to 0, which is different from Stripe behavior.

This actually cause some computation differences for some combinations of tax
rate and amount, so let's update _tax_amount rounding strategy to use the same
one as Stripe.

WARNING: This is a breaking change as it will change the computed total of an
         invoice in some scenarios.
Copy link
Owner

@adrienverge adrienverge left a comment

Choose a reason for hiding this comment

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

This makes much sense, thanks 👍

As you point out, this is a breaking change. If anyone has a good reason to be opposed to this, please tell it quickly 🙏

@feliixx
Copy link
Collaborator Author

feliixx commented Aug 6, 2025

Thanks for the review ! Nobody raised any concern about this so let's merge

@feliixx feliixx merged commit 9742dcd into master Aug 6, 2025
12 checks passed
@feliixx feliixx deleted the felix/fix-rounding branch August 29, 2025 13:56
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 this pull request may close these issues.

2 participants