génération XML et emplate
This commit is contained in:
225
generate_facturx_jinja2.py
Normal file
225
generate_facturx_jinja2.py
Normal file
@@ -0,0 +1,225 @@
|
||||
"""
|
||||
Générateur Factur-X BASIC via template Jinja2
|
||||
"""
|
||||
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List, Optional
|
||||
from datetime import date
|
||||
from collections import defaultdict
|
||||
|
||||
from fastapi.templating import Jinja2Templates
|
||||
|
||||
templates = Jinja2Templates(directory="templates")
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# Structures de données (identiques au générateur lxml)
|
||||
# ─────────────────────────────────────────────
|
||||
@dataclass
|
||||
class Address:
|
||||
line1: str
|
||||
city: str
|
||||
postcode: str
|
||||
country_code: str
|
||||
line2: Optional[str] = None
|
||||
|
||||
|
||||
@dataclass
|
||||
class Party:
|
||||
name: str
|
||||
vat_id: Optional[str] = None
|
||||
siret: Optional[str] = None
|
||||
address: Optional[Address] = None
|
||||
|
||||
|
||||
@dataclass
|
||||
class InvoiceLine:
|
||||
line_id: str
|
||||
description: str
|
||||
quantity: float
|
||||
unit_code: str
|
||||
unit_price: float
|
||||
vat_rate: float
|
||||
vat_category: str = "S"
|
||||
|
||||
# Raison d'exonération par catégorie TVA
|
||||
EXEMPTION_REASONS = {
|
||||
"E": "TVA non applicable, art. 293 B du CGI",
|
||||
"Z": "Taux zéro",
|
||||
"AE": "Autoliquidation",
|
||||
"K": "Exonération intracommunautaire",
|
||||
"G": "Exportation hors UE",
|
||||
}
|
||||
|
||||
@dataclass
|
||||
class TaxLine:
|
||||
rate: float
|
||||
category: str
|
||||
base_amount: float
|
||||
amount: float
|
||||
exemption_reason: Optional[str] = None
|
||||
|
||||
@dataclass
|
||||
class Invoice:
|
||||
number: str
|
||||
issue_date: date
|
||||
currency: str
|
||||
seller: Party
|
||||
buyer: Party
|
||||
lines: List[InvoiceLine] = field(default_factory=list)
|
||||
due_date: Optional[date] = None
|
||||
type_code: str = "380"
|
||||
payment_means_code: str = "30"
|
||||
iban: Optional[str] = None
|
||||
payment_reference: Optional[str] = None
|
||||
note: Optional[str] = None
|
||||
|
||||
# Calculés automatiquement (voir compute())
|
||||
tax_lines: List[TaxLine] = field(default_factory=list)
|
||||
total_ht: float = 0.0
|
||||
total_tva: float = 0.0
|
||||
total_ttc: float = 0.0
|
||||
|
||||
def compute(self):
|
||||
"""Calcule les totaux et les lignes de TVA depuis les lignes de facture."""
|
||||
tax_groups = defaultdict(float)
|
||||
self.total_ht = 0.0
|
||||
|
||||
for ln in self.lines:
|
||||
net = round(ln.quantity * ln.unit_price, 2)
|
||||
self.total_ht += net
|
||||
tax_groups[(ln.vat_rate, ln.vat_category)] += net
|
||||
|
||||
self.total_ht = round(self.total_ht, 2)
|
||||
self.tax_lines = []
|
||||
self.total_tva = 0.0
|
||||
|
||||
for (rate, category), base in tax_groups.items():
|
||||
base = round(base, 2)
|
||||
amount = round(base * rate / 100, 2)
|
||||
self.total_tva += amount
|
||||
self.tax_lines.append(TaxLine(
|
||||
rate=rate,
|
||||
category=category,
|
||||
base_amount=base,
|
||||
amount=amount,
|
||||
# Raison d'exonération automatique si catégorie != "S" (standard)
|
||||
exemption_reason=EXEMPTION_REASONS.get(category) if category != "S" else None,
|
||||
))
|
||||
|
||||
self.total_tva = round(self.total_tva, 2)
|
||||
self.total_ttc = round(self.total_ht + self.total_tva, 2)
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# Filtres Jinja2 personnalisés
|
||||
# ─────────────────────────────────────────────
|
||||
def filter_amount(value: float) -> str:
|
||||
return f"{float(value):.2f}"
|
||||
|
||||
|
||||
def filter_datefmt(value: date) -> str:
|
||||
return value.strftime("%Y%m%d")
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# Générateur
|
||||
# ─────────────────────────────────────────────
|
||||
def generate_facturx_xml(invoice: Invoice, template_dir: str = ".", output_file: str = "factur-x.xml") -> str:
|
||||
"""
|
||||
Génère le XML Factur-X BASIC depuis le template Jinja2.
|
||||
Retourne le XML sous forme de chaîne et l'écrit dans output_file.
|
||||
"""
|
||||
# Calcul des totaux
|
||||
invoice.compute()
|
||||
|
||||
# Environnement Jinja2
|
||||
env = Environment(
|
||||
loader=FileSystemLoader(template_dir),
|
||||
autoescape=False, # XML géré manuellement
|
||||
trim_blocks=True, # supprime le \n après les blocs {% %}
|
||||
lstrip_blocks=True, # supprime les espaces avant {% %}
|
||||
)
|
||||
env.filters["amount"] = filter_amount
|
||||
env.filters["datefmt"] = filter_datefmt
|
||||
|
||||
template = env.get_template("templates/xml/factur-x-basic.xml.j2")
|
||||
xml_str = template.render(
|
||||
invoice=invoice,
|
||||
seller=invoice.seller,
|
||||
buyer=invoice.buyer,
|
||||
)
|
||||
|
||||
with open(output_file, "w", encoding="utf-8") as f:
|
||||
f.write(xml_str)
|
||||
|
||||
return xml_str
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# Exemple d'utilisation
|
||||
# ─────────────────────────────────────────────
|
||||
if __name__ == "__main__":
|
||||
|
||||
invoice = Invoice(
|
||||
number="FA-2024-00123",
|
||||
issue_date=date(2024, 3, 15),
|
||||
due_date=date(2024, 4, 14),
|
||||
currency="EUR",
|
||||
type_code="380",
|
||||
note="Facture relative au contrat n°CTR-2024-01",
|
||||
|
||||
seller=Party(
|
||||
name="Ma Société SAS",
|
||||
# vat_id absent : pas de numéro TVA en franchise (art. 293 B CGI)
|
||||
siret="12345678900012",
|
||||
address=Address(
|
||||
line1="10 rue de la Paix",
|
||||
city="Paris",
|
||||
postcode="75001",
|
||||
country_code="FR",
|
||||
),
|
||||
),
|
||||
|
||||
buyer=Party(
|
||||
name="Client SARL",
|
||||
vat_id="FR98765432100",
|
||||
siret="98765432100011",
|
||||
address=Address(
|
||||
line1="5 avenue des Fleurs",
|
||||
city="Lyon",
|
||||
postcode="69001",
|
||||
country_code="FR",
|
||||
),
|
||||
),
|
||||
|
||||
payment_means_code="30",
|
||||
iban="FR7612345678901234567890189",
|
||||
payment_reference="CTR-2024-01",
|
||||
)
|
||||
|
||||
# Ajout des lignes — franchise de TVA (art. 293 B du CGI)
|
||||
# Utiliser vat_category="E" et vat_rate=0.0
|
||||
articles = [
|
||||
{"desc": "Développement logiciel - Sprint 1", "qty": 10, "unit": "HUR", "prix": 150.0, "tva": 0.0, "cat": "E"},
|
||||
{"desc": "Licence logicielle annuelle", "qty": 1, "unit": "C62", "prix": 500.0, "tva": 0.0, "cat": "E"},
|
||||
{"desc": "Formation utilisateurs", "qty": 2, "unit": "HUR", "prix": 200.0, "tva": 0.0, "cat": "E"},
|
||||
]
|
||||
|
||||
for i, art in enumerate(articles, start=1):
|
||||
invoice.lines.append(InvoiceLine(
|
||||
line_id=str(i),
|
||||
description=art["desc"],
|
||||
quantity=art["qty"],
|
||||
unit_code=art["unit"],
|
||||
unit_price=art["prix"],
|
||||
vat_rate=art["tva"],
|
||||
vat_category=art["cat"], # "E" = exonéré (franchise TVA)
|
||||
))
|
||||
|
||||
xml = generate_facturx_xml(invoice, template_dir=".", output_file="factur-x.xml")
|
||||
|
||||
print(f"✅ Fichier généré : factur-x.xml")
|
||||
print(f" Total HT : {invoice.total_ht:.2f} €")
|
||||
print(f" TVA 20% : {invoice.total_tva:.2f} €")
|
||||
print(f" Total TTC : {invoice.total_ttc:.2f} €")
|
||||
176
templates/xml/factur-x-basic.xml.j2
Normal file
176
templates/xml/factur-x-basic.xml.j2
Normal file
@@ -0,0 +1,176 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<rsm:CrossIndustryInvoice
|
||||
xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100"
|
||||
xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"
|
||||
xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"
|
||||
xmlns:qdt="urn:un:unece:uncefact:data:standard:QualifiedDataType:100"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
|
||||
<!-- 1. CONTEXTE -->
|
||||
<rsm:ExchangedDocumentContext>
|
||||
<ram:GuidelineSpecifiedDocumentContextParameter>
|
||||
<ram:ID>urn:cen.eu:en16931:2017#compliant#urn:factur-x.eu:1p0:basic</ram:ID>
|
||||
</ram:GuidelineSpecifiedDocumentContextParameter>
|
||||
</rsm:ExchangedDocumentContext>
|
||||
|
||||
<!-- 2. EN-TÊTE FACTURE -->
|
||||
<rsm:ExchangedDocument>
|
||||
<ram:ID>{{ invoice.number }}</ram:ID>
|
||||
<ram:TypeCode>{{ invoice.type_code }}</ram:TypeCode>
|
||||
<ram:IssueDateTime>
|
||||
<udt:DateTimeString format="102">{{ invoice.issue_date | datefmt }}</udt:DateTimeString>
|
||||
</ram:IssueDateTime>
|
||||
{% if invoice.note %}
|
||||
<ram:IncludedNote>
|
||||
<ram:Content>{{ invoice.note }}</ram:Content>
|
||||
</ram:IncludedNote>
|
||||
{% endif %}
|
||||
</rsm:ExchangedDocument>
|
||||
|
||||
<!-- 3. TRANSACTION COMMERCIALE -->
|
||||
<rsm:SupplyChainTradeTransaction>
|
||||
|
||||
<!-- 3a. Lignes de facture -->
|
||||
{% for line in invoice.lines %}
|
||||
<ram:IncludedSupplyChainTradeLineItem>
|
||||
<ram:AssociatedDocumentLineDocument>
|
||||
<ram:LineID>{{ line.line_id }}</ram:LineID>
|
||||
</ram:AssociatedDocumentLineDocument>
|
||||
<ram:SpecifiedTradeProduct>
|
||||
<ram:Name>{{ line.description }}</ram:Name>
|
||||
</ram:SpecifiedTradeProduct>
|
||||
<ram:SpecifiedLineTradeAgreement>
|
||||
<ram:NetPriceProductTradePrice>
|
||||
<ram:ChargeAmount>{{ line.unit_price | amount }}</ram:ChargeAmount>
|
||||
</ram:NetPriceProductTradePrice>
|
||||
</ram:SpecifiedLineTradeAgreement>
|
||||
<ram:SpecifiedLineTradeDelivery>
|
||||
<ram:BilledQuantity unitCode="{{ line.unit_code }}">{{ line.quantity | amount }}</ram:BilledQuantity>
|
||||
</ram:SpecifiedLineTradeDelivery>
|
||||
<ram:SpecifiedLineTradeSettlement>
|
||||
<ram:ApplicableTradeTax>
|
||||
<ram:TypeCode>VAT</ram:TypeCode>
|
||||
<ram:CategoryCode>{{ line.vat_category }}</ram:CategoryCode>
|
||||
<ram:RateApplicablePercent>{{ line.vat_rate | amount }}</ram:RateApplicablePercent>
|
||||
</ram:ApplicableTradeTax>
|
||||
<ram:SpecifiedTradeSettlementLineMonetarySummation>
|
||||
<ram:LineTotalAmount>{{ (line.quantity * line.unit_price) | amount }}</ram:LineTotalAmount>
|
||||
</ram:SpecifiedTradeSettlementLineMonetarySummation>
|
||||
</ram:SpecifiedLineTradeSettlement>
|
||||
</ram:IncludedSupplyChainTradeLineItem>
|
||||
{% endfor %}
|
||||
|
||||
<!-- 3b. Accord commercial -->
|
||||
<ram:ApplicableHeaderTradeAgreement>
|
||||
|
||||
<ram:SellerTradeParty>
|
||||
<ram:Name>{{ seller.name }}</ram:Name>
|
||||
{% if seller.siret %}
|
||||
<ram:SpecifiedLegalOrganization>
|
||||
<ram:ID schemeID="0002">{{ seller.siret }}</ram:ID>
|
||||
</ram:SpecifiedLegalOrganization>
|
||||
{% endif %}
|
||||
{% if seller.address %}
|
||||
<ram:PostalTradeAddress>
|
||||
<ram:PostcodeCode>{{ seller.address.postcode }}</ram:PostcodeCode>
|
||||
<ram:LineOne>{{ seller.address.line1 }}</ram:LineOne>
|
||||
{% if seller.address.line2 %}
|
||||
<ram:LineTwo>{{ seller.address.line2 }}</ram:LineTwo>
|
||||
{% endif %}
|
||||
<ram:CityName>{{ seller.address.city }}</ram:CityName>
|
||||
<ram:CountryID>{{ seller.address.country_code }}</ram:CountryID>
|
||||
</ram:PostalTradeAddress>
|
||||
{% endif %}
|
||||
{% if seller.vat_id %}
|
||||
<ram:SpecifiedTaxRegistration>
|
||||
<ram:ID schemeID="VA">{{ seller.vat_id }}</ram:ID>
|
||||
</ram:SpecifiedTaxRegistration>
|
||||
{% elif seller.siret %}
|
||||
{# Franchise TVA (art. 293 B CGI) : pas de n° TVA, on utilise le SIRET avec schemeID="FC" #}
|
||||
<ram:SpecifiedTaxRegistration>
|
||||
<ram:ID schemeID="FC">{{ seller.siret }}</ram:ID>
|
||||
</ram:SpecifiedTaxRegistration>
|
||||
{% endif %}
|
||||
</ram:SellerTradeParty>
|
||||
|
||||
<ram:BuyerTradeParty>
|
||||
<ram:Name>{{ buyer.name }}</ram:Name>
|
||||
{% if buyer.siret %}
|
||||
<ram:SpecifiedLegalOrganization>
|
||||
<ram:ID schemeID="0002">{{ buyer.siret }}</ram:ID>
|
||||
</ram:SpecifiedLegalOrganization>
|
||||
{% endif %}
|
||||
{% if buyer.address %}
|
||||
<ram:PostalTradeAddress>
|
||||
<ram:PostcodeCode>{{ buyer.address.postcode }}</ram:PostcodeCode>
|
||||
<ram:LineOne>{{ buyer.address.line1 }}</ram:LineOne>
|
||||
{% if buyer.address.line2 %}
|
||||
<ram:LineTwo>{{ buyer.address.line2 }}</ram:LineTwo>
|
||||
{% endif %}
|
||||
<ram:CityName>{{ buyer.address.city }}</ram:CityName>
|
||||
<ram:CountryID>{{ buyer.address.country_code }}</ram:CountryID>
|
||||
</ram:PostalTradeAddress>
|
||||
{% endif %}
|
||||
</ram:BuyerTradeParty>
|
||||
|
||||
{% if invoice.payment_reference %}
|
||||
<ram:BuyerOrderReferencedDocument>
|
||||
<ram:IssuerAssignedID>{{ invoice.payment_reference }}</ram:IssuerAssignedID>
|
||||
</ram:BuyerOrderReferencedDocument>
|
||||
{% endif %}
|
||||
|
||||
</ram:ApplicableHeaderTradeAgreement>
|
||||
|
||||
<!-- 3c. Livraison -->
|
||||
<ram:ApplicableHeaderTradeDelivery>
|
||||
<ram:ShipToTradeParty>
|
||||
<ram:Name>{{ buyer.name }}</ram:Name>
|
||||
</ram:ShipToTradeParty>
|
||||
</ram:ApplicableHeaderTradeDelivery>
|
||||
|
||||
<!-- 3d. Règlement -->
|
||||
<ram:ApplicableHeaderTradeSettlement>
|
||||
<ram:InvoiceCurrencyCode>{{ invoice.currency }}</ram:InvoiceCurrencyCode>
|
||||
|
||||
<ram:SpecifiedTradeSettlementPaymentMeans>
|
||||
<ram:TypeCode>{{ invoice.payment_means_code }}</ram:TypeCode>
|
||||
{% if invoice.iban %}
|
||||
<ram:PayeePartyCreditorFinancialAccount>
|
||||
<ram:IBANID>{{ invoice.iban }}</ram:IBANID>
|
||||
</ram:PayeePartyCreditorFinancialAccount>
|
||||
{% endif %}
|
||||
</ram:SpecifiedTradeSettlementPaymentMeans>
|
||||
|
||||
{% for tax in invoice.tax_lines %}
|
||||
<ram:ApplicableTradeTax>
|
||||
<ram:CalculatedAmount>{{ tax.amount | amount }}</ram:CalculatedAmount>
|
||||
<ram:TypeCode>VAT</ram:TypeCode>
|
||||
{% if tax.exemption_reason %}
|
||||
<ram:ExemptionReason>{{ tax.exemption_reason }}</ram:ExemptionReason>
|
||||
{% endif %}
|
||||
<ram:BasisAmount>{{ tax.base_amount | amount }}</ram:BasisAmount>
|
||||
<ram:CategoryCode>{{ tax.category }}</ram:CategoryCode>
|
||||
<ram:RateApplicablePercent>{{ tax.rate | amount }}</ram:RateApplicablePercent>
|
||||
</ram:ApplicableTradeTax>
|
||||
{% endfor %}
|
||||
|
||||
{% if invoice.due_date %}
|
||||
<ram:SpecifiedTradePaymentTerms>
|
||||
<ram:DueDateDateTime>
|
||||
<udt:DateTimeString format="102">{{ invoice.due_date | datefmt }}</udt:DateTimeString>
|
||||
</ram:DueDateDateTime>
|
||||
</ram:SpecifiedTradePaymentTerms>
|
||||
{% endif %}
|
||||
|
||||
<ram:SpecifiedTradeSettlementHeaderMonetarySummation>
|
||||
<ram:LineTotalAmount>{{ invoice.total_ht | amount }}</ram:LineTotalAmount>
|
||||
<ram:TaxBasisTotalAmount>{{ invoice.total_ht | amount }}</ram:TaxBasisTotalAmount>
|
||||
<ram:TaxTotalAmount currencyID="{{ invoice.currency }}">{{ invoice.total_tva | amount }}</ram:TaxTotalAmount>
|
||||
<ram:GrandTotalAmount>{{ invoice.total_ttc | amount }}</ram:GrandTotalAmount>
|
||||
<ram:DuePayableAmount>{{ invoice.total_ttc | amount }}</ram:DuePayableAmount>
|
||||
</ram:SpecifiedTradeSettlementHeaderMonetarySummation>
|
||||
|
||||
</ram:ApplicableHeaderTradeSettlement>
|
||||
|
||||
</rsm:SupplyChainTradeTransaction>
|
||||
</rsm:CrossIndustryInvoice>
|
||||
180
templates/xml/factur-x-basic.xml.j2.back
Normal file
180
templates/xml/factur-x-basic.xml.j2.back
Normal file
@@ -0,0 +1,180 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<rsm:CrossIndustryInvoice
|
||||
xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100"
|
||||
xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"
|
||||
xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"
|
||||
xmlns:qdt="urn:un:unece:uncefact:data:standard:QualifiedDataType:100"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
|
||||
<!-- 1. CONTEXTE -->
|
||||
<rsm:ExchangedDocumentContext>
|
||||
<ram:GuidelineSpecifiedDocumentContextParameter>
|
||||
<ram:ID>urn:cen.eu:en16931:2017#compliant#urn:factur-x.eu:1p0:basic</ram:ID>
|
||||
</ram:GuidelineSpecifiedDocumentContextParameter>
|
||||
</rsm:ExchangedDocumentContext>
|
||||
|
||||
<!-- 2. EN-TÊTE FACTURE -->
|
||||
<rsm:ExchangedDocument>
|
||||
<ram:ID>{{ invoice.number }}</ram:ID>
|
||||
<ram:TypeCode>{{ invoice.type_code }}</ram:TypeCode>
|
||||
<ram:IssueDateTime>
|
||||
<udt:DateTimeString format="102">{{ invoice.issue_date | datefmt }}</udt:DateTimeString>
|
||||
</ram:IssueDateTime>
|
||||
{% if invoice.note %}
|
||||
<ram:IncludedNote>
|
||||
<ram:Content>{{ invoice.note }}</ram:Content>
|
||||
</ram:IncludedNote>
|
||||
{% endif %}
|
||||
</rsm:ExchangedDocument>
|
||||
|
||||
<!-- 3. TRANSACTION COMMERCIALE -->
|
||||
<rsm:SupplyChainTradeTransaction>
|
||||
|
||||
<!-- 3a. Lignes de facture -->
|
||||
{% for line in invoice.lines %}
|
||||
<ram:IncludedSupplyChainTradeLineItem>
|
||||
<ram:AssociatedDocumentLineDocument>
|
||||
<ram:LineID>{{ line.line_id }}</ram:LineID>
|
||||
</ram:AssociatedDocumentLineDocument>
|
||||
<ram:SpecifiedTradeProduct>
|
||||
<ram:Name>{{ line.description }}</ram:Name>
|
||||
</ram:SpecifiedTradeProduct>
|
||||
<ram:SpecifiedLineTradeAgreement>
|
||||
<ram:NetPriceProductTradePrice>
|
||||
<ram:ChargeAmount>{{ line.unit_price | amount }}</ram:ChargeAmount>
|
||||
</ram:NetPriceProductTradePrice>
|
||||
</ram:SpecifiedLineTradeAgreement>
|
||||
<ram:SpecifiedLineTradeDelivery>
|
||||
<ram:BilledQuantity unitCode="{{ line.unit_code }}">{{ line.quantity | amount }}</ram:BilledQuantity>
|
||||
</ram:SpecifiedLineTradeDelivery>
|
||||
<ram:SpecifiedLineTradeSettlement>
|
||||
<ram:ApplicableTradeTax>
|
||||
<ram:TypeCode>VAT</ram:TypeCode>
|
||||
<ram:CategoryCode>{{ line.vat_category }}</ram:CategoryCode>
|
||||
<ram:RateApplicablePercent>{{ line.vat_rate | amount }}</ram:RateApplicablePercent>
|
||||
</ram:ApplicableTradeTax>
|
||||
<ram:SpecifiedTradeSettlementLineMonetarySummation>
|
||||
<ram:LineTotalAmount>{{ (line.quantity * line.unit_price) | amount }}</ram:LineTotalAmount>
|
||||
</ram:SpecifiedTradeSettlementLineMonetarySummation>
|
||||
</ram:SpecifiedLineTradeSettlement>
|
||||
</ram:IncludedSupplyChainTradeLineItem>
|
||||
{% endfor %}
|
||||
|
||||
<!-- 3b. Accord commercial -->
|
||||
<ram:ApplicableHeaderTradeAgreement>
|
||||
|
||||
<ram:SellerTradeParty>
|
||||
<ram:Name>{{ seller.name }}</ram:Name>
|
||||
{% if seller.siret %}
|
||||
<ram:SpecifiedLegalOrganization>
|
||||
<ram:ID schemeID="0002">{{ seller.siret }}</ram:ID>
|
||||
</ram:SpecifiedLegalOrganization>
|
||||
{% endif %}
|
||||
{% if seller.address %}
|
||||
<ram:PostalTradeAddress>
|
||||
<ram:PostcodeCode>{{ seller.address.postcode }}</ram:PostcodeCode>
|
||||
<ram:LineOne>{{ seller.address.line1 }}</ram:LineOne>
|
||||
{% if seller.address.line2 %}
|
||||
<ram:LineTwo>{{ seller.address.line2 }}</ram:LineTwo>
|
||||
{% endif %}
|
||||
<ram:CityName>{{ seller.address.city }}</ram:CityName>
|
||||
<ram:CountryID>{{ seller.address.country_code }}</ram:CountryID>
|
||||
</ram:PostalTradeAddress>
|
||||
{% endif %}
|
||||
{% if seller.vat_id %}
|
||||
<ram:SpecifiedTaxRegistration>
|
||||
<ram:ID schemeID="VA">{{ seller.vat_id }}</ram:ID>
|
||||
</ram:SpecifiedTaxRegistration>
|
||||
{% endif %}
|
||||
</ram:SellerTradeParty>
|
||||
|
||||
<ram:BuyerTradeParty>
|
||||
<ram:Name>{{ buyer.name }}</ram:Name>
|
||||
{% if buyer.siret %}
|
||||
<ram:SpecifiedLegalOrganization>
|
||||
<ram:ID schemeID="0002">{{ buyer.siret }}</ram:ID>
|
||||
</ram:SpecifiedLegalOrganization>
|
||||
{% endif %}
|
||||
{% if buyer.address %}
|
||||
<ram:PostalTradeAddress>
|
||||
<ram:PostcodeCode>{{ buyer.address.postcode }}</ram:PostcodeCode>
|
||||
<ram:LineOne>{{ buyer.address.line1 }}</ram:LineOne>
|
||||
{% if buyer.address.line2 %}
|
||||
<ram:LineTwo>{{ buyer.address.line2 }}</ram:LineTwo>
|
||||
{% endif %}
|
||||
<ram:CityName>{{ buyer.address.city }}</ram:CityName>
|
||||
<ram:CountryID>{{ buyer.address.country_code }}</ram:CountryID>
|
||||
</ram:PostalTradeAddress>
|
||||
{% endif %}
|
||||
</ram:BuyerTradeParty>
|
||||
|
||||
{% if invoice.payment_reference %}
|
||||
<ram:BuyerOrderReferencedDocument>
|
||||
<ram:IssuerAssignedID>{{ invoice.payment_reference }}</ram:IssuerAssignedID>
|
||||
</ram:BuyerOrderReferencedDocument>
|
||||
{% endif %}
|
||||
|
||||
</ram:ApplicableHeaderTradeAgreement>
|
||||
|
||||
<!-- 3c. Livraison -->
|
||||
<ram:ApplicableHeaderTradeDelivery>
|
||||
<ram:ShipToTradeParty>
|
||||
<ram:Name>{{ buyer.name }}</ram:Name>
|
||||
</ram:ShipToTradeParty>
|
||||
</ram:ApplicableHeaderTradeDelivery>
|
||||
|
||||
<!-- 3d. Règlement -->
|
||||
<ram:ApplicableHeaderTradeSettlement>
|
||||
<ram:InvoiceCurrencyCode>{{ invoice.currency }}</ram:InvoiceCurrencyCode>
|
||||
|
||||
<ram:SpecifiedTradeSettlementPaymentMeans>
|
||||
<ram:TypeCode>{{ invoice.payment_means_code }}</ram:TypeCode>
|
||||
{% if invoice.iban %}
|
||||
<ram:PayeePartyCreditorFinancialAccount>
|
||||
<ram:IBANID>{{ invoice.iban }}</ram:IBANID>
|
||||
</ram:PayeePartyCreditorFinancialAccount>
|
||||
{% endif %}
|
||||
</ram:SpecifiedTradeSettlementPaymentMeans>
|
||||
|
||||
{% for tax in invoice.tax_lines %}
|
||||
<ram:ApplicableTradeTax>
|
||||
<ram:CalculatedAmount>{{ tax.amount | amount }}</ram:CalculatedAmount>
|
||||
<ram:TypeCode>VAT</ram:TypeCode>
|
||||
{% if tax.exemption_reason %}
|
||||
<ram:ExemptionReason>{{ tax.exemption_reason }}</ram:ExemptionReason>
|
||||
{% endif %}
|
||||
<ram:BasisAmount>{{ tax.base_amount | amount }}</ram:BasisAmount>
|
||||
<ram:CategoryCode>{{ tax.category }}</ram:CategoryCode>
|
||||
<ram:RateApplicablePercent>{{ tax.rate | amount }}</ram:RateApplicablePercent>
|
||||
</ram:ApplicableTradeTax>
|
||||
|
||||
|
||||
<ram:ApplicableTradeTax>
|
||||
<ram:CalculatedAmount>{{ tax.amount | amount }}</ram:CalculatedAmount>
|
||||
<ram:TypeCode>VAT</ram:TypeCode>
|
||||
<ram:BasisAmount>{{ tax.base_amount | amount }}</ram:BasisAmount>
|
||||
<ram:CategoryCode>{{ tax.category }}</ram:CategoryCode>
|
||||
<ram:RateApplicablePercent>{{ tax.rate | amount }}</ram:RateApplicablePercent>
|
||||
</ram:ApplicableTradeTax>
|
||||
{% endfor %}
|
||||
|
||||
{% if invoice.due_date %}
|
||||
<ram:SpecifiedTradePaymentTerms>
|
||||
<ram:DueDateDateTime>
|
||||
<udt:DateTimeString format="102">{{ invoice.due_date | datefmt }}</udt:DateTimeString>
|
||||
</ram:DueDateDateTime>
|
||||
</ram:SpecifiedTradePaymentTerms>
|
||||
{% endif %}
|
||||
|
||||
<ram:SpecifiedTradeSettlementHeaderMonetarySummation>
|
||||
<ram:LineTotalAmount>{{ invoice.total_ht | amount }}</ram:LineTotalAmount>
|
||||
<ram:TaxBasisTotalAmount>{{ invoice.total_ht | amount }}</ram:TaxBasisTotalAmount>
|
||||
<ram:TaxTotalAmount currencyID="{{ invoice.currency }}">{{ invoice.total_tva | amount }}</ram:TaxTotalAmount>
|
||||
<ram:GrandTotalAmount>{{ invoice.total_ttc | amount }}</ram:GrandTotalAmount>
|
||||
<ram:DuePayableAmount>{{ invoice.total_ttc | amount }}</ram:DuePayableAmount>
|
||||
</ram:SpecifiedTradeSettlementHeaderMonetarySummation>
|
||||
|
||||
</ram:ApplicableHeaderTradeSettlement>
|
||||
|
||||
</rsm:SupplyChainTradeTransaction>
|
||||
</rsm:CrossIndustryInvoice>
|
||||
Reference in New Issue
Block a user