← Zurück zur Produktseite

Logikpläne & Systemarchitektur

173 Swift-Dateien. 13 Architektur-Ebenen. 59 SwiftUI-Views. Hier ist der komplette Bauplan.

173Swift-Dateien
13Architektur-Ebenen
59SwiftUI Views
8Kernel-Entitäten
Event Sourcing MUMPS-Kernel SHA-256 Hash-Chain Offline-First CloudKit Sync

System-Übersicht

Die wichtigsten Kennzahlen und das Gesamtbild der App-Architektur.

Views

59
SwiftUI Screens & Komponenten

Kernel-Entitäten

8
User, Task, Event, Einsatz, Schritt, Zuordnung, Product, Brigade

Rollen

4
Mitarbeiter → Schichtleiter → Dispatcher → Admin

PRP-Programme

10
Allergen, Reinigung, Schädling, Temperatur, Lieferant, …

Gesamtarchitektur — Schichtenmodell

graph TB subgraph UI["UI-Schicht (59 Views)"] direction LR Login["LoginView"] Root["RootTabView"] Dash["Dashboard"] Events["Event-Kalender"] Crew["Crew-Planung"] Scan["Vision-Scanner"] Knowledge["Wissens-Hub"] Audit["Audit-Hub"] Settings["Einstellungen"] end subgraph KERNEL["TheBrain — MUMPS-Kernel"] direction LR RAM["In-Memory Store"] Meier["Meier-Score"] Rules["Regelprüfung"] end subgraph ES["Event Sourcing"] direction LR Journal["Journal (append-only)"] Replayer["Replayer"] Diff["StateDiff"] end subgraph PERSIST["Persistenz"] direction LR SwiftData["SwiftData"] CoreData["CoreData (Legacy)"] HACCP["HACCP Records"] end subgraph SECURITY["Sicherheit"] direction LR AuditTrail["Audit Trail (Hash-Chain)"] Integrity["Integrity Verifier"] Auth["PIN-Auth"] end subgraph SYNC["Synchronisation"] direction LR Engine["SyncEngine"] CloudKit["CloudKit"] Conflict["Conflict Resolver"] end subgraph AI["ChefIQ"] direction LR OCR["OCR-Service"] Gemini["Google Gemini"] end subgraph EXPORT["Export"] direction LR CSV["CSV/JSON"] PDF["PDF"] Paper["Papier-Fallback"] end UI -->|"liest/schreibt"| KERNEL KERNEL -->|"protokolliert"| ES ES -->|"persistiert"| PERSIST KERNEL -->|"loggt"| SECURITY SYNC -->|"synchronisiert"| ES SYNC --> CloudKit AI -->|"erkennt"| KERNEL EXPORT -->|"exportiert"| PERSIST style UI fill:#1f3a5f,stroke:#58a6ff,color:#fff style KERNEL fill:#3b1f5e,stroke:#bc8cff,color:#fff style ES fill:#1f4f3a,stroke:#56d364,color:#fff style PERSIST fill:#4f3a1f,stroke:#d29922,color:#fff style SECURITY fill:#5f1f1f,stroke:#f85149,color:#fff style SYNC fill:#1f3a4f,stroke:#79c0ff,color:#fff style AI fill:#3a1f4f,stroke:#d2a8ff,color:#fff style EXPORT fill:#2f3a1f,stroke:#a5d6a7,color:#fff

System-Architektur

Die Event-Hierarchie und das Zusammenspiel der Komponenten.

Event → Einsatz → Schritt → Zuordnung

graph TB E["Event
z.B. Hochzeitsessen
Datum, Ort, Gäste, Menü"] E --> E1["Einsatz 1
Vorspeisen
Verantwortlich: Chef John"] E --> E2["Einsatz 2
Hauptgang
Verantwortlich: Chef James"] E --> E3["Einsatz 3
Desserts
Verantwortlich: Lisa"] E1 --> S1["Schritt 1
Garnelen vorbereiten
ANFÄNGER · 30min"] E1 --> S2["Schritt 2
Canapés anrichten
PROFI · 45min"] E2 --> S3["Schritt 3
Fleisch vorbereiten
SPEZIALIST · 60min"] E2 --> S4["Schritt 4
Sauce kochen
PROFI · 30min"] E3 --> S5["Schritt 5
Mousse zubereiten
PROFI · 40min"] S1 --> Z1["Maria
ERLEDIGT 14:30"] S2 --> Z2["Thomas
IN ARBEIT seit 14:45"] S3 --> Z3["Michael
BLOCKIERT
Lieferung fehlt"] S4 --> Z4["Sandra
OFFEN"] S5 --> Z5["Rebecca
OFFEN"] style E fill:#1f6feb,stroke:#58a6ff,color:#fff style E1 fill:#238636,stroke:#56d364,color:#fff style E2 fill:#238636,stroke:#56d364,color:#fff style E3 fill:#238636,stroke:#56d364,color:#fff style S1 fill:#30363d,stroke:#8b949e,color:#c9d1d9 style S2 fill:#30363d,stroke:#8b949e,color:#c9d1d9 style S3 fill:#30363d,stroke:#8b949e,color:#c9d1d9 style S4 fill:#30363d,stroke:#8b949e,color:#c9d1d9 style S5 fill:#30363d,stroke:#8b949e,color:#c9d1d9 style Z1 fill:#238636,stroke:#56d364,color:#fff style Z2 fill:#1f6feb,stroke:#58a6ff,color:#fff style Z3 fill:#da3633,stroke:#f85149,color:#fff style Z4 fill:#30363d,stroke:#6e7681,color:#8b949e style Z5 fill:#30363d,stroke:#6e7681,color:#8b949e

Meier-Score — Kognitive Belastungsberechnung

flowchart LR A["Offene Tasks
sammeln"] --> B["Gewicht je Task
addieren"] B --> C["Ermüdungsfaktor
1.0 + (Stunden/10)"] C --> D["Kapazität berechnen
Staff x 20"] D --> ECalc["Score berechnen
(Last/Kapazität)
x Ermüdung x 100
"] ECalc --> F{Score-Wert?} F -->|"0-30"| G["Normal
Alles im grünen Bereich"] F -->|"30-70"| H["Moderat
Erhöhte Aufmerksamkeit"] F -->|"70-80"| I["Hoch
Ermüdung setzt ein"] F -->|"80-100"| J["Kritisch
Fehlerrisiko!
+ Jitter-Modus"] style G fill:#238636,stroke:#56d364,color:#fff style H fill:#9e6a03,stroke:#d29922,color:#fff style I fill:#bd561d,stroke:#f0883e,color:#fff style J fill:#da3633,stroke:#f85149,color:#fff

Authentifizierung & Rollensystem

PIN-basierte Anmeldung mit 4-stufiger Rollenhierarchie.

Login-Flow

flowchart TD Start(["App-Start"]) --> Check{"Eingeloggt?"} Check -->|"Nein"| Login["LoginView
Mitarbeiter-Auswahl"] Check -->|"Ja"| Root["RootTabView"] Login --> Select["Mitarbeiter
auswählen"] Select --> HasPIN{"PIN
eingerichtet?"} HasPIN -->|"Nein"| Setup["SetupPINSheet
4-stellige PIN erstellen"] Setup --> SavePIN["PIN hashen
und speichern"] SavePIN --> Enter HasPIN -->|"Ja"| Enter["PIN eingeben"] Enter --> Validate{"PIN
korrekt?"} Validate -->|"Nein"| Error["Fehler anzeigen"] Error --> Enter Validate -->|"Ja"| Session["Session starten"] Session --> Brain["TheBrain aktualisieren
^NAV.ACTIVE_USER
^NAV.ACTIVE_ROLE"] Brain --> AuditLog["AuditTrail:
USER_LOGIN protokollieren"] AuditLog --> Root Root --> Logout["Logout"] Logout --> Kill["TheBrain:
^NAV.ACTIVE_USER löschen"] Kill --> AuditOut["AuditTrail:
USER_LOGOUT"] AuditOut --> Login style Start fill:#8957e5,stroke:#bc8cff,color:#fff style Root fill:#238636,stroke:#56d364,color:#fff style Error fill:#da3633,stroke:#f85149,color:#fff style Session fill:#1f6feb,stroke:#58a6ff,color:#fff

Rollen-Hierarchie & Berechtigungen

graph LR subgraph Rollen["Rollenhierarchie (aufsteigend)"] M["Mitarbeiter
Level 1"] --> SL["Schichtleiter
Level 2"] SL --> D["Dispatcher
Level 3"] D --> A["Admin
Level 4"] end subgraph Rechte_M["Mitarbeiter-Rechte"] M1["Eigene Aufgaben sehen"] M2["Tasks starten/beenden"] M3["Tasks blockieren"] end subgraph Rechte_SL["Schichtleiter-Rechte"] SL1["+ Einsätze erstellen"] SL2["+ Tasks umverteilen"] end subgraph Rechte_D["Dispatcher-Rechte"] D1["+ Events erstellen"] D2["+ Personal zuweisen"] D3["+ Eskalation auslösen"] end subgraph Rechte_A["Admin-Rechte"] A1["+ Rollen verwalten"] A2["+ Systemkonfiguration"] A3["+ HACCP-Export versiegeln"] end M -.-> Rechte_M SL -.-> Rechte_SL D -.-> Rechte_D A -.-> Rechte_A style M fill:#30363d,stroke:#8b949e,color:#c9d1d9 style SL fill:#0d419d,stroke:#58a6ff,color:#fff style D fill:#8957e5,stroke:#bc8cff,color:#fff style A fill:#da3633,stroke:#f85149,color:#fff

Datenmodell

Dual-Layer: MUMPS-Globals im TheBrain-Kernel + SwiftData/CoreData-Persistenz.

Kernel-Entitäten (TheBrain — In-Memory)

erDiagram USER ||--o{ ZUORDNUNG : "ist zugeordnet" USER ||--o{ EINSATZ : "ist verantwortlich" EVENT ||--o{ EINSATZ : "enthält" EVENT ||--o{ TASK : "hat Jobs" EINSATZ ||--o{ SCHRITT : "enthält" SCHRITT ||--o{ ZUORDNUNG : "hat Zuweisungen" TASK }o--|| USER : "zugewiesen an" PRODUCT ||--o| SUPPLIER : "bezogen von" USER { string id PK string name string rolle boolean aktiv timestamp loginTime } EVENT { string id PK string title date date string location int guests string status } EINSATZ { string id PK string name string event_id FK string verantwortlicher_id FK string status } SCHRITT { string id PK string bezeichnung string einsatz FK string anweisung string status int zeitvorgabe string level } ZUORDNUNG { string id PK string schritt FK string employee FK string status timestamp started_at timestamp completed_at } TASK { string id PK string title string status int weight string event_id FK string assigned_to FK } PRODUCT { string id PK string name string allergens date expiry_date } SUPPLIER { string id PK string name string contact }

Persistenz-Schicht (SwiftData / CoreData)

erDiagram iMOPSEvent { UUID id PK Date ts String eventType String path String value String userId String deviceId Int sequenceNumber } AuditLogEntry { UUID id PK Date timestamp String action String actorType String objectType String result String prevHash String chainHash String role } HACCPRecord { UUID id PK String key String value Date createdAt String createdBy String signature boolean isArchived } SyncMetadata { UUID id PK Date lastSyncTime String deviceId Data recordToken Int conflictCount }

Task-Lifecycle

Status-Maschinen für Jobs (Aufträge) und Arbeitsschritte.

Auftrag (Job) — Status-Maschine

stateDiagram-v2 [*] --> Offen : Job erstellt Offen --> InArbeit : START InArbeit --> Pausiert : PAUSE Pausiert --> InArbeit : RESUME InArbeit --> Fertig : COMPLETE Pausiert --> Fertig : COMPLETE Fertig --> [*] : Terminal

Zuordnung (Employee Assignment) — Status-Maschine

stateDiagram-v2 [*] --> OFFEN : Zuordnung erstellt OFFEN --> IN_ARBEIT : Mitarbeiter startet IN_ARBEIT --> BLOCKIERT : Problem gemeldet BLOCKIERT --> IN_ARBEIT : Problem gelöst IN_ARBEIT --> ERLEDIGT : Schritt abgeschlossen BLOCKIERT --> ESKALIERT : Eskalation durch Dispatcher

Einsatz — Status-Maschine

stateDiagram-v2 [*] --> GEPLANT : Einsatz erstellt GEPLANT --> LAUFEND : Erster Schritt gestartet LAUFEND --> BLOCKIERT : Kritischer Schritt blockiert BLOCKIERT --> LAUFEND : Blocker gelöst LAUFEND --> FERTIG : Alle Schritte erledigt

Eskalations-Flow

flowchart TD Block["Mitarbeiter meldet
Blockierung"] --> Reason["Grund eingeben
z.B. Lieferung fehlt"] Reason --> Status["Status BLOCKIERT
in TheBrain"] Status --> AuditB["AuditTrail:
TASK_BLOCKED"] AuditB --> Dispatcher["Dispatcher sieht
Blocker im Dashboard"] Dispatcher --> Decision{"Entscheidung?"} Decision -->|"Lösen"| Resolve["Problem lösen
Status IN_ARBEIT"] Decision -->|"Umverteilen"| Reassign["Anderen MA zuweisen
neue Zuordnung"] Decision -->|"Eskalieren"| Escalate["An Schichtleiter/
Admin eskalieren"] Resolve --> AuditR["AuditTrail:
BLOCKER_RESOLVED"] Reassign --> AuditA["AuditTrail:
TASK_REASSIGNED"] Escalate --> AuditE["AuditTrail:
ESCALATION_CREATED"] style Block fill:#da3633,stroke:#f85149,color:#fff style Resolve fill:#238636,stroke:#56d364,color:#fff

Event Sourcing & Crash Recovery

Jede Zustandsänderung wird als unveränderliches Event im Journal protokolliert.

Event Sourcing — Schreibpfad

sequenceDiagram participant UI as UI participant Brain as TheBrain participant Journal as Journal participant SwiftData as SwiftData participant Audit as AuditTrail UI->>Brain: set("^TASK.001.STATUS", "OPEN") Brain->>Brain: RAM-Store aktualisieren Brain->>Journal: Event erstellen Note over Journal: type: .set
path: ^TASK.001.STATUS
value: S:OPEN
seq: 42 Journal->>SwiftData: Persistieren Brain->>Audit: log(action: "SET", ...) Note over Audit: Hash-Chain:
chainHash = SHA-256(
prevHash + data) Audit->>SwiftData: Persistieren Brain-->>UI: @Observable Update

App-Boot & Recovery

flowchart TD Start(["App-Start"]) --> Container["ModelContainer
initialisieren"] Container --> Configure["brain.configure()
Journal + AuditTrail"] Configure --> Fetch["Journal.fetchAll()
Alle Events laden"] Fetch --> Rebuild["brain.rebuildFromJournal()"] Rebuild --> Loop{"Für jedes Event"} Loop -->|"set"| Set["RAM path = value"] Loop -->|"kill"| Kill["RAM path löschen"] Loop -->|"killTree"| KillTree["Alle mit Prefix löschen"] Loop -->|"navGoto"| Nav["Navigations-Kontext"] Set --> Loop Kill --> Loop KillTree --> Loop Nav --> Loop Loop -->|"fertig"| Migrate["SchemaMigrator
migrateIfNeeded()"] Migrate --> Validate["validateBootState()
Lücken prüfen"] Validate --> Gap{"Lücken
gefunden?"} Gap -->|"Ja"| Warn["Warnung loggen
Datenverlust möglich"] Gap -->|"Nein"| OK["Zustand intakt"] Warn --> Purge OK --> Purge Purge["Alte Events purgen
> 90 Tage"] --> Sync["SyncEngine starten"] Sync --> WarmUp["BootLoader.warmUp()
Aktive Daten laden"] WarmUp --> Ready(["App bereit"]) style Start fill:#8957e5,stroke:#bc8cff,color:#fff style Ready fill:#238636,stroke:#56d364,color:#fff style Warn fill:#d29922,stroke:#e3b341,color:#000

Synchronisation & Audit-Integrität

CloudKit-basierte Multi-Device-Sync mit Blockchain-artiger Audit-Kette.

Multi-Device Sync

sequenceDiagram participant A as Gerät A participant Cloud as CloudKit participant B as Gerät B A->>A: Task Status ändern A->>Cloud: Journal-Events hochladen Cloud->>B: Push-Notification B->>Cloud: Neue Events abrufen B->>B: MergeReplayer ausführen Note over A,B: Konflikt-Szenario A->>Cloud: ^TASK.001.STATUS = "IN_ARBEIT" (14:00) B->>Cloud: ^TASK.001.STATUS = "BLOCKIERT" (14:01) Cloud->>Cloud: Konflikt erkannt! Cloud->>A: ConflictResolver Cloud->>B: ConflictResolver Note over A,B: Last-Write-Wins:
B gewinnt (14:01 > 14:00)
Status = BLOCKIERT A->>A: TheBrain aktualisieren B->>B: TheBrain aktualisieren Note over A,B: Beide Geräte konsistent

Audit-Trail Hash-Chain

flowchart LR E1["Entry 1
LOGIN
hash: abc..."] --> E2["Entry 2
SET
prevHash: abc...
hash: def..."] E2 --> E3["Entry 3
SET
prevHash: def...
hash: ghi..."] E3 --> E4["Entry 4
EXPORT
prevHash: ghi...
hash: jkl..."] E4 --> Verify{"Integritäts-
prüfung"} Verify -->|"Alle Hashes stimmen"| OK["Kette intakt"] Verify -->|"Hash-Mismatch"| Alert["Manipulation!
Notfall-Modus"] style E1 fill:#1f6feb,stroke:#58a6ff,color:#fff style E2 fill:#1f6feb,stroke:#58a6ff,color:#fff style E3 fill:#1f6feb,stroke:#58a6ff,color:#fff style E4 fill:#1f6feb,stroke:#58a6ff,color:#fff style OK fill:#238636,stroke:#56d364,color:#fff style Alert fill:#da3633,stroke:#f85149,color:#fff

Notfall-Modus

flowchart TD Trigger{"Auslöser"} Trigger -->|"Integritäts-
verletzung"| NF Trigger -->|"IT-Ausfall"| NF Trigger -->|"Manuell
aktiviert"| NF NF["NotfallModusView
(Vollbild)"] NF --> Contact["Notfall-Kontakte
anzeigen"] NF --> PaperF["Papier-Fallback
generieren"] NF --> Manual["Manuelle
Dokumentation"] Manual --> Resolve["Problem
behoben"] Resolve --> Deactivate["Notfall-Modus
deaktivieren"] Deactivate --> AuditLog["AuditTrail:
NOTFALL_RESOLVED"] style NF fill:#da3633,stroke:#f85149,color:#fff style Resolve fill:#238636,stroke:#56d364,color:#fff