Roadmap & 4-Wochen-Umsetzungsplan

Ziel: Go-Live der vollständigen Plattform in 4 Wochen (Start Mo 30.06.2026 → Go-Live Fr 25.07.2026). Aggressiv, aber machbar — KI-gestützte Umsetzung direkt aus dem entscheidungs-vollständigen Pflichtenheft, parallele Arbeitsströme und tägliche Preview-Deploys. Die Detail-Phasen P0–P4 (unten) bleiben gültig und werden auf die vier Wochen verdichtet/parallelisiert abgebildet.


4-Wochen-Umsetzungsplan bis Go-Live

Diagramm wird geladen …

Woche für Woche

WocheFokusLiefergegenstand (Module)
W1 · 30.06–04.07Fundament + StammdatenSupabase + Auth (Entra/Supabase) + RLS + alle 48 Tabellen migriert, i18n, Audit-Log, Design-System, CI/Deploy · Modul 1 CRM · Modul 3 Produkte/Preise
W2 · 07.07–11.07Kommerziell + LogistikModul 4 Offerten (PDF/WhatsApp, Code-Rabatt) · Modul 5 Logistik (Boxen UUID+QR, 10 Tracking-Schritte, Container, Depot, Fahrer-App)
W3 · 14.07–18.07Finanzen + AutomatisierungModul 6 Finanzen (movements-Ledger, Auto-Posting, MWST-befreit, Abschluss) + Mehrwährung CHF/DOP + Revolut · Modul 7 Affiliate · Modul 2 WhatsApp-API + OCR (self-hosted)
W4 · 21.07–25.07Härtung + Migration + Go-LiveSecurity/RLS-Review, E2E-Tests, Audit-Restpunkte · Datenmigration Alt-ERP/Excel + Cutover · Schulung/Abnahme · 🚀 Go-Live 25.07

Parallel-Track (extern — blockiert Go-Live nicht)

Läuft neben dem Bau und kann um/nach dem Go-Live abschließen:

  • Recht: Datenschutzerklärung anwaltlich prüfen · DPAs zeichnen (Supabase/Vercel/Resend/WhatsApp/Revolut) · Supabase-Region = EU fixieren.
  • GS1-Mitgliedschaft + GCP → SSCC danach scharfschaltbar (Caja ist SSCC-ready, kein Umbau).

Was 4 Wochen tragfähig macht

  • Spec ist entscheidungs-vollständig — keine offenen Architektur-/Geschäftsentscheide mehr im kritischen Pfad.
  • Schema + Module direkt aus dem Pflichtenheft generierbar (48 Tabellen, RLS-Matrix, Auto-Posting-Funktionen sind spezifiziert).
  • Parallele Ströme (Daten-Layer ‖ UI ‖ Migration) statt strenger Phasen-Sequenz.
  • Tägliche Preview-Deploys (Supabase-Branch je Vercel-Preview) → kontinuierliche Abnahme statt Big-Bang am Ende.

Top-Risiken (früh angehen)

  • Datenmigration Alt-ERP/Excel (Datenqualität, Mapping) → ab W1 parallel vorbereiten, nicht erst W4.
  • OCR self-hosted (Proxmox) Setup + Revolut-API-Onboarding → in W3, mit Fallback (manueller KYC-Review / CSV-Statement-Import), falls Provider-Onboarding länger dauert.
  • WhatsApp-Business-API-Freigabe (Meta Templates/Opt-in) → Antrag in W1 stellen (Vorlaufzeit).

Übersicht

PhaseNameKerngewinn→ im 4-Wochen-Plan
P0FundamentSicheres, mehrsprachiges Grundgerüst; kein Fach-Feature ohne diese BasisW1
P1CRM + Finanzen-KernErster produktiver Ersatz des Excel-ERP; Ledger läuft, Kunden sind drinW1 (CRM) + W3 (Finanzen)
P2Produkte, Preise, Offerten, Affiliate-CodesVollständiger kommerzieller Zyklus: Preisliste → Offerte → Auftrag → ProvisionW1 (Produkte) + W2 (Offerten) + W3 (Affiliate)
P3Logistik: Boxen, Tracking, ContainerOperativer Kernfluss sichtbar; Box-QR, 10 Schritte, Container-Board, Depot-LifecycleW2
P4WhatsApp + OCR + DedupAutomatisierter Lead-Intake; Ausweis-Scan → Kontakt; Duplikat-BereinigungW1 (Dedup) + W3 (WhatsApp/OCR)

Die klassische sequentielle Schätzung (~18–22 Wochen) wird im 4-Wochen-Plan oben durch Parallelisierung + KI-gestützte Generierung aus der Spec verdichtet. Die Phasen-Detailbeschreibungen unten bleiben unverändert gültig — sie sind die fachliche Aufschlüsselung dessen, was in den vier Wochen gebaut wird.


P0 — Fundament

Ziele

Alle technischen Querschnittsthemen sind produktionsreif, bevor auch nur eine einzige Zeile Fach-Code geschrieben wird. Das verhindert spätere Sicherheits-Nachbesserungen und macht i18n, Audit und RLS zur Selbstverständlichkeit im gesamten Projekt.

Enthaltene Tabellen / Objekte

Auth & Identität:

  • roles (Seed: ADMIN, BUCHHALTUNG, OPERATIONS, FAHRER, AFFILIATE, READONLY)
  • app_users (Trigger handle_new_user() auf auth.users)
  • user_roles (n:m)
  • affiliate_users (1:1-Bridge, Struktur bereits, Daten kommen erst in P2)
  • RLS-Hilfsfunktionen: has_role(), is_internal(), current_affiliate_id()

i18n:

  • locale_strings (Namespace/Key/Locale)
  • Seed-Skript aus GLOSSAR-ERP_DE-ES-EN.csv (alle drei Locales, alle Namespaces)
  • label_de/es/en-Spalten an allen Lookup-Tabellen

Geteilte Fach-Lookups (Heimat P0, konsumiert ab P1):

  • movement_types (12 Codes mit Verhaltens-Flags, Seed)
  • payment_methods (5 Codes inkl. channel-Klassifikation, Seed)
  • vat_rates (CH-Sätze, active=false, schema-ready)

Audit & Periodensperre:

  • audit_log (append-only, Bigint-PK, Rules + Grant-Entzug)
  • Trigger-Funktion fn_audit() (generisch, wird an Fach-Tabellen gehängt)
  • monthly_closings (Struktur; Abschlüsse kommen erst ab P1)
  • fn_guard_closed_period() (Guard-Funktion)

Storage:

  • storage_objects (Metadaten-Tabelle; physische Buckets kyc, documents, receipts, public-assets in Supabase Storage mit RLS)

Notifications (Outbox-Struktur):

  • notifications (Tabelle + dedupe_key-Unique)
  • Erste Templates: AUTH_MAGIC_LINK (Supabase-SMTP)

Plattform-Screens:

  • Login / Magic-Link + OTP-Fallback (dreisprachig, ES-Default)
  • Team & Zugriff — ADMIN (Nutzer/Rollen verwalten, Affiliate-Verknüpfung)
  • Profil & Spracheinstellungen
  • Audit-Journal (read-only, Desktop Tabelle / Handy Timeline)
  • Dokument-Browser (Grundgerüst, Buckets navigierbar)

Infrastruktur:

  • Next.js App Router + TypeScript + Tailwind 4 + shadcn/ui (Atlas-Stack)
  • Supabase-Projekt (Region eu-central-1), Migrationen via supabase/migrations/
  • Vercel-Deployment, RESEND_API_KEY/RESEND_FROM in Vercel-Env
  • Design-Tokens (Light/Dark, CSS-Variablen)
  • Bottom-Tab-Bar + Drawer (Handy) / Sidebar (Desktop) — leere Navigationsstruktur
  • Command-Palette (⌘K) — Grundgerüst
  • pref_lang-Cookie + i18n-Resolver (RSC-Layout)
  • PWA-Manifest + Service-Worker-Grundgerüst (Offline-Shell)
  • Vercel Web Analytics aktiviert

Definition of Done P0

  • Alle Tabellen migriert, alle Constraints aktiv
  • Magic-Link-Login funktioniert für alle vier Team-Mitglieder
  • ADMIN-Rolle kann anderen Nutzern Rollen zuweisen
  • Sprachumschalter (DE/ES/EN) funktioniert, preferred_locale wird persistiert
  • Audit-Journal zeigt action=login nach erfolgreichem Login
  • audit_log: UPDATE/DELETE schlagen auch für service_role fehl (Rules-Test)
  • Alle RLS-Policies auf Plattform-Tabellen aktiv; ohne Rolle kein Datenzugriff
  • Vercel-Deployment grün; eu-central-1-Region bestätigt

Abhängigkeiten P0

Keine — P0 ist die Wurzel. Alles andere hängt davon ab.

Aufwandsklasse

XL — komplex wegen Auth-Trigger, RLS-Architektur, i18n-Seed, Audit-Unveränderbarkeit und PWA-Grundgerüst. Fehler hier kosten in späteren Phasen das Dreifache.


P1 — CRM + Finanzen-Kern

Ziele

Das Excel-ERP (Erfassung_Digitar) wird durch das movements-Ledger abgelöst. Alle Bestands-Buchungen werden migriert. Das Team kann ab P1-Ende ohne Excel arbeiten: Kontakte anlegen, Buchungen erfassen, Kasse/Dashboard einsehen, Monatsabschluss vorbereiten.

Der Website-Lead-Intake (POST /api/send-contact) wird direkt in die contacts-Tabelle geleitet — erstes produktives Ende-zu-Ende-Feature.

Enthaltene Tabellen

CRM (Modul 1):

  • contacts (Golden Record, inkl. i18n preferred_lang, lead_source, KYC-Felder als Spalten — OCR-Befüllung kommt erst P4)
  • contact_roles (Bridge customer/lead/supplier/affiliate/recipient_dr)
  • contact_role_labels (i18n-Seed)
  • recipients (Empfänger DR — Struktur; produktive Nutzung ab P3 beim Auftrag)
  • contact_merge_log (append-only, Merge-Workflow kommt in P4)

Finanzen (Modul 6):

  • movements (Kern-Ledger, inkl. source_type/source_id-Unique, voided_at)
  • payment_links (explizite Zahlungsverknüpfung)
  • monthly_closings
  • Views: v_movements, v_kasse, v_debitoren, v_kreditoren, v_anzahlungen, v_dashboard, v_monatskontrolle
  • fn_audit()-Trigger auf movements und monthly_closings
  • fn_guard_closed_period()-Trigger auf movements

Screens CRM:

  • Kontaktliste (adaptiv: Karten Handy / Tabelle Desktop, Suche, Rollen-Filter)
  • Kontaktdetail (Tabs: Info / Empfänger / Offerten / Aufträge / Finanzen / Dokumente)
  • Kontakt anlegen / bearbeiten (Bottom-Sheet-Formular)
  • Lead-Schnellerfassung WhatsApp (minimales Formular, Duplikat-Check live)
  • Empfänger anlegen / bearbeiten (Grundgerüst; OCR-Befüllung folgt P4)

Screens Finanzen:

  • Finanz-Dashboard (KPI-Kacheln aus v_dashboard, Monatsfilter)
  • Kasse / Cashflow (v_kasse, chronologisches Journal, laufender Saldo)
  • Schnellerfassung Quick-Entry (Bottom-Sheet: Vorgang → Zahlweise → Betrag → Datum → Partei → Notiz)
  • Debitoren / Kreditoren (v_debitoren / v_kreditoren, Ampeln, Swipe „Zahlung erfassen")
  • Anzahlungen / Depot (v_anzahlungen, Grundgerüst; Depot-Lifecycle folgt P3)
  • Monatsabschluss (v_monatskontrolle, Abschluss-Button)
  • Treuhänder-Export (CSV/Excel/PDF-Dialog, Edge-Function)
  • Notifications-Protokoll (Outbox-Ansicht für interne Nutzer)

Migration (Excel → Caja, läuft parallel zu P1-Entwicklung)

  • Migrations-Skript liest Erfassung_Digitar (CSV-Export) und bulk-inserted in movements mit source_type='import'
  • period_key aus entry_date berechnet (keine String-Parsung mehr)
  • payment_methods.channel aus Zahlweise-Mapping (ersetzt Excel-classifyPaymentChannel)
  • Anfangssalden (Saldo inicial caja/banco) als monthly_closings-Opening der ältesten Periode oder Settings-Wert (🔲 zu bestätigen)
  • Test: v_dashboard-Werte gegen Excel-Summen validieren (Differenz < CHF 1.00)

Website-Lead-Wire-in

  • /api/send-contact (bereits produktiv) erhält zusätzlichen supabase-Client-Aufruf: Fuzzy-Check auf contacts (E.164-Normalisierung + Name-Match), Insert oder Update, lead_source='website_form'
  • Notification an Mariela/Marcel (Kanal email, Template LEAD_INTAKE_INTERNAL — neu)
  • Honeypot-Prüfung bleibt erhalten; Resend-E-Mail an Kunden bleibt erhalten

Definition of Done P1

  • Alle Excel-Bewegungen migriert; v_dashboard-Summen validiert
  • Website-Formular speist contacts live (Test: Testsubmission erscheint in Caja)
  • Quick-Entry: manuelle Buchung erfassen, Kasse-Saldo aktualisiert sich sofort
  • Zahlung gegen offene INVOICE: payment_links-Eintrag, Status wechselt zu PAID
  • Monatsabschluss: Periode schliessen, anschliessender Insert in geschlossener Periode schlägt fehl
  • Audit-Journal zeigt jede movements-Mutation mit old_data/new_data
  • RLS: AFFILIATE-Session sieht keine movements-Zeilen; FAHRER sieht nur eigene Logistik-Quellen (noch leer)
  • Handy (375px): Karten-Layout überall, kein Horizontal-Scroll, alle Targets ≥ 44px

Abhängigkeiten P1

  • Voraussetzung: P0 vollständig (Auth, Rollen, RLS-Helfer, movement_types, payment_methods, Audit-Framework)
  • contacts ist Voraussetzung für alle weiteren Module (P2–P4 referenzieren contacts.id)
  • movements ist Voraussetzung für Auto-Posting aus P2 (Offerten→Rechnungen) und P3 (Depot-Zahlungen)

Aufwandsklasse

XL — grösster Einzel-Aufwand der Roadmap wegen Excel-Migrations-Skript (Daten-Validierung aufwändig), der v_movements-View-Logik (1:1-Nachbau der Excel-Routing-Formeln H..N) und dem Ende-zu-Ende-Lead-Intake.


P2 — Produkte, Preise, Offerten, Affiliate-Codes

Ziele

Der vollständige kommerzielle Zyklus läuft: Preisliste konfiguriert → Offerte erstellt aus Katalog → PDF erzeugt → per WhatsApp/E-Mail versendet → akzeptiert → Auftrag + Rechnung angelegt → Affiliate-Provision vorgemerkt. Affiliate-Codes sind aktiv und werden durch den Offerten-Flow hindurchgereicht.

Enthaltene Tabellen

Produkte & Preise (Modul 3):

  • box_products (Seed: 9 Produkte + SRV_ABHOLUNG, label_de/es/en)
  • zones (Seed: erste Zonen-Taxonomie DR, 🔲 finale Liste aus Betrieb)
  • price_lists (effective-dated, is_default)
  • price_list_items (Preis je Produkt × Zone; unveränderlich nach Aktivierung)
  • product_depot_rates (Depot-Satz je Produkt × Preisliste)
  • View v_current_prices
  • Preis-Resolver (Edge-Function oder Server-Action)

Offerten (Modul 4):

  • quotes (inkl. quote_status-Enum, Betragsfelder als Snapshots, referral_code_id)
  • quote_lines (Produkt-Snapshot, price_list_entry_id, Rabatt-Felder)
  • Sequenz quote_number_seq
  • Cron-Job: täglicher Expired-Lauf (valid_until < today AND status='SENT')
  • PDF-Generierung (Server-Action, Bibliothek 🔲 zu bestätigen)
  • Notifications: QUOTE_SENT (E-Mail via Resend + WhatsApp-Deep-Link)

Affiliate (Modul 7 — Basis):

  • affiliates (Stammdaten, FK auf contacts, affiliate_status)
  • referral_codes (Code, Rabatt-Regel, Provisions-Regel, Gültigkeitszeitraum)
  • commission_entries (Entstehung pending bei Offerte-Konversion; Freigabe approved beim Tracking-DELIVERED, #19/F-13 — nicht mehr bei invoices.status → PAID)
  • commission_payouts (gebündelte Auszahlung — Abrechnung folgt P2b oder als eigenes Increment)
  • affiliate_users (Verknüpfung Login ↔ Affiliate-Konto, Struktur war P0, Daten jetzt)
  • RLS: Affiliate sieht nur eigene quotes, eigene commission_entries

Screens Produkte & Preise:

  • Produktkatalog-Übersicht (Karten/Grid, Kategorie-Filter)
  • Produktdetail (Tabs: Info / Preise / Depot / Historie)
  • Preislisten-Verwaltung (Liste, Draft/Aktiv/Abgelaufen, Neu-Formular)
  • Preislisten-Items befüllen (Raster Produkt × Zone; CSV-Import Drag & Drop)
  • Preis-Resolver Testscreen (Admin, Desktop/Tablet)

Screens Offerten:

  • Offerten-Liste (adaptiv: Karten Handy / Tabelle Desktop, Status-Filter)
  • Offerte erstellen/bearbeiten (Wizard-Stepper Handy / Einseitiges Formular Tablet+)
  • Offerten-Detail (Header + Aktionsleiste, Versand-History, Links zu Auftrag/Rechnung)
  • Versand-Dialog (Bottom-Sheet Handy / Modal Tablet+, Kanal-Toggle, Vorschau)
  • PDF-Vorschau (signierte URL, 1h TTL)

Screens Affiliate (intern):

  • Affiliate-Liste (Karten mit Status-Badge)
  • Affiliate-Detail (Stammdaten, Codes, Provisions-Historie)
  • Referral-Code-Verwaltung (Anlegen, Aktivieren, Deaktivieren)
  • Provisions-Übersicht / Abrechnungs-Vorbereitung

Auto-Posting P2

Bei quote.CONVERTED → Server-Action (transaktional):

  1. orders.INSERT (quote_id, customer_id, referral_code_id, affiliate_id, status='OPEN')
  2. invoices.INSERT → Auto-Posting: movements Upsert (source_type='invoice_issued', movement_type='INVOICE', total_chf=grand_total)
  3. Bei affiliate_id IS NOT NULL: commission_entries.INSERT (status='pending', #19 — Entstehung hier bei Konversion). Freigabe (approved) erfolgt später beim Tracking-DELIVERED der Sendung (P3), nicht bei invoices → PAID (Modul 7 §4.5).

Definition of Done P2

  • Preis-Resolver: deterministisch für alle Produkt-/Zonen-Kombinationen; Test AMBIGUOUS_PRICE und PRICE_NOT_FOUND
  • Offerte erstellen → PDF generiert → E-Mail via Resend versendet (Template dreisprachig)
  • Offerte akzeptieren → orders-Eintrag + movements-INVOICE-Eintrag automatisch vorhanden
  • Affiliate-Code auf Offerte → commission_entries-Eintrag (pending) bei Offerte-Konversion (#19)
  • Affiliate-Login: sieht nur eigene Offerten und eigene Provisionen (RLS-Test)
  • Preislisten-Item unveränderlich nach Aktivierung (UI + DB-Constraint)
  • Cron-Job: Expired-Offerten werden täglich gesetzt

Abhängigkeiten P2

  • Voraussetzung P0: Auth, Rollen, RLS-Helfer, audit_log, Storage-Buckets
  • Voraussetzung P1: contacts (Offerte braucht contact_id), movements (Auto-Posting)
  • box_products aus P2 wird von P3 (Boxen-Materialisierung) und P4 (OCR-Empfänger) referenziert
  • orders aus P2 ist Eingangs-Punkt für P3 (Logistik)
  • referral_codes aus P2 werden in P3 (orders.referral_code_id) durchgereicht

Aufwandsklasse

L — Preis-Resolver und PDF-Generierung sind die technischen Knackpunkte; der Rest sind gut definierte CRUD-Flows.


P3 — Logistik: Boxen, Tracking, Container

Ziele

Der operative Kern von Dominicano Express läuft in Caja: aus einem Auftrag (P2) entstehen physische Boxen mit UUID/QR-Code, die entlang der 10 Tracking-Schritte verfolgt werden. Arkys kann am Depot Boxen scannen und Status setzen — auch offline. Container werden geplant und verwaltet. Das Depot-Lifecycle der Fässer ist vollständig abgebildet inkl. Rückzahlung/Verfall als Auto-Posting ins Ledger. Das Tracking-DELIVERED löst die Affiliate-Provisions-Freigabe aus (commission_entries.status pending → approved per DB-Trigger, #19/F-13) — die Provision selbst entsteht bereits bei der Offerte-Konversion (P2).

Enthaltene Tabellen

Logistik (Modul 5):

  • Lookups: tracking_statuses (9 Codes + Phase/Sort), tracking_phases (CH/OCEAN/RD), box_conditions, shipment_statuses, container_statuses, order_statuses, deposit_refund_kinds
  • containers (Planung, next_departure, Kapazität, BL-Nummer)
  • shipments (logistisches Bündel; FK auf orders, recipients, containers)
  • boxes (UUID = QR-Inhalt, box_no, current_status, is_returnable)
  • tracking_events (append-only, RLS kein UPDATE/DELETE)
  • fn_record_tracking_event() (SECURITY DEFINER, atomar Event + Statuswechsel + Idempotenz via client_event_id)
  • deposit_orders (ALTER: box_id-Spalte hinzufügen)
  • deposit_payments (Zahlungen gegen Depot-Auftrag)
  • deposit_refunds + deposit_refund_kinds (Rückzahlung / Verfall / Teilrückerstattung)
  • Views: v_box_tracking, v_shipment_progress, v_container_load, v_open_box_deposits
  • fn_bulk_track() (Bulk-Tracking-Event für Container-Verladung)
  • fn_audit()-Trigger auf boxes, shipments, containers, deposit_orders, deposit_refunds, tracking_events

Screens Logistik:

  • Scan-Screen (Camera-First, Vollbild-QR, Bottom-Sheet mit nächstem Schritt, Offline-Queue)
  • Boxen-Liste (adaptiv: Karten Handy / TanStack-Table Desktop, Status-Filter-Chips)
  • Box-Detail / Tracking-Timeline (vertikale Timeline, QR-Anzeige, Storno-Events)
  • Container-Board (Karten je Status, Progress-Bar, próxima salida)
  • Container-Detail + Bulk-Aktionen (Multi-Select, Bulk-Status-Wechsel)
  • Auftrag-Detail Logistik-Sicht (Boxen anlegen, Sendungen bilden, Empfänger zuordnen)
  • Depot-Lifecycle-Screen (v_open_box_deposits, Swipe „zurück" / „verfallen")

Offline-PWA:

  • IndexedDB-Queue für Tracking-Events (jedes Event mit client_event_id)
  • Sync-Logik beim Reconnect (Idempotenz via Unique-Index)
  • Offline-Status-Badge in der Navigationsleiste

Auto-Posting P3

Operatives Eventmovement_typesource_type
deposit_payment erfasstDEPOSIT_CASH (Eingang, Kanal nach payment_methods.channel)deposit_payment
deposit_refund RETURNED/PARTIALEXPENSE (Ausgang, Depot-Rückzahlung)deposit_refund
deposit_refund FORFEITEDINCOME (Ertragsbuchung, 🔲)deposit_refund

Notification bei box.status → DELIVERED: SHIPMENT_STATUS-Template an Kunde + Empfänger-DR (WhatsApp-Deep-Link / E-Mail).

Affiliate-Provision (#19): Entstehung bereits bei Offerte-Konversion (pending, P2); Freigabe (status → 'approved') automatisch per DB-Trigger beim Tracking-DELIVERED der Sendung (auf tracking_events/Sendungsabschluss) — DELIVERED ist der Auslöser der Fälligkeit, nicht mehr invoices → PAID (F-13).

Definition of Done P3

  • Auftrag (aus P2) → Boxen materialisieren → UUID/QR-PDF drucken
  • Box-QR scannen am Handy → Status-Wechsel in unter 5 Sekunden
  • Offline-Scan: Event in IndexedDB; nach Reconnect synct er idempotent (kein Duplikat)
  • Container-Board: Box verladen → CONTAINER_LOADED-Bulk-Event für alle Boxen
  • DELIVERED-Event → Kunden-Notification ausgelöst (Outbox-Eintrag vorhanden)
  • DELIVERED-Event → commission_entries.status der vermittelten Sendung wechselt pending → approved (DB-Trigger, #19)
  • Depot-Rückzahlung → movements-EXPENSE-Eintrag automatisch (Test: source_id eindeutig)
  • FAHRER-Rolle: kann nur tracking_events INSERT + SELECT, kein Finanz-Zugriff (RLS-Test)
  • Tracking-Events: UPDATE/DELETE schlägt für alle Rollen fehl

Abhängigkeiten P3

  • Voraussetzung P0: Auth, RLS, Audit, Storage (Box-Fotos)
  • Voraussetzung P1: contacts (Kunden, Fahrer-Actor), movements/Auto-Posting-Kontrakt
  • Voraussetzung P2: orders (Eingangs-Punkt), box_products (Katalog), referral_codes + commission_entries (pending, deren Freigabe der DELIVERED-Trigger in P3 auslöst — #19)
  • recipients (P1-Struktur) wird hier produktiv befüllt

Aufwandsklasse

XLfn_record_tracking_event() (Atomar-Transaktion + Idempotenz), Offline-IndexedDB-Queue, Container-Bulk-Aktionen und Depot-Auto-Posting sind komplex. Kamera-First auf Mittelklasse-Android muss Performance-Budget einhalten.


P4 — WhatsApp + OCR + Dedup

Ziele

Der Lead-Intake wird vollständig automatisiert: WhatsApp-Medien-Nachrichten landen in einer Eingangs-Queue, ein OCR-/Vision-Dienst extrahiert Ausweis-Daten und befüllt den Kontaktsatz vor. Manuelle Bestätigung bleibt Pflicht (revDSG). Die Duplikat-Bereinigung (Golden-Record-Workflow) wird produktiv — alle bisher angesammelten Duplikate werden aufgeräumt.

Enthaltene Tabellen

WhatsApp + OCR (Modul 2):

  • whatsapp_inbound (Eingangs-Queue: Sender-Phone, Media-URL/Path, Timestamp, Verarbeitungs-Status)
  • kyc_scans (Scan-Versuch: doc_type, extracted_fields JSONB, raw_image_path, ocr_provider, ocr_confidence, review_status)
  • kyc_field_corrections (append-only Audit-Journal manueller Korrekturen)
  • Enums: kyc_doc_type, kyc_ocr_provider, kyc_review_status
  • fn_audit()-Trigger auf kyc_scans
  • Storage-Bucket kyc: Scan-Upload via signierte URL (Edge-Function), RLS strikt (is_sensitive=true)
  • Webhook-Receiver (Edge-Function): eingehende WhatsApp-Medien → whatsapp_inbound-Insert → OCR-Job
  • OCR-Edge-Function: Vision-API-Call (Anbieter 🔲) → kyc_scans-Insert mit extracted_fields
  • Manuelle Review-UI → OCR-Felder bestätigen → contacts-Update

CRM Dedup (Modul 1 — Ergänzung zu P1):

  • contact_duplicates (Fuzzy-Score-Paare, resolution-Enum)
  • Duplikat-Erkennungs-Job (Edge-Function / pg_cron: pg_trgm-Trigram-Score auf Name/Telefon/E-Mail, 🔲 Algorithmus bestätigen)
  • Merge-Server-Action (transaktional: Golden Record, FKs umbiegen, contact_merge_log, contact_duplicates.resolution='merged')

Screens OCR / KYC:

  • Ausweis-Scan-Screen (Camera-First: Kamera-Auslöser → Upload → OCR-Status-Spinner → Review-Formular)
  • KYC-Review-Queue (Pendig-Scans, je Scan extrahierte Felder vs. Formular-Felder, Bestätigen/Ablehnen)
  • Scan-Historie pro Kontakt (Tab „Dokumente" im Kontaktdetail, P1-Grundgerüst wird befüllt)

Screens Dedup:

  • Duplikat-Review-Queue (Liste Duplikat-Paare sortiert nach Score)
  • Merge-Screen (Spalten A vs. B, Radiogruppe je Feld, Bestätigung → Transaktion)
  • Nicht-Duplikat-Markierung (Swipe/Button)

Definition of Done P4

  • WhatsApp-Bild-Eingang → whatsapp_inbound-Queue → OCR → kyc_scans (End-to-End-Test mit echter Cédula)
  • OCR-Felder im Review-Formular bestätigen → contacts.id_number, id_type aktualisiert, audit_log-Eintrag
  • KYC-Scan-Bild: nur abrufbar mit signierter URL, kein öffentlicher Zugriff (Storage-Test)
  • Duplikat-Queue zeigt Paare mit Score ≥ 0.75; Merge läuft transaktional (alle FKs umgebogen)
  • Nicht-Duplikat-Markierung: Paar verschwindet aus Queue
  • DSG-Löschung: Scan-Datei aus Storage löschbar, Audit-Eintrag bleibt (Lifecycle-Job-Grundgerüst)

Abhängigkeiten P4

  • Voraussetzung P0: Auth, Storage-Buckets (kyc), RLS, Audit
  • Voraussetzung P1: contacts (Ziel-Entität), contact_merge_log (Struktur bereits vorhanden)
  • P4 ist bewusst am Ende: die Fuzzy-Dedup-Qualität steigt, je mehr Kontakte ab P1 akkumuliert sind
  • OCR-Anbieter (🔲 Claude Vision / Google Vision / Azure) muss vor Implementierung entschieden werden

Aufwandsklasse

L — OCR-Integration und Webhook-Receiver sind einmalig komplex; die Merge-Transaktion ist heikel (FK-Kaskade über alle Module). Danach ist die Duplikat-UI geradlinig.


Phasen-Abhängigkeitsdiagramm

P0 Fundament
│  Auth, Rollen, RLS-Helfer, i18n, Audit, Storage, movement_types, payment_methods
│
└─► P1 CRM + Finanzen-Kern
    │  contacts, movements, v_movements, v_dashboard, Excel-Migration, Lead-Wire-in
    │
    └─► P2 Produkte + Preise + Offerten + Affiliate-Codes
        │  box_products, price_lists, quotes, orders, invoice→movements, referral_codes
        │
        └─► P3 Logistik: Boxen, Tracking, Container
            │  boxes (UUID/QR), tracking_events, containers, deposit_lifecycle→movements
            │
            └─► P4 WhatsApp + OCR + Dedup
                   whatsapp_inbound, kyc_scans, contact_duplicates, merge-workflow

Alle Pfeile sind harte Voraussetzungen: keine Phase kann ohne die vollständige Vorgänger-Phase in Produktion gehen.


Modul-zu-Phase-Zuordnung

Modul-SpecEnthaltende Phase(n)
Modul 8 — Plattform (Auth, Rollen, i18n, Audit, Storage, Notifications)P0 vollständig
Modul 1 — CRM (contacts, contact_roles, recipients-Struktur)P1 (Grundstruktur + Lead-Wire-in) + P4 (Dedup, Merge)
Modul 6 — Finanzen (movements, Views, Abschluss, Migration)P1 vollständig + P2/P3 Auto-Posting
Modul 3 — Produkte & Preise (box_products, price_lists, Resolver)P2 vollständig
Modul 4 — Offerten (quotes, PDF, Status-Flows, Konversion)P2 vollständig
Modul 7 — Affiliate (affiliates, referral_codes, commissions, payouts)P2 (Kern)
Modul 5 — Logistik (boxes, tracking_events, containers, deposit_lifecycle)P3 vollständig
Modul 2 — WhatsApp + OCR (kyc_scans, whatsapp_inbound, Webhook)P4 vollständig
Modul 18 — Design/Mobile (Design-Tokens, PWA, Offline, Kamera)P0 (Tokens/Shell) + Inkrementell P1–P4

Geteilte Kern-Entitäten — wann sie entstehen

EntitätEntsteht inErweitert in
contactsP1P4 (KYC-Felder befüllt via OCR)
movementsP1P2 (invoice-Auto-Posting), P3 (deposit-Auto-Posting), P2 (affiliate-payout)
movement_types / payment_methodsP0 (Seed)
box_productsP2 (Seed)
boxes (UUID)P3
shipmentsP3
containersP3
quotesP2
ordersP2 (aus Quote-Konversion)P3 (Boxen-Materialisierung)
invoicesP2 (Auto-Insert)
deposits (deposit_orders/payments/refunds)P3
affiliates / referral_codesP2
audit_logP0Trigger auf je neue Tabelle in P1–P4
storage_objectsP0 (Buckets)P2 (Offerte-PDF), P3 (Box-Fotos), P4 (KYC-Scans)
notificationsP0 (Outbox-Struktur)P1 (Lead-Intake), P2 (QUOTE_SENT), P3 (SHIPMENT_STATUS), P2 (AFFILIATE_STATEMENT)

Offene Punkte mit Phasen-Relevanz

Die folgenden Entscheide müssen vor der jeweiligen Phase geklärt sein:

EntscheidErforderlich vorReferenz-Spec
Anfangssalden-Strategie (Excel Saldo inicial)P1-StartModul 6 §9
Anfangs-Zonen-Taxonomie DR (SDQ/STI/PROV/…)P2-StartModul 3 §9
PDF-Bibliothek (@react-pdf/renderer vs. Puppeteer)P2-StartModul 4 §9 O-02
Affiliate-Code-Rabatt: Kundenrabatt oder intern? ✅ entschieden 2026-06-28: Kundenrabatt (mindert grand_total_chf, auf PDF)Modul 4 §9 O-08
Returnable-Definition pro Produkt (welche Boxen haben Depot?)P2-StartModul 5 §9
OCR-Anbieter (Claude Vision / Google Vision / Azure)P4-StartModul 2 §3
Duplikat-Score-Algorithmus (pg_trgm vs. Edge-Function)P4-StartModul 1 §9
KYC-Aufbewahrungsfrist (DSG-Minimierung vs. Zollanforderung)P4-StartModul 8 §9