Häufige Peppol BIS 3.0-Validierungsfehler und wie man sie behebt
Peppol-BIS-3.0-Validierungsfehler fallen in eine überschaubare Anzahl von Kategorien. Die Fehlermeldungen referenzieren Business-Rule-Codes (BR-xx) und Business-Term-Nummern (BT-xx) aus dem EN16931-Standard, zu deren Verständnis die Spezifikation gelesen werden muss. Dieser Artikel ordnet die häufigsten Fehler ihren Ursachen zu und bietet konkrete Lösungen.
Alle Beispiele verwenden UBL-2.1-Syntax. Für CII-Äquivalente siehe UBL vs. CII.
BR-01 bis BR-06: fehlende Pflicht-Header-Felder
Diese Regeln erzwingen die Anwesenheit von Pflichtfeldern auf der obersten Ebene. Sie schlagen fehl, wenn ein Element fehlt oder leer ist.
| Regel | Feld | BT | Lösung |
|---|---|---|---|
| BR-01 | Spezifikationskennung | BT-24 | CustomizationID mit der exakten Peppol-BIS-3.0-URI hinzufügen |
| BR-02 | Rechnungsnummer | BT-1 | Nicht-leeres ID-Element hinzufügen |
| BR-03 | Rechnungsdatum | BT-2 | IssueDate im Format JJJJ-MM-TT hinzufügen |
| BR-04 | Rechnungswährungscode | BT-5 | DocumentCurrencyCode mit ISO-4217-Code hinzufügen |
| BR-05 | Lieferantenname | BT-27 | AccountingSupplierParty/Party/PartyName/Name hinzufügen |
| BR-06 | Käufername | BT-44 | AccountingCustomerParty/Party/PartyName/Name hinzufügen |
BR-01 spezifisch: Die häufigste Ursache ist die Verwendung der EN16931-Basis-URI statt der Peppol-BIS-3.0-URI. Diese sehen ähnlich aus, sind aber verschieden:
Falsch (EN16931-Basis):
<cbc:CustomizationID>urn:cen.eu:en16931:2017</cbc:CustomizationID>
Richtig (Peppol BIS 3.0):
<cbc:CustomizationID>
urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1
</cbc:CustomizationID>
Der Validator prüft den genauen String. Hintergrund dazu finden Sie in der Peppol-BIS-3.0-Einführung.
BR-CO-10: Summe der Positionsbeträge stimmt nicht mit Gesamtbetrag überein
[BR-CO-10]-Sum of Invoice line net amount (BT-106) =
sum of Invoice line net amount (BT-131).
Diese Regel verlangt, dass LegalMonetaryTotal/LineExtensionAmount (BT-106) der Summe aller InvoiceLine/LineExtensionAmount-Werte (BT-131) entspricht.
Der Fehler ist fast immer ein Rundungsfehler. Wenn Sie jeden Positionsbetrag vor der Summierung einzeln runden, kann die Summe der gerundeten Werte von der gerundeten Summe der Rohwerte abweichen.
Falsch (Rundung pro Position, dann Summierung):
// Line 1: 3 × 33.333... = 100.00 (rounded)
// Line 2: 3 × 33.333... = 100.00 (rounded)
// Sum of rounded: 200.00
// But raw sum: 3 × 33.333... + 3 × 33.333... = 200.00 exactly in this case
Der Fehler wird deutlicher bei Sätzen wie 7 % USt. auf variierende Mengen, bei denen sich die Rundung über viele Positionen akkumuliert.
Richtiger Ansatz: Rohwerte (ungerundete) über alle Positionen summieren und dann einmal auf Aggregatebene runden:
var lineNetTotal = invoiceLines.Sum(l => l.Quantity * l.UnitPrice); // raw
var lineNetTotalRounded = Math.Round(lineNetTotal, 2, MidpointRounding.AwayFromZero);
BR-CO-15: Arithmetikfehler beim Rechnungs-USt.-Betrag
[BR-CO-15]-Invoice total VAT amount (BT-110) =
sum of VAT category tax amount (BT-117).
Der gesamte USt.-Betrag in TaxTotal/TaxAmount muss der Summe der TaxTotal/TaxSubtotal/TaxAmount-Werte über alle Steuerkategorien entsprechen.
Bei einer Rechnung mit einem einzigen Steuersatz scheint das trivial, aber Fehler entstehen, wenn:
- Mehrere USt.-Sätze vorhanden sind und die Rundung pro Kategorie statt auf das Aggregat angewendet wird
- Eine Null-Satz- oder Befreiungskategorie vorhanden ist und ihr
TaxAmount0.00ist statt zu fehlen - Der
TaxAmountaufTaxTotal-Ebene unabhängig von denTaxSubtotal-Beträgen berechnet wird
Lösung: Alle TaxSubtotal/TaxAmount-Werte zuerst berechnen, summieren und diese Summe als TaxTotal/TaxAmount-Wert verwenden. TaxTotal/TaxAmount nicht separat berechnen.
BR-CO-16: Fälliger Zahlungsbetrag
[BR-CO-16]-Amount due for payment (BT-115) =
Invoice total with VAT (BT-112) - Paid amount (BT-113) + Rounding amount (BT-114).
Wenn BT-113 (gezahlter Betrag) und BT-114 (Rundungsbetrag) nicht vorhanden sind, vereinfacht sich das zu BT-115 = BT-112. Der Fehler tritt auf, wenn PayableAmount und TaxInclusiveAmount um mehr als die erlaubte Rundungstoleranz abweichen.
Häufige Ursache: PayableAmount aus gerundeten Positionsbeträgen berechnen und TaxInclusiveAmount aus einer separaten Gesamtberechnung, die ein leicht abweichendes Ergebnis liefert.
Lösung: Einen einzigen kanonischen Gesamtbetrag berechnen und sowohl für TaxInclusiveAmount als auch für PayableAmount verwenden.
BR-S-08 und BR-S-09: USt.-Satz und Betragskonsistenz
[BR-S-08]-For each different value of VAT category rate (BT-119) where the
VAT category code (BT-118) is "S", the VAT category taxable amount (BT-116)
in a VAT breakdown (BG-23) shall equal the sum of Invoice line net amounts
(BT-131) where the VAT category code of the Invoice line (BT-151) is "S"
and the VAT rate for the Invoice line (BT-152) equals the VAT category rate.
Diese Regel gruppiert alle Positionen nach USt.-Satz und prüft, ob der Steuerbetrag in jedem TaxSubtotal der Summe der Positionen mit diesem Satz entspricht. Sie schlägt fehl, wenn:
- Eine Position einen USt.-Satz hat, für den kein
TaxSubtotalexistiert - Ein
TaxSubtotalfür einen Satz existiert, aber keine Positionen diesen Satz verwenden - Rundungsdifferenzen sich zwischen positions- und teilergebnisebene Berechnungen ansammeln
Lösung: TaxSubtotal-Elemente dynamisch aus den Positionen aufbauen, gruppiert nach (USt.-Kategoriecode, USt.-Satz), statt sie unabhängig zu konstruieren.
BR-E-01 / BR-AE-01: Rechnungen mit Reverse Charge und Steuerbefreiung
[BR-E-01]-An Invoice that contains an Invoice line (BG-25), a Document level
allowance (BG-20) or a Document level charge (BG-21) where the VAT category
code (BT-151) is "E" shall contain exactly one VAT breakdown...
Rechnungen mit befreiten (E), Reverse-Charge- (AE) oder Nullsatz-Kategorien (Z) erfordern spezifische TaxCategory-Strukturen, die sich von Standard-Satz-Rechnungen (S) unterscheiden.
Häufige Fehler:
ID-WertSfür alle Positionen unabhängig von der tatsächlichen USt.-Behandlung verwendenTaxExemptionReasonCodeoderTaxExemptionReason-Elemente, die für befreite Kategorien erforderlich sind, weglassenAccountingSupplierParty/Party/PartyTaxSchemefehlt, wenn die Rechnung Reverse Charge verwendet
Beim Reverse Charge (AE) muss die USt.-Kennung des Steuerschemas des Käufers vorhanden sein, und die USt.-Kennung des Lieferanten muss ebenfalls vorhanden sein.
Peppol-spezifische Erweiterungsregeln: Deutschland
Deutsche Peppol-Profile fügen Regeln über EN16931-Basis hinzu. Häufige Fehler:
BR-DE-TMP-32: Das Lieferdatum (BT-72) ist für deutsche B2G-Rechnungen erforderlich. Delivery/ActualDeliveryDate im Format JJJJ-MM-TT hinzufügen.
BR-DE-18: Entweder die USt.-Kennung des Lieferanten (BT-31) oder eine Steuernummer (BT-32) muss vorhanden sein. Fehlen beide, führt das zur Ablehnung. Wenn der Lieferant von der USt. befreit ist, BT-32 mit der Steuernummer angeben.
BR-DE-16: Die Käuferreferenz (BT-10, Leitweg-ID) ist für deutsche B2G-Rechnungen Pflicht. Das Format der Leitweg-ID wird geprüft: Sie muss dem Muster \d{2,12}-\d{4,12}-\d{2} entsprechen.
Effizientes Debuggen
Die Schematron-Fehlerausgabe enthält eine XPath-Position:
<svrl:failed-assert location="/Invoice[1]/cac:LegalMonetaryTotal[1]">
<svrl:text>[BR-CO-10]-Sum of Invoice line net amounts...</svrl:text>
</svrl:failed-assert>
Nutzen Sie die XPath-Position, um direkt zum fehlerhaften Element zu navigieren. Fügen Sie bei arithmetischen Regeln Debug-Ausgaben hinzu, die die Rohwerte vor der Rundung protokollieren, damit Sie die Ursache der Abweichung nachvollziehen können.
Die vorkompilierten XSLT-Dateien aus den Peppol-BIS-GitHub-Releases sind die maßgeblichen Validierungsartefakte. Führen Sie sie mit Saxon HE aus, wie in Peppol-BIS-3.0-Rechnungen in C# generieren beschrieben. Die Verwendung der neuesten Version ist wichtig: Regelwerke werden mit jedem Peppol-BIS-Release aktualisiert, und eine Regel, die gegen ein älteres XSLT besteht, kann gegen das aktuelle scheitern.
SealDoc und Validierungsfehler
SealDoc führt EN16931- und Peppol-BIS-3.0-Schematron-Validierung für jede Rechnung vor der Zustellung durch. Bei Validierungsfehlern gibt die API eine strukturierte Fehlerantwort zurück, die jeden Fehler seinem BR-Code, dem verletzten BT und der XPath-Position im eingereichten Dokument zuordnet.
Für Organisationen, die eine bestehende Rechnungsgenerierungspipeline debuggen, akzeptiert der öffentliche SealDoc-Validator UBL- und CII-Rechnungsdateien, führt das aktuelle Peppol-BIS-3.0-XSLT aus und gibt die vollständige Liste der Fehler mit Klartextbeschreibungen zurück. Die Regelwerke werden mit Peppol-BIS-Releases aktuell gehalten, sodass der Validator immer die Regeln widerspiegelt, die ein empfangender Access Point anwenden wird.