# Phase 1 Component Specification ## Dokumentstatus 1. Typ: `operational` 2. Zweck: verbindliche Umsetzungs-Spezifikation fuer Schritt 1 Komponenten 3. Normative Referenz: `/Users/mathias/Documents/Dokumente Chouchou/Codebases/erp_naurua/docs/CONCEPT.md` 4. Abgeleitete Referenz: `/Users/mathias/Documents/Dokumente Chouchou/Codebases/erp_naurua/docs/SCHEMA_PHASE1.sql` 5. Prozessreferenz: `/Users/mathias/Documents/Dokumente Chouchou/Codebases/erp_naurua/docs/PROCESS_PHASE1.md` 6. Implementierungsreferenz: `/Users/mathias/Documents/Dokumente Chouchou/Codebases/erp_naurua/db/migrations/` ## Scope Diese Spezifikation deckt alle Schritt-1-Komponenten ab: 1. Bestellerfassung 2. Kontakt- und Adressdaten 3. Artikel-Mapping und Stuecklisten 4. Lagerverwaltung mit Chargen, MHD, Zu-/Abgaengen 5. Chargenrueckverfolgung 6. Teil-/Vollstorno 7. Inbound/Outbound Webhooks 8. Audit und technische Guardrails ## Globale Invarianten 1. `sales_order.external_ref` ist eindeutig und dient als Upsert-Schluessel (Shop: `BestellungNr`, Direktverkauf: `DIR-...`). 2. Datensaetze werden nicht geloescht; Statusaenderungen und Audit-Trail werden verwendet. 3. Verkaufsbewegungen sind immer chargengebunden. 4. Negativbestand ist unzulaessig. 5. Pro Produkt existieren exakt eine `current`-Charge und eine `open`-Charge. 6. `open` darf nie fehlen. 7. Zahlungsstatus aus Shop wird intern auf `paid` normalisiert. 8. Direktverkaeufe haben `order_source = direct` und `external_ref` mit `DIR-`-Praefix. ## Komponente 1: Bestellerfassung ### Ziel Persistente Erfassung von Bestellungen aus Shop und Direktverkauf inkl. Positionen, Summen und Import-/Erfassungsdaten. ### Eingangsquelle 1. n8n Inbound Webhook mit Shop-JSON (`order_source = wix`) 2. Manuelle ERP-Erfassung fuer Direktverkauf (`order_source = direct`) ### Datenregeln 1. Upsert auf `sales_order.external_ref` fuer Shop-Bestellungen. 2. Direktbestellungen erhalten ERP-interne Nummern mit `DIR-`-Praefix. 3. `order_status` initial `imported`. 4. Summenfelder werden direkt gespeichert (`amount_net`, `amount_shipping`, `amount_tax`, `amount_discount`, `total_amount`). 5. `webhook_payload` wird fuer Shop-Rohdaten gespeichert (Nachvollziehbarkeit). 6. Fuer Direktverkauf darf `party_id` leer sein (Laufkundschaft). ### Fehlerverhalten 1. Bei fehlender `BestellungNr`: Import ablehnen, Audit-Log `import_rejected`. 2. Bei unbekanntem Artikelfehler: Bestellung speichern, Position mit Rohdaten speichern, Mapping-Luecke markieren. ### Akzeptanzkriterien 1. Wiederholter Import derselben `BestellungNr` erzeugt kein Duplikat. 2. Direktbestellungen sind ueber den `DIR-`-Praefix eindeutig erkennbar. 3. Positionsdaten bleiben stabil und auditierbar. ## Komponente 2: Kontakt- und Adressdaten ### Ziel Speicherung von Kundenkontakt, Lieferadresse und optionaler Rechnungsadresse. ### Datenregeln 1. Rechnungsadresse darf vollstaendig `NULL` sein. 2. Lieferadresse wird als eigener Datensatz gespeichert. 3. Land wird immer doppelt gespeichert: `country_name` + `country_iso2`. 4. Keine serverseitige Adressvalidierung in Phase 1. 5. Ausnahmefaelle bei Name/Firma werden unveraendert uebernommen. 6. Bei Direktverkauf ist keine Kontakt-/Adressanlage erforderlich. ### Akzeptanzkriterien 1. Bestellung kann ohne Rechnungsadresse gespeichert werden. 2. Liefer- und Rechnungsadresse sind getrennt auswertbar. ## Komponente 3: Artikel-Mapping und Stuecklisten ### Ziel Stabile Entkopplung von Shop-Artikeln und lagergefuehrten Produkten. ### Datenmodell 1. `sellable_item`: verkaufbarer Artikel (auch Bundles). 2. `external_item_alias`: Mapping Shop-Artikelnummer/Titel -> `sellable_item`. 3. `sellable_item_component`: Stueckliste `sellable_item` -> `product` mit Menge. ### Aufloesungsreihenfolge 1. Match ueber `external_article_number`. 2. Fallback ueber normalisierten Titel. 3. Wenn beides fehlschlaegt: Position als unmapped speichern und auditieren. ### Akzeptanzkriterien 1. Bundle-Artikel koennen auf mehrere Lagerprodukte aufgeloest werden. 2. Ohne Mapping bleibt Bestellung dennoch erfassbar. ## Komponente 4: Lagerverwaltung und Chargen ### Ziel Konsistente Bestandsfuehrung je Charge inklusive Auto-Wechsel. ### Statusmodell Charge 1. `open`: vorbereitete Charge 2. `current`: aktive Entnahmecharge 3. `closed`: abgeschlossene Charge ### Lebenszyklus 1. `open -> current -> closed` 2. Wenn `current` auf `qty_net <= 0` faellt: 1. alte `current` wird `closed` 2. vorhandene `open` wird `current` 3. neue `open` wird auto-angelegt ### Feldregeln 1. `lot_number` bei `open` darf leer sein. 2. `lot_number` fuer `current/closed` ist Pflicht. 3. Chargennummer ist pro Produkt eindeutig. 4. Chargensalden werden aus `stock_move` berechnet (`v_stock_lot_balance`). 5. Abverkaufprognose pro aktueller Charge wird im System gepflegt (`sellout_date`, `warning_state`). ### Korrekturregeln 1. Korrekturen erfolgen ueber `adjustment`-Bewegungen. 2. Keine direkten Netto-Setzungen als Betriebsprozess. ### Akzeptanzkriterien 1. Nach jeder Entnahme bleibt die Invariante `1x current + 1x open` erhalten. 2. Negativbestand wird technisch verhindert. 3. Warnstatus fuer UI ist ohne E-Mail nutzbar (`none`, `due_60d`, `due_now`). ## Komponente 5: Chargenrueckverfolgung ### Ziel Lueckenlose Rueckverfolgung Bestellung -> Position -> Produkt -> Charge -> Lagerbewegung. ### Datenregeln 1. Jede Entnahme schreibt `stock_move` (`move_type = out`) mit `lot_id`. 2. Pro Entnahme wird `sales_order_line_lot_allocation` geschrieben. 3. `allocation_status` in Phase 1 standardmaessig `allocated`. ### Akzeptanzkriterien 1. Fuer jede ausgelieferte Position ist die verwendete Charge abfragbar. 2. Rueckverfolgung funktioniert auch nach Teilstorno. ## Komponente 6: Storno (Teil/Voll) ### Ziel Revisionssicheres Storno ohne physisches Loeschen. ### Datenregeln 1. Teil- und Vollstorno sind erlaubt. 2. `sales_order_line.qty_cancelled` wird fortgeschrieben. 3. `line_status`: `allocated`, `partially_cancelled`, `cancelled`. 4. Bei Storno von bereits `allocated` Mengen erfolgt Gegenbuchung als `adjustment in` auf dieselbe Charge. 5. Bestellung bleibt erhalten; Statuswechsel statt Delete. ### Akzeptanzkriterien 1. Historische Ursprungs- und Korrekturbewegungen bleiben sichtbar. 2. Vollstorno setzt `sales_order.order_status = cancelled`. ## Komponente 7: Webhooks ### Inbound (n8n -> ERP) 1. Transport: JSON via HTTP. 2. Idempotenzschluessel: `BestellungNr`. 3. Verarbeitung: Upsert Bestellung, Kontakt, Positionen, Lagerabgang, Audit. 4. Quelle wird als `order_source = wix` gespeichert. ### Direkt (ERP intern) 1. Transport: manuelle Erfassung in ERP-Maske. 2. Nummernlogik: ERP erzeugt `external_ref` mit `DIR-`-Praefix. 3. Verarbeitung: Bestellung (optional ohne Kontakt), Positionen, Lagerabgang, Audit. ### Outbound (ERP -> n8n) 1. Transport: Queue-basierter POST ueber `outbound_webhook_event`. 2. Events Phase 1: 1. `order.imported` 2. `order.cancelled.partial` 3. `order.cancelled.full` 4. `lot.auto_switched` 3. Signatur: `X-ERP-Signature` (HMAC-SHA256). 4. Zustellung: Retry mit Backoff; final `dead_letter`. ### Akzeptanzkriterien 1. Event-Zustellung ist idempotent (`event_key` eindeutig). 2. Fehlgeschlagene Events sind operativ auffindbar. 3. Outbound-Payload enthaelt die Quelle (`order_source`), damit `wix` und `direct` getrennt auswertbar sind. ## Komponente 8: Audit und Betriebssicherheit ### Audit 1. Jede fachliche Aenderung schreibt `audit_log`. 2. Pflichtfelder: `entity_name`, `entity_id`, `action`, `changed_at`. 3. Vorher/Nachher-Daten werden als JSON gespeichert, wenn verfuegbar. ### Guardrails 1. Check-Constraints fuer Statuswerte. 2. Check-Constraints fuer Mengenbereiche. 3. Unique-Constraints fuer kritische Eindeutigkeiten. 4. Outbox-Statusmaschine fuer robuste externe Zustellung. ## Komponenten-Matrix 1. `Bestellerfassung` Zustandsquelle: `sales_order`, `sales_order_line` Hauptereignisse: `order.imported`, `order.cancelled.*` 2. `Kontakt/Adressen` Zustandsquelle: `party`, `contact`, `address` Hauptereignisse: `order.imported` 3. `Artikel-Mapping` Zustandsquelle: `sellable_item`, `external_item_alias`, `sellable_item_component` Hauptereignisse: `order.imported` 4. `Lagerverwaltung` Zustandsquelle: `stock_lot`, `stock_move`, `v_stock_lot_balance` Hauptereignisse: `order.imported`, `lot.auto_switched`, `order.cancelled.*` 5. `Rueckverfolgung` Zustandsquelle: `sales_order_line_lot_allocation` Hauptereignisse: alle Abgaenge und Stornos 6. `Outbound-Integration` Zustandsquelle: `outbound_webhook_event` Hauptereignisse: alle publizierten Domain-Events ## Nicht in Phase 1 1. Rechnungswesen, Buchungssaetze, OCR-Verarbeitung. 2. Automatisierte Preis-/Steuerneuberechnung. 3. Vollautomatische Chargennummerngenerierung nach Produktklasse. ## Change Governance 1. Konzeptaenderungen zuerst in `CONCEPT.md`. 2. Prozess- und Betriebsablauf in `PROCESS_PHASE1.md`. 3. Technische Ableitung in `SCHEMA_PHASE1.sql`. 4. Diese Spezifikation synchronisiert alle Komponenten auf Umsetzungsniveau.