# Olympus CRM Entwicklungssetup Dieses Dokument beschreibt das lokale Setup fuer neue Rechner und parallele Entwicklung auf mehreren Macs. ## Setup auf neuem Mac Voraussetzungen: - Git - Docker Desktop - Node.js passend zu Athena - Python/uv fuer lokale Hermes-Checks Repository klonen: ```bash git clone Olympus cd Olympus ``` Umgebung anlegen: ```bash cp .env.example .env ``` Wichtige lokale Werte: ```env AUTH_COOKIE_SECURE=false ATHENA_PUBLIC_ORIGIN=http://localhost:3001 STORAGE_PROVIDER=local STORAGE_BASE_PATH=/data/storage STORAGE_MAX_UPLOAD_MB=50 STORAGE_HOST_PATH=./storage OLYMPUS_REPAIR_INTAKE_TOKEN= PUBLIC_REPAIR_STATUS_BASE_URL= SMTP_HOST= SMTP_PORT=587 SMTP_USERNAME= SMTP_PASSWORD= SMTP_FROM_EMAIL= SMTP_FROM_NAME=Funktechnik Schubert SMTP_USE_TLS=true LEXWARE_ENABLED=false LEXWARE_API_BASE_URL=https://api.lexware.io LEXWARE_API_KEY= ``` `PUBLIC_REPAIR_STATUS_BASE_URL` und die SMTP-Werte sind ab v0.8.4 Fallbacks. Bevorzugt wird die Admin-Konfiguration in Olympus unter `/settings`. Fuer Apple Mail/iCloud gilt: `smtp.mail.me.com`, Port `587`, TLS/STARTTLS aktiv, Benutzername = vollstaendige Mailadresse, Passwort = app-spezifisches Passwort. `LEXWARE_*` ist ab v0.8.9 nur ein Env-Fallback. Bevorzugt wird die Lexware-Konfiguration im Adminbereich unter `/settings -> Lexware Office`. Der API-Key darf nicht ins Git und wird nie an Athena zurueckgegeben. Wenn `SECRET_KEY` Sonderzeichen wie `$` enthaelt, den Wert in der Shell oder Compose-Umgebung korrekt quoten. Secrets gehoeren nicht ins Git. ## Docker Netzwerk Das gemeinsame Compose-File nutzt ein externes Docker-Netzwerk: ```bash docker network create olympus-network ``` Wenn das Netzwerk bereits existiert, meldet Docker das nur als Hinweis. ## Docker Compose Start ```bash docker compose build docker compose up -d ``` Hermes ist im gemeinsamen Stack nur intern im Docker-Netzwerk erreichbar. Athena ist lokal ueber den Browser erreichbar: - Athena: `http://localhost:3001` - Hermes intern: `http://hermes:8000` Der Browser spricht nicht direkt mit Hermes. ## Migrationen Migrationen ausfuehren: ```bash scripts/migrate.sh ``` Alternativ lokal im Backend: ```bash cd backend/hermes uv run alembic upgrade head ``` ## Initial Admin Fuer neue Installationen ohne aktive Benutzer kann Hermes beim Startup einen initialen Admin anlegen. ```env INITIAL_ADMIN_USERNAME=admin INITIAL_ADMIN_EMAIL=admin@example.local INITIAL_ADMIN_PASSWORD= INITIAL_ADMIN_FIRST_NAME= INITIAL_ADMIN_LAST_NAME= ``` Diese Werte nur lokal oder sicher auf dem Zielsystem setzen. Nach dem ersten produktiven Login sollte das Passwort geaendert und die Bootstrap-Variablen wieder entfernt werden. ## Login Nach Start und Migration: 1. Browser auf `http://localhost:3001` oeffnen. 2. Mit dem initialen Admin oder einem bestehenden Benutzer anmelden. 3. Athena setzt das HttpOnly-Cookie. Hermes setzt keine Browser-Cookies. ## Storage Neue Dateiablagen laufen ueber das Storage Framework. Lokaler Standard: ```env STORAGE_HOST_PATH=./storage STORAGE_BASE_PATH=/data/storage ``` VPS-Empfehlung: ```env STORAGE_HOST_PATH=/opt/olympus-storage STORAGE_BASE_PATH=/data/storage ``` Bestehende Knowledge-Dateien aus alten Setups unter `/data/knowledge` werden nicht automatisch verschoben. Vor einer manuellen Migration immer Backup erstellen. ## Backup und Restore Ab v0.9.1 nutzt Olympus ein serverseitiges Backup-Modul. Ablage: - Hermes schreibt Backups nach `${STORAGE_BASE_PATH}/backups` - Im lokalen Standard entspricht das `${STORAGE_HOST_PATH}/backups` - Backup-Dateien gehoeren nie ins Git Inhalt eines Backups: - `manifest.json` - `database.dump` - `storage/` Athena stellt dafuer ausschliesslich Same-Origin-BFF-Routen bereit: - `GET /api/backups` - `POST /api/backups/create` - `GET /api/backups/[filename]/download` - `POST /api/backups/[filename]/validate` - `POST /api/backups/[filename]/restore` - `DELETE /api/backups/[filename]/delete` Hermes nutzt intern `pg_dump` im Custom-Format. Deshalb muss im Hermes-Container `postgresql-client` verfuegbar sein. Automatischer Restore ist in v0.9.1 absichtlich deaktiviert. Vor jedem produktiven Restore gilt: 1. Backup validieren. 2. Sicherheitsbestaetigung pruefen. 3. Restore ueber `scripts/restore.sh ` ausfuehren. 4. Ergebnis und Audit Logs kontrollieren. Empfehlung fuer den Betrieb: - Backups regelmaessig extern von `${STORAGE_HOST_PATH}/backups` sichern. - Backup-Dateien vor Offsite-Kopie verschluesseln. - Restore nur in Wartungsfenstern ausfuehren. ## Knowledge Workflow Die Wissensdatenbank folgt lokal und produktiv diesem Ablauf: ```text Hersteller -> Gerät -> Dokument -> Notiz/Reparaturhinweis ``` Hermes legt beim Startup Standard-Hersteller an, wenn sie noch fehlen. Danach koennen Geraete angelegt werden. Dokumentuploads sind erst sinnvoll, wenn Hersteller und Geraet vorhanden sind; Athena blockiert unvollstaendige Uploads direkt im Formular. ## Reparaturmanagement Das Reparaturmodul ist ab v0.8.0 aktiv. Lokaler Ablauf: ```bash cd backend/hermes SECRET_KEY=local-check uv run alembic upgrade head ``` Athena erreicht Reparaturen ausschliesslich ueber BFF-Routen: - `/api/repairs` - `/api/repairs/[id]` - `/api/repairs/[id]/documents` - `/api/repairs/[id]/documents/upload` - `/api/repairs/[id]/documents/[documentId]` - `/api/repairs/[id]/documents/[documentId]/download` - `/api/repairs/[id]/status` - `/api/repairs/[id]/history` - `/api/repairs/[id]/public-link` - `/api/repairs/[id]/notifications` - `/api/repairs/[id]/send-status-mail` Hermes stellt zusaetzlich `POST /public/repair-intake` fuer die spaetere Website-Anbindung bereit. Der Endpunkt ist fuer Server-zu-Server-Kommunikation gedacht und erwartet `X-Olympus-Intake-Token`. Der Token wird ueber `OLYMPUS_REPAIR_INTAKE_TOKEN` gesetzt und darf nicht im Browser verwendet werden. Ab v0.8.1 zeigt Athena deutsche Statuslabels, waehrend die API-Statuscodes englisch und stabil bleiben. Statuswechsel werden als Timeline mit Benutzer, Datum und Notiz angezeigt. Statuslink-Konzept: - Interne Verwaltung ueber `GET|POST|DELETE /repairs/{id}/public-link`. - RBAC-Permission: `repairs.public_link.manage`. - Tokens sind lang, zufaellig und werden nur gehasht gespeichert. - Der Klartexttoken wird nur einmal bei Erstellung zurueckgegeben. - `PUBLIC_REPAIR_STATUS_BASE_URL` kann auf die Website-Route zeigen, z. B. `https://test.funktechnik-schubert.de/status`. - Ab v0.8.4 kann die Basis-URL im Adminbereich unter `/settings` gepflegt werden; die Env Var bleibt Fallback. - Oeffentliche Statusdaten kommen spaeter ueber `GET /public/repairs/status/{token}`. - Die Antwort enthaelt keine Kundendaten, keine internen Notizen und keine nicht freigegebenen Diagnosen. ## Lexware Office Foundation Ab v0.8.9 ist eine Lexware-Office-Grundlage vorbereitet. Rollenverteilung: - Olympus bleibt Werkstatt-ERP und verwaltet Kunden-, Reparatur-, Lager- und KV-Daten. - Lexware Office bleibt fuehrend fuer Buchhaltung, Rechnungen, Steuer, DATEV und EÜR. Konfiguration: - Adminbereich: `/settings -> Lexware Office` - Hermes-Endpunkte: `GET|PUT /lexware/settings`, `POST /lexware/test-connection` - Athena-BFF: `/api/lexware/settings`, `/api/lexware/test-connection` - Env-Fallback: `LEXWARE_ENABLED`, `LEXWARE_API_BASE_URL`, `LEXWARE_API_KEY` Der Verbindungstest nutzt serverseitig `GET {LEXWARE_API_BASE_URL}/v1/profile` mit Bearer API-Key. Browser rufen weder Hermes noch Lexware direkt auf. Freigegebene Kostenvoranschlaege koennen manuell fuer Lexware vorbereitet werden: ```text POST /api/repairs/[id]/estimates/[estimateId]/lexware/prepare-invoice ``` v0.8.9 erstellt noch keine echte Rechnung automatisch. Die Aktion erzeugt eine validierte Payload-Zusammenfassung, Mapping-Informationen und einen `lexware_sync_records`-Eintrag. Ab dem Buchhaltungsworkflow wird die UI-Aktion neutral als `In Buchhaltung übernehmen` gefuehrt. Der Benutzer kopiert Kundendaten und Positionen in Lexware Office, sevdesk oder eine andere Buchhaltungssoftware und markiert die Vorbereitung danach als `transferred`. Optional kann eine Buchhaltungsnotiz wie `Lexware RG-2026-154` gespeichert werden. Exportstatus: - `prepared` - `transferred` - `booked` - `cancelled` Benachrichtigungen: - Vorlagen liegen in `backend/hermes/app/services/repair_notification_service.py`. - `repair_notification_events` dokumentiert jeden Versandversuch. - Beim Statuswechsel wird automatisch eine Statusmail verarbeitet. - Ohne SMTP-Konfiguration bleibt der Statuswechsel erfolgreich; der Versandversuch wird als `skipped` dokumentiert. - SMTP wird bevorzugt ueber `/settings` konfiguriert. `SMTP_HOST`, `SMTP_PORT`, `SMTP_USERNAME`, `SMTP_PASSWORD`, `SMTP_FROM_EMAIL`, `SMTP_FROM_NAME` und `SMTP_USE_TLS` bleiben als Env-Fallback erhalten. - `SMTP_PASSWORD` wird nicht an Athena zurueckgegeben und gehoert nie ins Git oder in Logs. - Verschluesselung at rest ist fuer v0.8.x vorbereitet/geplant; bis dahin bleibt das Passwort serverseitig in `system_settings` und wird in Responses/Audits maskiert. Reparaturdokumente: - Ab v0.8.5 koennen Dokumente und Bilder direkt an Reparaturen gepflegt werden. - Hermes speichert Uploads ueber `StorageService` unter `repairs//documents`. - Erlaubte Dateitypen: JPG, PNG, WEBP und PDF. - Metadaten liegen in `repair_documents`; Dateiinhalte liegen nie im Git oder in `public`. - `visibility` ist mit `internal` und `customer` vorbereitet. In v0.8.5 gibt es noch keine oeffentliche Kundenanzeige fuer diese Dateien. - PDF-Dateien koennen inline oder als Download ueber Athena-BFF geoeffnet werden; ein vollstaendiger PDF-Viewer ist ein Folgefeature. Kostenvoranschlaege: - Ab v0.8.6 koennen KVs direkt auf der Reparaturdetailseite erstellt, bearbeitet, gesendet, storniert und geloescht werden. - Athena nutzt ausschliesslich BFF-Routen unter `/api/repairs/[id]/estimates`. - Hermes berechnet alle Summen serverseitig. Client-Summen sind nur Vorschau. - Nummernformat: `KV-000001`. - Der Versand nutzt die bestehende SMTP-Konfiguration aus `/settings` mit Env-Fallback. - Der Versand erzeugt/erneuert einen sicheren Public-Statuslink und sendet ihn an `customer_email`. - `GET /public/repairs/status/{token}` liefert aktive/gesendete KV-Daten ohne interne Notizen. - Public-Entscheidungen laufen ohne Kundenlogin ueber: - `POST /public/repairs/status/{token}/estimate/approve` - `POST /public/repairs/status/{token}/estimate/decline` - `POST /public/repairs/status/{token}/estimate/question` - Die oeffentliche Website zeigt diese Daten erst nach einer spaeteren Website-Version an. Olympus stellt die API dafuer bereit. - PDF-Erzeugung, Lexoffice und Rechnungen sind Folgefeatures. ## Lager / Ersatzteile Das Lagermodul ist ab v0.8.7 aktiv. Migration lokal ausfuehren: ```bash cd backend/hermes SECRET_KEY=local-check uv run alembic upgrade head ``` Athena erreicht Lagerdaten ausschliesslich ueber BFF-Routen: - `/api/inventory/items` - `/api/inventory/items/search` - `/api/inventory/items/[id]` - `/api/inventory/items/[id]/stock/adjust` - `/api/inventory/items/[id]/stock/reserve` - `/api/inventory/items/[id]/stock/release` - `/api/inventory/items/[id]/stock/consume` - `/api/inventory/items/[id]/movements` - `/api/inventory/categories` - `/api/inventory/categories/[id]` - `/api/inventory/locations` - `/api/inventory/locations/[id]` - `/api/inventory/suppliers` - `/api/inventory/suppliers/[id]` Hermes-Endpunkte liegen unter `/inventory/...` und sind mit `inventory.*` Permissions geschuetzt. Bestandslogik: - SKU optional; bei leerer SKU erzeugt Hermes `ET--000001`. - `quantity_available = quantity_on_hand - quantity_reserved`. - Bestandsanpassungen, Reservierungen, Freigaben und Verbrauch erzeugen `inventory_stock_movements`. - Artikel mit Bewegungen werden deaktiviert statt hart geloescht. - Preise werden intern in cents gespeichert; Athena akzeptiert deutsche Euro-Eingaben wie `1`, `1,50` und `1.50`. KV-Integration ab v0.8.8: - Lagerartikel koennen im KV-Dialog gesucht und als Position uebernommen werden. - Hermes uebernimmt Verkaufspreis, Einheit, Artikelname, SKU und Hersteller serverseitig. - `repair_estimate_items` speichert Snapshot-Felder, damit spaetere Lageraenderungen alte KVs nicht veraendern. - Nur gesendete KVs reservieren Bestand. - Ablehnung, Storno und Loeschung eines gesendeten KV geben Reservierungen frei. - Freigegebene KVs behalten die Reservierung. - Automatischer Verbrauch beim Reparaturabschluss ist vorbereitet, aber noch nicht aktiv. Folgefeatures: - CSV-Template, Import/Export und Barcode-/QR-Funktionen bleiben vorbereitet, sind aber in v0.8.8 nicht aktiv. Vorbereitete Website-/Portal-Routen fuer spaeter: - `/status/` - `/portal/login` ## Typische Fehler Hermes restartet wegen fehlender Migration: ```bash scripts/migrate.sh docker compose restart hermes ``` `SECRET_KEY` mit `$` wird falsch interpretiert: - Wert in `.env` korrekt escapen oder quoten. - Keine Secrets in Commit oder Logs schreiben. Docker Container Name Conflict: ```bash docker compose down docker ps -a ``` Danach blockierenden Altcontainer gezielt entfernen, wenn er wirklich nicht mehr gebraucht wird. External network fehlt: ```bash docker network create olympus-network ``` DB leer oder Admin fehlt: - `INITIAL_ADMIN_*` Werte setzen. - `scripts/migrate.sh` ausfuehren. - `docker compose restart hermes`. Athena nicht erreichbar: - `docker compose ps` pruefen. - Port `3001` auf dem Rechner pruefen. - `scripts/healthcheck.sh` ausfuehren. ## MacBook und Mac mini parallel Empfehlung: - `.env` pro Rechner lokal pflegen und nicht committen. - `STORAGE_HOST_PATH` pro Rechner bewusst setzen. - Datenbank- und Storage-Backups nicht ungeprueft zwischen Rechnern ueberschreiben. - Vor Branch-Wechseln Migrationen pruefen. - Bei paralleler Arbeit keine Docker-Volumes loeschen, solange ungesicherte Uploads existieren. ## Qualitaetschecks ```bash python3 -m compileall backend/hermes/app cd frontend/athena npm run lint npx next build --webpack ``` Skripte pruefen: ```bash bash -n scripts/*.sh ```