Bestandskorrektur (GoBD-Verfahrensdokumentation)
Manuelle Minus- und Plus-Buchungen im WMS — Reason-Codes, Workflow, Aufbewahrung, Datenzugriff.
Teil des WMS Operations-Plugins
Dieses Modul ist kein Standard-Feature von flowagents. Es wird über das WMS Operations-Plugin bereitgestellt und muss von einem Admin im Marketplace aktiviert werden.
Diese Seite ist die Verfahrensdokumentation für das Feature „Bestandskorrektur" im WMS-Modul. Sie ist Bestandteil der GoBD-Pflichtdokumentation und muss bei einer Betriebsprüfung vorgelegt werden können.
1. Zweck und Anwendungsbereich
Die Bestandskorrektur erlaubt autorisierten Mitarbeitern, den Lagerbestand eines Artikels manuell zu reduzieren oder zu erhöhen, wenn der reale Bestand vom Systembestand abweicht. Typische Anlässe:
- Diebstahl (Laden- oder Lagerdiebstahl)
- Bruch / Beschädigung
- Inventur-Differenzen (Plus oder Minus)
- Vernichtung am Saison- oder Produktende
- Eigenverbrauch (Showroom, Foto-Shoot)
- Marketing-Samples / Presse / Influencer
- Kulanz-Ersatz ohne Retoure-Beleg
- Qualitäts-Mängel, die nach der Einlagerung erkannt wurden
- Bestand, der wieder aufgetaucht ist
Die Funktion ist nicht für regulären Wareneingang oder Standort-Umlagerungen vorgesehen — dafür existieren eigene Routen.
2. Reason-Code-Katalog
Jede Buchung muss einen Reason-Code haben. Reasons sind im System hartcodiert und versioniert.
| Code | Anzeige (DE) | Richtung | Typischer Anlass |
|---|---|---|---|
theft | Diebstahl | nur Minus | Ladendiebstahl, Lagerdiebstahl — Note Pflicht (z.B. Polizei-Aktenzeichen) |
damage | Bruch / Beschädigung | nur Minus | Fallschaden, Transportschaden im Haus |
inventory_diff_loss | Inventur-Differenz (Minus) | nur Minus | Jahres-/Cycle-Count mit Minus-Δ, Ursache unbekannt |
inventory_diff_gain | Inventur-Differenz (Plus) | nur Plus | Cycle-Count mit Plus-Δ |
expired | Saison-/Produkt-Ende, vernichtet | nur Minus | Vernichtung statt Abschrift |
internal_use | Eigenverbrauch / Showroom | nur Minus | Foto-Shoot, Schaufenster, Messe |
sample | Marketing / Sample / Presse | nur Minus | Influencer-Seeding, PR-Versand |
goodwill | Kulanz-Ersatz | nur Minus | Kundengeschenk bei Beschwerde, ohne Retoure |
quality_reject | Qualitäts-Mangel | nur Minus | latente Wareneingangs-Reklamation |
found | Bestand wiederaufgetaucht | nur Plus | Falsch-Einlagerung später korrekt gefunden |
correction_other | Sonstige Korrektur | beide | Freie Korrektur — Note Pflicht |
3. Pflichtfelder und Validierungsregeln
| Feld | Pflicht | Bemerkung |
|---|---|---|
direction | ✅ | out oder in |
location_id | ✅ | Lagerplatz, an dem die Korrektur erfolgt |
variant_id | ✅ | Artikel-Variante |
quantity | ✅ | Ganze Zahl, > 0 |
reason_code | ✅ | Predefined Enum (siehe Katalog) |
reason_note | ⚠️ | Pflicht für correction_other und theft (mind. 3 Zeichen). Bei allen anderen Codes optional. |
created_by | ✅ | UUID des eingeloggten Users (vom System gesetzt) |
created_at | ✅ | Server-Timestamp (UTC, vom System gesetzt) |
doc_no | ✅ | Fortlaufende Belegnummer ADJ-YYYY-NNNNNN, atomar via next_doc_no() (vom System) |
Weitere Validierungen:
inventory_diff_lossist nur in Richtungoutzulässig.inventory_diff_gainundfoundsind nur in Richtunginzulässig.- Bei Direction
out: Source-Lagerplatz muss genug Bestand haben (Pessimistic Lock, ADR-0022).
4. Rollen-/Berechtigungs-Matrix
Zugriff wird über die Permission wms-correct-stock gesteuert:
| Rolle | Standard-Zugriff |
|---|---|
super_admin | Voll |
admin | Voll |
member | Nein — Admin kann pro User extra_modules: ['wms-correct-stock'] setzen (/settings/company/team) |
sales_rep, employee | Nein |
Permission-Check passiert in jeder API-Route (apps/web/src/app/api/wms/adjustments/**) über canAccessModule(role, 'wms-correct-stock', extraModules).
5. Korrektur- und Storno-Workflow
┌────────────────────────────┐
│ Benutzer öffnet /warehouse/│
│ adjustments/new │
└──────────┬─────────────────┘
│
┌──────────▼─────────────────┐
│ Formular: Richtung, Site, │
│ Location, Artikel, Menge, │
│ Reason-Code, Notiz │
└──────────┬─────────────────┘
│
┌──────────▼─────────────────┐
│ Confirm-Dialog mit │
│ Übersicht aller Felder │
└──────────┬─────────────────┘
│
┌──────────▼─────────────────┐
│ POST /api/wms/adjustments │
│ → bookMovement (Ledger) │
│ → next_doc_no (Beleg-Nr.) │
│ → INSERT stock_adjustments│
└──────────┬─────────────────┘
│
┌──────────▼─────────────────┐
│ Success-Card mit Belegnr. │
└────────────────────────────┘Storno (kein Edit, kein Delete):
- Original-Buchung bleibt unverändert (Append-only-Trigger blockt UPDATE/DELETE).
- User öffnet Detail-Seite → klickt "Stornieren" → Pflicht-Begründung (≥ 3 Zeichen).
- System legt eine neue Adjustment-Zeile an mit:
- invertierter
direction - gleicher
quantity/location_id/variant_id reason_code = 'correction_other'reverses_id→ ID der Original-Buchung- eigener neuer
doc_no
- invertierter
- Die Bestandsbewegung wird symmetrisch über das normale Movement-Ledger gebucht.
Eine Buchung kann nur einmal storniert werden; ein Storno selbst kann nicht erneut storniert werden.
6. Datenfelder pro Buchung (für Prüfer)
Tabelle stock_adjustments:
| Spalte | Typ | Beschreibung |
|---|---|---|
id | UUID | Primärschlüssel |
tenant_id | UUID | Mandant (Multi-Tenancy) |
doc_no | text | Belegnummer (z.B. ADJ-2026-000123) |
direction | enum | out (Minus) oder in (Plus) |
site_id | UUID | Standort |
location_id | UUID | Lagerplatz innerhalb des Standorts |
variant_id | UUID | Artikel-Variante |
quantity | integer | Menge (immer positiv, Vorzeichen kommt aus direction) |
reason_code | enum | Predefined Reason (siehe Katalog) |
reason_note | text? | Optionaler Freitext; Pflicht bei correction_other und theft |
movement_id | UUID | Verweis auf die zugehörige Zeile in stock_movements |
reverses_id | UUID? | Bei Storno: Verweis auf Original-Buchung |
created_by | UUID | Verursachender User |
created_at | timestamptz | Server-Timestamp UTC |
7. Aufbewahrung
- Die Tabelle
stock_adjustmentsist append-only: UPDATE und DELETE werden durch einen Datenbank-Trigger (stock_adjustments_no_update,stock_adjustments_no_delete) blockiert. - Die zugehörige Bewegung in
stock_movementsist ebenfalls append-only (stock_movements_no_update,stock_movements_no_delete). - Die Daten werden mindestens 8 Jahre aufbewahrt (§ 147 AO, Buchungsbelege seit 2025). Ein automatisierter Cleanup ist derzeit nicht eingerichtet; sollte er später per
pg_cronergänzt werden, gilt diese Frist als Mindestalter.
8. Datenzugriff Z3 (Betriebsprüfer)
Für Z3-Prüfungen kann der CSV-Export verwendet werden:
GET /api/wms/adjustments/export?from_date=2026-01-01&to_date=2026-12-31Response: text/csv; charset=utf-8 mit UTF-8 BOM (Excel-kompatibel), Spalten in dieser Reihenfolge:
doc_no, created_at, direction, reason_code, reason_note, site_id, location_id, variant_id, quantity, movement_id, reverses_id, created_by
Der Export ist nur für Benutzer mit Permission wms-correct-stock zugänglich und filtert serverseitig nach tenant_id.
9. Änderungshistorie der Doku
| Datum | Änderung | Autor |
|---|---|---|
| 2026-05-22 | Erstfassung (Feature-Release) | flowagents |