Daily updates from Odoo
Tuesday, February 20, 2024
1 change · master
Resolved issues and error corrections
This fixes tax calculation errors in complex real-world cases involving included taxes, fixed fees, and division-based taxes used in countries such as India, Belgium, and Brazil. Businesses should see more reliable invoice totals, tax amounts, and fiscal position mappings, reducing discrepancies in accounting and compliance workflows.
Original PR description
REAL TAX CASES TO COVER INDIAN CASE: 6% incl + 6% incl + 3% excl Both 6% incl must always have the same tax amounts (not working in master but fixed as well in this task). The 3% must be based on 12%…
REAL TAX CASES TO COVER INDIAN CASE: 6% incl + 6% incl + 3% excl Both 6% incl must always have the same tax amounts (not working in master but fixed as well in this task). The 3% must be based on 12% (working thanks to the is_base_affected checkbox). BELGIUM CASE: fixed tax + 21% incl (recupel case) That's for this case we allow to mix price-excluded with price-included taxes. BRAZILIAN CASE: 5 taxes having the 'division' type: 5% 3%, 0.65%, 9% and 15%. This case is tricky because it's based on the price-included amount and the whole computation was made only from the price-excluded amount. With a base of 48.0, the base amount of the 15% tax is computed as 48.0 * (1 - 0.15) = 40.8 so a tax amount of 48.0 - 40.8 = 7.2. So the respective <base, tax_amount> of each taxes are: 45.6, 2.4 46.56, 1.44 47.69, 0.31 43.68, 4.32 40.8, 7.2 ...and the price-excluded amount is 40.8. PROBLEMS TO SOLVE INDIAN CASE: Suppose a base of 100 with 2 x 6% incl taxes. The behavior in master: a - Find the price-excluded base: 100 / 1.12 ~= 89.29 b - Compute the first 6% incl tax amount: 89.29 * 0.06 = 5.36 c - Compute the second 6% incl tax amount. Since it's the last one before the "cached base amount of 100", it's computed as 100 - 89.29 - 5.36 = 5.35 => 5.35 != 5.36 The behavior in the current task: a - Compute the base amount for the computation of the 2 x 6% incl taxes: 100 / 1.12 = 89.2857 b - Compute the tax amount for the 2 taxes: 89.2857 * 0.06 = 5.357142 ~= 5.36 c - Compute the base amount of the 2 x 6% incl taxes: 100 - 5.36 - 5.36 = 89.28. => Problem solved BELGIUM CASE: Suppose a base of 120.90 with 0.10 fixed tax (must be include_base_amount), then 21% incl tax. The behavior in master: a - Find the price-excluded base: 120.90 / 1.21 = 99.92 b - Compute the percentage tax: (99.92 + 0.10) * 0.21 = 21.0 => total tax is 21.0 + 0.10 = 21.10 but the base is 99.92 so the total of the invoice will be 121.02. The results is supposed to be the same as 2 lines: line1: 120.90 with 21% incl tax line2: 0.10 with 21% incl tax ...giving a price total of 121, a price subtotal of 100 and a tax amount of 21. The behavior in the current task: a - First ascending computation: Compute first the tax amounts of the fixed taxes: 0.10. b - Descending computation: Compute the base and tax amounts for the 21% tax: (120.90 + 0.10) / 1.21 = 100 then 100 * 0.21 = 21.0. c - Second ascending computation: Compute the base of 0.10 being 120.90. BRAZILIAN CASE: As said before, from 40.8, it's impossible to recompute the correct tax amounts. Suppose a base of 48.0 with 5% 3%, 0.65%, 9% and 15%, all division price included taxes. The behavior in master: a - Find the price-excluded base: 48.0 * (1 - 0.3265) ~= 32.33 b - Wrongly compute the tax amounts price-excluded for 5%, 3%, 0.65%, 9%: tax of 5%: 32.33 / 0.95 - 32.33 = 1.7 tax of 3%: 32.33 / 0.97 - 32.33 = 1.0 tax of 0.65%: 32.33 / 0.9935 - 32.33 = 0.21 tax of 9%: 32.33 / 0.91 - 32.33 = 3.2 c - the tax of 15% takes the remaining amount: 48.0 - 32.33 - 1.7 - 1.0 - 0.21 - 3.2 = 9.56 => Nothing works at all... The behavior in the current task: a - Descending computation: Compute the base and tax amounts for all taxes: 48.0 * 0.95 = 45.6; 48.0 - 45.6 = 2.4 48.0 * 0.97 = 46.56; 48.0 - 46.56 = 1.44 48.0 * 0.65 = 47.69; 48.0 - 47.69 = 0.31 48.0 * 0.91 = 43.68; 48.0 - 43.68 = 4.32 48.0 * 0.85 = 40.8; 48.0 - 40.8 = 7.2 REMAINING PROBLEMS Even the taxes computation will be fixed by this commit, some issues remain: -rounding issues on POS global discount/loyalties -bad computation of combo product with complex taxes -python taxes not working on the POS -perf of the tax details queries -round globally not working due to the accounting grouping key -... For all those reasons, this commit also adds new cool features: The taxes computation is splitted in 2 parts: a - prepare_taxes_computation that gives a formula to compute each tax independently. b - evaluate the taxes computation given by (a). This will help a lot to change the tax details query later by: a - pre-compile the taxes combinations first python-side. b - compute the tax details in SQL. The taxes computation is now completely reversible if you don't have any rounding in the process and thus, would help to solve the global discount/loyalties/product combo taxes computation. Also, the fiscal position mapping is now more accurate and is able to manage division taxes as well. The method are splitted in a way is will be quite easy to fix the round globally: Instead of: For each line, create a tax detail per repartition line Sum the tax details per repartition line and create tax lines => It gives a sum of rounded amounts that could be far from the expected amount: round(base * percentage). Do: For each line, create a tax detail per tax. Sum the tax details per tax and round them if round_per_line. Spread the amounts onto the repartition lines. => It will give exactly the tax amount expected by the user: round(base * percentage). opw: 3443703