Add facilities, contracts, orders, value lists, audit log, and desktop app modules
Extends omsorgCore with full CRUD for Facility/Contract/Order plus configurable value lists and an audit trail, and wires the omsorgapp frontend up to the new facilities, settings, and audit-log modules; includes a sidebar active-nav-item highlight. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
ee74ed65f5
commit
e9e96a57dc
+10
-8
@@ -5,22 +5,24 @@ Gilt zusätzlich zur Root-`CLAUDE.md`. Dies ist das Electron/React-Desktop-Proje
|
||||
## Stack & Struktur
|
||||
|
||||
- **Electron** (Hauptprozess) + **React 18** + **Vite** (Renderer), reines JSX (kein TS trotz `typescript`-Dependency — bisher ungenutzt).
|
||||
- `electron/main.cjs` — Electron-Hauptprozess. Legt beim Start `~/Documents/Omsorg Business Controls Pro/` mit Unterordnern (`database/`, `documents/employees`, `documents/customers`, `backups/`) an. Aktuell einzige lokale Datenhaltung (für die Fachmodule, nicht für Auth): **eine lokale JSON-Datei** (`database/omsorg-local-db.json`), gelesen/geschrieben über IPC-Handler (`db:get`, `db:set`, `app:paths`, `app:openRoot`, `backup:create`).
|
||||
- `electron/main.cjs` — Electron-Hauptprozess. **Keine lokale Fachdaten-Persistenz** — die frühere lokale JSON-Datei (`database/omsorg-local-db.json`, samt IPC-Handlern `db:get`/`db:set`/`app:paths`/`app:openRoot`/`backup:create`) ist entfernt; sie wurde ohnehin nur noch von der toten Prototyp-Variante `src/main.legacy.jsx` genutzt (ebenfalls entfernt, war seit dem Umstieg auf die echte App nicht mehr in `index.html` verlinkt). Alle Fachdaten kommen ausschließlich über `electron/backend/*Client.cjs` aus `omsorgCore`.
|
||||
- `electron/backend/` — Adapterschicht zu `omsorgCore` (HTTP), ausschließlich im Main-Prozess genutzt: `config.cjs` (einzige Stelle mit der Backend-URL, Default `http://localhost:5245`, überschreibbar per `OMSORG_CORE_URL`), `httpClient.cjs` (einzige Stelle mit `fetch`/Auth-Header), `authClient.cjs` (`login`/`refresh`/`logout` gegen `/api/auth/*`), `employeesClient.cjs` (`list`/`get`/`create`/`update` gegen `/api/employees`, kein `delete` da der Endpunkt in `omsorgCore` fehlt). Für künftige Ressourcen (Einrichtungen, ...) entsteht nach demselben Muster je eine eigene `<kategorie>Client.cjs`-Datei, analog zu den Controllern in `omsorgCore` — siehe `main.cjs`s `api:get`/`api:post`-Proxy für Ressourcen ohne eigene Client-Datei.
|
||||
- **Login + Session:** `main.cjs` hält den Access-Token nur im Speicher, verschlüsselt den Refresh-Token via `safeStorage` und speichert ihn unter `app.getPath('userData')/session.enc`. Silent Refresh läuft per Timer (kurz vor Ablauf) und reaktiv bei 401 (z. B. nach Laptop-Standby). IPC-Handler: `auth:login`, `auth:logout`, `auth:getSession`, `api:get`/`api:post` (authentifizierter Proxy). Kein Token verlässt je den Main-Prozess in Richtung Renderer.
|
||||
- `electron/preload.cjs` — exponiert `window.omsorg` (contextBridge) mit `getDb`, `setDb`, `paths`, `openRoot`, `createBackup`, `auth.{login,logout,getSession,onSessionChanged}`, `api.{get,post}`. Renderer darf nie direkt auf Node/`fs` zugreifen — immer über diese Brücke.
|
||||
- `electron/preload.cjs` — exponiert `window.omsorg` (contextBridge) mit `auth.{login,logout,getSession,onSessionChanged}`, `api.{get,post}` und den ressourcenspezifischen Namespaces (`employees`, `facilities`, `facilityContacts`, `users`, `roles`, `auditLog`, `valueLists`). Renderer darf nie direkt auf Node/`fs` zugreifen — immer über diese Brücke.
|
||||
- `src/main.jsx` — Renderer-Einstiegspunkt, wrappt `App` in `AuthProvider` (`src/app/AuthContext.jsx`) und rendert in `#root`.
|
||||
- `src/app/AuthContext.jsx` — React-Context um `window.omsorg.auth`, stellt `useAuth()` mit `{ isAuthenticated, user, isLoading, login, logout }` bereit.
|
||||
- `src/app/app.jsx` — gated zuerst auf Auth (`isLoading` → Ladehinweis, `!isAuthenticated` → `src/modules/auth/LoginPage.jsx`), danach Top-Level-Router: hält `activePage` als lokalen State (kein Routing-Framework), switcht zwischen Modulen. Noch nicht implementierte Module rendern `PlaceholderPage`.
|
||||
- `src/layouts/AppLayout.jsx` — Grundlayout: `Sidebar` + `Header` + `main.page-content`.
|
||||
- `src/components/` — geteilte UI: `Sidebar`, `Header`, `OmsorgCard`, und `components/ui/` (`OmsorgButton`, `OmsorgBadge`, `OmsorgStatCard`).
|
||||
- `src/modules/<modulname>/` — ein Ordner pro Fachmodul, z. B. `modules/home/` (HomePage, HomeStats, ContractWidget), `modules/employees/` (EmployeesPage, EmployeeDetailPanel, EmployeeTabs), `modules/debug/` (`DebugSessionsPage.jsx`). Neue Module folgen diesem Muster: eigener Ordner unter `src/modules/`, Einstiegskomponente `<Modul>Page.jsx`.
|
||||
- `src/modules/<modulname>/` — ein Ordner pro Fachmodul, z. B. `modules/home/` (HomePage, HomeStats, ContractWidget), `modules/employees/` (EmployeesPage, EmployeeDetailPanel, EmployeeTabs), `modules/facilities/` (FacilitiesPage, FacilityDetailPanel, FacilityForm, FacilityContactsList/FacilityContactForm für die Ansprechpartner-Unterliste (FR-EIN-2) — Referenz war 1:1 `modules/employees/`, ohne Tabs, da noch keine weiteren Unterobjekte wie Dokumente/Verträge existieren), `modules/debug/` (`DebugSessionsPage.jsx`), `modules/settings/` (`SettingsPage.jsx`, `RolesPanel.jsx`, `RolePermissionMatrix.jsx`, `UserOverridesPanel.jsx`, `permissionOptions.js`). Neue Module folgen diesem Muster: eigener Ordner unter `src/modules/`, Einstiegskomponente `<Modul>Page.jsx`.
|
||||
- **Rollen- & Rechteverwaltung (`modules/settings/`):** Admin-UI unter dem Sidebar-Tab "Einstellungen" (`ModuleType.UserManagement`). `SettingsPage.jsx` schaltet zwischen drei Tabs: `RolesPanel.jsx` (Rollen anlegen via `window.omsorg.roles.create`, Auswahl öffnet `RolePermissionMatrix.jsx` — Checkbox-Matrix `ModuleType`×`PermissionAction`, speichert über `window.omsorg.roles.updatePermissions`), `UserOverridesPanel.jsx` (Nutzerauswahl über `window.omsorg.users.list`, individuelle `UserPermissionOverride`-Ausnahmen je Nutzer via `window.omsorg.users.{listPermissionOverrides,addPermissionOverride,deletePermissionOverride}`) und `StatusManagementPanel.jsx` ("Status-Verwaltung" — Mitarbeiterstatus, Beschäftigungsart, CRM-Status, Einrichtungstyp, Vertragstyp/-status, Auftragsstatus als admin-editierbare Auswahllisten über `window.omsorg.valueLists.*`; Löschen eines Werts wird serverseitig verweigert, solange er noch irgendwo gesetzt ist — Details: `omsorgCore/CLAUDE.md`, Abschnitt "Konfigurierbare Auswahllisten"). `ModuleType`/`PermissionAction`/`PermissionEffect`-Werte + deutsche Labels sind in `permissionOptions.js` hart codiert (kein gemeinsames Enum-Modul zwischen Backend und Frontend, analog `navPermissions.js`). Backend-Details: `omsorgCore/CLAUDE.md`, Abschnitt "Rechtesystem".
|
||||
- **Audit-Log (`modules/auditLog/AuditLogPage.jsx`):** rein lesende, paginierte Liste (`OmsorgPagination`, `PAGE_SIZE = 50`) über `window.omsorg.auditLog.list({ page, pageSize })` → `electron/backend/auditLogClient.cjs` → `GET /api/audit-log` in `omsorgCore`. Keine Bearbeiten-/Löschen-Aktionen (Audit-Einträge sind unveränderlich, es gibt serverseitig keine entsprechenden Endpoints). Im `Sidebar.jsx`-Menü nur sichtbar, wenn `hasPermission("AuditLog", "View")` (`navPermissions.js`, `NAV_MODULES["Audit-Log"] = "AuditLog"`) — per Default nur die Rolle Geschäftsführung (Backend-Details: `omsorgCore/CLAUDE.md`, Abschnitt "Audit-Log"). `ModuleType.AuditLog` ist zusätzlich in `modules/settings/permissionOptions.js`s `MODULE_OPTIONS` eingetragen, damit Geschäftsführung die Berechtigung über die Rollen-Rechte-Matrix auch anderen Rollen zuweisen kann.
|
||||
- **Debug-Sicht (`modules/debug/DebugSessionsPage.jsx`):** listet aktive Sessions (`GET /api/admin/sessions` über den generischen `api:get`-Proxy), erlaubt Einzel- und Gesamt-Widerruf (`POST /api/admin/sessions/{id}/revoke`, `POST /api/admin/sessions/revoke-all`) — invalidiert serverseitig sofort alle betroffenen Access-Tokens (Details: `omsorgCore/CLAUDE.md` Abschnitt "Session-Killswitch"). Im `Sidebar.jsx`-Menü nur sichtbar, wenn `useAuth().hasPermission("UserManagement", "View")` — dieselbe granulare Rechteprüfung, die serverseitig über `RequirePermission(ModuleType.UserManagement, ...)` auf `AdminSessionsController` erzwungen wird (kein Rollennamen-Vergleich mehr, siehe "Rechtesystem im Client" unten).
|
||||
- **Rechtesystem im Client:** Rechte kommen nicht aus dem JWT (das trägt nur `sub`/`name`/`role`/`sst`). `main.cjs` lädt nach jedem Login/Refresh zusätzlich `GET /api/auth/me` (`electron/backend/authClient.cjs#me`) und ersetzt `session.user` durch `{ username, role, permissions }` — `permissions` ist die vom Backend aufgelöste Liste aus `PermissionService.GetGrantedPermissionsAsync` (Rollen-Default + Overrides, je `{ module, action }` als String). `AuthContext.jsx` stellt darauf `hasPermission(module, action)` bereit; UI-Komponenten prüfen darüber, nie über `user.role` direkt.
|
||||
- **Verbindliche Regel — UI folgt den Rechten, für jedes Modul:** Jeder Sidebar-Tab und jede Aktion (Anlegen/Bearbeiten/Löschen/...) muss über `hasPermission(module, action)` gegated werden — das ist kein Sonderfall für Mitarbeiter, sondern das Standardmuster für jedes neue Modul (mindestens `View` fürs Sichtbarsein des Tabs, `Create`/`Edit`/... für einzelne Aktionen darin). Referenzimplementierung: `src/modules/employees/EmployeesPage.jsx` (`canCreate = hasPermission("Employees", "Create")`) und `src/modules/employees/EmployeeDetailPanel.jsx` (`canEdit = hasPermission("Employees", "Edit")`).
|
||||
- Die Zuordnung Sidebar-Tab → `ModuleType` steht zentral in `src/app/navPermissions.js` (`NAV_MODULES`) und wird sowohl von `Sidebar.jsx` (blendet nicht erlaubte Tabs aus) als auch von `app.jsx` (fällt auf `"Home"` zurück, falls der aktive Tab durch eine Rechteänderung nicht mehr erlaubt ist) genutzt — neue Zuordnungen nur dort eintragen, nicht duplizieren.
|
||||
- Aktuelles Mapping: Mitarbeiter→`Employees`, Kunden→`Facilities`, Disposition→`Orders`, Rechnungen→`Invoices`, Controlling→`Controlling`, Einstellungen→`UserManagement`, Debug→`UserManagement`. Home hat kein Modul und ist immer sichtbar. Kalkulation und Fahrzeuge sind reine `PlaceholderPage`-Stubs ohne Fachlogik und haben (noch) kein passendes `ModuleType` — bewusst ungegated, bis ein echtes Modul dahintersteht; dann Eintrag in `navPermissions.js` ergänzen (ggf. mit neuem `ModuleType`-Wert in `omsorgCore`, additiv, keine Migration nötig).
|
||||
- `src/style.css` — einziges Stylesheet, kein CSS-Framework (`style.backup.css` ist eine Sicherungskopie, keine aktive Datei).
|
||||
- Aktuelles Mapping: Mitarbeiter→`Employees`, Kunden→`Facilities`, Disposition→`Orders`, Rechnungen→`Invoices`, Controlling→`Controlling`, Einstellungen→`UserManagement`, Debug→`UserManagement`, Audit-Log→`AuditLog`. Home hat kein Modul und ist immer sichtbar. Kalkulation und Fahrzeuge sind reine `PlaceholderPage`-Stubs ohne Fachlogik und haben (noch) kein passendes `ModuleType` — bewusst ungegated, bis ein echtes Modul dahintersteht; dann Eintrag in `navPermissions.js` ergänzen (ggf. mit neuem `ModuleType`-Wert in `omsorgCore`, additiv, keine Migration nötig).
|
||||
- `src/style.css` — einziges Stylesheet, kein CSS-Framework.
|
||||
|
||||
## Wichtige Startbefehle
|
||||
|
||||
@@ -33,9 +35,9 @@ npm run start # nur Electron (erwartet gebauten dist/)
|
||||
|
||||
## Aktueller Ist-Stand (siehe auch `REQUIREMENTS.md`)
|
||||
|
||||
- Vollständig: `HomePage`, `EmployeesPage` (Grundgerüst; Daten kommen über `electron/backend/employeesClient.cjs` echt aus `omsorgCore`, keine hartcodierten Beispieldaten mehr für dieses Modul), Login-Screen + persistente Session gegen `omsorgCore`.
|
||||
- Alle anderen Menüpunkte (Kunden, Disposition, Kalkulation, Fahrzeuge, Rechnungen, Controlling, Einstellungen) sind reine `PlaceholderPage`-Platzhalter in `app.jsx`.
|
||||
- **Auth und Mitarbeiter sprechen bereits gegen `omsorgCore`** (siehe `employeesClient.cjs`, IPC-Handler `employees:list/create/update` in `main.cjs`), die übrigen Fachmodule (Kunden, ...) noch nicht — die lokale JSON-Datei bleibt für diese vorerst die Datenquelle (Übergangslösung, README: "SQLite wird später sauber über eine entkoppelte Persistenzschicht eingebaut"). Nächster Schritt: weitere Fachmodule nach und nach auf `electron/backend/<kategorie>Client.cjs` + `omsorgCore`-Endpunkte umstellen, analog zum Mitarbeiter-/Auth-Vorbild.
|
||||
- Vollständig: `HomePage`, `EmployeesPage` (Grundgerüst; Daten kommen über `electron/backend/employeesClient.cjs` echt aus `omsorgCore`, keine hartcodierten Beispieldaten mehr für dieses Modul), `FacilitiesPage` (Sidebar-Tab "Kunden", `ModuleType.Facilities`; Grundgerüst analog `EmployeesPage`, Daten über `electron/backend/facilitiesClient.cjs` echt aus `omsorgCore`; deckt Stammdaten **und** eine Ansprechpartner-Liste je Einrichtung ab (`FacilityContactsList` im `FacilityDetailPanel`, über `electron/backend/facilityContactsClient.cjs` gegen `/api/facilities/{id}/contacts`, Anlegen/Bearbeiten, kein Löschen) — CRM-Pipeline-Automatik/Konditionen aus `REQUIREMENTS.md` FR-EIN-3..5 sind noch offen), Login-Screen + persistente Session gegen `omsorgCore`, `SettingsPage` (Rollen-Rechte-Matrix + User-Permission-Overrides, siehe "Rollen- & Rechteverwaltung" oben), `AuditLogPage` (siehe "Audit-Log" oben).
|
||||
- Alle anderen Menüpunkte (Disposition, Kalkulation, Fahrzeuge, Rechnungen, Controlling) sind reine `PlaceholderPage`-Platzhalter in `app.jsx`.
|
||||
- **Auth, Mitarbeiter und Kunden/Einrichtungen sprechen bereits gegen `omsorgCore`** (siehe `employeesClient.cjs`/`facilitiesClient.cjs`, IPC-Handler `employees:list/create/update` und `facilities:list/create/update` in `main.cjs`). Die übrigen Fachmodule (Disposition, Kalkulation, Fahrzeuge, Rechnungen, Controlling) haben noch **gar keine** Datenhaltung — weder lokal noch über `omsorgCore` — sondern sind reine `PlaceholderPage`-Stubs. Nächster Schritt: weitere Fachmodule nach und nach nach demselben Muster (`electron/backend/<kategorie>Client.cjs` + `omsorgCore`-Endpunkte) umsetzen, analog zum Mitarbeiter-/Kunden-Vorbild.
|
||||
- Keine Verbindung zu `omsorgWeb`/MySQL — Mitarbeiterdaten hier sind komplett getrennt von denen in OMSORG Connect. Nicht durch neue Kopplungen/Workarounds "beheben"; die eigentliche Lösung ist die gemeinsame Datenbasis in `omsorgCore`.
|
||||
|
||||
## Konventionen
|
||||
|
||||
Reference in New Issue
Block a user