Phase 3: Einsatz- und Uebungserfassung

Schnellerfassung im Alarmfall, sechs Zeitstempel mit Ausrueckzeit, Anfahrt
und Hilfsfrist, Staerke nach FwDV 3, Personalvorschlag mit
Qualifikationsstand, Einsatzbericht als PDF, Jahresexport fuer die Gemeinde,
Statistik und Uebungen mit Anwesenheitsliste.

Dazu das Einsatzportal fuer Fremdwehren: ein signierter Link ohne Anmeldung,
zeitlich und mengenbegrenzt, der Stichwort, Ort, Zeiten und Lagemeldungen
zeigt und Meldungen mit Foto annimmt. Es sind die ersten oeffentlich
erreichbaren Endpunkte in FLORIAN.

Acht neue Tabellen, alle mit organisationId und Row Level Security. Ein
freigegebener Einsatzbericht ist unveraenderlich; ein Datenbanktrigger setzt
das durch. Koordinaten liegen doppelt — als Dezimalgrad und als
PostGIS-Punkt, zusammengehalten von einem Trigger.

57 neue Tests (32 Unit, 14 gegen eine echte Datenbank, 11 E2E).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Florian Wilde
2026-09-03 13:50:58 +02:00
co-authored by Claude Opus 5
parent bc62a9c1e8
commit 91954c402b
100 changed files with 9667 additions and 38 deletions
+124 -1
View File
@@ -26,7 +26,7 @@ Anmelden mit `SEED_ADMIN_EMAIL` und `SEED_ADMIN_PASSWORT` aus der `.env`
| Phase 0 — Fundament | fertig |
| Phase 1 — Stammdaten | fertig |
| Phase 2 — Wartung und Prüfung | fertig |
| Phase 3 — Einsätze und Übungen | offen |
| Phase 3 — Einsätze und Übungen | fertig |
| Phase 4 — Kiosk-PWA | offen |
| Phase 5 — Atemschutz (FwDV 7) | offen |
| Phase 6 — Kartenmodule | offen |
@@ -279,6 +279,129 @@ passt selten eins zu eins auf die Seriennummern im eigenen Bestand.
| `WARTUNG_PLANUNGSHORIZONT_TAGE` | `180` | wie weit im Voraus Termine angelegt werden |
---
## Phase 3 — Einsätze und Übungen
Was die Wehr tut, wird hier dokumentiert — für die Gemeinde, für die
Versicherung und für die eigene Mannschaft.
### Der Weg durch das Modul
```
Schnellerfassung Stichwort, Ort, Fahrzeuge — im Alarmfall in 20 Sekunden
↓ während des Einsatzes
Zeitstempel alarmiert, ausgerückt, eingetroffen, Ende, eingerückt,
einsatzbereit — je ein Knopf
Lagemeldungen aus der Wehr und über das Portal einer Fremdwehr
↓ danach, in Ruhe
Kräfte und Material wer war dabei, was wurde verbraucht
Bericht der Text des Einsatzleiters
↓ Freigabe
Einsatzbericht als PDF, festgeschrieben, an die Gemeinde
```
### Die sechs Zeitstempel
Sie sind der Kern jeder Einsatzauswertung. Aus ihnen ergeben sich drei Zahlen:
| Kennzahl | Rechnung | sagt etwas aus über |
|---|---|---|
| **Ausrückzeit** | Alarm bis Ausrücken | die Wehr selbst |
| **Anfahrtszeit** | Ausrücken bis Eintreffen | Lage und Wegstrecke |
| **Hilfsfrist** | Alarm bis Eintreffen | das, wonach die Gemeinde fragt |
In Bayern gilt als Ziel: **in 80 Prozent der Fälle innerhalb von zehn Minuten**.
Genau dieser Wert steht in der Statistik — nicht der Durchschnitt, denn der
verdeckt die Ausreißer, um die es geht.
### Stärke nach FwDV 3
Aus den Funktionen der erfassten Kräfte errechnet FLORIAN die Stärke in der
üblichen Schreibweise `Führer/Unterführer/Mannschaft/Gesamt`:
| Einheit | Stärke | Besetzung |
|---|---|---|
| Trupp | 0/1/1/2 | Truppführer, Truppmann |
| Staffel | 1/1/4/6 | Gruppenführer, Maschinist, zwei Trupps |
| Gruppe | 1/3/5/9 | Gruppenführer, Maschinist, Melder, drei Trupps |
| Zug | 1/5/12/18 | Zugführer, Melder, Gruppe und Staffel |
**Regional unterschiedlich.** Manche Wehren zählen den Maschinisten zu den
Unterführern, andere schreiben dreistellig ohne Unterführer (Gruppe = 1/8/9).
Die Zuordnung steht an einer Stelle — [`src/lib/einsatz/staerke.ts`](src/lib/einsatz/staerke.ts) —
und ist bewusst leicht zu ändern.
### Der freigegebene Bericht ist unveränderbar
Dieselbe Logik wie beim Prüfprotokoll aus Phase 2, denn der Bericht geht an
die Gemeinde und im Schadensfall an die Versicherung. Bis zur Freigabe ist
alles änderbar — ein Einsatz wird tagelang ergänzt, und genau dafür ist der
Entwurfsstand da. Mit der Freigabe ist Schluss; der Trigger
`einsatz_freigabe_schuetzen` setzt das durch.
Zwei Ausnahmen bleiben, beide nachtragend: das PDF, solange keines hinterlegt
ist, und `geaendertAm`.
**Lagemeldungen sind ausdrücklich ausgenommen.** Sie sind das Protokoll des
Verlaufs, kein Bestandteil des Berichts — und eine Meldung aus dem Portal kann
eintreffen, wenn der Bericht längst geschrieben ist.
### Einsatzportal für Fremdwehren
Bei einer größeren Sache sind Nachbarwehren, THW oder Rettungsdienst mit vor
Ort. Die haben kein Konto in FLORIAN und sollen auch keines bekommen. Der
Einsatzleiter erzeugt stattdessen einen Link, den er als QR-Code zeigt oder
weiterschickt.
Vier Schranken sichern ihn ab:
1. **Zufall** — 32 zufällige Bytes im Link.
2. **Nur ein Hash in der Datenbank** — wer sie liest, bekommt keinen gültigen Link.
3. **Zeitlich begrenzt** — Vorgabe 24 Stunden, jederzeit widerrufbar, jeder
Aufruf wird mitgezählt.
4. **Zugriffsbegrenzung** — 120 Aufrufe je Link und Stunde, 30 Meldungen, 10
Fotos.
Und eine fünfte, die keine technische ist: das Portal zeigt Stichwort, Ort,
Zeitstempel und Lagemeldungen. **Keine Namen von Einsatzkräften, keine
Berichte, kein Weg in den Rest der Anwendung.**
### Adressen zu Koordinaten
Über einen **selbst betriebenen** Nominatim (`NOMINATIM_URL`). Einsatzadressen
sagen, wo es gebrannt hat und wer betroffen war; solche Anfragen gehören nicht
an einen fremden Dienst, und die Nutzungsbedingungen des öffentlichen Nominatim
erlauben es ohnehin nicht.
Ohne Konfiguration bleibt das Feld leer und die Koordinaten werden von Hand
eingetragen — kein Fehler, sondern der Normalfall in einer frischen
Installation. Die Karte dazu kommt in Phase 6.
Gespeichert wird doppelt: als Dezimalgrad, die Prisma lesen kann, und als
PostGIS-Punkt für die Karte. Ein Trigger hält beides zusammen.
### Statistik und Jahresexport
`/einsaetze/statistik` beantwortet beide Fragen: die der Gemeinde (Anzahl nach
Kategorie der Landesstatistik, Hilfsfristen) und die der Wehr (Beteiligung je
Person, Auslastung je Fahrzeug). Der Jahresexport als PDF liegt unter
`/api/einsaetze/jahresexport?jahr=…` und wird bewusst **nicht** abgelegt — er
ist eine Auswertung, keine Urkunde, und ändert sich, solange noch Einsätze
nachgetragen werden.
### Zusätzliche Umgebungsvariablen
| Variable | Vorgabe | Bedeutung |
|---|---|---|
| `GEOCODING_ENABLED` | `false` | Adresssuche einschalten |
| `NOMINATIM_URL` | — | Adresse des eigenen Nominatim |
| `GEOCODING_LAENDER` | `de,at,ch` | Eingrenzung der Suche |
| `PORTAL_ENABLED` | `true` | Einsatzportal für Fremdwehren |
| `PORTAL_GUELTIGKEIT_STUNDEN` | `24` | Lebensdauer eines Links |
| `PORTAL_MAX_ZUGRIFFE` | `120` | Aufrufe je Link und Stunde |
---
## Befehle