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>

Reply via email to