Files
webshop/funktionen.md
2026-07-04 15:43:45 +02:00

7.0 KiB

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, Angebote/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

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 (oder ihre eigenen, falls keine Company zugewiesen ist).
    • Admins haben uneingeschränkten Zugriff.
  • Lizenzen (licenses):
    • Partner sehen nur Lizenzen von Endkunden, die ihrer Company zugeordnet sind.

Kommentarbereich

Bitte nutze diesen Bereich oder füge Zeilenkommentare hinzu, um Änderungen oder Ergänzungen vorzuschlagen.

  • Kommentar 1:
  • Kommentar 2: