Files
tryton/modules/edocument_uncefact/template/16B-CII/CrossIndustryInvoice.xml
T
Cédric Krier b5a32b6e65 Set format attribute for DateTimeString in UN/CEFACT 16B-CII
Closes #15004
(grafted from 9b3043220a6da6f9d31dd70f1b1e348b3dc425fe)

--HG--
branch : 8.0
2026-08-11 12:05:48 +02:00

172 lines
12 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<rsm:CrossIndustryInvoice
xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100"
xmlns:qdt="urn:un:unece:uncefact:data:standard:QualifiedDataType:100"
xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"
xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"
xmlns:py="http://genshi.edgewall.org/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<py:def function="DateTime(value)">
<udt:DateTimeString format="102">${value.strftime('%Y%m%d')}</udt:DateTimeString>
</py:def>
<py:def function="TradeParty(party, address=None, tax_identifier=None)">
<ram:Name>${party.name}</ram:Name>
<ram:SpecifiedLegalOrganization>
<py:for each="id, attrs in this.party_legal_ids(party, address)">
<ram:ID py:attrs="attrs">${id}</ram:ID>
</py:for>
</ram:SpecifiedLegalOrganization>
<ram:PostalTradeAddress py:if="address">${TradeAddress(address)}</ram:PostalTradeAddress>
<ram:SpecifiedTaxRegistration py:if="tax_identifier and tax_identifier.type == 'eu_vat'">
<ram:ID schemeID='VA'>${tax_identifier.code_compact}</ram:ID>
</ram:SpecifiedTaxRegistration>
</py:def>
<py:def function="TradeAddress(address)">
<ram:PostcodeCode py:if="address.postal_code">${address.postal_code}</ram:PostcodeCode>
<ram:BuildingName py:if="address.building_name">${address.building_name}</ram:BuildingName>
<py:with vars="lines = (address.street_unstructured or '').splitlines()">
<ram:LineOne py:if="len(lines) > 0">${lines[0]}</ram:LineOne>
<ram:LineTwo py:if="len(lines) > 1">${lines[1]}</ram:LineTwo>
<ram:LineThree py:if="len(lines) > 2">${lines[2]}</ram:LineThree>
<ram:LineFour py:if="len(lines) > 3">${lines[3]}</ram:LineFour>
<ram:LineFive py:if="len(lines) > 4">${lines[4]}</ram:LineFive>
</py:with>
<ram:StreetName py:if="address.street_name">${address.street_name}</ram:StreetName>
<ram:CityName py:if="address.city">${address.city}</ram:CityName>
<ram:CountryID py:if="address.country">${address.country.code}</ram:CountryID>
<ram:CountryName py:if="address.country">${address.country.name}</ram:CountryName>
<ram:CountrySubDivisionID py:if="address.subdivision">${address.subdivision.code}</ram:CountrySubDivisionID>
<ram:CountrySubDivisionName py:if="address.subdivision">${address.subdivision.name}</ram:CountrySubDivisionName>
<ram:BuildingNumber py:if="address.building_number">${address.building_number}</ram:BuildingNumber>
</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}">${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">${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>
</py:def>
<rsm:ExchangedDocumentContext>
</rsm:ExchangedDocumentContext>
<rsm:ExchangedDocument>
<ram:ID>${this.invoice.number}</ram:ID>
<ram:TypeCode>${this.type_code}</ram:TypeCode>
<ram:IssueDateTime>
${DateTime(this.invoice.invoice_date)}
</ram:IssueDateTime>
</rsm:ExchangedDocument>
<rsm:SupplyChainTradeTransaction>
<ram:IncludedSupplyChainTradeLineItem py:for="line_id, line in enumerate(this.lines, 1)">
<ram:AssociatedDocumentLineDocument>
<ram:LineID>${line_id}</ram:LineID>
</ram:AssociatedDocumentLineDocument>
<ram:SpecifiedTradeProduct py:if="line.product">
<ram:ID py:if="line.product.code">${line.product.code}</ram:ID>
<ram:Name>${line.product.name}</ram:Name>
<ram:Description py:if="line.description">${line.description}</ram:Description>
</ram:SpecifiedTradeProduct>
<ram:SpecifiedLineTradeAgreement>
<ram:NetPriceProductTradePrice>
<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>
<ram:BilledQuantity py:attrs="{'unitCode': line.unit.unece_code} if line.unit and line.unit.unece_code else {}">${format(Decimal(str(line.quantity * this.type_sign)), '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}">${format(line.amount.normalize(), 'f')}</ram:LineTotalAmount>
</ram:SpecifiedTradeSettlementLineMonetarySummation>
</ram:SpecifiedLineTradeSettlement>
</ram:IncludedSupplyChainTradeLineItem>
<ram:ApplicableHeaderTradeAgreement>
<ram:SellerTradeParty>
${TradeParty(this.seller_trade_party, this.seller_trade_address, this.seller_trade_tax_identifier)}
</ram:SellerTradeParty>
<ram:BuyerTradeParty>
${TradeParty(this.buyer_trade_party, this.buyer_trade_address, this.buyer_trade_tax_identifier)}
</ram:BuyerTradeParty>
<ram:SellerOrderReferencedDocument py:if="this.invoice.type == 'in'">
<ram:IssuerAssignedID>${this.invoice.reference}</ram:IssuerAssignedID>
</ram:SellerOrderReferencedDocument>
<ram:BuyerOrderReferencedDocument py:if="this.invoice.type == 'out'">
<ram:IssuerAssignedID>${this.invoice.reference}</ram:IssuerAssignedID>
</ram:BuyerOrderReferencedDocument>
</ram:ApplicableHeaderTradeAgreement>
<ram:ApplicableHeaderTradeDelivery>
<ram:ShipToTradeParty py:if="this.ship_to_trade_party">
${TradeParty(this.ship_to_trade_party, this.ship_to_trade_address)}
</ram:ShipToTradeParty>
<ram:ShipFromTradeParty py:if="this.ship_from_trade_party">
${TradeParty(this.ship_from_trade_party, this.ship_from_trade_address)}
</ram:ShipFromTradeParty>
</ram:ApplicableHeaderTradeDelivery>
<ram:ApplicableHeaderTradeSettlement>
<ram:PaymentReference>${this.payment_reference}</ram:PaymentReference>
<ram:InvoiceCurrencyCode>${this.invoice.currency.code}</ram:InvoiceCurrencyCode>
<ram:InvoiceDateTime>
${DateTime(this.invoice.invoice_date)}
</ram:InvoiceDateTime>
<py:choose test="len(this.invoice.payment_means)">
<py:when test="0">
<ram:SpecifiedTradeSettlementPaymentMeans>
<ram:TypeCode>1</ram:TypeCode> <!-- Instrument not defined -->
</ram:SpecifiedTradeSettlementPaymentMeans>
</py:when>
<py:otherwise>
<py:for each="payment_mean in this.invoice.payment_means">
<ram:SpecifiedTradeSettlementPaymentMeans py:if="payment_mean.unece_code">
<ram:TypeCode>${payment_mean.unece_code}</ram:TypeCode>
<ram:ID py:if="this.invoice.customer_payment_reference">${this.invoice.customer_payment_reference}</ram:ID>
<py:choose test="payment_mean.unece_code">
<py:when test="'42'">
<ram:PayeePartyCreditorFinancialAccount>
<udt:IBANID>${payment_mean.instrument.iban}</udt:IBANID>
</ram:PayeePartyCreditorFinancialAccount>
<ram:PayeeSpecifiedCreditorFinancialInstitution py:if="payment_mean.instrument.bank and payment_mean.instrument.bank.bic">
<udt:BICID>${payment_mean.instrument.bank.bic}</udt:BICID>
</ram:PayeeSpecifiedCreditorFinancialInstitution>
</py:when>
<py:when test="'59'">
<ram:PayerPartyDebtorFinancialAccount py:if="payment_mean.instrument.sepa_mandate">
<udt:IBANID>${payment_mean.instrument.account_number.number}</udt:IBANID>
<ram:PayerSpecifiedDebtorFinancialInstitution py:if="payment_mean.instrument.account_number.account.bank and payment_mean.instrument.account_number.account.bank.bic">
<udt:BICID>${payment_mean.instrument.account_number.account.bank.bic}</udt:BICID>
</ram:PayerSpecifiedDebtorFinancialInstitution>
</ram:PayerPartyDebtorFinancialAccount>
</py:when>
</py:choose>
</ram:SpecifiedTradeSettlementPaymentMeans>
</py:for>
</py:otherwise>
</py:choose>
<py:for each="tax in this.invoice.taxes">
${TradeTax(tax.tax, tax.amount, tax.base)}
</py:for>
<ram:SpecifiedTradePaymentTerms py:for="line in this.invoice.lines_to_pay">
<ram:Description py:if="this.invoice.payment_term and this.invoice.payment_term.description">${this.invoice.payment_term.description}</ram:Description>
<ram:DueDateDateTime>
${DateTime(line.maturity_date)}
</ram:DueDateDateTime>
<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}">${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>
</rsm:CrossIndustryInvoice>