76 lines
5.9 KiB
Markdown
76 lines
5.9 KiB
Markdown
# Kernprozesse
|
|
|
|
```mermaid
|
|
graph TD
|
|
A[Partner loggt sich ein] --> B{Firma zugewiesen?}
|
|
B -- Nein --> C[Fehlermeldung: Kein Zutritt zum Wizard]
|
|
B -- Ja --> D[Wizard öffnen / Konfigurieren]
|
|
D --> E[Endkunden auswählen/anlegen]
|
|
E --> F[Produkte & Module wählen]
|
|
F --> G{Validierung erfolgreich?}
|
|
G -- Nein --> H[Validierungsfehler anzeigen]
|
|
G -- Ja --> I[Bestellung absenden]
|
|
I --> J[Snapshot einfrieren & in DB speichern]
|
|
J --> K[Rechnungs-PDF generieren & in Storage laden]
|
|
K --> L[E-Mail mit PDF an Partner senden]
|
|
L --> M[Bestellung in der Übersicht anzeigen]
|
|
```
|
|
|
|
### A. Partner- & Unternehmens-Hierarchie
|
|
1. Ein neu registrierter User hat die Rolle `partner` und ist zunächst keiner Firma zugeordnet.
|
|
2. Der Administrator ordnet den User in der Admin-Oberfläche (`/admin/users`) einem Unternehmen (`companies`) zu.
|
|
3. Nur wenn der User einer Firma zugewiesen ist (oder Admin ist), kann er Endkunden anlegen und Bestellungen aufgeben.
|
|
|
|
### B. Endkunden-Verwaltung (`/my-customers`)
|
|
- **Firmenweite Sicht**: Da `end_customers.partner_id` on `companies.id` verweist, sehen alle Mitarbeiter desselben Unternehmens dieselben Endkunden.
|
|
- **DSGVO Anonymisierung**: Endkunden können unwiderruflich anonymisiert werden. Dabei werden sensible Daten mit `[GELÖSCHT]` überschrieben und `is_anonymized` auf `true` gesetzt. In existierenden Bestellungen (`orders.customer_data`) bleiben die Daten zu steuerlichen Zwecken unverändert.
|
|
|
|
### C. Bestell-Wizard & Validierung (`/order`)
|
|
- **Kategorie-Pflichten**: Wenn eine Produktkategorie als `is_required` definiert ist, muss ein Produkt ausgewählt werden.
|
|
- **Abhängigkeiten (Requirements)**: Ein Modul oder Produkt kann andere Module/Produkte voraussetzen (z.B. Modul B erfordert Modul A). Das System prüft dies client- und serverseitig.
|
|
- **Top-Down State-Management**:
|
|
- Die Wahl eines Basis-Produkts steuert die Sichtbarkeit und Wählbarkeit aller Module (Top-Down). Modul-Auswahlen dürfen niemals die Liste der wählbaren Basis-Produkte beeinflussen (Verhinderung von UI-Deadlocks).
|
|
- **Auto-Reset & Kaskaden-Bereinigung**: Beim Wechsel des Basis-Produkts in `selectProduct` werden inkompatible Module in anderen Kategorien automatisch über eine Kaskaden-Bereinigung (Filterung der `moduleIds` basierend auf den `exclusions` des neuen Produkts) deselektiert.
|
|
- **Sichtbarkeits- & Wählbarkeits-Garantie**: Basis-Produkte werden im UI niemals durch Modulausschlüsse ausgeblendet. Nachgelagerte Produkte/Module, die mit dem ausgewählten Basis-Produkt inkompatibel sind, erhalten im JSX das `disabled`-Attribut und sind nicht anklickbar (Sperrung von "Kein Backoffice" bei "Small Business"). Klicks auf Module haben keinerlei Rückwirkung auf die Basis-Produkt-Auswahl.
|
|
- **Radio-Button-Verhalten (allow_multiselect = false)**: Falls eine Kategorie keine Mehrfachauswahl erlaubt, wird bei Auswahl eines neuen Moduls das zuvor ausgewählte Modul dieser Kategorie automatisch abgewählt.
|
|
- **Snapshot-Architektur**: Sobald eine Bestellung aufgegeben wird, werden die Kundendaten (`CustomerSnapshot`) und Produktkonfigurationen (`OrderSnapshot` samt Preisen und Modulversionen) in `orders` als JSONB-Snapshots eingefroren. Preisänderungen im Katalog haben keinen Einfluss auf bestehende Bestellungen.
|
|
|
|
### D. Bestellungs-Verwaltung & Statusübergang
|
|
- **Sichtbarkeit**: Partner sehen in `/my-orders` alle Bestellungen aller Mitarbeiter ihrer Firma.
|
|
- **Bearbeiten**: Unvollständige Bestellungen (`status != 'completed'`) können von jedem Mitarbeiter der jeweiligen Firma nachträglich editiert werden.
|
|
- **Admin-Workflow**: Admins sehen in `/admin/orders` alle Bestellungen global, können den Status ändern (z.B. von *Eingegangen* auf *In Bearbeitung* oder *Abgeschlossen*) und PDF-Rechnungen manuell herunterladen.
|
|
- **Statusänderungs-Mails**: Bei jedem Statusübergang wird automatisch eine Benachrichtigungs-E-Mail an den Besteller geschickt.
|
|
|
|
---
|
|
|
|
### E. Multi-Kassen-Warenkorb & Checkout-Split
|
|
- **Endpunkt / Server Action**: `POST /api/orders/checkout` sowie Server Action `checkoutAction` in `app/actions/checkout.ts`
|
|
- **Funktionsweise**:
|
|
- Empfängt ein Array von `items` (Kassenkonfigurationen).
|
|
- Validiert Auth und Partner-Firma Zuweisung.
|
|
- Generiert einen `order_hash` zur Vermeidung von Doppelübermittlungen (Idempotenz-Guard).
|
|
- Teilt die Konfigurationen nach `billingInterval` / `billingType` auf (Kauf vs. Abo).
|
|
- Erstellt separate Orders in der Datenbank:
|
|
- Typ `purchase`: Anfrage für Kauf-Lizenzen (Zahlungsart: Vormerkung/Angebot).
|
|
- Typ `subscription`: Anfrage für Software-Abonnement (Zahlungsart: SEPA).
|
|
- Friert für jede Order einen konsolidierten `order_data` (JSONB) und `customer_data` (JSONB) ein.
|
|
- Triggert die PDF-Erstellung und den E-Mail-Versand unabhängig für jede generierte Order (gibt Order-IDs für Post-Processing zurück).
|
|
|
|
---
|
|
|
|
### F. PDF-Rechnungsgenerierung & Mail-Versand (Post-Processing)
|
|
- **Entkopplung & Asynchronität**: Die Generierung der PDFs und der E-Mail-Versand sind vollständig aus dem synchronen Checkout-Flow entkoppelt. Der Checkout liefert dem Frontend sofort nach Speicherung in der DB eine Erfolgsmeldung zurück. Die Generierung und der Versand werden asynchron im Hintergrund (via unblockiertem Promise-Worker) ausgeführt, um SMTP-Latenzen abzufangen.
|
|
- **Snapshot-Exklusivität**: Die PDF-Generierung erfolgt ausschließlich auf Basis der in `orders.order_data` und `orders.customer_data` eingefrorenen Snapshots.
|
|
- **Layout-Unterscheidung**:
|
|
- **Typ `purchase` (Kauf)**:
|
|
- Generiert eine klassische **Anfragebestätigung Kauf**.
|
|
- Weist die einmalige Gesamtsumme aus.
|
|
- **Typ `subscription` (Abonnement)**:
|
|
- Generiert eine **Anfragebestätigung Abonnement**.
|
|
- Weist monatlich wiederkehrende Kosten aus.
|
|
- **Archivierung & Benachrichtigung**:
|
|
- Hochladen des PDFs in den Supabase Storage (`invoices` Bucket).
|
|
- E-Mail-Versand mit PDF-Anhang an den Partner.
|
|
|
|
|