Kassenverwaltung als Phase 9 ergaenzen, Festlegungen dokumentieren

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>
This commit is contained in:
Florian Wilde
2026-09-03 07:11:37 +02:00
co-authored by Claude Opus 5
parent 845942f36c
commit 4b3021bb50
7 changed files with 103 additions and 31 deletions
+38
View File
@@ -0,0 +1,38 @@
Phase 9: Kassenverwaltung.
Ergänzt am 03.09.2026. Die Rolle KASSIER ist seit Phase 0 angelegt, ein Modul
dazu fehlte in der ursprünglichen Planung.
Modelle: Kassenkonto (Bezeichnung, Art: bar | bank | ruecklage, IBAN,
Anfangsbestand, aktiv), Buchungskategorie (Name, Art: einnahme | ausgabe,
Oberkategorie, Konto im Kontenrahmen), Buchung (Konto, Kategorie, Datum,
Betrag, Verwendungszweck, Belegnummer, Gegenkonto, Person ODER
Lieferant, Beleg als Datei, festgeschrieben), Beitragssatz (Bezeichnung,
Betrag je Jahr, gilt für Abteilung), Beitrag (Person, Jahr, Satz, Betrag,
Status: offen | bezahlt | erlassen | gemahnt, bezahlt_am),
Rechnung (Empfänger, Positionen, Betrag, Datum, faellig_am, Status),
Kassenabschluss (Zeitraum, Kassenbestand laut Buch, gezählter Bestand,
Differenz, Prüfer, geprueft_am, Bericht als PDF).
Funktionen:
- Buchungsmaske mit Kategorievorschlag aus dem Verwendungszweck
- Beleg als Foto oder PDF anhängen, Ablage in MinIO
- Beitragslauf: erzeugt für ein Jahr alle Beiträge nach Abteilung,
Mahnstufen mit Vorlage, Zahlungseingang manuell oder per CSV-Abgleich
aus dem Bankkonto (CAMT.053 oder MT940)
- Rechnungen an Dritte (Fehlalarm, Öleinsatz, Vereinsveranstaltung) mit
Nummernkreis und PDF über Gotenberg
- Kassenabschluss: Zeitraum wählen, Bestand zählen, Differenz erklären,
Kassenprüfbericht als PDF mit Unterschriftsfeldern
- Auswertungen: Einnahmen/Ausgaben nach Kategorie und Monat,
Jahresvergleich, offene Posten, Beitragsrückstände
- Export für den Steuerberater und für die Kassenprüfung der Gemeinde
Wichtig:
- Eine festgeschriebene Buchung ist unveränderbar. Korrekturen erfolgen über
eine Gegenbuchung mit Verweis, nie durch Ändern.
- Der Kassenabschluss friert den Zeitraum ein: danach sind Buchungen mit
Datum in diesem Zeitraum nicht mehr möglich.
- Beträge als DECIMAL(12,2), niemals als Fließkommazahl.
- Der Kassier sieht keine Geräte- oder Atemschutzdaten, der Gerätewart keine
Buchungen. Die Trennung ist in lib/authz.ts bereits angelegt.
+1
View File
@@ -32,6 +32,7 @@ Anmelden mit `SEED_ADMIN_EMAIL` und `SEED_ADMIN_PASSWORT` aus der `.env`
| Phase 6 — Kartenmodule | offen |
| Phase 7 — Benachrichtigungen und Termine | offen |
| Phase 8 — Lokale KI | offen |
| Phase 9 — Kassenverwaltung | offen |
Vollständige Planung mit Aufwänden: [docs/ROADMAP.md](docs/ROADMAP.md) und
[docs/AUFWANDSSCHAETZUNG.md](docs/AUFWANDSSCHAETZUNG.md).
+24 -9
View File
@@ -39,9 +39,10 @@ Faktoren, die in die Schätzung eingehen:
| 6 | Kartenmodule | 14–18 PT | 3,5–4,5 h | offen |
| 7 | Benachrichtigungen und Termine | 10–13 PT | 2,5–3,5 h | offen |
| 8 | Lokale KI | 9–12 PT | 2,5–3 h | offen |
| | **Summe** | **115–153 PT** | **26–34 h** | |
| 9 | Kassenverwaltung | 8–11 PT | 2–3 h | offen |
| | **Summe** | **123–164 PT** | **28–37 h** | |
115–153 Personentage entsprechen etwa **6 bis 8 Monaten Vollzeitarbeit** einer
123–164 Personentage entsprechen etwa **6 bis 8 Monaten Vollzeitarbeit** einer
einzelnen Person. Zum Vergleich: eine kommerzielle Feuerwehrverwaltung kostet
je nach Umfang 500 bis 2.500 Euro im Jahr, dauerhaft, mit den Daten beim
Anbieter.
@@ -221,17 +222,31 @@ Kennzeichnungspflicht — jede KI-Ausgabe ist als solche erkennbar und muss
bestätigt werden, bevor sie in ein Dokument mit Nachweischarakter gelangt —
kostet wenig Zeit, ist aber nicht verhandelbar.
## Phase 9 — Kassenverwaltung
**Vergleichsaufwand: 8–11 PT** — am 03.09.2026 ergänzt
| Baustein | PT |
|---|---:|
| Modelle: Konto, Kategorie, Buchung, Beitragssatz, Beitrag, Rechnung, Abschluss | 2,0 |
| Buchungsmaske mit Kategorievorschlag, Beleg als Datei | 1,5 |
| Beitragslauf, Mahnstufen, Zahlungsabgleich aus CAMT.053 oder MT940 | 2,5 |
| Rechnungen mit Nummernkreis und PDF | 1,0 |
| Kassenabschluss mit Zeitraumsperre und Prüfbericht | 1,5 |
| Auswertungen und Exporte | 1,5 |
Der Zahlungsabgleich ist der unsichere Posten: CAMT.053 ist gut spezifiziert,
MT940 dagegen je nach Bank unterschiedlich ausgelegt. Falls die Hausbank nur
MT940 liefert, kommt ein halber bis ganzer Tag für die Eigenheiten dazu.
Die Unveränderlichkeit festgeschriebener Buchungen kostet hier fast nichts —
das Muster steht seit Phase 0 mit dem Audit-Log-Trigger und lässt sich
übernehmen.
---
## Was hier nicht drin ist
**Kassenmodul.** Die Rolle `KASSIER` ist in Phase 0 gefordert und angelegt,
die Rechte `kasse.lesen`, `kasse.bearbeiten` und `kasse.abschluss` stehen
bereit. Ein Kassenmodul kommt in keiner der Phasen 0 bis 8 vor. Geschätzter
Vergleichsaufwand, falls gewünscht: **8–11 PT** für Buchungen, Beiträge,
Rechnungen, Kassenabschluss und Jahresauswertung. Siehe
[ROADMAP.md](ROADMAP.md).
**Betrieb und Einführung.** Datenübernahme aus der Altsoftware, Schulung der
Wehr, Sicherungskonzept, Monitoring: nach Erfahrung noch einmal 15 bis 25
Prozent des Entwicklungsaufwands.
+31 -17
View File
@@ -18,6 +18,7 @@ Phase 5 ░░░░░░░░░░░░░░░░░░░░ offen
Phase 6 ░░░░░░░░░░░░░░░░░░░░ offen 0.7.0
Phase 7 ░░░░░░░░░░░░░░░░░░░░ offen 0.8.0
Phase 8 ░░░░░░░░░░░░░░░░░░░░ offen 0.9.0
Phase 9 ░░░░░░░░░░░░░░░░░░░░ offen 0.10.0
Freigabe ░░░░░░░░░░░░░░░░░░░░ offen 1.0.0
```
@@ -159,6 +160,28 @@ Alles gegen Ollama, kein externer Anbieter, komplett abschaltbar.
Jede KI-Ausgabe ist gekennzeichnet und muss bestätigt werden, bevor sie in ein
Dokument mit Nachweischarakter gelangt.
## Phase 9 — Kassenverwaltung
Am 03.09.2026 ergänzt. Die Rolle `KASSIER` war seit Phase 0 angelegt, ein Modul
dazu fehlte in der ursprünglichen Planung. Spezifikation: `Phase-9.md`.
- Kassenkonten (Bar, Bank, Rücklage), Buchungskategorien, Buchungen mit Beleg
- Beitragslauf je Jahr nach Abteilung, Mahnstufen, Zahlungsabgleich aus
CAMT.053 oder MT940
- Rechnungen an Dritte mit Nummernkreis und PDF
- Kassenabschluss mit gezähltem Bestand, Differenz und Kassenprüfbericht
- Auswertungen nach Kategorie und Monat, offene Posten, Beitragsrückstände
- Export für Steuerberater und Kassenprüfung der Gemeinde
Zwei Festlegungen, die den Rest bestimmen: eine festgeschriebene Buchung ist
unveränderbar — Korrekturen laufen über eine Gegenbuchung mit Verweis. Und der
Kassenabschluss friert seinen Zeitraum ein, danach nimmt die Buchungsmaske
kein Datum daraus mehr an. Beträge durchgängig als `DECIMAL(12,2)`, nie als
Fließkommazahl.
**Danach kann die Wehr:** ihre Kasse führen und den Kassenprüfbericht auf
Knopfdruck erzeugen.
## 1.0.0 — Freigabe
Kein neues Modul, sondern eine Entscheidung: die Wehr setzt FLORIAN im
@@ -173,26 +196,17 @@ Echtbetrieb ein. Voraussetzungen:
---
## Offene Punkte
## Getroffene Festlegungen
### Kassenmodul fehlt in der Phasenplanung
Am 03.09.2026 entschieden:
Phase 0 verlangt die Rolle `KASSIER`, und sie ist angelegt — mit den Rechten
`kasse.lesen`, `kasse.bearbeiten` und `kasse.abschluss`. Ein Kassenmodul kommt
in keiner der Phasen 0 bis 8 vor. Die Rolle hätte also dauerhaft Rechte ohne
zugehörige Oberfläche.
| Punkt | Entscheidung |
|---|---|
| Kassenmodul | Wird als **Phase 9** ergänzt. Spezifikation in `Phase-9.md`, Aufwand 8–11 PT. |
| `Berechtigung` ohne `organisationId` | Bleibt so. Die Tabelle ist der systemweite Katalog dessen, was die Software kann, für alle Wehren identisch — mandantenbezogen wird es erst über `RolleBerechtigung`. Für die Anwendungsrolle nur lesbar. |
| Löschausnahme im Audit-Log | Bleibt so. `UPDATE` ist dauerhaft gesperrt, `DELETE` nur mit `SET LOCAL app.audit_bereinigung = 'an'` im Aufbewahrungslauf des Workers. Ohne diese Ausnahme wäre das Löschkonzept nach DSGVO nicht umsetzbar. |
Zwei Wege:
1. **Phase 9 ergänzen** — Buchungen, Beiträge, Rechnungen, Kassenabschluss,
Jahresauswertung. Geschätzt 8–11 PT.
2. **Rolle belassen, Modul streichen** — der Kassier nutzt weiterhin seine
bisherige Lösung, die Rechte bleiben als Platzhalter stehen.
Solange das nicht entschieden ist, bleiben die Rechte im Katalog, aber es gibt
keinen Navigationseintrag dafür.
### Weitere Kandidaten für später
## Weitere Kandidaten für später
| Idee | Nutzen | grob |
|---|---|---:|
+5 -1
View File
@@ -30,9 +30,13 @@ Versionsnummer eine Aussage über den Funktionsumfang.
| `0.7.0` | Phase 6 — Kartenmodule |
| `0.8.0` | Phase 7 — Benachrichtigungen und Termine |
| `0.9.0` | Phase 8 — Lokale KI |
| `0.10.0` | Phase 9 — Kassenverwaltung |
| `1.0.0` | Freigabe für den Wirkbetrieb durch die Wehr |
`1.0.0` ist bewusst an die **Freigabe** gebunden, nicht an Phase 8. Erst wenn
`0.10.0` ist nach SemVer korrekt größer als `0.9.0` — die Stellen werden als
Zahlen verglichen, nicht als Text.
`1.0.0` ist bewusst an die **Freigabe** gebunden, nicht an die letzte Phase. Erst wenn
eine Wehr die Software im Echtbetrieb einsetzt, darf die analoge Überwachung
zurücktreten — und erst dann ist eine Zusage über Stabilität ehrlich.
+3 -1
View File
@@ -15,6 +15,7 @@ import {
MonitorSmartphone,
Siren,
Truck,
Wallet,
Users,
Wrench,
X,
@@ -31,7 +32,7 @@ import type { Recht, Rolle } from "@/lib/authz";
* bleibt in lib/authz.ts, wie es die Projektregeln verlangen. Ein ausgeblendeter
* Eintrag ist Bequemlichkeit, kein Schutz; der Schutz sitzt in der tRPC-Schicht.
*
* Die Phasenangaben entsprechen den Dateien Phase-0.md bis Phase-8.md.
* Die Phasenangaben entsprechen den Dateien Phase-0.md bis Phase-9.md.
*/
interface Eintrag {
@@ -86,6 +87,7 @@ const EINTRAEGE: Eintrag[] = [
rechte: ["ausbildung.lesen"],
abPhase: 7,
},
{ titel: "Kasse", pfad: "/kasse", symbol: Wallet, rechte: ["kasse.lesen"], abPhase: 9 },
{
titel: "Protokoll",
pfad: "/protokoll",
+1 -3
View File
@@ -114,9 +114,7 @@ export const RECHTE = {
"qualifikation.lesen": { bereich: "Ausbildung", bezeichnung: "Qualifikationen ansehen" },
"qualifikation.bearbeiten": { bereich: "Ausbildung", bezeichnung: "Qualifikationen pflegen" },
// Kasse — die Rolle KASSIER ist in Phase 0 gefordert, ein Kassenmodul ist
// in Phase-0.md bis Phase-8.md aber nicht vorgesehen. Die Rechte stehen hier
// bereits bereit, damit die Rolle nicht leer bleibt. Siehe docs/ROADMAP.md.
// Kasse (Phase 9)
"kasse.lesen": { bereich: "Kasse", bezeichnung: "Buchungen und Auswertungen ansehen" },
"kasse.bearbeiten": { bereich: "Kasse", bezeichnung: "Buchungen erfassen" },
"kasse.abschluss": { bereich: "Kasse", bezeichnung: "Kassenabschluss durchführen" },