369 lines
12 KiB
Markdown
369 lines
12 KiB
Markdown
# 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 <repository-url> 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=<lokales-passwort>
|
|
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.
|
|
|
|
## 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.
|
|
|
|
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/<repair_id>/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<jahr>-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-<jahr>-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/<token>`
|
|
- `/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
|
|
```
|