Do not normalize Decimal value in XML document

Some third party expect to always have the trailing 0 in the format of currency
amount. So the amount coming from the database must already have the right
precision to format.

Closes #15085
This commit is contained in:
Cédric Krier
2026-09-28 11:26:56 +02:00
parent 86c51cd9da
commit 7b809a4bf9
13 changed files with 67 additions and 67 deletions
@@ -32,7 +32,7 @@ this repository contains the full copyright notices and license terms. -->
<CreDtTm>${datetime.datetime.now().replace(microsecond=0).isoformat()}</CreDtTm>
<!-- Authstn -->
<NbOfTxs>${sum(len(payments) for _, payments in group.sepa_payments)}</NbOfTxs>
<CtrlSum>${format(sum(p.amount for p in group.payments).normalize(), 'f')}</CtrlSum>
<CtrlSum>${format(sum(p.amount for p in group.payments), 'f')}</CtrlSum>
<!-- PmtTpInf -->
<!-- ReqdColltnDt -->
<InitgPty>
@@ -45,7 +45,7 @@ this repository contains the full copyright notices and license terms. -->
<PmtMtd>TRF</PmtMtd>
<BtchBookg>${'true' if group.journal.sepa_batch_booking else 'false'}</BtchBookg>
<NbOfTxs>${len(payments)}</NbOfTxs>
<CtrlSum>${format(sum(p.amount for p in payments).normalize(), 'f')}</CtrlSum>
<CtrlSum>${format(sum(p.amount for p in payments), 'f')}</CtrlSum>
<PmtTpInf>
<!-- InstrPrty -->
<SvcLvl>
@@ -77,7 +77,7 @@ this repository contains the full copyright notices and license terms. -->
</PmtId>
<!-- PmtTpInf --> <!-- EPC only at payment information level -->
<Amt>
<InstdAmt py:attrs="{'Ccy': payment.currency.code}">${format(payment.amount.normalize(), 'f')}</InstdAmt>
<InstdAmt py:attrs="{'Ccy': payment.currency.code}">${format(payment.amount, 'f')}</InstdAmt>
<!-- EqvtAmt -->
</Amt>
<!-- XchgRateInf -->
@@ -13,7 +13,7 @@ this repository contains the full copyright notices and license terms. -->
<CreDtTm>${datetime.datetime.now().replace(microsecond=0).isoformat()}</CreDtTm>
<!-- Authstn -->
<NbOfTxs>${sum(len(payments) for _, payments in group.sepa_payments)}</NbOfTxs>
<CtrlSum>${format(sum(p.amount for p in group.payments).normalize(), 'f')}</CtrlSum>
<CtrlSum>${format(sum(p.amount for p in group.payments), 'f')}</CtrlSum>
<!-- PmtTpInf -->
<!-- ReqdColltnDt -->
<InitgPty>
@@ -26,7 +26,7 @@ this repository contains the full copyright notices and license terms. -->
<PmtMtd>TRF</PmtMtd>
<BtchBookg>${'true' if group.journal.sepa_batch_booking else 'false'}</BtchBookg>
<NbOfTxs>${len(payments)}</NbOfTxs>
<CtrlSum>${format(sum(p.amount for p in payments).normalize(), 'f')}</CtrlSum>
<CtrlSum>${format(sum(p.amount for p in payments), 'f')}</CtrlSum>
<PmtTpInf>
<!-- InstrPrty -->
<SvcLvl>
@@ -59,7 +59,7 @@ this repository contains the full copyright notices and license terms. -->
</PmtId>
<!-- PmtTpInf --> <!-- EPC only at payment information level -->
<Amt>
<InstdAmt py:attrs="{'Ccy': payment.currency.code}">${format(payment.amount.normalize(), 'f')}</InstdAmt>
<InstdAmt py:attrs="{'Ccy': payment.currency.code}">${format(payment.amount, 'f')}</InstdAmt>
<!-- EqvtAmt -->
</Amt>
<!-- XchgRateInf -->
@@ -14,7 +14,7 @@ this repository contains the full copyright notices and license terms. -->
<CreDtTm>${datetime.datetime.now().replace(microsecond=0).isoformat()}</CreDtTm>
<!-- Authstn -->
<NbOfTxs>${sum(len(payments) for _, payments in group.sepa_payments)}</NbOfTxs>
<CtrlSum>${format(sum(p.amount for p in group.payments).normalize(), 'f')}</CtrlSum>
<CtrlSum>${format(sum(p.amount for p in group.payments), 'f')}</CtrlSum>
<InitgPty>
${PartyIdentification(group.sepa_initiating_party, id=group.journal.sepa_payable_initiator_id)}
</InitgPty>
@@ -25,7 +25,7 @@ this repository contains the full copyright notices and license terms. -->
<PmtMtd>TRF</PmtMtd>
<BtchBookg>${'true' if group.journal.sepa_batch_booking else 'false'}</BtchBookg>
<NbOfTxs>${len(payments)}</NbOfTxs>
<CtrlSum>${format(sum(p.amount for p in payments).normalize(), 'f')}</CtrlSum>
<CtrlSum>${format(sum(p.amount for p in payments), 'f')}</CtrlSum>
<PmtTpInf>
<!-- InstrPrty -->
<SvcLvl>
@@ -61,7 +61,7 @@ this repository contains the full copyright notices and license terms. -->
</PmtId>
<!-- PmtTpInf --> <!-- EPC only at payment information level -->
<Amt>
<InstdAmt py:attrs="{'Ccy': payment.currency.code}">${format(payment.amount.normalize(), 'f')}</InstdAmt>
<InstdAmt py:attrs="{'Ccy': payment.currency.code}">${format(payment.amount, 'f')}</InstdAmt>
<!-- EqvtAmt -->
</Amt>
<!-- XchgRateInf -->
@@ -15,7 +15,7 @@ this repository contains the full copyright notices and license terms. -->
<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>${format(sum(p.amount for p in group.payments).normalize(), 'f')}</CtrlSum>
<CtrlSum>${format(sum(p.amount for p in group.payments), 'f')}</CtrlSum>
<InitgPty>
${PartyIdentification(group.sepa_initiating_party, id=group.journal.sepa_payable_initiator_id, with_address=False)}
</InitgPty>
@@ -25,7 +25,7 @@ this repository contains the full copyright notices and license terms. -->
<PmtMtd>TRF</PmtMtd>
<BtchBookg>${'true' if group.journal.sepa_batch_booking else 'false'}</BtchBookg>
<NbOfTxs>${len(payments)}</NbOfTxs>
<CtrlSum>${format(sum(p.amount for p in payments).normalize(), 'f')}</CtrlSum>
<CtrlSum>${format(sum(p.amount for p in payments), 'f')}</CtrlSum>
<PmtTpInf>
<!-- InstrPrty -->
<SvcLvl>
@@ -52,7 +52,7 @@ this repository contains the full copyright notices and license terms. -->
</PmtId>
<!-- PmtTpInf --> <!-- EPC only at payment information level -->
<Amt>
<InstdAmt py:attrs="{'Ccy': payment.currency.code}">${format(payment.amount.normalize(), 'f')}</InstdAmt>
<InstdAmt py:attrs="{'Ccy': payment.currency.code}">${format(payment.amount, 'f')}</InstdAmt>
</Amt>
<!-- ChrgBr --> <!-- EPC only at payment information level -->
<!-- UltmtDbtr -->
@@ -32,7 +32,7 @@ this repository contains the full copyright notices and license terms. -->
<CreDtTm>${datetime.datetime.now().replace(microsecond=0).isoformat()}</CreDtTm>
<!-- Authstn -->
<NbOfTxs>${sum(len(payments) for _, payments in group.sepa_payments)}</NbOfTxs>
<CtrlSum>${format(sum(p.amount for p in group.payments).normalize(), 'f')}</CtrlSum>
<CtrlSum>${format(sum(p.amount for p in group.payments), 'f')}</CtrlSum>
<!-- PmtTpInf -->
<!-- ReqdColltnDt -->
<InitgPty>
@@ -45,7 +45,7 @@ this repository contains the full copyright notices and license terms. -->
<PmtMtd>DD</PmtMtd>
<BtchBookg>${'true' if group.journal.sepa_batch_booking else 'false'}</BtchBookg>
<NbOfTxs>${len(payments)}</NbOfTxs>
<CtrlSum>${format(sum(p.amount for p in payments).normalize(), 'f')}</CtrlSum>
<CtrlSum>${format(sum(p.amount for p in payments), 'f')}</CtrlSum>
<PmtTpInf>
<!-- InstrPrty -->
<SvcLvl>
@@ -83,7 +83,7 @@ this repository contains the full copyright notices and license terms. -->
<EndToEndId>${payment.sepa_end_to_end_id}</EndToEndId>
</PmtId>
<!-- PmtTpInf -->
<InstdAmt py:attrs="{'Ccy': payment.currency.code}">${format(payment.amount.normalize(), 'f')}</InstdAmt>
<InstdAmt py:attrs="{'Ccy': payment.currency.code}">${format(payment.amount, 'f')}</InstdAmt>
<!-- ChrgBr --> <!-- EPC only at payment information level -->
<DrctDbtTx>
<MndtRltdInf py:with="mandate = payment.sepa_mandate">
@@ -13,7 +13,7 @@ this repository contains the full copyright notices and license terms. -->
<CreDtTm>${datetime.datetime.now().replace(microsecond=0).isoformat()}</CreDtTm>
<!-- Authstn -->
<NbOfTxs>${len(group.payments)}</NbOfTxs>
<CtrlSum>${format(sum(p.amount for p in group.payments).normalize(), 'f')}</CtrlSum>
<CtrlSum>${format(sum(p.amount for p in group.payments), 'f')}</CtrlSum>
<!-- PmtTpInf -->
<!-- ReqdColltnDt -->
<InitgPty>
@@ -26,7 +26,7 @@ this repository contains the full copyright notices and license terms. -->
<PmtMtd>DD</PmtMtd>
<BtchBookg>${'true' if group.journal.sepa_batch_booking else 'false'}</BtchBookg>
<NbOfTxs>${len(payments)}</NbOfTxs>
<CtrlSum>${format(sum(p.amount for p in payments).normalize(), 'f')}</CtrlSum>
<CtrlSum>${format(sum(p.amount for p in payments), 'f')}</CtrlSum>
<PmtTpInf>
<!-- InstrPrty -->
<SvcLvl>
@@ -64,7 +64,7 @@ this repository contains the full copyright notices and license terms. -->
<EndToEndId>${payment.sepa_end_to_end_id}</EndToEndId>
</PmtId>
<!-- PmtTpInf -->
<InstdAmt py:attrs="{'Ccy': payment.currency.code}">${format(payment.amount.normalize(), 'f')}</InstdAmt>
<InstdAmt py:attrs="{'Ccy': payment.currency.code}">${format(payment.amount, 'f')}</InstdAmt>
<!-- ChrgBr --> <!-- EPC only at payment information level -->
<DrctDbtTx>
<MndtRltdInf py:with="mandate = payment.sepa_mandate">
@@ -14,7 +14,7 @@ this repository contains the full copyright notices and license terms. -->
<CreDtTm>${datetime.datetime.now().replace(microsecond=0).isoformat()}</CreDtTm>
<!-- Authstn -->
<NbOfTxs>${len(group.payments)}</NbOfTxs>
<CtrlSum>${format(sum(p.amount for p in group.payments).normalize(), 'f')}</CtrlSum>
<CtrlSum>${format(sum(p.amount for p in group.payments), 'f')}</CtrlSum>
<InitgPty>
${PartyIdentification(group.sepa_initiating_party, id=group.journal.sepa_receivable_initiator_id)}
</InitgPty>
@@ -25,7 +25,7 @@ this repository contains the full copyright notices and license terms. -->
<PmtMtd>DD</PmtMtd>
<BtchBookg>${'true' if group.journal.sepa_batch_booking else 'false'}</BtchBookg>
<NbOfTxs>${len(payments)}</NbOfTxs>
<CtrlSum>${format(sum(p.amount for p in payments).normalize(), 'f')}</CtrlSum>
<CtrlSum>${format(sum(p.amount for p in payments), 'f')}</CtrlSum>
<PmtTpInf>
<!-- InstrPrty -->
<SvcLvl>
@@ -64,7 +64,7 @@ this repository contains the full copyright notices and license terms. -->
<!-- UETR -->
</PmtId>
<!-- PmtTpInf -->
<InstdAmt py:attrs="{'Ccy': payment.currency.code}">${format(payment.amount.normalize(), 'f')}</InstdAmt>
<InstdAmt py:attrs="{'Ccy': payment.currency.code}">${format(payment.amount, 'f')}</InstdAmt>
<!-- ChrgBr --> <!-- EPC only at payment information level -->
<DrctDbtTx>
<MndtRltdInf py:with="mandate = payment.sepa_mandate">
@@ -15,7 +15,7 @@ this repository contains the full copyright notices and license terms. -->
<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>${format(sum(p.amount for p in group.payments).normalize(), 'f')}</CtrlSum>
<CtrlSum>${format(sum(p.amount for p in group.payments), 'f')}</CtrlSum>
<InitgPty>
${PartyIdentification(group.sepa_initiating_party, id=group.journal.sepa_receivable_initiator_id, with_address=False)}
</InitgPty>
@@ -25,7 +25,7 @@ this repository contains the full copyright notices and license terms. -->
<PmtMtd>DD</PmtMtd>
<BtchBookg>${'true' if group.journal.sepa_batch_booking else 'false'}</BtchBookg>
<NbOfTxs>${len(payments)}</NbOfTxs>
<CtrlSum>${format(sum(p.amount for p in payments).normalize(), 'f')}</CtrlSum>
<CtrlSum>${format(sum(p.amount for p in payments), 'f')}</CtrlSum>
<PmtTpInf>
<SvcLvl>
<Cd>SEPA</Cd>
@@ -56,7 +56,7 @@ this repository contains the full copyright notices and license terms. -->
<InstrId>${payment.sepa_instruction_id}</InstrId>
<EndToEndId>${payment.sepa_end_to_end_id}</EndToEndId>
</PmtId>
<InstdAmt py:attrs="{'Ccy': payment.currency.code}">${format(payment.amount.normalize(), 'f')}</InstdAmt>
<InstdAmt py:attrs="{'Ccy': payment.currency.code}">${format(payment.amount, 'f')}</InstdAmt>
<!-- ChrgBr --> <!-- EPC only at payment information level -->
<DrctDbtTx>
<MndtRltdInf py:with="mandate = payment.sepa_mandate">
@@ -26,7 +26,7 @@ this repository contains the full copyright notices and license terms. -->
<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>${format(sum(p.amount for p in group.payments).normalize(), 'f')}</CtrlSum>
<CtrlSum>${format(sum(p.amount for p in group.payments), 'f')}</CtrlSum>
<InitgPty>
${PartyIdentification(group.sepa_initiating_party)}
</InitgPty>
@@ -36,7 +36,7 @@ this repository contains the full copyright notices and license terms. -->
<PmtMtd>TRF</PmtMtd>
<BtchBookg>${'true' if group.journal.sepa_batch_booking else 'false'}</BtchBookg>
<NbOfTxs>${len(payments)}</NbOfTxs>
<CtrlSum>${format(sum(p.amount for p in payments).normalize(), 'f')}</CtrlSum>
<CtrlSum>${format(sum(p.amount for p in payments), 'f')}</CtrlSum>
<PmtTpInf>
<!-- InstrPrty -->
<SvcLvl>
@@ -62,7 +62,7 @@ this repository contains the full copyright notices and license terms. -->
<EndToEndId>${payment.sepa_end_to_end_id}</EndToEndId>
</PmtId>
<Amt>
<InstdAmt py:attrs="{'Ccy': payment.currency.code}">${format(payment.amount.normalize(), 'f')}</InstdAmt>
<InstdAmt py:attrs="{'Ccy': payment.currency.code}">${format(payment.amount, 'f')}</InstdAmt>
<!-- EqvtAmt -->
</Amt>
<!-- ChrgBr --> <!-- EPC only at payment information level -->
@@ -32,7 +32,7 @@ this repository contains the full copyright notices and license terms. -->
<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>${format(sum(p.amount for p in group.payments).normalize(), 'f')}</CtrlSum>
<CtrlSum>${format(sum(p.amount for p in group.payments), 'f')}</CtrlSum>
<InitgPty>
${PartyIdentification(group.sepa_initiating_party)}
</InitgPty>
@@ -42,7 +42,7 @@ this repository contains the full copyright notices and license terms. -->
<PmtMtd>DD</PmtMtd>
<BtchBookg>${'true' if group.journal.sepa_batch_booking else 'false'}</BtchBookg>
<NbOfTxs>${len(payments)}</NbOfTxs>
<CtrlSum>${format(sum(p.amount for p in payments).normalize(), 'f')}</CtrlSum>
<CtrlSum>${format(sum(p.amount for p in payments), 'f')}</CtrlSum>
<PmtTpInf>
<SvcLvl>
<Cd>SEPA</Cd>
@@ -73,7 +73,7 @@ this repository contains the full copyright notices and license terms. -->
<InstrId>${payment.sepa_instruction_id}</InstrId>
<EndToEndId>${payment.sepa_end_to_end_id}</EndToEndId>
</PmtId>
<InstdAmt py:attrs="{'Ccy': payment.currency.code}">${format(payment.amount.normalize(), 'f')}</InstdAmt>
<InstdAmt py:attrs="{'Ccy': payment.currency.code}">${format(payment.amount, 'f')}</InstdAmt>
<DrctDbtTx>
<MndtRltdInf py:with="mandate = payment.sepa_mandate">
<MndtId>${mandate.identification}</MndtId>
+13 -13
View File
@@ -90,7 +90,7 @@ this repository contains the full copyright notices and license terms. -->
<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}">${format(line.amount.normalize(), 'f')}</cbc:Amount>
<cbc:Amount py:attrs="{'currencyID': this.invoice.currency.code}">${format(line.amount, 'f')}</cbc:Amount>
<cbc:PaymentDueDate>${line.maturity_date}</cbc:PaymentDueDate>
</cac:PaymentTerms>
</py:otherwise>
@@ -101,16 +101,16 @@ this repository contains the full copyright notices and license terms. -->
<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}">${format(abs(allowance_charge.amount).normalize(), 'f')}</cbc:Amount>
<cbc:Amount py:attrs="{'currencyID': this.invoice.currency.code}">${format(abs(allowance_charge.amount), '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}">${format((-amount).normalize(), 'f')}</cbc:TaxAmount>
<cbc:TaxAmount py:attrs="{'currencyID': this.invoice.currency.code}">${format(-amount, 'f')}</cbc:TaxAmount>
<cac:TaxSubtotal py:for="line in lines">
<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:TaxableAmount py:attrs="{'currencyID': this.invoice.currency.code}">${format(-line.base, 'f')}</cbc:TaxableAmount>
<cbc:TaxAmount py:attrs="{'currencyID': this.invoice.currency.code}">${format(-line.amount, '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 @@ this repository contains the full copyright notices and license terms. -->
</cac:TaxSubtotal>
</cac:TaxTotal>
<cac:LegalMonetaryTotal>
<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>
<cbc:LineExtensionAmount py:attrs="{'currencyID': this.invoice.currency.code}">${format(-this.invoice.untaxed_amount, 'f')}</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount py:attrs="{'currencyID': this.invoice.currency.code}">${format(-this.invoice.untaxed_amount, 'f')}</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount py:attrs="{'currencyID': this.invoice.currency.code}">${format(-(this.invoice.untaxed_amount + this.invoice.tax_amount), '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}">${format((-(this.invoice.total_amount - this.invoice.untaxed_amount - this.invoice.tax_amount)).normalize(), 'f')}</cbc:PayableRoundingAmount>
<cbc:PayableRoundingAmount py:attrs="{'currencyID': this.invoice.currency.code}">${format(-(this.invoice.total_amount - this.invoice.untaxed_amount - this.invoice.tax_amount), 'f')}</cbc:PayableRoundingAmount>
</py:if>
<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>
<cbc:PrepaidAmount py:if="this.prepaid_amount" py:attrs="{'currencyID': this.invoice.currency.code}">${format(-this.prepaid_amount, 'f')}</cbc:PrepaidAmount>
<cbc:PayableAmount py:attrs="{'currencyID': this.invoice.currency.code}">${format(-this.invoice.total_amount + this.prepaid_amount, '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}">${format((-line.amount).normalize(), 'f')}</cbc:LineExtensionAmount>
<cbc:CreditedQuantity py:attrs="{'unitCode': line.unit.unece_code if line.unit and line.unit.unece_code else 'ZZ'}">${format(-Decimal(str(line.quantity)).normalize(), 'f')}</cbc:CreditedQuantity>
<cbc:LineExtensionAmount py:attrs="{'currencyID': this.invoice.currency.code}">${format(-line.amount, '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>
+13 -13
View File
@@ -90,7 +90,7 @@ this repository contains the full copyright notices and license terms. -->
<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}">${format(line.amount.normalize(), 'f')}</cbc:Amount>
<cbc:Amount py:attrs="{'currencyID': this.invoice.currency.code}">${format(line.amount, 'f')}</cbc:Amount>
<cbc:PaymentDueDate>${line.maturity_date}</cbc:PaymentDueDate>
</cac:PaymentTerms>
</py:otherwise>
@@ -101,16 +101,16 @@ this repository contains the full copyright notices and license terms. -->
<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}">${format(abs(allowance_charge.amount).normalize(), 'f')}</cbc:Amount>
<cbc:Amount py:attrs="{'currencyID': this.invoice.currency.code}">${format(abs(allowance_charge.amount), '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}">${format(amount.normalize(), 'f')}</cbc:TaxAmount>
<cbc:TaxAmount py:attrs="{'currencyID': this.invoice.currency.code}">${format(amount, 'f')}</cbc:TaxAmount>
<cac:TaxSubtotal py:for="line in lines">
<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:TaxableAmount py:attrs="{'currencyID': this.invoice.currency.code}">${format(line.base, 'f')}</cbc:TaxableAmount>
<cbc:TaxAmount py:attrs="{'currencyID': this.invoice.currency.code}">${format(line.amount, '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 @@ this repository contains the full copyright notices and license terms. -->
</cac:TaxSubtotal>
</cac:TaxTotal>
<cac:LegalMonetaryTotal>
<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>
<cbc:LineExtensionAmount py:attrs="{'currencyID': this.invoice.currency.code}">${format(this.invoice.untaxed_amount, 'f')}</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount py:attrs="{'currencyID': this.invoice.currency.code}">${format(this.invoice.untaxed_amount, 'f')}</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount py:attrs="{'currencyID': this.invoice.currency.code}">${format((this.invoice.untaxed_amount + this.invoice.tax_amount), '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}">${format((this.invoice.total_amount - this.invoice.untaxed_amount - this.invoice.tax_amount).normalize(), 'f')}</cbc:PayableRoundingAmount>
<cbc:PayableRoundingAmount py:attrs="{'currencyID': this.invoice.currency.code}">${format((this.invoice.total_amount - this.invoice.untaxed_amount - this.invoice.tax_amount), 'f')}</cbc:PayableRoundingAmount>
</py:if>
<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>
<cbc:PrepaidAmount py:if="this.prepaid_amount" py:attrs="{'currencyID': this.invoice.currency.code}">${format(this.prepaid_amount, 'f')}</cbc:PrepaidAmount>
<cbc:PayableAmount py:attrs="{'currencyID': this.invoice.currency.code}">${format(this.invoice.total_amount - this.prepaid_amount, '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}">${format(line.amount.normalize(), 'f')}</cbc:LineExtensionAmount>
<cbc:InvoicedQuantity py:attrs="{'unitCode': line.unit.unece_code if line.unit and line.unit.unece_code else 'ZZ'}">${format(Decimal(str(line.quantity)).normalize(), 'f')}</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount py:attrs="{'currencyID': this.invoice.currency.code}">${format(line.amount, '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>
@@ -59,11 +59,11 @@ this repository contains the full copyright notices and license terms. -->
</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} if not (exchange_context or '').startswith('urn:cen.eu:en16931:2017') and not (exchange_context or '').startswith('urn:factur-x.eu:1p') else {}">${format((amount * this.type_sign).normalize(), 'f')}</ram:CalculatedAmount>
<ram:CalculatedAmount py:if="amount" py:attrs="{'currencyID': this.invoice.currency.code} if not (exchange_context or '').startswith('urn:cen.eu:en16931:2017') and not (exchange_context or '').startswith('urn:factur-x.eu:1p') else {}">${format(amount * this.type_sign, '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">${format((base * this.type_sign).normalize(), 'f')}</ram:BasisAmount>
<ram:BasisAmount py:if="base">${format(base * this.type_sign, '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>
@@ -92,18 +92,18 @@ this repository contains the full copyright notices and license terms. -->
</ram:SpecifiedTradeProduct>
<ram:SpecifiedLineTradeAgreement>
<ram:NetPriceProductTradePrice>
<ram:ChargeAmount py:attrs="{'currencyID': this.invoice.currency.code} if not (exchange_context or '').startswith('urn:cen.eu:en16931:2017') and not (exchange_context or '').startswith('urn:factur-x.eu:1p') else {}">${format(this.invoice.currency.round(line.unit_price).normalize(), 'f')}</ram:ChargeAmount>
<ram:ChargeAmount py:attrs="{'currencyID': this.invoice.currency.code} if not (exchange_context or '').startswith('urn:cen.eu:en16931:2017') and not (exchange_context or '').startswith('urn:factur-x.eu:1p') else {}">${format(this.invoice.currency.round(line.unit_price), 'f')}</ram:ChargeAmount>
</ram:NetPriceProductTradePrice>
</ram:SpecifiedLineTradeAgreement>
<ram:SpecifiedLineTradeDelivery>
<ram:BilledQuantity py:attrs="{'unitCode': line.unit.unece_code} if line.unit and line.unit.unece_code else {}">${format(abs(Decimal(str(line.quantity))), 'f')}</ram:BilledQuantity>
<ram:BilledQuantity py:attrs="{'unitCode': line.unit.unece_code} if line.unit and line.unit.unece_code else {}">${format(abs(Decimal(str(line.quantity)).normalize()), 'f')}</ram:BilledQuantity>
</ram:SpecifiedLineTradeDelivery>
<ram:SpecifiedLineTradeSettlement>
<py:for each="tax in line.invoice_taxes">
${TradeTax(tax.tax)}
</py:for>
<ram:SpecifiedTradeSettlementLineMonetarySummation>
<ram:LineTotalAmount py:attrs="{'currencyID': this.invoice.currency.code} if not (exchange_context or '').startswith('urn:cen.eu:en16931:2017') and not (exchange_context or '').startswith('urn:factur-x.eu:1p') else {}">${format((line.amount * this.type_sign).normalize(), 'f')}</ram:LineTotalAmount>
<ram:LineTotalAmount py:attrs="{'currencyID': this.invoice.currency.code} if not (exchange_context or '').startswith('urn:cen.eu:en16931:2017') and not (exchange_context or '').startswith('urn:factur-x.eu:1p') else {}">${format(line.amount * this.type_sign, 'f')}</ram:LineTotalAmount>
</ram:SpecifiedTradeSettlementLineMonetarySummation>
</ram:SpecifiedLineTradeSettlement>
</ram:IncludedSupplyChainTradeLineItem>
@@ -181,15 +181,15 @@ this repository contains the full copyright notices and license terms. -->
<ram:DueDateDateTime>
${DateTime(line.maturity_date)}
</ram:DueDateDateTime>
<ram:PartialPaymentAmount py:attrs="{'currencyID': this.invoice.currency.code} if not (exchange_context or '').startswith('urn:cen.eu:en16931:2017') else {}" py:if="(exchange_context or '') != 'urn:cen.eu:en16931:2017' and (exchange_context or '') != 'urn:cen.eu:en16931:2017#compliant#urn:factur-x.eu:1p0:basic' and not (exchange_context or '').startswith('urn:factur-x.eu:1p0')">${format(((line.amount_second_currency or (line.debit - line.credit)) * this.type_sign).normalize(), 'f')}</ram:PartialPaymentAmount>
<ram:PartialPaymentAmount py:attrs="{'currencyID': this.invoice.currency.code} if not (exchange_context or '').startswith('urn:cen.eu:en16931:2017') else {}" py:if="(exchange_context or '') != 'urn:cen.eu:en16931:2017' and (exchange_context or '') != 'urn:cen.eu:en16931:2017#compliant#urn:factur-x.eu:1p0:basic' and not (exchange_context or '').startswith('urn:factur-x.eu:1p0')">${format((line.amount_second_currency or (line.debit - line.credit)) * this.type_sign, 'f')}</ram:PartialPaymentAmount>
</ram:SpecifiedTradePaymentTerms>
</py:if>
<ram:SpecifiedTradeSettlementHeaderMonetarySummation>
<ram:LineTotalAmount py:attrs="{'currencyID': this.invoice.currency.code} if not (exchange_context or '').startswith('urn:cen.eu:en16931:2017') and not (exchange_context or '').startswith('urn:factur-x.eu:1p') else {}" py:if="(exchange_context or '') != 'urn:factur-x.eu:1p0:minimum'">${format((this.invoice.untaxed_amount * this.type_sign).normalize(), 'f')}</ram:LineTotalAmount>
<ram:TaxBasisTotalAmount py:attrs="{'currencyID': this.invoice.currency.code} if not (exchange_context or '').startswith('urn:cen.eu:en16931:2017') and not (exchange_context or '').startswith('urn:factur-x.eu:1p') else {}">${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} if not (exchange_context or '').startswith('urn:cen.eu:en16931:2017') and not (exchange_context or '').startswith('urn:factur-x.eu:1p0') else {}">${format((this.invoice.total_amount * this.type_sign).normalize(), 'f')}</ram:GrandTotalAmount>
<ram:DuePayableAmount py:attrs="{'currencyID': this.invoice.currency.code} if not (exchange_context or '').startswith('urn:cen.eu:en16931:2017') and not (exchange_context or '').startswith('urn:factur-x.eu:1p0') else {}">${format((this.invoice.amount_to_pay * this.type_sign).normalize(), 'f')}</ram:DuePayableAmount>
<ram:LineTotalAmount py:attrs="{'currencyID': this.invoice.currency.code} if not (exchange_context or '').startswith('urn:cen.eu:en16931:2017') and not (exchange_context or '').startswith('urn:factur-x.eu:1p') else {}" py:if="(exchange_context or '') != 'urn:factur-x.eu:1p0:minimum'">${format(this.invoice.untaxed_amount * this.type_sign, 'f')}</ram:LineTotalAmount>
<ram:TaxBasisTotalAmount py:attrs="{'currencyID': this.invoice.currency.code} if not (exchange_context or '').startswith('urn:cen.eu:en16931:2017') and not (exchange_context or '').startswith('urn:factur-x.eu:1p') else {}">${format(this.invoice.untaxed_amount * this.type_sign, 'f')}</ram:TaxBasisTotalAmount>
<ram:TaxTotalAmount py:attrs="{'currencyID': this.invoice.currency.code}">${format(this.invoice.tax_amount * this.type_sign, 'f')}</ram:TaxTotalAmount>
<ram:GrandTotalAmount py:attrs="{'currencyID': this.invoice.currency.code} if not (exchange_context or '').startswith('urn:cen.eu:en16931:2017') and not (exchange_context or '').startswith('urn:factur-x.eu:1p0') else {}">${format(this.invoice.total_amount * this.type_sign, 'f')}</ram:GrandTotalAmount>
<ram:DuePayableAmount py:attrs="{'currencyID': this.invoice.currency.code} if not (exchange_context or '').startswith('urn:cen.eu:en16931:2017') and not (exchange_context or '').startswith('urn:factur-x.eu:1p0') else {}">${format(this.invoice.amount_to_pay * this.type_sign, 'f')}</ram:DuePayableAmount>
</ram:SpecifiedTradeSettlementHeaderMonetarySummation>
</ram:ApplicableHeaderTradeSettlement>
</rsm:SupplyChainTradeTransaction>