<!-- md-source: 01b63197e5e9 FactoorSharpWeb/Views/Service/GoodsInvoice.cshtml -->
<!-- md-source: a6d68a004bba FactoorSharpWeb/Views/Shared/_GoodsInvoiceSamples.cshtml -->

# Erweiterte Warenrechnung

> Markdown-Fassung von <https://www.factoorsharp.de/de/Service/GoodsInvoice> für KI-Agenten.
> Sprachen: [Deutsch](https://www.factoorsharp.de/de/Service/GoodsInvoice.md) ·
> [English](https://www.factoorsharp.de/en/Service/GoodsInvoice.md) ·
> [Français](https://www.factoorsharp.de/fr/Service/GoodsInvoice.md)

Eine vollständige Warenrechnung im Profil EXTENDED: sechs Positionen mit
Verpackungsangaben und Artikelrabatten, zwei Steuersätze, Rechnungsrabatte auf
Dokumentenebene, Transportkosten, Skonto und abweichende Waren- und Rechnungsempfänger.

Grundlage ist die offizielle Beispielrechnung `X19_01_Warenrechnung` aus der
Factur-X-/ZUGFeRD-Dokumentation (FeRD-Beispielpaket, ZUGFeRD 2.5.0, Profil EXTENDED).
Fachlich eine Lieferung aus dem Lebensmittel-Großhandel an eine Supermarkt-Filiale.

Sämtliche EXTENDED-Felder – Dokumentenname, Testkennzeichen, Rechnungsempfänger,
Verpackungsangaben, Bestandteile einer Verkaufseinheit, Transportkosten und die
erweiterten Steuerbasen – werden nur geschrieben, wenn am Ende auch tatsächlich als
`Profile.Extended` gespeichert wird. Ein kleineres Profil ist kein Fehler; die Felder
fallen dann lautlos weg.

## 1. Rechnungskopf

```csharp
// BT-1 Rechnungsnummer, BT-2 Rechnungsdatum, BT-5 Rechnungswährung
FacturXInvoice invoice = FacturXInvoice.CreateInvoice(
    invoiceNo: "R87654321012345",
    invoiceDate: new DateTime(2025, 10, 1),
    currency: CurrencyCodes.EUR);

// BT-3: Rechnungstyp 380 = Handelsrechnung. Das ist der Default, steht hier aber
// bewusst ausgeschrieben, damit sichtbar ist, wo der Typ gesetzt wird.
invoice.Type = InvoiceType.Invoice;

// BT-X-2: freier Dokumentenname. Nur im Profil EXTENDED erlaubt und nur dort
// ausgegeben – in BASIC/COMFORT lässt der Writer das Element stillschweigend weg.
invoice.Name = "WARENRECHNUNG";

// ram:TestIndicator kennzeichnet den Beleg als Testdatensatz (ebenfalls nur EXTENDED).
invoice.IsTest = true;
```

## 2. Freitexte

Freitexte landen in `ram:IncludedNote` (BG-1). `subjectCode` (BT-21, UNTDID 4451) sagt,
worüber die Notiz spricht, `contentCode` (BT-X-5) ist ein zusätzlicher standardisierter
Textbaustein. Die beiden Codes sind **nicht frei kombinierbar**: `ST1`, `ST2` und `ST3`
gehören zu `AAK` (Rabatt- und Bonusvereinbarungen), `EEV`, `WEB` und `VEV` zu `AAJ`
(Eigentumsvorbehalt).

```csharp
// REG = Regulatorische Angaben, hier die handelsrechtliche Vertretung.
invoice.AddNote("Geschäftsführer: Herr Geschäftsführer ,  MUSTERLIEFERANT GmbH  ",
                subjectCode: SubjectCodes.REG);

// AAI = allgemeine Information.
invoice.AddNote("Es bestehen Vereinbarungen, aus denen sich Minderungen des Entgelts ergeben können.",
                subjectCode: SubjectCodes.AAI);

// ACB = zusätzliche Information; hier für die Formatkennzeichnung …
invoice.AddNote("ZUGFeRD vers 2.5.0 (Extended)", subjectCode: SubjectCodes.ACB);
// … und für den Hinweis, dass es sich um ein Beispiel handelt.
invoice.AddNote("Dies ist ein Waren-Rechnungs-Beispiel", subjectCode: SubjectCodes.ACB);

// AAK + ST3: standardisierter Hinweis auf bestehende Rabatt- oder Bonusvereinbarungen.
invoice.AddNote("Es bestehen Rabatt- oder Bonusvereinbarungen.",
                subjectCode: SubjectCodes.AAK,
                contentCode: ContentCodes.ST3);

// AAJ + EEV: standardisierter Eigentumsvorbehalt.
invoice.AddNote("Der Verkäufer bleibt Eigentümer der Waren bis zu vollständigen Erfüllung der Kaufpreisforderung.",
                subjectCode: SubjectCodes.AAJ,
                contentCode: ContentCodes.EEV);

// Notizen ohne subjectCode sind zulässig – reiner Freitext.
invoice.AddNote("Leergutwert: 46,50");
invoice.AddNote("Wichtige Information: Bei Bestellungen bis zum 19.12. ist die Auslieferung bis spätestens 23.12. garantiert.");
```

## 3. Verkäufer

`SetSeller` füllt `ram:SellerTradeParty` (BG-4). Die Partei trägt zwei Kennungen: die
interne Lieferantennummer (`id`, BT-29) und die GLN (`globalID` mit schemeID `0088`).

```csharp
invoice.SetSeller(
    name: "MUSTERLIEFERANT GMBH",
    postcode: "99199",
    city: "MUSTERHAUSEN",
    street: "BAHNHOFSTRASSE 99",
    country: CountryCodes.DE,
    id: "549910",
    globalID: new GlobalID(GlobalIDSchemeIdentifiers.GLN, "4333741000005"));

// BT-42 / BT-43: Ansprechpartner. Name und Abteilung bleiben leer – der Writer gibt
// ram:PersonName / ram:DepartmentName dann gar nicht erst aus.
invoice.SetSellerContact(
    emailAddress: "max.mustermann@musterlieferant.de",
    phoneno: "+49 932 431 500");

// BT-34: elektronische Adresse des Verkäufers, hier als EAN Location Code (0088).
invoice.SetSellerElectronicAddress("info@musterlieferant.de",
                                   ElectronicAddressSchemeIdentifiers.EanLocationCode);

// BT-31: USt-IdNr. des Verkäufers (Schema VA). FC wäre die nationale Steuernummer.
invoice.AddSellerTaxRegistration("DE123456788", TaxRegistrationSchemeID.VA);
```

## 4. Käufer

Der Käufer ist die Zentrale – geliefert wird an eine Filiale, die Rechnung geht an einen
dritten Standort.

```csharp
invoice.SetBuyer(
    name: "MUSTER-KUNDE GMBH",
    postcode: "40235",
    city: "KUNDENSTADT",
    street: "KUNDENWEG 88",
    country: CountryCodes.DE,
    id: "009420",
    globalID: new GlobalID(GlobalIDSchemeIdentifiers.GLN, "4304171000002"));
```

## 5. Belegverweise im Kopf

```csharp
// BT-13: Bestellnummer des Käufers → ram:BuyerOrderReferencedDocument
invoice.SetBuyerOrderReferenceDocument("B123456789");

// BT-18 / BG-24: zusätzliche Dokumentenreferenz. TypeCode 130 = Rechnungsdatenblatt.
invoice.AddAdditionalReferencedDocument(
    id: "A456123",
    typeCode: AdditionalReferencedDocumentTypeCode.InvoiceDataSheet);

// BT-16: Lieferscheinnummer → ram:DeliveryNoteReferencedDocument (EXTENDED)
invoice.SetDeliveryNoteReferenceDocument("L87654321012345");

// BT-72: tatsächliches Lieferdatum → ram:ActualDeliverySupplyChainEvent
invoice.ActualDeliveryDate = new DateTime(2025, 10, 1);
```

## 6. Warenempfänger und Rechnungsempfänger

Warenempfänger (BG-13) und Rechnungsempfänger (BG-X-36) werden nicht über
`Set…`-Methoden, sondern als `Party`-Objekte gesetzt.

```csharp
invoice.ShipTo = new Party()
{
    GlobalID = new GlobalID(GlobalIDSchemeIdentifiers.GLN, "4304171088093"),
    Name     = "MUSTER-MARKT",
    Postcode = "31157",
    Street   = "HAUPTSTRASSE 44",
    City     = "SARSTEDT",
    Country  = CountryCodes.DE
};

// ram:DefinedTradeContact/ram:DepartmentName – die Abteilung ("8211") in der Filiale.
invoice.ShipToContact = new Contact() { OrgUnit = "8211" };

// BG-X-36 (nur EXTENDED): gleiche Firma wie der Käufer, anderer Standort.
invoice.Invoicee = new Party()
{
    ID       = new GlobalID(null, "009420"),
    GlobalID = new GlobalID(GlobalIDSchemeIdentifiers.GLN, "4304171000002"),
    Name     = "MUSTER-KUNDE GMBH",
    Postcode = "40235",
    Street   = "KUNDENWEG 88",
    City     = "DUESSELDORF",
    Country  = CountryCodes.DE
};
```

## 7. Rechnungspositionen

Sechs Positionen (BG-25). Das wiederkehrende Muster:

| Parameter | BT-Code | Bedeutung |
|---|---|---|
| `lineID` | BT-126 | Positionsnummer; ohne Angabe vergibt FactoorSharp sie automatisch |
| `id` | BT-157 | GTIN mit schemeID `0160` (GS1), `GlobalIDSchemeIdentifiers.EAN` |
| `sellerAssignedID` | BT-155 | Artikelnummer des Lieferanten |
| `buyerAssignedID` | BT-156 | Artikelnummer des Käufers für dieselbe Ware |
| `grossUnitPrice` | BT-148 | Bruttopreis, Listenpreis vor Artikelrabatt |
| `netUnitPrice` | BT-146 | Nettopreis nach Artikelrabatt – Basis der Positionssumme |
| `lineTotalAmount` | BT-131 | `netUnitPrice` × `billedQuantity` |
| `PackageQuantity` / `PackageUnitCode` | BT-X-9 | Versandeinheit, nur EXTENDED. `XCT` = Karton, `XBC` = Kiste, `XBO` = Flasche, `XPX` = Palette |

### Position 1 – Artikelattribut und Versandeinheit

```csharp
// 100 Flaschen Zitronensäure zu 1,00 € = 100,00 €, 19 % USt
TradeLineItem line1 = invoice.AddTradeLineItem(
    lineID: "1",
    name: "Zitronensäure 100ml",
    netUnitPrice: 1.00m,
    grossUnitPrice: 1.00m,
    unitCode: QuantityCodes.H87,       // H87 = Stück
    billedQuantity: 100m,
    lineTotalAmount: 100.00m,
    taxType: TaxTypes.VAT,
    categoryCode: TaxCategoryCodes.S,  // S = Regelsteuersatz
    taxPercent: 19m,
    sellerAssignedID: "ZS997",
    id: new GlobalID(GlobalIDSchemeIdentifiers.EAN, "4123456000014"));

// BG-32 Artikelattribut: frei definierbares Merkmal/Wert-Paar (BT-160 / BT-161).
line1.ApplicableProductCharacteristics.Add(new ApplicableProductCharacteristic()
{
    Description = "Verpackungsart",
    Value       = "BO"
});

line1.PackageQuantity = 4m;
line1.PackageUnitCode = QuantityCodes.XCT;
```

### Position 2 – Artikelrabatte im Bruttopreis

Diese Rabatte stehen nicht auf Dokumentebene, sondern als
`ram:AppliedTradeAllowanceCharge` innerhalb des Bruttopreises (BT-147). Die Beträge
gelten **pro Einheit**: 1,50 − 0,03 − 0,02 = 1,45. FactoorSharp rechnet den Nettopreis
nicht aus – er wird gesetzt, die Rabatte erklären ihn.

```csharp
TradeLineItem line2 = invoice.AddTradeLineItem(
    lineID: "2",
    name: "Gelierzucker Extra 250g",
    netUnitPrice: 1.45m,
    grossUnitPrice: 1.50m,
    unitCode: QuantityCodes.H87,
    billedQuantity: 50m,
    lineTotalAmount: 72.50m,
    taxType: TaxTypes.VAT,
    categoryCode: TaxCategoryCodes.S,
    taxPercent: 7m,
    sellerAssignedID: "GZ250",
    id: new GlobalID(GlobalIDSchemeIdentifiers.EAN, "4123456000021"));

line2.AddTradeAllowance(CurrencyCodes.EUR, basisAmount: null, actualAmount: 0.03m, reason: "Artikelrabatt 1");
line2.AddTradeAllowance(CurrencyCodes.EUR, basisAmount: null, actualAmount: 0.02m, reason: "Artikelrabatt 2");

line2.PackageQuantity = 1m;
line2.PackageUnitCode = QuantityCodes.XCT;
```

### Position 3 – Naturalrabatt

Zehn Stück ohne Berechnung. Die Position bleibt im Beleg, damit die gelieferte Menge
nachvollziehbar ist, trägt aber 0,00 € zur Summe bei.

```csharp
TradeLineItem line3 = invoice.AddTradeLineItem(
    lineID: "3",
    name: "Gelierzucker Extra 250g",
    description: "Artikel wie vereinbart ohne Berechnung",   // BT-154
    netUnitPrice: 0.00m,
    grossUnitPrice: 0.00m,
    unitCode: QuantityCodes.H87,
    billedQuantity: 10m,
    lineTotalAmount: 0.00m,
    taxType: TaxTypes.VAT,
    categoryCode: TaxCategoryCodes.S,
    taxPercent: 7m,
    sellerAssignedID: "GZ250",
    id: new GlobalID(GlobalIDSchemeIdentifiers.EAN, "4123456000021"));

line3.PackageQuantity = 1m;
line3.PackageUnitCode = QuantityCodes.XCT;
```

### Positionen 4 und 5 – abweichende Einheiten und Käufer-Artikelnummer

Abgerechnet wird in Kisten, versandt in Flaschen. Position 5 ist das zugehörige
Leergutpfand und führt zusätzlich die Artikelnummer des Käufers (BT-156).

```csharp
TradeLineItem line4 = invoice.AddTradeLineItem(
    lineID: "4",
    name: "Bierbrau Pils 20/0500",
    description: "EAN-VKE: 4100130913297",
    netUnitPrice: 12.00m,
    grossUnitPrice: 12.00m,
    unitCode: QuantityCodes.XBC,   // XBC = Kiste
    billedQuantity: 15m,
    lineTotalAmount: 180.00m,
    taxType: TaxTypes.VAT,
    categoryCode: TaxCategoryCodes.S,
    taxPercent: 19m,
    sellerAssignedID: "2031",
    id: new GlobalID(GlobalIDSchemeIdentifiers.EAN, "4100130013294"));

line4.ApplicableProductCharacteristics.Add(new ApplicableProductCharacteristic()
{
    Description = "Verpackung",
    Value       = "Kiste"
});

line4.PackageQuantity = 20m;
line4.PackageUnitCode = QuantityCodes.XBO;   // XBO = Flasche

TradeLineItem line5 = invoice.AddTradeLineItem(
    lineID: "5",
    name: "Leergutpfand 20 x 0,5l",
    netUnitPrice: 3.10m,
    grossUnitPrice: 3.10m,
    unitCode: QuantityCodes.H87,
    billedQuantity: 15m,
    lineTotalAmount: 46.50m,
    taxType: TaxTypes.VAT,
    categoryCode: TaxCategoryCodes.S,
    taxPercent: 19m,
    sellerAssignedID: "1805",
    buyerAssignedID: "4711",
    id: new GlobalID(GlobalIDSchemeIdentifiers.EAN, "2001015001325"));

line5.ApplicableProductCharacteristics.Add(new ApplicableProductCharacteristic()
{
    Description = "Verpackung",
    Value       = "unverpackt"
});

line5.PackageQuantity = 1m;
line5.PackageUnitCode = QuantityCodes.XBC;
```

### Position 6 – Mischpalette mit Bestandteilen

Die Palette wird als eine Position abgerechnet, ihr Inhalt über
`IncludedReferencedProducts` (BG-X-1) aufgeschlüsselt. Rein informativ: Preise und
Steuern hängen weiterhin an der übergeordneten Position.

```csharp
TradeLineItem line6 = invoice.AddTradeLineItem(
    lineID: "6",
    name: "Mischpalette Joghurt Karton 3 x 20",
    netUnitPrice: 29.10m,
    grossUnitPrice: 30.00m,
    unitCode: QuantityCodes.H87,
    billedQuantity: 2m,
    lineTotalAmount: 58.20m,
    taxType: TaxTypes.VAT,
    categoryCode: TaxCategoryCodes.S,
    taxPercent: 7m,
    sellerAssignedID: "MP107",
    id: new GlobalID(GlobalIDSchemeIdentifiers.EAN, "4123456000038"));

line6.ApplicableProductCharacteristics.Add(new ApplicableProductCharacteristic()
{
    Description = "Verpackung",
    Value       = "Karton"
});

// Die Komfort-Methode AddIncludedReferencedProduct() kennt keine GlobalID, deshalb
// werden die Objekte hier direkt angelegt.
line6.IncludedReferencedProducts.Add(new IncludedReferencedProduct()
{
    GlobalID         = new GlobalID(GlobalIDSchemeIdentifiers.EAN, "4123456001035"),
    SellerAssignedID = "JOG103",
    Name             = "Erdbeer 20 x 150g Becher",
    UnitQuantity     = 20m,
    UnitCode         = QuantityCodes.H87
});
line6.IncludedReferencedProducts.Add(new IncludedReferencedProduct()
{
    GlobalID         = new GlobalID(GlobalIDSchemeIdentifiers.EAN, "4123456002032"),
    SellerAssignedID = "JOG203",
    Name             = "Banane 20 x 150g Becher",
    UnitQuantity     = 20m,
    UnitCode         = QuantityCodes.H87
});
line6.IncludedReferencedProducts.Add(new IncludedReferencedProduct()
{
    GlobalID         = new GlobalID(GlobalIDSchemeIdentifiers.EAN, "4123456003039"),
    SellerAssignedID = "JOG303",
    Name             = "Schoko 20 x 150g Becher",
    UnitQuantity     = 20m,
    UnitCode         = QuantityCodes.H87
});

// BT-147 wie bei Position 2: Rabatt pro Einheit, 30,00 − 0,90 = 29,10.
line6.AddTradeAllowance(CurrencyCodes.EUR, basisAmount: null, actualAmount: 0.90m, reason: "Artikelrabatt 1");

line6.PackageQuantity = 1m;
line6.PackageUnitCode = QuantityCodes.XPX;   // XPX = Palette
```

## 8. Rechnungsrabatte auf Dokumentenebene

Ein Dokumentrabatt gilt immer nur für **einen** Steuersatz. Da der Beleg 19 % und 7 %
mischt, muss jeder Rabatt **zweimal** angelegt werden – aus zwei Rabatten werden vier
Aufrufe. Die Reihenfolge im XML entspricht der Aufrufreihenfolge im Code.

Die Bemessungsgrundlagen sind nicht einfach die Positionssummen: Für 19 % ergäben die
Positionen 1, 4 und 5 zusammen 326,50 €, vereinbart sind aber nur 280,00 € – Leergutpfand
und Teile der Ware sind rabattbefreit. Für 7 % gilt die volle Summe der Positionen 2, 3
und 6: 130,70 €.

```csharp
// Rechnungsrabatt 1 – prozentual, 2 % (BT-94 CalculationPercent + BT-93 BasisAmount).
invoice.AddTradeAllowance(
    basisAmount: 280.00m, currency: CurrencyCodes.EUR, actualAmount: 5.60m,
    chargePercentage: 2.00m, reason: "Rechnungsrabatt 1",
    taxTypeCode: TaxTypes.VAT, taxCategoryCode: TaxCategoryCodes.S, taxPercent: 19m);

invoice.AddTradeAllowance(
    basisAmount: 130.70m, currency: CurrencyCodes.EUR, actualAmount: 2.61m,
    chargePercentage: 2.00m, reason: "Rechnungsrabatt 1",
    taxTypeCode: TaxTypes.VAT, taxCategoryCode: TaxCategoryCodes.S, taxPercent: 7m);

// Rechnungsrabatt 2 – absoluter Betrag, deshalb ohne chargePercentage.
invoice.AddTradeAllowance(
    basisAmount: 280.00m, currency: CurrencyCodes.EUR, actualAmount: 2.50m,
    reason: "Rechnungsrabatt 2",
    taxTypeCode: TaxTypes.VAT, taxCategoryCode: TaxCategoryCodes.S, taxPercent: 19m);

invoice.AddTradeAllowance(
    basisAmount: 130.70m, currency: CurrencyCodes.EUR, actualAmount: 0.50m,
    reason: "Rechnungsrabatt 2",
    taxTypeCode: TaxTypes.VAT, taxCategoryCode: TaxCategoryCodes.S, taxPercent: 7m);
```

## 9. Transportkosten

Logistikkosten haben in CII ein eigenes Element und sind nicht dasselbe wie ein
gewöhnlicher Zuschlag über `AddTradeCharge`. In der XRechnung ist das Element nicht
zulässig, in ZUGFeRD EXTENDED schon. Es fließt in `ChargeTotalAmount` (BT-108) ein.

```csharp
invoice.AddLogisticsServiceCharge(
    amount: 3.00m,
    description: "Transportkosten",
    taxTypeCode: TaxTypes.VAT,
    taxCategoryCode: TaxCategoryCodes.S,
    taxPercent: 19m);
```

## 10. Umsatzsteueraufstellung

Je Kombination aus Steuersatz und Steuerkategorie ist eine Gruppe
`ram:ApplicableTradeTax` (BG-23) verpflichtend. FactoorSharp summiert die Beträge nicht
selbst; die Werte werden gesetzt.

| Feld | 19 % (Pos. 1, 4, 5) | 7 % (Pos. 2, 3, 6) |
|---|---|---|
| `lineTotalBasisAmount` | 326,50 | 130,70 |
| `allowanceChargeBasisAmount` | −5,60 − 2,50 + 3,00 = −5,10 | −2,61 − 0,50 = −3,11 |
| `basisAmount` | 326,50 − 5,10 = **321,40** | 130,70 − 3,11 = **127,59** |
| `taxAmount` | 321,40 × 19 % = 61,066 → **61,07** | 127,59 × 7 % = 8,9313 → **8,93** |

Der Zuschlag für die Transportkosten geht mit positivem Vorzeichen in die 19-%-Zeile ein,
die Rabatte mit negativem.

```csharp
// lineTotalBasisAmount und allowanceChargeBasisAmount sind EXTENDED-Felder;
// in BASIC/COMFORT entfallen sie ersatzlos.
invoice.AddApplicableTradeTax(
    basisAmount: 321.40m, percent: 19m, taxAmount: 61.07m,
    typeCode: TaxTypes.VAT, categoryCode: TaxCategoryCodes.S,
    allowanceChargeBasisAmount: -5.10m, lineTotalBasisAmount: 326.50m);

invoice.AddApplicableTradeTax(
    basisAmount: 127.59m, percent: 7m, taxAmount: 8.93m,
    typeCode: TaxTypes.VAT, categoryCode: TaxCategoryCodes.S,
    allowanceChargeBasisAmount: -3.11m, lineTotalBasisAmount: 130.70m);
```

## 11. Zahlungsbedingung mit Skonto

`paymentTermsType = Skonto` erzeugt den Block `ram:ApplicableTradePaymentDiscountTerms`
mit `BasisPeriodMeasure` (Tage) und `CalculationPercent`. Ohne diesen Typ bliebe nur der
Freitext übrig – der Skonto wäre dann maschinell nicht auswertbar.

```csharp
invoice.AddTradePaymentTerms(
    description: "Bei Zahlung innerhalb 14 Tagen gewähren wir 2,0% Skonto.",
    paymentTermsType: PaymentTermsType.Skonto,
    dueDays: 14,
    percentage: 2.00m);
```

## 12. Gesamtsummen

| BT-Code | Parameter | Rechenweg |
|---|---|---|
| BT-106 | `lineTotalAmount` | 100,00 + 72,50 + 0,00 + 180,00 + 46,50 + 58,20 = **457,20** |
| BT-108 | `chargeTotalAmount` | 3,00 (Transportkosten) |
| BT-107 | `allowanceTotalAmount` | 5,60 + 2,61 + 2,50 + 0,50 = **11,21** |
| BT-109 | `taxBasisAmount` | 457,20 + 3,00 − 11,21 = **448,99** |
| BT-110 | `taxTotalAmount` | 61,07 + 8,93 = **70,00** |
| BT-112 | `grandTotalAmount` | 448,99 + 70,00 = **518,99** |
| BT-113 | `totalPrepaidAmount` | 0,00 – keine Anzahlung |
| BT-115 | `duePayableAmount` | 518,99 − 0,00 = **518,99** |

```csharp
invoice.SetTotals(
    lineTotalAmount: 457.20m,      // BT-106
    chargeTotalAmount: 3.00m,      // BT-108
    allowanceTotalAmount: 11.21m,  // BT-107
    taxBasisAmount: 448.99m,       // BT-109
    taxTotalAmount: 70.00m,        // BT-110
    grandTotalAmount: 518.99m,     // BT-112
    totalPrepaidAmount: 0.00m,     // BT-113
    duePayableAmount: 518.99m);    // BT-115
```

## 13. Speichern

Erst beim Speichern entscheidet sich, welche der gesetzten Felder tatsächlich im XML
landen. Version, Profil und Syntax gehören zusammen.

```csharp
// Version25 + Profile.Extended + CII ergibt die Profilkennung
// "urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended".
invoice.Save("X19_01_Warenrechnung.xml",
             ZUGFeRDVersion.Version25,
             Profile.Extended,
             ZUGFeRDFormats.CII);
```

## 14. Gegenprobe

Die erzeugte Datei muss dieselbe Baumstruktur haben wie `X19_01_Warenrechnung.xml` aus
dem FeRD-Beispielpaket. Zahlen vergleicht man numerisch, damit `1.00` und `1.0000` als
gleich gelten – FactoorSharp schreibt Preise adaptiv mit zwei Nachkommastellen.

```csharp
// Lesefassung für Menschen – kein Rechtsdokument und kein hybrides ZUGFeRD-PDF.
// Gerendert wird aus dem Objekt, nicht aus der XML-Datei.
InvoiceVisualizer.RenderPdf(invoice, "X19_01_Warenrechnung.pdf");
InvoiceVisualizer.RenderHtml(invoice, "X19_01_Warenrechnung.html");
```

Validator, Visualizer und die ausführliche Dokumentation dazu liegen im Kunden-Bereich
unter <https://www.factoorsharp.de/support/>.

## Verwandte Seiten

- [Rechnungskorrektur](https://www.factoorsharp.de/de/Service/CorrectionInvoice.md): Typ 384 mit negativen Beträgen, abgegrenzt gegen die Gutschrift.
- [Rechnung in Fremdwährung](https://www.factoorsharp.de/de/Service/ForeignCurrencyInvoice.md): GBP mit Steuerbetrag zusätzlich in EUR samt Umrechnungskurs.
- [Los geht's](https://www.factoorsharp.de/de/Home/GettingStarted.md): Installation, Lizenzschlüssel und erste Rechnung.
- [Factur-X-Referenz](https://www.factoorsharp.de/de/Service/Documentation): XML-Elemente und BT-/BG-Nummern zum Nachschlagen.
