feat(customers): add initial admin bootstrap and csv import

This commit is contained in:
DS | Schubert 2026-07-03 09:14:56 +02:00
parent c816e9869d
commit ecab0fe6b6
27 changed files with 1197 additions and 34 deletions

View file

@ -93,6 +93,12 @@ Hermes setzt kein Cookie.
2. Athena loescht das HttpOnly-Cookie.
3. Der Benutzer wird zur Login-Seite gefuehrt.
### Aktueller Benutzer
Athena stellt `GET /api/me` bereit und ruft dafuer serverseitig Hermes `GET /auth/me` auf. Der Header laedt den aktuellen Benutzer ausschliesslich ueber diese BFF-Route und zeigt bevorzugt Vorname plus Nachname, danach den Benutzernamen und vor dem Laden `Benutzer`.
Der Browser erhaelt dabei kein Token und ruft Hermes nicht direkt auf.
### HttpOnly Cookie
Das Auth-Cookie wird von Athena gesetzt.
@ -238,6 +244,56 @@ Kunden:
- `customers.read`
- `customers.create`
- `customers.update`
### Initial Admin Bootstrap
Hermes prueft beim Startup nach dem RBAC-Seed, ob mindestens ein aktiver Benutzer existiert. Existiert ein aktiver Benutzer, wird kein Benutzer automatisch erstellt.
Existiert kein aktiver Benutzer, kann Hermes ueber optionale Umgebungsvariablen einen initialen Administrator anlegen:
- `INITIAL_ADMIN_USERNAME`
- `INITIAL_ADMIN_EMAIL`
- `INITIAL_ADMIN_PASSWORD`
- `INITIAL_ADMIN_FIRST_NAME`
- `INITIAL_ADMIN_LAST_NAME`
Benutzername, E-Mail und Passwort sind fuer die automatische Anlage erforderlich. Fehlen Werte oder ist die E-Mail ungueltig, startet Hermes weiter und schreibt nur eine Warnung ohne Secrets. Das Passwort wird mit der bestehenden `hash_password`-Funktion gehasht. Der Benutzer erhaelt `role_id` der Systemrolle `administrator` und das Legacy-Feld `role=administrator`.
### Kundenimport
Hermes stellt fuer CSV-Importe zwei Endpunkte bereit:
- `POST /customers/import/preview`
- `POST /customers/import/commit`
Athena stellt die Browser-BFF-Routen bereit:
- `POST /api/customers/import/preview`
- `POST /api/customers/import/commit`
- `GET /api/customers/import/template`
Der Browser sendet Multipart-FormData nur an Athena. Athena leitet die Datei serverseitig mit Bearer Token aus dem HttpOnly-Cookie an Hermes weiter. Hermes begrenzt CSV-Dateien auf 5 MB, bevorzugt UTF-8, erkennt Semikolon und Komma und ignoriert leere Zeilen.
Importmodi:
- `create_only`: neue Kunden erstellen, bestehende Kundennummern ueberspringen
- `update_existing`: bestehende Kunden anhand der Kundennummer aktualisieren
- `upsert`: bestehende Kunden aktualisieren und neue Kunden erstellen
RBAC:
- Preview benoetigt `customers.read`
- Commit mit `create_only` benoetigt `customers.create`
- Commit mit `update_existing` benoetigt `customers.update`
- Commit mit `upsert` benoetigt `customers.create` und `customers.update`
CSV-Spalten:
```text
customer_number;company_name;legal_name;customer_type;status;industry;website;email;phone;tax_number;vat_id;notes;address_type;street;postal_code;city;state;country;address_is_primary;contact_first_name;contact_last_name;contact_position;contact_email;contact_phone;contact_mobile;contact_is_primary;contact_notes
```
Pflichtfeld ist `company_name`. Wenn `customer_number`, `customer_type` oder `status` fehlen, erzeugt der Import fuer neue Kunden eine Kundennummer bzw. nutzt produktive Defaults und weist in der Preview darauf hin. Vollstaendige CSV-Inhalte werden nicht im Audit Log gespeichert.
- `customers.delete`
Projekte: