Skip to content

Commit 9166e39

Browse files
committed
[FIX] account: Fix down payment/global discount in multi-currency + manual_tax_amounts
When using 'manual_tax_amounts', both 'raw_tax_amount' & 'tax_amount' get the forced tax amount. However, by doing that, we lost accuracy in the raw amount. With this commit, the manual_tax_amounts become a way to ensure some results in '_round_base_lines_tax_details'. So after this commit, the manual_tax_amounts won't be manage in '_get_tax_details' anymore. That way, we could also use the manual_tax_amounts for amounts in company's currency. For down payment/global discount, let's handle both currencies instead of only the foreign one. Also, the percentage is applied for each line to keep the whole thing as most accurate and close to the input percentage. If we don't do that, we could end up with a base of 99.99 and a tax amount of 15.01 for a tax of 15%. Since the percentage is applied in a more "global" way, this commits also partially revert odoo@3a26986 This approach is more complex and doesn't give always better results when using round_per_line either. Let's keep it simple and come back to a global approach. closes odoo#219930 Signed-off-by: Antoine Dupuis (andu) <andu@odoo.com>
1 parent 3a8522e commit 9166e39

9 files changed

Lines changed: 1397 additions & 788 deletions

File tree

addons/account/models/account_tax.py

Lines changed: 393 additions & 186 deletions
Large diffs are not rendered by default.

addons/account/static/src/helpers/account_tax.js

Lines changed: 474 additions & 258 deletions
Large diffs are not rendered by default.

addons/account/tests/test_taxes_downpayment.py

Lines changed: 214 additions & 164 deletions
Large diffs are not rendered by default.

addons/account/tests/test_taxes_global_discount.py

Lines changed: 157 additions & 157 deletions
Large diffs are not rendered by default.

addons/l10n_it_edi/tests/export_xmls/test_export_invoice_with_two_downpayments.xml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,20 +83,21 @@
8383
<NumeroLinea>2</NumeroLinea>
8484
<Descrizione>Down Payment (ref: INV/2025/00001 on 02/03/2025), INV/2025/00001</Descrizione>
8585
<Quantita>1.00</Quantita>
86-
<PrezzoUnitario>-40.98000000</PrezzoUnitario>
87-
<PrezzoTotale>-40.98000000</PrezzoTotale>
86+
<PrezzoUnitario>-40.98360656</PrezzoUnitario>
87+
<PrezzoTotale>-40.98360656</PrezzoTotale>
8888
<AliquotaIVA>22.00</AliquotaIVA>
8989
</DettaglioLinee>
9090
<DettaglioLinee>
9191
<NumeroLinea>3</NumeroLinea>
9292
<Descrizione>Down Payment (ref: INV/2025/00002 on 02/03/2025), INV/2025/00002</Descrizione>
9393
<Quantita>1.00</Quantita>
94-
<PrezzoUnitario>-81.97000000</PrezzoUnitario>
95-
<PrezzoTotale>-81.97000000</PrezzoTotale>
94+
<PrezzoUnitario>-81.96721311</PrezzoUnitario>
95+
<PrezzoTotale>-81.96721311</PrezzoTotale>
9696
<AliquotaIVA>22.00</AliquotaIVA>
9797
</DettaglioLinee>
9898
<DatiRiepilogo>
9999
<AliquotaIVA>22.00</AliquotaIVA>
100+
<Arrotondamento>0.00081967</Arrotondamento>
100101
<ImponibileImporto>77.05</ImponibileImporto>
101102
<Imposta>16.95</Imposta>
102103
<EsigibilitaIVA>I</EsigibilitaIVA>

addons/point_of_sale/static/src/app/models/pos_order_line.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,7 @@ export class PosOrderline extends Base {
363363
discount: discount,
364364
tax_ids: this.tax_ids,
365365
product_id: product,
366+
rate: 1.0,
366367
...customValues,
367368
};
368369
if (order.fiscal_position_id) {

addons/pos_discount/static/tests/tours/test_taxes_global_discount.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,15 @@ registry
7474
]),
7575
...addDiscount("7"),
7676
ProductScreen.checkTotalAmount("34.08"),
77-
ProductScreen.checkTaxAmount("4.50"),
77+
ProductScreen.checkTaxAmount("4.53"),
7878
...payAndInvoice("34.08"),
7979
...addDocument([
8080
{ product: "product_1_1", quantity: "1" },
8181
{ product: "product_1_2", quantity: "1" },
8282
]),
8383
...addDiscount("18"),
8484
ProductScreen.checkTotalAmount("30.04"),
85-
ProductScreen.checkTaxAmount("3.98"),
85+
ProductScreen.checkTaxAmount("3.99"),
8686
...payAndInvoice("30.04"),
8787
].flat(),
8888
});
@@ -144,15 +144,15 @@ registry
144144
]),
145145
...addDiscount("7"),
146146
ProductScreen.checkTotalAmount("34.08"),
147-
ProductScreen.checkTaxAmount("4.50"),
147+
ProductScreen.checkTaxAmount("4.53"),
148148
...payAndInvoice("34.08"),
149149
...addDocument([
150150
{ product: "product_3_1", quantity: "1" },
151151
{ product: "product_3_2", quantity: "1" },
152152
]),
153153
...addDiscount("18"),
154154
ProductScreen.checkTotalAmount("30.04"),
155-
ProductScreen.checkTaxAmount("3.98"),
155+
ProductScreen.checkTaxAmount("3.99"),
156156
...payAndInvoice("30.04"),
157157
].flat(),
158158
});

addons/pos_sale/static/tests/tours/test_taxes_downpayment.js

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -81,19 +81,19 @@ registry
8181
...payAndInvoice("0.73"),
8282
...addDownPayment("7", 3, "percent"),
8383
ProductScreen.checkTotalAmount("2.56"),
84-
ProductScreen.checkTaxAmount("0.36"),
84+
ProductScreen.checkTaxAmount("0.33"),
8585
...payAndInvoice("2.56"),
8686
...addDownPayment("2.56", 4, "fixed"),
8787
ProductScreen.checkTotalAmount("2.56"),
88-
ProductScreen.checkTaxAmount("0.36"),
88+
ProductScreen.checkTaxAmount("0.33"),
8989
...payAndInvoice("2.56"),
9090
...addDownPayment("18", 5, "percent"),
9191
ProductScreen.checkTotalAmount("6.60"),
92-
ProductScreen.checkTaxAmount("0.88"),
92+
ProductScreen.checkTaxAmount("0.87"),
9393
...payAndInvoice("6.60"),
9494
...addDownPayment("6.60", 6, "fixed"),
9595
ProductScreen.checkTotalAmount("6.60"),
96-
ProductScreen.checkTaxAmount("0.88"),
96+
ProductScreen.checkTaxAmount("0.87"),
9797
...payAndInvoice("6.60"),
9898
].flat(),
9999
});
@@ -151,19 +151,19 @@ registry
151151
...payAndInvoice("0.73"),
152152
...addDownPayment("7", 3, "percent"),
153153
ProductScreen.checkTotalAmount("2.56"),
154-
ProductScreen.checkTaxAmount("0.36"),
154+
ProductScreen.checkTaxAmount("0.33"),
155155
...payAndInvoice("2.56"),
156156
...addDownPayment("2.56", 4, "fixed"),
157157
ProductScreen.checkTotalAmount("2.56"),
158-
ProductScreen.checkTaxAmount("0.36"),
158+
ProductScreen.checkTaxAmount("0.33"),
159159
...payAndInvoice("2.56"),
160160
...addDownPayment("18", 5, "percent"),
161161
ProductScreen.checkTotalAmount("6.60"),
162-
ProductScreen.checkTaxAmount("0.88"),
162+
ProductScreen.checkTaxAmount("0.87"),
163163
...payAndInvoice("6.60"),
164164
...addDownPayment("6.60", 6, "fixed"),
165165
ProductScreen.checkTotalAmount("6.60"),
166-
ProductScreen.checkTaxAmount("0.88"),
166+
ProductScreen.checkTaxAmount("0.87"),
167167
...payAndInvoice("6.60"),
168168
].flat(),
169169
});
@@ -190,7 +190,7 @@ registry
190190
...payAndInvoice("2.57"),
191191
...addDownPayment("2.57", 4, "fixed"),
192192
ProductScreen.checkTotalAmount("2.57"),
193-
ProductScreen.checkTaxAmount("0.33"),
193+
ProductScreen.checkTaxAmount("0.34"),
194194
...payAndInvoice("2.57"),
195195
...addDownPayment("18", 5, "percent"),
196196
ProductScreen.checkTotalAmount("6.60"),
@@ -213,7 +213,7 @@ registry
213213

214214
...addDownPayment("2", 1, "percent"),
215215
ProductScreen.checkTotalAmount("1.92"),
216-
ProductScreen.checkTaxAmount("0.64"),
216+
ProductScreen.checkTaxAmount("0.63"),
217217
...payAndInvoice("1.92"),
218218
].flat(),
219219
});
@@ -243,7 +243,7 @@ registry
243243

244244
...addDownPayment("2", 1, "percent"),
245245
ProductScreen.checkTotalAmount("1.92"),
246-
ProductScreen.checkTaxAmount("0.64"),
246+
ProductScreen.checkTaxAmount("0.63"),
247247
...payAndInvoice("1.92"),
248248
].flat(),
249249
});
@@ -273,7 +273,7 @@ registry
273273

274274
...addDownPayment("2", 1, "percent"),
275275
ProductScreen.checkTotalAmount("0.86"),
276-
ProductScreen.checkTaxAmount("0.14"),
276+
ProductScreen.checkTaxAmount("0.15"),
277277
...payAndInvoice("0.86"),
278278
].flat(),
279279
});
@@ -303,7 +303,7 @@ registry
303303

304304
...addDownPayment("2", 1, "percent"),
305305
ProductScreen.checkTotalAmount("0.86"),
306-
ProductScreen.checkTaxAmount("0.14"),
306+
ProductScreen.checkTaxAmount("0.15"),
307307
...payAndInvoice("0.86"),
308308
].flat(),
309309
});

addons/sale/tests/test_taxes_downpayment.py

Lines changed: 136 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -593,16 +593,21 @@ def test_down_payment_invoice_then_refunded_then_invoiced_again(self):
593593
'amount_total': so.amount_total - dp_invoice_2.amount_total,
594594
}])
595595

596+
@freeze_time('2018-01-01')
596597
def test_down_payment_100_first_then_0_final_invoice_round_per_line(self):
597598
self.env.company.tax_calculation_rounding_method = 'round_per_line'
598599
product = self.company_data['product_order_cost']
599600
tax_23 = self.percent_tax(23.0)
601+
other_currency = self.setup_other_currency('EUR', rates=[('2017-01-01', 1.2834)])
602+
self.foreign_currency_pricelist.currency_id = other_currency
600603

601604
so = self.env['sale.order'].create({
602605
'partner_id': self.partner_a.id,
606+
'currency_id': other_currency.id,
607+
'pricelist_id': self.foreign_currency_pricelist.id,
603608
'order_line': [
604609
Command.create({
605-
'name': 'line_1',
610+
'name': 'line',
606611
'product_id': product.id,
607612
'price_unit': price_unit,
608613
'product_uom_qty': quantity,
@@ -645,6 +650,37 @@ def test_down_payment_100_first_then_0_final_invoice_round_per_line(self):
645650
'amount_tax': 275.27,
646651
'amount_total': 1472.14,
647652
}])
653+
self.assert_invoice_tax_totals_summary(dp_invoice, {
654+
'same_tax_base': True,
655+
'currency_id': other_currency.id,
656+
'company_currency_id': self.env.company.currency_id.id,
657+
'base_amount_currency': 1196.87,
658+
'base_amount': 932.57,
659+
'tax_amount_currency': 275.27,
660+
'tax_amount': 214.49,
661+
'total_amount_currency': 1472.14,
662+
'total_amount': 1147.06,
663+
'subtotals': [
664+
{
665+
'name': "Untaxed Amount",
666+
'base_amount_currency': 1196.87,
667+
'base_amount': 932.57,
668+
'tax_amount_currency': 275.27,
669+
'tax_amount': 214.49,
670+
'tax_groups': [
671+
{
672+
'id': self.tax_groups[0].id,
673+
'base_amount_currency': 1196.87,
674+
'base_amount': 932.57,
675+
'tax_amount_currency': 275.27,
676+
'tax_amount': 214.49,
677+
'display_base_amount_currency': 1196.87,
678+
'display_base_amount': 932.57,
679+
},
680+
],
681+
},
682+
],
683+
})
648684

649685
# Create the final invoice.
650686
wizard = (
@@ -659,17 +695,53 @@ def test_down_payment_100_first_then_0_final_invoice_round_per_line(self):
659695
'amount_tax': 0.0,
660696
'amount_total': 0.0,
661697
}])
698+
self.assert_invoice_tax_totals_summary(final_invoice, {
699+
'same_tax_base': True,
700+
'currency_id': other_currency.id,
701+
'company_currency_id': self.env.company.currency_id.id,
702+
'base_amount_currency': 0.0,
703+
'base_amount': 0.0,
704+
'tax_amount_currency': 0.0,
705+
'tax_amount': 0.0,
706+
'total_amount_currency': 0.0,
707+
'total_amount': 0.0,
708+
'subtotals': [
709+
{
710+
'name': "Untaxed Amount",
711+
'base_amount_currency': 0.0,
712+
'base_amount': 0.0,
713+
'tax_amount_currency': 0.0,
714+
'tax_amount': 0.0,
715+
'tax_groups': [
716+
{
717+
'id': self.tax_groups[0].id,
718+
'base_amount_currency': 0.0,
719+
'base_amount': 0.0,
720+
'tax_amount_currency': 0.0,
721+
'tax_amount': 0.0,
722+
'display_base_amount_currency': 0.0,
723+
'display_base_amount': 0.0,
724+
},
725+
],
726+
},
727+
],
728+
})
662729

730+
@freeze_time('2018-01-01')
663731
def test_down_payment_100_first_then_0_final_invoice_round_globally(self):
664732
self.env.company.tax_calculation_rounding_method = 'round_globally'
665733
product = self.company_data['product_order_cost']
666734
tax_23 = self.percent_tax(23.0)
735+
other_currency = self.setup_other_currency('EUR', rates=[('2017-01-01', 1.2834)])
736+
self.foreign_currency_pricelist.currency_id = other_currency
667737

668738
so = self.env['sale.order'].create({
669739
'partner_id': self.partner_a.id,
740+
'currency_id': other_currency.id,
741+
'pricelist_id': self.foreign_currency_pricelist.id,
670742
'order_line': [
671743
Command.create({
672-
'name': 'line_1',
744+
'name': 'line',
673745
'product_id': product.id,
674746
'price_unit': price_unit,
675747
'product_uom_qty': quantity,
@@ -712,6 +784,37 @@ def test_down_payment_100_first_then_0_final_invoice_round_globally(self):
712784
'amount_tax': 275.28,
713785
'amount_total': 1472.17,
714786
}])
787+
self.assert_invoice_tax_totals_summary(dp_invoice, {
788+
'same_tax_base': True,
789+
'currency_id': other_currency.id,
790+
'company_currency_id': self.env.company.currency_id.id,
791+
'base_amount_currency': 1196.89,
792+
'base_amount': 932.59,
793+
'tax_amount_currency': 275.28,
794+
'tax_amount': 214.5,
795+
'total_amount_currency': 1472.17,
796+
'total_amount': 1147.09,
797+
'subtotals': [
798+
{
799+
'name': "Untaxed Amount",
800+
'base_amount_currency': 1196.89,
801+
'base_amount': 932.59,
802+
'tax_amount_currency': 275.28,
803+
'tax_amount': 214.5,
804+
'tax_groups': [
805+
{
806+
'id': self.tax_groups[0].id,
807+
'base_amount_currency': 1196.89,
808+
'base_amount': 932.59,
809+
'tax_amount_currency': 275.28,
810+
'tax_amount': 214.5,
811+
'display_base_amount_currency': 1196.89,
812+
'display_base_amount': 932.59,
813+
},
814+
],
815+
},
816+
],
817+
})
715818

716819
# Create the final invoice.
717820
wizard = (
@@ -726,6 +829,37 @@ def test_down_payment_100_first_then_0_final_invoice_round_globally(self):
726829
'amount_tax': 0.0,
727830
'amount_total': 0.0,
728831
}])
832+
self.assert_invoice_tax_totals_summary(final_invoice, {
833+
'same_tax_base': False, # <- This is a bug because we end up with 0.0 & -0.0 as base. Remove this comment when fixed.
834+
'currency_id': other_currency.id,
835+
'company_currency_id': self.env.company.currency_id.id,
836+
'base_amount_currency': 0.0,
837+
'base_amount': 0.0,
838+
'tax_amount_currency': 0.0,
839+
'tax_amount': 0.0,
840+
'total_amount_currency': 0.0,
841+
'total_amount': 0.0,
842+
'subtotals': [
843+
{
844+
'name': "Untaxed Amount",
845+
'base_amount_currency': 0.0,
846+
'base_amount': 0.0,
847+
'tax_amount_currency': 0.0,
848+
'tax_amount': 0.0,
849+
'tax_groups': [
850+
{
851+
'id': self.tax_groups[0].id,
852+
'base_amount_currency': 0.0,
853+
'base_amount': 0.0,
854+
'tax_amount_currency': 0.0,
855+
'tax_amount': 0.0,
856+
'display_base_amount_currency': 0.0,
857+
'display_base_amount': 0.0,
858+
},
859+
],
860+
},
861+
],
862+
})
729863

730864
def test_down_payment_analytic_distribution_aggregation(self):
731865
tax_account = self.company_data['default_account_tax_sale']

0 commit comments

Comments
 (0)