details: https://code.tryton.org/tryton/commit/6cb75123ee20
branch: default
user: Cédric Krier <[email protected]>
date: Wed Jul 15 18:07:22 2026 +0200
description:
Format numeric values in XML templates using fixed-point notation
Closes #14948
diffstat:
modules/account_payment_sepa/template/pain.001.001.03.xml | 6 +-
modules/account_payment_sepa/template/pain.001.001.05.xml | 6 +-
modules/account_payment_sepa/template/pain.001.003.03.xml | 6 +-
modules/account_payment_sepa/template/pain.008.001.02.xml | 6 +-
modules/account_payment_sepa/template/pain.008.001.04.xml | 6 +-
modules/account_payment_sepa/template/pain.008.003.02.xml | 6 +-
modules/account_payment_sepa_cfonb/template/pain.001.001.03-cfonb.xml | 6 +-
modules/account_payment_sepa_cfonb/template/pain.008.001.02-cfonb.xml | 6 +-
modules/edocument_ubl/edocument.py | 2 +-
modules/edocument_ubl/template/2/CreditNote.xml | 26
+++++-----
modules/edocument_ubl/template/2/Invoice.xml | 26
+++++-----
modules/edocument_uncefact/template/16B-CII/CrossIndustryInvoice.xml | 20
+++---
12 files changed, 61 insertions(+), 61 deletions(-)
diffs (446 lines):
diff -r 4b3c250361bc -r 6cb75123ee20
modules/account_payment_sepa/template/pain.001.001.03.xml
--- a/modules/account_payment_sepa/template/pain.001.001.03.xml Tue Jul 14
17:07:07 2026 +0200
+++ b/modules/account_payment_sepa/template/pain.001.001.03.xml Wed Jul 15
18:07:22 2026 +0200
@@ -32,7 +32,7 @@
<CreDtTm>${datetime.datetime.now().replace(microsecond=0).isoformat()}</CreDtTm>
<!-- Authstn -->
<NbOfTxs>${sum(len(payments) for _, payments in
group.sepa_payments)}</NbOfTxs>
- <CtrlSum>${sum(p.amount for p in group.payments)}</CtrlSum>
+ <CtrlSum>${format(sum(p.amount for p in
group.payments).normalize(), 'f')}</CtrlSum>
<!-- PmtTpInf -->
<!-- ReqdColltnDt -->
<InitgPty>
@@ -45,7 +45,7 @@
<PmtMtd>TRF</PmtMtd>
<BtchBookg>${'true' if group.journal.sepa_batch_booking else
'false'}</BtchBookg>
<NbOfTxs>${len(payments)}</NbOfTxs>
- <CtrlSum>${sum(p.amount for p in payments)}</CtrlSum>
+ <CtrlSum>${format(sum(p.amount for p in payments).normalize(),
'f')}</CtrlSum>
<PmtTpInf>
<!-- InstrPrty -->
<SvcLvl>
@@ -77,7 +77,7 @@
</PmtId>
<!-- PmtTpInf --> <!-- EPC only at payment information level
-->
<Amt>
- <InstdAmt py:attrs="{'Ccy':
payment.currency.code}">${payment.amount}</InstdAmt>
+ <InstdAmt py:attrs="{'Ccy':
payment.currency.code}">${format(payment.amount.normalize(), 'f')}</InstdAmt>
<!-- EqvtAmt -->
</Amt>
<!-- XchgRateInf -->
diff -r 4b3c250361bc -r 6cb75123ee20
modules/account_payment_sepa/template/pain.001.001.05.xml
--- a/modules/account_payment_sepa/template/pain.001.001.05.xml Tue Jul 14
17:07:07 2026 +0200
+++ b/modules/account_payment_sepa/template/pain.001.001.05.xml Wed Jul 15
18:07:22 2026 +0200
@@ -13,7 +13,7 @@
<CreDtTm>${datetime.datetime.now().replace(microsecond=0).isoformat()}</CreDtTm>
<!-- Authstn -->
<NbOfTxs>${sum(len(payments) for _, payments in
group.sepa_payments)}</NbOfTxs>
- <CtrlSum>${sum(p.amount for p in group.payments)}</CtrlSum>
+ <CtrlSum>${format(sum(p.amount for p in
group.payments).normalize(), 'f')}</CtrlSum>
<!-- PmtTpInf -->
<!-- ReqdColltnDt -->
<InitgPty>
@@ -26,7 +26,7 @@
<PmtMtd>TRF</PmtMtd>
<BtchBookg>${'true' if group.journal.sepa_batch_booking else
'false'}</BtchBookg>
<NbOfTxs>${len(payments)}</NbOfTxs>
- <CtrlSum>${sum(p.amount for p in payments)}</CtrlSum>
+ <CtrlSum>${format(sum(p.amount for p in payments).normalize(),
'f')}</CtrlSum>
<PmtTpInf>
<!-- InstrPrty -->
<SvcLvl>
@@ -59,7 +59,7 @@
</PmtId>
<!-- PmtTpInf --> <!-- EPC only at payment information level
-->
<Amt>
- <InstdAmt py:attrs="{'Ccy':
payment.currency.code}">${payment.amount}</InstdAmt>
+ <InstdAmt py:attrs="{'Ccy':
payment.currency.code}">${format(payment.amount.normalize(), 'f')}</InstdAmt>
<!-- EqvtAmt -->
</Amt>
<!-- XchgRateInf -->
diff -r 4b3c250361bc -r 6cb75123ee20
modules/account_payment_sepa/template/pain.001.003.03.xml
--- a/modules/account_payment_sepa/template/pain.001.003.03.xml Tue Jul 14
17:07:07 2026 +0200
+++ b/modules/account_payment_sepa/template/pain.001.003.03.xml Wed Jul 15
18:07:22 2026 +0200
@@ -15,7 +15,7 @@
<MsgId>${group.sepa_message_id[:35]}</MsgId>
<CreDtTm>${datetime.datetime.now().replace(microsecond=0).isoformat()}</CreDtTm>
<NbOfTxs>${sum(len(payments) for _, payments in
group.sepa_payments)}</NbOfTxs>
- <CtrlSum>${sum(p.amount for p in group.payments)}</CtrlSum>
+ <CtrlSum>${format(sum(p.amount for p in
group.payments).normalize(), 'f')}</CtrlSum>
<InitgPty>
${PartyIdentification(group.sepa_initiating_party,
id=group.journal.sepa_payable_initiator_id, with_address=False)}
</InitgPty>
@@ -25,7 +25,7 @@
<PmtMtd>TRF</PmtMtd>
<BtchBookg>${'true' if group.journal.sepa_batch_booking else
'false'}</BtchBookg>
<NbOfTxs>${len(payments)}</NbOfTxs>
- <CtrlSum>${sum(p.amount for p in payments)}</CtrlSum>
+ <CtrlSum>${format(sum(p.amount for p in payments).normalize(),
'f')}</CtrlSum>
<PmtTpInf>
<!-- InstrPrty -->
<SvcLvl>
@@ -52,7 +52,7 @@
</PmtId>
<!-- PmtTpInf --> <!-- EPC only at payment information level
-->
<Amt>
- <InstdAmt py:attrs="{'Ccy':
payment.currency.code}">${payment.amount}</InstdAmt>
+ <InstdAmt py:attrs="{'Ccy':
payment.currency.code}">${format(payment.amount.normalize(), 'f')}</InstdAmt>
</Amt>
<!-- ChrgBr --> <!-- EPC only at payment information level -->
<!-- UltmtDbtr -->
diff -r 4b3c250361bc -r 6cb75123ee20
modules/account_payment_sepa/template/pain.008.001.02.xml
--- a/modules/account_payment_sepa/template/pain.008.001.02.xml Tue Jul 14
17:07:07 2026 +0200
+++ b/modules/account_payment_sepa/template/pain.008.001.02.xml Wed Jul 15
18:07:22 2026 +0200
@@ -32,7 +32,7 @@
<CreDtTm>${datetime.datetime.now().replace(microsecond=0).isoformat()}</CreDtTm>
<!-- Authstn -->
<NbOfTxs>${sum(len(payments) for _, payments in
group.sepa_payments)}</NbOfTxs>
- <CtrlSum>${sum(p.amount for p in group.payments)}</CtrlSum>
+ <CtrlSum>${format(sum(p.amount for p in
group.payments).normalize(), 'f')}</CtrlSum>
<!-- PmtTpInf -->
<!-- ReqdColltnDt -->
<InitgPty>
@@ -45,7 +45,7 @@
<PmtMtd>DD</PmtMtd>
<BtchBookg>${'true' if group.journal.sepa_batch_booking else
'false'}</BtchBookg>
<NbOfTxs>${len(payments)}</NbOfTxs>
- <CtrlSum>${sum(p.amount for p in payments)}</CtrlSum>
+ <CtrlSum>${format(sum(p.amount for p in payments).normalize(),
'f')}</CtrlSum>
<PmtTpInf>
<!-- InstrPrty -->
<SvcLvl>
@@ -83,7 +83,7 @@
<EndToEndId>${payment.sepa_end_to_end_id}</EndToEndId>
</PmtId>
<!-- PmtTpInf -->
- <InstdAmt py:attrs="{'Ccy':
payment.currency.code}">${payment.amount}</InstdAmt>
+ <InstdAmt py:attrs="{'Ccy':
payment.currency.code}">${format(payment.amount.normalize(), 'f')}</InstdAmt>
<!-- ChrgBr --> <!-- EPC only at payment information level -->
<DrctDbtTx>
<MndtRltdInf py:with="mandate = payment.sepa_mandate">
diff -r 4b3c250361bc -r 6cb75123ee20
modules/account_payment_sepa/template/pain.008.001.04.xml
--- a/modules/account_payment_sepa/template/pain.008.001.04.xml Tue Jul 14
17:07:07 2026 +0200
+++ b/modules/account_payment_sepa/template/pain.008.001.04.xml Wed Jul 15
18:07:22 2026 +0200
@@ -13,7 +13,7 @@
<CreDtTm>${datetime.datetime.now().replace(microsecond=0).isoformat()}</CreDtTm>
<!-- Authstn -->
<NbOfTxs>${len(group.payments)}</NbOfTxs>
- <CtrlSum>${sum(p.amount for p in group.payments)}</CtrlSum>
+ <CtrlSum>${format(sum(p.amount for p in
group.payments).normalize(), 'f')}</CtrlSum>
<!-- PmtTpInf -->
<!-- ReqdColltnDt -->
<InitgPty>
@@ -26,7 +26,7 @@
<PmtMtd>DD</PmtMtd>
<BtchBookg>${'true' if group.journal.sepa_batch_booking else
'false'}</BtchBookg>
<NbOfTxs>${len(payments)}</NbOfTxs>
- <CtrlSum>${sum(p.amount for p in payments)}</CtrlSum>
+ <CtrlSum>${format(sum(p.amount for p in payments).normalize(),
'f')}</CtrlSum>
<PmtTpInf>
<!-- InstrPrty -->
<SvcLvl>
@@ -64,7 +64,7 @@
<EndToEndId>${payment.sepa_end_to_end_id}</EndToEndId>
</PmtId>
<!-- PmtTpInf -->
- <InstdAmt py:attrs="{'Ccy':
payment.currency.code}">${payment.amount}</InstdAmt>
+ <InstdAmt py:attrs="{'Ccy':
payment.currency.code}">${format(payment.amount.normalize(), 'f')}</InstdAmt>
<!-- ChrgBr --> <!-- EPC only at payment information level -->
<DrctDbtTx>
<MndtRltdInf py:with="mandate = payment.sepa_mandate">
diff -r 4b3c250361bc -r 6cb75123ee20
modules/account_payment_sepa/template/pain.008.003.02.xml
--- a/modules/account_payment_sepa/template/pain.008.003.02.xml Tue Jul 14
17:07:07 2026 +0200
+++ b/modules/account_payment_sepa/template/pain.008.003.02.xml Wed Jul 15
18:07:22 2026 +0200
@@ -15,7 +15,7 @@
<MsgId>${group.sepa_message_id[:35]}</MsgId>
<CreDtTm>${datetime.datetime.now().replace(microsecond=0).isoformat()}</CreDtTm>
<NbOfTxs>${sum(len(payments) for _, payments in
group.sepa_payments)}</NbOfTxs>
- <CtrlSum>${sum(p.amount for p in group.payments)}</CtrlSum>
+ <CtrlSum>${format(sum(p.amount for p in
group.payments).normalize(), 'f')}</CtrlSum>
<InitgPty>
${PartyIdentification(group.sepa_initiating_party,
id=group.journal.sepa_receivable_initiator_id, with_address=False)}
</InitgPty>
@@ -25,7 +25,7 @@
<PmtMtd>DD</PmtMtd>
<BtchBookg>${'true' if group.journal.sepa_batch_booking else
'false'}</BtchBookg>
<NbOfTxs>${len(payments)}</NbOfTxs>
- <CtrlSum>${sum(p.amount for p in payments)}</CtrlSum>
+ <CtrlSum>${format(sum(p.amount for p in payments).normalize(),
'f')}</CtrlSum>
<PmtTpInf>
<SvcLvl>
<Cd>SEPA</Cd>
@@ -56,7 +56,7 @@
<InstrId>${payment.sepa_instruction_id}</InstrId>
<EndToEndId>${payment.sepa_end_to_end_id}</EndToEndId>
</PmtId>
- <InstdAmt py:attrs="{'Ccy':
payment.currency.code}">${payment.amount}</InstdAmt>
+ <InstdAmt py:attrs="{'Ccy':
payment.currency.code}">${format(payment.amount.normalize(), 'f')}</InstdAmt>
<!-- ChrgBr --> <!-- EPC only at payment information level -->
<DrctDbtTx>
<MndtRltdInf py:with="mandate = payment.sepa_mandate">
diff -r 4b3c250361bc -r 6cb75123ee20
modules/account_payment_sepa_cfonb/template/pain.001.001.03-cfonb.xml
--- a/modules/account_payment_sepa_cfonb/template/pain.001.001.03-cfonb.xml
Tue Jul 14 17:07:07 2026 +0200
+++ b/modules/account_payment_sepa_cfonb/template/pain.001.001.03-cfonb.xml
Wed Jul 15 18:07:22 2026 +0200
@@ -26,7 +26,7 @@
<MsgId>${group.sepa_message_id[:35]}</MsgId>
<CreDtTm>${datetime.datetime.now().replace(microsecond=0).isoformat()}</CreDtTm>
<NbOfTxs>${sum(len(payments) for _, payments in
group.sepa_payments)}</NbOfTxs>
- <CtrlSum>${sum(p.amount for p in group.payments)}</CtrlSum>
+ <CtrlSum>${format(sum(p.amount for p in
group.payments).normalize(), 'f')}</CtrlSum>
<InitgPty>
${PartyIdentification(group.sepa_initiating_party)}
</InitgPty>
@@ -36,7 +36,7 @@
<PmtMtd>TRF</PmtMtd>
<BtchBookg>${'true' if group.journal.sepa_batch_booking else
'false'}</BtchBookg>
<NbOfTxs>${len(payments)}</NbOfTxs>
- <CtrlSum>${sum(p.amount for p in payments)}</CtrlSum>
+ <CtrlSum>${format(sum(p.amount for p in payments).normalize(),
'f')}</CtrlSum>
<PmtTpInf>
<!-- InstrPrty -->
<SvcLvl>
@@ -62,7 +62,7 @@
<EndToEndId>${payment.sepa_end_to_end_id}</EndToEndId>
</PmtId>
<Amt>
- <InstdAmt py:attrs="{'Ccy':
payment.currency.code}">${payment.amount}</InstdAmt>
+ <InstdAmt py:attrs="{'Ccy':
payment.currency.code}">${format(payment.amount.normalize(), 'f')}</InstdAmt>
<!-- EqvtAmt -->
</Amt>
<!-- ChrgBr --> <!-- EPC only at payment information level -->
diff -r 4b3c250361bc -r 6cb75123ee20
modules/account_payment_sepa_cfonb/template/pain.008.001.02-cfonb.xml
--- a/modules/account_payment_sepa_cfonb/template/pain.008.001.02-cfonb.xml
Tue Jul 14 17:07:07 2026 +0200
+++ b/modules/account_payment_sepa_cfonb/template/pain.008.001.02-cfonb.xml
Wed Jul 15 18:07:22 2026 +0200
@@ -32,7 +32,7 @@
<MsgId>${group.sepa_message_id[:35]}</MsgId>
<CreDtTm>${datetime.datetime.now().replace(microsecond=0).isoformat()}</CreDtTm>
<NbOfTxs>${sum(len(payments) for _, payments in
group.sepa_payments)}</NbOfTxs>
- <CtrlSum>${sum(p.amount for p in group.payments)}</CtrlSum>
+ <CtrlSum>${format(sum(p.amount for p in
group.payments).normalize(), 'f')}</CtrlSum>
<InitgPty>
${PartyIdentification(group.sepa_initiating_party)}
</InitgPty>
@@ -42,7 +42,7 @@
<PmtMtd>DD</PmtMtd>
<BtchBookg>${'true' if group.journal.sepa_batch_booking else
'false'}</BtchBookg>
<NbOfTxs>${len(payments)}</NbOfTxs>
- <CtrlSum>${sum(p.amount for p in payments)}</CtrlSum>
+ <CtrlSum>${format(sum(p.amount for p in payments).normalize(),
'f')}</CtrlSum>
<PmtTpInf>
<SvcLvl>
<Cd>SEPA</Cd>
@@ -73,7 +73,7 @@
<InstrId>${payment.sepa_instruction_id}</InstrId>
<EndToEndId>${payment.sepa_end_to_end_id}</EndToEndId>
</PmtId>
- <InstdAmt py:attrs="{'Ccy':
payment.currency.code}">${payment.amount}</InstdAmt>
+ <InstdAmt py:attrs="{'Ccy':
payment.currency.code}">${format(payment.amount.normalize(), 'f')}</InstdAmt>
<DrctDbtTx>
<MndtRltdInf py:with="mandate = payment.sepa_mandate">
<MndtId>${mandate.identification}</MndtId>
diff -r 4b3c250361bc -r 6cb75123ee20 modules/edocument_ubl/edocument.py
--- a/modules/edocument_ubl/edocument.py Tue Jul 14 17:07:07 2026 +0200
+++ b/modules/edocument_ubl/edocument.py Wed Jul 15 18:07:22 2026 +0200
@@ -279,7 +279,7 @@
elif self.invoice.currency == self.invoice.company.currency:
return line.debit - line.credit
else:
- return 0
+ return Decimal(0)
return sum(map(balance, self.invoice.lines_to_pay))
@classmethod
diff -r 4b3c250361bc -r 6cb75123ee20
modules/edocument_ubl/template/2/CreditNote.xml
--- a/modules/edocument_ubl/template/2/CreditNote.xml Tue Jul 14 17:07:07
2026 +0200
+++ b/modules/edocument_ubl/template/2/CreditNote.xml Wed Jul 15 18:07:22
2026 +0200
@@ -90,7 +90,7 @@
<py:otherwise>
<cac:PaymentTerms py:for="line in this.invoice.lines_to_pay">
<cbc:Note py:if="this.invoice.payment_term and
this.invoice.payment_term.description">${this.invoice.payment_term.description}</cbc:Note>
- <cbc:Amount py:attrs="{'currencyID':
this.invoice.currency.code}">${line.amount}</cbc:Amount>
+ <cbc:Amount py:attrs="{'currencyID':
this.invoice.currency.code}">${format(line.amount.normalize(),
'f')}</cbc:Amount>
<cbc:PaymentDueDate>${line.maturity_date}</cbc:PaymentDueDate>
</cac:PaymentTerms>
</py:otherwise>
@@ -101,16 +101,16 @@
<cbc:AllowanceChargeReasonCode
py:if="reason_code">${reason_code}</cbc:AllowanceChargeReasonCode>
</py:with>
<cbc:AllowanceChargeReason>${allowance_charge.product.name}</cbc:AllowanceChargeReason>
- <cbc:Amount py:attrs="{'currencyID':
this.invoice.currency.code}">${abs(allowance_charge.amount)}</cbc:Amount>
+ <cbc:Amount py:attrs="{'currencyID':
this.invoice.currency.code}">${format(abs(allowance_charge.amount).normalize(),
'f')}</cbc:Amount>
<cac:TaxCategory py:for="tax_line in allowance_charge.invoice_taxes">
${TaxCategory(tax_line.tax)}
</cac:TaxCategory>
</cac:AllowanceCharge>
<cac:TaxTotal py:for="group, lines, amount in this.taxes">
- <cbc:TaxAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${-amount}</cbc:TaxAmount>
+ <cbc:TaxAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format((-amount).normalize(),
'f')}</cbc:TaxAmount>
<cac:TaxSubtotal py:for="line in lines">
- <cbc:TaxableAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${-line.base}</cbc:TaxableAmount>
- <cbc:TaxAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${-line.amount}</cbc:TaxAmount>
+ <cbc:TaxableAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format((-line.base).normalize(),
'f')}</cbc:TaxableAmount>
+ <cbc:TaxAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format((-line.amount).normalize(),
'f')}</cbc:TaxAmount>
<cbc:Percent py:if="line.tax.type == 'percentage' and not
(specification or '').startswith('peppol')">${format((line.tax.rate *
100).normalize(), 'f')}</cbc:Percent>
<cac:TaxCategory>
${TaxCategory(line.tax)}
@@ -118,19 +118,19 @@
</cac:TaxSubtotal>
</cac:TaxTotal>
<cac:LegalMonetaryTotal>
- <cbc:LineExtensionAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${-this.invoice.untaxed_amount}</cbc:LineExtensionAmount>
- <cbc:TaxExclusiveAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${-this.invoice.untaxed_amount}</cbc:TaxExclusiveAmount>
- <cbc:TaxInclusiveAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${-(this.invoice.untaxed_amount +
this.invoice.tax_amount)}</cbc:TaxInclusiveAmount>
+ <cbc:LineExtensionAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format((-this.invoice.untaxed_amount).normalize(),
'f')}</cbc:LineExtensionAmount>
+ <cbc:TaxExclusiveAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format((-this.invoice.untaxed_amount).normalize(),
'f')}</cbc:TaxExclusiveAmount>
+ <cbc:TaxInclusiveAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format((-(this.invoice.untaxed_amount +
this.invoice.tax_amount)).normalize(), 'f')}</cbc:TaxInclusiveAmount>
<py:if test="this.invoice.total_amount != (this.invoice.untaxed_amount +
this.invoice.tax_amount)">
- <cbc:PayableRoundingAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${-(this.invoice.total_amount -
this.invoice.untaxed_amount -
this.invoice.tax_amount)}</cbc:PayableRoundingAmount>
+ <cbc:PayableRoundingAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format((-(this.invoice.total_amount -
this.invoice.untaxed_amount - this.invoice.tax_amount)).normalize(),
'f')}</cbc:PayableRoundingAmount>
</py:if>
- <cbc:PrepaidAmount py:if="this.prepaid_amount" py:attrs="{'currencyID':
this.invoice.currency.code}">${-this.prepaid_amount}</cbc:PrepaidAmount>
- <cbc:PayableAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${-this.invoice.total_amount +
this.prepaid_amount}</cbc:PayableAmount>
+ <cbc:PrepaidAmount py:if="this.prepaid_amount" py:attrs="{'currencyID':
this.invoice.currency.code}">${format((-this.prepaid_amount).normalize(),
'f')}</cbc:PrepaidAmount>
+ <cbc:PayableAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format((-this.invoice.total_amount +
this.prepaid_amount).normalize(), 'f')}</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
<cac:CreditNoteLine py:for="line_id, line in enumerate(this.lines, 1)">
<cbc:ID>${line_id}</cbc:ID>
<cbc:CreditedQuantity py:attrs="{'unitCode': line.unit.unece_code if
line.unit and line.unit.unece_code else
'ZZ'}">${format(-Decimal(str(line.quantity)), 'f')}</cbc:CreditedQuantity>
- <cbc:LineExtensionAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${-line.amount}</cbc:LineExtensionAmount>
+ <cbc:LineExtensionAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format((-line.amount).normalize(),
'f')}</cbc:LineExtensionAmount>
<cac:Item>
<cbc:Description
py:if="line.description">${line.description}</cbc:Description>
<cbc:Name>${line.product.name if line.product else
line.summary}</cbc:Name>
@@ -152,7 +152,7 @@
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
- <cbc:PriceAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${line.unit_price}</cbc:PriceAmount>
+ <cbc:PriceAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format(line.unit_price.normalize(),
'f')}</cbc:PriceAmount>
</cac:Price>
</cac:CreditNoteLine>
</CreditNote>
diff -r 4b3c250361bc -r 6cb75123ee20
modules/edocument_ubl/template/2/Invoice.xml
--- a/modules/edocument_ubl/template/2/Invoice.xml Tue Jul 14 17:07:07
2026 +0200
+++ b/modules/edocument_ubl/template/2/Invoice.xml Wed Jul 15 18:07:22
2026 +0200
@@ -90,7 +90,7 @@
<py:otherwise>
<cac:PaymentTerms py:for="line in this.invoice.lines_to_pay">
<cbc:Note py:if="this.invoice.payment_term and
this.invoice.payment_term.description">${this.invoice.payment_term.description}</cbc:Note>
- <cbc:Amount py:attrs="{'currencyID':
this.invoice.currency.code}">${line.amount}</cbc:Amount>
+ <cbc:Amount py:attrs="{'currencyID':
this.invoice.currency.code}">${format(line.amount.normalize(),
'f')}</cbc:Amount>
<cbc:PaymentDueDate>${line.maturity_date}</cbc:PaymentDueDate>
</cac:PaymentTerms>
</py:otherwise>
@@ -101,16 +101,16 @@
<cbc:AllowanceChargeReasonCode
py:if="reason_code">${reason_code}</cbc:AllowanceChargeReasonCode>
</py:with>
<cbc:AllowanceChargeReason>${allowance_charge.product.name}</cbc:AllowanceChargeReason>
- <cbc:Amount py:attrs="{'currencyID':
this.invoice.currency.code}">${abs(allowance_charge.amount)}</cbc:Amount>
+ <cbc:Amount py:attrs="{'currencyID':
this.invoice.currency.code}">${format(abs(allowance_charge.amount).normalize(),
'f')}</cbc:Amount>
<cac:TaxCategory py:for="tax_line in allowance_charge.invoice_taxes">
${TaxCategory(tax_line.tax)}
</cac:TaxCategory>
</cac:AllowanceCharge>
<cac:TaxTotal py:for="group, lines, amount in this.taxes">
- <cbc:TaxAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${amount}</cbc:TaxAmount>
+ <cbc:TaxAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format(amount.normalize(), 'f')}</cbc:TaxAmount>
<cac:TaxSubtotal py:for="line in lines">
- <cbc:TaxableAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${line.base}</cbc:TaxableAmount>
- <cbc:TaxAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${line.amount}</cbc:TaxAmount>
+ <cbc:TaxableAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format(line.base.normalize(),
'f')}</cbc:TaxableAmount>
+ <cbc:TaxAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format(line.amount.normalize(),
'f')}</cbc:TaxAmount>
<cbc:Percent py:if="line.tax.type == 'percentage' and not
(specification or '').startswith('peppol')">${format((line.tax.rate *
100).normalize(), 'f')}</cbc:Percent>
<cac:TaxCategory>
${TaxCategory(line.tax)}
@@ -118,19 +118,19 @@
</cac:TaxSubtotal>
</cac:TaxTotal>
<cac:LegalMonetaryTotal>
- <cbc:LineExtensionAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${this.invoice.untaxed_amount}</cbc:LineExtensionAmount>
- <cbc:TaxExclusiveAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${this.invoice.untaxed_amount}</cbc:TaxExclusiveAmount>
- <cbc:TaxInclusiveAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${this.invoice.untaxed_amount +
this.invoice.tax_amount}</cbc:TaxInclusiveAmount>
+ <cbc:LineExtensionAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format(this.invoice.untaxed_amount.normalize(),
'f')}</cbc:LineExtensionAmount>
+ <cbc:TaxExclusiveAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format(this.invoice.untaxed_amount.normalize(),
'f')}</cbc:TaxExclusiveAmount>
+ <cbc:TaxInclusiveAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format((this.invoice.untaxed_amount +
this.invoice.tax_amount).normalize(), 'f')}</cbc:TaxInclusiveAmount>
<py:if test="this.invoice.total_amount != (this.invoice.untaxed_amount +
this.invoice.tax_amount)">
- <cbc:PayableRoundingAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${this.invoice.total_amount -
this.invoice.untaxed_amount -
this.invoice.tax_amount}</cbc:PayableRoundingAmount>
+ <cbc:PayableRoundingAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format((this.invoice.total_amount -
this.invoice.untaxed_amount - this.invoice.tax_amount).normalize(),
'f')}</cbc:PayableRoundingAmount>
</py:if>
- <cbc:PrepaidAmount py:if="this.prepaid_amount" py:attrs="{'currencyID':
this.invoice.currency.code}">${this.prepaid_amount}</cbc:PrepaidAmount>
- <cbc:PayableAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${this.invoice.total_amount -
this.prepaid_amount}</cbc:PayableAmount>
+ <cbc:PrepaidAmount py:if="this.prepaid_amount" py:attrs="{'currencyID':
this.invoice.currency.code}">${format(this.prepaid_amount.normalize(),
'f')}</cbc:PrepaidAmount>
+ <cbc:PayableAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format((this.invoice.total_amount -
this.prepaid_amount).normalize(), 'f')}</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
<cac:InvoiceLine py:for="line_id, line in enumerate(this.lines, 1)">
<cbc:ID>${line_id}</cbc:ID>
<cbc:InvoicedQuantity py:attrs="{'unitCode': line.unit.unece_code if
line.unit and line.unit.unece_code else
'ZZ'}">${format(Decimal(str(line.quantity)), 'f')}</cbc:InvoicedQuantity>
- <cbc:LineExtensionAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${line.amount}</cbc:LineExtensionAmount>
+ <cbc:LineExtensionAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format(line.amount.normalize(),
'f')}</cbc:LineExtensionAmount>
<cac:Item>
<cbc:Description
py:if="line.description">${line.description}</cbc:Description>
<cbc:Name>${line.product.name if line.product else
line.summary}</cbc:Name>
@@ -152,7 +152,7 @@
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
- <cbc:PriceAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${line.unit_price}</cbc:PriceAmount>
+ <cbc:PriceAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format(line.unit_price.normalize(),
'f')}</cbc:PriceAmount>
</cac:Price>
</cac:InvoiceLine>
</Invoice>
diff -r 4b3c250361bc -r 6cb75123ee20
modules/edocument_uncefact/template/16B-CII/CrossIndustryInvoice.xml
--- a/modules/edocument_uncefact/template/16B-CII/CrossIndustryInvoice.xml
Tue Jul 14 17:07:07 2026 +0200
+++ b/modules/edocument_uncefact/template/16B-CII/CrossIndustryInvoice.xml
Wed Jul 15 18:07:22 2026 +0200
@@ -43,11 +43,11 @@
</py:def>
<py:def function="TradeTax(tax, amount=None, base=None)">
<ram:ApplicableTradeTax>
- <ram:CalculatedAmount py:if="amount" py:attrs="{'currencyID':
this.invoice.currency.code}">${amount * this.type_sign}</ram:CalculatedAmount>
+ <ram:CalculatedAmount py:if="amount" py:attrs="{'currencyID':
this.invoice.currency.code}">${format((amount * this.type_sign).normalize(),
'f')}</ram:CalculatedAmount>
<ram:TypeCode
py:if="tax.unece_code">${tax.unece_code}</ram:TypeCode>
<ram:ExemptionReasonCode py:if="hasattr(tax, 'vatex_code') and
tax.vatex_code">${tax.vatex_code}</ram:ExemptionReasonCode>
<ram:ExemptionReason
py:if="tax.legal_notice">${tax.legal_notice}</ram:ExemptionReason>
- <ram:BasisAmount py:if="base">${base *
this.type_sign}</ram:BasisAmount>
+ <ram:BasisAmount py:if="base">${format((base *
this.type_sign).normalize(), 'f')}</ram:BasisAmount>
<ram:CategoryCode
py:if="tax.unece_category_code">${tax.unece_category_code}</ram:CategoryCode>
<ram:RateApplicablePercent py:if="tax.type ==
'percentage'">${format((tax.rate * 100).normalize(),
'f')}</ram:RateApplicablePercent>
</ram:ApplicableTradeTax>
@@ -73,7 +73,7 @@
</ram:SpecifiedTradeProduct>
<ram:SpecifiedLineTradeAgreement>
<ram:NetPriceProductTradePrice>
- <ram:ChargeAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${this.invoice.currency.round(line.unit_price)}</ram:ChargeAmount>
+ <ram:ChargeAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format(this.invoice.currency.round(line.unit_price).normalize(),
'f')}</ram:ChargeAmount>
</ram:NetPriceProductTradePrice>
</ram:SpecifiedLineTradeAgreement>
<ram:SpecifiedLineTradeDelivery>
@@ -84,7 +84,7 @@
${TradeTax(tax.tax)}
</py:for>
<ram:SpecifiedTradeSettlementLineMonetarySummation>
- <ram:LineTotalAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${line.amount}</ram:LineTotalAmount>
+ <ram:LineTotalAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format(line.amount.normalize(),
'f')}</ram:LineTotalAmount>
</ram:SpecifiedTradeSettlementLineMonetarySummation>
</ram:SpecifiedLineTradeSettlement>
</ram:IncludedSupplyChainTradeLineItem>
@@ -157,14 +157,14 @@
<ram:DueDateDateTime>
${DateTime(line.maturity_date)}
</ram:DueDateDateTime>
- <ram:PartialPaymentAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${(line.amount_second_currency or (line.debit -
line.credit)) * this.type_sign}</ram:PartialPaymentAmount>
+ <ram:PartialPaymentAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format(((line.amount_second_currency or
(line.debit - line.credit)) * this.type_sign).normalize(),
'f')}</ram:PartialPaymentAmount>
</ram:SpecifiedTradePaymentTerms>
<ram:SpecifiedTradeSettlementHeaderMonetarySummation>
- <ram:LineTotalAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${this.invoice.untaxed_amount *
this.type_sign}</ram:LineTotalAmount>
- <ram:TaxBasisTotalAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${this.invoice.untaxed_amount *
this.type_sign}</ram:TaxBasisTotalAmount>
- <ram:TaxTotalAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${this.invoice.tax_amount *
this.type_sign}</ram:TaxTotalAmount>
- <ram:GrandTotalAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${this.invoice.total_amount *
this.type_sign}</ram:GrandTotalAmount>
- <ram:DuePayableAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${this.invoice.amount_to_pay *
this.type_sign}</ram:DuePayableAmount>
+ <ram:LineTotalAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format((this.invoice.untaxed_amount *
this.type_sign).normalize(), 'f')}</ram:LineTotalAmount>
+ <ram:TaxBasisTotalAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format((this.invoice.untaxed_amount *
this.type_sign).normalize(), 'f')}</ram:TaxBasisTotalAmount>
+ <ram:TaxTotalAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format((this.invoice.tax_amount *
this.type_sign).normalize(), 'f')}</ram:TaxTotalAmount>
+ <ram:GrandTotalAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format((this.invoice.total_amount *
this.type_sign).normalize(), 'f')}</ram:GrandTotalAmount>
+ <ram:DuePayableAmount py:attrs="{'currencyID':
this.invoice.currency.code}">${format((this.invoice.amount_to_pay *
this.type_sign).normalize(), 'f')}</ram:DuePayableAmount>
</ram:SpecifiedTradeSettlementHeaderMonetarySummation>
</ram:ApplicableHeaderTradeSettlement>
</rsm:SupplyChainTradeTransaction>