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>
44 lines
1.6 KiB
TypeScript
44 lines
1.6 KiB
TypeScript
/**
|
|
* Laufende Nummern je Wehr und Jahr.
|
|
*
|
|
* Prüfprotokolle, Einsätze und Übungen tragen dieselbe Art von Nummer:
|
|
* `JJJJ-NNNN`, fortlaufend innerhalb eines Jahres, je Wehr getrennt. Sie steht
|
|
* auf Papier und wird am Telefon genannt — deshalb kurz, sprechbar und ohne
|
|
* Bindestrichwüste.
|
|
*
|
|
* Die Nummern werden nie wiederverwendet. Vergeben wird die höchste vorhandene
|
|
* plus eins, nicht die Anzahl der Datensätze; sonst bekäme ein im
|
|
* Aufbewahrungslauf entfernter Vorgang seine Nummer an einen neuen vererbt.
|
|
*
|
|
* Reine Zeichenkettenarbeit, kein Datenbankzugriff: wer die Nummer vergibt,
|
|
* muss dabei selbst für eine Sperre sorgen (siehe `abschliessen` im
|
|
* Prüfungs-Router und `anlegen` im Einsatz-Router).
|
|
*/
|
|
|
|
/** Vier Stellen reichen für 9999 Vorgänge im Jahr — mehr hat keine Wehr. */
|
|
const STELLEN = 4;
|
|
|
|
/** Bildet "2026-0042". */
|
|
export function nummerBilden(jahr: number, laufend: number): string {
|
|
return `${jahr}-${String(laufend).padStart(STELLEN, "0")}`;
|
|
}
|
|
|
|
/** Zerlegt eine Nummer wieder. Gibt null zurück, wenn sie nicht passt. */
|
|
export function nummerLesen(
|
|
nummer: string | null | undefined,
|
|
): { jahr: number; laufend: number } | null {
|
|
if (!nummer) return null;
|
|
const treffer = /^(\d{4})-(\d{1,6})$/.exec(nummer.trim());
|
|
if (!treffer) return null;
|
|
return { jahr: Number(treffer[1]), laufend: Number(treffer[2]) };
|
|
}
|
|
|
|
/**
|
|
* Die nächste Nummer nach der bisher höchsten.
|
|
*
|
|
* @param hoechste die bisher höchste Nummer des Jahres, oder null
|
|
*/
|
|
export function naechsteNummer(jahr: number, hoechste: string | null | undefined): string {
|
|
return nummerBilden(jahr, (nummerLesen(hoechste)?.laufend ?? 0) + 1);
|
|
}
|