DATEV-Integration — LODAS-ASCII, EXTF, Monatsabschluss, Korrekturlauf
Feinkonzept · §3.10 DATEV-Integration — LODAS-ASCII, EXTF, Monatsabschluss, Korrekturlauf
Abschnitt betitelt „Feinkonzept · §3.10 DATEV-Integration — LODAS-ASCII, EXTF, Monatsabschluss, Korrekturlauf“Einordnung. Dieses Feinkonzept setzt FUNKTIONSUMFANG §3.10 um. DATEV ist in Deutschland nicht „ein“ Lohn-Abrechnungssystem unter vielen — es ist in rund 40 % der mittelständischen Handwerksbetriebe der de-facto-Standard, verzahnt mit dem Steuerberater. Wer Zeiterfassung baut, baut Lohn-Vorbereitung; wer Lohn-Vorbereitung baut und DATEV nicht sauber bedient, liefert ein halbes Produkt. Frau Müller in der Buchhaltung tippt heute Überstunden, Krankheit, Urlaub und Spesen in drei Systeme ab; jedes Zahlenspiel ist Handarbeit. Wir setzen auf zwei parallele Wege, nicht einen:
LODAS-ASCIIfür Lohnbuchhalter, die in DATEV LODAS mandantenseitig arbeiten, undEXTFfür die Kanzlei, die in DATEV Lohn und Gehalt klassisch bucht. LESSONS-LEARNED §8 mahnt uns: niemals einen proprietären CSV-Export als „DATEV-Export“ verkaufen — das hat die Alt-App so gemacht, und es hat Frau Müller eine Stunde pro Monat gekostet, die Mapping-Fehler händisch zu korrigieren.
1. Header & Metadaten
Abschnitt betitelt „1. Header & Metadaten“feature_id: kern/10-datev-integrationtitle: DATEV-Integration — LODAS-ASCII, EXTF, Monatsabschluss, Korrekturlauffunktionsumfang_ref: §3.10roadmap_horizont: MVP # Ohne DATEV kein Markt — Pflicht ab Tag 1plattformen: mobile: aus # Lohn-Export ist Back-Office-Arbeit web: vollständig # Export, Status, Korrektur, Mandanten-Setup desktop: ausowner_rolle: Buchhaltung # Frau Müller; Admin macht Mandanten-Setupmodul_gate_flag: module.kern.datevcompliance_flags: gobd: true # Lohn-Export ist handelsrechtlich relevant arbzg: false vob: false dsgvo: true # Sozialversicherungsnummer, Bankdaten — Art. 9/Art. 88 bfsg: false # Back-Office-Funktion, kein ESS betrvg: false # §87(1)6 greift nicht bei Lohn-Export stvg: false weitere: - "§147 AO (10-Jahres-Aufbewahrung der Lohnunterlagen)" - "§41 EStG (Lohnsteuerabzug, Aufzeichnungspflicht)" - "§28f SGB IV (Sozialversicherungs-Beitragsnachweise)" - "DATEV-Schnittstellenbeschreibung Lohnvorerfassung (LODAS-ASCII, Stand Jg. 2026)" - "DATEV EXTF-Format v9.0 (Kassenbuch / Finanzbuchhaltung / Lohn)" - "DATEV Unternehmen online API v1.4 (optional ab V1)"referenzkunde: status: TBD name: "zu klären — Zielprofil: Handwerksbetrieb 40–80 MA mit externer Steuerkanzlei, DATEV-Mandat bestätigt" quelle: "Sales-Discovery + Steuerberater-Netzwerk ZDH/HWK"estimate_eng_tage: 38 # LODAS-Writer (10), EXTF-Writer (6), Mapping-UI (8), # Monatsabschluss (6), Korrekturlauf (4), DUO-API (4)abhängigkeiten: - kern/01-zeiterfassung # Ist-Stunden sind die Quelle - kern/02-arbeitszeit-compliance # Überstunden-/Nachtzuschlag-Kategorisierung - kern/03-abwesenheiten # Krank/Urlaub-Tage gehen als AAG/EFZG - kern/06-spesen-reisemanagement # Verpflegungsmehraufwand, Km-Geld - kern/11-compliance-audit # Export ist ein auditierter Vorgang2. Kontext & Problem
Abschnitt betitelt „2. Kontext & Problem“Marktrealität (DE-Handwerk). In der typischen Gebrüder-Schmidt-GmbH (SHK, 80 MA) übernimmt die Buchhaltung — Frau Müller, 56, seit 22 Jahren im Betrieb — die Lohn-Vorbereitung. Sie zieht am 25. jedes Monats den „Lohnjournal“-Bericht aus der Alt-App (das war in der Alt-App: eine CSV-Datei mit 18 Spalten, datum;name;stunden;zuschlag;projekt;…), öffnet Excel, schiebt Spalten, löscht Kopfzeile, gleicht Überstunden-Konten händisch ab, tippt Zuschläge in einen DATEV-Erfassungsbogen und schickt ihn per DATEV-Unternehmen-Online an den Steuerberater. Das Ganze kostet sie 3–4 Arbeitsstunden pro Monat, produziert reihenweise Fehler (Komma statt Punkt, falsche Lohnart, vergessene Schlüsselzahlen) und wird vom Steuerberater mit monatlichen Rückfragen quittiert. Beim Maler-Betrieb mit 25 MA macht das die Steuerkanzlei direkt aus dem übergebenen Ordner — kein Export, keine Datenhaltung im Betrieb. Beide Fälle sind legitim, beide wollen wir bedienen.
Rechtlicher Rahmen. Lohnunterlagen unterliegen §147 AO (10 Jahre Aufbewahrung), §41 EStG (Lohnkonten-Pflichtfelder) und §28f SGB IV (Beitragsnachweis). Die DATEV-Schnittstelle ist nicht gesetzlich normiert, aber faktisch Pflichtstandard: Wer als Betrieb „DATEV-Export“ bewirbt, muss das offizielle LODAS-ASCII-Format der aktuellen Jahrgangsversion oder EXTF liefern, sonst stößt er bei der Steuerkanzlei auf eine verschlossene Tür. LODAS-ASCII ist ein CP1252-codiertes Festlängen-ASCII-Format mit Satzarten (100 Stammsatz, 110 Bewegungssatz, 120 Zuschlags-/Zulagensatz), strengem Spaltenraster und DATEV-spezifischen Schlüsselzahlen (Lohnart 1=Grundlohn, 5=Überstunden, 9=Sonntagszuschlag…). EXTF (externe Datei) ist ein CSV-Format mit 730+ Feldern in der Finanzbuchhaltung und einem separaten Lohn-Layout (v9.0), UTF-8 mit BOM, Semikolon-separiert, Buchungsperiode hart auf Monat normiert. DATEV Unternehmen online ist die Web-API-Brücke, die den Dateiversand automatisieren kann — optional, nicht MVP-kritisch.
Schmerzpunkt der Alt-App. LESSONS-LEARNED §8 hält fest: Die Alt-App exportierte in einem selbstgestrickten CSV-Format, das die Betriebe als „DATEV-Export“ verkauft bekamen — mit freier Spaltenfolge, deutschem Datumsformat, UTF-8 ohne BOM. Kein Steuerberater konnte das direkt importieren. Es entstand eine Zwischenschicht („Frau Müller’s Excel-Makro“), die Mapping-Fehler produzierte. Die DATEV-Validator-Suite wurde nie angewandt, Jahrgangs-Schlüsselzahlen veralteten. Wir machen das anders: Der Export ist byte-genau DATEV-konform ab dem ersten Release, durchläuft pre-release die DATEV-Validator-Toolchain, und wird als Write-Contract behandelt — was wir schreiben, muss DATEV lesen, keine Ausnahme.
Erwarteter Outcome (SMART).
- Spezifisch: Monatsabschluss-Klick erzeugt LODAS-ASCII + EXTF, parallel zur Wahl, mit Versand-Status und Audit-Trail.
- Messbar: Lohn-Vorbereitungszeit Frau Müller von 240 min/Monat auf ≤ 20 min/Monat (91 % Reduktion).
- Achievable: 38 Engineering-Tage für MVP (Writer + Mapping-UI + Korrekturlauf).
- Relevant: DATEV-Mapping-Fehlerquote < 0,5 % (Steuerberater-Rückfragen).
- Terminiert: Ab MVP-Release (ohne DATEV ist die App im deutschen Handwerk unverkäuflich — DOR §1.2.1).
3. Personas & Rollen
Abschnitt betitelt „3. Personas & Rollen“| Rolle | Aktion | Scope | Plattform |
|---|---|---|---|
| Buchhaltung | Monatslauf anstoßen, Mapping pflegen, Export herunterladen | all |
🌐 |
| Admin | Mandantenstamm (Beraternummer, Mandantennummer, Lohnkonten-Zuordnung) pflegen | all |
🌐 |
| Steuerberater (extern) | Optional: liest Export via DATEV Unternehmen online API | — | — |
| Manager | Monatslauf-Freigabe (fachliche Prüfung: Überstunden-Konten korrekt?) | team |
🌐 |
| Mitarbeiter | Keine direkte Interaktion; sieht nur „Lohn-Beleg Januar versandt“ im ESS | own |
📱 (nur Info) |
Persona-Skizzen:
- Frau Müller (Buchhaltung, 56, SHK-Betrieb Gebr. Schmidt) — Tastatur-User, kennt DATEV LODAS seit 2005. Erwartet Jahres-Versionswechsel automatisch, will keine Excel-Brücke mehr. Verzichtet gern auf Schönheit, besteht auf Präzision.
- Herr Schuster (Steuerberater extern, Kanzlei Schuster & Partner, betreut 80 Mandanten) — bekommt EXTF-Dateien per DATEV Unternehmen online direkt ins Rechnungswesen. Rückfrage-Typ: „Wo ist die Schlüsselzahl 9 bei Hannes’ Sonntagsstunden?“ — wenn das passiert, ist unser Mapping kaputt.
- Markus (Admin, 34, IT-affiner Meister) — setzt einmalig die Mandantennummer, Beraternummer, Lohnart-Mapping auf. Will klare Defaults für die Branchen-Tarifverträge (TV Maler, SOKA-Bau, TV SHK).
4. User-Stories
Abschnitt betitelt „4. User-Stories“US-01 [MVP] Als Buchhaltung möchte ich am Monatsende einen Klick "DATEV-Export" drücken und eine valide LODAS-ASCII-Datei + EXTF-Datei erhalten, um den Lauf in <=5 Minuten an die Kanzlei zu übergeben.
US-02 [MVP] Als Buchhaltung möchte ich das Mapping "Werkszeit-Zeitart → DATEV- Lohnart" einmal pflegen, um es nicht jeden Monat neu zu tippen.
US-03 [MVP] Als Buchhaltung möchte ich bei Korrekturen einen Nachlauf erzeugen können (Storno + Neu), ohne die Original-Datei manuell zu editieren.
US-04 [MVP] Als Admin möchte ich Beraternummer + Mandantennummer validiert eingeben (Check-Digit), um Fehlläufe zum Steuerberater zu vermeiden.
US-05 [MVP] Als Manager möchte ich den Monatsabschluss fachlich freigeben, bevor die Buchhaltung exportiert — keine Export-Datei ohne 4-Augen.
US-06 [V1] Als Buchhaltung möchte ich den Versand via DATEV Unternehmen online direkt aus Werkszeit anstoßen, um die manuelle Upload-Strecke zu sparen.
US-07 [V1] Als Steuerberater möchte ich Rückläufer (Import-Fehler) in Werkszeit sehen, um sie dort zu korrigieren statt per E-Mail.
US-08 [V1.5] Als Admin möchte ich den Jahrgangs-Wechsel (2026→2027) per automatischem Update der DATEV-Schlüsselzahlen einspielen.
US-09 [V2] Als Referenzkunde möchte ich auch SAP HCM / Sage-Personal anbinden können, über denselben Lohnart-Mapping-Layer.5. Funktionale Anforderungen
Abschnitt betitelt „5. Funktionale Anforderungen“5.1 Mobile App (📱) — iOS + Android
Abschnitt betitelt „5.1 Mobile App (📱) — iOS + Android“— nicht zutreffend, weil DATEV-Export eine Back-Office-Funktion ist. Mitarbeiter sehen im ESS höchstens den Info-Stand „Lohn April 2026 versandt“ — das liegt im Feinkonzept §3.9 Self-Service, nicht hier.
5.2 Web-App (🌐)
Abschnitt betitelt „5.2 Web-App (🌐)“- F-W-01 — Monatsabschluss-Dashboard: Liste der letzten 13 Monate mit Status-Pill (
Entwurf/BR-Freigabe/Buchhaltung-Freigabe/Versandt/Korrekturlauf). Kennzahlen pro Monat: Stunden gesamt, Überstunden, Krank-Tage, Urlaubstage, DATEV-Export-Zeitpunkt, letzter Download. Filter: Jahr, Status, Sortierung chronologisch absteigend. - F-W-02 — Export-Wizard (3 Schritte): Schritt 1 „Zeitraum + Mandant wählen“ (Jahr/Monat/Mandantennummer-Auswahl bei Multi-Tenant-Steuerkanzlei), Schritt 2 „Vorschau“ (Tabelle mit Mitarbeiter × Lohnart × Stunden/Betrag, Validierungs-Rot-Markierung fehlender Zuordnungen), Schritt 3 „Format wählen“ (
LODAS-ASCII/EXTF/ beide) + Download-Trigger. - F-W-03 — Mapping-Editor: Tabelle „Werkszeit-Zeitart → DATEV-Lohnart“ mit Autocomplete auf DATEV-Schlüsselzahl-Liste (aktueller Jahrgang). Beispiele:
arbeitszeit.regulaer → 1 (Grundlohn),zuschlag.nacht → 13 (Nachtzuschlag),zuschlag.sonntag → 9 (Sonntagszuschlag 50%),abwesenheit.krank → 58 (Entgeltfortzahlung). Validierung: keine ungespeicherten Werte, keine Duplikate. - F-W-04 — Korrekturlauf: Jeder bereits versandte Monat bekommt Button „Korrekturlauf erstellen“. Erzeugt Storno-Satz (identische Sätze mit negativen Stunden/Beträgen) + neue korrigierte Sätze. Korrekturlauf referenziert per
ref_export_idauf Ursprungs-Export. Audit-Begründung Pflicht (min. 20 Zeichen). - F-W-05 — Mandantenstamm-Verwaltung: Eingabemaske für Beraternummer (7-stellig), Mandantennummer (1–5-stellig), Wirtschaftsjahr-Beginn, Kontenrahmen (SKR03/SKR04), DATEV-E-Mail für Rückläufer. Check-Digit-Validierung: offizielle DATEV-Prüfziffer auf Beraternummer-Eingabe.
- F-W-06 — Monats-Freigabe-Workflow: Manager sieht „zu prüfen“-Queue, gibt per Klick frei (oder verwirft mit Begründung). Erst nach Manager-Freigabe wird der Export-Button für Buchhaltung aktiv.
- F-W-07 — Versand-Status-Pill: Für jeden Monat:
Versandt 15.04.2026 15:32 · Frau Müller · Download-Log 2×. Klick auf Pill öffnet Audit-Detail. - F-W-08 — DATEV Unternehmen online API (V1): Zusätzlicher Button „An DATEV senden“ neben Download. OAuth 2.0-Flow beim Mandanten-Setup, API-Call
POST /uo/v1/belege. - F-W-09 — Dry-Run-Validator: Vor dem echten Export kann Buchhaltung einen „Trockenlauf“ starten — erzeugt Datei, lässt sie durch den internen DATEV-Validator laufen, zeigt Befunde, schreibt nichts in den Audit-Log. Nur finaler Export ist dokumentationspflichtig.
5.3 Cross-Plattform (🔄)
Abschnitt betitelt „5.3 Cross-Plattform (🔄)“- F-X-01 — Zeiteinheit konsistent: Stunden werden firmeneinheitlich als Industrie-Stunden (Dezimal, 2 Nachkommastellen) geführt — so wie es die Zeiterfassung §3.1 speichert. DATEV erwartet ebenfalls Industrie-Stunden; wir konvertieren nicht, wir passieren nur durch.
- F-X-02 — Monatsgrenze hart: Eine Zeitbuchung gehört zu dem Monat, in dem sie angefangen hat. Schichten über Mitternacht am 31.→1. werden beim Tag-Anfang abgeschnitten; die Stunden nach Mitternacht zählen in den Folgemonat (das ist DATEV-Standardverhalten, nicht unsere Wahl).
- F-X-03 — Nachträgliche Änderung gesperrt: Sobald ein Monat Status
Versandthat, werden die zugrunde liegenden Zeitbuchungen read-only. Änderungen sind nur über Korrekturlauf möglich (siehe F-W-04). Siehe auch Feinkonzeptkern/11-compliance-audit§3 „Monatsschluss-Lock“.
5.4 Admin-Konfiguration
Abschnitt betitelt „5.4 Admin-Konfiguration“- F-A-01 — Lohnart-Defaults je Branche: Bei Tenant-Anlage kommt ein Wizard, der die Branche abfragt (SHK, Maler, Elektro, Dachdecker, Trockenbau) und die passenden DATEV-Lohnarten inklusive SOKA-Bau-Zuschläge vorbelegt. Admin kann einzelne Mappings überschreiben.
- F-A-02 — Kontenrahmen-Wahl: SKR03 oder SKR04 (Default SKR03). Betrifft Sachkonten-Zuordnung im EXTF-Export.
- F-A-03 — Jahrgangs-Pflege: Admin-Oberfläche zeigt, welche DATEV-Schlüsselzahlen-Version aktuell geladen ist (z. B. „Jahrgang 2026, geladen 2026-01-08“). Update-Button lädt aktuelle Version aus
datev-schluessel-NPM-Paket (eigenes Repository, gegen DATEV-Schnittstellenbeschreibung validiert). - F-A-04 — Feature-Flag-Abschaltung: Wenn Betrieb kein DATEV nutzt (z. B. ADDISON, lexoffice), blendet der Admin
module.kern.datevkomplett aus. Die Zeiterfassung bleibt erhalten.
5.5 Roadmap-Schichtung
Abschnitt betitelt „5.5 Roadmap-Schichtung“| Anforderung-ID | MVP | V1 | V1.5 | V2 |
|---|---|---|---|---|
| F-W-01 Monatsabschluss-Dashboard | ✅ | |||
| F-W-02 Export-Wizard | ✅ | |||
| F-W-03 Mapping-Editor | ✅ | |||
| F-W-04 Korrekturlauf | ✅ | |||
| F-W-05 Mandantenstamm | ✅ | |||
| F-W-06 Monats-Freigabe | ✅ | |||
| F-W-07 Versand-Status | ✅ | |||
| F-W-08 DUO-API | ✅ | |||
| F-W-09 Dry-Run-Validator | ✅ | |||
| F-A-03 Jahrgangs-Pflege automatisch | ✅ | |||
| SAP HCM / Sage-Writer | ✅ |
6. Mockups & Flows
Abschnitt betitelt „6. Mockups & Flows“HTML-Hero-Mockup: 10-datev-integration.html — Web-primäres Layout mit Monatsabschluss-Dashboard + Export-Wizard.
6.1 Monatsabschluss-Dashboard (Web)
Abschnitt betitelt „6.1 Monatsabschluss-Dashboard (Web)“┌────────────────────────────────────────────────────────────────────────────────┐│ Werkszeit · shk-gebruder-schmidt Frau Müller · Buchhaltung [▾] │├────────────────────────────────────────────────────────────────────────────────┤│ Sidebar │ Lohn-Vorbereitung DATEV ││ ─────── │ ┌──────────────────────────────────────────────────────────────┐ ││ Zeit │ │ Monat │ Stunden │ Überst. │ Krank │ Status │ Aktion │ ││ Urlaub │ │ Apr 2026 │ 13.184 │ 412 │ 54 │ Entwurf │ prüfen │ ││ Plan │ │ Mrz 2026 │ 14.012 │ 398 │ 38 │ Versandt │ view │ ││ Projekte │ │ Feb 2026 │ 12.876 │ 302 │ 47 │ Versandt │ view │ ││ Rechnung │ │ Jan 2026 │ 13.501 │ 421 │ 61 │ Korrektur 1 │ view │ ││ ▶ DATEV │ │ Dez 2025 │ 11.984 │ 287 │ 89 │ Versandt │ view │ ││ Audit │ └──────────────────────────────────────────────────────────────┘ ││ │ Mandant: 12345 · Berater: 1234567 (Kanzlei Schuster) ││ │ Jahrgang DATEV 2026, Kontenrahmen SKR03 ││ │ [Monatslauf April starten] [Mapping pflegen] [DUO verbinden] │└────────────────────────────────────────────────────────────────────────────────┘6.2 Export-Wizard Schritt 2 — Vorschau (Web)
Abschnitt betitelt „6.2 Export-Wizard Schritt 2 — Vorschau (Web)“┌────────────────────────────────────────────────────────────────────────────────┐│ Export April 2026 · Vorschau (2/3) [Abbrechen] [Weiter]│├────────────────────────────────────────────────────────────────────────────────┤│ 🛡 Compliance: §147 AO · §41 EStG · §28f SGB IV · DSGVO Art. 88 ││ ││ Summen pro Lohnart: ││ ┌──────────────────────────────────────────────────────────────────────────┐ ││ │ Lohnart │ DATEV-Schl. │ Stunden │ MA │ Mapping │ ││ │ Grundlohn │ 1 │ 12.140 │ 78 │ ✓ Standard │ ││ │ Überstunden 25% │ 5 │ 302 │ 42 │ ✓ Standard │ ││ │ Nachtzuschlag │ 13 │ 81 │ 11 │ ✓ Standard │ ││ │ Sonntag 50% │ 9 │ 24 │ 6 │ ✓ Standard │ ││ │ Feiertag 125% │ 10 │ — │ — │ ✓ Standard │ ││ │ Ruf-Bereitschaft │ —— │ — │ — │ 🔴 NICHT GEMAPPT │ ││ │ EFZG Krank │ 58 │ 378 │ 12 │ ✓ Standard │ ││ │ Urlaub │ 65 │ 216 │ 9 │ ✓ Standard │ ││ │ SOKA-Bau-Zuschlag │ 142 │ — │ — │ ✓ Custom │ ││ └──────────────────────────────────────────────────────────────────────────┘ ││ ││ 🔴 1 Mapping-Lücke: "Ruf-Bereitschaft" hat keine DATEV-Schlüsselzahl. ││ Ohne Mapping läuft die Datei in LODAS auf Fehler. [Jetzt mappen →] │└────────────────────────────────────────────────────────────────────────────────┘6.3 Export-Wizard Schritt 3 — Format & Download
Abschnitt betitelt „6.3 Export-Wizard Schritt 3 — Format & Download“┌────────────────────────────────────────────────────────────────────────────────┐│ Export April 2026 · Format wählen (3/3) [Zurück] [Exportieren]│├────────────────────────────────────────────────────────────────────────────────┤│ ││ Zu welchem DATEV-Format? ││ ( ) LODAS-ASCII (für DATEV LODAS, CP1252, Festlänge) ││ (•) EXTF v9.0 (für DATEV Lohn und Gehalt, UTF-8 BOM, CSV) ││ ( ) Beide parallel (ZIP mit beiden Dateien) ││ ││ [ ] Zusätzlich via DATEV Unternehmen online direkt versenden (DUO-API) ││ ││ Dry-Run: Datei wurde intern mit dem DATEV-Validator geprüft — alle Regeln ││ eingehalten (0 Fehler, 0 Warnungen). ✓ ││ ││ [Export erstellen] ││ ││ Nach dem Export wird dieser Monat schreibgeschützt. Änderungen nur per ││ Korrekturlauf. │└────────────────────────────────────────────────────────────────────────────────┘6.4 Mapping-Editor (Web)
Abschnitt betitelt „6.4 Mapping-Editor (Web)“┌────────────────────────────────────────────────────────────────────────────────┐│ Lohnart-Mapping · Tenant shk-gebruder-schmidt · Branche SHK │├────────────────────────────────────────────────────────────────────────────────┤│ ┌──────────────────────────────────────────────────────────────────────────┐ ││ │ Werkszeit-Zeitart │ DATEV-Lohnart │ Konto (SKR03) │ ││ │ arbeitszeit.regulaer │ 1 Grundlohn │ 6200 │ ││ │ arbeitszeit.ueberstunde_25 │ 5 Überstunden 25% │ 6200 │ ││ │ arbeitszeit.ueberstunde_50 │ 6 Überstunden 50% │ 6200 │ ││ │ zuschlag.nacht │ 13 Nachtzuschlag │ 6206 │ ││ │ zuschlag.sonntag │ 9 Sonntag 50% │ 6206 │ ││ │ zuschlag.feiertag │ 10 Feiertag 125% │ 6206 │ ││ │ bereitschaft.ruf │ ▼ Bitte wählen … │ 🔴 │ ││ │ abwesenheit.krank │ 58 EFZG │ 6210 │ ││ │ abwesenheit.urlaub │ 65 Urlaub │ 6220 │ ││ │ spesen.verpflegung_12h │ 300 Verpflegungsmehr. │ 4674 │ ││ │ soka.bau.zuschlag │ 142 SOKA-Bau │ 6100 │ ││ └──────────────────────────────────────────────────────────────────────────┘ ││ [+ Zeile] [Branchen-Defaults wiederherstellen] [Speichern] │└────────────────────────────────────────────────────────────────────────────────┘6.5 Korrekturlauf-Dialog
Abschnitt betitelt „6.5 Korrekturlauf-Dialog“┌────────────────────────────────────────────────────────────────────────────────┐│ Korrekturlauf für Januar 2026 [Abbrechen] [OK]│├────────────────────────────────────────────────────────────────────────────────┤│ ││ Originallauf: 15.02.2026 14:08 · Export-ID export_2026-01_v1 ││ ││ Welche Änderung? ││ ( ) Einzelne Buchung korrigieren ││ (•) Komplett-Storno + Neulauf ││ ││ Begründung (Pflicht, min. 20 Zeichen): ││ ┌──────────────────────────────────────────────────────────────────────────┐ ││ │ Mehmet Yılmaz: Nachträgliche Genehmigung 4 h Samstagsarbeit KW2, │ ││ │ Freigabe durch Thomas Schmidt 2026-02-28, DGUV-Meldung Nr. 2026-014. │ ││ └──────────────────────────────────────────────────────────────────────────┘ ││ ││ Die erzeugte Datei enthält: ││ • Storno aller Originalsätze (negative Stunden) ││ • Neue korrigierte Sätze ││ • Referenz export_ref = export_2026-01_v1 ││ ││ [Korrekturlauf erstellen] │└────────────────────────────────────────────────────────────────────────────────┘6.6 Versand-Status-Pill (Audit-Detail)
Abschnitt betitelt „6.6 Versand-Status-Pill (Audit-Detail)“┌────────────────────────────────────────────────────────────────────────────────┐│ Audit-Trail · Monat März 2026 │├────────────────────────────────────────────────────────────────────────────────┤│ 📅 2026-04-15 09:12 datev.monatslauf.erstellt Frau Müller ││ 📅 2026-04-15 10:24 datev.monatslauf.freigegeben Thomas Schmidt (Bauleiter) ││ 📅 2026-04-15 15:32 datev.export.lodas-ascii Frau Müller ││ └─ Datei SHA256: 4a8f…c9b2 ││ └─ 412 Sätze, 17 KB CP1252, Validator ✓ ││ 📅 2026-04-15 15:33 datev.export.extf Frau Müller ││ └─ Datei SHA256: 8b1c…92e7 ││ 📅 2026-04-15 15:45 datev.duo.versandt System (DUO-API v1.4) ││ └─ DUO-Beleg-ID bel_9af82b3c · Empfang bestätigt ││ 📅 2026-04-22 11:08 datev.download Frau Müller (Re-Download) ││ ││ Aufbewahrung: Datei + Audit bis 31.12.2036 (§147 AO, 10 Jahre) │└────────────────────────────────────────────────────────────────────────────────┘Symbol-Konvention. 🔴 Pflichtfeld / Error, ✓ Validierung ok, 📅 Audit-Zeitstempel, ⤓ Download, ▲ Upload, ▼ Select.
7. Datenmodell-Skizze
Abschnitt betitelt „7. Datenmodell-Skizze“Pseudo-Drizzle-Schema.
export const datevMandantenTable = pgTable('datev_mandanten', { id: uuid('id').primaryKey().defaultRandom(), tenantId: uuid('tenant_id').notNull().references(() => tenantsTable.id), beraternummer: varchar('beraternummer', { length: 7 }).notNull(), // DATEV-Beraternr mandantennummer: varchar('mandantennummer', { length: 5 }).notNull(), // innerhalb Berater kontenrahmen: varchar('kontenrahmen', { length: 5 }).notNull(), // SKR03 | SKR04 wjBeginnMonat: integer('wj_beginn_monat').notNull().default(1), // Jan=1 jahrgang: varchar('jahrgang', { length: 4 }).notNull(), // "2026" duoClientId: text('duo_client_id'), // OAuth bei DUO duoRefreshToken: text('duo_refresh_token_encrypted'), // KMS-verschlüsselt createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),}, (t) => ({ tenantIdx: uniqueIndex('datev_mandanten_tenant_idx').on(t.tenantId), berMandCheck: check('datev_ber_digit', sql`length(${t.beraternummer})=7`),}));
export const datevLohnartMappingTable = pgTable('datev_lohnart_mapping', { id: uuid('id').primaryKey().defaultRandom(), tenantId: uuid('tenant_id').notNull().references(() => tenantsTable.id), zeitart: varchar('zeitart', { length: 64 }).notNull(), // 'arbeitszeit.regulaer' datevSchluessel: integer('datev_schluessel').notNull(), // 1, 5, 9, 13, 58 … sachkonto: varchar('sachkonto', { length: 8 }).notNull(), // '6200' bezeichnung: varchar('bezeichnung', { length: 80 }).notNull(), // 'Grundlohn' createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(), createdBy: uuid('created_by').notNull().references(() => usersTable.id),}, (t) => ({ tenantZeitUq: uniqueIndex('datev_lohnart_tenant_zeit_uq').on(t.tenantId, t.zeitart),}));
export const datevMonatslaufTable = pgTable('datev_monatslaufe', { id: uuid('id').primaryKey().defaultRandom(), // UUID v7 (Idempotenz) tenantId: uuid('tenant_id').notNull().references(() => tenantsTable.id), jahr: integer('jahr').notNull(), monat: integer('monat').notNull(), status: varchar('status', { length: 24 }).notNull(), // entwurf | freigabe | versandt | korrektur refMonatslaufId: uuid('ref_monatslauf_id').references(() => datevMonatslaufTable.id), // bei Korrektur freigegebenVon: uuid('freigegeben_von').references(() => usersTable.id), freigegebenAt: timestamp('freigegeben_at', { withTimezone: true }), versandtAt: timestamp('versandt_at', { withTimezone: true }), exportFormate: jsonb('export_formate').$type<{ lodas?: FileRef; extf?: FileRef }>(), validatorReport: jsonb('validator_report'), korrekturGrund: text('korrektur_grund'), // Pflicht bei status=korrektur createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(), createdBy: uuid('created_by').notNull().references(() => usersTable.id), // GoBD-Felder hashPrev: bytea('hash_prev'), hashSelf: bytea('hash_self'),}, (t) => ({ tenantYearMonthUq: uniqueIndex('datev_monatslauf_t_y_m_uq') .on(t.tenantId, t.jahr, t.monat) .where(sql`status != 'korrektur'`), // nur 1 Hauptlauf je Monat statusIdx: index('datev_monatslauf_status_idx').on(t.tenantId, t.status),}));RLS-Policy-Sketch.
ALTER TABLE datev_monatslaufe ENABLE ROW LEVEL SECURITY;
CREATE POLICY datev_mon_tenant_iso ON datev_monatslaufe USING (tenant_id = current_setting('app.tenant_id')::uuid);
CREATE POLICY datev_mon_read ON datev_monatslaufe FOR SELECT USING ( tenant_id = current_setting('app.tenant_id')::uuid AND current_setting('app.scope') IN ('all','team') -- kein 'own'-Zugriff AND current_setting('app.roles') LIKE '%buchhaltung%' OR current_setting('app.roles') LIKE '%admin%' OR current_setting('app.roles') LIKE '%manager%' );
CREATE POLICY datev_mon_write ON datev_monatslaufe FOR INSERT WITH CHECK ( tenant_id = current_setting('app.tenant_id')::uuid AND current_setting('app.roles') LIKE '%buchhaltung%' );
-- Append-only: keine UPDATE/DELETE durch normale RollenCREATE POLICY datev_mon_no_update ON datev_monatslaufe FOR UPDATE USING (false);ER-Bezug. Referenziert tenantsTable, usersTable, zeitbuchungenTable (Feinkonzept §3.1), abwesenheitenTable (§3.3), spesenTable (§3.6). Schreibt in auditLogTable (§3.11).
8. API-Endpunkte
Abschnitt betitelt „8. API-Endpunkte“Pfad-Konvention: /v1/kern/datev/….
| Methode | Pfad | Auth-Scope | Rate-Limit | Idempotenz | Beschreibung |
|---|---|---|---|---|---|
GET |
/v1/kern/datev/mandant |
datev:read |
Standard | — | Mandantenstamm lesen |
PUT |
/v1/kern/datev/mandant |
datev:admin |
Privileged | Idempotency-Key | Beraternr/Mandantennr setzen |
GET |
/v1/kern/datev/mapping |
datev:read |
Standard | — | Lohnart-Mapping-Liste |
PUT |
/v1/kern/datev/mapping |
datev:admin |
Privileged | Idempotency-Key | Mapping anlegen/ändern |
GET |
/v1/kern/datev/monatslauf |
datev:read |
Standard | — | Monatsliste 13 Monate |
POST |
/v1/kern/datev/monatslauf |
datev:write |
Privileged | Idempotency-Key | Monatslauf erstellen (Entwurf) |
POST |
/v1/kern/datev/monatslauf/{id}/preview |
datev:read |
Privileged | — | Vorschau-Tabelle (Schritt 2) |
POST |
/v1/kern/datev/monatslauf/{id}/dry-run |
datev:write |
Privileged | — | Validator-Trockenlauf, kein Audit |
POST |
/v1/kern/datev/monatslauf/{id}/freigeben |
datev:approve |
Privileged | Idempotency-Key | Manager-Freigabe |
POST |
/v1/kern/datev/monatslauf/{id}/export |
datev:export |
Privileged | Idempotency-Key | Export mit format=lodas|extf|beide |
GET |
/v1/kern/datev/monatslauf/{id}/download/{format} |
datev:export |
Privileged | — | Datei-Download (presigned) |
POST |
/v1/kern/datev/monatslauf/{id}/korrektur |
datev:write |
Privileged | Idempotency-Key | Korrekturlauf-Start |
POST |
/v1/kern/datev/monatslauf/{id}/duo-send |
datev:export |
Privileged | Idempotency-Key | Versand via DATEV Unternehmen online |
OpenAPI-Schema-Skizze.
paths: /v1/kern/datev/monatslauf/{id}/export: post: operationId: exportMonatslauf x-werkszeit-scope: datev:export x-werkszeit-rate-limit: privileged parameters: - name: id in: path required: true schema: { type: string, format: uuid } requestBody: required: true content: application/json: schema: type: object required: [format] properties: format: { type: string, enum: [lodas, extf, beide] } duoSend: { type: boolean, default: false } responses: '200': content: application/json: schema: type: object properties: status: { type: string, enum: [versandt] } lodasUrl: { type: string, format: uri } extfUrl: { type: string, format: uri } validator: { $ref: '#/components/schemas/ValidatorReport' } auditEventId: { type: string, format: uuid } '409': { description: 'Monatslauf bereits exportiert — Korrekturlauf nötig' } '422': { description: 'Mapping-Lücken oder Validator-Fehler' }Webhook-Events.
datev.monatslauf.erstelltdatev.monatslauf.freigegebendatev.monatslauf.versandtdatev.monatslauf.korrekturdatev.duo.rueckmeldung(V1)
9. Offline-Profil
Abschnitt betitelt „9. Offline-Profil“| Profil | Begründung | Mechanik |
|---|---|---|
| Online-only | DATEV-Export ist ein Back-Office-Vorgang an einem Arbeitsplatz mit Festnetz. Offline-Export wäre gefährlich (veraltete Schlüsselzahlen, keine Validator-Prüfung, keine DUO-Quittung). | UI-Block bei connectivity == none; Hinweis „DATEV-Export nur online verfügbar“. |
Konflikt-Strategie. Entfällt — keine Mobile-Interaktion, keine Offline-Mutation.
Datei-Handling. Erzeugte LODAS-/EXTF-Dateien werden in S3 (eu-central-1, Object Lock Compliance Mode, 10 Jahre) abgelegt. Download erfolgt über presigned URL (15 min Gültigkeit). Die Datei selbst wird NICHT in der DB gespeichert, nur die SHA-256-Hash-Referenz im datev_monatslaufe-Eintrag.
10. Compliance-Mapping
Abschnitt betitelt „10. Compliance-Mapping“10.1 GoBD
Abschnitt betitelt „10.1 GoBD“- Append-only:
datev_monatslaufehathashPrev/hashSelf(SHA-256 kanonisiert). KeineUPDATE-Policy (siehe §7). - Korrekturlauf statt Änderung: Original bleibt unverändert, Korrektur als eigener Datensatz mit
ref_monatslauf_id. Begründung Pflicht (min. 20 Zeichen). - Aufbewahrung: LODAS-/EXTF-Dateien +
datev_monatslaufe-Zeilen + zugehörige Audit-Events bleiben 10 Jahre + laufendes Jahr gem. §147 AO. S3 Object Lock Compliance Mode verhindert technisch das Löschen. - Verfahrensdokumentation: Auto-generiert aus diesem Feinkonzept + tatsächlicher Systemparameter (Jahrgang, Validator-Version) in
gobd-verfahrensdoku.md(siehekern/11-compliance-audit). - Nachvollziehbarkeit: Jeder Export erzeugt Audit-Event mit User, Zeit, Datei-Hash, Validator-Report-Hash. Hash-Chain unveränderlich.
- Unveränderlichkeit nach Monatsschluss: Sobald
status=versandt, werden referenzierte Zeitbuchungen im DB-Trigger read-only (Zuordnungs-ID statt „Monatsschluss-Flag“).
10.2 ArbZG
Abschnitt betitelt „10.2 ArbZG“— nicht zutreffend, weil DATEV-Export nur Lohn-Daten transportiert, keine Arbeitszeit-Regel durchsetzt. ArbZG-Compliance passiert beim Stempeln (§3.1) und Planen (§3.8).
10.3 VOB/B
Abschnitt betitelt „10.3 VOB/B“— nicht zutreffend, DATEV ist Lohn, nicht Bauleistung.
10.4 DSGVO
Abschnitt betitelt „10.4 DSGVO“- Art. 5 Datenminimierung: Exportiert werden nur die zur Lohnabrechnung gesetzlich notwendigen Felder (Name, SV-Nummer, Steuerklasse, Stunden, Lohnart, Konto). Keine Fotos, keine Geo-Daten, keine Bautagebuch-Einträge.
- Art. 6 Rechtsgrundlage: Vertrag (Art. 6 Abs. 1 b) — Arbeitsvertrag verpflichtet zur Lohnabrechnung. SV-Nummer & Steuer-ID: gesetzliche Pflicht (Art. 6 Abs. 1 c) + §41 EStG / §28a SGB IV.
- Art. 9 Besondere Kategorien: Krankheitstage erscheinen als EFZG-Zeilen — aber ohne Diagnose. Nur Anzahl-Tage, was nach AAG/EFZG zulässig ist.
- Art. 17 Löschung: Scheidet ein Mitarbeiter aus, bleiben Lohn-Daten 10 Jahre (§147 AO > Art. 17 DSGVO, konkurrierende Pflicht). Nach Ablauf Frist wird der Datensatz in
datev_monatslaufepseudonymisiert (Name → Hash), die Datei selbst wird gelöscht. - Art. 20 Datenexport: Mitarbeiter erhält auf Anfrage seine persönlichen Lohn-Daten als JSON (Name, Monate, Stunden, Zuschläge, Zusatzbeträge). Nicht die gesamte LODAS-Datei (die enthält Daten anderer Mitarbeiter).
- Art. 30 Verarbeitungsverzeichnis: Eintrag „DATEV-Export Lohnvorerfassung“ — Zweck: Lohnabrechnung, Empfänger: Steuerkanzlei X, Aufbewahrung: 10 Jahre §147 AO, Rechtsgrundlage: Art. 6 Abs. 1 b/c.
- DSFA: Keine Pflicht. Es handelt sich um eine gesetzlich geforderte, standardisierte Datenverarbeitung ohne automatisierte Einzelentscheidung, ohne Profiling, ohne Art. 35 Abs. 3 Fallgruppe.
- Art. 88 (Beschäftigten-Datenschutz): SV-Nummer, Bankdaten, Steuermerkmale werden verschlüsselt at-rest (PostgreSQL
pgcrypto+ KMS-verwaltete Keys) gespeichert und nur bei Export in die DATEV-Datei geschrieben. Audit-Events protokollieren jeden Zugriff auf das Feld.
10.5 BFSG / WCAG 2.2 AA
Abschnitt betitelt „10.5 BFSG / WCAG 2.2 AA“— nicht zutreffend, weil Back-Office-Funktion ohne ESS-Bezug. Intern gilt trotzdem WCAG 2.1 AA für die Web-UI (Tastatur-Navigation, Kontrast, Screenreader-Labels), weil es Teil des Werkszeit-Design-Systems ist.
10.6 BetrVG §87(1)6
Abschnitt betitelt „10.6 BetrVG §87(1)6“— nicht zutreffend, DATEV-Export ist keine Leistungs-/Verhaltenskontrolle. Der Export zeigt Stunden und Lohnarten, die aus bereits genehmigten Zeitbuchungen stammen; keine neue Überwachungsdimension entsteht.
10.7 Weitere Spezial-Compliance
Abschnitt betitelt „10.7 Weitere Spezial-Compliance“- §147 AO (10 Jahre): S3 Object Lock Compliance Mode, bucketseitig konfiguriert, Löschversuche werden von S3 selbst zurückgewiesen.
- §41 EStG (Lohnkonto-Pflichtfelder): Sozialversicherungsnummer, Steuer-ID, Geburtsdatum, Steuerklasse, Konfession müssen im LODAS-Stammsatz (Satzart 100) geführt werden. Werkszeit liest sie aus dem HR-Stamm; fehlen Felder, blockiert der Validator den Export.
- §28f SGB IV (Beitragsnachweis): SV-Nummer zwingend. Validator prüft Modulo-11-Prüfziffer der SV-Nr.
- DATEV-Schnittstellenbeschreibung LODAS-ASCII (Jg. 2026): Jede Satzart (100 Stamm, 110 Bewegung, 120 Zuschlag) hat festgelegte Feldbreiten, CP1252-Encoding,
CRLF-Zeilenenden. Unser Writer-Modul folgt dem Kapitel „Satzaufbau LODAS-ASCII“ der aktuellen Jahrgangs-Doku byte-genau; Generator-Konstruktor bekommt das Jahrgangs-Objekt injiziert, so dass beim Jahreswechsel 2026→2027 nur das Jahrgangs-Paket getauscht wird. - DATEV EXTF v9.0: UTF-8 BOM, Semikolon-separiert, Header-Zeile 1 ist Metadaten-Zeile (
EXTF;700;21;Buchungsstapel;9;…), Header-Zeile 2 ist Spaltennamen. Wir schreiben Lohn-Bewegungen auf „Buchungsstapel“-Schema. - DATEV Unternehmen online API v1.4 (V1): OAuth 2.0 Authorization Code + Refresh Token, POST
/uo/v1/belegemitkategorie=lohn, Datei als Multipart-Body. Refresh-Token KMS-verschlüsselt in DB. - DATEV-Validator: Eigenes Team-internes Npm-Paket
@werkszeit/datev-validator, das die offiziellen Regelwerke der DATEV-Schnittstellenbeschreibung abbildet. CI läuft Musterdateien durch Validator; Abweichung blockt Merge.
11. Edge-Cases
Abschnitt betitelt „11. Edge-Cases“| # | Szenario | Erwartetes Verhalten |
|---|---|---|
| EC-01 | Monatsübergreifende Schicht (Schicht 31.03. 22:00 – 01.04. 06:00) | Split bei 24:00; Stunden vor Mitternacht → März, nach Mitternacht → April. Entsprechend zwei Zeilen im Export, Mitarbeiter merkt nichts. |
| EC-02 | Mapping-Lücke zum Export-Zeitpunkt (neue Zeitart bereitschaft.ruf erstmals erfasst) |
Vorschau Schritt 2 markiert 🔴, „Jetzt mappen“ führt zum Mapping-Editor, dort Schlüsselzahl eingeben, zurück zum Wizard. Export blockiert bis Mapping vollständig. |
| EC-03 | Multi-Tenant-Bleed-Versuch (Buchhaltung einer Kanzlei bedient 10 Mandanten) | current_setting('app.tenant_id') erzwingt Isolation. Download einer fremden Export-URL via ID-Guessing liefert 404 (nicht 403). Kein Audit in fremdem Tenant. |
| EC-04 | Korrekturlauf auf Korrekturlauf (Mehrfach-Korrektur Januar 2026) | Kette v1 → v1.k1 → v1.k2, jede Version referenziert Vorgänger. UI zeigt Version-Tree. Validator prüft Gesamt-Saldo Original − Storno + Neu == aktueller Soll-Stand. |
| EC-05 | Großmenge (250 MA × 31 Tage = 7.750 Stundeneinträge) | LODAS-Writer streamt als node:stream.Writable direkt in S3-Multipart-Upload. P95 < 15 s für 10.000 Sätze (Last-Test-Ziel). |
| EC-06 | Abgelaufene DATEV-Jahrgangs-Version (Betrieb hat Jahrgang 2025, Export wird im April 2026 versucht) | Validator wirft UnsupportedYearFault, UI zeigt „Jahrgang 2026 laden“ → Admin klickt → NPM-Paket wird aktualisiert → Retry. |
| EC-07 | SV-Nummer fehlt (neuer Mitarbeiter, noch nicht eingetragen) | Vorschau zeigt 🔴 neben Name, Link zu HR-Stamm-Edit. Export ohne SV-Nr. wird nicht erzeugt. |
| EC-08 | DUO-API down (DATEV-Server 503 bei Versand) | Status bleibt versandt_lokal, Retry-Queue läuft Backoff (1 min, 5 min, 30 min, 2 h). Nach 3 Fehlversuchen: Buchhaltung wird benachrichtigt, manueller Upload-Pfad (Datei-Download) als Fallback. |
| EC-09 | Buchhaltungs-Nutzerin wechselt den Arbeitgeber mitten im Monatslauf | RBAC entfernt bei Austritt sofort den Scope datev:export. Laufender Lauf bleibt in Status Entwurf, Admin muss neuen Nutzer zuweisen. Kein Datenverlust. |
| EC-10 | Double-Submit (Buchhaltung klickt „Export“ zweimal schnell) | Idempotency-Key auf POST /monatslauf/{id}/export erkennt Duplikat → 200 mit identischer Antwort, kein zweiter Audit-Eintrag, keine zweite S3-Datei. |
| EC-11 | Zeitzonen-Chaos (Buchhaltung im Urlaub in Thailand, klickt Export um 22:00 Bangkok = 16:00 CET) | Export-Zeitstempel = UTC, UI-Anzeige = Europe/Berlin. In LODAS-Datei steht der CET-Monat, niemals Bangkok-Zeit. |
| EC-12 | Kanzlei-Wechsel zum Jahreswechsel (Beraternummer 1234567 → 7654321) | Admin ändert Mandantenstamm per neuem Datensatz mit gueltig_ab=2027-01-01; alte Zeilen bleiben für Altläufe referenziert (Append-only-Pattern). |
12. Akzeptanzkriterien (Gherkin)
Abschnitt betitelt „12. Akzeptanzkriterien (Gherkin)“Funktionalität: DATEV-Monatsabschluss und Export
Hintergrund: Angenommen ein Tenant "shk-gebruder-schmidt" mit Modul-Gate "module.kern.datev" Und ein Mandantenstamm mit Beraternummer "1234567" und Mandantennummer "12345" Und ein Nutzer "Frau Müller" mit Rolle "Buchhaltung" Und ein Nutzer "Thomas Schmidt" mit Rolle "Manager" Und gepflegtes Lohnart-Mapping für alle im April 2026 benutzten Zeitarten
Szenario: Happy Path — Monatsabschluss April 2026, LODAS + EXTF exportieren Wenn Frau Müller "Monatslauf April starten" klickt Dann wird ein Monatslauf mit Status "Entwurf" angelegt Und Frau Müller sieht die Vorschau-Tabelle mit allen Lohnarten, 0 Mapping-Lücken Wenn Thomas Schmidt den Lauf freigibt Und Frau Müller einen Dry-Run klickt Dann meldet der DATEV-Validator 0 Fehler, 0 Warnungen Wenn Frau Müller "Export erstellen" mit Format "beide" klickt Dann werden zwei Dateien erzeugt (LODAS-ASCII, EXTF) Und der Status wechselt auf "Versandt" Und die referenzierten April-Zeitbuchungen sind read-only Und ein Audit-Log-Eintrag "datev.export.lodas-ascii" existiert Und ein Audit-Log-Eintrag "datev.export.extf" existiert
Szenario: Grenzfall — Mapping-Lücke blockiert Export Angenommen ein Mitarbeiter hat erstmals eine Zeitbuchung mit Zeitart "bereitschaft.ruf" Und diese Zeitart ist nicht gemappt Wenn Frau Müller den Monatslauf-Export-Wizard öffnet Dann zeigt die Vorschau (Schritt 2) die Zeitart mit rotem Marker "NICHT GEMAPPT" Und der "Weiter"-Button zu Schritt 3 ist deaktiviert Wenn Frau Müller im Mapping-Editor "bereitschaft.ruf → 62 Bereitschaftszuschlag" hinzufügt Und zurück zum Wizard geht Dann ist die Vorschau grün, der "Weiter"-Button aktiv
Szenario: Grenzfall — Korrekturlauf nach nachträglicher Samstagsgenehmigung Angenommen Januar 2026 ist bereits versandt (Export-ID "export_2026-01_v1") Und eine nachträgliche Samstagsarbeit 4 h für "Mehmet Yılmaz" wurde genehmigt Wenn Frau Müller "Korrekturlauf erstellen" für Januar klickt Und als Begründung "Nachträgliche Samstagsgenehmigung KW2, Freigabe 28.02.2026" eingibt Und "Komplett-Storno + Neulauf" wählt und bestätigt Dann wird ein neuer Monatslauf mit status="korrektur" und ref_monatslauf_id=Ursprung erzeugt Und die Export-Datei enthält einen Stornoblock (negative Stunden) plus den neuen Monatsstand Und das Audit-Log zeigt drei Events: "korrektur.erstellt", "korrektur.validiert", "korrektur.versandt"
Szenario: Grenzfall — Multi-Tenant-Isolation beim Direkt-Download Angenommen ein zweiter Tenant "musterbetrieb-maler" Und ein dort existierender Monatslauf mit ID "mon_ABC" Wenn Frau Müller (Tenant shk-gebruder-schmidt) GET /monatslauf/mon_ABC/download/lodas aufruft Dann antwortet die API mit 404 Und es entsteht KEIN Audit-Log-Eintrag im Tenant musterbetrieb-maler
Szenario: Grenzfall — GoBD-Unveränderlichkeit blockiert Zeitbuchungs-Korrektur Angenommen April 2026 ist "Versandt" Wenn Thomas Schmidt versucht, eine April-Zeitbuchung direkt zu ändern Dann antwortet die API mit 409 "Monat ist abgeschlossen — Korrekturlauf nutzen" Und es entsteht KEIN DB-UPDATE Und das Audit-Log zeigt "zeitbuchung.korrektur.blockiert"
Szenario: Grenzfall — DATEV Unternehmen online API 503 Wenn Frau Müller "Export + DUO senden" klickt Und die DUO-API 503 antwortet Dann wechselt der Status auf "versandt_lokal" Und eine Retry-Queue startet mit Backoff 1 min → 5 min → 30 min → 2 h Und nach 3 Fehlversuchen erhält Frau Müller eine UI-Benachrichtigung Und sie hat weiterhin Zugriff auf den lokalen Datei-Download als Fallback13. Test-Cases
Abschnitt betitelt „13. Test-Cases“13.1 Unit-Tests (TypeScript)
Abschnitt betitelt „13.1 Unit-Tests (TypeScript)“- U-01 — Beraternummer-Prüfziffer (Modulo-Check) gegen offizielle DATEV-Beispiele.
- U-02 — SV-Nummer-Modulo-11 (§28a SGB IV) als Property-based Test (10 000 Seed-Werte).
- U-03 — LODAS-Satzart-100-Layout: Festlängen, Padding, CP1252-Encoding bei Umlauten („Müller“ →
4D 75 EC 6C 6C 65 72). - U-04 — EXTF-Header-Zeile: Version, Buchungsart, Mandantennummer an korrekten Positionen.
- U-05 — Monats-Split bei Schichten über Mitternacht (Property-based auf 1 000 Zufalls-Schichten).
- U-06 — Korrekturlauf-Saldo-Formel:
sum(storno) + sum(neu) == delta_stand. - U-07 — Rundung Stunden auf 2 Nachkommastellen (Banker’s Rounding, IEEE 754 half-even) — Property-based.
- U-08 — Idempotency-Key-Dedup-Logik: doppelter Key in 60 s → 200 mit Cache-Antwort, kein zweiter DB-Insert.
13.2 Widget- / Component-Tests
Abschnitt betitelt „13.2 Widget- / Component-Tests“— entfällt (keine Mobile-Komponenten). Web-Component-Tests in §13.4.
13.3 Integrations-Tests (Backend, Drizzle In-Memory)
Abschnitt betitelt „13.3 Integrations-Tests (Backend, Drizzle In-Memory)“- I-01 — Multi-Tenant-Isolation für alle 13 DATEV-Endpunkte (Pflicht DOD §2.2).
- I-02 — RLS: Buchhaltung Tenant A sieht keine Monatsläufe Tenant B.
- I-03 — Outbox-Idempotenz bei POST export: doppelter Idempotency-Key → 409 oder identische Antwort.
- I-04 — Hash-Chain-Bruch-Detection: direkte DB-Mutation eines
datev_monatslaufe-Eintrags → Integrity-Check meldet Chain-Bruch. - I-05 — Zeitbuchungs-Read-Only-Lock nach
versandt: UPDATE auf Buchung blockiert per Trigger. - I-06 — Mapping-Uniqueness: zweiter Mapping-Eintrag für identische Zeitart → 409.
13.4 E2E-Tests (Playwright auf Web)
Abschnitt betitelt „13.4 E2E-Tests (Playwright auf Web)“- E-01 — Happy-Path April 2026 auf Seed-Tenant
shk-gebruder-schmidt(80 MA, 12 000 Stunden): Wizard-Strecke + Download + SHA-256-Verifikation der Datei gegen Fixture-Hash. - E-02 — Mapping-Lücke-Flow: Zeitart „bereitschaft.ruf“ erstmalig erfasst, Wizard blockt, Admin pflegt Mapping, Wizard geht weiter.
- E-03 — Korrekturlauf-Flow mit Begründungs-Validierung (<20 Zeichen abgewiesen).
- E-04 — Accessibility: axe-core auf allen 3 Wizard-Schritten + Mapping-Editor, 0 Critical/Serious.
- E-05 — Visuelle Regression: Golden-Image Dashboard + Wizard-Steps für Chromium + Firefox + WebKit.
13.5 Compliance-Tests (Suite apps/api/test/compliance/datev/)
Abschnitt betitelt „13.5 Compliance-Tests (Suite apps/api/test/compliance/datev/)“- C-01 — Hash-Chain-Integrität auf 1 000 zufälligen Monatsläufen.
- C-02 — DATEV-Validator offiziell: Test-Fixtures
fixtures/lodas/happy-path-april-2026.csv+fixtures/extf/happy-path-april-2026.csvdurchlaufen den offiziellen DATEV-Prüfservice (eingerichtet als eigener CI-Job mit DATEV-Test-Mandant). - C-03 — Jahrgangs-Wechsel-Test: Fixture mit Jahrgang 2025 wird mit Jahrgang-2026-Writer geladen → erwarteter Fehler
UnsupportedYearFault. - C-04 — CP1252-Byte-Treue: LODAS-Datei vom Writer wird byte-genau mit Referenz-Dump (von DATEV Beispiel-Kunde) verglichen.
- C-05 — SV-Nr.-Modulo-Validierung als Property-based Test (10 000 Samples).
- C-06 — GoBD-Aufbewahrungs-Test: Attempt zu DELETE auf S3 Object Lock → AWS-SDK wirft
InvalidWriteOffset, Test erwartet diesen Fehler.
13.6 Flakiness-Schutz
Abschnitt betitelt „13.6 Flakiness-Schutz“- Lokaler 20×-Re-Run der E2E-Tests grün (DOD §2.2).
- CI-Job
datev-validator-smokeläuft nightly gegen offiziellen Service.
14. Nicht-Ziele
Abschnitt betitelt „14. Nicht-Ziele“| Nicht-Ziel | Begründung |
|---|---|
| Integration mit ADDISON, Sage Payroll, lexoffice-Lohn | Phase 1: nur DATEV. Markt-Realität: 40 % Handwerksbetriebe auf DATEV, alle anderen zusammen < 20 %. Kein Referenzkunde aus diesen Ökosystemen fragt es an. V2 auf Request. |
| Direkte Lohnabrechnung (Netto-Berechnung, Steuer/SV-Beiträge) | Werkszeit ist Lohn-Vorerfassung, nicht Lohnabrechnung. Die Kanzlei macht die eigentliche Abrechnung. Ein Netto-Rechner wäre rechtlich riskant (ständige Steuer- und SV-Updates) und außerhalb unseres Fokus. |
| DMS-Funktionalität (Lohnzettel-Archiv, elektronische Lohnsteuerbescheinigung) | DATEV macht das selbst via DUO. Wir leiten nur die Vorerfassung durch. |
| Abrechnung von Minijobs auf Minijob-Zentrale | V1.5+, benötigt separates Feinkonzept und Anbindung. |
| SOKA-Bau-Meldungen direkt aus Werkszeit | Eigenes Feinkonzept handwerk/12-soka-bau. DATEV-Export enthält SOKA-Zuschlag-Sätze, aber die Meldung an SOKA läuft separat. |
| Export historischer Monate vor Werkszeit-Go-Live | Einmalige Migration kein Produkt-Feature. Wird als Professional Service umgesetzt. |
| Custom-CSV-Export-Designer („Wenn-Sie-nicht-DATEV-nutzen“) | Nein. LESSONS-LEARNED §8 erklärt die Bananenschale. Wenn DATEV nicht passt: module.kern.datev abschalten, Rohdaten via Reporting §3.7 exportieren. |
15. Risiken & offene Annahmen
Abschnitt betitelt „15. Risiken & offene Annahmen“| Risiko / Annahme | Impact | Wahrscheinlichkeit | Gegenmaßnahme |
|---|---|---|---|
| DATEV-Schnittstellenbeschreibung Jg. 2026 ändert Spaltenlayout kurzfristig | hoch | niedrig | Jahrgangs-Paket @werkszeit/datev-schluessel wird quartalsweise gegen offizielle Doku reviewed; Canary-Deploy bei Jahrgangswechsel |
| DUO-API v1.4 wird deprecated zugunsten v2 | mittel | mittel | Schema-Abstraktion im API-Client, v1 + v2 parallel, Rollout per Feature-Flag |
| Referenzkunde hat Sonder-Lohnarten (z. B. Akkord, Werkverträge), die kein Standard-Mapping haben | mittel | hoch | Mapping-Editor hat „Custom“-Flag, Admin kann freie Schlüsselzahlen eingeben + Kommentar; Steuerberater-Review vor Go-Live |
| Steuerkanzlei weigert sich, EXTF zu importieren, will nur LODAS | niedrig | mittel | Beide Formate parallel ab MVP. Buchhaltung wählt am Wizard. |
| Mehrere Mandantennummern beim selben Betrieb (Holding-Struktur) | mittel | niedrig | V1.5: Tenant-Hierarchie. MVP: 1:1 Tenant = 1 Mandantennummer. |
| Zeitzonen-Bug beim Monatsgrenze-Split (Sommer-/Winterzeit-Umstellung) | hoch | niedrig | Property-based Test mit 1000 Samples aus DST-Übergängen. Konsequent UTC-storage + Europe/Berlin-Darstellung. |
16. Abhängigkeiten
Abschnitt betitelt „16. Abhängigkeiten“- Vorbedingung:
kern/01-zeiterfassungliefert die Stunden-Quelle;kern/03-abwesenheitenliefert Krank/Urlaub;kern/06-spesen-reisemanagementliefert Verpflegungsmehraufwand + Km-Geld;kern/09-auth-self-serviceliefert Rolle „Buchhaltung“. - Schnittstelle zu: S3 Object Lock (Aufbewahrung), KMS (SV-Nr-Verschlüsselung), Audit-Log-Service
kern/11-compliance-audit. - Wird konsumiert von: Reporting
kern/07-reporting-auswertung(Kennzahl „DATEV-Exporte YTD“), Compliance-Dashboardkern/11-compliance-audit.
17. Referenzkunde-Slot
Abschnitt betitelt „17. Referenzkunde-Slot“Status: TBD — zu klären mit Sales / Product-Owner.
DOR §1.1.1 verlangt: „Mindestens ein zahlender Design-Partner ist namentlich dokumentiert, der das Feature konkret fordert.“
Kandidaten-Profile:
- Handwerksbetrieb 40–80 MA, eigenständige Lohnbuchhaltung, DATEV LODAS
- Steuerkanzlei mit 3–10 Handwerks-Mandanten auf DATEV Lohn und Gehalt (mandantenseitig)
- Regional: Bayern, NRW, Baden-Württemberg (höchste DATEV-Dichte)
Validierungs-Fragen:
- Wie viele Stunden kostet Sie heute der Monats-Lohnabschluss (von Zeitstunden-Export bis Kanzlei-Bestätigung)?
- Welchen Anteil Ihrer monatlichen Kanzlei-Rückfragen betrifft falsche Lohnart-Zuordnungen?
- Nutzen Sie DATEV Unternehmen online für den Dateiversand, oder per E-Mail/USB-Stick?
- Wären Sie bereit, einen Bugfix-Release gegen 30 Tage Beta-Test zu tauschen?
18. Senior-Berater-Empfehlung
Abschnitt betitelt „18. Senior-Berater-Empfehlung“Build-Sequenz:
- Datenmodell (
datev_mandanten,datev_lohnart_mapping,datev_monatslaufe) + RLS + Multi-Tenant-Test. @werkszeit/datev-schluessel-NPM-Paket mit Jahrgang 2026 anlegen; LODAS-Schlüsselzahlen gegen offizielle Schnittstellenbeschreibung validieren.- LODAS-ASCII-Writer als Stream (
node:stream.Writable→ S3-Multipart), Unit-Tests auf byte-genauem Layout. - EXTF-Writer analog.
- Mapping-Editor-UI + Branchen-Defaults.
- Wizard (3 Schritte) + Dry-Run-Validator.
- Monats-Freigabe + Monatsschluss-Lock (DB-Trigger auf
zeitbuchungen). - Korrekturlauf-Logik.
- DATEV-Validator-CI-Job (offizieller Service + lokales Mock).
- DUO-API-Integration (V1).
Risiko-Reihenfolge (was zuerst absichern):
- Byte-Treue des LODAS-Writers. Wenn der falsch ist, ist alles falsch.
- Mandantennummer-Prüfziffer-Validierung (verhindert Fehlläufe zur Kanzlei).
- Monatsschluss-Lock (GoBD nicht verhandelbar).
Streich-Kandidaten bei Zeitnot:
- DUO-API → V1 statt MVP.
- Jahrgangs-Auto-Update → V1.5.
- Branchen-Defaults jenseits SHK + Maler → V1.
Stop-the-Bus-Triggers:
- LODAS-Writer produziert ein Byte Abweichung zur Referenz-Dump → sofortiger Stop, kein Release.
- DATEV-Validator meldet Fehler bei Fixture „happy-path“ → Merge blockiert, Tech-Lead eskaliert.
- SV-Nummer-Leak im Audit-Log oder Fehlertext → Sofort-Patch.
Was uns 2027 dankbar macht:
@werkszeit/datev-schluesselals separates Paket mit Jahrgangs-Sequenz — Jahreswechsel wird ein 30-Minuten-Ticket, kein Release-Event. Die Jahrgangsabhängigkeit haben 90 % der Mitbewerber fest eingebaut; unsere Architektur macht daraus ein Update-Problem statt eines Produktproblems.- Korrekturlauf als First-Class-Konzept (nicht nachträglicher Bugfix) — künftige Compliance-Fragen wie „Kann man bei SOKA-Stornierung nachweisen, was ursprünglich gemeldet wurde?“ beantworten wir per Link in die Hash-Chain.
- Der Mapping-Editor ist der Hebel für weitere Lohnsysteme: Sobald jemand eine Mapping-Engine zu SAP HCM fordert, ersetzen wir den DATEV-Writer durch einen SAP-Writer und behalten den gesamten Workflow (Vorschau, Korrektur, Audit).
Feinkonzept-Version 1.0 · Stand 2026-04-20 · Autor: Senior Consultant · Review: Tech-Lead + Buchhaltungs-PO
Für Entwickler — API-Endpoints14
| Methode | Pfad | Auth | Zweck |
|---|---|---|---|
| POST | /v1/kern/datev/extf-export/lohnzeiten | bearerAuth | EXTF-Buchungsstapel Lohnzeiten (CSV-Download) |
| POST | /v1/kern/datev/extf-export/rechnungen | bearerAuth | EXTF-Buchungsstapel Rechnungsausgang (CSV-Download) |
| GET | /v1/kern/datev/kontenrahmen-mappings | bearerAuth | Kontenrahmen-Sachkonto-Mappings auflisten |
| PUT | /v1/kern/datev/kontenrahmen-mappings/{id} | bearerAuth | Kontenrahmen-Sachkonto-Mapping ändern |
| GET | /v1/kern/datev/mandant | bearerAuth | DATEV-Mandantenstamm lesen |
| PUT | /v1/kern/datev/mandant | bearerAuth | DATEV-Mandantenstamm anlegen oder ändern |
| GET | /v1/kern/datev/mapping | bearerAuth | Lohnart-/Zeitart-Mappings auflisten |
| PUT | /v1/kern/datev/mapping | bearerAuth | Lohnart-/Zeitart-Mapping anlegen oder ändern |
| DELETE | /v1/kern/datev/mapping/{zeitart} | bearerAuth | Lohnart-/Zeitart-Mapping löschen |
| GET | /v1/kern/datev/monatslauf | bearerAuth | Lohn-Monatsläufe auflisten |
| POST | /v1/kern/datev/monatslauf | bearerAuth | Monatslauf-Entwurf anlegen |
| GET | /v1/kern/datev/monatslauf/{id} | bearerAuth | Monatslauf-Einzelsatz lesen |
| POST | /v1/kern/zeit/exports/datev-csv | bearerAuth | DATEV-CSV-Export (async, BullMQ-Job) |
| GET | /v1/kern/zeit/exports/datev-csv/{jobId} | bearerAuth | DATEV-CSV-Export-Job-Status (Polling) |