In Shopware 5 bearbeitest du das Rechnungsformular meist nicht unter „Formulare“, sondern in der PDF-Belegerstellung oder direkt im Dokument-Template. Für einfache Layout-Änderun...
Wie sieht das XML-Format einer ZUGFeRD-Rechnung mit Zuschlägen und mehreren Positionen aus?
Antwort vom## Klare Antwort **Eine ZUGFeRD-Rechnung mit mehreren Positionen und Zuschlägen besteht im XML nicht aus „irgendwelchen freien Tags“, sondern aus einer festen EN16931-/CII-Struktur: Kopf der Rechnung, Summen/Steuern und dann je Position ein `IncludedSupplyChainTradeLineItem`; Zuschläge stehen entweder auf Belegebene als `SpecifiedTradeAllowanceCharge` oder auf Positionsebene innerhalb der jeweiligen Zeile.** Die entscheidende praktische Folge: Wenn du Zuschläge einfach als zusätzliche Textzeile modellierst, ist die Rechnung oft fachlich lesbar, aber nicht sauber validierbar. ([en.e-rechnung-bund.de](https://en.e-rechnung-bund.de/e-invoicing-faq/xrechnung/)) ## So ist die Struktur wirklich aufgebaut Bei ZUGFeRD 2.x ist das XML in der Regel **UN/CEFACT Cross Industry Invoice (CII)**. Für mehrere Positionen wiederholt sich der Block `IncludedSupplyChainTradeLineItem` einfach mehrfach. Ein Zuschlag ist dagegen **kein eigener Fantasie-Knoten**, sondern fachlich eine **Charge**: - **Dokumentenzuschlag**: im Summenbereich der Rechnung - **Positionszuschlag**: innerhalb der betroffenen Rechnungsposition - **Normale weitere Leistung** wie „Versand“ oder „Verpackung“ kann alternativ auch als eigene Position modelliert werden, wenn sie wie ein abrechenbarer Artikel behandelt werden soll Genau dieser Unterschied wird in vielen Erklärungen zu oberflächlich behandelt: **„Versandkosten“ sind technisch nicht automatisch ein Zuschlag.** Wenn sie eine eigenständige abrechenbare Leistung sind, ist eine eigene Position oft sauberer; wenn sie ein echter Aufschlag auf die Rechnung oder auf eine Zeile sind, dann als Charge. ([bvbs.de](https://www.bvbs.de/wp-content/uploads/2024/04/ZUGFeRD-Implementierungs-Leitfaden-2.2_20240321.pdf)) ## Beispiel: ZUGFeRD-XML mit 2 Positionen und Dokumentenzuschlag Das folgende Beispiel ist **vereinfacht, aber strukturell nah an echtem CII/ZUGFeRD EN16931**. Es zeigt: - 2 Positionen - 1 Zuschlag auf Dokumentebene - Netto-/Steuer-/Bruttosummen ```xml <?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"> <rsm:ExchangedDocumentContext> <ram:GuidelineSpecifiedDocumentContextParameter> <ram:ID>urn:cen.eu:en16931:2017</ram:ID> </ram:GuidelineSpecifiedDocumentContextParameter> </rsm:ExchangedDocumentContext> <rsm:ExchangedDocument> <ram:ID>RE-2026-1001</ram:ID> <ram:TypeCode>380</ram:TypeCode> <ram:IssueDateTime> <udt:DateTimeString format="102">20260420</udt:DateTimeString> </ram:IssueDateTime> </rsm:ExchangedDocument> <rsm:SupplyChainTradeTransaction> <ram:IncludedSupplyChainTradeLineItem> <ram:AssociatedDocumentLineDocument> <ram:LineID>1</ram:LineID> </ram:AssociatedDocumentLineDocument> <ram:SpecifiedTradeProduct> <ram:Name>Artikel A</ram:Name> </ram:SpecifiedTradeProduct> <ram:SpecifiedLineTradeAgreement> <ram:NetPriceProductTradePrice> <ram:ChargeAmount>100.00</ram:ChargeAmount> </ram:NetPriceProductTradePrice> </ram:SpecifiedLineTradeAgreement> <ram:SpecifiedLineTradeDelivery> <ram:BilledQuantity unitCode="C62">2</ram:BilledQuantity> </ram:SpecifiedLineTradeDelivery> <ram:SpecifiedLineTradeSettlement> <ram:ApplicableTradeTax> <ram:TypeCode>VAT</ram:TypeCode> <ram:CategoryCode>S</ram:CategoryCode> <ram:RateApplicablePercent>19.00</ram:RateApplicablePercent> </ram:ApplicableTradeTax> <ram:SpecifiedTradeSettlementLineMonetarySummation> <ram:LineTotalAmount>200.00</ram:LineTotalAmount> </ram:SpecifiedTradeSettlementLineMonetarySummation> </ram:SpecifiedLineTradeSettlement> </ram:IncludedSupplyChainTradeLineItem> <ram:IncludedSupplyChainTradeLineItem> <ram:AssociatedDocumentLineDocument> <ram:LineID>2</ram:LineID> </ram:AssociatedDocumentLineDocument> <ram:SpecifiedTradeProduct> <ram:Name>Artikel B</ram:Name> </ram:SpecifiedTradeProduct> <ram:SpecifiedLineTradeAgreement> <ram:NetPriceProductTradePrice> <ram:ChargeAmount>50.00</ram:ChargeAmount> </ram:NetPriceProductTradePrice> </ram:SpecifiedLineTradeAgreement> <ram:SpecifiedLineTradeDelivery> <ram:BilledQuantity unitCode="C62">1</ram:BilledQuantity> </ram:SpecifiedLineTradeDelivery> <ram:SpecifiedLineTradeSettlement> <ram:ApplicableTradeTax> <ram:TypeCode>VAT</ram:TypeCode> <ram:CategoryCode>S</ram:CategoryCode> <ram:RateApplicablePercent>19.00</ram:RateApplicablePercent> </ram:ApplicableTradeTax> <ram:SpecifiedTradeSettlementLineMonetarySummation> <ram:LineTotalAmount>50.00</ram:LineTotalAmount> </ram:SpecifiedTradeSettlementLineMonetarySummation> </ram:SpecifiedLineTradeSettlement> </ram:IncludedSupplyChainTradeLineItem> <ram:ApplicableHeaderTradeAgreement> <ram:SellerTradeParty> <ram:Name>Muster GmbH</ram:Name> </ram:SellerTradeParty> <ram:BuyerTradeParty> <ram:Name>Kunde AG</ram:Name> </ram:BuyerTradeParty> </ram:ApplicableHeaderTradeAgreement> <ram:ApplicableHeaderTradeDelivery> <ram:ActualDeliverySupplyChainEvent> <ram:OccurrenceDateTime> <udt:DateTimeString format="102">20260420</udt:DateTimeString> </ram:OccurrenceDateTime> </ram:ActualDeliverySupplyChainEvent> </ram:ApplicableHeaderTradeDelivery> <ram:ApplicableHeaderTradeSettlement> <ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode> <ram:ApplicableTradeTax> <ram:CalculatedAmount>49.40</ram:CalculatedAmount> <ram:TypeCode>VAT</ram:TypeCode> <ram:BasisAmount>260.00</ram:BasisAmount> <ram:CategoryCode>S</ram:CategoryCode> <ram:RateApplicablePercent>19.00</ram:RateApplicablePercent> </ram:ApplicableTradeTax> <ram:SpecifiedTradeAllowanceCharge> <ram:ChargeIndicator> <udt:Indicator>true</udt:Indicator> </ram:ChargeIndicator> <ram:ActualAmount>10.00</ram:ActualAmount> <ram:Reason>Versandzuschlag</ram:Reason> <ram:CategoryTradeTax> <ram:TypeCode>VAT</ram:TypeCode> <ram:CategoryCode>S</ram:CategoryCode> <ram:RateApplicablePercent>19.00</ram:RateApplicablePercent> </ram:CategoryTradeTax> </ram:SpecifiedTradeAllowanceCharge> <ram:SpecifiedTradeSettlementHeaderMonetarySummation> <ram:LineTotalAmount>250.00</ram:LineTotalAmount> <ram:ChargeTotalAmount>10.00</ram:ChargeTotalAmount> <ram:TaxBasisTotalAmount>260.00</ram:TaxBasisTotalAmount> <ram:TaxTotalAmount currencyID="EUR">49.40</ram:TaxTotalAmount> <ram:GrandTotalAmount>309.40</ram:GrandTotalAmount> <ram:DuePayableAmount>309.40</ram:DuePayableAmount> </ram:SpecifiedTradeSettlementHeaderMonetarySummation> </ram:ApplicableHeaderTradeSettlement> </rsm:SupplyChainTradeTransaction> </rsm:CrossIndustryInvoice> ``` ## Beispiel: Zuschlag direkt an einer Position Wenn der Zuschlag **nur eine einzelne Position** betrifft, gehört er an die Zeile, nicht in den Kopf. Genau das wird in vielen Implementierungen falsch gemacht. Für line-level Charges/Allowances gibt es eigene Gruppen und Validierungsregeln. ([xoev.de](https://www.xoev.de/sixcms/media.php/13/211-XRechnung-2021-07-29.pdf)) Vereinfacht sieht das so aus: ```xml <ram:IncludedSupplyChainTradeLineItem> <ram:AssociatedDocumentLineDocument> <ram:LineID>1</ram:LineID> </ram:AssociatedDocumentLineDocument> <ram:SpecifiedTradeProduct> <ram:Name>Artikel A</ram:Name> </ram:SpecifiedTradeProduct> <ram:SpecifiedLineTradeAgreement> <ram:GrossPriceProductTradePrice> <ram:ChargeAmount>100.00</ram:ChargeAmount> <ram:AppliedTradeAllowanceCharge> <ram:ChargeIndicator> <udt:Indicator>true</udt:Indicator> </ram:ChargeIndicator> <ram:ActualAmount>5.00</ram:ActualAmount> <ram:Reason>Expressaufschlag</ram:Reason> </ram:AppliedTradeAllowanceCharge> </ram:GrossPriceProductTradePrice> <ram:NetPriceProductTradePrice> <ram:ChargeAmount>105.00</ram:ChargeAmount> </ram:NetPriceProductTradePrice> </ram:SpecifiedLineTradeAgreement> <ram:SpecifiedLineTradeDelivery> <ram:BilledQuantity unitCode="C62">2</ram:BilledQuantity> </ram:SpecifiedLineTradeDelivery> <ram:SpecifiedLineTradeSettlement> <ram:ApplicableTradeTax> <ram:TypeCode>VAT</ram:TypeCode> <ram:CategoryCode>S</ram:CategoryCode> <ram:RateApplicablePercent>19.00</ram:RateApplicablePercent> </ram:ApplicableTradeTax> <ram:SpecifiedTradeSettlementLineMonetarySummation> <ram:LineTotalAmount>210.00</ram:LineTotalAmount> </ram:SpecifiedTradeSettlementLineMonetarySummation> </ram:SpecifiedLineTradeSettlement> </ram:IncludedSupplyChainTradeLineItem> ``` ## Was in der Praxis oft schiefgeht Der wichtigste Unterschied ist: - **Eigene Position**: sinnvoll für Versand, Verpackung, Servicepauschale, wenn das als separat abrechenbare Leistung erscheinen soll - **Zuschlag/Charge**: sinnvoll, wenn es fachlich ein Aufschlag auf Rechnung oder Position ist - **Rabatt/Nachlass**: gleiche Struktur, aber `ChargeIndicator = false` Das ist nicht nur Stilfrage, sondern wirkt direkt auf Summenbildung, Steueraufschlüsselung und Validierung. Gerade bei EN16931 müssen Zuschläge und Nachlässe mit Betrag und Steuerbezug sauber modelliert werden. ([xoev.de](https://www.xoev.de/sixcms/media.php/13/211-XRechnung-2021-07-29.pdf)) ## Was du mindestens brauchst Für eine valide ZUGFeRD-Rechnung mit mehreren Positionen und Zuschlägen brauchst du mindestens: - Rechnungsnummer, Datum, Typ - Verkäufer und Käufer - Währung - je Position: laufende Nummer, Bezeichnung, Menge, Einheit, Preis, Steuer - Zuschlag entweder auf Kopf- oder Positionsebene - korrekte Summen: - Summe der Positionen - Summe Zuschläge - Steuerbasis - Steuerbetrag - Gesamtbetrag Die eigentliche Hürde ist meist **nicht das XML-Schreiben**, sondern die **konsistente Berechnung**. Wenn `LineTotalAmount`, `ChargeTotalAmount`, `TaxBasisTotalAmount`, `TaxTotalAmount` und `GrandTotalAmount` nicht exakt zusammenpassen, fällt die Rechnung bei der Validierung durch. Das ist der Punkt, an dem viele Beispielseiten zu ungenau bleiben. ([xoev.de](https://www.xoev.de/sixcms/media.php/13/211-XRechnung-2021-07-29.pdf)) ## Praktische Empfehlung **Wenn du ein ERP oder Shopsystem anbindest, modelliere Zuschläge nur dann als echte Charge, wenn sie fachlich ein Aufschlag sind; alles, was der Kunde als eigene abrechenbare Leistung sehen soll, ist meist besser als normale Rechnungsposition aufgehoben.** Das macht XML, Steuerlogik und spätere Verarbeitung deutlich rob