# Projekt-Dokumentation: CASPOS Webshop Diese Datei beschreibt die Architektur, das Datenmodell, die Kernprozesse und das Sicherheitskonzept des CASPOS Webshops. --- ## 1. Projekt-Überblick Der CASPOS Webshop ist ein B2B-Portal für Vertriebspartner. Partner können hier Software-Pakete und Zusatzmodule (für POS/Kassenlösungen) konfigurieren, Anfragen für ihre Endkunden erstellen und Lizenzen verwalten. --- ## 2. Technologie-Stack - **Frontend/Backend**: Next.js 15+ (App Router, React Server Components, Server Actions). - **Styling**: Tailwind CSS & Vanilla CSS (modernes Dark-Theme). - **Datenbank & Auth**: Supabase (PostgreSQL, Row Level Security - RLS, Supabase Auth). - **E-Mail-Versand**: SMTP-Integration für automatisierte Bestätigungen. - **PDF-Generierung**: `@react-pdf/renderer` zur Erzeugung von Anfragebestätigungen als PDF. - **Storage**: Supabase Storage (`invoices` Bucket) zur Archivierung der PDF-Dokumente. --- ## 3. Datenmodell & Beziehungen (Schema) Das Datenbankschema besteht aus folgenden Tabellen im Schema `public`: ### `companies` (Unternehmen) - Repräsentiert die Partner-Unternehmen (Retailer). - `id` (UUID, Primary Key) - `name` (TEXT) - `street`, `zip`, `city`, `email` (Adressdaten) ### `users` (Systembenutzer) - Erweitert die Authentifizierungsdaten aus `auth.users`. - `id` (UUID, References `auth.users(id)`) - `role` (TEXT, standardmäßig `'partner'`, oder `'admin'`) - `company_id` (UUID, References `public.companies(id)`) ### `profiles` (Benutzerprofile) - Stammdaten der einzelnen Benutzer (Ansprechpartner). - `id` (UUID, References `auth.users(id)`) - `first_name`, `last_name`, `email` etc. ### `end_customers` (Endkunden) - Die Endkunden, für die die Partner Lizenzen bestellen. - `id` (UUID, Primary Key) - `partner_id` (UUID, References `public.companies(id)`) <-- *Direkte Zuordnung zur Firma des Partners* - `company_name` (TEXT) - `first_name`, `last_name`, `street`, `zip`, `city`, `email` (Stammdaten) - `bank_iban`, `bank_bic`, `bank_name`, `bank_owner` (Bankdaten) - `is_anonymized` (BOOLEAN) <-- *Für DSGVO-Löschung* ### `products` (Katalogprodukte) - Hauptlösungen (z.B. Basic-Kasse, Backoffice). - `id`, `name`, `base_price`, `tax_rate`, `billing_interval` (`one_time` / `monthly`). - `requirements` (UUID[] von anderen Produkten) - `exclusions` (UUID[] von inkompatiblen Produkten) ### `product_modules` (Zusatzmodule) - Optionale Erweiterungen für Produkte. - `id`, `product_id` (References `products`), `name`, `price`, `has_quantity` (BOOLEAN). - `requirements` (UUID[] von Modulen) - `exclusions` (UUID[] von Modulen) ### `orders` (Bestellungen / Anfragen) - Gespeicherte Snapshots von Konfigurationen. - `id` (UUID, Primary Key) - `user_id` (UUID, References `auth.users(id)`) <-- *Ersteller der Bestellung* - `order_number` (TEXT, Format: `AE-YYYY-NNNNN`) - `order_hash` (TEXT, Idempotenz-Guard gegen Doppelübermittlung) - `end_customer_id` (UUID, References `end_customers(id)`) - `total_price` (DECIMAL) - `customer_data` (JSONB) <-- *Eingefrorener Snapshot des Endkunden* - `order_data` (JSONB) <-- *Eingefrorener Snapshot der Produktkonfiguration* - `pdf_url` (TEXT, Link zur PDF-Rechnung im Storage) - `status` (TEXT: `'pending'`, `'active'`, `'completed'`, `'cancelled'`) --- ## 4. 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` auf `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. - **Ausschlüsse (Exclusions)**: Inkompatible Produkte oder Module blockieren sich gegenseitig. - **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. --- ## 5. Sicherheitskonzept (RLS - Row Level Security) RLS ist auf Datenbankebene in Postgres implementiert und erzwingt Datenisolierung: - **Unternehmen (`companies`)**: Authentifizierte Benutzer dürfen nur die Unternehmen lesen. - **Endkunden (`end_customers`)**: - `USING (partner_id = (SELECT company_id FROM public.users WHERE id = auth.uid()))` - Partner sehen und modifizieren nur Endkunden, deren `partner_id` mit der `company_id` des angemeldeten Benutzers übereinstimmt. - **Bestellungen (`orders`)**: - Partner sehen und modifizieren nur Bestellungen von Benutzern, die derselben Company angehören (sie müssen einer company zugewiesen sein). - Admins haben uneingeschränkten Zugriff. - **Lizenzen (`licenses`)**: - Partner sehen nur Lizenzen von Endkunden, die ihrer Company zugeordnet sind. - **Erstellung: jede bestellung wird der firma des erstellers zugewiesen. Ein admin ist aber fähig einer bestellung nachträglich eine andere firma zuzuweisen. --- ## Kommentarbereich *Bitte nutze diesen Bereich oder füge Zeilenkommentare hinzu, um Änderungen oder Ergänzungen vorzuschlagen.* - **Kommentar 1**: - **Kommentar 2**: