← Back to all articles

Typowe błędy walidacji Peppol BIS 3.0 i jak je naprawić

SealDoc Team · · 6 min read

Błędy walidacji Peppol BIS 3.0 wpadają w przewidywalny zestaw kategorii. Komunikaty o błędach odwołują się do kodów reguł biznesowych (BR-xx) i numerów terminów biznesowych (BT-xx) z normy EN16931, co wymaga lektury specyfikacji do interpretacji. Ten artykuł mapuje najczęstsze błędy na ich przyczyny i podaje konkretne rozwiązania.

Wszystkie przykłady używają składni UBL 2.1. Dla odpowiedników CII zob. UBL vs CII.

BR-01 do BR-06: brakujące obowiązkowe pola nagłówka

Te reguły wymuszają obecność obligatoryjnych pól najwyższego poziomu. Zawodzą, gdy element jest nieobecny lub pusty.

RegułaPoleBTRozwiązanie
BR-01Identyfikator specyfikacjiBT-24Dodaj CustomizationID z dokładnym URI Peppol BIS 3.0
BR-02Numer fakturyBT-1Dodaj niepusty element ID
BR-03Data wystawienia fakturyBT-2Dodaj IssueDate w formacie YYYY-MM-DD
BR-04Kod waluty fakturyBT-5Dodaj DocumentCurrencyCode z kodem ISO 4217
BR-05Nazwa sprzedawcyBT-27Dodaj AccountingSupplierParty/Party/PartyName/Name
BR-06Nazwa nabywcyBT-44Dodaj AccountingCustomerParty/Party/PartyName/Name

Specyfika BR-01: najczęstszą przyczyną jest użycie bazowego URI EN16931 zamiast URI Peppol BIS 3.0. Wyglądają podobnie, ale są różne:

Błędnie (baza EN16931):

<cbc:CustomizationID>urn:cen.eu:en16931:2017</cbc:CustomizationID>

Poprawnie (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>

Walidator sprawdza dokładny ciąg znaków. Kontekst tego, dlaczego ma to znaczenie, znajdziesz we wprowadzeniu do Peppol BIS 3.0.

BR-CO-10: suma kwot pozycji nie zgadza się z sumą

[BR-CO-10]-Sum of Invoice line net amount (BT-106) = 
sum of Invoice line net amount (BT-131).

Ta reguła wymaga, żeby LegalMonetaryTotal/LineExtensionAmount (BT-106) było równe sumie wszystkich wartości InvoiceLine/LineExtensionAmount (BT-131).

Błąd to niemal zawsze błąd zaokrąglania. Jeśli zaokrąglasz każdą kwotę pozycji niezależnie przed zsumowaniem, suma zaokrąglonych wartości może różnić się od zaokrąglonej sumy surowych wartości.

Błędnie (zaokrąglanie na poziomie pozycji, następnie sumowanie):

// 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

Błąd jest bardziej widoczny przy stawkach jak 7% VAT na różnych ilościach, gdzie zaokrąglanie kumuluje się na wielu pozycjach.

Poprawne podejście: zsumuj surowe, niezaokrąglone wartości dla wszystkich pozycji, a następnie zaokrąglij agregat raz:

var lineNetTotal = invoiceLines.Sum(l => l.Quantity * l.UnitPrice);  // raw
var lineNetTotalRounded = Math.Round(lineNetTotal, 2, MidpointRounding.AwayFromZero);

BR-CO-15: błąd arytmetyczny kwoty VAT faktury

[BR-CO-15]-Invoice total VAT amount (BT-110) = 
sum of VAT category tax amount (BT-117).

Całkowita kwota VAT w TaxTotal/TaxAmount musi być równa sumie wartości TaxTotal/TaxSubtotal/TaxAmount dla wszystkich kategorii podatkowych.

Dla faktury z jedną stawką wydaje się to trywialne, ale błędy występują gdy:

  • Istnieje wiele stawek VAT i zaokrąglanie jest stosowane do każdej kategorii zamiast do agregatu
  • Kategoria zerowej stawki lub zwolnienia jest obecna i jej TaxAmount wynosi 0.00 zamiast być nieobecna
  • TaxAmount na poziomie TaxTotal jest obliczana niezależnie od kwot TaxSubtotal

Rozwiązanie: najpierw oblicz wszystkie wartości TaxSubtotal/TaxAmount, zsumuj je i użyj tej sumy jako wartości TaxTotal/TaxAmount. Nie obliczaj TaxTotal/TaxAmount osobno.

BR-CO-16: kwota należna do zapłaty

[BR-CO-16]-Amount due for payment (BT-115) = 
Invoice total with VAT (BT-112) - Paid amount (BT-113) + Rounding amount (BT-114).

Jeśli BT-113 (kwota zapłacona) i BT-114 (kwota zaokrąglenia) nie są obecne, upraszcza się to do BT-115 = BT-112. Błąd pojawia się, gdy PayableAmount i TaxInclusiveAmount różnią się o więcej niż dopuszczalna tolerancja zaokrąglania.

Częsta przyczyna: obliczanie PayableAmount z zaokrąglonych kwot pozycji i TaxInclusiveAmount z osobnego obliczenia sumy, które daje nieco inny wynik.

Rozwiązanie: oblicz jedną kanoniczną sumę końcową i użyj jej zarówno dla TaxInclusiveAmount, jak i PayableAmount.

BR-S-08 i BR-S-09: spójność stawki i kwoty VAT

[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.

Ta reguła grupuje wszystkie pozycje według stawki VAT i weryfikuje, że kwota opodatkowania w każdym TaxSubtotal odpowiada sumie pozycji z tą stawką. Zawodzi gdy:

  • Pozycja ma stawkę VAT, dla której nie ma odpowiedniego TaxSubtotal
  • TaxSubtotal istnieje dla stawki, ale żadna pozycja nie używa tej stawki
  • Różnice w zaokrąglaniu kumulują się między obliczeniami na poziomie pozycji i poziomu podsumy

Rozwiązanie: buduj elementy TaxSubtotal dynamicznie z pozycji, grupując według (kod kategorii VAT, stawka VAT), zamiast konstruować je niezależnie.

BR-E-01 / BR-AE-01: faktury z odwrotnym obciążeniem i zwolnione z podatku

[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...

Faktury ze zwolnieniem (E), odwrotnym obciążeniem (AE) lub zerową stawką (Z) VAT wymagają specyficznych struktur TaxCategory, różnych od faktur ze standardową (S) stawką.

Typowe błędy:

  • Używanie wartości ID równej S dla wszystkich pozycji niezależnie od faktycznego traktowania VAT
  • Pomijanie elementów TaxExemptionReasonCode lub TaxExemptionReason wymaganych dla kategorii zwolnionych
  • Brakujący AccountingSupplierParty/Party/PartyTaxScheme gdy faktura stosuje odwrotne obciążenie

W przypadku odwrotnego obciążenia (AE) identyfikator VAT schematu podatkowego nabywcy musi być obecny, a identyfikator VAT sprzedawcy musi być również obecny.

Reguły rozszerzeń Peppol dla Niemiec

Niemieckie profile Peppol dodają reguły ponad bazę EN16931. Częste błędy:

BR-DE-TMP-32: data dostawy (BT-72) jest wymagana dla niemieckich faktur B2G. Dodaj Delivery/ActualDeliveryDate w formacie YYYY-MM-DD.

BR-DE-18: musi być obecny identyfikator VAT sprzedawcy (BT-31) lub numer rejestracji podatkowej (BT-32). Brak obu powoduje odrzucenie. Jeśli sprzedawca jest zwolniony z VAT, podaj BT-32 z numerem rejestracji podatkowej.

BR-DE-16: numer referencyjny nabywcy (BT-10, Leitweg-ID) jest obowiązkowy dla niemieckich faktur B2G. Format Leitweg-ID jest walidowany: musi pasować do wzorca \d{2,12}-\d{4,12}-\d{2}.

Efektywne debugowanie

Dane wyjściowe Schematron zawierają lokalizację XPath:

<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>

Użyj lokalizacji XPath, aby przejść bezpośrednio do błędnego elementu. Dla reguł arytmetycznych dodaj dane wyjściowe debugowania rejestrujące surowe wartości przed zaokrąglaniem, żebyś mógł śledzić, gdzie powstaje rozbieżność.

Wstępnie skompilowane pliki XSLT z wydań GitHub Peppol BIS to autorytatywne artefakty walidacyjne. Uruchamiaj je z Saxon HE, jak opisano w artykule generowanie faktur Peppol BIS 3.0 w C#. Ważne jest uruchamianie ich z najnowszym wydaniem: zestawy reguł są aktualizowane przy każdym wydaniu Peppol BIS, a reguła, która przechodzi starszy XSLT, może nie przejść bieżącego.

SealDoc a błędy walidacji

SealDoc uruchamia walidację Schematron EN16931 i Peppol BIS 3.0 dla każdej faktury przed dostarczeniem. Gdy walidacja nie powiedzie się, API zwraca ustrukturyzowaną odpowiedź błędu mapującą każde naruszenie na kod BR, naruszony BT i lokalizację XPath w przesłanym dokumencie.

Dla organizacji debugujących istniejący system generowania faktur publiczny walidator SealDoc akceptuje pliki faktur UBL i CII, uruchamia bieżący XSLT Peppol BIS 3.0 i zwraca pełną listę błędów z opisami w prostym języku. Zestawy reguł są aktualizowane na bieżąco z wydaniami Peppol BIS, więc walidator zawsze odzwierciedla reguły, które zastosuje odbierający Access Point.


← Back to all articles