Files
omsorg/REQUIREMENTS.md
T
Felix KemmlerandClaude Sonnet 5 598dfcd38a
Docker-Images bauen und veröffentlichen / build (, omsorgCore/Dockerfile, omsorgcore) (push) Successful in 23s
Docker-Images bauen und veröffentlichen / build (VITE_OMSORG_CORE_URL=${{ vars.OMSORG_CORE_PUBLIC_URL }}, omsorgapp/Dockerfile, omsorgapp) (push) Failing after 2s
Docker-Images bauen und veröffentlichen / build (, omsorgWeb/Dockerfile, omsorgweb) (push) Failing after 39s
Migrate omsorgapp to browser SPA, add Docker/CI build setup
- omsorgapp: drop Electron, run as a plain Vite/React browser app; refresh
  token moves to an HttpOnly cookie (omsorgCore), CORS added for the new
  browser origin, document download/preview switched to Blob-based browser
  APIs.
- Add Dockerfiles for omsorgCore, omsorgapp, and omsorgWeb, a docker-compose.yml
  wiring Postgres/MySQL/all three apps together, and a Gitea Actions workflow
  that builds and pushes images to the repo's container registry on push to
  main and on version tags.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 17:42:45 +02:00

38 KiB
Raw Permalink Blame History

OMSORG Business Controls Pro — Requirements-Dokument (SRS)

Status: Entwurf 1.0 Basis: omsorg.md (Kurzvision) + omsorgapp/docs/OMSORG-BLUEPRINT.md (Vision/Architektur, verbindliche Arbeitsgrundlage) Zweck: Aus der Vision konkrete, testbare Anforderungen ableiten — Grundlage für Entwicklung, Abnahme und Tests.

Dieses Dokument dupliziert den Blueprint nicht. Es referenziert ihn ([Blueprint Kap. X]) und übersetzt ihn in nummerierte Requirements mit Akzeptanzkriterium und Ist-Status.

Status-Legende: vorhanden · 🔶 teilweise vorhanden · offen


1. Einleitung

1.1 Zweck

Dieses Dokument definiert die funktionalen und nicht-funktionalen Anforderungen an OMSORG Business Controls Pro — die Plattform, mit der Omsorg (Pflege-Zeitarbeit) ihren gesamten Arbeitsalltag abwickelt.

1.2 Geltungsbereich

Umfasst alle drei Plattform-Ebenen: OMSORG Desktop, OMSORG Connect, OMSORG Backend (Core + Engine) [Blueprint Kap. 4].

Architektur-Entscheidung: Der Blueprint beschreibt Core und Engine als zwei separate Ebenen (Kap. 19/20). In diesem Requirements-Dokument werden sie als eine Backend-Komponente mit zwei internen Schichten geführt: Datenschicht (Core) und Event-Schicht (Engine), betrieben im selben Prozess/Service. Grund: Die Engine liest und schreibt permanent auf denselben Core-Objekten; eine Trennung in zwei Deployables würde nur Netzwerk-Roundtrips und Konsistenzrisiken erzeugen, ohne dass ein reales Skalierungsproblem das rechtfertigt. Die inhaltliche Beschreibung aus dem Blueprint bleibt unverändert — nur die Einordnung als eine statt zwei Plattform-Ebenen ändert sich.

1.3 Begriffe

Begriff Bedeutung
Mitarbeiter Person im Personalbestand (Büro oder Außendienst)
Einrichtung Kunde (Pflegeeinrichtung), CRM-Objekt
Vertrag Verbindliche Vereinbarung (Arbeitsvertrag, Rahmenvertrag, Einsatzvertrag, ...)
Auftrag Personalbedarf einer Einrichtung
Einsatz Konkrete Zuweisung eines Mitarbeiters zu einem Auftrag/Zeitraum
Zeiterfassung Dokumentierte, tatsächlich geleistete Arbeitszeit
Tätigkeitsnachweis Nachweis-Dokument zu geleisteter Zeit (ggf. mit Unterschrift)
Rechnung Aus freigegebener Zeiterfassung + Konditionen erzeugtes Abrechnungsdokument
Engine Event-Schicht des OMSORG Backends: ereignisgesteuerte Automatisierung ohne eigene UI, im selben Prozess wie die Datenschicht (Core) [Blueprint Kap. 20]

2. Systemüberblick & Ist-Stand

Ebene Beschreibung Ist-Stand im Repo
OMSORG Desktop Vollständige Unternehmensmodule für Büromitarbeiter 🔶 omsorgapp/ — Electron/React, Release 0.1.1. Vorhanden: HomePage, HomeStats, ContractWidget, EmployeesPage mit Tabs/Detailpanel. Lokale JSON-DB (~/Documents/Omsorg Business Controls Pro/database/omsorg-local-db.json), noch keine SQLite/Server-Anbindung.
OMSORG Connect Mobile/Web-App für Außendienst omsorgWeb/mitarbeiter-app/ — PHP/MySQL, produktiv als PWA (Manifest + Service Worker). Deckt bereits Zeiterfassung/Stundennachweis, Urlaub, Abwesenheit, Fortbildung, Dokumente, News, Benefits, Werben, Einsatzanweisung, Dienstplan, Bewertungen ab.
OMSORG Backend (Core + Engine) Eine Backend-Komponente, zwei interne Schichten: Datenschicht (Core) — gemeinsame Datenbasis, 6 Objekte; Event-Schicht (Engine) — Ereignis→Aktion-Automatisierung ohne eigene UI, arbeitet auf denselben Objekten der Datenschicht 🔶 omsorgCore/ — Grundgerüst steht (C#/.NET 8, ASP.NET Core Controller, EF Core/PostgreSQL, JWT-Auth, Rollen+Permission-Override-Rechtesystem, In-Process-Event-Dispatcher). Employee, Facility (+ FacilityContact), Contract, Order, Absence und TimeEntry haben inzwischen volles Repository/Service/Controller; Invoice existiert weiterhin nur als Domain-Entität, aber ohne Endpunkte. omsorgapp ist für Mitarbeiter jetzt echt angebunden (Login/Refresh sowie Employees-CRUD laufen über omsorgCore, keine lokale JSON-Datenhaltung mehr für dieses Modul), ebenso Kunden/Einrichtungen (FacilitiesPage) und Aufträge/Disposition (OrdersPage). Noch keine Anbindung von omsorgWeb (MySQL) an dieses Backend, und die übrigen omsorgapp-Fachmodule (Kalkulation, Fahrzeuge, Rechnungen, Controlling) sind weiterhin reine PlaceholderPage-Stubs ohne Datenhaltung. DB-Migration wurde gegen eine echte PostgreSQL-Instanz verifiziert (siehe omsorgCore/CLAUDE.md, "Verifiziert"); die neueste Migration (Order/Statuspipeline) noch nicht. Details: omsorgCore/CLAUDE.md.

Kernrisiko für die Roadmap: Solange das Backend (Core + Engine) nicht existiert, sind Connect (MySQL) und Desktop (JSON) zwei Insellösungen — genau das, was Blueprint Kap. 19.9 ausschließt. Phase 1 der Roadmap muss dies zuerst auflösen (siehe Abschnitt 10).


3. Akteure & Rollen

Rolle Personen Zugriffsniveau [Blueprint Kap. 6]
Geschäftsführung Sabina, Malik Vollzugriff: alle Module, Finanzdaten, Gewinn, Margen, Benutzerverwaltung
Disposition/Buchhaltung Sabrina Mitarbeiter, Einrichtungen, Aufträge/Einsätze, Zeiterfassung, Rechnungen, Zahlungen, Recruiting/CRM — kein vollständiger Gewinn/Gesamtmargen
Recruiting Sascha Recruiting, Bewerber, Mitarbeiterakten (soweit nötig), Einrichtungs-Leads, Akquise, Marketing — kein Zugriff auf Rechnungen, Zahlungen, Gewinn, Margen, Controlling
Außendienst alle Pflegekräfte Nur OMSORG Connect, nur eigene Daten
Zukünftige Büromitarbeiter Rolle als Vorlage + individuell vergebene/entzogene Rechte (sehen/anlegen/bearbeiten/löschen/exportieren/freigeben je Modul)

4. Funktionale Anforderungen (FR)

4.1 Dashboard / Morning Briefing / Tagesabschluss

ID Anforderung Akteur Akzeptanzkriterium Status
FR-DASH-1 Beim Öffnen zeigt das Dashboard neue Outlook-Mails, Krankmeldungen, fehlende Tätigkeitsnachweise, Vertragsverlängerungen, offene Rechnungen, Kaltaquise-Termine, neue Mitarbeiter, Auslastung [Blueprint 2.1] alle Büro-Rollen Jede Kategorie ist als eigene Kachel/Liste sichtbar und führt per Klick zur passenden Aktion 🔶 (HomePage/HomeStats/ContractWidget in omsorgapp zeigen einen Teil; Outlook, Krankmeldungen, Kaltaquise fehlen)
FR-DASH-2 Gewinn-Kachel ist ausschließlich für Sabina/Malik sichtbar [Blueprint 6.1] Geschäftsführung Anderer Rolle wird die Kachel serverseitig nicht ausgeliefert, nicht nur UI-verborgen
FR-DASH-3 Tagesabschluss-Ansicht zeigt „Heute erledigt" vs. „Noch offen" [Blueprint 2.3] alle Büro-Rollen Am Ende des Tages ist eine konsolidierte Liste abrufbar
FR-DASH-4 Jede Dashboard-Information führt direkt zur zugehörigen Aktion (z. B. Vertrag öffnen, Mitarbeiter zurückrufen) alle Büro-Rollen Klick navigiert ins jeweilige Modul mit vorausgewähltem Datensatz

4.2 Mitarbeiter (Personalakte)

ID Anforderung Akteur Akzeptanzkriterium Status
FR-MA-1 Stammdaten erfassen (Name, Geburtsdatum, Adresse, Kontakt, Notfallkontakt, Beschäftigungsart, Qualifikation, Ein-/Austritt, Status) [Blueprint 19.1] Sabina, Malik, Sabrina Datensatz anlegen/bearbeiten mit Pflichtfeldern; Validierung verhindert unvollständige Sätze (alle Felder in Employee-Entity + EmployeeForm in omsorgapp vorhanden; Validierung serverseitig in EmployeesController (Pflichtfelder, Längen, Ein-/Austrittslogik, Beschäftigungsart-Allowlist) und clientseitig verdrahtet; omsorgapp spricht für Mitarbeiter jetzt über employeesClient.cjs echt gegen omsorgCore, keine JSON-lokale Persistenz mehr für dieses Modul — Abgleich mit Connect/omsorgWeb weiterhin offen, siehe FR-CORE-1)
FR-MA-2 Arbeitsvertragsdaten (Beginn/Ende, Arbeitszeit, Stundenlohn, Zuschläge, Überstunden, Urlaubsanspruch, Probezeit) [Blueprint 19.1] Sabina, Malik, Sabrina Vertragsfelder je Mitarbeiter editierbar, Historie bei Änderung nachvollziehbar (Contract-Entity in omsorgCore um alle geforderten Felder erweitert, volles Repository/Service/Controller (ContractsController, GET/POST/PUT/DELETE /api/contracts) nach dem Facility-Muster, gegated über [RequirePermission(ModuleType.Contracts, ...)]; Änderungshistorie automatisch über den generischen AuditSaveChangesInterceptor abgedeckt; omsorgapp-UI jetzt vorhanden — "Verträge"-Tab in EmployeeDetailPanel (ContractsList/ContractForm/Create-/EditContractDialog.jsx), Anlegen/Bearbeiten/Löschen funktionsfähig gegen omsorgCore, neue Verträge starten als "Entwurf", Statuswechsel nur im Bearbeiten-Formular)
FR-MA-3 Dokumente, Qualifikationen, Fortbildungen, Führerschein, Gesundheitsnachweise, Notizen, Historie je Mitarbeiter Sabina, Malik, Sabrina Upload/Anzeige je Kategorie, Zugriffsprotokoll (Backend: omsorgCore DocumentsController/Document-Entität, Dateien auf Disk + Metadaten in Postgres, Zugriffsprotokoll über AuditEvent "DocumentDownloaded"; Frontend: "Dokumente"-Tab in der Personalakte (omsorgapp, DocumentsList/UploadDocumentDialog/EditDocumentDialog/DocumentViewerDialog) mit Upload, Bearbeiten, In-App-Vorschau (PDF/Bild) und Download je Kategorie, rechtegegated — siehe omsorgCore/CLAUDE.md/omsorgapp/CLAUDE.md "Dokumentenarchiv"/"Dokumente". Offen: omsorgWeb-Insellösung (pages/dokumentenarchiv.php) ist noch nicht abgelöst/migriert, siehe FR-CORE-1)
FR-MA-4 Eintrittsdatum löst Dashboard-Hinweis auf bevorstehenden Mitarbeiterstart aus [Blueprint 7] alle Büro-Rollen X Tage vor Eintritt erscheint Engine-Hinweis im Dashboard (abhängig von Engine, siehe 4.10)
FR-MA-5 Bei Büromitarbeitern kann der Mitarbeiterdatensatz mit einem Benutzerkonto + individuellen Rechten verknüpft werden [Blueprint 19.1] Sabina, Malik Rechteliste pro Modul (sehen/anlegen/bearbeiten/löschen/exportieren/freigeben) editierbar (in omsorgCore, nicht mehr omsorgWeb: User.EmployeeId verknüpft ein Benutzerkonto mit dem Employee-Datensatz, UsersController.Create/UserService.CreateForEmployeeAsync erzwingt genau 1 Konto je Mitarbeiter; Rechte sind granular pro Modul × Aktion — Rolle als Vorlage (RolePermission) plus individuelle Grant/Revoke-Ausnahmen je Nutzer (UserPermissionOverride), inkl. Recover seit dem Soft-Delete-Schritt; Admin-UI in omsorgapp: RolesPanel/RolePermissionMatrix/UserOverridesPanel unter "Einstellungen")
FR-MA-6 Außendienstmitarbeiter sehen ausschließlich eigene Daten [Blueprint 4.2] Außendienst Query/Route liefert nur Datensätze mit user_id = aktueller Nutzer (Session-basierter Zugriff in omsorgWeb/mitarbeiter-app, z. B. pages/urlaubsantrag.php)

4.3 Einrichtungen & CRM

ID Anforderung Akteur Akzeptanzkriterium Status
FR-EIN-1 Stammdaten (Name, Art, Adresse, Rechnungsadresse, Telefon, E-Mail, Website, Status) [Blueprint 19.2] Sabina, Malik, Sabrina, Sascha (Leads) Datensatz anlegen/bearbeiten (Facility-Entity + volles Repository/Service/Controller (FacilitiesController, GET/POST/PUT /api/facilities) in omsorgCore, serverseitige Rechteprüfung über [RequirePermission(ModuleType.Facilities, ...)]; Felder Name/Art(FacilityType)/Adresse/Rechnungsadresse/Website/Status(CrmStatus) abgedeckt — Adresse und Rechnungsadresse sind je strukturierte Felder (Straße/PLZ/Ort/Land, analog Mitarbeiter-Adresse), kein Freitext; UI-Modul in omsorgapp vorhanden (FacilitiesPage, Sidebar-Tab "Kunden", analog EmployeesPage) — Anlegen/Bearbeiten funktionsfähig gegen omsorgCore. Bewusste Abweichung von der Zeile: kein allgemeines Telefon/E-Mail direkt auf Facility — Kontaktwege leben ausschließlich pro Ansprechpartner auf FacilityContact (FR-EIN-2), da eine Einrichtung i. d. R. mehrere Ansprechpartner mit je eigenen Kontaktdaten hat und ein zusätzliches, nicht klar zuordenbares "allgemeines" Einrichtungstelefon eine zweite, redundante Kontakt-Datenquelle wäre (widerspricht dem Grundsatz "jede Information wird nur einmal gespeichert", siehe Root-CLAUDE.md). Diese Entscheidung ist absichtlich, kein offener Punkt.)
FR-EIN-2 Mehrere Ansprechpartner je Einrichtung mit Funktion, Abteilung, Kontaktwegen, Notizen Sabina, Malik, Sabrina, Sascha Liste von Ansprechpartnern editierbar, mind. 1:n-Beziehung (neue Entität FacilityContact (1:n zu Facility) in omsorgCore, FacilityContactsController unter GET/POST/PUT/DELETE /api/facilities/{facilityId}/contacts[/...], gegated über dieselben ModuleType.Facilities-Rechte wie die Einrichtung selbst; Felder Name/Funktion(Role)/Abteilung(Department)/Telefon/E-Mail/Notizen abgedeckt; UI-Liste im FacilityDetailPanel (omsorgapp) anlegen/bearbeiten/löschen funktionsfähig; Löschen ist Soft-Delete (IsDeleted/DeletedAt) und über die neue "Papierkorb"-Seite (ModuleType.Facilities+PermissionAction.Recover) wiederherstellbar)
FR-EIN-3 CRM-Status-Pipeline: Lead → kontaktiert → kein Bedarf → Wiedervorlage → Interesse → Angebot → Kunde → Bestandskunde [Blueprint, omsorg.md] Sascha, Sabrina Statuswechsel wird protokolliert; bei „kein Bedarf" wird automatisch Wiedervorlage in 14 Tagen erzeugt (Statuswechsel-Protokollierung läuft automatisch über den bestehenden AuditSaveChangesInterceptor, kein Zusatzcode nötig; neues Feld Facility.FollowUpDueDate (nullable), gesetzt über FacilitiesController.Update, wenn der neu gewählte CrmStatus-Wert das Flag TriggersFollowUp trägt (aktuell nur "Kein Bedarf" — generisch statt hartcodiert, damit künftig weitere Status dieselbe Mechanik nutzen können) — serverseitig muss dann ein FollowUpDays aus der admin-editierbaren ValueList "FollowUpPeriods" (7/14/21/31 Tage, Default 14) mitgegeben werden; omsorgapp zeigt dafür beim Statuswechsel auf einen solchen Status einen Auswahldialog (FollowUpDaysDialog.jsx in EditFacilityDialog.jsx, 14 Tage vorausgewählt) und das Fälligkeitsdatum im FacilityDetailPanel; Dashboard-Widget "Fällige Wiedervorlagen" (FollowUpWidget.jsx, in HomePage.jsx eingebunden) zeigt fällige Einrichtungen an; die Statuspipeline erzwingt wie bei OrderStatus erlaubte Übergänge (ValueListItemTransition für "CrmStatus", geseedet mit der Vorwärtskette der Pipeline plus jederzeitigem Rückfall auf "Kein Bedarf"/"Wiedervorlage", admin-editierbar über dieselbe "Erlaubte Übergänge"-Matrix wie beim Auftragsstatus, FacilitiesController.Update prüft serverseitig via CanTransitionAsync, das CRM-Status-Dropdown in FacilityForm.jsx (nur im EditFacilityDialog) zeigt dem Nutzer dabei ebenfalls nur den aktuellen Status plus die laut GET /api/value-lists/CrmStatus/transitions erlaubten Zielstatus an — vorher listete das Dropdown ungefiltert alle CRM-Status auf, ein unzulässiger Wechsel wurde erst nach "Speichern" per 400-Fehler vom Server abgelehnt). Die wählbare Frist statt einer starren 14-Tage-Automatik ist eine bewusste, finale Designentscheidung — kein offener Punkt.)
FR-EIN-4 Konditionen (Verrechnungssatz, Zuschläge, Fahrtkosten, Mindeststunden, Zahlungsziel etc.) je Einrichtung [Blueprint 19.2] Sabina, Malik, Sabrina Konditionssatz ist Grundlage für Rechnungserstellung (siehe FR-RE-1) (Backend: elf der zwölf Blueprint-19.2-Felder als flache, nullable Spalten auf Facility — Verrechnungssatz, vier Zuschläge (als Prozent), Fahrtkosten (Pauschale je Einsatz), Mindeststunden, Pausenregelung, Abrechnungsintervall (validiert gegen neue ValueList "BillingInterval"), Zahlungsziel, individuelle Vereinbarungen —, nur über PUT /api/facilities/{id} pflegbar; qualifikationsabhängige Preise als neue 1:n-Unterressource FacilityQualificationRate (GET/POST/PUT/DELETE /api/facilities/{facilityId}/qualification-rates[/...], Qualifikation gegen die bestehende ValueList "Qualification" validiert) nach dem FacilityContact-Muster, inkl. Soft-Delete/Papierkorb; Migration AddFacilityConditionsAndQualificationRates erfolgreich gegen die echte Postgres-Instanz angewendet (automatisch beim API-Start); omsorgapp-UI (Konditionen-Fieldset in FacilityForm.jsx, FacilityQualificationRatesList im FacilityDetailPanel) vorhanden, omsorgapp/api-client-ts regeneriert und gebaut (Methodennamen/Feldnamen gegen den generierten Client verifiziert). Akzeptanzkriterium "Grundlage für Rechnungserstellung" im engeren Sinn bewusst weiterhin nicht vollständig erfüllt, da FR-RE-1/Invoice diese Daten noch nicht konsumiert — dieser Schritt legt nur die Datenbasis.)
FR-EIN-5 Verknüpfte Historie: Verträge, Aufträge, zugewiesene Mitarbeiter, Nachweise, Rechnungen, Zahlungen, Mahnungen, Kommunikation alle Büro-Rollen (rechteabhängig) Einrichtungsakte zeigt konsolidierte Historie ohne Datenduplizierung

4.4 Einsatzmanagement (Auftrag → Einsatz → Zuweisung)

ID Anforderung Akteur Akzeptanzkriterium Status
FR-EM-1 Auftrag erfassen (Einrichtung, Ansprechpartner, Qualifikation, Zeitraum, Schichtart, Anzahl Mitarbeiter, Konditionen, Priorität) [Blueprint 19.4] Sabrina Auftragsdatensatz mit Pflichtfeldern anlegbar (Order-Entity in omsorgCore um alle geforderten Felder erweitert, volles Repository/Service/Controller (OrdersController, GET/POST/PUT/DELETE /api/orders) nach dem Facility/Contract-Muster, gegated über [RequirePermission(ModuleType.Orders, ...)]; Ansprechpartner (FacilityContactId) wird gegen die angegebene Einrichtung cross-validiert; omsorgapp-UI-Modul vorhanden (Sidebar-Tab "Disposition" → OrdersPage/OrderForm/OrderDetailPanel/Create-/EditOrderDialog, über src/api/ordersApi.js echt gegen omsorgCore), alle Pflichtfelder inkl. abhängigem Ansprechpartner-Dropdown (lädt Kontakte der gewählten Einrichtung nach) und Qualifikation/Schichtart/Priorität als admin-editierbare Auswahllisten abgedeckt)
FR-EM-2 Auftragsstatus-Pipeline: Anfrage → Prüfung → offen → teilweise besetzt → vollständig besetzt → aktiv → abgeschlossen/storniert [Blueprint 19.4] Sabrina Statuswechsel nur in zulässiger Reihenfolge, sichtbar im Dashboard (Pipeline serverseitig erzwungen: Status und erlaubte Übergänge sind DB-konfigurierbar über das generische ValueList/ValueListItem/ValueListItemTransition-Modell (Liste "OrderStatus", gleiches Muster wie CRM-Status bei Facilities, siehe omsorgCore/CLAUDE.md "Konfigurierbare Auswahllisten") statt eines eigenen OrderStatusDefinition/OrderStatusTransition-Modells, Standard-Pipeline per DbSeeder geseedet, OrderService.UpdateAsync lehnt unzulässige Übergänge über ValueListRepository.CanTransitionAsync mit 400 ab; omsorgapp-OrderForm.jsx filtert das Status-Dropdown im Bearbeiten-Formular serverseitig identisch auf die laut /api/value-lists/OrderStatus/transitions erlaubten Zielstatus (kein Client/Server-Auseinanderlaufen); Dashboard-Sichtbarkeit jetzt über OrderStatusWidget.jsx in HomePage.jsx (Auftragsanzahl je Status, rechtegegated über hasPermission("Orders","View"), analog FollowUpWidget.jsx))
FR-EM-3 Mitarbeiterzuweisung prüft Qualifikation, Verfügbarkeit, Arbeitszeit, Abwesenheiten, Überschneidungen, Vertragsbedingungen [Blueprint 19.4] Sabrina System verhindert/warnt bei Konflikten vor Zuweisung (weiterhin offen — es gibt noch keine Mitarbeiterzuweisung/Einsatz-Entität, nur den Auftrag selbst. Die Abwesenheitsdatenbasis für den "Abwesenheiten"-Teil der Konfliktprüfung existiert jetzt aber bereits in omsorgCore (Absence, siehe FR-CON-1/omsorgCore/CLAUDE.md) — von der eigentlichen Zuweisungs-Konfliktprüfung wird sie noch nicht konsumiert)
FR-EM-4 Nach Zuweisung erhält Mitarbeiter automatisch Einsatzanweisung über OMSORG Connect [Blueprint 19.4] System → Außendienst Einsatzanweisung erscheint in Connect ohne manuellen Zusatzschritt 🔶 (Connect hat bereits pages/einsatzanweisung.php inkl. Admin-Upload actions/einsatzanweisung-action.php; automatische Erzeugung aus Zuweisung fehlt, da Aufträge/Zuweisung noch nicht existieren)
FR-EM-5 Krankmeldung löst Ersatzbesetzungs-Workflow aus [omsorg.md, Blueprint 20.2] System, Sabrina Bei Krankmeldung erscheint Einsatz als "muss neu besetzt werden" inkl. Vorschlägen

4.5 Zeiterfassung & Tätigkeitsnachweise

ID Anforderung Akteur Akzeptanzkriterium Status
FR-ZE-1 Erfassung von Beginn, Pause, Ende, Einrichtung, Auftrag, Nacht-/Wochenend-/Feiertagsstunden [Blueprint 19.5] Außendienst Eintrag pro Schicht mit Pflichtfeldern (TimeEntry in omsorgCore, volles CRUD über TimeEntriesController; Einrichtung wird über Order.FacilityId aufgelöst statt redundant gespeichert; Erfassung über omsorgWeb/mitarbeiter-app pages/stundenerfassung.php, Prüfung/Freigabe über omsorgapp "Zeiterfassung")
FR-ZE-2 Statuspipeline: Entwurf → eingereicht → Prüfung → Rückfrage → freigegeben → abgerechnet [Blueprint 19.5] Außendienst, Sabrina Statuswechsel sichtbar für beide Seiten, Rückfrage möglich (ValueList "TimeEntryStatus" mit ValueListItemTransition-Graph wie OrderStatus, zusätzlich RequiresApproval je Kante — Außendienst löst nur die Selbst-Einreichungs-Kanten über POST /api/time-entries/{id}/submit aus, Sabrina/Büro entscheidet über POST /api/time-entries/{id}/decision)
FR-ZE-3 Nur freigegebene Zeiten dürfen in Rechnungsstellung einfließen [Blueprint 19.5, 19.8] System Rechnungslauf ignoriert nicht-freigegebene Datensätze; Verstoß ist technisch unmöglich, nicht nur UI-Regel
FR-ZE-4 Optionale Unterschrift/Bestätigung der Einrichtung, Upload als Foto/PDF Außendienst Upload-Feld vorhanden, an Zeiterfassungssatz gekoppelt 🔶 (Upload existiert für Monatsnachweis, nicht pro Einzel-Einsatz)

4.6 Rechnungen & Zahlungsüberwachung

ID Anforderung Akteur Akzeptanzkriterium Status
FR-RE-1 Automatische Rechnungserstellung aus freigegebener Zeit + Konditionen + Zuschlägen [Blueprint 19.6] System, Sabrina (Freigabe) Rechnungsentwurf wird ohne manuelle Neuerfassung generiert
FR-RE-2 Statuspipeline: Entwurf → Prüfung → freigegeben → versendet → offen → bezahlt (alternativ überfällig → Mahnung → bezahlt) [Blueprint 19.6] Sabrina, Sabina/Malik (Freigabe) Statuswechsel protokolliert, keine übersprungenen Zwischenschritte
FR-RE-3 Zahlungsziel 14 Tage wird von der Engine überwacht; bei Überschreitung Dashboard-Warnung + Mahnentwurf [Blueprint 19.6, 20.2] System → Sabrina Nach 14 Tagen ohne Zahlungseingang erscheint automatisch Mahnentwurf
FR-RE-4 Rechnungs-PDF-Erzeugung und Versand, Dokumentation in Mahnhistorie Sabrina PDF entspricht Rechnungsdaten; Versand/Historie nachvollziehbar

4.7 Recruiting & Akquise

ID Anforderung Akteur Akzeptanzkriterium Status
FR-REC-1 Bewerberpipeline: Interessent → Bewerbung → Erstkontakt → Vorstellung → Unterlagen → Angebot → Einstellung → geplanter Eintritt [Blueprint 3.2] Sascha Bewerberdatensatz mit Statuswechsel
FR-REC-2 Werbung/Empfehlung: Kanäle Indeed, Facebook, Instagram, Mitarbeiterempfehlung erfassbar [omsorg.md] Sascha Herkunft je Bewerber taggable, auswertbar 🔶 (pages/werben.php/actions/submit-werben.php erfasst Mitarbeiterempfehlungen bereits; Kanaltracking für externe Werbung fehlt)
FR-REC-3 Einrichtungsakquise: Lead anlegen → Ansprechpartner erfassen → Kontakt → Gesprächsnotiz → Ergebnis → automatische Wiedervorlage nach 14 Tagen [Blueprint 3.5] Sascha Wiedervorlage wird ohne manuellen Trigger vom System erzeugt
FR-REC-4 Sascha hat keinen Zugriff auf Rechnungen, Zahlungen, Gewinn, Margen, Controlling [Blueprint 6.2] System Rollenprüfung blockiert Zugriff serverseitig

4.8 Controlling

ID Anforderung Akteur Akzeptanzkriterium Status
FR-CTL-1 Auswertungen: Umsatz, Kosten, Gewinn, Deckungsbeitrag, Margen, Auslastung, Fehlzeiten, Einrichtungsrentabilität, offene Forderungen, Recruiting-/Marketing-Erfolg, Fahrzeugkosten [Blueprint 11] Sabina, Malik (voll), Sabrina (eingeschränkt) Jede Kennzahl aus Core-Daten berechnet, nicht manuell gepflegt
FR-CTL-2 Drei-Monats-Durchschnitt und Trends/Prognosen [Blueprint 11] Sabina, Malik Rollierender Durchschnitt wird automatisch aktualisiert
FR-CTL-3 Vollständige Gewinn-/Margendaten ausschließlich für Sabina/Malik [Blueprint 11] System Andere Rollen erhalten aggregierte/gekürzte Werte oder keinen Zugriff

4.9 OMSORG Connect (Mobile)

ID Anforderung Akteur Akzeptanzkriterium Status
FR-CON-1 Zeiterfassung, digitaler Tätigkeitsnachweis, Fahrtenbuch, Einsatzanweisung, Krankmeldung, Urlaub, Dokumente, News, Benefits, Ansprechpartner [omsorg.md, Blueprint 4.2] Außendienst Jede Funktion als eigener Menüpunkt erreichbar 🔶 (produktiv über omsorgWeb/mitarbeiter-app-legacy (eigene MySQL): Stundennachweis-Upload, Urlaubs-/Abwesenheitsantrag, Dokumentenarchiv, News, Benefits, Einsatzanweisung, Fortbildung, Dienstplan, Werben, Bewertung — Fahrtenbuch fehlt vollständig, Zeiterfassung ist Upload statt Live-Erfassung. Der aktiv weiterentwickelte Neuaufbau omsorgWeb/mitarbeiter-app (gegen omsorgCore, keine eigene Datenhaltung mehr) deckt bisher Login/Passwort sowie Urlaubs-/Abwesenheits-/Krankmeldungsanträge ab (pages/urlaubsantrag.php gegen den neuen AbsencesController, Datenbasis zugleich für FR-EM-3 — siehe omsorgCore/CLAUDE.md "Abwesenheits-/Urlaubs-/Krankmeldungsanträge"); alle anderen Menüpunkte müssen im Neuaufbau noch nachgezogen werden, bis die Legacy-App abgelöst werden kann)
FR-CON-2 Automatische Synchronisation mit OMSORG Desktop [omsorg.md] System Änderung in Connect ist ohne manuellen Export in Desktop sichtbar (blockiert durch fehlendes OMSORG Backend, s. Abschnitt 2)
FR-CON-3 PWA-Installierbarkeit ("Add to Home Screen") Außendienst Manifest + Service Worker vorhanden und funktionsfähig (manifest.webmanifest, service-worker.js)
FR-CON-4 Login-Rate-Limiting: 5 Fehlversuche → 10 Min. Sperre Außendienst/alle Nach 5 Fehlversuchen wird Login für 10 Minuten blockiert (index.php, login_attempts-Tabelle, Migration 004)

4.10 OMSORG Backend Event-Schicht (Engine, Ereignis → Aktion)

Die Event-Schicht ist Teil des Backends (siehe Abschnitt 2) und läuft im selben Prozess/Service wie die Datenschicht (Core, Abschnitt 6) — nicht als separates Deployable.

Trigger Erwartete Aktionen [Blueprint 20.2] Status
Krankmeldung eingereicht Dashboard aktualisieren, Disposition informieren, Einsatz markieren, Ersatzvorschläge anzeigen, Einsatzanweisung vorbereiten, Historie ergänzen
Tätigkeitsnachweis fehlt (montags) Dashboard aktualisieren, Mitarbeiter markieren, Erinnerung via Connect senden, Rechnungsfreigabe blockieren
Vertragsende nähert sich (30 Tage) Dashboard-Warnung, zuständige Person informieren, Kontakt/Vertrag direkt öffnen
Neue Bewerbung Recruiting informieren, Bewerber anlegen, Wiedervorlage erzeugen, Status "Neu"
Zahlung eingegangen Zahlungsstatus ändern, Mahnungen stoppen, Dashboard/Controlling/Liquidität aktualisieren
Neuer Mitarbeiter beginnt Dashboard-Hinweis, Personalakte/Dokumente prüfen, App-Zugang vorbereiten, Einsatzanweisung kontrollieren
Rechnung überfällig Warnung, Mahnentwurf, Freigabe, Versand, Mahnhistorie

FR-ENG-1: Die Event-Schicht besitzt keine eigene UI, arbeitet ereignisbasiert im Hintergrund und schreibt alle Aktionen protokolliert in die jeweiligen Objekte der Datenschicht [Blueprint 20.1, 20.6]. Status: — bislang keinerlei Automatisierungsschicht im Repo vorhanden.

4.11 Outlook-Integration (spätere Phase)

ID Anforderung Status
FR-OUT-1 Neue E-Mails im Morning Briefing, E-Mail↔Einrichtung/Mitarbeiter-Zuordnung, Auftrag/Aufgabe aus E-Mail erzeugen, Rechnungsversand dokumentieren [Blueprint 12] — explizit als spätere Roadmap-Phase (Phase 7) markiert, kein Blocker für Phase 16

5. Nicht-funktionale Anforderungen (NFR)

ID Anforderung Quelle Status
NFR-1 DSGVO-konforme Verarbeitung, minimale notwendige Berechtigungen Blueprint 13 🔶 (rollenbasierte Sichten in Connect vorhanden, keine dokumentierte DSGVO-Prüfung)
NFR-2 Getrennte Benutzerkonten, sichere Anmeldung, Sitzungssperre Blueprint 13 (Session-Auth, Rate-Limiting in lib/auth.php)
NFR-3 Verschlüsselte Datenübertragung und -speicherung sensibler Daten Blueprint 13 🔶 (HTTPS wird vorausgesetzt, aber nicht im Repo erzwungen; keine Feldverschlüsselung für besonders sensible Daten)
NFR-4 CSRF-Schutz auf jedem POST-Formular omsorgWeb CLAUDE.md (csrf_field()/verify_csrf() durchgängig verwendet)
NFR-5 Ausgabe-Escaping gegen XSS omsorgWeb CLAUDE.md (e()-Helper)
NFR-6 Automatische Backups + regelmäßige Wiederherstellungsprüfung Blueprint 13
NFR-7 Nachvollziehbare Änderungshistorie / Protokollierung sicherheitsrelevanter Vorgänge Blueprint 13, 19.8 🔶 (Login-Versuche protokolliert; generisches Audit-Log für Datensatzänderungen fehlt)
NFR-8 Aufbewahrungs- und Löschkonzept, Schutz vor unbefugtem Export Blueprint 13 🔶 (Löschkonzept-Teil umgesetzt: Employee/Facility/Contract/Order/FacilityContact werden ausschließlich soft-gelöscht (IsDeleted/DeletedAt, kein Hard-Delete), gegated über PermissionAction.Delete je Modul, und über eine neue "Papierkorb"-Seite (PermissionAction.Recover) wiederherstellbar — nichts geht verloren, nichts wird unkontrolliert entfernt; noch offen: Aufbewahrungsfristen/automatisches endgültiges Löschen nach Frist sowie expliziter Schutz vor unbefugtem Export)
NFR-9 Berechtigungsprüfung auf Oberflächen- und Datenebene Blueprint 13, 19.8 🔶 (in Connect vorhanden für Außendienst-Eigendaten; granulare Rechtematrix für Büromitarbeiter fehlt)
NFR-10 White-Label-Fähigkeit: Branding (Name, Logo, Farben, Schrift, Vorlagen) von Geschäftslogik getrennt Blueprint 14 (aktuell Branding fest im Code/CSS von omsorgWeb/omsorgapp)
NFR-11 Vollständige Mandantentrennung für spätere Multi-Tenant-Nutzung Blueprint 14 (nicht Teil der aktuellen Datenmodelle; explizit erst „bei Bedarf")
NFR-12 Wiederverwendbare Komponenten, modulare Architektur, klare Verantwortlichkeiten Blueprint 15 🔶 (omsorgapp/src/components/ui als Ansatz vorhanden)

6. Datenmodell-Anforderungen (OMSORG Backend Datenschicht/Core)

Die sechs Core-Objekte [Blueprint Kap. 19]: Mitarbeiter, Einrichtung, Vertrag, Auftrag, Zeiterfassung, Rechnung.

Verbindliche Regeln [Blueprint 19.8]:

  1. Jeder Datensatz besitzt eine eindeutige interne ID.
  2. Beziehungen werden über IDs hergestellt, nicht durch doppelte Texteingaben.
  3. Stammdaten werden nur an einer zentralen Stelle gepflegt.
  4. Änderungen werden nachvollziehbar protokolliert.
  5. Löschungen sensibler/geschäftsrelevanter Daten erfolgen nicht unkontrolliert (Soft-Delete/Archivierung statt Hard-Delete). umgesetzt für alle Core-Objekte mit vollem CRUD (Employee, Facility, Contract, Order, FacilityContact, Absence, TimeEntry) — IsDeleted/DeletedAt statt Hard-Delete, wiederherstellbar über die "Papierkorb"-Seite; Invoice hat noch kein CRUD, daher hier noch nicht relevant.
  6. Berechtigungen werden auf Daten- und Funktionsebene geprüft.
  7. Automatisierungen (Event-Schicht) greifen ausschließlich auf verlässliche, freigegebene Daten zu — dadurch, dass Datenschicht und Event-Schicht im selben Backend-Prozess laufen, ist dies technisch einfacher garantierbar als bei getrennten Services (kein Risiko von veralteten/inkonsistenten Zwischenständen durch asynchrone Synchronisation).
  8. Rechnungen entstehen ausschließlich aus freigegebenen Arbeitszeiten.
  9. OMSORG Connect erhält nur die für den jeweiligen Mitarbeiter freigegebenen Daten.

FR-CORE-1: Es gibt genau eine Datenquelle für jedes Core-Objekt, die von Desktop, Connect, Event-Schicht (Engine) und Controlling gemeinsam genutzt wird — bereitgestellt durch die Datenschicht des Backends. Status: 🔶 — das Backend selbst existiert jetzt (omsorgCore, PostgreSQL/EF Core, alle 6 Core-Objekte als Entitäten angelegt). omsorgapp ist für das Mitarbeiter-Objekt bereits umgestellt (echtes CRUD über omsorgCore, keine JSON-Persistenz mehr für dieses Modul), die übrigen omsorgapp-Fachmodule und omsorgWeb (MySQL) sprechen noch nicht damit. Solange diese Anbindung für die restlichen Objekte/Projekte fehlt, bleiben es weiterhin getrennte Speicher parallel zum neuen Backend. Anbindung der bestehenden Projekte an omsorgCore ist die zentrale technische Voraussetzung, bevor Phase 2 ff. sinnvoll umsetzbar sind.


7. Rechtematrix (Auszug, aus Blueprint Kap. 6 abgeleitet)

Modul Sabina/Malik Sabrina Sascha Außendienst
Mitarbeiter (Personalakte) voll voll eingeschränkt (soweit erforderlich) nur eigene Daten
Einrichtungen/CRM voll voll Leads/Akquise
Aufträge/Disposition voll voll nur eigene Einsätze
Zeiterfassung voll prüfen/freigeben eigene erfassen
Rechnungen/Zahlungen voll erstellen/freigeben kein Zugriff
Recruiting/CRM voll nutzen voll
Controlling voll (inkl. Gewinn/Margen) eingeschränkt (kein Gewinn) kein Zugriff
Benutzerkonten (anlegen, (de)aktivieren, Passwort zurücksetzen) voll
Rollen & Rechte (Rechte-Matrix, individuelle Ausnahmen) voll
Konfiguration (Status-Verwaltung/Auswahllisten) voll

Die drei letzten Zeilen waren bis 2026-08-09 ein einziger Punkt "Benutzerverwaltung" — technisch jetzt als drei getrennte Rechte (ModuleType.Users/UserManagement/Configuration, siehe omsorgCore/CLAUDE.md, Abschnitt "Rechtesystem") umgesetzt, damit z. B. künftig Status-Verwaltung an Sabrina vergeben werden kann, ohne ihr auch Zugriff auf die Rechte-Matrix zu geben. Aktuell hat davon nur Sabina/Malik überhaupt Zugriff (Basis-Rollen-Seed unverändert).

Für zukünftige Büromitarbeiter: Rolle als Vorlage, zusätzlich granular je Modul einstellbar: sehen / lesen / anlegen / bearbeiten / löschen / exportieren / freigeben [Blueprint 6.5].


8. Abnahmekriterien (Definition of Done, je Gruppe)

  • Dashboard: Alle in 4.1 gelisteten Kategorien sind sichtbar, rollenabhängig gefiltert, klickbar zur Zielaktion.
  • Mitarbeiter/Einrichtungen: CRUD vollständig, keine Pflichtfeld-Lücken, Änderungen protokolliert.
  • Einsatzmanagement: Zuweisung ohne Qualifikations-/Zeitkonflikt möglich; bei Konflikt blockiert oder mit Warnung.
  • Zeiterfassung/Rechnung: Rechnung technisch nicht erzeugbar aus nicht freigegebener Zeit (FR-ZE-3) — verifizierbar per Testfall, nicht nur Review.
  • Rollen/Rechte: Jeder Endpunkt/jede Route prüft Berechtigung serverseitig, nicht nur im UI.
  • Engine: Jeder in 4.10 gelistete Trigger löst nachweisbar (Log-Eintrag) die zugehörigen Aktionen aus.

9. Offene Punkte / Annahmen

  • Tiefe der Outlook-Integration (nur Anzeige vs. bidirektionale Synchronisation) ist noch nicht spezifiziert.
  • Zeitpunkt und Umfang der Mandantentrennung (White-Label) ist bewusst auf „bei Bedarf" verschoben — keine Anforderung für aktuelle Phasen.
  • Unklar, ob das OMSORG Backend (Core + Engine) als eigenständiger Service (eigene API, von Desktop und Connect angesprochen) oder als gemeinsame DB-/Logikschicht unter omsorgWeb/omsorgapp realisiert wird — technische Entscheidung noch offen, aber Voraussetzung für FR-CORE-1. Klar ist nur: Core (Datenschicht) und Engine (Event-Schicht) gehören in denselben Service, nicht in zwei getrennte.
  • Fahrtenbuch (FR-CON-1) ist in keiner der bestehenden Codebasen auch nur ansatzweise vorhanden — vollständige Neuentwicklung nötig.
  • Rechtsform granularer Einzelrechte (FR-MA-5) — Datenmodell für Berechtigungen (Modul × Recht) ist noch nicht definiert.

10. Rückverweis zur Roadmap [Blueprint Kap. 16]

Roadmap-Phase Betroffene FR-Gruppen Voraussetzung erfüllt?
Phase 1 Fundament FR-CORE-1, NFR-6, NFR-7, NFR-9, NFR-10 🔶 Teilweise — Backend-Grundgerüst mit Rechtesystem/Auth/Datenmodell steht, Mitarbeiter-Objekt in omsorgapp bereits angebunden, aber Anbindung von omsorgWeb und der übrigen omsorgapp-Fachmodule fehlt noch, ebenso Backups (NFR-6) und vollständiger Audit-Trail (NFR-7)
Phase 2 Stammdaten FR-MA-1..5, FR-EIN-1..5 Blockiert durch Phase 1
Phase 3 Operatives Geschäft FR-EM-1..5 Blockiert durch Phase 1/2
Phase 4 Zeit und Abrechnung FR-ZE-1..4, FR-RE-1..4 Teilbasis vorhanden (Connect-Upload), aber ohne Core nicht rechnungsfähig
Phase 5 Recruiting und CRM FR-REC-1..4 Teilbasis vorhanden (Werben), CRM-Pipeline fehlt
Phase 6 OMSORG Connect FR-CON-1..4 🔶 größtenteils vorhanden, Fahrtenbuch + Sync offen
Phase 7 Dashboard und Controlling FR-DASH-1..4, FR-CTL-1..3, FR-OUT-1 Teilbasis (omsorgapp Dashboard-Ansätze) vorhanden

Empfehlung für den nächsten Sprint: Phase 1 zuerst — das OMSORG Backend (Core + Engine als eine Komponente) mit gemeinsamer Datenbasis definieren (Datenmodell für die 6 Core-Objekte, IDs, Beziehungen, plus die Event-Schicht als Aufsatz auf denselben Daten), bevor weitere Module in omsorgapp gebaut werden. Ohne diesen Schritt wächst die Diskrepanz zwischen Connect (MySQL, produktiv) und Desktop (JSON, lokal) weiter.