Dauerzahlungen zu einem Vertrag gelten als belegt #11
Notifications
Total Time Spent: 42 minutes
florian.wilde
42 minutes
No due date set.
Dependencies
No dependencies set.
Reference: florian.wilde/betreuungs-cockpit#11
Reference in New Issue
Block a user
Problem
Aus dem Kontoauszug importierte Buchungen haben keinen Beleg. Bei einer
monatlichen Versicherungsprämie gibt es auch keinen — es gibt einen
Vertrag, und der wird einmal abgeschlossen, nicht monatlich quittiert.
Heute bleibt nur
belegFehltBegruendung, ein Freitextfeld pro Buchung.Für eine Prämie heißt das zwölfmal im Jahr denselben Satz tippen, mal
Anzahl der Verträge. Wer das nicht macht, hat die Zeilen dauerhaft als
„Beleg fehlt" markiert und eine Belegquote, die schlechter aussieht als die
Aktenlage ist.
Beides ist unbefriedigend: Die Arbeit ist stumpf, und das Ergebnis ist
schwächer als die Wahrheit. Bei einem Dauerschuldverhältnis ist der
Vertrag der Beleg. Ein Rechtspfleger will für zwölf gleiche Lastschriften
keine zwölf Quittungen sehen, sondern die Police. Ein handgetippter Satz
„regelmäßige Zahlung" belegt dagegen gar nichts — er behauptet nur.
Was ich will
Eine Buchung lässt sich einem Vertrag zuordnen. Diese Zuordnung gilt
als Nachweis: Die Buchung zählt nicht mehr als „Beleg fehlt" und nicht als
„begründet fehlend", sondern als eigene, dritte Kategorie —
durch Vertrag belegt.
Damit das die Arbeit auch wirklich spart:
Gegenstelle eindeutig zu genau einem Vertrag passt
einmal setzen, nicht nur einzeln
Zwei Sicherungen, die dazugehören
Das darf keine Hintertür werden, mit der sich alles als beleglos abhaken
lässt.
1. Betragsabweichung hebt die Anerkennung auf. Weicht die Zahlung
deutlich vom hinterlegten Beitrag ab, gilt sie nicht automatisch als
belegt, sondern wird zur Prüfung markiert. Eine Prämie, die von 42 € auf
420 € springt, will man sehen — und eine Beitragsanpassung gehört am
Vertrag nachgetragen, nicht stillschweigend geschluckt.
2. Die Rechnungslegung nennt den Vertrag. Statt „ohne Beleg – …" steht
dort „Dauerzahlung zu Vertrag «Bezeichnung», Vertragsnummer …". Die Lücke
wird nicht versteckt, sie wird erklärt. Wer nachprüfen will, weiß sofort,
welches Papier er aus dem Ordner holen muss.
Akzeptanzkriterien
der Buchungsliste sichtbar
und erscheint nicht mehr auf „Heute" unter „Unverbuchte Belege"
durch Vertrag belegt, begründet ohne Beleg. Nicht zusammengeworfen —
sonst verliert die Zahl ihre Aussage
Buchung nicht automatisch als belegt, sondern wird zur Prüfung
markiert. Die Toleranz ist nachvollziehbar dokumentiert
die Zuordnung gilt trotzdem, aber es wird nicht so getan, als wäre
geprüft worden
Gegenstelle eindeutig zu genau einem Vertrag passt; bei Mehrdeutigkeit
geschieht nichts
lassen sich einzeln aufheben
aus, mit Bezeichnung und Vertragsnummer
fallen zurück in „Beleg fehlt" — kein stiller Nachweis auf etwas,
das es nicht mehr gibt
Hinweise zur Umsetzung
Buchunghat heutebelegIdundbelegFehltBegruendung; die Logikliegt in
src/lib/finanzen/kassenbuch.ts(belegFehlt,belegBegruendet,belegquote)src/lib/dashboard/laden.tsaufbelegId: null, belegFehltBegruendung: nullabsrc/lib/berichte/rechnungslegung.tsxBuchung.vertragIdmit IndexZusammenhang
Art von Feld an derselben Tabelle; zwei Migrationen dafür wären
Verschwendung.
Vertrag": Dort entstehen die Verträge, hier werden die Zahlungen daran
gehängt. Zusammen wird aus einer Liste unerklärter Abbuchungen eine
saubere Rechnungslegung.
Angelegt auf Zuruf im Chat, nicht aus dem Dashboard — bitte in Nebula
nachtragen.
🤖 Claude Code hat mit der Umsetzung begonnen.
feat/11-dauerzahlungen-belegtBuchung.vertragIdals Fremdschlüssel mitonDelete: SetNullkassenbuch.tsvon zwei auf drei Fälle erweitern, getrennt ausgewiesen — als reine Funktionen, mit EinheitstestsZum Bündeln mit
Buchung.immobilieId: Das geht so nicht. ZuimmobilieIdgibt es kein Issue, und ein Feld einzubauen, das keine Logik hat und in keiner Oberfläche vorkommt, wäre schlechter als eine zweite Migration — es sähe fertig aus und wäre es nicht. Ich lege nurvertragIdan. Wenn der Immobilien-Punkt aus Roadmap 1.1 drankommt, kostet ihn seine eigene Migration wenige Sekunden Laufzeit; das ist der geringere Preis.Zur Toleranz bei der Betragsprüfung: Ich vergleiche die Zahlung mit dem Jahresbeitrag des Vertrags, heruntergerechnet auf die üblichen Zahlweisen (jährlich, halbjährlich, vierteljährlich, monatlich). So passt es auch, wenn der Vertrag monatlich hinterlegt ist, die Bank aber jährlich abbucht. Die genaue Toleranz und ihre Begründung stehen am Ende im Abschlusskommentar.
Zeiterfassung läuft.
✅ Umsetzung abgeschlossen — bereit zum Testen.
Was geändert wurde
Buchung.vertragIdmitonDelete: SetNull, dazu ein Kennzeichen für automatisch gesetzte Zuordnungen.Geänderte Dateien
src/lib/finanzen/kassenbuch.ts,rechnungslegung.ts,wiederkehrend.ts,wiederkehrend-laden.tssrc/lib/berichte/gemeinsam.ts,rechnungslegung.tsx,src/lib/dashboard/laden.tssrc/server/actions/finanzen.ts,src/lib/validierung/finanzen.tssrc/components/finanzen/{bausteine,buchungs-formular,wiederkehrend-aktionen}.tsxsrc/app/(app)/finanzen/tests/dauerzahlung.test.ts(neu),e2e/dauerzahlung.spec.ts(neu), Schema, Migration, DokuSo testest du es
git switch feat/11-dauerzahlungen-belegtundnpm run db:deploynpm run dev. Lege einen Vertrag mit Gesellschaft, Beitrag und Zahlweise an — die Zahlweise ist wichtig, sie ist der MaßstabAufgewendete Zeit: 00:42
Pull Request: #14
Anmerkungen
Ich habe die Toleranzprüfung während der Umsetzung umgebaut. Der erste Entwurf verglich den Betrag gegen alle üblichen Zahlweisen, damit es auch passt, wenn die Bank anders abbucht als der Vertrag es führt. Der eigene Test hat ihn widerlegt: Bei 42,50 € monatlich liegen 420 € innerhalb von 20 % des Jahresbetrags von 510 € — ausgerechnet der Fall aus dieser Aufgabenstellung wäre durchgerutscht. Jetzt wird stur gegen den hinterlegten Beitrag verglichen.
Zum Bündeln mit
Buchung.immobilieId: nicht getan, siehe Startkommentar. Ein Feld ohne Logik sähe fertig aus und wäre es nicht.Nebenbei aufgefallen (gehört ins Dashboard, nicht Teil dieses PR):
prisma migrate diffwill zum dritten Mal die Trigramm-Indizes löschen. Ich habe dieDROP INDEX-Zeilen erneut von Hand entfernt. Beim vierten Mal wird jemand es übersehen, und dann ist die unscharfe Suche still weg — ohne Fehlermeldung. Einnpm run db:migration, das erzeugt und gleich bereinigt, kostet zwanzig Zeilen.Nach Freigabe:
/issue-freigabe 11🚀 Freigegeben und nach
mainübernommen.de21f1cBeim Ausrollen: Eine Migration läuft mit (
20260823062000_buchung_vertragszahlung). Sie fügt zwei Spalten hinzu und ändert nichts an vorhandenen Daten — ohne Zuordnung bleibt alles, wie es war.Issue wird geschlossen.