Handling discount and taxes, help needed!

  1. you are wrong here.
    If you calculate your discount AFTER taxes they are paying 91.60€ for your product. and 17.40€ (19% of 91.60€) taxes. Together its the 109€ you already mentioned.
  2. This is already planned for v1.6.0 (LINK, LINK2)

There will be an official answer from @Severenth @UnderDog and me in the next coming days.

1 Like

No brother, you are simply redistributing the proportion of what is item price and what is tax, but this will give you nonsense numbers.
We are not doing math for number’s sake, the numbers actually stand for something.

If you take the example from before:
-price: 100 euro
-discount: 10 euro discount
-taxes: 19% taxes

You’ll never be able to obtain the numbers you gave from the actual data:
In my price book, this item minus the discount should be 90 (100-10), but in the result I get 91,60 euro. What is 91,60? What does it stand for?
In my price book, this item should be sold for 100, but I’m selling it for 101,60 if I remove the discount… What is 101,60?

The result is different from the sum of the parts.

In the current Italian e-invoice XML, I have to specify the tax base, and if I put the number that IP gives me it will be wrong.
For reasons like this, like @ComputingFroggy said, in most countries, you cannot discount after-tax, period.

If you do solve both ways, it’s clear that with this system you are taxing the wrong amount, look:
Step 1:
Before tax: ((100 - 10) + ((100 - 10) / 100 * 19)) = 107.1 euro
After tax: ((100 + (100 / 100 * 19)) - 10) = 109 euro
Step 2:
Before tax: (90 + (90 / 100 * 19)) = 107.1 euro
After tax: (90 + (100 / 100 * 19)) = 109 euro

The tax bases are both 90, but you are taxing in the second case the full amount and not the discounted amount.
The difference between the two prices is the 1.9 euro in excess you are adding, look:

Difference: ((100 - 90) / 100 * 19) = 1.9 euro

1 Like

This is the reason why this change should be made as soon as possible,
cause aside DE and how is done there, for the rest of us, the calculation is literally wrong.

In the same breath, the different interpretations of how the taxes and discounts are applied is a good motivation of not rushing into the completion of the process while it is not properly speced out.

Since this will be new functionality, I would rather all possible scenarios be specified and build, instead of catering for one market and re-coding later on, which become expensive (in terms of time, complexity, stability etc).

I want to step aside from my opinion on discounts, taxes, etc. and purely looking at the code.

Version 1.5.10 is purely meant as a patch version. We want to improve:

  • compatibility with PHP 7.3
  • bootstrap CSS version
  • numerous javascript dependencies (package.json)

After we get this version released we can focus on other things and yes, we’ll figure out this topic, but let’s not do that in 1.5.10

1 Like

You are wrong with this statement.
Taxes in the secon example are 17.40€ not 19.00€! So we are not taxing the full amount.
Pls understand this. This is how it works in germany and I can say that its not working the same way in other countrys.

(I marked what you did wrong)
Here is how “After Tax” is done right:

After tax: (91.60 + (91.60 / 100 * 19)) = 109.004 euro

But as 91.60 stands for 91.5966386555€ (as it is rounded) so its basically :

After tax: (91.5966386555 + (91.5966386555 / 100 * 19)) = 109.00 euro

Now you also know what the “91.60” stands for.

To leave a few words about it:

If you give a discount, who are you giving that discount for? For you or for your client?
Most probably for your client. So if you give a discount of 10€ the client in the end should pay exactly 10€ less then before, right?

So in the end he should pay 109.00€ if the product costs 119.00€ (with 10€ discount).
If you calculate discount after taxes you will make more profit.

I understand that this is not the case in other countrys. But this feature will not make it into IP before v1.6.0. Other countrys are working differently and InvoicePlane should aim for statisfying the international market. There are open Feature Requests and they will be implemented.

To make this happen we first have to get IP back on track. IPv1.5.10 is a big step for this, as its the first release since abount 2 years which will make sure IP is up to date. IPv1.5.XX will not include any new features or any new functions, its a maintain release.

We are not getting anywhere with this discussion, anyway like it is right now most people cannot use it without jumping the discount system all together, it’s fine to do it at v1.6.0, leaving v1.5.9 as a fixup, in the meantime I’ll fork from our end, until fixed.
Since it’s America the first user base, and America uses before tax by default, I would consider this a priority.
I also ask myself how the program does/will do accounting, since the subprice from the article side and the calculation side are different? Offsetting all the calculations?

Back on the discussion:

I think I know what you are doing @Martin_Anonym, I think I got it:
This is the problem! You are definitely not doing after-tax! you are doing before-tax equating to the discounted amount.

final_price_not_discounted - discount = before_tax(x) --> x is the amount needed to arrive to that price, but you are using before-tax formula!

item price: 100
discount: 10
tax: 19%

final_price - discount = (price - x) + ((price - x) / 100 * tax_perc)
119 - 10 = (100 - x) + ((100 - x) / 100 * 19)

we set (100 - x) = k

109 = k + (k / 100 * 19)
109 = 119/100 k
k = (100 * 109)/119

bring back (100 - x)

100 - x = (100 * 109)/119
x = 1000/119
x = 8.4 euro

this is the x amount we need to offset the calculation to get 10 euro discount, so:

109 = (100 - 8.4) + ((100 - 8.4) / 100 * 19)
109 = 91.60 + 17.40

and those are the numbers you are getting…

So @Martin_Anonym you didn’t understand the point of the conversation, you are still using before-tax formula but you are offsetting an amount to get the 10 euros from the final price. This is not like using after-tax discount. IP is using after-tax discount. And this is wrong.

And this was pointed out from many users:

IP is not using another method, is doing the calculation wrong.
This should be on top of our priority. Users might not be aware.

1 Like

I do not want to interfere too much, but . . .

say Netprice is 100
say Discount is 10
say VAT is 19%

Discount can be given on Net-Price or on Gross-Price

Netprice-Discount is easy - Calculation gros-price -> (100 - 10) * 1.19 = 107,1 instead of 119

Grossprice-Discount Gross-price without discount 119 - with discount 109 meaning
Netprice = 109/1.19 = 91,60 and VAT is 110 - 91.60 = 17.40

Using this simple arithmetic and the choice for NET-Discount or GROSS-Discount should do it.

If a percentage is used, then the arithmetic must first calculate the sum with which the grosprice is reduced in order to recalculate the netprice.

I have been dealing with POS-Systems for years and with some ERPs, I have checked this with several tax consultants in NL, D and A.
Feel free to do the same with any tax consultant where ever in the world.


Hi @janvl,

let me be clear, the problem here is not Net price or Gross price, we can easily make a setting switching between the two.
The problem is that right now IP is using none of 'em. It is just subtracting discounts after tax.
We should first fix this problem, and then we can discuss, what option to give the user, what should be the default, how, where, when…

To make this clear, I invite you to fill an invoice with your data, and see this yourself:

say Net-price is 100
say Discount is 10
say VAT is 19%

As you said:
Netprice-Discount (or before-tax) gets you: 90 + 17.1 = 107.1 euro

As you said:
Gross-price-Discount (or equating-from-the-final-price) gets you: 91.60 + 17.40 = 109 euro

But now get IP, and make this invoice:
it gets you 90 + 19 = 109

and this is clearly wrong, you are getting the wrong tax amount for that net.

After merging the IT version with 1.5.10, I did this PR to add percent discounts on items and fix the total calculation for the time being.

It applies the discount on the net amount, as it’s accustom in Italy, we can add a setting to switch between the two calculations in IP international 1.6.0.
Eventually, we will merge and rectify it with 1.6.0.

Thanks for the PR, but actually the InvoicePlane-it is not the official Repository, so if you want this to be included in official Releases you should open a PR to the official InvoicePlane Repo into the branch v1.6.0


Of course, InvoicePlane-it is the Italian fork.

What I mean is that we are prob. going to anticipate these fixes into 1.5.10, and they are going to be used and tested.

So whenever works for 1.6.0 will start, it can be a base for 1.6.0 for the international version. Just that.
I can make a second PR for the 1.6.0 branch myself when I finish on the other end.

1 Like

I’ve merged master on branch v1.6.0, and added both before and after-tax calculation based on a switch in settings. I’ve noticed there was a switch already there called ‘default_invoice_tax_rate_placement’ connected apparently to nothing, and I’ve used it for this.

To a first comparison, the numbers should be ok for both cases, we need to check the total invoice numbers, that are still wrong. Let’s go by steps. I don’t want to push too much stuff all at once.
I’ll make another commit fixing the total.

In the meantime,
lets’ all check the numbers together and make sure we all agree they are correct.

I’ve made a couple of invoices to check the calculation, but I don’t use the “after-tax” day-by-day, so please do a test and check.

1 Like

Got finally around to fixing totals, now they are correct.

I’ve made tests using the following scenarios:

Case 1:

Item price: 100 euro
Item discount: 10 euro
Item tax: 19% VAT


subprice: 90 euro
tax amount: 17.10 euro
discount: 10 euro
total: 107.10 euro


subprice: 91.59 euro
tax amount: 17.41 euro
discount: 10 euro
total: 109 euro

Case 2:

Item price: 105 euro
Item quantity: 2
Item discount: 12 + 5% euro
Item tax: 19% VAT


subprice: 175.50 euro
tax amount: 33.34 euro
discount: 34.50 euro
total: 208.84 euro


subprice: 168.84 euro
tax amount: 32.08 euro
discount: 48.98 euro
total 200.92 euro

To me it’s correct, consider merging in 1.6.0 when someone can.

1 Like

Befor merging I would like to publish a Test-Release for v1.6.0 made of your Fork (LINK) to give the community the opportunity to test it and to give some feedback.

Therefor I just build a “TaxTestv1.6.0” release which is just for testing purposes and should not be installed on any productive System, but on Testing/Dev System.

I have not tested it yet but will do so soon.
Here is the Test-Release:

Identifier Value
name: TaxTestv1.6.0.zip
md5: 0eb0db1a3ba5779a52dcbd99bdfbe5fb
sha256: b0c2ff61f5d5e8b1754e367e3f9b4d1389080f118424220c5895cbecc1a3a12a
size: 13.801 MiB
dl file (com): https://dl.invoiceplane.com/TaxTestv1.6.0.zip
txt sums (com): https://dl.invoiceplane.com/TaxTestv1.6.0.zip.txt
dl file (org): https://dl.invoiceplane.org/TaxTestv1.6.0.zip
txt sums (org): https://dl.invoiceplane.org/TaxTestv1.6.0.zip.txt

NOTE: This TestBuild is probably just PHP 7.0-7.2 compatible, so pls do not test with PHP 7.3 or PHP 7.4 yet

Pls report after testing if everything was like expected or not.
Have fun testing!

thank for the screenshot, i now understan and thanks to Martin and you for solving this in 1.6.
regards Jan

1 Like

@bob thanks for your valuable feedback.
Pls have a look here: LINK
As this is the official Pull Request and may contribute your Code-Change here.

I also added a comment to the PR and let @Luca_Pellizzari know that there are some issues/questions and may he clarifies how this exactly should work, or if this behaviour is a bug or a feature.

great martin thanks for your swift reaction. will also invest some time this week to contribute

@Luca_Pellizzari @bob
thanks for your work and for testing!

Anytime you need a new Test-Build pls tell me. We have optimized some Backend-Tasks to be able to generate Test-Builds much faster and much more frequently to support people which are supporting the project with Test-Builds.