Phase 9: Kassenverwaltung

Kassenbuch, Mitgliedsbeitraege, Rechnungen an Dritte, Kassenpruefung und
die Auswertungen fuer die Jahreshauptversammlung.

Die drei Festlegungen aus Phase-9.md sitzen in der Datenbank, nicht im
Router: eine festgeschriebene Buchung ist unveraenderbar, ein geprueftes
Jahr nimmt kein Datum mehr an, und gerechnet wird mit Prisma.Decimal.
Korrigiert wird ueber eine Gegenbuchung mit Verweis - beide Buchungen
bleiben stehen, damit im Kassenbuch zu sehen ist, dass etwas berichtigt
wurde.

Neun Modelle, drei Trigger, zwoelf CHECKs, sechs Router, fuenf Ansichten.
Dazu der Bankimport fuer CAMT.053 und MT940 ohne Fremdbibliothek, der
Kategorievorschlag aus dem eigenen Buchungsbestand und die Bruecke von
Phase 8: aus einem gegengezeichneten Beleg wird eine Buchung, das Foto
haengt danach an ihr.

Nebenbei behoben: die Rechnungsnummer war ein Wettlauf, und eine
Organisation liess sich nicht mehr loeschen, sobald sie eine
festgeschriebene Buchung hatte - der Trigger kannte den
Aufbewahrungsschalter nicht.

562 Unit-Tests und 239 E2E-Tests gruen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Florian Wilde
2026-09-04 19:23:34 +02:00
co-authored by Claude Opus 5
parent d70acad4cd
commit 4165334c5a
78 changed files with 12314 additions and 42 deletions
+294 -12
View File
@@ -1,10 +1,8 @@
# Anleitung
Bedienung von FLORIAN, Stand Phase 8 (Version 0.9.0). Die Bilder zeigen die
Bedienung von FLORIAN, Stand Phase 9 (Version 0.10.0). Die Bilder zeigen die
Beispielwehr aus dem Seed und werden mit `npm run screenshots` neu erzeugt.
> Die Kassenverwaltung kommt in Phase 9 dazu. Siehe [ROADMAP.md](ROADMAP.md).
---
## 1. Anmelden
@@ -1680,9 +1678,9 @@ Prüfen Sie gegen das Foto, das links daneben steht. Dann **Gegenzeichnen**.
Ohne Vision-Modell funktioniert alles bis auf das Auslesen: der Beleg wird
fotografiert und abgelegt, die Angaben tragen Sie von Hand ein.
Die Buchung daraus kommt mit der Kasse in Phase 9. Hier entsteht erst einmal ein
sauber erfasster Beleg mit Foto — und der ist schon mehr wert als ein
Schuhkarton.
Ist der Beleg gegengezeichnet, steht in der Liste der erledigten Belege ein
Knopf **Buchen**. Er führt in einem Schritt ins Kassenbuch — zu wählen sind
nur Konto und Kategorie. Siehe [Kapitel 48](#48-buchen).
### Das KI-Protokoll
@@ -1704,7 +1702,291 @@ Datensatz, seit dem ersten Tag.
---
## 47. Rollen und was sie dürfen
## 47. Die Kasse
Unter **Kasse** stehen alle Konten der Wehr mit ihrem heutigen Bestand.
![Kassenübersicht](screenshots/45-kasse-light.png)
Drei Arten von Konten:
| Art | Wofür |
|---|---|
| **Barkasse** | Die Kassette im Gerätehaus. Wechselgeld für Feste, Kleinausgaben. |
| **Bankkonto** | Das Girokonto der Wehr. Mit IBAN, damit sich Kontoauszüge zuordnen lassen. |
| **Rücklage** | Angespartes für eine Beschaffung. Wird nicht laufend bewegt. |
**Der Bestand wird gerechnet, nicht gespeichert.** Anfangsbestand plus alle
Buchungen. Wer nachträglich eine Buchung einträgt, sieht den Bestand sofort
richtig — es gibt keinen zweiten Wert, der danebenläuft.
### Beim ersten Mal
Steht die Kasse leer, bietet die Übersicht an, den **Standardkontenrahmen**
anzulegen: rund zwanzig Kategorien, wie sie eine Feuerwehrkasse braucht —
Kraftstoff, Reparatur, Schutzkleidung, Ausbildung, Verpflegung auf der einen
Seite; Zuschüsse, Spenden, Mitgliedsbeiträge, Veranstaltungen, Kostenersatz
auf der anderen.
Sie lassen sich danach umbenennen, ergänzen und um eigene Unterkategorien
erweitern. Wer eine eigene Gliederung hat, legt sie stattdessen von Hand an.
---
## 48. Buchen
![Kassenbuch](screenshots/46-kassenbuch-light.png)
Oben stehen drei Summen: Einnahmen, Ausgaben, Saldo. Sie beziehen sich auf
**alle** Treffer der eingestellten Auswahl, nicht nur auf die angezeigten
Zeilen — eine Summe unter einer abgeschnittenen Liste bedeutete nichts.
### Eine Buchung erfassen
Der Betrag ist immer positiv; ob es eine Einnahme oder eine Ausgabe ist, steht
mit den beiden Knöpfen daneben. Eine „negative Ausgabe" gibt es nicht: sie
wäre eine Einnahme in Verkleidung und in keiner Auswertung als solche zu
erkennen.
Sobald ein Verwendungszweck dasteht, schlägt FLORIAN eine Kategorie vor.
Zuerst aus den **eigenen früheren Buchungen** der Wehr — steht darunter „zuletzt
so gebucht", ist dieselbe Sache schon einmal so einsortiert worden. Erst wenn
es dazu nichts gibt, greift eine Stichwortliste.
Der Vorschlag ist ein Angebot, kein Automatismus: er wird erst übernommen,
wenn er angeklickt wird. Und ist er unsicher, erscheint gar keiner. Ein
falscher Vorschlag wäre schlechter als keiner — er wird übernommen, ohne
gelesen zu werden.
### Entwurf und festgeschrieben
Eine neue Buchung ist zunächst ein **Entwurf**. Sie lässt sich ändern und
verwerfen, solange der Kassier sie durchsieht.
Mit **Festschreiben** wird sie unveränderbar. Das ist der Zustand, den eine
Kassenprüfung erwartet, und dahinter führt kein Weg zurück — auch nicht über
einen Umweg, die Datenbank lehnt jede Änderung ab.
Ein Schloss in der Zeile zeigt, welche Buchungen festgeschrieben sind.
### Einen Beleg buchen
Wurde eine Quittung unter **Belege** fotografiert und gegengezeichnet, muss
sie nicht noch einmal abgetippt werden. In der Liste der erledigten Belege
steht dort ein Knopf **Buchen**.
Zu wählen sind nur Konto und Kategorie — alles andere steht schon fest.
Betrag, Datum und Händler kommen aus dem gegengezeichneten Beleg, und das
Foto hängt danach an der Buchung. Das ist der Zustand, den eine
Kassenprüfung erwartet: zu jeder Ausgabe ein Beleg, und zwar an der Buchung
und nicht in einem Ordner daneben.
Ein Beleg, der noch nicht gegengezeichnet ist, lässt sich nicht buchen. Er
ist bis dahin ein von einer Maschine ausgefülltes Formular.
### Wenn etwas falsch war
Bei einem Entwurf: ändern oder verwerfen.
Bei einer festgeschriebenen Buchung: **Gegenbuchen**. Es entsteht eine zweite
Buchung mit derselben Summe in die andere Richtung, mit Verweis auf die erste
und mit dem eingegebenen Grund im Verwendungszweck. Beide bleiben stehen.
Das sieht nach mehr Aufwand aus, als eine Zahl zu korrigieren, und ist genau
der Punkt: eine verschwundene Buchung kann ein Kassenprüfer nicht prüfen. Eine
berichtigte kann er nachvollziehen.
Das Datum der Gegenbuchung ist immer **heute**. Läge es im geprüften Zeitraum,
würde die Datenbank sie ablehnen — und das zu Recht.
---
## 49. Kontoauszug einlesen
Statt fünfzig Umsätze abzutippen, lässt sich der Auszug aus dem Online-Banking
einlesen. Zwei Formate:
| Format | Datei |
|---|---|
| **CAMT.053** | `.xml` oder `.camt` |
| **MT940** | `.txt` oder `.sta` |
Beides bietet fast jedes Online-Banking zum Herunterladen an, meist unter
„Umsatzexport" oder „Umsätze exportieren". Welches von beiden, spielt keine
Rolle — FLORIAN erkennt es am Inhalt.
### Was dabei passiert — und was nicht
Es entstehen **Entwürfe**, keine fertigen Buchungen. Jeder Posten muss danach
noch durchgesehen und die Kategorie geprüft werden.
Umsätze, die schon in der Kasse stehen, sind grau hinterlegt und mit „steht
schon in der Kasse" gekennzeichnet. Sie sind nicht vorausgewählt. Das ist der
eigentliche Wert der Sache: ein zweimal eingelesener Auszug wäre sonst ein
doppelt gebuchter Monat, und der fällt erst beim Kassenabschluss auf — also
drei Monate später.
Umsätze, die nicht gelesen werden konnten, stehen mit Grund darüber. Sie
verschwinden nicht stillschweigend.
---
## 50. Mitgliedsbeiträge
![Beiträge](screenshots/47-beitraege-light.png)
### Sätze
Ein Beitragssatz gilt **ab einem Jahr** und wahlweise für eine Abteilung. Ein
Satz ohne Abteilung gilt für alle, die keinen eigenen haben.
Rückwirkend wird nichts geändert. Wer den Beitrag erhöht, legt einen neuen
Satz ab dem kommenden Jahr an — sonst stimmten die Beiträge der vergangenen
Jahre nicht mehr, und die sind bereits geprüft.
### Der Beitragslauf
Einmal im Jahr, meist im Januar. Vorher zeigt FLORIAN, was entstehen wird:
- wie viele Beiträge und über welche Summe
- wie viele Mitglieder für dieses Jahr schon einen haben (die bleiben unberührt)
- **wer keinen passenden Satz hat**
Der letzte Punkt ist der wichtige. Das sind die Mitglieder, für die niemand
entschieden hat, was sie zahlen — entweder fehlt ein Satz für ihre Abteilung
oder es gibt keinen allgemeinen.
Der Lauf lässt sich wiederholen. Wer im Februar drei Neue aufgenommen hat,
startet ihn noch einmal; doppelt entsteht nichts.
### Zahlungen und Mahnungen
Ein Zahlungseingang erzeugt zugleich die **Buchung** im Kassenbuch. Ein
Häkchen ohne Geld in der Kasse wäre eine Behauptung.
Gemahnt wird als Sammelaktion: die offenen Beiträge auswählen, mahnen. Die
Mahnstufe zählt hoch. Ab der fünften Stufe hört FLORIAN auf — was danach
kommt, entscheidet die Kommandantschaft und nicht die Software.
Ein **Erlass** braucht eine Begründung. Ohne sie wird er nicht gespeichert:
ein erlassener Beitrag ohne Grund ist in der Kassenprüfung eine offene Frage,
und in fünf Jahren weiß es niemand mehr.
### Rückstände
Ganz oben steht die Rückstandsliste über **alle Jahre**, nach Person
gruppiert. Sie ist die einzige Ansicht, in der auffällt, wer seit drei Jahren
offen steht — in der Jahresliste sieht das aus wie ein einzelner offener
Beitrag.
---
## 51. Rechnungen an Dritte
![Rechnungen](screenshots/48-rechnungen-light.png)
Kostenersatz nach Art. 28 BayFwG (Fehlalarm einer Brandmeldeanlage, Öleinsatz
mit Verursacher), Vermietung des Schulungsraums, Absicherung einer
Veranstaltung.
### Nummer und Betrag
Die **Rechnungsnummer** vergibt FLORIAN fortlaufend je Jahr, lückenlos. Eine
fehlende Nummer muss in der Kassenprüfung erklärt werden, deshalb wird auch
eine stornierte Rechnung nicht gelöscht, sondern bleibt mit Grund stehen.
Der **Betrag** ist die Summe der Positionen und wird nicht eingegeben. Ein von
Hand eingetippter Gesamtbetrag neben Positionen, die etwas anderes ergeben,
ist der Fehler, den niemand bemerkt, bis der Empfänger anruft.
Die Menge hat drei Nachkommastellen: Einsatzstunden werden vielerorts
viertelstündlich abgerechnet, und 0,25 × 47,50 € muss auf den Cent stimmen.
### Entwurf, versendet, bezahlt
Bis zum **Versenden** ist eine Rechnung ein Entwurf und lässt sich vollständig
ändern. Danach nicht mehr: was beim Empfänger liegt, muss dem entsprechen, was
hier steht.
Beim Versenden entsteht das PDF im Hintergrund. Es steht kurz darauf zum
Herunterladen bereit.
Der Zahlungseingang erzeugt — wie beim Beitrag — zugleich die Buchung. Wurde
weniger überwiesen als berechnet, lässt sich der abweichende Betrag eintragen.
Für eine Korrektur: stornieren und neu schreiben. Eine bezahlte Rechnung wird
nicht storniert; dort ist zuerst die Buchung gegenzubuchen.
---
## 52. Kassenprüfung
![Kassenabschluss](screenshots/49-kassenabschluss-light.png)
Einmal im Jahr, meist vor der Jahreshauptversammlung. Zwei Kassenprüfer zählen
die Kasse und vergleichen mit dem Buch.
### Der Ablauf
1. **Zeitraum wählen.** In der Regel das abgelaufene Kalenderjahr.
2. **Zählen.** In der Maske stehen links die Bestände laut Buch und rechts
leere Felder für das Gezählte. Die Reihenfolge ist Absicht: wer erst das
Buch sieht und dann zählt, zählt, bis es passt.
3. **Differenz erklären**, falls eine bleibt.
4. **Prüfer und Prüfdatum eintragen.**
5. **Festschreiben.**
Steht ein Hinweis auf noch nicht festgeschriebene Buchungen im Zeitraum: erst
durchsehen. Das Festschreiben des Abschlusses nimmt sie mit.
### Was das Festschreiben bewirkt
Der Zeitraum ist danach **zu**. Es lässt sich keine Buchung mehr mit einem
Datum darin anlegen, und keine vorhandene mehr dorthin verschieben. Wer nach
der Prüfung noch eine Quittung findet, bucht sie mit dem heutigen Datum.
Der Abschluss selbst ist ebenfalls unveränderbar — Zahlen, Prüfer und
Erläuterung stehen fest. Nachgetragen wird nur der Prüfbericht, weil das PDF
im Hintergrund entsteht.
Ohne Prüfer und Prüfdatum lässt sich nichts festschreiben: ohne beides ist es
kein Abschluss, sondern eine Notiz. Und eine Differenz ohne Erläuterung
ebenfalls nicht — sonst steht in fünf Jahren „stimmt nicht" im Bericht und
niemand weiß mehr, warum.
### Der Prüfbericht
Entsteht als PDF mit vier Unterschriftsfeldern: beide Prüfer, der Kassier und
der Kommandant. Er lässt sich ausdrucken, unterschreiben und abheften — die
Papierform bleibt für die Entlastung in der Versammlung die maßgebliche.
---
## 53. Auswertungen und Export
Unter **Kasse → Abschluss → Auswertung** stehen die Zahlen für die
Jahreshauptversammlung:
- Einnahmen und Ausgaben je Kategorie, absteigend nach Betrag
- der Verlauf über zwölf Monate
- das Vorjahr daneben — eine Zahl ohne Vergleich sagt nichts
Das ist die Ansicht, in der auffällt, dass sich die Kraftstoffkosten verdoppelt
haben.
### Export
**Kassenbuch als CSV** lädt alle Buchungen eines Jahres herunter: Datum,
Konto, Richtung, Betrag, Ober- und Unterkategorie, Kontonummer,
Verwendungszweck, Belegnummer, Gegenüber und ob festgeschrieben.
Die Datei ist für den Steuerberater oder die Kämmerei gedacht und öffnet in
Excel ohne Rückfrage richtig: Semikolon als Trennzeichen, Komma als
Dezimaltrennzeichen, UTF-8 mit Kennung.
---
## 54. Rollen und was sie dürfen
Neun Rollen, jede mit einem festen Satz Rechte. Die Zuordnung steht zentral in
`src/lib/authz.ts` und wird beim Seed in die Datenbank gespiegelt — eine Wehr
@@ -1716,7 +1998,7 @@ kann sie also nachträglich zuschneiden, ohne dass jemand Code ändert.
| **Kommandant** | alles innerhalb der eigenen Wehr, einschließlich Rollen vergeben und Protokoll einsehen |
| **Gerätewart** | Fahrzeuge und Geräte anlegen, ändern, aussondern; Prüfungen planen und durchführen |
| **Atemschutzgerätewart** | zusätzlich Atemschutzgeräte, Träger und die Überwachung nach FwDV 7 |
| **Kassier** | Buchungen und Kassenabschluss (Modul in Phase 9), Belege erfassen und gegenzeichnen |
| **Kassier** | Kassenbuch, Beiträge, Rechnungen und Kassenabschluss; Belege erfassen und gegenzeichnen |
| **Schriftführer** | Mitglieder pflegen, Einsätze und Berichte erfassen, den Terminkalender führen |
| **Ausbilder** | Übungen und Übungstermine planen, Teilnahme, Anwesenheit und Qualifikationen erfassen |
| **Mitglied** | eigene Daten, Listen lesen, Termine sehen und sich zurückmelden, eigene Benachrichtigungswege einrichten, im Wiki lesen |
@@ -1738,7 +2020,7 @@ sind nur die Textvorlagen, und die hängen an einem eigenen Recht.
---
## 48. Anmeldung über authentik einrichten
## 55. Anmeldung über authentik einrichten
authentik läuft **getrennt** von FLORIAN und ist nicht Teil dieses Stacks.
@@ -1791,7 +2073,7 @@ ganze Wehr aus.
---
## 49. PIN und Ausweiskarte verwalten
## 56. PIN und Ausweiskarte verwalten
Wie sich am Terminal angemeldet wird, steht in Kapitel 24. Hier geht es darum,
was dahinter liegt.
@@ -1814,7 +2096,7 @@ Huber), PIN `471203`.
---
## 50. Was protokolliert wird
## 57. Was protokolliert wird
Jede schreibende Änderung erzeugt einen Eintrag mit Zeitpunkt, Person,
betroffenem Datensatz und den geänderten Feldern im Vorher-Nachher-Vergleich.
@@ -1839,7 +2121,7 @@ jeweiligen Detailseite sichtbar.
---
## 51. Wenn etwas nicht geht
## 58. Wenn etwas nicht geht
| Beobachtung | Wahrscheinliche Ursache | Was hilft |
|---|---|---|