Facture en devise étrangère
Une facture en GBP dont le montant de TVA est également indiqué en EUR – avec le taux de change et sa date. S’y ajoutent un représentant fiscal, un bénéficiaire du paiement distinct, une période de facturation, un acompte et des remises au niveau de la ligne.
La base est la facture d’exemple officielle
X07_01_Fremdwaehrung issue de la documentation
Factur-X / ZUGFeRD (jeu d’exemples FeRD, ZUGFeRD 2.5.0, profil
EXTENDED). Le code ci-dessous produit exactement ce document, champ par champ
et dans le même ordre.
Certains liens de cette page mènent à la documentation approfondie dans l’espace client et demandent une connexion.
C’est le plus exigeant des trois documents d’exemple : il réunit dans un seul fichier ce qui est autrement dispersé sur de nombreuses pages. Si vous construisez un document EXTENDED pour la première fois, la facture de marchandises étendue est le meilleur point de départ ; ici, il est question des cas particuliers.
Ce que montre cet exemple
- Deux devises : devise de facturation GBP (BT-5), devise comptable EUR (BT-6)
- Le montant de TVA deux fois – une fois par devise (BT-110 et BT-111) – plus le taux de change (BG-X-41)
- Représentant fiscal du vendeur (BG-11) et bénéficiaire du paiement distinct (BG-10)
- Remises au niveau de la ligne comme
SpecifiedTradeAllowanceCharge - Période de facturation (BT-73/BT-74) et acompte (BT-113)
1. En-tête de facture et les deux devises
La ligne décisive est invoice.TaxCurrency. Tous les montants du
document sont exprimés dans la devise de facturation BT-5, ici GBP ; la devise
comptable BT-6 ne concerne que le montant de TVA indiqué en supplément.
// BT-5 la devise de facturation est GBP – tous les montants sont dans CETTE devise.
FacturXInvoice invoice = FacturXInvoice.CreateInvoice(
invoiceNo: "47110815",
invoiceDate: new DateTime(2025, 12, 1),
currency: CurrencyCodes.GBP);
invoice.Type = InvoiceType.Invoice;
invoice.Name = "RECHNUNG"; // BT-X-2
invoice.BusinessProcess = "Beispielgeschäftsprozess"; // BT-23
// BT-6 : devise comptable. Dès qu'elle est définie et diffère de BT-5,
// l'EN 16931 attend le montant de TVA également dans cette devise.
invoice.TaxCurrency = CurrencyCodes.EUR;
' BT-5 la devise de facturation est GBP – tous les montants sont dans CETTE devise.
Dim invoice As FacturXInvoice = FacturXInvoice.CreateInvoice(
invoiceNo:="47110815",
invoiceDate:=New DateTime(2025, 12, 1),
currency:=CurrencyCodes.GBP)
invoice.Type = InvoiceType.Invoice
invoice.Name = "RECHNUNG" ' BT-X-2
invoice.BusinessProcess = "Beispielgeschäftsprozess" ' BT-23
' BT-6 : devise comptable. Dès qu'elle est définie et diffère de BT-5,
' l'EN 16931 attend le montant de TVA également dans cette devise.
invoice.TaxCurrency = CurrencyCodes.EUR
2. Notes en texte libre
Le code TXD (information fiscale) explique au lecteur humain pourquoi
deux devises apparaissent dans le document – un complément utile aux champs
structurés plus bas.
Les sauts de ligne et l’indentation à l’intérieur d’une note sont significatifs dans le XML. Les tabulations du premier appel ne sont pas décoratives – elles proviennent caractère par caractère du fichier de référence, et sans elles le contrôle croisé signale une différence.
// La première note est multiligne. Les sauts de ligne et l'indentation sont
// significatifs dans le XML – ce sont exactement les tabulations du fichier de référence.
invoice.AddNote("Mitglieder der Geschäftsleitung\n\t\t\t\tH. Meier Geschäftsführer"
+ "\n\t\t\t\tT. Müller Prokurist\n\t\t\t\tHRB Braunschweig 12345",
subjectCode: SubjectCodes.REG);
invoice.AddNote("Vom 17. Dezember 2025 bis 6. Januar 2026 haben wir Betriebsferien.",
subjectCode: SubjectCodes.AAI);
// TXD = information fiscale. Explique au lecteur pourquoi deux devises apparaissent.
invoice.AddNote("Aus konzern-internen Gründen wird der Steuerbetrag sowohl in der "
+ "Rechungswährung (EUR) als auch in der Buchwährung (GBP) ausgegeben.",
subjectCode: SubjectCodes.TXD);
invoice.AddNote("ZUGFeRD vers 2.5.0 (Extended)", subjectCode: SubjectCodes.ACB);
invoice.AddNote("Dies ist ein Beispiel zur empfohlenen Darstellung von Fremdwährungsrechnungen",
subjectCode: SubjectCodes.ACB);
' La première note est multiligne. Les sauts de ligne et l'indentation sont
' significatifs dans le XML – ce sont exactement les tabulations du fichier de référence.
invoice.AddNote("Mitglieder der Geschäftsleitung" & vbLf & vbTab & vbTab & vbTab & vbTab &
"H. Meier Geschäftsführer" & vbLf & vbTab & vbTab & vbTab & vbTab &
"T. Müller Prokurist" & vbLf & vbTab & vbTab & vbTab & vbTab &
"HRB Braunschweig 12345",
subjectCode:=SubjectCodes.REG)
invoice.AddNote("Vom 17. Dezember 2025 bis 6. Januar 2026 haben wir Betriebsferien.",
subjectCode:=SubjectCodes.AAI)
' TXD = information fiscale. Explique au lecteur pourquoi deux devises apparaissent.
invoice.AddNote("Aus konzern-internen Gründen wird der Steuerbetrag sowohl in der " &
"Rechungswährung (EUR) als auch in der Buchwährung (GBP) ausgegeben.",
subjectCode:=SubjectCodes.TXD)
invoice.AddNote("ZUGFeRD vers 2.5.0 (Extended)", subjectCode:=SubjectCodes.ACB)
invoice.AddNote("Dies ist ein Beispiel zur empfohlenen Darstellung von Fremdwährungsrechnungen",
subjectCode:=SubjectCodes.ACB)
Les textes des notes, les noms de produits et les motifs de remise restent en allemand sur toute cette page : ce sont les données de la facture de référence officielle, et les traduire romprait la comparaison avec elle.
3. Vendeur et représentant fiscal
Le représentant fiscal (BG-11) est une partie à part entière avec son propre numéro de TVA – typique lorsqu’un fournisseur étranger opère sur le territoire par l’intermédiaire d’un représentant fiscal. Il se définit comme toute autre partie, mais son numéro fiscal passe par une méthode dédiée.
// Vendeur (BG-4) – sans interlocuteur et sans GLN.
invoice.SetSeller(
name: "Rohstoff AG Salzgitter",
postcode: "38226",
city: "Salzgitter",
street: "Marktstr. 153",
country: CountryCodes.DE,
id: "12345676");
invoice.AddSellerTaxRegistration("DE123456788", TaxRegistrationSchemeID.VA);
// Représentant fiscal du vendeur (BG-11) : partie distincte avec son propre n° de TVA.
invoice.SellerTaxRepresentative = new Party()
{
Name = "Global Supplies Financial Services",
Postcode = "12345",
Street = "Friedrichstraße 165",
City = "Berlin",
Country = CountryCodes.DE
};
invoice.AddSellerTaxRepresentativeTaxRegistration("DE136695976", TaxRegistrationSchemeID.VA);
' Vendeur (BG-4) – sans interlocuteur et sans GLN.
invoice.SetSeller(
name:="Rohstoff AG Salzgitter",
postcode:="38226",
city:="Salzgitter",
street:="Marktstr. 153",
country:=CountryCodes.DE,
id:="12345676")
invoice.AddSellerTaxRegistration("DE123456788", TaxRegistrationSchemeID.VA)
' Représentant fiscal du vendeur (BG-11) : partie distincte avec son propre n° de TVA.
invoice.SellerTaxRepresentative = New Party() With
{
.Name = "Global Supplies Financial Services",
.Postcode = "12345",
.Street = "Friedrichstraße 165",
.City = "Berlin",
.Country = CountryCodes.DE
}
invoice.AddSellerTaxRepresentativeTaxRegistration("DE136695976", TaxRegistrationSchemeID.VA)
4. Acheteur
Deux petites choses souvent recherchées : street2 remplit
ram:LineTwo, c’est-à-dire la deuxième ligne d’adresse, et
l’adresse électronique de l’acheteur (BT-49) porte ici une Leitweg-ID.
// Acheteur (BG-7). street2 remplit ram:LineTwo – la deuxième ligne d'adresse ("Hof 3").
invoice.SetBuyer(
name: "Metallbau Leipzig GmbH & Co. KG",
postcode: "12345",
city: "Leipzig",
street: "Pappelallee 15",
street2: "Hof 3",
country: CountryCodes.DE,
id: "75969813");
// BT-49 : adresse électronique de l'acheteur, schéma 0204 = Leitweg-ID.
invoice.SetBuyerElectronicAddress("04011000-1234512345-35",
ElectronicAddressSchemeIdentifiers.LeitwegId);
' Acheteur (BG-7). street2 remplit ram:LineTwo – la deuxième ligne d'adresse ("Hof 3").
invoice.SetBuyer(
name:="Metallbau Leipzig GmbH & Co. KG",
postcode:="12345",
city:="Leipzig",
street:="Pappelallee 15",
street2:="Hof 3",
country:=CountryCodes.DE,
id:="75969813")
' BT-49 : adresse électronique de l'acheteur, schéma 0204 = Leitweg-ID.
invoice.SetBuyerElectronicAddress("04011000-1234512345-35",
ElectronicAddressSchemeIdentifiers.LeitwegId)
5. Livraison et période de facturation
Le destinataire des marchandises porte lui aussi une adresse électronique.
Contrairement au vendeur et à l’acheteur, il n’existe pas de méthode
Set… pour cela : le champ ElectronicAddress est rattaché
directement à la partie et n’est écrit que dans le profil EXTENDED.
// Destinataire des marchandises (BG-13)
invoice.ShipTo = new Party()
{
ID = new GlobalID(null, "75969815"),
Name = "Metallbau Leipzig GmbH & Co. KG",
Postcode = "12347",
Street = "Eichenpromenade 37",
Street2 = "Tor 1",
City = "Metallstadt",
Country = CountryCodes.DE,
// BT-X-160 : adresse électronique du destinataire, ici un numéro D-U-N-S
// sous le schéma 0060. Chaque partie porte ce champ – pour le vendeur et l'acheteur
// ce sont BT-34 et BT-49, pour toutes les autres un champ BT-X propre, écrit uniquement dans le
// profil EXTENDED.
ElectronicAddress = new ElectronicAddress()
{
Address = "999999999",
ElectronicAddressSchemeID = ElectronicAddressSchemeIdentifiers.DunsNumber
}
};
invoice.ActualDeliveryDate = new DateTime(2025, 11, 25); // BT-72
// BT-73 / BT-74 : période de facturation de tout le document
invoice.SetBillingPeriod(new DateTime(2025, 11, 1), new DateTime(2025, 11, 30));
' Destinataire des marchandises (BG-13)
invoice.ShipTo = New Party() With
{
.ID = New GlobalID(Nothing, "75969815"),
.Name = "Metallbau Leipzig GmbH & Co. KG",
.Postcode = "12347",
.Street = "Eichenpromenade 37",
.Street2 = "Tor 1",
.City = "Metallstadt",
.Country = CountryCodes.DE,
' BT-X-160 : adresse électronique du destinataire, ici un numéro D-U-N-S
' sous le schéma 0060. Chaque partie porte ce champ – pour le vendeur et l'acheteur
' ce sont BT-34 et BT-49, pour toutes les autres un champ BT-X propre, écrit uniquement dans le
' profil EXTENDED.
.ElectronicAddress = New ElectronicAddress() With
{
.Address = "999999999",
.ElectronicAddressSchemeID = ElectronicAddressSchemeIdentifiers.DunsNumber
}
}
invoice.ActualDeliveryDate = New DateTime(2025, 11, 25) ' BT-72
' BT-73 / BT-74 : période de facturation de tout le document
invoice.SetBillingPeriod(New DateTime(2025, 11, 1), New DateTime(2025, 11, 30))
6. Bénéficiaire du paiement et coordonnées bancaires
Le paiement ne va pas au vendeur mais à son prestataire financier (BG-10). Les
coordonnées bancaires se définissent séparément via
AddCreditorFinancialAccount.
// Bénéficiaire du paiement (BG-10) : le paiement ne va pas au vendeur mais à son
// prestataire financier. Schéma 0060 = numéro D-U-N-S.
invoice.Payee = new Party()
{
GlobalID = new GlobalID(GlobalIDSchemeIdentifiers.DUNS, "432156789"),
Name = "Global Supplies Financial Services",
Postcode = "12345",
Street = "Friedrichstraße 165",
City = "Berlin",
Country = CountryCodes.DE
};
// Pas de texte d'information ni de BIC – la référence n'émet ni l'un ni l'autre.
invoice.SetPaymentMeans(PaymentMeansTypeCodes.SEPACreditTransfer);
invoice.AddCreditorFinancialAccount(
iban: "DE77 3707 0060 0321 9870 00",
bic: null,
name: "Global Supplies Financial Services");
' Bénéficiaire du paiement (BG-10) : le paiement ne va pas au vendeur mais à son
' prestataire financier. Schéma 0060 = numéro D-U-N-S.
invoice.Payee = New Party() With
{
.GlobalID = New GlobalID(GlobalIDSchemeIdentifiers.DUNS, "432156789"),
.Name = "Global Supplies Financial Services",
.Postcode = "12345",
.Street = "Friedrichstraße 165",
.City = "Berlin",
.Country = CountryCodes.DE
}
' Pas de texte d'information ni de BIC – la référence n'émet ni l'un ni l'autre.
invoice.SetPaymentMeans(PaymentMeansTypeCodes.SEPACreditTransfer)
invoice.AddCreditorFinancialAccount(
iban:="DE77 3707 0060 0321 9870 00",
bic:=Nothing,
name:="Global Supplies Financial Services")
7. Ligne avec remises
Une seule ligne, mais avec la distinction la plus souvent confondue en pratique : il existe deux types de remise différents au niveau de la ligne.
| Méthode | Élément XML | Effet |
|---|---|---|
AddTradeAllowance |
ram:AppliedTradeAllowanceCharge(à l’intérieur du prix brut) |
Montant par unité. Abaisse le prix net. C’est ainsi que procède la facture de marchandises. |
AddSpecifiedTradeAllowance |
ram:SpecifiedTradeAllowanceCharge(dans le règlement de la ligne) |
Montant pour la ligne entière. Abaisse le total de ligne, le prix reste inchangé. C’est la voie utilisée ici. |
Concrètement : le prix unitaire reste à 100 GBP, le total de ligne passe de 1 000 à 850 GBP du fait des deux remises.
// 10 bobines d'acier à 100 GBP = 1 000 GBP, dont deux remises (100 + 50) → 850 GBP.
TradeLineItem coil = invoice.AddTradeLineItem(
lineID: "1",
name: "Stahlcoil",
netUnitPrice: 100m,
grossUnitPrice: 100m,
unitCode: QuantityCodes.H87,
unitQuantity: 1m,
billedQuantity: 10m,
lineTotalAmount: 850m, // après déduction des deux remises ci-dessous
taxType: TaxTypes.VAT,
categoryCode: TaxCategoryCodes.S,
taxPercent: 19m,
sellerAssignedID: "CO-123/V2A",
buyerAssignedID: "Toolbox 0815");
coil.GrossQuantity = 1m; // ram:BasisQuantity dans le prix brut
coil.OriginTradeCountry = CountryCodes.DE; // BT-159 pays d'origine
// Note de ligne sans SubjectCode, à nouveau avec l'indentation de la référence.
coil.AddNote("Materialzertifikat X-234 gem ISO XYZ.\n\t\t\t\t\t\tWare bleibt bis zur "
+ "vollständigen Bezahlung unser Eigentum.\n\t\t\t\t\t");
// Référence de commande avec ligne de commande, mais sans date
coil.SetBuyerOrderReferencedDocument("ORDER84359", orderReferencedDate: null,
orderReferencedLineId: "1");
// Remise 1 : en pourcentage, 10 % de 1 000. ReasonCode 64 = accord particulier.
coil.AddSpecifiedTradeAllowance(
currency: CurrencyCodes.GBP,
basisAmount: 1000m,
actualAmount: 100m,
chargePercentage: 10m,
reason: "Lagerware",
reasonCode: AllowanceReasonCodes.SpecialAgreement);
// Remise 2 : montant fixe. ReasonCode 70 = remise Incoterm.
coil.AddSpecifiedTradeAllowance(
currency: CurrencyCodes.GBP,
basisAmount: 1000m,
actualAmount: 50m,
reason: "Direktbelieferung",
reasonCode: AllowanceReasonCodes.IncotermDiscount);
' 10 bobines d'acier à 100 GBP = 1 000 GBP, dont deux remises (100 + 50) → 850 GBP.
Dim coil As TradeLineItem = invoice.AddTradeLineItem(
lineID:="1",
name:="Stahlcoil",
netUnitPrice:=100D,
grossUnitPrice:=100D,
unitCode:=QuantityCodes.H87,
unitQuantity:=1D,
billedQuantity:=10D,
lineTotalAmount:=850D, ' après déduction des deux remises ci-dessous
taxType:=TaxTypes.VAT,
categoryCode:=TaxCategoryCodes.S,
taxPercent:=19D,
sellerAssignedID:="CO-123/V2A",
buyerAssignedID:="Toolbox 0815")
coil.GrossQuantity = 1D ' ram:BasisQuantity dans le prix brut
coil.OriginTradeCountry = CountryCodes.DE ' BT-159 pays d'origine
' Note de ligne sans SubjectCode, à nouveau avec l'indentation de la référence.
coil.AddNote("Materialzertifikat X-234 gem ISO XYZ." & vbLf &
vbTab & vbTab & vbTab & vbTab & vbTab & vbTab &
"Ware bleibt bis zur vollständigen Bezahlung unser Eigentum." & vbLf &
vbTab & vbTab & vbTab & vbTab & vbTab)
' Référence de commande avec ligne de commande, mais sans date
coil.SetBuyerOrderReferencedDocument("ORDER84359", orderReferencedDate:=Nothing,
orderReferencedLineId:="1")
' Remise 1 : en pourcentage, 10 % de 1 000. ReasonCode 64 = accord particulier.
coil.AddSpecifiedTradeAllowance(
currency:=CurrencyCodes.GBP,
basisAmount:=1000D,
actualAmount:=100D,
chargePercentage:=10D,
reason:="Lagerware",
reasonCode:=AllowanceReasonCodes.SpecialAgreement)
' Remise 2 : montant fixe. ReasonCode 70 = remise Incoterm.
coil.AddSpecifiedTradeAllowance(
currency:=CurrencyCodes.GBP,
basisAmount:=1000D,
actualAmount:=50D,
reason:="Direktbelieferung",
reasonCode:=AllowanceReasonCodes.IncotermDiscount)
8. Suppléments et remises au niveau du document
Un supplément pour emballage à usage unique et une remise de fidélité en
pourcentage. Dans le XML, les deux partagent le même élément
ram:SpecifiedTradeAllowanceCharge et ne se distinguent que par
ram:ChargeIndicator. Le writer les écrit dans l’ordre où ils ont
été ajoutés – c’est pourquoi le supplément figure en premier dans le
code.
// Le supplément d'abord – le writer écrit suppléments et remises dans l'ordre où
// ils sont ajoutés, et la référence place le supplément en premier.
invoice.AddTradeCharge(
basisAmount: null, // la référence n'émet pas de base de calcul ici
currency: CurrencyCodes.GBP,
actualAmount: 30m,
reason: "Einwegverpackung",
taxTypeCode: TaxTypes.VAT,
taxCategoryCode: TaxCategoryCodes.S,
taxPercent: 19m,
reasonCode: ChargeReasonCodes.Miscellaneous); // ABK
invoice.AddTradeAllowance(
basisAmount: 850m,
currency: CurrencyCodes.GBP,
actualAmount: 21.25m,
chargePercentage: 2.5m,
reason: "Stammkundenrabatt",
taxTypeCode: TaxTypes.VAT,
taxCategoryCode: TaxCategoryCodes.S,
taxPercent: 19m,
reasonCode: AllowanceReasonCodes.FixedLongTerm); // 102
' Le supplément d'abord – le writer écrit suppléments et remises dans l'ordre où
' ils sont ajoutés, et la référence place le supplément en premier.
invoice.AddTradeCharge(
basisAmount:=Nothing, ' la référence n'émet pas de base de calcul ici
currency:=CurrencyCodes.GBP,
actualAmount:=30D,
reason:="Einwegverpackung",
taxTypeCode:=TaxTypes.VAT,
taxCategoryCode:=TaxCategoryCodes.S,
taxPercent:=19D,
reasonCode:=ChargeReasonCodes.Miscellaneous) ' ABK
invoice.AddTradeAllowance(
basisAmount:=850D,
currency:=CurrencyCodes.GBP,
actualAmount:=21.25D,
chargePercentage:=2.5D,
reason:="Stammkundenrabatt",
taxTypeCode:=TaxTypes.VAT,
taxCategoryCode:=TaxCategoryCodes.S,
taxPercent:=19D,
reasonCode:=AllowanceReasonCodes.FixedLongTerm) ' 102
9. TVA dans la devise de facturation
D’abord tout à fait ordinaire, en GBP : 850,00 + 30,00 − 21,25 = 858,75, dont 19 % = 163,1625 → 163,16 GBP.
// BT-110 : montant de TVA dans la devise de facturation (GBP).
invoice.AddApplicableTradeTax(
basisAmount: 858.75m,
percent: 19m,
taxAmount: 163.16m,
typeCode: TaxTypes.VAT,
categoryCode: TaxCategoryCodes.S,
allowanceChargeBasisAmount: 8.75m, // +30,00 − 21,25
lineTotalBasisAmount: 850m);
' BT-110 : montant de TVA dans la devise de facturation (GBP).
invoice.AddApplicableTradeTax(
basisAmount:=858.75D,
percent:=19D,
taxAmount:=163.16D,
typeCode:=TaxTypes.VAT,
categoryCode:=TaxCategoryCodes.S,
allowanceChargeBasisAmount:=8.75D, ' +30,00 − 21,25
lineTotalBasisAmount:=850D)
10. Montant de TVA en devise comptable et taux de change
Pour la déclaration de TVA, le montant en devise étrangère ne suffit pas : l’art. 230 de la directive TVA de l’UE (2006/112/CE) exige le montant également dans la monnaie nationale du vendeur. Trois indications solidaires existent pour cela :
| Code | Champ | Signification |
|---|---|---|
| BT-6 | TaxCurrency |
La devise comptable elle-même, ici EUR. |
| BT-111 | TaxTotalAmountInAccountingCurrency |
Le même montant de TVA, converti en BT-6 : 183,14 EUR. |
| BG-X-41 | TaxCurrencyExchange (groupe) | Le taux avec lequel la conversion a été faite. |
| BT-X-258 | SourceCurrency |
Devise de facturation, donc BT-5 (GBP). FactoorSharp la déduit automatiquement. |
| BT-X-259 | TargetCurrency |
Devise comptable, donc BT-6 (EUR). |
| BT-X-260 | ConversionRate |
Le taux proprement dit, ici 1,12244. |
| BT-X-261 | ConversionRateTimestamp |
Date du taux, facultative. Ici le jour de la livraison, 25.11.2025. |
Sans BG-X-41, seul le résultat figurerait dans le document, pas le chemin qui y mène – et pour une comptabilité qui veut recalculer le montant ou le vérifier contre le taux du jour, c’est précisément l’indication qui manque.
Pourquoi une seule méthode pour trois business terms ? Parce que la règle de gestion EN 16931 BR-53 exige que si BT-6 est présent, BT-111 soit fourni également. Et le taux de BG-X-41 est la justification de la valeur de BT-111. Des setters séparés auraient permis de définir un montant de TVA en devise comptable sans jamais dire avec quel taux il a été obtenu – ou inversement d’enregistrer un taux qui ne correspond à aucun montant déclaré.
// Un seul appel écrit BT-111, BT-6 et tout le groupe BG-X-41 :
// 163,16 GBP × 1,12244 = 183,14 EUR
// La méthode déduit automatiquement la devise source de invoice.Currency (BT-5).
invoice.SetTaxCurrencyExchange(
taxTotalInAccountingCurrency: 183.14m,
accountingCurrency: CurrencyCodes.EUR,
conversionRate: 1.12244m,
conversionRateTimestamp: new DateTime(2025, 11, 25));
' Un seul appel écrit BT-111, BT-6 et tout le groupe BG-X-41 :
' 163,16 GBP × 1,12244 = 183,14 EUR
' La méthode déduit automatiquement la devise source de invoice.Currency (BT-5).
invoice.SetTaxCurrencyExchange(
taxTotalInAccountingCurrency:=183.14D,
accountingCurrency:=CurrencyCodes.EUR,
conversionRate:=1.12244D,
conversionRateTimestamp:=New DateTime(2025, 11, 25))
L’ancienne méthode SetTaxTotalInAccountingCurrency ne définissait
que BT-111 et BT-6, sans taux. Elle a été supprimée dans la version 20.0 ;
utilisez SetTaxCurrencyExchange.
Sur le taux lui-même : BT-X-260 est défini dans le schéma comme un simple
xs:decimal sans limite de décimales, et la référence FeRD en écrit
cinq. Le writer arrondit donc de manière adaptative – à deux décimales quand
c’est possible sans perte, sinon jusqu’à cinq – et restitue
1,12244 exactement. La date du taux s’écrit, comme tous les champs de date,
au format UN/CEFACT 102 (AAAAMMJJ).
BG-X-41 n’existe que dans le profil EXTENDED et uniquement côté CII. UBL
connaît certes avec cac:TaxExchangeRate un élément structurellement
comparable, mais celui-ci se situe en dehors de la CIUS EN 16931 et
n’est donc pas pris en charge par FactoorSharp – voir
UBL vs. CII.
11. Conditions de paiement
Deux échéances, ici délibérément en texte libre avec date. La façon de rendre un escompte exploitable automatiquement est montrée par la facture de marchandises.
// Deux échéances en texte libre plus date – sans PaymentTermsType.Skonto, donc
// sans bloc d'escompte exploitable automatiquement.
invoice.AddTradePaymentTerms("Zahlbar ohne Abschlag bis ", new DateTime(2025, 12, 31));
invoice.AddTradePaymentTerms("Zahlbar mit 2% Skonto bis", new DateTime(2025, 12, 14));
' Deux échéances en texte libre plus date – sans PaymentTermsType.Skonto, donc
' sans bloc d'escompte exploitable automatiquement.
invoice.AddTradePaymentTerms("Zahlbar ohne Abschlag bis ", New DateTime(2025, 12, 31))
invoice.AddTradePaymentTerms("Zahlbar mit 2% Skonto bis", New DateTime(2025, 12, 14))
12. Totaux du document
Tous les totaux sont en GBP. Nouveauté par rapport aux autres exemples : l’acompte (BT-113), qui est déduit du montant TTC :
| Code BT | Paramètre | Calcul (GBP) |
|---|---|---|
| BT-106 | lineTotalAmount |
850,00 (total de ligne après les deux remises) |
| BT-108 | chargeTotalAmount |
30,00 (emballage à usage unique) |
| BT-107 | allowanceTotalAmount |
21,25 (remise de fidélité) |
| BT-109 | taxBasisAmount |
850,00 + 30,00 − 21,25 = 858,75 |
| BT-110 | taxTotalAmount |
858,75 × 19 % = 163,16 |
| BT-112 | grandTotalAmount |
858,75 + 163,16 = 1 021,91 |
| BT-113 | totalPrepaidAmount |
500,00. La façon de détailler les acomptes est décrite sous Acomptes. |
| BT-115 | duePayableAmount |
1 021,91 − 500,00 = 521,91 |
// Toutes les valeurs en GBP, la devise de facturation – y compris le montant de TVA.
invoice.SetTotals(
lineTotalAmount: 850m, // BT-106
chargeTotalAmount: 30m, // BT-108
allowanceTotalAmount: 21.25m, // BT-107
taxBasisAmount: 858.75m, // BT-109
taxTotalAmount: 163.16m, // BT-110
grandTotalAmount: 1021.91m, // BT-112
totalPrepaidAmount: 500m, // BT-113 acompte
duePayableAmount: 521.91m); // BT-115
' Toutes les valeurs en GBP, la devise de facturation – y compris le montant de TVA.
invoice.SetTotals(
lineTotalAmount:=850D, ' BT-106
chargeTotalAmount:=30D, ' BT-108
allowanceTotalAmount:=21.25D, ' BT-107
taxBasisAmount:=858.75D, ' BT-109
taxTotalAmount:=163.16D, ' BT-110
grandTotalAmount:=1021.91D, ' BT-112
totalPrepaidAmount:=500D, ' BT-113 acompte
duePayableAmount:=521.91D) ' BT-115
13. Enregistrement et contrôle
invoice.Save("X07_01_Fremdwaehrung.xml",
ZUGFeRDVersion.Version25,
Profile.Extended,
ZUGFeRDFormats.CII);
invoice.Save("X07_01_Fremdwaehrung.xml",
ZUGFeRDVersion.Version25,
Profile.Extended,
ZUGFeRDFormats.CII)
Le résultat doit présenter la même structure arborescente que
X07_01_Fremdwaehrung.xml du jeu d’exemples FeRD. Quant à savoir
si le document respecte également le jeu de règles, vous le vérifiez soit
dans le navigateur,
soit directement
depuis votre code.
Un constat est à prévoir et ne provient pas de la reconstruction : la référence
FeRD porte comme Leitweg-ID 04011000-1234512345-35, dont la clé de
contrôle est fausse. La valeur est reprise caractère par caractère du modèle,
le constat touche donc le modèle tout autant. Si vous utilisez cette facture
comme document propre, mettez ici une Leitweg-ID valide.
Une version lisible par un humain est produite par le visualiseur ; la façon d’en tirer un PDF/A-3 avec XML intégré est décrite sous Travailler avec des fichiers PDF.