Zum Inhalt springen

Feinkonzept §4.5 — Bau-Abrechnung (XRechnung / ZUGFeRD / Peppol, VOB/B §14)

Live in Produktion

Feinkonzept §4.5 — Bau-Abrechnung (XRechnung / ZUGFeRD / Peppol, VOB/B §14)

Abschnitt betitelt „Feinkonzept §4.5 — Bau-Abrechnung (XRechnung / ZUGFeRD / Peppol, VOB/B §14)“
Feld Wert
feature_id handwerk/05-bau-abrechnung
titel Bau-Abrechnung: XRechnung 3.0, ZUGFeRD 2.3, Peppol BIS 3, VOB/B-Teilzahlung, §13b/§48
version V1.0 (MVP) — Stand 19.04.2026
status DOR angenommen → Implementierung Sprint 26-Q2-A
referenzkunde musterbetrieb-maler (25-MA Maler Bayern, ~410 Rechnungen/Jahr) · shk-gebruder-schmidt (80-MA SHK NRW, ~1 800 Rechnungen/Jahr, Kommunal-Kunden Peppol-pflichtig)
modul Handwerk → §4.5 (Produktreifegrad V1 Pflicht: GAEB §4.3 + Aufmaß §4.4 + Nachtrag §4.2)
business-owner Paul Wagner (CFO Referenz-Beirat Werkszeit)
tech-owner Ingenieursteam „Rechnung“ (2 Backend, 1 Frontend, 1 QA, 0,4 Compliance)
geschätzt 84 Ingenieur-Tage (MVP) · +22 Tage Härtung · ∑ 106 Tage bis GA
kritikalität Geschäftskritisch — ohne konforme eRechnung kein Geldfluss; §14 VOB/B Ausschluss möglich
compliance-flags GoBD §147 AO (10 J.), §14 UStG, §14 Abs. 4 UStG, XRechnung 3.0 (KoSIT), EN 16931, §13b UStG, §48 EStG, §14 VOB/B, VOB/C DIN 18299, §4 Abs. 1 E-Rech-V, Peppol BIS 3.0, DSGVO Art. 6/17/30
quellen KoSIT XRechnung-Spezifikation 3.0.2 (Stand 2025-11-15) · EN 16931-1:2017+A1:2019+A2:2023 · Mustang-Library 2.14 · KoSIT-Validator 1.5.0 · OpenPeppol BIS Billing 3.0.17 · UStAE 13b.1 · § 48 EStG i.V.m. § 48b EStG · BFA-Merkblatt 2025

Der Bau ist im Pflicht-eRechnungs-Umstellungsjahr. Seit 01.01.2025 muss jeder Unternehmer in DE eine strukturierte eRechnung empfangen können (Wachstumschancengesetz, § 14 Abs. 1 Satz 2 UStG n.F.), die Pflicht zum Versand an B2B-Empfänger greift für KMU ab 01.01.2027 (Übergang 01.01.2028 für Kleinunternehmer < 800 k€ Vorjahresumsatz). Für öffentliche Auftraggeber gilt bereits seit 27.11.2020 die ERechV (Bundesverwaltung) plus 16 Landes-Verordnungen mit je eigenen Leitweg-IDs (Bund: 991-xxxxx-yyyy, Bayern: 04, NRW: eigene Regionsschlüssel via Mandanten-Leitweg).

Zwei Formate sind spezifikations-konform:

  • UBL 2.1 (OASIS Universal Business Language) — XML-Namespace urn:oasis:names:specification:ubl:schema:xsd:Invoice-2, empfohlen für Peppol-Flow.
  • UN/CEFACT CII (Cross Industry Invoice, D16B) — XML-Namespace urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100, Basis von ZUGFeRD.

Beide werden durch CIUS XRechnung (Core Invoice Usage Specification) eingeschränkt, sind aber nicht deckungsgleich: So ist BT-115 Paid amount in UBL optional, in XRechnung 3.0 bei Teilzahlungen bedingt Pflicht; BG-20 Document level allowances in CII technisch anders modelliert.

Hybride: ZUGFeRD 2.3 legt CII-XML als Attachment in ein PDF/A-3 — Vorteil: Lesbarkeit + Struktur, Nachteil: PDF/A-3 ist nicht von allen DMS akzeptiert (Adobe rendert, Archiv-Systeme teils nur PDF/A-1/2). Profile: MINIMUM, BASIC, EN 16931, EXTENDED, XRECHNUNG (Zielprofil für DE-eRechnung).

Peppol BIS 3.0 Billing: Für Grenzüberschreitenden Versand (EU öffentliche Auftraggeber, Skandinavien mandatorisch, NL/BE teils Pflicht) und optional als 4-Corner-Model (Sender-AP → SMP-Lookup → Receiver-AP → Empfänger). DE-Peppol-Authority (KoSIT) schreibt ISO 20022 Schematron vor.

2.2 VOB/B §14 — Prüfbarkeit von Bau-Rechnungen

Abschnitt betitelt „2.2 VOB/B §14 — Prüfbarkeit von Bau-Rechnungen“

VOB/B § 14 Abs. 1: “Die Rechnungen sind übersichtlich aufzustellen”. § 14 Abs. 2: “Teilrechnungen” — monatlich zulässig, kumulative Aufstellung (Bruttoleistung bis Stichtag ./. bereits geleistete Abschläge = Zahlungs-Saldo). § 14 Abs. 3: “Schlussrechnung” — prüfbar muss enthalten: vollständige Positions-Nachweise, Aufmaß-Referenzen (→ §4.4), Preisermittlung, Nachträge (→ §4.2). § 14 Abs. 4: Prüfungs-Frist Auftraggeber — Teilrechnung 21 Tage, Schlussrechnung 30 Tage (bei Bund 60 Tage).

Eine XRechnung, die VOB-Teilrechnung abbildet, muss kumulativ sein. EN 16931 kennt BT-113 Paid amount (bereits gezahlt), aber die kumulative Logik (bis-heute-Brutto ./. bis-gestern-gezahlt = heutiger Zahlbetrag) ist nicht im Core-Modell — wir lösen das über INVOICE_TYPE_CODE=386 Prepayment invoice bzw. CIUS-XRechnung-Erweiterung + BG-22 Document totals mit vertraglich vereinbarter Kumulations-Logik. Die Kumulation wird im Begleittext (BT-22 Invoice note) menschen-lesbar ausgewiesen — KoSIT-Validator meckert sonst nicht, aber der Architekt tut es.

Reverse-Charge (Umkehr der Steuerschuldnerschaft) gilt nach §13b Abs. 2 Nr. 4 i.V.m. Abs. 5 Satz 2 UStG für Bauleistungen an Bau-Unternehmer. Kriterium: Der Leistungsempfänger führt selbst nachhaltig Bauleistungen aus (> 10 % Umsatzanteil) und legt Bescheinigung USt 1 TG (gültig 3 Jahre) vor. Rechtsfolge:

  • Rechnungssteller schreibt Netto aus, kein USt-Ausweis.
  • Hinweis nach § 14 Abs. 4 Nr. 8 UStG zwingend: “Steuerschuldnerschaft des Leistungsempfängers”.
  • In XRechnung: BT-96 VAT category code = AE (VAT Reverse Charge) auf Ebene BG-23 VAT breakdown.
  • BT-118 VAT category rate = 0,00 Prozent, BT-120 VAT exemption reason text = „§ 13b UStG“.

Bei fehlerhafter Anwendung haftet der Rechnungssteller für die USt. Bei fehlerhafter Nicht-Anwendung (Ausweis von USt bei Reverse-Charge) droht dem Empfänger der Vorsteuer-Ausschluss.

Leistungsempfänger (Unternehmer oder JurPerson öffentl. Rechts) muss 15 % des Rechnungsbetrags einbehalten und ans FA des Leistenden abführen — es sei denn, Leistender legt gültige Freistellungsbescheinigung nach § 48b EStG vor. Bagatellgrenze: Rechnung ≤ 5 000 € (Bau-Unternehmer) bzw. ≤ 15 000 € (Vermieter mit ≤ 2 Wohnungen). In XRechnung nicht abbildbar (keine BT-Referenz); wir informieren über BT-22 Invoice note mit Bescheinigungs-Nr + Gültigkeit. Im Abrechnungs-Workflow blockieren wir den Versand, wenn Freistellung fehlt ∧ Betrag > Bagatelle.

  • DATEV Lexware, Sage u. a. können XRechnung — aber nicht kumulative Teilrechnungen nach VOB/B §14 Abs. 2 (Workaround: Handschlag-PDFs).
  • Aufmaß-→-Rechnung-Kopplung fehlt in fast allen Office-Suiten; LV-Positionen werden doppelt gepflegt.
  • Peppol-AP-Anbindung ist Kapitän-schwierig (Zertifikat-Management, SMP-Lookup, Delivery-Receipts).
  • KoSIT-Validator lokal zu betreiben ist Java-lastig (JRE 17+) — Handwerk will SaaS, nicht Java-Installer.

Wir bauen eine Rechnung-Engine, die aus LV-Positionen (→ §4.3) + freigegebenem Aufmaß (→ §4.4) + akzeptierten Nachträgen (→ §4.2) XRechnung-UBL + PDF/A-3 ZUGFeRD-Profil XRECHNUNG erzeugt, mit kumulativer VOB-Teil-/Schlussrechnungs-Logik, Reverse-Charge-Pflichthinweis-Automatik und Peppol-Versand via Access-Point. Empfangene eRechnungen werden automatisch validiert (KoSIT 1.5.0 + Mustang 2.14 + Peppol-Schematron) und als prüffähig gegen den korrespondierenden LV-Plan abgeglichen.

Ziel: 99,5 % KoSIT-Konformität beim Erstversuch, TTR < 3 Minuten vom Aufmaß-Freigabe bis versandbereite XRechnung, Zero-Manual-Entry bei VOB-Teilrechnungs-Kumulation.


3.1 Primär: Paul Wagner — CFO shk-gebruder-schmidt

Abschnitt betitelt „3.1 Primär: Paul Wagner — CFO shk-gebruder-schmidt“
  • Kontext: 80-MA-SHK-Betrieb, 1 800 Rechnungen/Jahr, davon ~210 Kommunal (Peppol-pflichtig ab Leitweg), Rest Gewerbe / Privat.
  • Gerät: Web am 27“-Bildschirm, Dual-Monitor; Outlook als zweites Fenster für PDF-Empfang.
  • Schmerzen: Bislang 3,5 VZÄ in Buchhaltung, davon 1,5 NUR für Rechnungs-PDF-Aufbereitung + manuelle XRechnung-Erstellung in OpenXRechnung-Tool.
  • Erfolg: < 10 Minuten/Rechnung, inkl. Prüfung. Peppol-Mandaten-Onboarding ohne IT-Dienstleister.

3.2 Primär: Anja Beltz — Leiterin Buchhaltung musterbetrieb-maler

Abschnitt betitelt „3.2 Primär: Anja Beltz — Leiterin Buchhaltung musterbetrieb-maler“
  • Kontext: 25-MA-Maler, ~410 Rechnungen/Jahr, kaum Peppol-Bedarf, aber §13b + §48 häufig (Subunternehmer-Ketten).
  • Gerät: Laptop + Second-Screen. Ggf. Handy für Freigabe vom Inhaber.
  • Schmerzen: §48 EStG vergessen → Haftung. Freistellungs-Bescheinigungen auf Papier im Ordner.
  • Erfolg: System warnt vor Versand, wenn Bescheinigung abgelaufen oder fehlt; automatische Prüfung USt 1 TG bei §13b.
  • Kontext: Erstellt keine Rechnungen, aber signiert Aufmaß-Freigaben vor Ort (→ §4.4), die als Basis der Rechnung dienen. Bekommt Benachrichtigung, wenn Architekt die Rechnung zurückweist, weil Aufmaß unklar.
  • Erfolg: Sieht Rechnungs-Status mit seinem Aufmaß-Block zugeordnet, kann binnen 24 h Rückfrage telefonisch klären.

3.4 Sekundär: Architektin Dr. Ina Pietsch (Rechnungs-Empfängerin Architektin des Bauherrn)

Abschnitt betitelt „3.4 Sekundär: Architektin Dr. Ina Pietsch (Rechnungs-Empfängerin Architektin des Bauherrn)“
  • Kontext: Prüft VOB-Teilrechnungen der Auftragnehmer. Will XRechnung + PDF/A-3-Visualisierung, Aufmaß-Referenz pro Position, Nachtrags-Positionen sauber ausgewiesen.
  • Erfolg: Rechnung lässt sich maschinell ins Prüf-Programm (z. B. „California“ von RIB) importieren + VOB-konform prüfen.

  • US-05-01 · Als Buchhalterin will ich aus freigegebenen Aufmaß-Positionen (→ §4.4) eine XRechnung erzeugen, sodass ich keine LV-Position doppelt eintippe. (DOR: §1.1 Referenzkunde shk-gebruder-schmidt · §1.2 Modul 4.5 · §1.3 §14 UStG, XRechnung 3.0)
  • US-05-02 · Als CFO will ich kumulative VOB/B-§14-Abs.-2-Teilrechnungen mit Abzug der bisherigen Abschläge, sodass der Architekt die Prüfbarkeit bestätigt.
  • US-05-03 · Als Buchhalterin will ich bei §13b-Empfängern automatisch Reverse-Charge (USt=0, Hinweistext), sodass ich nicht haftbar werde.
  • US-05-04 · Als CFO will ich vor Versand einen Block, wenn § 48 EStG Freistellung fehlt oder abgelaufen ist (und Betrag > 5 000 €), sodass Bauabzugssteuer korrekt abgeführt wird.
  • US-05-05 · Als Buchhalterin will ich Versand via Peppol Access Point mit Delivery-Receipt, sodass Kommunal-Empfänger die Rechnung rechtssicher erhalten.
  • US-05-06 · Als CFO will ich jede ausgehende XRechnung mit KoSIT 1.5.0 validiert bekommen (Schematron + Codeliste), sodass Retouren < 0,5 %.
  • US-05-07 · Als Buchhalterin will ich eingehende XRechnungen automatisch parsen + mit LV abgleichen, sodass Abweichungen binnen 24 h auffallen.
  • US-05-08 · Als Monteur will ich Push-Nachricht, wenn mein Aufmaß in eine Rechnung eingeflossen und bezahlt wurde, sodass ich die Baustelle abschließen kann.
  • US-05-09 · Als Buchhalterin will ich Storno via § 14 Abs. 4 UStG + Gutschrift-Hinweis (INVOICE_TYPE_CODE=381), sodass GoBD-konform.
  • US-05-10 · Als Datenschutzbeauftragte will ich Art.-17-DSGVO-Löschung nach Ablauf der 10-Jahres-GoBD-Frist, sodass Privatpersonen-Adressen nicht ewig vorgehalten werden.
  • US-05-11 · Als IT-Admin will ich Peppol-Zertifikat-Rotation automatisch 30 Tage vor Ablauf, sodass Versand nicht stoppt.
  • US-05-12 · Als CFO will ich DATEV-Export (DATEV-Format Buchungsstapel-CSV v7 + XRechnung-XML als Beleg-Link), sodass Steuerberater arbeiten kann.
  • US-05-13 · Als Referenzkunde will ich Mandanten-Freigabe-Workflow (CFO sieht, Inhaber signiert) vor Versand bei Rechnungen > 25 000 €.

R-01 Engine generiert XRechnung 3.0.2 UBL 2.1 (default) ODER CII D16B (je Empfänger-Präferenz, Feld debitor.ausgabeformat). R-02 Engine liest LV-Version (immutable_at > 0) + Aufmaß-Blöcke (immutable_at > 0) + akzeptierte Nachträge (status=akzeptiert). Keine anderen Quellen (keine „freien“ Positionen außer Abschlags-Einbehalte). R-03 Kumulation VOB §14 Abs. 2: Engine zieht alle bisherigen Teilrechnungen derselben bauvorhaben_id heran, summiert bezahlte_beträge und einbehaltene_beträge (Sicherheits-Einbehalt 5 %, Gewährleistungs-Einbehalt 3 %), bildet zahlungsanspruch_aktuell = brutto_kumuliert - bereits_bezahlt_kumuliert - einbehalten_kumuliert. R-04 Reverse-Charge-Automatik: Wenn debitor.ust_1_tg_bescheinigung.gueltig_bis >= heuteBT-96=AE, kein USt-Ausweis, Hinweistext Pflicht; GoBD-Log. R-05 §48-EStG-Pre-Check: Wenn leistender.freistellungsbescheinigung_48b.gueltig_bis < versand_datumbrutto > 5 000 €Versand blockiert, Meldung mit Handlungsempfehlung. R-06 Leitweg-ID: Pflichtfeld BT-10 Buyer reference für öff. Auftraggeber. System prüft Format via Regex pro Land (Bund \d{3}-[A-Z\d]{1,30}-\d{2}, Bayern 2-stellig, NRW mehrstellig). Fehler → Block. R-07 PDF/A-3-Anhang (ZUGFeRD): Engine rendert Rechnung nach XSL-FO → FOP 2.9 → PDF/A-3 + embedded CII-XML (Name factur-x.xml). R-08 Peppol-Versand: Wenn debitor.peppol_id vorhanden → SMP-Lookup (OpenPeppol Directory), AS4-Push zu Access Point (V1: B2BRouter Managed-AP, V2: eigenes Zertifikat). Delivery-Receipt persistent speichern. R-09 E-Mail-Versand (Fallback): PDF/A-3 als Attachment, signiert via S/MIME optional. UBL-XML auf Wunsch als zweites Attachment. R-10 KoSIT-Validierung erfolgt für jede ausgehende Rechnung vor Versand (nicht asynchron). Fehler = FATAL → Versand blockiert. Fehler = WARNING → Versand erlaubt, Log-Eintrag.

R-11 Eingangs-Kanäle: E-Mail (IMAP-Import oder MX-Forward an rechnung@<tenant>.werkszeit.io), Peppol-AP (inbound push), Manueller Upload (PDF oder XML). R-12 Format-Detection: MIME-Sniff + XML-Root-Element; ZUGFeRD extrahiert CII-XML aus PDF/A-3 via iText 8.0 (BouncyCastle für Signaturen). R-13 Validierung: KoSIT 1.5.0 (ohne PDF/A-Check) + Mustang 2.14 (PDF/A-3 Conformance) + Peppol-Schematron (optional). R-14 LV-Abgleich: Bei vorhandenem bauvorhaben_id (aus BT-11 Project reference oder manueller Zuordnung) versucht System, Rechnungs-Positionen den LV-Positionen per OZ-Match (→ §4.3) zuzuordnen. Abweichung > 2 % → Warnung. R-15 §13b-Empfang-Check: Wenn wir Leistungsempfänger sind ∧ Rechnung weist § 13b aus ∧ wir erfüllen Bau-Kriterium → System schlägt Reverse-Charge-Buchung vor (0 % USt + Meldung in USt-VA Zeile 87).

R-16 Storno: INVOICE_TYPE_CODE=381 (credit note) mit BT-25 Preceding invoice reference. Originalrechnung erhält Status=storniert_durch, nicht hart gelöscht (GoBD). R-17 Korrektur per Neu-Ausstellung: Originalrechnung stornieren (R-16), neue Rechnung mit Bezug. System legt beides atomar an.

R-18 Jede ausgehende XRechnung (UBL/CII-XML) + PDF/A-3 wird in S3 mit Object Lock Compliance Mode, 10 Jahre abgelegt. SHA-256 im rechnung_blob + Hash-Chain mit Vorgänger. R-19 KoSIT-Validator-Report als report.xml beigefügt, gleiche Hash-Chain. R-20 Append-only in DB; Änderungen nur über Storno+Neu-Ausstellung.

  • Performance: XRechnung-Generierung < 900 ms p95 für bis zu 200 Positionen.
  • Durchsatz: 500 Rechnungen/Tag pro Tenant bei shk-gebruder-schmidt.
  • Verfügbarkeit: 99,5 % (Werktage 06–20 Uhr); Peppol-AP darf nachts 4 h Wartung haben.
  • Offline: Nein. Rechnungserstellung ist desk-office, Online-Pflicht für KoSIT-Validator.
  • Auditierbarkeit: 100 % der Rechnungen mit Hash-Chain, Revisions-Log, Validator-Bericht.
  • A11y: PDF/A-3 muss WCAG 2.1 AA sein (tagged PDF).

6.1 Hauptscreen Web — „Rechnung erstellen“ (Desk-Office, Paul Wagner)

Abschnitt betitelt „6.1 Hauptscreen Web — „Rechnung erstellen“ (Desk-Office, Paul Wagner)“
┌──────────────────────────────────────────────────────────────────────────────────────────┐
│ WERKSZEIT · Gebrüder Schmidt GmbH (NRW) [Paul Wagner · CFO] Mo 19.04.2026 [⚙] [?] │
├──────────────────────────────────────────────────────────────────────────────────────────┤
│ Sidebar │ Handwerk › Abrechnung › BV "Stadthalle Krefeld" › Teilrechnung Nr. 4 │
│ Zeit │──────────────────────────────────────────────────────────────────────────── │
│ Dispo │ [Status: ENTWURF] [⚠ Reverse-Charge aktiv · USt 1 TG bis 30.06.2027] │
│ LV │ │
│ »Rechnung« │ Rechnung: TR-2026-00471 BV-ID: 000123 Leitweg-ID: – │
│ Nachtrag │ Debitor: Stadt Krefeld, Hochbauamt Peppol-ID: 0204:DE220612345 │
│ Material │ Empfänger-Präferenz: ⓘ XRechnung UBL 2.1 │
│ Mängel │─────────────────── VOB §14 Abs. 2 — Kumulation ────────────────────────────│
│ Doku │ Brutto bisher kumuliert (TR 1–3) € 182 340,22 │
│ │ + Leistung diesen Zeitraum (TR 4) € 58 117,90 │
│ │ = Brutto kumuliert € 240 458,12 │
│ │ – Bereits bezahlt (TR 1 + TR 3, inkl.) € 168 406,40 │
│ │ – Sicherheits-Einbehalt 5 % € 12 022,91 │
│ │ = Auszahlungsbetrag diese Rechnung € 60 028,81 │
│ │──────────────────────────────────────────────────────────────────────────── │
│ │ Positionen (aus LV v7 + Aufmaß-Block #A-118 freigegeben 17.04.2026): │
│ │ ┌────┬───────────────────────────┬──────┬─────┬──────────┬──────────────┐ │
│ │ │ OZ │ Kurztext │ Menge│ Ein.│ EP € │ GP € │ │
│ │ ├────┼───────────────────────────┼──────┼─────┼──────────┼──────────────┤ │
│ │ │01.02.030│ Putz-Innenwand abreißen│ 214,7│ m² │ 12,40│ 2 662,28 │ │
│ │ │01.02.040│ Gipsputz Q2 auftragen │ 214,7│ m² │ 28,90│ 6 204,83 │ │
│ │ │01.03.010│ Malerarbeiten lattenl.│ 214,7│ m² │ 11,20│ 2 404,64 │ │
│ │ │02.NT.001│ Nachtrag Dämmung EPS │ 48,0│ m² │ 42,00│ 2 016,00 │ │
│ │ │… (27 weitere Positionen sichtbar mit Scroll) │ │
│ │ └────┴───────────────────────────┴──────┴─────┴──────────┴──────────────┘ │
│ │ │
│ │ ⓘ Reverse-Charge §13b: USt-Betrag = 0,00 € │
│ │ ⚠ §48 EStG: Freistellungsbescheinigung Ihrer Firma gültig bis 31.12.2028 ✓ │
│ │ │
│ │ [ ] XRechnung UBL 2.1 + [x] PDF/A-3 (ZUGFeRD XRECHNUNG-Profil) │
│ │ │
│ │ [Validieren KoSIT 1.5.0 →] [Versand ➜ Peppol] │
│ │ │
├──────────────────────────────────────────────────────────────────────────────────────────┤
│ Paul Wagner · CFO · [email protected] [Audit-Log] [Exports] [Support] │
└──────────────────────────────────────────────────────────────────────────────────────────┘
┌───────────────── KoSIT-Validator 1.5.0 · Szenario „XRechnung 3.0.2 UBL" ──────────────────┐
│ │
│ ✓ 0 FATAL · 0 ERROR · 1 WARNING · 0 INFO Dauer 642 ms │
│ │
│ ⚠ BR-CO-15 Aufmaßreferenz `BT-DEX-30` empfohlen │
│ Kontext: Position 01.02.030 enthält keine REB-DA11-Referenz im Annotation-Block. │
│ Wirkung: Kein Versand-Block. Architekt prüft manuell. │
│ [Ignore] [Fix & erneut validieren] │
│ │
│ ✓ Schema: UBL-Invoice-2.xsd │
│ ✓ Schematron: xrechnung-UBL-validation.sch (v3.0.2) │
│ ✓ Codelisten: EAS, Currency (ISO 4217), UNTDID 1001 Document Type │
│ ✓ PDF/A-3 Conformance (Mustang 2.14) · factur-x.xml eingebettet, XMP-Metadaten ok │
│ │
│ Report-Download: [XML] [HTML] Hash-Chain: 4f9c8e…2a7e ← [vorige: bb21…c6a1] │
│ │
│ [Abbrechen] [Zurück] [Versand bestätigen]│
└────────────────────────────────────────────────────────────────────────────────────────────┘
┌────────────────────────┐
│ 11:42 ●●●●● 100 % │
├────────────────────────┤
│ ← BV Stadthalle Kref.│
├────────────────────────┤
│ │
│ [Aufmaß-Block A-118] │
│ Freigegeben 17.04. │
│ 214,7 m² Innenwand │
│ │
│ Status: │
│ ┌──────────────────┐ │
│ │● Aufmaß │ │
│ │● Rechnung erst. │ │
│ │● KoSIT ok │ │
│ │● Versand Peppol │ │
│ │ Architekt prüft │ │
│ │ ⏳ noch 9 Tage │ │
│ └──────────────────┘ │
│ │
│ TR-2026-00471 │
│ 60 028,81 € netto │
│ │
│ [Rückfrage öffnen] │
│ │
├────────────────────────┤
│ [Heute] [BV] [Prof.] │
└────────────────────────┘
Anja (Buchhaltung) Werkszeit-Backend KoSIT-Lambda Peppol-AP (B2BRouter) Debitor
│ │ │ │ │
│ 1. „Neue Rechnung" │ │ │ │
├────────────────────►│ │ │ │
│ │ 2. lädt LV-v7 │ │ │
│ │ + Aufmaß-Block │ │ │
│ │ + Nachträge │ │ │
│ │ 3. berechnet │ │ │
│ │ Kumulation │ │ │
│ │ + Reverse-Chg │ │ │
│ 4. UI zeigt Entwurf │ │ │ │
│◄────────────────────┤ │ │ │
│ 5. „Validieren" │ │ │ │
├────────────────────►│ 6. generiert UBL │ │ │
│ │ + PDF/A-3 │ │ │
│ ├─────────────────► │ 7. validate │ │
│ │ │ (0 FATAL) │ │
│ │◄──────────────────┤ │ │
│ 8. „Versand" │ │ │ │
├────────────────────►│ 9. SMP-Lookup │ │ │
│ ├───────────────────────────────────────►│ │
│ │ │ 10. AS4-Push │
│ │ ├────────────────────►│
│ │ │◄────────────────────┤
│ │◄───────────────────────────────────────┤ 11. Receipt │
│ 12. Status=VERSANDT │ │ │ │
│◄────────────────────┤ │ │ │

packages/db/schema/rechnung.ts
export const rechnung = pgTable("rechnung", {
id: uuid("id").primaryKey().defaultRandom(), // UUID v7
tenant_id: uuid("tenant_id").notNull(),
bauvorhaben_id: uuid("bauvorhaben_id"), // null bei Nicht-Bau
debitor_id: uuid("debitor_id").notNull(),
rechnungs_nr: text("rechnungs_nr").notNull(), // fortlaufend, Tenant-scoped, §14 (4) Nr. 4 UStG
typ: rechnungstyp("typ").notNull(), // 'teilrechnung' | 'schlussrechnung' | 'abschlag' | 'storno' | 'gutschrift'
invoice_type_code: text("invoice_type_code").notNull(), // UNCL 1001: 380, 381, 386 ...
waehrung: char("waehrung", { length: 3 }).notNull().default("EUR"),
ausstellungs_datum: date("ausstellungs_datum").notNull(),
leistungs_zeitraum_von: date("leistungs_zeitraum_von"),
leistungs_zeitraum_bis: date("leistungs_zeitraum_bis"),
faelligkeit: date("faelligkeit").notNull(),
leitweg_id: text("leitweg_id"), // BT-10
netto_aktuell_cent: bigint("netto_aktuell_cent", { mode: "bigint" }).notNull(),
ust_cent: bigint("ust_cent", { mode: "bigint" }).notNull(),
brutto_aktuell_cent: bigint("brutto_aktuell_cent", { mode: "bigint" }).notNull(),
brutto_kumuliert_cent: bigint("brutto_kumuliert_cent", { mode: "bigint" }).notNull(), // VOB §14 Abs. 2
bereits_gezahlt_cent: bigint("bereits_gezahlt_cent", { mode: "bigint" }).notNull(),
sicherheits_einbehalt_cent: bigint("sicherheits_einbehalt_cent", { mode: "bigint" }).notNull(),
gewaehrleistungs_einbehalt_cent: bigint("gewaehrleistungs_einbehalt_cent", { mode: "bigint" }).notNull(),
zahlungsanspruch_cent: bigint("zahlungsanspruch_cent", { mode: "bigint" }).notNull(),
reverse_charge: boolean("reverse_charge").notNull().default(false),
reverse_charge_grund: text("reverse_charge_grund"), // "§ 13b UStG" oder BT-120-Text
paragraph_48_estg_pruefung: jsonb("paragraph_48_estg_pruefung").notNull(), // {freistellung: true, gueltig_bis: '...'} oder {abzug_cent: 150000}
lv_version_id: uuid("lv_version_id"), // FK auf §4.3
ausgabeformat: text("ausgabeformat").notNull(), // 'xrechnung-ubl' | 'xrechnung-cii' | 'zugferd-xrechnung' | 'zugferd-en16931'
versandkanal: text("versandkanal"), // 'peppol' | 'email' | 'manual' | 'download'
status: text("status").notNull(), // 'entwurf' | 'validiert' | 'versandt' | 'bezahlt' | 'storniert_durch' | 'mahnung_1' | 'mahnung_2' | 'gerichtlich'
storniert_durch_rechnung_id: uuid("storniert_durch_rechnung_id"),
vorheriger_rechnung_id: uuid("vorheriger_rechnung_id"), // Kette der Teilrechnungen (BV-scope)
erstellt_von: uuid("erstellt_von").notNull(),
erstellt_am: timestamp("erstellt_am", { withTimezone: true }).notNull().defaultNow(),
immutable_at: timestamp("immutable_at", { withTimezone: true }), // gesetzt bei Versand
hash_prev: bytea("hash_prev").notNull(), // 32 Byte SHA-256
hash_self: bytea("hash_self").notNull(), // 32 Byte SHA-256
}, (t) => ({
tenantIdx: index("rechnung_tenant_idx").on(t.tenant_id, t.erstellt_am.desc()),
bvIdx: index("rechnung_bv_idx").on(t.tenant_id, t.bauvorhaben_id, t.typ, t.erstellt_am),
rnrUnique: uniqueIndex("rechnung_rnr_tenant_uq").on(t.tenant_id, t.rechnungs_nr),
debitorIdx: index("rechnung_debitor_idx").on(t.tenant_id, t.debitor_id, t.status),
}));
export const rechnung_position = pgTable("rechnung_position", {
id: uuid("id").primaryKey().defaultRandom(),
tenant_id: uuid("tenant_id").notNull(),
rechnung_id: uuid("rechnung_id").notNull(),
position_nr: integer("position_nr").notNull(),
oz: text("oz").notNull(), // 01.02.030 (→ §4.3)
lv_knoten_id: uuid("lv_knoten_id"), // FK auf lv_knoten
aufmass_block_id: uuid("aufmass_block_id"), // FK auf §4.4
kurztext: text("kurztext").notNull(),
langtext_md: text("langtext_md"),
menge: numeric("menge", { precision: 18, scale: 6 }).notNull(), // negative bei Gutschrift
einheit: text("einheit").notNull(), // m², m, Stk, Psch
ep_cent: bigint("ep_cent", { mode: "bigint" }).notNull(),
gp_cent: bigint("gp_cent", { mode: "bigint" }).notNull(),
ust_satz_bps: integer("ust_satz_bps").notNull(), // 0 bei Reverse-Charge, 1900 = 19,00 %
ust_category: text("ust_category").notNull(), // 'S', 'AE', 'Z', 'E', 'G', 'K', 'O'
ust_exemption_reason: text("ust_exemption_reason"), // BT-120
nachtrag_id: uuid("nachtrag_id"),
ist_abschlag: boolean("ist_abschlag").notNull().default(false),
}, (t) => ({
rechIdx: index("rp_rech_idx").on(t.tenant_id, t.rechnung_id, t.position_nr),
}));
export const rechnung_blob = pgTable("rechnung_blob", {
id: uuid("id").primaryKey().defaultRandom(),
tenant_id: uuid("tenant_id").notNull(),
rechnung_id: uuid("rechnung_id").notNull(),
art: text("art").notNull(), // 'ubl' | 'cii' | 'pdfa3' | 'report-kosit' | 'report-mustang' | 'peppol-receipt'
mime: text("mime").notNull(),
s3_key: text("s3_key").notNull(),
s3_object_lock_retain_until: timestamp("s3_object_lock_retain_until", { withTimezone: true }).notNull(),
sha256: bytea("sha256").notNull(),
groesse_bytes: bigint("groesse_bytes", { mode: "bigint" }).notNull(),
erzeugt_am: timestamp("erzeugt_am", { withTimezone: true }).notNull().defaultNow(),
hash_prev: bytea("hash_prev").notNull(),
hash_self: bytea("hash_self").notNull(),
}, (t) => ({
rechIdx: index("rb_rech_idx").on(t.tenant_id, t.rechnung_id, t.art),
}));
export const peppol_zertifikat = pgTable("peppol_zertifikat", {
id: uuid("id").primaryKey().defaultRandom(),
tenant_id: uuid("tenant_id").notNull(),
peppol_id: text("peppol_id").notNull(), // 0204:DE123...
kn_truststore_alias: text("kn_truststore_alias").notNull(), // Schlüsselname KMS
ausgestellt_am: timestamp("ausgestellt_am").notNull(),
gueltig_bis: timestamp("gueltig_bis").notNull(),
status: text("status").notNull(), // 'aktiv' | 'rotation_geplant' | 'abgelaufen'
rotations_job_id: uuid("rotations_job_id"),
});
export const freistellungsbescheinigung_48b = pgTable("freistellungsbescheinigung_48b", {
id: uuid("id").primaryKey().defaultRandom(),
tenant_id: uuid("tenant_id").notNull(),
subjekt_id: uuid("subjekt_id").notNull(), // leistender / debitor
subjekt_typ: text("subjekt_typ").notNull(), // 'wir' | 'debitor' | 'sub'
bescheinigungs_nr: text("bescheinigungs_nr").notNull(),
ausgestellt_von: text("ausgestellt_von").notNull(), // Finanzamt
gueltig_bis: date("gueltig_bis").notNull(),
pdf_s3_key: text("pdf_s3_key"),
erfasst_von: uuid("erfasst_von").notNull(),
erfasst_am: timestamp("erfasst_am", { withTimezone: true }).notNull().defaultNow(),
}, (t) => ({
subjIdx: index("fb48b_subj_idx").on(t.tenant_id, t.subjekt_id, t.gueltig_bis.desc()),
}));
export const ust_1_tg = pgTable("ust_1_tg", {
id: uuid("id").primaryKey().defaultRandom(),
tenant_id: uuid("tenant_id").notNull(),
debitor_id: uuid("debitor_id").notNull(),
bescheinigungs_nr: text("bescheinigungs_nr").notNull(),
gueltig_bis: date("gueltig_bis").notNull(),
pdf_s3_key: text("pdf_s3_key"),
erfasst_von: uuid("erfasst_von").notNull(),
erfasst_am: timestamp("erfasst_am", { withTimezone: true }).notNull().defaultNow(),
});
-- Mandantentrennung
ALTER TABLE rechnung ENABLE ROW LEVEL SECURITY;
CREATE POLICY rechnung_tenant_isolation ON rechnung
USING (tenant_id = current_setting('app.tenant_id')::uuid);
-- Immutability: nach Versand (immutable_at gesetzt) kein UPDATE / DELETE mehr
CREATE POLICY rechnung_no_update_after_versand ON rechnung
FOR UPDATE USING (immutable_at IS NULL);
CREATE POLICY rechnung_no_delete ON rechnung FOR DELETE USING (false);
-- rechnung_blob nur Insert, nie Delete / Update
ALTER TABLE rechnung_blob ENABLE ROW LEVEL SECURITY;
CREATE POLICY rb_no_update ON rechnung_blob FOR UPDATE USING (false);
CREATE POLICY rb_no_delete ON rechnung_blob FOR DELETE USING (false);
-- Rollenbasierte Sichten: Monteur sieht nur Rechnungs-Status, nicht Preise
CREATE POLICY rechnung_monteur_read ON rechnung FOR SELECT USING (
current_setting('app.role') <> 'monteur'
OR (bauvorhaben_id IN (SELECT bv_id FROM mitarbeiter_bv WHERE mitarbeiter_id = current_setting('app.user_id')::uuid))
);
CREATE OR REPLACE FUNCTION rechnung_hash_self() RETURNS trigger LANGUAGE plpgsql AS $$
DECLARE prev bytea;
BEGIN
SELECT COALESCE(hash_self, '\x00'::bytea) INTO prev
FROM rechnung
WHERE tenant_id = NEW.tenant_id
ORDER BY erstellt_am DESC, id DESC
LIMIT 1;
NEW.hash_prev := COALESCE(prev, '\x00');
NEW.hash_self := digest(
NEW.tenant_id::text || '|' || NEW.rechnungs_nr || '|' || NEW.brutto_aktuell_cent::text
|| '|' || NEW.ausstellungs_datum::text || '|' || encode(NEW.hash_prev, 'hex'),
'sha256');
RETURN NEW;
END $$;
CREATE TRIGGER rechnung_hash_chain BEFORE INSERT ON rechnung
FOR EACH ROW EXECUTE FUNCTION rechnung_hash_self();

Basis-Pfad: /v1/handwerk/rechnung · Auth: OAuth2 Bearer · Mandant per Header X-Tenant.

POST /v1/handwerk/rechnung

{
"typ": "teilrechnung",
"bauvorhaben_id": "01H..._krefeld",
"debitor_id": "01H..._stadt_krefeld",
"aufmass_block_ids": ["01H..._aufmassA118"],
"nachtrag_ids": ["01H..._nt01"],
"leistungs_zeitraum_von": "2026-04-01",
"leistungs_zeitraum_bis": "2026-04-17",
"faelligkeit": "2026-05-10",
"ausgabeformat": "xrechnung-ubl",
"vorheriger_rechnung_id": "01H..._tr3",
"idempotency_key": "01H..."
}

201{ rechnung_id, netto_aktuell_cent, brutto_kumuliert_cent, warnings: [...] } 409INVOICE_NUMBER_GAP (fortlaufende Numerierung verletzt), UST_1_TG_EXPIRED

POST /v1/handwerk/rechnung/{id}/validate → ruft KoSIT-Lambda asynchron, antwortet mit Job-ID + WebSocket-Channel. Job-Ergebnis landet als rechnung_blob (art='report-kosit').

POST /v1/handwerk/rechnung/{id}/send

{ "kanal": "peppol", "delivery_mode": "reliable" }

200 → Delivery-Receipt (mit message_id, timestamp, ap_signature) als rechnung_blob persistiert. 422PEPPOL_CERT_EXPIRED, LEITWEG_FORMAT_INVALID, KOSIT_FATAL, FREISTELLUNG_48B_MISSING, REVERSE_CHARGE_CONFLICT.

POST /v1/handwerk/rechnung/{id}/cancel Body: { "grund": "falsche Menge", "gutschrift_rechnungs_nr_vorschlag": "TR-2026-00471-S" } → Atomar: Status der Original=storniert_durch, neue Storno-Rechnung mit invoice_type_code=381, BT-25=....

POST /v1/handwerk/rechnung/inbound (Multipart) Felder: xml (UBL/CII), pdf (ZUGFeRD), source (email-from, peppol-inbound, manual). → Validierung + Parsing + LV-Abgleich + Event rechnung.inbound.parsed.

  • rechnung.erstellt
  • rechnung.validiert
  • rechnung.versandt
  • rechnung.bezahlt
  • rechnung.storniert
  • rechnung.inbound.abweichung_erkannt

Webhooks mit HMAC-SHA256-Signatur (Secret pro Tenant rotierbar).

Idempotency-Key Header (UUID v7, 24 h Geltung). Bei Duplikat → 200 mit original_response_cached.


Rechnungs-Erstellung: OFFLINE NICHT SUPPORTED. Grund: KoSIT-Validator muss synchron laufen, Peppol-SMP-Lookup erfordert Internet, Fehl-Validierungen können nicht bei schwacher Verbindung „zwischengespeichert“ werden ohne Risiko der Doppel-Nummer-Vergabe (→ GoBD-Verstoß).

Lese-Modus offline (Mobile für Monteur, Referenz §4.1 Bautagebuch-Cache):

  • Rechnungs-Status (entwurf|validiert|versandt|bezahlt|storniert) wird via SQLite-Cache (Drift) gespiegelt (read-only).
  • Rechnungs-Details werden nicht offline verfügbar gemacht (Preise, Debitor-Daten) — DSGVO Min-Prinzip für Monteure.

Aufmaß-Signatur offline ist separater Flow (→ §4.4), entsteht nicht in diesem Modul.

Konflikt-Strategie: Da nur read, entfallen Konflikte. Kein Last-Write-Wins — hier irrelevant, da nur schreibender Teil online ist.


Ident Norm Umsetzung im Feature Artefakt
C-01 § 14 UStG (inkl. § 14 Abs. 4 Pflichtangaben) Pflichtfelder harte Validation vor Draft→Validiert Unit-Test Pflichtfeld-Matrix
C-02 § 14 Abs. 1 Satz 2 UStG n.F. (E-Rech-V) Ausgabeformat default=xrechnung-ubl für B2B R-01
C-03 EN 16931-1:2017+A2:2023 Kern-Rechnungsdatenmodell Mapping-Tabelle BT-IDs ↔ DB-Spalten
C-04 XRechnung 3.0.2 (KoSIT) CIUS-Schematron Validation C-TEST-01
C-05 § 13b UStG + UStAE 13b.1 Reverse-Charge-Automatik + USt 1 TG-Pflege R-04, US-05-03
C-06 § 48 / § 48b EStG Pre-Check + Versand-Block + Dokumentation Bescheinigung R-05, Test Gherkin 3
C-07 § 14 Abs. 2/3 VOB/B Kumulation + Schlussrechnungs-Prüfbarkeit R-03, UI §6.1
C-08 GoBD § 147 AO Append-only + Hash-Chain + S3 Object Lock 10 J §7.3, R-18
C-09 DSGVO Art. 6 (1) lit. b, c Rechtsgrundlage Vertrag + gesetzl. Pflicht Verfahrensverzeichnis Art. 30
C-10 DSGVO Art. 17 (Löschung) Löschauftrag erst nach 10 J ab Ausstellung; vorher Sperre §7.1 + Job „retention-sweeper“
C-11 Peppol BIS 3.0.17 Billing AS4-Push + Schematron + SMP-Lookup R-08
C-12 § 27b UStG (Umsatzsteuer-Nachschau) Audit-Export in 24 h abrufbar API §8.6 Exports
C-13 § 93 AO (Vorlage) Betriebsprüfer-Export (XRechnung + Signaturen) Standard-Export
C-14 BSI-Grundschutz APP.3.3 (Webanwendungen) Session-Handling, CSRF, CSP Pen-Test-Report
C-15 ZUGFeRD 2.3 (FeRD) Mustang 2.14 Profile XRECHNUNG C-TEST-02
Art Retention Grund
rechnung (Hauptsatz) 10 Jahre ab Ende Kalenderjahr § 147 Abs. 3 AO
rechnung_blob (UBL/CII/PDF/Reports) 10 Jahre ab Erzeugung § 147 Abs. 3 AO + § 14b UStG
peppol_zertifikat (abgelaufen) 30 J Strafverfolgungs-Verjährung
ust_1_tg (abgelaufen) 6 Jahre nach Ablauf § 147 Abs. 3 Nr. 5 AO (analog Geschäftsbriefe)

  • EC-01 Rechnungs-Nummer-Lücke (Netzwerk-Fehler zw. ID-Reserve und Commit): System nutzt HiLo-Sequenz pro Tenant; Lücken können entstehen, werden als GoBD-konforme Begründung im Audit-Log dokumentiert (zulässig nach AEAO § 146 „fortlaufend, nicht lückenlos“).
  • EC-02 Leitweg-ID Format falsch (Bund 991-xxx-yy): Regex-Prüfung ja — aber Bundesland-Regex variiert. V1: Bund, Bayern, NRW, BW explizit; andere per generischem [A-Z0-9\-]{4,50}-Fallback + WARN.
  • EC-03 Debitor weigert sich, Peppol-ID herauszugeben → Fallback E-Mail + PDF/A-3 ZUGFeRD (UBL ist trotzdem im PDF).
  • EC-04 Empfänger will UBL ohne PDF → Option: "ausgabeformat":"xrechnung-ubl", kein PDF/A-3.
  • EC-05 ZUGFeRD-PDF/A-3 schlägt Mustang-Check fehl (XMP-Metadaten), weil Kunden-Logo PNG mit ICC-Profil-Fehler → Pre-Generator konvertiert Logo via ImageMagick 7 in PDF/A-3-tauglich (sRGB, kein Alpha).
  • EC-06 Kunde zahlt zu viel → Erstattungsrechnung invoice_type_code=381 (credit note) mit negativem Gesamtbetrag, Referenz auf Originalrechnung.
  • EC-07 Summen-Divergenz Aufmaß ↔ Rechnung-Position (Rundungsfehler): Nur Bank-Rounding HALF_EVEN auf Cent, Check |Σ_pos − brutto_aktuell| ≤ 0,02 €, sonst INTERNAL_CONSISTENCY_ERROR 500.
  • EC-08 USt 1 TG läuft morgen ab — aktive Banner im UI 30 Tage vorher, Versand erlaubt solange heute < gueltig_bis.
  • EC-09 USt-Satz-Wechsel (Corona-Historie 16 %): Historische Rechnungen mit altem Satz bleiben unverändert (immutable), neue Rechnungen nutzen tagesaktuellen Satz aus ust_satz_historie.
  • EC-10 Peppol-AP unreachable (Fehler 503): Retry mit exp. Backoff (1 min, 5, 15, 60, 240 min). Nach 4 h Alarm an Admin.
  • EC-11 Eingangs-Rechnung in FatturaPA oder FranceRechnung statt XRechnung → V1: Ablehnung mit freundlicher Meldung; V2: Multi-CIUS-Parser.
  • EC-12 Doppel-Versand (Kunde erhält zweimal) → Idempotency-Key auf API-Ebene; auf Peppol-Ebene Message-ID dedupliziert.
  • EC-13 Rechnung-Nr-Prefix-Wechsel zum Jahreswechsel: System nutzt Template {prefix}-{YYYY}-{running:05d}, Sequenz reset 01.01.
  • EC-14 Debitor zahlt mit falscher Referenz (BT-83 Payment reference fehlt) → Bank-Matching nur unscharf möglich; manuelle Zuordnung UI.
  • EC-15 Reverse-Charge gilt nur für Bauleistungen; Material-Lieferung allein nicht → System prüft, ob lv_knoten.art = 'leistung' vs. 'material' und markiert gemischte Positionen rot: Splitting nötig.
  • EC-16 Positions-weise ust_category-Mix: §13b (AE) + Regelsatz (S) auf einer Rechnung technisch erlaubt, aber inhaltlich fast nie — WARN, kein Block.
  • EC-17 Kunde-Tenant wird gelöscht (DSGVO-Art.-17-Gesuch) → Rechnung bleibt (gesetzl. Pflicht > Löschanspruch), Debitor-PII wird pseudonymisiert (Privatperson A), Adresse anonymisiert.
  • EC-18 Sicherheitseinbehalt-Auflösung (Gewährleistungszeit-Ende 4 Jahre nach Abnahme): Scheduler-Job schlägt Auflösungsrechnung vor.

12. Gherkin — Acceptance (Happy + 3 Grenzfälle)

Abschnitt betitelt „12. Gherkin — Acceptance (Happy + 3 Grenzfälle)“

12.1 Happy Path — XRechnung erzeugen + Peppol-Versand

Abschnitt betitelt „12.1 Happy Path — XRechnung erzeugen + Peppol-Versand“
Feature: Teilrechnung VOB §14 Abs. 2 als XRechnung UBL 2.1 an Peppol-Empfänger
Background:
Given der Tenant "shk-gebruder-schmidt"
And eine CFO "Paul Wagner" mit Rolle "cfo"
And ein Bauvorhaben "Stadthalle Krefeld" mit 3 bezahlten Teilrechnungen 182.340,22 € brutto
And ein Aufmaß-Block "A-118" freigegeben mit 214,7 m² Innenwand-Malerarbeiten
And der Debitor "Stadt Krefeld" mit Peppol-ID "0204:DE220612345" und USt 1 TG gültig bis 30.06.2027
And eine gültige Freistellungsbescheinigung § 48b für uns bis 31.12.2028
Scenario: Erfolgreicher Versand einer Teilrechnung
When Paul eine neue Teilrechnung Typ "teilrechnung" für BV "Stadthalle Krefeld" erstellt
Then berechnet das System eine Brutto-Summe diesen Zeitraum von 58.117,90 €
And eine kumulierte Brutto-Summe 240.458,12 €
And einen Zahlungsanspruch 60.028,81 € (nach 5 % Sicherheits-Einbehalt)
And USt-Betrag = 0,00 € mit Kategorie "AE" (Reverse-Charge)
And Hinweistext "Steuerschuldnerschaft des Leistungsempfängers nach § 13b UStG"
When Paul auf "Validieren" klickt
Then ruft das System die KoSIT-Lambda mit Szenario "XRechnung 3.0.2 UBL"
And der Validator-Report enthält 0 FATAL und 0 ERROR
When Paul auf "Versand ➜ Peppol" klickt
Then macht das System einen SMP-Lookup auf "0204:DE220612345"
And sendet via AS4-Push an den Receiver-AP
And persistiert die Delivery-Receipt als "rechnung_blob" mit art="peppol-receipt"
And setzt "rechnung.status" auf "versandt"
And füllt "rechnung.immutable_at" mit NOW()
And der Hash-Chain-Eintrag ist konsistent mit dem Vorgänger
Scenario: Versand blockiert, wenn Freistellungsbescheinigung abgelaufen und Betrag > 5000 €
Given eine Rechnung mit Brutto 12.000 €
And die Freistellungsbescheinigung § 48b unseres Betriebs ist abgelaufen am 31.03.2026
When Paul auf "Versand" klickt
Then liefert die API 422 mit Fehler-Code "FREISTELLUNG_48B_MISSING"
And zeigt eine prominente Warnung mit Handlungsempfehlungen: "Neue Bescheinigung beim Finanzamt beantragen"
And das Debitor-System muss 15 % Bauabzugssteuer (1800,00 €) einbehalten und ans FA abführen
And der Versand-Button ist deaktiviert, bis eine neue Bescheinigung eingetragen wurde
And ein Audit-Log-Eintrag dokumentiert den Block mit Grund + User + Zeit

12.3 Grenzfall 2 — KoSIT-Validator liefert FATAL (Leitweg-ID fehlt bei öffentlichem Auftraggeber)

Abschnitt betitelt „12.3 Grenzfall 2 — KoSIT-Validator liefert FATAL (Leitweg-ID fehlt bei öffentlichem Auftraggeber)“
Scenario: Validator schlägt fehl, Versand unmöglich
Given ein Debitor "Land Berlin" mit Kategorie "öffentlicher Auftraggeber"
And die Rechnung hat keine Leitweg-ID
When Paul auf "Validieren" klickt
Then antwortet KoSIT-Lambda mit 1 FATAL (Code "BR-DE-15: Kauferreferenz Pflicht")
And der UI-Dialog zeigt den Fehler mit Lösungsvorschlag
And der Versand-Button bleibt deaktiviert
And die API-Antwort auf POST /v1/handwerk/rechnung/{id}/send ist 422 mit "KOSIT_FATAL"
And der Validator-Report wird als "rechnung_blob" art="report-kosit" persistiert (auch Fehl-Reports für Audit)
Scenario: Zweiter POST mit gleichem Idempotency-Key liefert gecachte Antwort, kein Doppel-Versand
Given ein Idempotency-Key "01H8A..." wurde in den letzten 24 h für diese Rechnung verwendet
And der erste Request hat Status "versandt" zurückgegeben
When ein zweiter POST /v1/handwerk/rechnung/{id}/send mit gleichem Idempotency-Key eingeht
Then liefert das System 200 mit Body identisch zum Erstergebnis
And das Peppol-AP bekommt keinen zweiten AS4-Push
And im Audit-Log erscheint ein "idempotency_cache_hit"-Event
Scenario: Debitor hat USt 1 TG abgelaufen, Rechnung aber mit §13b vorausgesetzt
Given der Debitor hat USt 1 TG bis 31.12.2025
And heute ist der 19.04.2026
And der Rechnungs-Entwurf setzt reverse_charge=true
When Paul "Validieren" klickt
Then zeigt das UI WARN (nicht FATAL) "Reverse-Charge riskant, USt 1 TG nicht mehr aktuell"
And der Versand ist nicht automatisch blockiert, aber Paul muss die Rechnung mit Häkchen "Ich bestätige, dass der Leistungsempfänger weiterhin Bauleistender i.S.v. § 13b UStG ist" bestätigen
And ein Audit-Eintrag dokumentiert diese Bestätigung mit User + Zeit + User-Agent

13. Test-Cases (funktional + compliance + performance)

Abschnitt betitelt „13. Test-Cases (funktional + compliance + performance)“
ID Typ Titel Tooling
T-01 Unit EN-16931-BT-Mapping LV→UBL (alle 20 Core-Profile-Felder) Vitest + xmllint
T-02 Unit VOB-Kumulations-Algorithmus (5-Teilrechnungs-Kaskade) Vitest
T-03 Unit Rundungs-Property-Test (Σ_pos == brutto_aktuell ± 0,02 €) für 10 000 Zufalls-LVs fast-check
T-04 Unit Reverse-Charge-Automatik an/aus je Debitor-Status Vitest
T-05 Unit §48-Pre-Check (Freistellung abgelaufen · Betrag > 5000 €) → Block Vitest
C-TEST-01 Compliance KoSIT-Validator 1.5.0 gegen 200 generierte Rechnungen (0 FATAL) KoSIT CLI + GitHub-Action nightly
C-TEST-02 Compliance Mustang-Project-Validator gegen PDF/A-3 (alle Beispiele Profile=XRECHNUNG) Mustang 2.14 Jar
C-TEST-03 Compliance Peppol-Schematron für EU-Versand (BE, NL, FR, NO, SE) OpenPeppol TestBed
C-TEST-04 Compliance BMF-Muster-XRechnungen round-trip (lesen + erzeugen) Datensatz KoSIT-XRechnung-Testsuite
C-TEST-05 Security XXE + Billion-Laughs bei Eingangs-XML secure XML parser (disable DOCTYPE)
C-TEST-06 Security KMS-Zertifikat-Rotation simuliert (30-Tage-Alarm) Terraform-Test
C-TEST-07 Compliance GoBD-Hash-Chain-Integrität nach 1 000 Rechnungen Python-Script Nightly
C-TEST-08 Compliance Retention-Sweeper (> 10 Jahre alte Privatrechnungen werden anonymisiert) Pytest + Testcontainers
T-10 Integration End-to-End: Aufmaß-Freigabe → Rechnung → KoSIT → Peppol-AP-Sandbox Playwright + B2BRouter Test-AP
T-11 Load 500 Rechnungen/Tag · Generierung p95 < 900 ms k6
T-12 Chaos KoSIT-Lambda Timeout → Retry + Alarm AWS FIS
T-13 UAT Referenzkunde shk-gebruder-schmidt erstellt 10 reale Rechnungen (Anonymisierung) Sprint-Review
import { fc } from "fast-check";
import { berechneKumulation } from "@/lib/vob-kumulation";
test("P-01 Kumulation ist monoton", () => {
fc.assert(fc.property(
fc.array(fc.record({
nettoCent: fc.bigInt({ min: 1n, max: 10_000_000n }),
einbehalteneCent: fc.bigInt({ min: 0n, max: 2_000_000n }),
}), { minLength: 1, maxLength: 50 }),
(teilrechnungen) => {
const kum = berechneKumulation(teilrechnungen);
// Brutto kumuliert darf nie sinken
for (let i = 1; i < kum.length; i++) {
expect(kum[i].bruttoKumuliert).toBeGreaterThanOrEqual(kum[i - 1].bruttoKumuliert);
}
}));
});

  • Keine Buchungs-Engine: Wir integrieren DATEV-CSV-Export und GDPdU-Schnittstelle — aber wir führen keine eigene Kostenrechnung (kein Kontenplan, keine BWA).
  • Keine Mahn-Automatik in V1: Status-Feld existiert, automatisches Mahnwesen V2.
  • Keine Factoring-Integration: Vorbereitet (Daten-Export JSON), aber kein Live-Factoring-Anbieter in V1.
  • Keine Lohnsteueranmeldung für §48: Nur Pflicht-Erinnerung; Abführung erfolgt extern.
  • Keine Kassen-Nachschau-Anbindung: Bau ≠ Gastro/Handel, TSE-Pflicht irrelevant.
  • Kein WebPortal für Debitor: V1 nur Versand + PDF; Self-Service-Portal für Debitor erst V2.
  • Keine Multi-Währung: EUR only; GBP/CHF erst V3.
  • Keine FatturaPA / FR-E-Rech-Parser inbound: Nur XRechnung/ZUGFeRD/Peppol BIS in V1.

ID Risiko Wahrsch. Wirkung Mitigation
R-01 KoSIT-Validator-Spec-Change (v3.1 in 2026) bricht XSDs hoch mittel Validator-Version im Feature-Flag, Shadow-Run neuer Version parallel 90 Tage
R-02 Peppol-Managed-AP (B2BRouter) Ausfall mittel hoch Multi-AP-Strategie (B2BRouter + Unimaze + eigener AP ab V2); Failover-Config
R-03 §14-UStG-Auslegung FA uneinheitlich mittel mittel Begleitschreiben als Fußnote in PDF/A-3; Klausel-Bibliothek pflegbar
R-04 VOB/B-§14-Kumulation vom Architekten abgelehnt (“nicht prüfbar”) mittel hoch Muster-Kumulationsdarstellung mit BauSoft-Bayern Best-Practice-Format als Template
R-05 Reverse-Charge-Fehlanwendung → Steuerhaftung gering hoch Double-Check-Workflow bei Erstanwendung je Debitor; jährliche USt 1 TG-Prüfung via FA-Abfrage
R-06 PDF/A-3-Erzeugung resource-intensiv (große LVs > 500 Pos.) mittel mittel FOP-Stream-Rendering, 2-GB-Lambda-Tier, Async-Ready-Notification
R-07 DSGVO-Löschungsanspruch kollidiert mit 10 J AO-Aufbewahrung mittel mittel Sperre + Pseudonymisierung dokumentiert, DPO-Freigabe Schreibweise
R-08 Zertifikat-Rotation Peppol vergessen mittel hoch 30-Tage-Alarm, 14-Tage-Eskalation, 7-Tage-Block-Gefahr
R-09 §13b-Auslegung bei Mischrechnung (Leistung+Material) mittel mittel Position-Splitting-UI mit Steuerberater-Review-Flow
R-10 Fortlaufende Numerierung bricht bei Tenant-Migration gering mittel Migration-Playbook: Einmal-Nummer-Prefix-Wechsel, Audit-Begründung
R-11 ZUGFeRD-PDF/A-3 zu groß (> 20 MB Attachment-Limit mancher Systeme) gering mittel Bild-Kompression, Logo-Caching, Pre-Generator-Hinweis
R-12 Geringe Adoption Peppol in DE (Rückfall auf E-Mail) hoch niedrig E-Mail-Fallback robust, Peppol als USP vermarkten

  • §4.3 GAEB-LV — Pflicht. LV-Version_id ist Quelle für alle Positions-Texte (Immutable Ref).
  • §4.4 Mobiles Aufmaß — Pflicht. Aufmaß-Block-IDs sind Pflicht für Mengen-Herkunft; ohne freigegebenen Aufmaß keine Teilrechnung.
  • §4.2 Nachtrag — Pflicht, wenn lv_knoten.art == 'nachtrag' involviert ist.
  • §4.1 Bautagebuch — optional (Querverweis auf Stundenbelege bei Regieleistung).
  • §5 Zeit/Personal — optional (Stunden als Nachweis bei Regieleistung in Anlage).
  • KoSIT-Validator 1.5.0 (Docker-Image als AWS Lambda im Single-Tenant-Account der Plattform, nicht pro Mandant).
  • Mustang-Project 2.14 (Java 21, SnapStart-Lambda).
  • Peppol Access Point (V1: B2BRouter Managed-AP, Vertrag Q1/2026 geplant).
  • AWS S3 Object Lock Compliance Mode Bucket werkszeit-rechnung-archiv-<region> (10-J-Retention).
  • AWS KMS für Peppol-Client-Zertifikat (CMK mit Rotation 365 Tage).
  • Bundes-DeMail-Adapter (optional, für §14 Steuer-Bescheide).
  • FA-Abfrage-Schnittstelle (via DATEV oder manuell) für §48b-Bescheinigungs-Validität.
  • packages/oz-core (gemeinsam mit §4.3) — OZ-Parsing / -Formatting.
  • packages/xrechnung-generator (neu, TypeScript) — BT-ID-Mapping, UBL/CII-XML-Serialization via fast-xml-builder.
  • packages/zugferd-renderer (neu, Java 21) — FOP-XSLT → PDF/A-3 via Mustang.
  • packages/peppol-client (neu, TypeScript) — SMP-Lookup (HTTP+XSD), AS4-Push via jgroups-like oasis-as4-ts (ADR noch offen).
  • packages/einkommensteuer (neu, klein) — §48-Pre-Check-Logik.
  • services/api Hono-Backend.
  • services/frontend React 19 + TanStack Router.
  • apps/mobile Flutter (nur read-Views).
Rolle Aufwand Wer
Backend-Lead 40 % × 12 Wochen J. Peters
Backend-Dev 100 % × 10 Wochen L. Okafor
Frontend-Dev 100 % × 6 Wochen K. Schmidt
QA 50 % × 10 Wochen F. Reiss
Compliance-Berater (extern) 0,4 VZÄ × 4 Wochen Dr. M. Blank (StB Lübeck)
DevOps/Lambda/KMS 20 % × 4 Wochen A. Bauer

Woche 1–2 Mandanten-Onboarding: Leitweg-ID Kommunal-Kunden einspielen (CSV-Import 210 Debitoren), Peppol-ID-Mapping, USt 1 TG-Bescheinigungen (via E-Mail-Weiterleitung → KI-OCR). Woche 3 Schatten-Betrieb: Rechnungen werden zusätzlich in Werkszeit erstellt, aber alter Workflow (OpenXRechnung) bleibt primär. Differenzen werden automatisch dokumentiert. Woche 4 Umschwenk bei 25 % des Rechnungsvolumens (kleine Beträge, nicht-kritische Debitoren). Woche 5–6 100 %-Übernahme, alter Workflow archiviert. Woche 7 Retrospektive mit Paul Wagner + CFO-Beirat; Lessons Learned → LESSONS-LEARNED.md.

  • Time-to-Rechnung (Aufmaß-Freigabe → Versand): Baseline 32 min, Zielwert 8 min.
  • Retour-Quote (Rechnungen vom Debitor abgelehnt): Baseline 1,8 %, Zielwert < 0,5 %.
  • VZÄ in Buchhaltung: Baseline 3,5, Zielwert 2,5 (Freisetzung 1 VZÄ für Kundenbetreuung).
  • Peppol-Adoption Kommunal: Start 0 %, Woche 12 Zielwert 60 %.

Wesentlich kleineres Volumen, Fokus auf §13b und §48b-Pflege. Shadow-Betrieb entfällt (zu klein), stattdessen Direkt-Umschwenk mit Rollback-Garantie (7 Tage).


  1. Validator-Version nicht hart codieren. KoSIT wechselt alle 6 Monate. Jede Rechnung speichert die Validator-Version, mit der sie validiert wurde (rechnung_blob.art='report-kosit' Hash-Chain). Rückwirkende Prüfung alter Rechnungen mit neuer Validator-Version ist optional (Audit-Komfort), nicht Pflicht.

  2. PDF/A-3 ist Komfort, UBL ist Wahrheit. Bei jeder Diskrepanz zwischen PDF-Anzeige und UBL-Struktur hat UBL Vorrang. Das muss im UI explizit kommuniziert werden (“Rechtsverbindlich ist die XML-Struktur; das PDF dient der menschenlesbaren Darstellung”). Sonst gibt es Ärger mit Finanzamt-Prüfern, die nur das PDF lesen.

  3. Peppol-AP via B2BRouter in V1, eigener AP in V2. Ein eigener Peppol-AP kostet ~ 80 k€ Zertifizierung + 4 k€/Monat Betrieb + 0,3 VZÄ. Lohnt sich erst ab > 5 000 Rechnungen/Monat via Peppol. Bis dahin managed.

  4. §48 EStG ist kein Rechnungsmerkmal, sondern ein Compliance-Gate. Die Versand-Blockade bei fehlender Freistellung ist radikal, aber richtig — jede andere Lösung führt in die Haftung. Kommuniziere das explizit im Onboarding.

  5. VOB §14 Kumulation ist Maßarbeit je Architekt. Die Kumulations-Darstellung in der PDF-Seite muss pro Auftraggeber konfigurierbar sein (BauSoft-Bayern-Format ≠ RIB-iTWO-Format ≠ Excel-Handschlag). Template-Editor ab V1.1.

  • G1 (Sprint 26-Q2-A Ende): 100 % der KoSIT-Testsuite-Musterrechnungen werden korrekt erzeugt. No-Go → verschiebt Sprint 26-Q2-B um 2 Wochen.
  • G2 (Sprint 26-Q2-B Ende): B2BRouter-Sandbox-AP liefert 10 aufeinanderfolgende erfolgreiche Deliveries ohne manuellen Eingriff. No-Go → Peppol verschoben auf V1.1 (MVP mit E-Mail-Only).
  • G3 (Sprint 26-Q2-C Ende): Referenzkunde shk-gebruder-schmidt Schatten-Betrieb 0 Differenzen vs. Altsystem. No-Go → Rollback-Plan aktivieren.
  • G4 (vor GA): Pen-Test + DSGVO-DSFA + Steuerberater-Gutachten (Dr. Blank). No-Go → GA verschoben.
  • Vorgefertigte „Schöner-Rechnen-Teilrechnung-nach-VOB“-Demo mit echt aussehenden Zahlen (shk-gebruder-schmidt Sample).
  • Live-KoSIT-Validator-Dialog (“schaut, es findet den Fehler in 600 ms”) — sehr überzeugend in Sales-Calls.
  • PDF/A-3 mit gut lesbarem Bau-Layout (Referenz: RIB-iTWO-Schema) statt Accountant-Stil.
  • Reverse-Charge-Automatik live umschalten per Toggle (“mit/ohne §13b”) — Wow-Effekt bei CFOs.

Das ePeppol-Ökosystem wird in 2027/2028 der defacto-Rechnungsweg im EU-Bau, getrieben durch ViDA („VAT in the Digital Age“, EU-Direktive 2025/XYZ, Peppol-CTC-Reporting). Wer heute saubere Peppol-Pipeline baut, kann den 2027/2028-Realtime-Reporting-Turn bedienen, ohne Architektur-Umbau. Das ist der strategische Graben (Moat) dieses Moduls.

Empfehlung: GA-Freigabe sobald G1–G4 grün. Parallel Entwicklung V1.1 (Mahnwesen, eigener Peppol-AP, Template-Editor) im Folge-Quartal.


19. Wave 2 — XRechnung-Bau-Extension (2026-04-23)

Abschnitt betitelt „19. Wave 2 — XRechnung-Bau-Extension (2026-04-23)“

Umsetzung von drei zusätzlichen Endpoints und zwei neuen TypeScript-Modulen, die den kern-05 XRechnung-Exporter um Bau-spezifische Anteile erweitern und eine offline Validierung gegen einen Teil der EN-16931/KoSIT-Schematron-Regeln durchführen. Keine externen Services, keine Java-Runtime, rein TypeScript.

Methode Pfad Zweck
GET /v1/handwerk/bau-abrechnung/rechnungen/{id}/xrechnung.xml UBL 2.1 XML inkl. Bau-Extensions + X-XRechnung-Validation Header
GET /v1/handwerk/bau-abrechnung/rechnungen/{id}/leitweg-id-check Regex + mod-97-10 Offline-Check + Klassifikation (Bund/Land/…)
POST /v1/handwerk/bau-abrechnung/xrechnung-validate Ad-hoc Validierung eines beliebigen XRechnung-XMLs (≤ 5 MB)
  • BT-3 InvoiceTypeCoderechnungstyp (UNCL1001): abschlagszahlung=386, teilrechnung=387, schlussrechnung=380, storno=381 (bzw. 384 bei gesetztem originRechnungsnummer).
  • §13b UStG Reverse-Charge → VAT-Kategorie SAE, Percent=0.00, TaxExemptionReasonCode=VATEX-EU-AE, Hinweistext (BT-120), TaxAmount=0, TaxInclusive = TaxExclusive (Payable = Netto).
  • §48 EStG Bauabzug → BG-20 Document-Level-Allowance mit AllowanceChargeReasonCode=95 (UNCL5189 Deduction) und AllowanceChargeReason="§48 EStG Bauabzugssteuer 15 %...".
  • VOB/B §14 Abs. 2 Kumulation → je vorherige Rechnungsnummer ein cac:AdditionalDocumentReference mit DocumentType="VOB-Teilrechnung-Kumulation".

Implementiert in kosit-offline-validator.ts. Abgedeckt: BR-01..BR-17, BR-21, BR-22, BR-24..BR-28, BR-CO-04/10/13/15/25/26, BR-S-01, BR-AE-01, BR-Z-01, BR-DE-15, BR-DE-17, BR-DE-21, BR-B-01, BR-33. Severity error oder warning. Report wird im Response-Header der XRechnung-Download-Route mitgeliefert (X-XRechnung-Validation: valid=<bool>;errors=<n>;warnings=<n>).

leitweg-id-validator.ts prüft das Schema ^\d{1,12}(-[A-Z0-9]{1,30})?(-\d{1,5})?$ und — wenn ein Prüfziffern-Suffix vorhanden ist — ISO/IEC 7064 mod-97-10 (gleiche Arithmetik wie IBAN, berechnet in 9-Stellen-Chunks ohne BigInt-Dependency).

Fügt bau_rechnung_meta.ust1tg_bescheinigung_id uuid (lose Ref, keine DB-FK), CHECK (reverse_charge_13b = false OR ust1tg_bescheinigung_id IS NOT NULL) und brm_tenant_leitweg_idx / brm_tenant_ust1tg_idx hinzu. leitweg_id und reverse_charge_13b existierten bereits in Migration 0021.

  • xrechnung-bau-extension.test.ts — 12 Cases
  • kosit-offline-validator.test.ts — 33 Cases (pro Regel ≥ 1 pass + 1 fail)
  • leitweg-id-validator.test.ts — 15 Cases (inkl. mod-97-10 happy/fail)

— Ende Feinkonzept §4.5 — Version 1.0 · 19.04.2026 · Senior-Berater-Verantwortung: Team “Rechnung” (Werkszeit GmbH) · Compliance-Review: Dr. M. Blank, StB —

— Wave 2 · 23.04.2026 · XRechnung-Bau-Extension · rein TS / offline · Migration 0034 —

Für Entwickler — API-Endpoints13
MethodePfadAuthZweck
GET/v1/handwerk/bau-abrechnung/freistellungsbescheinigungenbearerAuth§48 EStG Freistellungsbescheinigungen — Liste
POST/v1/handwerk/bau-abrechnung/freistellungsbescheinigungenbearerAuth§48 EStG Freistellungsbescheinigung anlegen
PUT/v1/handwerk/bau-abrechnung/freistellungsbescheinigungen/{id}bearerAuth§48 EStG Freistellungsbescheinigung aktualisieren
GET/v1/handwerk/bau-abrechnung/rechnungenbearerAuthBau-Rechnungen — Liste
POST/v1/handwerk/bau-abrechnung/rechnungenbearerAuthBau-Rechnung anlegen (transaktional rechnungen + bau_rechnung_meta)
GET/v1/handwerk/bau-abrechnung/rechnungen/{id}bearerAuthBau-Rechnung Detail (inkl. VOB-Status-History)
POST/v1/handwerk/bau-abrechnung/rechnungen/{id}/kumulation-berechnenbearerAuthKumulative VOB/B §14 Saldo-Werte berechnen (kein DB-Change)
GET/v1/handwerk/bau-abrechnung/rechnungen/{id}/leitweg-id-checkbearerAuthLeitweg-ID einer Bau-Rechnung prüfen
POST/v1/handwerk/bau-abrechnung/rechnungen/{id}/stornierenbearerAuthBau-Rechnung stornieren (US-05-09)
GET/v1/handwerk/bau-abrechnung/rechnungen/{id}/xrechnung.xmlbearerAuthBau-Rechnung als XRechnung-XML
GET/v1/handwerk/bau-abrechnung/ust1tg-bescheinigungenbearerAuth§13b UStG USt-1-TG-Bescheinigungen — Liste
POST/v1/handwerk/bau-abrechnung/ust1tg-bescheinigungenbearerAuth§13b UStG USt-1-TG-Bescheinigung anlegen
POST/v1/handwerk/bau-abrechnung/xrechnung-validatebearerAuthXRechnung-XML validieren