← Back to all articles

Häufige Peppol BIS 3.0-Validierungsfehler und wie man sie behebt

SealDoc Team · · 6 min read

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.

RegelFeldBTLösung
BR-01SpezifikationskennungBT-24CustomizationID mit der exakten Peppol-BIS-3.0-URI hinzufügen
BR-02RechnungsnummerBT-1Nicht-leeres ID-Element hinzufügen
BR-03RechnungsdatumBT-2IssueDate im Format JJJJ-MM-TT hinzufügen
BR-04RechnungswährungscodeBT-5DocumentCurrencyCode mit ISO-4217-Code hinzufügen
BR-05LieferantennameBT-27AccountingSupplierParty/Party/PartyName/Name hinzufügen
BR-06KäufernameBT-44AccountingCustomerParty/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 TaxAmount 0.00 ist statt zu fehlen
  • Der TaxAmount auf TaxTotal-Ebene unabhängig von den TaxSubtotal-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 TaxSubtotal existiert
  • Ein TaxSubtotal fü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-Wert S für alle Positionen unabhängig von der tatsächlichen USt.-Behandlung verwenden
  • TaxExemptionReasonCode oder TaxExemptionReason-Elemente, die für befreite Kategorien erforderlich sind, weglassen
  • AccountingSupplierParty/Party/PartyTaxScheme fehlt, 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.


← Back to all articles