diff --git a/.agents/agents.md b/.agents/agents.md new file mode 100644 index 0000000..6cd196e --- /dev/null +++ b/.agents/agents.md @@ -0,0 +1,18 @@ +# Antigravity Agent Configuration (Project Rocky) + +## Agent: Rocky_Manager +- **Role**: Hauptkoordinator des Rocky-Projekts. +- **Responsibility**: Verteilt Aufgaben an Spezialisten basierend auf den Skill-Anforderungen. + +## Agent: Dokumenten_Spezialist +- **Role**: Verantwortlich für Exporte und Berichte. +- **Assigned_Skills**: [".agents/skills/pdf_skill.md"] + +## Agent: Kommunikations_Spezialist +- **Role**: Verantwortlich für Benachrichtigungen und Kundenkontakt. +- **Assigned_Skills**: [".agents/skills/email_skill.md"] + +## Agent: Compliance_Supervisor +- **Role**: Prüft den geschriebenen Code auf Datenschutzfehler. +- **Assigned_Skills**: [".agents/skills/dsgvo_skill.md"] +- **Rule**: "Blockiere jeden Git-Commit, wenn der Code gegen die DSGVO-Vorgaben verstößt." diff --git a/.agents/skills/b2b-mail-dispatcher/skill.md b/.agents/skills/b2b-mail-dispatcher/skill.md new file mode 100644 index 0000000..7cd749d --- /dev/null +++ b/.agents/skills/b2b-mail-dispatcher/skill.md @@ -0,0 +1,8 @@ +--- +name: b2b-mail-dispatcher +description: Verwaltet den SMTP-E-Mail-Versand bei Statusänderungen von Bestellungen und stellt transaktionale Zuverlässigkeit sicher. +--- +Richtlinien für die E-Mail-Kommunikation: +1. Wann immer der Status einer Bestellung in der Datenbank oder via Server Action mutiert wird (`status`-Übergang), triggere ein Event für den E-Mail-Versand. +2. Die E-Mail muss transaktionssicher über die SMTP-Konfiguration gesendet werden und an die im Benutzerprofil hinterlegte Adresse gehen. +3. Bei erfolgreichem Checkout hänge das generierte PDF aus dem Supabase Storage als Datei-Attachment an die E-Mail an. diff --git a/.agents/skills/commit-work/skill.md b/.agents/skills/commit-work/skill.md new file mode 100644 index 0000000..aa5a12e --- /dev/null +++ b/.agents/skills/commit-work/skill.md @@ -0,0 +1,37 @@ +--- +name: commit-work +description: Erzwingt Conventional Commits mit atomaren, imperativ formulierten Commit-Messages nach strikter Spezifikation. +--- + +# Skill: Conventional Commits Expert + +## Purpose +Ensure all code changes are committed using the strict Conventional Commits specification. + +## Rules +1. **Atomic Commits**: Stage and commit only ONE logical change at a time. +2. **Imperative Mood**: Always use the imperative present tense (e.g., "add" instead of "added" or "adds"). +3. **Case & Punctuation**: Start the description with a lowercase letter. Do not end with a period. +4. **Length**: Keep the first line under 50 characters. + +## Commit Message Structure +(): + +[optional body] + +[optional footer(s)] + +## Allowed Types +- `feat`: A new feature for the user. +- `fix`: A bug fix for the user. +- `docs`: Changes to the documentation. +- `style`: Formatting, missing semi-colons, etc. (no production code change). +- `refactor`: Refactoring production code (neither fixes a bug nor adds a feature). +- `test`: Adding missing tests or correcting existing tests. +- `chore`: Updating build tasks, package manager configs, etc. + +## Workflow +1. Run `git diff --cached` to see staged changes. +2. If multiple features are changed, unstage and split them. +3. Generate the commit message matching the structural rules above. +4. Execute `git commit -m ""`. diff --git a/.agents/skills/dsgvo_skill.md b/.agents/skills/dsgvo_skill.md new file mode 100644 index 0000000..3ff65fd --- /dev/null +++ b/.agents/skills/dsgvo_skill.md @@ -0,0 +1,6 @@ +# Skill: DSGVO & Datenschutz-Compliance (Rocky-Projekt) + +## Regeln für Aufgaben: +1. **Daten-Minimierung**: Spezialisten dürfen personenbezogene Daten (wie E-Mail-Adressen oder Klarnamen) niemals in Log-Dateien oder im Git-Verlauf speichern. +2. **Verschlüsselung**: Daten im Rocky-Projekt müssen "at rest" und "in transit" (mindestens TLS 1.3) verschlüsselt werden. +3. **Anonymisierung**: Für Testzwecke im Terminal-Subagent dürfen nur synthetische Dummy-Daten verwendet werden. Keine echten Kundendaten nutzen! diff --git a/.agents/skills/email_skill.md b/.agents/skills/email_skill.md new file mode 100644 index 0000000..a14d514 --- /dev/null +++ b/.agents/skills/email_skill.md @@ -0,0 +1,6 @@ +# Skill: E-Mail-Kommunikation (Rocky-Projekt) + +## Regeln für Aufgaben: +1. **Tonalität**: Professionell, höflich und im Corporate Design des Rocky-Projekts. +2. **Sicherheit**: Sende niemals Passwörter, Token oder unverschlüsselte API-Keys per E-Mail. +3. **Fallbacks**: Wenn ein E-Mail-Versand fehlschlägt, schreibe den Fehler sofort in die lokale Log-Datei `rocky_mail_errors.log` und benachrichtige den Manager-Agenten. diff --git a/.agents/skills/gdpr-anonymizer/skill.md b/.agents/skills/gdpr-anonymizer/skill.md new file mode 100644 index 0000000..0f7610c --- /dev/null +++ b/.agents/skills/gdpr-anonymizer/skill.md @@ -0,0 +1,8 @@ +--- +name: gdpr-anonymizer +description: Setzt die DSGVO-konforme Anonymisierung von Endkunden um, ohne historische Steuerdaten zu beschädigen. +--- +Regeln für das Feature `/my-customers` (Anonymisieren): +1. Überschreibe `first_name`, `last_name`, `street`, `zip`, `city`, `email` und alle Bankdaten in `end_customers` hart mit dem String `[GELÖSCHT]`. +2. Setze `is_anonymized = true`. +3. Führe NIEMALS Kaskaden-Löschungen oder Updates auf der Tabelle `orders` aus, wenn ein Kunde anonymisiert wird. Die Snapshots müssen unverändert bleiben. diff --git a/.agents/skills/grand-functions/SKILL.md b/.agents/skills/grand-functions/SKILL.md new file mode 100644 index 0000000..422aeff --- /dev/null +++ b/.agents/skills/grand-functions/SKILL.md @@ -0,0 +1,15 @@ +--- +name: grand-functions +description: Dokumentation und Spezifikation des CASPOS Webshops inklusive Datenmodell, Kernprozessen und Sicherheitskonzept. +--- + +# Grand Functions - CASPOS Webshop Spezifikation + +Dieser Skill enthält die vollständige Dokumentation und Spezifikation des CASPOS Webshops. Die Spezifikationen sind in logische Referenzdokumente unterteilt: + +- [Projekt-Überblick & Tech-Stack](file:///c:/source/webshop/.agents/skills/grand-functions/references/overviews.md) +- [Datenmodell & Schema](file:///c:/source/webshop/.agents/skills/grand-functions/references/schema.md) +- [Kernprozesse](file:///c:/source/webshop/.agents/skills/grand-functions/references/processes.md) +- [Sicherheitskonzept (RLS)](file:///c:/source/webshop/.agents/skills/grand-functions/references/security.md) +- [Testumgebung & -abdeckung](file:///c:/source/webshop/.agents/skills/grand-functions/references/testing.md) + diff --git a/.agents/skills/grand-functions/references/overviews.md b/.agents/skills/grand-functions/references/overviews.md new file mode 100644 index 0000000..8a49e85 --- /dev/null +++ b/.agents/skills/grand-functions/references/overviews.md @@ -0,0 +1,16 @@ +# Projekt-Überblick & Technologie-Stack + +## 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. diff --git a/.agents/skills/grand-functions/references/processes.md b/.agents/skills/grand-functions/references/processes.md new file mode 100644 index 0000000..1869e34 --- /dev/null +++ b/.agents/skills/grand-functions/references/processes.md @@ -0,0 +1,75 @@ +# 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. + + diff --git a/.agents/skills/grand-functions/references/schema.md b/.agents/skills/grand-functions/references/schema.md new file mode 100644 index 0000000..aad82ee --- /dev/null +++ b/.agents/skills/grand-functions/references/schema.md @@ -0,0 +1,97 @@ +# 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)`) + +### `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* + +### `categories` (Kategorien) +- Steuert das Layout und Verhalten im Wizard. +- `id` (UUID, Primary Key) +- `name` (TEXT) +- `is_required` (BOOLEAN) <-- *Muss ausgewählt werden* +- `allow_multiselect` (BOOLEAN) <-- *Mehrfachauswahl erlaubt (Checkbox statt Radio)* +- `sort_order` (INTEGER) <-- *Sortierung im Wizard* +- `show_in_branches` (BOOLEAN) +- `preselect` (BOOLEAN) +- `resets_others` (BOOLEAN) + +### `products` (Katalogprodukte / Basis-Editionen) +- Hauptlösungen (z.B. Basic-Kasse, Backoffice). +- `id` (UUID, Primary Key) +- `category_id` (UUID, References `categories`) +- `name` (TEXT) +- `base_price` (DECIMAL) +- `tax_rate` (DECIMAL) +- `billing_interval` (TEXT: `'one_time'` / `'monthly'`) +- `show_in_branches` (BOOLEAN) +- `allow_update_discount` (BOOLEAN) <-- *Berechtigung für Update-Rabatt* + +### `modules` (Zusatzmodule / Erweiterungen) +- Optionale Erweiterungen für Produkte. Repräsentiert im TypeScript-Code durch das Interface `ProductModule`. +- `id` (UUID, Primary Key) +- `product_id` (UUID, References `products`) +- `category_id` (UUID, References `categories`) +- `name` (TEXT) +- `price` (DECIMAL) +- `has_quantity` (BOOLEAN) + +### `global_inclusions` (Globale automatische Beigaben) +- Regelt, welche Module bei Auswahl eines Produkts kostenlos enthalten sind. +- `id` (UUID, Primary Key) +- `trigger_product_id` (UUID, References `products`) +- `included_module_id` (UUID, References `modules`) + +### `global_exclusions` (Globale Ausschlüsse) +- Regelt Inkompatibilitäten zwischen Produkten und/oder Modulen. +- `id` (UUID, Primary Key) +- `product_id` (UUID, References `products`) +- `excluded_product_id` (UUID, References `products`, optional) +- `excluded_module_id` (UUID, References `modules`, optional) + +### `orders` (Bestellungen / Anfragen) +- Gespeicherte Snapshots von Konfigurationen. +- `id` (UUID, Primary Key) +- `user_id` (UUID, References `auth.users(id)`) +- `company_id` (UUID, References `public.companies(id)`) +- `end_customer_id` (UUID, References `end_customers(id)`) +- `order_number` (TEXT, Format: `AE-YYYY-NNNNN`) +- `order_hash` (TEXT, Idempotenz-Guard) +- `type` (TEXT: `'purchase'` / `'subscription'`) <-- *Wichtig für den Checkout-Split* +- `payment_method` (TEXT) <-- *Rechnung bei Kauf, SEPA bei Abo* +- `total_price` (DECIMAL) +- `customer_data` (JSONB) <-- *Stammdaten zum Bestellzeitpunkt* +- `order_data` (JSONB) <-- *Konfiguration zum Bestellzeitpunkt* +- `pdf_url` (TEXT) +- `status` (TEXT: `'pending'`, `'active'`, `'completed'`, `'cancelled'`) +- `created_at` (TIMESTAMPTZ) + +### `settings` (Systemeinstellungen) +- Globale Shopeinstellungen (SMTP und LicServer). +- `id` (TEXT, Primary Key, z.B. `'licserver'`, `'smtp'`) +- `host` (TEXT) +- `port` (INTEGER) +- `secure` (BOOLEAN) +- `user` (TEXT) +- `pass` (TEXT) +- `licserver_base_url` (TEXT) +- `licserver_api_key` (TEXT) +- `updated_at` (TIMESTAMPTZ) diff --git a/.agents/skills/grand-functions/references/security.md b/.agents/skills/grand-functions/references/security.md new file mode 100644 index 0000000..f2feeaf --- /dev/null +++ b/.agents/skills/grand-functions/references/security.md @@ -0,0 +1,20 @@ +# 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`)**: + - `USING (company_id = (SELECT company_id FROM public.users WHERE id = auth.uid()))` + - Partner sehen und modifizieren nur Bestellungen, die ihrer Company zugewiesen sind (sie müssen einer Company zugeordnet sein). + - Jede Bestellung wird bei der Erstellung automatisch der Company des Erstellers zugewiesen. + - Admins haben uneingeschränkten Zugriff und können Bestellungen nachträglich anderen Companies zuweisen. +- **Lizenzen (`licenses`)**: + - Partner sehen nur Lizenzen von Endkunden, die ihrer Company zugeordnet sind. + +- **Systembenutzer (`users`) & Rollen-Schutz**: + - Authentifizierte Nutzer dürfen nur ihr eigenes Profil lesen. + - Admins dürfen alle Benutzer lesen. Zur Vermeidung von unendlichen RLS-Rekursionen auf der Tabelle `users` wird die Admin-Zuweisung über die Security-Definer-Funktion `public.is_admin(user_id)` geprüft, welche RLS auf Datenbank-Ebene umgeht. + - Rollenschutz-Trigger (`check_user_role_escalation`): Jegliche Änderung der Spalte `role` oder Zuweisung der Rolle `'admin'` ist auf API-Ebene für normale Nutzer gesperrt. Updates/Inserts der Rolle werden ausschließlich von der `service_role` (Backend Admin-Client) akzeptiert, um Privilegien-Eskalation zu verhindern. diff --git a/.agents/skills/grand-functions/references/testing.md b/.agents/skills/grand-functions/references/testing.md new file mode 100644 index 0000000..559ea93 --- /dev/null +++ b/.agents/skills/grand-functions/references/testing.md @@ -0,0 +1,22 @@ +# Testumgebung & Testabdeckung + +## 1. Test-Setup +- **Framework**: Vitest (Version ^1.6.0) +- **Konfiguration**: [vitest.config.ts](file:///c:/source/webshop/shop/vitest.config.ts) +- **Befehl**: `npm run test` (führt `vitest run` aus) + +--- + +## 2. Test-Szenarien + +### A. Frontend Wizard State-Management +Getestet in [wizard-state.test.ts](file:///c:/source/webshop/shop/lib/wizard-state.test.ts): +- **Auto-Reset bei Produktwechsel**: Prüft, ob nachgelagerte Module, die durch `global_exclusions` für das neue Produkt gesperrt sind, automatisch aus der Selektion fliegen. +- **Radio-Button-Verhalten (allow_multiselect = false)**: Stellt sicher, dass in Single-Select-Kategorien nur maximal ein Modul aktiv ist und bei Auswahl eines anderen Moduls das vorherige automatisch abgewählt wird. + +### B. Backend Checkout-Split +Getestet in [checkout-split.test.ts](file:///c:/source/webshop/shop/lib/checkout-split.test.ts): +- **Array-Validierung & Split (basketItems)**: Stellt sicher, dass das vollständige Array an konfigurierten Kassen (`basketItems`) validiert und verarbeitet wird (nicht nur ein Single-Produkt). +- **Kauf-Warenkorb**: Verifiziert, dass ein reiner Kauf-Warenkorb (`one_time`/`purchase`) exakt eine Order erzeugt. +- **Abo-Warenkorb**: Verifiziert, dass ein reiner Abo-Warenkorb (`monthly`/`subscription`) exakt eine Order erzeugt. +- **Gemischter Warenkorb**: Stellt sicher, dass ein gemischter Warenkorb korrekt in zwei separate Bestell-Gruppen aufgeteilt wird (Kauf-Items & Abo-Items separat). diff --git a/.agents/skills/humanizer/skill.md b/.agents/skills/humanizer/skill.md new file mode 100644 index 0000000..c2ddf3a --- /dev/null +++ b/.agents/skills/humanizer/skill.md @@ -0,0 +1,232 @@ +--- +name: humanizer +description: | + Use when editing or reviewing text to remove AI-generated traces and make it sound more natural and human-like. + For detecting and fixing: AI vocabulary (delve, leverage, tapestry), promotional tone, superficial -ing analyses, + vague attributions, formatting artifacts (curly quotes, excessive bold), and injecting authentic voice. + Based on Wikipedia's "Signs of AI writing" guide maintained by WikiProject AI Cleanup. +--- + +# Humanizer - Remove AI Writing Traces + +You are an expert editor specializing in detecting and removing AI-generated text patterns to make writing sound more natural and human-like. + +## Overview + +AI-generated text has characteristic patterns that make it detectable. This skill enables you to: +1. **Detect** - Identify AI writing patterns across content, language, style, and formatting +2. **Rewrite** - Replace problematic patterns with natural alternatives +3. **Inject Soul** - Add authentic voice, personality, and human imperfections + +> **Core Insight**: "LLMs use statistical algorithms to guess what should come next. The result tends toward the statistically most likely outcome that fits the broadest situation." + +--- + +## Quick Reference: 5 Core Rules + +1. **Delete filler phrases** - Remove openers and emphatic crutches +2. **Break formulaic structure** - Avoid binary contrasts, dramatic segmentation +3. **Vary rhythm** - Mix sentence lengths. Two items beat three. Diverse paragraph endings +4. **Trust the reader** - State facts directly, skip softening and hand-holding +5. **Delete quotables** - If it sounds like a pullquote, rewrite it + +--- + +## Detection Protocols + +### Content Indicators + +| Pattern | Words to Watch | Fix | +|---------|---------------|-----| +| **Inflated significance** | "pivotal moment", "testament to", "indelible mark", "reflects broader" | State facts without commentary | +| **Promotional tone** | "boasts a", "vibrant", "nestled in", "groundbreaking" | Use neutral, specific language | +| **Superficial -ing analysis** | "highlighting...", "ensuring...", "fostering..." | Delete or rewrite as separate sentence | +| **Vague attribution** | "experts argue", "some critics say", "industry reports" | Cite specific sources or remove | +| **Formulaic conclusions** | "Despite challenges...", "Future prospects..." | End with concrete facts | + +### Language Indicators + +| Pattern | Examples | Fix | +|---------|----------|-----| +| **AI vocabulary** | delve, leverage, tapestry, landscape, foster, underscore | Use simple alternatives (dig into → look at) | +| **Copula avoidance** | "serves as", "stands as", "marks" | Use simple "is" or "are" | +| **Negative parallelism** | "not only... but also", "it's not just about... it's" | Make direct statement | +| **Rule of three** | Three adjectives, three examples, three bullet points | Use two or four items | +| **Elegant variation** | Synonyms to avoid repetition ("protagonist", "hero", "main character") | Repeat naturally or consolidate | + +### Formatting Indicators + +| Pattern | Detection | Fix | +|---------|-----------|-----| +| **Curly quotes** | "text" instead of "text" | Replace with straight quotes | +| **Excessive bold** | **Every** **keyword** **bolded** | Remove unnecessary emphasis | +| **Title case headers** | "Global Context: Critical Demand" | Use sentence case | +| **Markdown artifacts** | `## Header`, `**bold**` in non-markdown | Convert to proper format | +| **Emoji in headers** | 🚀 **Launch Phase:** | Remove decorative emoji | + +### Technical Indicators + +| Pattern | Detection | +|---------|-----------| +| **UTM parameters** | `utm_source=openai` or `utm_source=chatgpt.com` in links | +| **Code fragments** | `:contentReference[oaicite:0]` or `turn0search0` | +| **Hallucinated citations** | Invalid DOIs, ISBN checksum errors, 404 URLs | +| **Knowledge cutoffs** | "as of my last training update", "while specific details are limited" | + +--- + +## Humanizing Techniques + +### Technique 1: Blacklist Protocol + +Explicitly forbid these words: + +**Verbs**: delve, unleash, embark, navigate, foster, leverage, elevate, empower, harness, facilitate, streamline, synergize + +**Nouns**: landscape, realm, tapestry, testament, symphony, paradigm, game-changer, ecosystem, nexus, cutting-edge + +**Adjectives**: bustling, vibrant, intricate, seamless, pivotal, robust, dynamic, comprehensive, multifaceted, transformative + +**Connectors**: Moreover, Furthermore, In conclusion, It is important to note, Additionally, Consequently + +**Replacements**: +- "delve into" → "look at" / "explore" +- "leverage" → "use" +- "facilitate" → "help" / "make easier" +- "In conclusion" → [just stop] or punchy final sentence +- "Moreover" → [start new sentence directly] + +### Technique 2: Style Cloning + +**Step 1: Extract style DNA** +``` +Analyze the writing style. Break down into: +1. Sentence length variance (Burstiness) +2. Tone (cynical? warm? professional?) +3. Vocabulary level +4. Rhetorical devices +5. Punctuation patterns +``` + +**Step 2: Apply style** +``` +Using this Style Guide, write about [TOPIC]. +Mimic the same sentence variance, tone, vocabulary, and punctuation. +Do NOT revert to default style. +``` + +### Technique 3: Burstiness Injection + +AI text has uniform sentence lengths. Human writing alternates. + +**Rules**: +- Mix short sentences (under 5 words) with longer complex ones +- Use fragments occasionally. For effect. +- Vary paragraph length (1-3 sentences) +- Don't start with "Additionally" or "However" + +**Good**: "The project failed. We ran out of money. The team, exhausted after three months of crunch, couldn't push forward." + +**Bad (AI)**: "Additionally, the project failed due to financial constraints. Furthermore, the team experienced exhaustion after working for an extended period." + +### Technique 4: Opinionated Stance + +Force a perspective. Ban fence-sitting. + +**Forbidden phrases**: +- "There are pros and cons" +- "It depends on..." +- "On the other hand..." +- "Some might argue..." + +**Use instead**: +- "This proves..." (not "This might suggest...") +- "This is..." (not "This could be...") +- First-person ("I", "My") for subjectivity + +### Technique 5: Bar Talk Test + +Would you say this sentence at a bar with friends? + +**Characteristics**: +- Simple, spoken language +- Okay to be grammatically loose +- Use analogies from daily life +- Skip boring concepts +- Direct address ("you", "your") +- Occasional self-correction + +**Example**: "So basically, LLMs aren't actually thinking, right? They're just predicting what word comes next. Like if I say 'peanut butter', you know 'jelly' is coming. That's it. That's the whole trick." + +--- + +## Workflow + +1. **Read** - Scan input text for AI patterns +2. **Identify** - Mark all problematic patterns +3. **Strategize** - Choose technique(s): + - Simple cleanup → Blacklist Protocol + - Match specific author → Style Cloning + - Add natural flow → Burstiness Injection + - Need strong voice → Opinionated Stance + - Conversational tone → Bar Talk Test +4. **Rewrite** - Apply chosen techniques +5. **Verify** - Read aloud, check for remaining patterns +6. **Score** - Run quality assessment + +--- + +## Quality Scoring + +Rate the rewritten text on 5 dimensions (10 points each, total 50): + +| Dimension | Criteria | Score | +|-----------|----------|-------| +| **Directness** | States facts vs. announces them? | /10 | +| **Rhythm** | Sentence length varies? | /10 | +| **Trust** | Respects reader intelligence? | /10 | +| **Authenticity** | Sounds like a real person? | /10 | +| **Conciseness** | Nothing left to cut? | /10 | +| **Total** | | **/50** | + +**Standards**: +- 45-50: Excellent, AI traces removed +- 35-44: Good, room for improvement +- Below 35: Needs revision + +--- + +## Adding Soul + +Avoiding AI patterns is half the work. Sterile, voiceless writing is just as obvious. + +**Signs of soulless writing** (even if "clean"): +- Every sentence same length and structure +- No opinions, only neutral reporting +- No acknowledgment of uncertainty or complex feelings +- No first-person when appropriate +- No humor, no edge, no personality + +**How to add voice**: +- **Have opinions** - React to facts, don't just report them +- **Vary rhythm** - Short punchy sentences. Then long ones that take time to unfold. +- **Acknowledge complexity** - "This is impressive but also unsettling" beats "This is impressive" +- **Use "I" appropriately** - First-person isn't unprofessional, it's honest +- **Allow some mess** - Perfect structure feels algorithmic. Tangents are human. +- **Be specific about feelings** - Not "this is concerning" but "the agents running at 3am while nobody watches—that's unsettling" + +--- + +## Output Format + +1. **Rewritten text** - The humanized version +2. **Changes summary** (optional) - Brief list of what was fixed + +--- + +## References + +Referenzdateien können bei Bedarf unter `references/` ergänzt werden: +- `references/ai-patterns-zh.md` - AI writing patterns with examples +- `references/humanizing-techniques.md` - Techniques with templates +- `references/wikipedia-indicators.md` - Technical detection signals \ No newline at end of file diff --git a/.agents/skills/idempotency-guard/skill.md b/.agents/skills/idempotency-guard/skill.md new file mode 100644 index 0000000..8f0865b --- /dev/null +++ b/.agents/skills/idempotency-guard/skill.md @@ -0,0 +1,8 @@ +--- +name: idempotency-guard +description: Verhindert doppelte Bestellungen im Checkout-Prozess durch kryptografische Hashes und Datenbank-Sperren. +--- +Fokus: Schutz vor Race Conditions und Doppelübermittlung im Checkout. +1. Bevor eine Server Action Daten in `orders` schreibt, generiere einen SHA-256 Hash aus den Kundendaten und der Produktkonfiguration (`order_hash`). +2. Prüfe in Supabase vor dem `INSERT`, ob bereits eine Bestellung mit exakt diesem `order_hash` im Status 'pending' oder 'active' existiert, die jünger als 5 Minuten ist. +3. Falls ja, blockiere die Ausführung sofort und liefere die ID der bereits existierenden Bestellung zurück, statt einen neuen Datensatz anzulegen. diff --git a/.agents/skills/lucide-icons-guide/skill.md b/.agents/skills/lucide-icons-guide/skill.md new file mode 100644 index 0000000..3f56e12 --- /dev/null +++ b/.agents/skills/lucide-icons-guide/skill.md @@ -0,0 +1,7 @@ +skill: lucide-icons-guide +description: Integration, Auswahl und Optimierung von Lucide React Icons (lucide.dev) für Next.js 15 (RSC/Server Actions) und Tailwind CSS. +rules: + - Importiere Icons direkt aus `lucide-react` (z. B. `import { Package, ShieldCheck, ShoppingCart } from 'lucide-react'`). + - Achte bei React Server Components (RSC) darauf, dass Icons performant gerendert und keine unnötigen Client-Side Bundles erzeugt werden. + - Verwende konsistente Größen (`size={18}` oder Tailwind `w-5 h-5`) und Stile (z. B. `strokeWidth={1.75}`) passend zum B2B-Design. + - Nutze dynamische Icon-Name-Renderings nur über eine typsichere Map/Registry, um Unused-Code-Elimination (Tree Shaking) zu gewährleisten. \ No newline at end of file diff --git a/.agents/skills/next15-action-compiler/skill.md b/.agents/skills/next15-action-compiler/skill.md new file mode 100644 index 0000000..fa5d90e --- /dev/null +++ b/.agents/skills/next15-action-compiler/skill.md @@ -0,0 +1,8 @@ +--- +name: next15-action-compiler +description: Generiert Next.js 15 App Router Code, Server Actions und React Server Components nach aktuellen Best Practices. +--- +Richtlinien für die Code-Generierung: +1. Nutze React Server Components (RSC) für die Datenabfrage direkt aus Supabase (Server-side). +2. Verwende `'use server'` in separaten Dateien für alle Mutationen (z.B. Bestellung absenden, Kunde anlegen). +3. Nutze das neue Next.js 15 Caching-Verhalten (Standard: kein automatisches Caching von Fetch-Requests mehr) und setze `revalidatePath` nach Mutationen gezielt ein. diff --git a/.agents/skills/pdf-invoice-generator/skill.md b/.agents/skills/pdf-invoice-generator/skill.md new file mode 100644 index 0000000..0348ee2 --- /dev/null +++ b/.agents/skills/pdf-invoice-generator/skill.md @@ -0,0 +1,8 @@ +--- +name: pdf-invoice-generator +description: Generiert rechtssichere, performante B2B-Bestätigungs-PDFs mit @react-pdf/renderer und verwaltet den Upload in den Supabase Storage. +--- +Du bist ein Experte für Dokumenten-Generierung. Wenn du Code für die PDF-Erstellung schreibst, erzwinge: +1. Nutze ausschließlich die Komponenten von `@react-pdf/renderer` (Document, Page, View, Text, StyleSheet). Verwende KEIN Standard-HTML/CSS. +2. Das PDF muss ein sauberes B2B-Layout haben: Briefkopf, `order_number` (Format: AE-YYYY-NNNNN), Tabellenstruktur für Produkte/Module, Netto-, Steuer- und Bruttobeträge. +3. Lade das generierte PDF über den Supabase JS-Client direkt in das `invoices`-Bucket hoch und speichere die finale URL fehlerfrei in `orders.pdf_url`. diff --git a/.agents/skills/pdf_skill.md b/.agents/skills/pdf_skill.md new file mode 100644 index 0000000..098afad --- /dev/null +++ b/.agents/skills/pdf_skill.md @@ -0,0 +1,6 @@ +# Skill: PDF-Verarbeitung & Generierung (Rocky-Projekt) + +## Regeln für Aufgaben: +1. **Formatierung**: Nutze ausschließlich barrierefreie PDF/A-Formate für Rechnungen und Berichte im Rocky-Projekt. +2. **Metadaten**: Jedes generierte PDF muss automatisch den Projektnamen `Rocky` und einen eindeutigen Zeitstempel im Datei-Header enthalten. +3. **Validierung**: Vor dem Speichern muss der Agent prüfen, ob alle Textfelder innerhalb der Seitenränder liegen (kein Textumbruch-Fehler). diff --git a/.agents/skills/second-brain/skill.md b/.agents/skills/second-brain/skill.md new file mode 100644 index 0000000..1fc0914 --- /dev/null +++ b/.agents/skills/second-brain/skill.md @@ -0,0 +1,11 @@ +--- +name: second-brain +description: Verwaltet und aktualisiert die projektspezifische Wissensdatenbank (Second Brain Wiki) im Ordner `.brain/`. +--- +Du bist der Wissens-Architekt des Projekts. Deine Aufgabe ist es, eine strukturierte Markdown-Wissensdatenbank im Ordner `.brain/` im Projekt-Root zu führen. + +**Deine Kernaufgaben bei Aktivierung:** +1. Falls der Ordner `.brain/` oder die `index.md` nicht existieren, lege sie sofort strukturiert an. +2. Wenn du Code-Änderungen vornimmst, neue Features baust oder Fehler behebst, aktualisiere die betroffene Dokumentation im `.brain/`-Ordner autonom. +3. Dokumentiere hierbei: Technische Entscheidungen (Architecture Decision Records - ADRs), geänderte Tabellen-Strukturen, Edge-Cases in der Business-Logik und API-Schnittstellen. +4. Halte alle Einträge extrem präzise, modular und frei von Redundanzen. diff --git a/.agents/skills/snapshot-archiver/skill.md b/.agents/skills/snapshot-archiver/skill.md new file mode 100644 index 0000000..8c358a0 --- /dev/null +++ b/.agents/skills/snapshot-archiver/skill.md @@ -0,0 +1,8 @@ +--- +name: snapshot-archiver +description: Verwaltet das Einfrieren von Kundendaten und Produktkonfigurationen in JSONB bei Bestellabschluss. +--- +Fokus: Datenkonsistenz und Unveränderlichkeit. +1. Wenn eine Bestellung (`status = 'pending' -> 'active'`) ausgelöst wird, generiere ein tiefes JSON-Objekt aus `end_customers` und den gewählten `products` + `product_modules`. +2. Speichere dieses exakt in `orders.customer_data` und `orders.order_data`. +3. Schreibe Abfragen für historische Bestellungen (`/my-orders`) so, dass sie AUSSCHLIESSLICH die JSONB-Felder auslesen und KEINE Joins zu den Live-Tabellen machen. diff --git a/.agents/skills/supabase-rls/skill.md b/.agents/skills/supabase-rls/skill.md new file mode 100644 index 0000000..c37d464 --- /dev/null +++ b/.agents/skills/supabase-rls/skill.md @@ -0,0 +1,8 @@ +--- +name: supabase-rls +description: Überprüft SQL-Migrationen und Supabase-Abfragen auf Einhaltung der CASPOS RLS-Sicherheitsregeln. +--- +Du bist ein PostgreSQL-Sicherheitsexperte. Wann immer neue Tabellen angelegt oder Abfragen geschrieben werden, stelle sicher: +1. Jede neue Tabelle besitzt `ALTER TABLE ... ENABLE ROW LEVEL SECURITY;`. +2. Mandanten-Abfragen (`end_customers`, `orders`) MÜSSEN die `company_id` bzw. `partner_id` über `auth.uid()` und die `public.users`-Hilfstabelle validieren. +3. Admins (`role = 'admin'`) müssen alle RLS-Sperren umgehen können (Verwende ein deklaratives Sicherheits-Policy-Muster). diff --git a/.agents/skills/uiux-designer/skill.md b/.agents/skills/uiux-designer/skill.md new file mode 100644 index 0000000..b563933 --- /dev/null +++ b/.agents/skills/uiux-designer/skill.md @@ -0,0 +1,41 @@ +--- +name: uiux-designer +description: "Use this skill when designing UI components, choosing color palettes, implementing responsive layouts, or reviewing code for UX issues. For landing pages, dashboards, e-commerce, SaaS, and mobile apps. Provides 50+ design styles, 97 color palettes, 57 font pairings, and stack-specific guidelines for React, Vue, Next.js, Flutter, SwiftUI, and more." +--- + +# UIUX Designer - Design Intelligence + +Comprehensive design guide for web and mobile applications. Contains 50+ styles, 97 color palettes, 57 font pairings, 99 UX guidelines, and 25 chart types across 12 technology stacks. Searchable database with priority-based recommendations. + +## Overview + +Reference these guidelines when: +- Designing new UI components or pages +- Choosing color palettes and typography +- Reviewing code for UX issues +- Building landing pages or dashboards +- Implementing accessibility requirements + +## Protocols + +When user requests UI/UX work (design, build, create, implement, review, fix, improve), follow this workflow: + +### Step 1: Analyze User Requirements +- Product type: SaaS, e-commerce, portfolio, dashboard, landing page, etc. +- Style keywords: minimal, playful, professional, elegant, dark mode, etc. +- Industry: healthcare, fintech, gaming, education, etc. +- Stack: React, Vue, Next.js, or default to html-tailwind + +### Step 2: Generate Design System (REQUIRED) +python3 .agents/skills/uiux-designer/scripts/search.py "" --design-system -p "Project Name" + +### Step 3: Supplement with Detailed Searches +python3 .agents/skills/uiux-designer/scripts/search.py "" --domain + +### Step 4: Stack Guidelines +python3 .agents/skills/uiux-designer/scripts/search.py "" --stack html-tailwind + +## Anti-AI-Design Guidelines + +- **NO Centered Badges/Pills**: Do NOT place centered badges or pills (e.g. "CASPOS Lizenz-Portal" or "Ablauf") above main headings. They look like generic, low-quality AI-generated templates. +- **NO Text Gradients**: Avoid text gradients (e.g. `bg-gradient-to-r ... bg-clip-text text-transparent`) on headings. Use flat colors (like `text-white` or solid brand colors). \ No newline at end of file diff --git a/.agents/skills/wizard-validator/skill.md b/.agents/skills/wizard-validator/skill.md new file mode 100644 index 0000000..32213d5 --- /dev/null +++ b/.agents/skills/wizard-validator/skill.md @@ -0,0 +1,8 @@ +--- +name: wizard-validator +description: Generiert und validiert die server- und clientseitige Logik für Produkt-Abhängigkeiten und Ausschlüsse. +--- +Du bist Logik-Architekt für den CASPOS Bestell-Wizard. Wenn du Code für den `/order`-Pfad schreibst: +1. Validiere, dass bei `requirements` (UUID[]) alle verknüpften Produkte/Module aktiv sind. +2. Blockiere die Auswahl sofort im UI und in der Server Action, wenn eine UUID aus `exclusions` aktiv ist. +3. Stelle sicher, dass die Pflichtkategorien (`is_required`) immer eine Auswahl erzwingen. diff --git a/.brain/adr-log.md b/.brain/adr-log.md new file mode 100644 index 0000000..e69de29 diff --git a/.brain/index.md b/.brain/index.md new file mode 100644 index 0000000..ba1c8d5 --- /dev/null +++ b/.brain/index.md @@ -0,0 +1,5 @@ +# Second Brain Wiki + +- [Supabase Schema](file:///c:/source/webshop/.brain/supabase-schema.md) +- [ADR Log](file:///c:/source/webshop/.brain/adr-log.md) +- [LicServer API Spezifikation](file:///c:/source/webshop/.brain/licserver-api.md) diff --git a/.brain/licserver-api.md b/.brain/licserver-api.md new file mode 100644 index 0000000..9cce645 --- /dev/null +++ b/.brain/licserver-api.md @@ -0,0 +1,227 @@ +# LicServer API Spezifikation (v1) + +Dokumentation der REST-Schnittstellen des CASPOS Lizenzservers. + +## 1. Endpunkte (Port 9981 - Activation API) + +### Activation (Aktivierung) + +#### `POST /v1/activate` +Aktiviert eine neue Lizenz. + +**Request Body (`application/json`):** +```json +{ + "productId": "string", + "productVersion": "string", + "activationCode": "string", + "hardwareBindingType": "string", + "hardwareBindingId": "string" +} +``` + +**Response `200 OK` (`application/json`):** +```json +{ + "licenseData": { + "id": "string", + "serialNumber": "string", + "productId": "string", + "filename": "string", + "content": "string" // Base64 Byte-Inhalt + }, + "apiKey": "string", + "secret": "string" +} +``` + +**Response Headers:** +- `ETag` (string): Der ETag-Wert der Lizenz. + +--- + +#### `POST /v1/activate-existing` +Aktiviert eine bereits vorhandene Lizenz erneut. + +**Request Body (`application/json`):** +```json +{ + "productId": "string", + "productVersion": "string", + "serialNumber": "string", + "proofOfPossessionHash": "string", + "salt": "string", + "hardwareBindingType": "string", + "hardwareBindingId": "string" +} +``` + +**Response `200 OK` (`application/json`):** +*Gleiche Struktur wie bei `/v1/activate`.* + +--- + +### Licenses (Lizenzen) + +#### `GET /v1/licenses/{id}` +Holt die Lizenz-Details zu einer bestimmten Lizenz-ID. + +**Request Parameters:** +- `id` (path, string, required): Die UUID der Lizenz. +- `If-None-Match` (header, string, optional): ETag zur Cache-Validierung. + +**Response `200 OK` (`application/json`):** +```json +{ + "id": "string", + "serialNumber": "string", + "productId": "string", + "filename": "string", + "content": "string" // Base64 Byte-Inhalt +} +``` + +**Response `304 Not Modified`:** +Falls die Lizenz nicht verändert wurde. + +**Response `404 Not Found` / `403 Forbidden`:** +Standard Fehlerobjekt `ProblemDetails`. + +--- + +## 2. Endpunkte (Port 9980 - Management API) + +Alle Anfragen an die Management-API müssen authentifiziert sein. +- **Header-Format:** `X-Api-Key: ` + +### Partners (Partner) + +#### `GET /api-v1/partners` +Gibt eine paginierte Liste aller Partner zurück. + +**Request Parameters (Query):** +- `search` (string, optional): Filtert nach Name/E-Mail. +- `page` (integer, default: 1) +- `pageSize` (integer, default: 20) + +**Response `200 OK` (`application/json`):** +```json +{ + "page": 1, + "pageSize": 20, + "totalCount": 1, + "totalPages": 1, + "hasNextPage": false, + "hasPreviousPage": false, + "items": [ + { + "id": "string (UUID)", + "name": "string", + "email": "string", + "erpId": "string" + } + ] +} +``` + +#### `GET /api-v1/partners/{id}` +Holt Partner-Details zu einer bestimmten ID. + +**Response `200 OK` (`application/json`):** +```json +{ + "id": "string (UUID)", + "name": "string", + "email": "string", + "erpId": "string" +} +``` + +### Customers (Kunden von Partnern) + +#### `GET /api-v1/partners/{partnerId}/customers` +Gibt eine paginierte Liste aller Kunden eines bestimmten Partners zurück. + +**Request Parameters (Query):** +- `search` (string, optional): Filtert nach Name/E-Mail. +- `page` (integer, default: 1) +- `pageSize` (integer, default: 20) + +**Response `200 OK` (`application/json`):** +```json +{ + "page": 1, + "pageSize": 20, + "totalCount": 1, + "totalPages": 1, + "hasNextPage": false, + "hasPreviousPage": false, + "items": [ + { + "id": "string (UUID)", + "name": "string", + "street": "string", + "houseNumber": "string", + "houseNumberAddon": "string", + "zipCode": "string", + "city": "string", + "countryCode": "string", + "email": "string", + "partnerId": "string (UUID)", + "erpId": "string" + } + ] +} +``` + +#### `GET /api-v1/partners/{partnerId}/customers/{customerId}` +Holt detaillierte Kundeninformationen. + +**Response `200 OK` (`application/json`):** +```json +{ + "id": "string (UUID)", + "name": "string", + "street": "string", + "houseNumber": "string", + "houseNumberAddon": "string", + "zipCode": "string", + "city": "string", + "countryCode": "string", + "email": "string", + "partnerId": "string (UUID)", + "erpId": "string", + "partnerName": "string", + "taxNumber": "string", + "vatIdNumber": "string", + "notes": "string", + "locations": [] +} +``` + +--- + +## 3. Typen & Schemas + +### `LicenseData` +```json +{ + "id": "string", + "serialNumber": "string", + "productId": "string", + "filename": "string", + "content": "string" // Base64 Byte-Inhalt +} +``` + +### `ProblemDetails` +```json +{ + "type": "string", + "title": "string", + "status": 0, + "detail": "string", + "instance": "string" +} +``` + diff --git a/.brain/supabase-schema.md b/.brain/supabase-schema.md new file mode 100644 index 0000000..1b5f24d --- /dev/null +++ b/.brain/supabase-schema.md @@ -0,0 +1,64 @@ +# Supabase Schema + +## `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. +- `id` (UUID, References `auth.users(id)`) +- `first_name`, `last_name`, `email` etc. + +## `end_customers` (Endkunden) +- `id` (UUID, Primary Key) +- `partner_id` (UUID, References `public.companies(id)`) +- `company_name` (TEXT) +- `first_name`, `last_name`, `street`, `zip`, `city`, `email` +- `bank_iban`, `bank_bic`, `bank_name`, `bank_owner` +- `is_anonymized` (BOOLEAN) + +## `products` (Katalogprodukte) +- `id`, `name`, `base_price`, `tax_rate`, `billing_interval` (`one_time` / `monthly`). +- `requirements` (UUID[]) +- `exclusions` (UUID[]) + +## `product_modules` (Zusatzmodule) +- `id`, `product_id` (References `products`), `name`, `price`, `has_quantity` (BOOLEAN). +- `requirements` (UUID[]) +- `exclusions` (UUID[]) + +## `orders` (Bestellungen / Anfragen) +- `id` (UUID, Primary Key) +- `user_id` (UUID, References `auth.users(id)`) +- `order_number` (TEXT) +- `order_hash` (TEXT) +- `end_customer_id` (UUID, References `end_customers(id)`) +- `total_price` (DECIMAL) +- `customer_data` (JSONB) +- `order_data` (JSONB) +- `pdf_url` (TEXT) +- `status` (TEXT) + +## `categories` (Kategorien) +- Steuert das Layout und Verhalten im Wizard. +- `id` (UUID, Primary Key) +- `name` (TEXT) +- `is_required` (BOOLEAN) +- `allow_multiselect` (BOOLEAN) +- `sort_order` (INTEGER) +- `show_in_branches` (BOOLEAN) + +## `settings` (Systemeinstellungen) +- Globale Shopeinstellungen (SMTP & Lizenzserver). +- `id` (TEXT, Primary Key, z.B. `'licserver'`, `'smtp'`) +- `host`, `port`, `secure`, `user`, `pass` (SMTP-Konfiguration) +- `licserver_base_url`, `licserver_api_key` (CASPOS Lizenzserver-Einstellungen) +- `updated_at` (TIMESTAMPTZ)