Phase 2: Wartungs- und Prüfmanagement #3

Merged
florian.wilde merged 1 commits from feat/phase-2-wartung into main 2026-09-03 10:35:45 +00:00
Owner

Das Modul, wegen dem eine Wehr so ein Programm einführt: Prüffristen im Blick behalten und im Streitfall nachweisen können, dass geprüft wurde.

Was drin ist

Datenmodell — elf neue Tabellen, alle mit organisationId und Row Level Security:
Wartungsvorlage, Checklistenpunkt, Wartungstermin, Pruefung, Pruefergebnis, Signatur, Mangel, Rueckruf, RueckrufGeraetetyp, RueckrufBetroffenheit, Erinnerung.

Fristen-Dashboard (/pruefungen) — vier Töpfe nach Dringlichkeit (überfällig / diese Woche / diesen Monat / nächste 90 Tage), jede Zahl gleichzeitig ein Filter. Bündelung nach Fahrzeug, Standort, Gerätetyp oder Zuständigem. Sammelzuweisung mehrerer Termine.

Prüfwizard (/pruefungen/neu) — ein Punkt je Bildschirm, Foto aus der Kamera, mitlaufende Zeiterfassung, Unterschrift auf dem Zeichenfeld. Jede Antwort geht sofort zum Server; ein abgebrochener Durchgang wird fortgesetzt.

Prüfprotokoll als PDF — der Worker rendert über Gotenberg und legt in MinIO ab: Kopf mit Wehr, Gerät und Prüfer-Kennung, Checkliste mit Soll/Ist/Befund, eingebettete Fotos und Unterschriften, Fußzeile mit Prüfvorschrift und Prüfdatum. Laufende Nummer JJJJ-NNNN je Wehr und Jahr.

Nächtlicher Lauf — fristen.pruefen (3:15 Uhr) plant Termine und zieht den Gerätestatus nach, erinnerung.senden (3:45 Uhr) verschickt Vorwarnungen bei T-30, T-7, T-0 und einmal bei Überfälligkeit, als Sammelnachricht je Empfänger.

Mängel (/maengel) — melden → zugewiesen → in Arbeit → behoben. Melden darf jedes Mitglied; ein kritischer Mangel sperrt das Gerät.

Rückrufe (/rueckrufe) — Suche nach betroffenen Geräten über Bauart, Modell, Seriennummernbereich und Herstellungszeitraum, Sperre auf Wunsch, Stand je Gerät.

Lebensdauer (/pruefungen/lebensdauer) — was abgelaufen ist, mit Aussonderungsvorschlag.

Die wichtigste Festlegung

Ein abgeschlossenes Prüfprotokoll ist unveränderbar, und zwar durchgesetzt von einem Datenbanktrigger, nicht vom Anwendungscode. Zulässig bleiben genau drei Änderungen: der Wechsel auf „ersetzt", das Nachtragen des PDF, solange keines hinterlegt ist, und geaendertAm. Dasselbe gilt für Einzelergebnisse und Unterschriften — sonst ließe sich ein festgeschriebenes Protokoll über den Umweg seiner Bestandteile ändern.

Eine Korrektur erzeugt eine neue Prüfung mit Verweis auf die alte. Beide bleiben lesbar.

Zum Testen

git checkout feat/phase-2-wartung
npm install
docker compose up -d
npm run db:migrate
npm run db:seed
npm run dev          # Anwendung auf :3100
npm run worker       # zweites Fenster: plant Termine, erzeugt die PDFs

Anmeldung: admin@beispielwehr.de / Feuerwehr2026

  1. /pruefungen — die vier Zahlen anklicken (filtert die Liste), Bündelung auf „nach Gerätetyp" umschalten.
  2. /pruefungen/vorlagen — fünf Vorlagen aus dem Seed mit echten Prüfvorgaben; eine öffnen, Punkt ergänzen, Reihenfolge mit den Pfeiltasten ändern.
  3. Prüfung durchführen — im Dashboard auf „Prüfen", Checkliste durchklicken, Foto anhängen, unterschreiben, abschließen. Danach „Protokoll als PDF" (der Worker braucht ein bis zwei Sekunden).
  4. Unveränderbarkeit — am fertigen Protokoll „Korrektur anlegen": es entsteht ein neuer Entwurf mit den alten Antworten, das alte Protokoll bleibt stehen.
  5. /maengel — Mangel mit Dringlichkeit „kritisch" melden; das Gerät wird gesperrt. Beheben gibt es wieder frei.
  6. /rueckrufe — Beispielrückruf öffnen, Treffer im Bestand zuordnen, Stand je Gerät setzen.

Nachweise

  • npm run typecheck — ohne Ausgabe
  • npm run test — 161 Tests grün (davon 18 gegen eine echte Datenbank)
  • npm run test:e2e — 71 Tests grün, 2 begründet übersprungen (Desktop und Tablet)
  • npm run build — 30 Routen

Nebenbei behoben

  • Zwei gleichzeitig abgeschlossene Prüfungen zogen dieselbe Protokollnummer. Sie wird jetzt unter einer Transaktionssperre je Wehr und Jahr vergeben — gefunden von den E2E-Tests, weil Desktop und Tablet parallel prüfen.
  • Der Worker ließ sich außerhalb des Containers nicht starten (.env wurde nicht geladen, server-only warf unter Node). Beide Startbefehle laufen jetzt mit --conditions=react-server.

Aufgefallen, gehört in ein eigenes Issue

Der Navigationseintrag „Protokoll" (/protokoll) zeigt seit Phase 1 auf eine Seite, die es nicht gibt. Das Audit-Log ist über tRPC abrufbar, hat aber keine Ansicht.

🤖 Generated with Claude Code

Das Modul, wegen dem eine Wehr so ein Programm einführt: Prüffristen im Blick behalten und im Streitfall nachweisen können, dass geprüft wurde. ## Was drin ist **Datenmodell** — elf neue Tabellen, alle mit `organisationId` und Row Level Security: `Wartungsvorlage`, `Checklistenpunkt`, `Wartungstermin`, `Pruefung`, `Pruefergebnis`, `Signatur`, `Mangel`, `Rueckruf`, `RueckrufGeraetetyp`, `RueckrufBetroffenheit`, `Erinnerung`. **Fristen-Dashboard** (`/pruefungen`) — vier Töpfe nach Dringlichkeit (überfällig / diese Woche / diesen Monat / nächste 90 Tage), jede Zahl gleichzeitig ein Filter. Bündelung nach Fahrzeug, Standort, Gerätetyp oder Zuständigem. Sammelzuweisung mehrerer Termine. **Prüfwizard** (`/pruefungen/neu`) — ein Punkt je Bildschirm, Foto aus der Kamera, mitlaufende Zeiterfassung, Unterschrift auf dem Zeichenfeld. Jede Antwort geht sofort zum Server; ein abgebrochener Durchgang wird fortgesetzt. **Prüfprotokoll als PDF** — der Worker rendert über Gotenberg und legt in MinIO ab: Kopf mit Wehr, Gerät und Prüfer-Kennung, Checkliste mit Soll/Ist/Befund, eingebettete Fotos und Unterschriften, Fußzeile mit Prüfvorschrift und Prüfdatum. Laufende Nummer `JJJJ-NNNN` je Wehr und Jahr. **Nächtlicher Lauf** — `fristen.pruefen` (3:15 Uhr) plant Termine und zieht den Gerätestatus nach, `erinnerung.senden` (3:45 Uhr) verschickt Vorwarnungen bei T-30, T-7, T-0 und einmal bei Überfälligkeit, als Sammelnachricht je Empfänger. **Mängel** (`/maengel`) — melden → zugewiesen → in Arbeit → behoben. Melden darf jedes Mitglied; ein kritischer Mangel sperrt das Gerät. **Rückrufe** (`/rueckrufe`) — Suche nach betroffenen Geräten über Bauart, Modell, Seriennummernbereich und Herstellungszeitraum, Sperre auf Wunsch, Stand je Gerät. **Lebensdauer** (`/pruefungen/lebensdauer`) — was abgelaufen ist, mit Aussonderungsvorschlag. ## Die wichtigste Festlegung Ein abgeschlossenes Prüfprotokoll ist **unveränderbar**, und zwar durchgesetzt von einem Datenbanktrigger, nicht vom Anwendungscode. Zulässig bleiben genau drei Änderungen: der Wechsel auf „ersetzt", das Nachtragen des PDF, solange keines hinterlegt ist, und `geaendertAm`. Dasselbe gilt für Einzelergebnisse und Unterschriften — sonst ließe sich ein festgeschriebenes Protokoll über den Umweg seiner Bestandteile ändern. Eine Korrektur erzeugt eine **neue** Prüfung mit Verweis auf die alte. Beide bleiben lesbar. ## Zum Testen ```bash git checkout feat/phase-2-wartung npm install docker compose up -d npm run db:migrate npm run db:seed npm run dev # Anwendung auf :3100 npm run worker # zweites Fenster: plant Termine, erzeugt die PDFs ``` Anmeldung: `admin@beispielwehr.de` / `Feuerwehr2026` 1. **`/pruefungen`** — die vier Zahlen anklicken (filtert die Liste), Bündelung auf „nach Gerätetyp" umschalten. 2. **`/pruefungen/vorlagen`** — fünf Vorlagen aus dem Seed mit echten Prüfvorgaben; eine öffnen, Punkt ergänzen, Reihenfolge mit den Pfeiltasten ändern. 3. **Prüfung durchführen** — im Dashboard auf „Prüfen", Checkliste durchklicken, Foto anhängen, unterschreiben, abschließen. Danach „Protokoll als PDF" (der Worker braucht ein bis zwei Sekunden). 4. **Unveränderbarkeit** — am fertigen Protokoll „Korrektur anlegen": es entsteht ein neuer Entwurf mit den alten Antworten, das alte Protokoll bleibt stehen. 5. **`/maengel`** — Mangel mit Dringlichkeit „kritisch" melden; das Gerät wird gesperrt. Beheben gibt es wieder frei. 6. **`/rueckrufe`** — Beispielrückruf öffnen, Treffer im Bestand zuordnen, Stand je Gerät setzen. ## Nachweise - `npm run typecheck` — ohne Ausgabe - `npm run test` — 161 Tests grün (davon 18 gegen eine echte Datenbank) - `npm run test:e2e` — 71 Tests grün, 2 begründet übersprungen (Desktop und Tablet) - `npm run build` — 30 Routen ## Nebenbei behoben - Zwei gleichzeitig abgeschlossene Prüfungen zogen dieselbe Protokollnummer. Sie wird jetzt unter einer Transaktionssperre je Wehr und Jahr vergeben — gefunden von den E2E-Tests, weil Desktop und Tablet parallel prüfen. - Der Worker ließ sich außerhalb des Containers nicht starten (`.env` wurde nicht geladen, `server-only` warf unter Node). Beide Startbefehle laufen jetzt mit `--conditions=react-server`. ## Aufgefallen, gehört in ein eigenes Issue Der Navigationseintrag „Protokoll" (`/protokoll`) zeigt seit Phase 1 auf eine Seite, die es nicht gibt. Das Audit-Log ist über tRPC abrufbar, hat aber keine Ansicht. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
florian.wilde added 1 commit 2026-09-03 10:08:32 +00:00
Wartungsvorlagen mit Checklisten, Prueftermine aus einem naechtlichen Lauf,
Prueffristen-Dashboard, Pruefwizard mit Foto und Unterschrift, unveraenderliche
Protokolle als PDF, Maengel-Workflow, Rueckrufe und Lebensdauerueberwachung.

Elf neue Tabellen, alle mit organisationId und Row Level Security. Die
Unveraenderbarkeit abgeschlossener Protokolle setzt ein Datenbanktrigger
durch, nicht der Anwendungscode: eine Korrektur erzeugt eine neue Pruefung
mit Verweis auf die alte, beide bleiben lesbar.

79 neue Tests (47 Unit, 10 gegen eine echte Datenbank, 22 E2E).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
florian.wilde merged commit bc62a9c1e8 into main 2026-09-03 10:35:45 +00:00
florian.wilde deleted branch feat/phase-2-wartung 2026-09-03 10:35:45 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: florian.wilde/FireAdministration#3