Ab hier führt die Wehr ihren Bestand in FLORIAN: Standorte, Fahrzeuge samt
Beladeordnung, Gerätetypen als Vorgabe, Geräte mit QR-Etiketten,
Qualifikationen mit Ablaufwarnung und der Import aus vorhandenen Tabellen.
Enthält zusätzlich den Planungs-Commit, der die Kassenverwaltung als Phase 9
ergänzt (Phase-9.md).
Was zu testen ist
Geräteliste (/geraete)
Suche über Inventarnummer, Bezeichnung, Hersteller, Seriennummer
Statusfilter, Sortierung per Klick auf die Spaltenüberschrift
„Spalten": ein- und ausblenden, die Auswahl bleibt nach dem Neuladen erhalten
Mehrere Geräte auswählen → Status setzen, Etiketten drucken
Gerätedetail
QR-Code sichtbar, „Etikett drucken" liefert ein PDF
Beim Prüfintervall steht „(aus dem Gerätetyp)", wenn am Gerät keines gesetzt ist
Verlauf zeigt Einträge aus dem Audit-Log
QR-Route
/g/INV-0001 leitet auf das Gerät weiter
/g/INV-GIBTESNICHT erklärt verständlich, warum nichts gefunden wurde
Abgemeldet aufgerufen: erst Anmeldung, danach das Gerät
Fahrzeuge
Detailseite zeigt die Beladung nach Geräteräumen (G1 … G6, Heck, Dach, MR)
Qualifikationen
Oben steht, was abläuft — gerechnet mit der Vorwarnzeit des jeweiligen Typs
Import (/geraete/importieren)
CSV mit Semikolon und deutschen Datumsangaben hochladen
Zuordnung prüfen, eine Spalte von Hand umstellen → Vorschau passt sich an
Fehlerhafte Zeilen sind rot markiert und werden nicht übernommen
Scannen (/geraete/scannen)
Kamera freigeben und ein Etikett scannen, oder die Nummer eintippen
Behobene Fehler
Fristenrechnung war um einen Tag verschoben.startOfDay aus date-fns
rechnet in der Zeitzone des Servers; ein DATE aus Postgres kommt als
UTC-Mitternacht und wurde dadurch auf den Vortag geschoben. Jede Prüffrist
wäre einen Tag zu früh fällig geworden. Jetzt eigene Kalenderarithmetik auf
UTC-Bestandteilen.
ctx.sitzung blieb in tRPC-Prozeduren nullbar, weil t.middleware() die
Verengung der vorigen Middleware verwirft.
CardTitle war ein div und damit keine Überschrift — Karten fehlten in
der Überschriftennavigation von Sprachausgaben.
Nachweise
Prüfung
Ergebnis
npm run typecheck
ohne Ausgabe
npm run test
104 grün (vorher 32)
npm run test:e2e
44 grün, Desktop und Tablet (vorher 10)
npm run build
17 Routen, 103 kB gemeinsames JavaScript
Browser-Konsole
keine Fehler, keine Hydratationswarnungen
Noch offen
Ein Formular zum einzelnen Anlegen eines Geräts fehlt. Die Router können
anlegen, ändern, umlagern und aussondern; die Oberfläche deckt Liste, Detail,
Massenbearbeitung und Import ab. Geschätzt 0,5 PT, sinnvoll in Phase 2
mitzunehmen — dort entstehen ohnehin Formulare. Steht so in docs/DEVLOG.md.
Ab hier führt die Wehr ihren Bestand in FLORIAN: Standorte, Fahrzeuge samt
Beladeordnung, Gerätetypen als Vorgabe, Geräte mit QR-Etiketten,
Qualifikationen mit Ablaufwarnung und der Import aus vorhandenen Tabellen.
Enthält zusätzlich den Planungs-Commit, der die Kassenverwaltung als Phase 9
ergänzt (`Phase-9.md`).
## Was zu testen ist
**Geräteliste** (`/geraete`)
- Suche über Inventarnummer, Bezeichnung, Hersteller, Seriennummer
- Statusfilter, Sortierung per Klick auf die Spaltenüberschrift
- „Spalten": ein- und ausblenden, die Auswahl bleibt nach dem Neuladen erhalten
- Mehrere Geräte auswählen → Status setzen, Etiketten drucken
**Gerätedetail**
- QR-Code sichtbar, „Etikett drucken" liefert ein PDF
- Beim Prüfintervall steht „(aus dem Gerätetyp)", wenn am Gerät keines gesetzt ist
- Verlauf zeigt Einträge aus dem Audit-Log
**QR-Route**
- `/g/INV-0001` leitet auf das Gerät weiter
- `/g/INV-GIBTESNICHT` erklärt verständlich, warum nichts gefunden wurde
- Abgemeldet aufgerufen: erst Anmeldung, danach das Gerät
**Fahrzeuge**
- Detailseite zeigt die Beladung nach Geräteräumen (G1 … G6, Heck, Dach, MR)
**Qualifikationen**
- Oben steht, was abläuft — gerechnet mit der Vorwarnzeit des jeweiligen Typs
**Import** (`/geraete/importieren`)
- CSV mit Semikolon und deutschen Datumsangaben hochladen
- Zuordnung prüfen, eine Spalte von Hand umstellen → Vorschau passt sich an
- Fehlerhafte Zeilen sind rot markiert und werden nicht übernommen
**Scannen** (`/geraete/scannen`)
- Kamera freigeben und ein Etikett scannen, oder die Nummer eintippen
## Behobene Fehler
- **Fristenrechnung war um einen Tag verschoben.** `startOfDay` aus date-fns
rechnet in der Zeitzone des Servers; ein `DATE` aus Postgres kommt als
UTC-Mitternacht und wurde dadurch auf den Vortag geschoben. Jede Prüffrist
wäre einen Tag zu früh fällig geworden. Jetzt eigene Kalenderarithmetik auf
UTC-Bestandteilen.
- **`ctx.sitzung` blieb in tRPC-Prozeduren nullbar**, weil `t.middleware()` die
Verengung der vorigen Middleware verwirft.
- **`CardTitle` war ein `div`** und damit keine Überschrift — Karten fehlten in
der Überschriftennavigation von Sprachausgaben.
## Nachweise
| Prüfung | Ergebnis |
|---|---|
| `npm run typecheck` | ohne Ausgabe |
| `npm run test` | 104 grün (vorher 32) |
| `npm run test:e2e` | 44 grün, Desktop und Tablet (vorher 10) |
| `npm run build` | 17 Routen, 103 kB gemeinsames JavaScript |
| Browser-Konsole | keine Fehler, keine Hydratationswarnungen |
## Noch offen
Ein Formular zum einzelnen Anlegen eines Geräts fehlt. Die Router können
anlegen, ändern, umlagern und aussondern; die Oberfläche deckt Liste, Detail,
Massenbearbeitung und Import ab. Geschätzt 0,5 PT, sinnvoll in Phase 2
mitzunehmen — dort entstehen ohnehin Formulare. Steht so in `docs/DEVLOG.md`.
Die Rolle KASSIER war seit Phase 0 angelegt, ein Kassenmodul fehlte in der
Planung. Phase-9.md beschreibt es jetzt: Konten, Buchungen mit Beleg,
Beitragslauf mit Mahnstufen, Rechnungen, Kassenabschluss und Auswertungen.
Geschaetzt 8-11 PT, Version 0.10.0.
Zwei Festlegungen aus der Spezifikation, weil sie den Rest bestimmen: eine
festgeschriebene Buchung ist unveraenderbar und wird nur ueber eine
Gegenbuchung korrigiert; der Kassenabschluss friert seinen Zeitraum ein.
Ausserdem als entschieden festgehalten:
- Berechtigung bleibt ohne organisationId. Die Tabelle ist der systemweite
Katalog dessen, was die Software kann; mandantenbezogen wird es erst ueber
RolleBerechtigung.
- Die Loeschausnahme im Audit-Log bleibt. UPDATE ist dauerhaft gesperrt,
DELETE nur im gekennzeichneten Aufbewahrungslauf des Workers.
Roadmap, Aufwandsschaetzung, Versionierung, README und die Seitenleiste sind
entsprechend ergaenzt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ab hier fuehrt die Wehr ihren Bestand in FLORIAN.
Datenmodell:
- Standort, Geraeteraum, Geraetetyp, Qualifikationstyp und Qualifikation
- Fahrzeug um Fahrgestellnummer, DIN-Typ, Erstzulassung, Sitzplaetze,
Tankinhalt und UVV-Frist erweitert
- Geraet um Geraetetyp, Lebensdauerkategorie, errechnetes Lebensdauerende,
Anschaffungspreis und die Lagerung erweitert
- Ein Geraet steht entweder an einem Standort oder ist auf einem Fahrzeug
verlastet. Eine Pruefbedingung setzt das durch, ein Trigger stellt zusaetzlich
sicher, dass ein angegebener Geraeteraum zum angegebenen Fahrzeug gehoert.
- RLS auf allen neuen Tabellen, Trigram-Indizes fuer die Volltextsuche
Fachlogik:
- lib/stammdaten/fristen.ts rechnet Prueftermine, Lebensdauer und den
abgeleiteten Geraetestatus. Der Geraetetyp gibt vor, das Geraet darf
abweichen.
- lib/stammdaten/qr.ts und qr-parser.ts erzeugen und lesen die Codes
- lib/stammdaten/etiketten.ts baut den A4-Bogen mit 65 Etiketten
- lib/stammdaten/import.ts liest CSV und Excel, erkennt deutsche Datums- und
Zahlenformate, Windows-1252 und Dubletten innerhalb der Datei
- lib/pdf.ts spricht Gotenberg an
Oberflaeche:
- Geraeteliste mit Volltextsuche, Statusfilter, serverseitiger Sortierung,
Blaettern, Spaltenauswahl und Massenbearbeitung
- Geraetedetail mit QR-Code, Pruefvorgabe aus dem Geraetetyp und Verlauf
- Fahrzeugliste und -detail mit Beladung nach Beladeordnung
- Mitgliederliste nach Abteilung, Mitgliedsdetail mit Qualifikationen
- Qualifikationen mit Ablaufwarnung je Vorwarnzeit des Typs
- Import-Assistent mit Zuordnung und Vorschau vor dem Uebernehmen
- QR-Scanner ueber die Kamera, mit Eingabefeld als Rueckfallweg
Behoben:
- Fristenrechnung lief ueber startOfDay aus date-fns und damit in der Zeitzone
des Servers. Ein DATE aus der Datenbank kommt als UTC-Mitternacht und wurde
dadurch auf den Vortag geschoben — Fristen waeren einen Tag zu frueh faellig
geworden. Jetzt eigene Kalenderarithmetik auf UTC-Bestandteilen.
- ctx.sitzung blieb in tRPC-Prozeduren nullbar, weil t.middleware() die
Verengung der vorigen Middleware verwirft. Middleware jetzt direkt an .use().
- CardTitle war ein div und damit keine Ueberschrift. Wer mit einer
Sprachausgabe arbeitet, springt von Ueberschrift zu Ueberschrift; Karten
tauchten in dieser Navigation nicht auf.
Daten und Tests:
- Seed um 3 Standorte, 20 Geraeteraeume, 14 Geraetetypen mit echten
Pruefvorgaben, 49 Geraete und 107 Qualifikationen erweitert
- 104 Vitest-Tests (vorher 32), 44 Playwright-Tests (vorher 10)
- Anleitung um sieben bebilderte Abschnitte erweitert, Changelog, Devlog,
Aufwandsschaetzung und Roadmap fortgeschrieben
Co-Authored-By: Claude Opus 5 <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.
Ab hier führt die Wehr ihren Bestand in FLORIAN: Standorte, Fahrzeuge samt
Beladeordnung, Gerätetypen als Vorgabe, Geräte mit QR-Etiketten,
Qualifikationen mit Ablaufwarnung und der Import aus vorhandenen Tabellen.
Enthält zusätzlich den Planungs-Commit, der die Kassenverwaltung als Phase 9
ergänzt (
Phase-9.md).Was zu testen ist
Geräteliste (
/geraete)Gerätedetail
QR-Route
/g/INV-0001leitet auf das Gerät weiter/g/INV-GIBTESNICHTerklärt verständlich, warum nichts gefunden wurdeFahrzeuge
Qualifikationen
Import (
/geraete/importieren)Scannen (
/geraete/scannen)Behobene Fehler
startOfDayaus date-fnsrechnet in der Zeitzone des Servers; ein
DATEaus Postgres kommt alsUTC-Mitternacht und wurde dadurch auf den Vortag geschoben. Jede Prüffrist
wäre einen Tag zu früh fällig geworden. Jetzt eigene Kalenderarithmetik auf
UTC-Bestandteilen.
ctx.sitzungblieb in tRPC-Prozeduren nullbar, weilt.middleware()dieVerengung der vorigen Middleware verwirft.
CardTitlewar eindivund damit keine Überschrift — Karten fehlten inder Überschriftennavigation von Sprachausgaben.
Nachweise
npm run typechecknpm run testnpm run test:e2enpm run buildNoch offen
Ein Formular zum einzelnen Anlegen eines Geräts fehlt. Die Router können
anlegen, ändern, umlagern und aussondern; die Oberfläche deckt Liste, Detail,
Massenbearbeitung und Import ab. Geschätzt 0,5 PT, sinnvoll in Phase 2
mitzunehmen — dort entstehen ohnehin Formulare. Steht so in
docs/DEVLOG.md.