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
/pruefungen — die vier Zahlen anklicken (filtert die Liste), Bündelung auf „nach Gerätetyp" umschalten.
/pruefungen/vorlagen — fünf Vorlagen aus dem Seed mit echten Prüfvorgaben; eine öffnen, Punkt ergänzen, Reihenfolge mit den Pfeiltasten ändern.
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).
Unveränderbarkeit — am fertigen Protokoll „Korrektur anlegen": es entsteht ein neuer Entwurf mit den alten Antworten, das alte Protokoll bleibt stehen.
/maengel — Mangel mit Dringlichkeit „kritisch" melden; das Gerät wird gesperrt. Beheben gibt es wieder frei.
/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.
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)
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>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
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
organisationIdund 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-NNNNje 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
Anmeldung:
admin@beispielwehr.de/Feuerwehr2026/pruefungen— die vier Zahlen anklicken (filtert die Liste), Bündelung auf „nach Gerätetyp" umschalten./pruefungen/vorlagen— fünf Vorlagen aus dem Seed mit echten Prüfvorgaben; eine öffnen, Punkt ergänzen, Reihenfolge mit den Pfeiltasten ändern./maengel— Mangel mit Dringlichkeit „kritisch" melden; das Gerät wird gesperrt. Beheben gibt es wieder frei./rueckrufe— Beispielrückruf öffnen, Treffer im Bestand zuordnen, Stand je Gerät setzen.Nachweise
npm run typecheck— ohne Ausgabenpm 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 RoutenNebenbei behoben
.envwurde nicht geladen,server-onlywarf 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