Files
betreuungs-cockpit/docs/ROADMAP.md
T
Florian Wilde fa994350d6 Dauerzahlungen zu einem Vertrag gelten als belegt
Bei einer monatlichen Praemie gibt es keinen Beleg - es gibt einen
Vertrag, und der wird einmal abgeschlossen, nicht monatlich quittiert.
Bisher blieb nur ein Freitextfeld pro Buchung: zwoelfmal im Jahr
derselbe Satz, mal Anzahl der Vertraege.

Buchung.vertragId mit onDelete: SetNull. Der Belegzustand kennt jetzt
drei Faelle statt zwei, getrennt ausgewiesen - ein Vertrag belegt, eine
Begruendung erklaert nur; zusammengeworfen verliert die Belegquote ihre
Aussage gegenueber dem Rechtspfleger.

Dazu: automatische Zuordnung beim Import bei eindeutiger Gegenstelle,
Sammelzuordnung ueber die Gruppen aus Issue #3, und die Rechnungslegung
nennt den Vertrag samt Nummer statt "ohne Beleg".

Die Sicherung dagegen: Weicht der Betrag um mehr als ein Fuenftel vom
hinterlegten Beitrag ab, faellt die Anerkennung weg und die Buchung wird
als "Betrag pruefen" markiert. Sonst waere die Zuordnung eine Hintertuer.

Zur Toleranz - ein Entwurf und seine Korrektur: Zuerst verglich ich den
Betrag gegen alle ueblichen Zahlweisen, damit es auch passt, wenn die
Bank anders abbucht als der Vertrag es fuehrt. Der eigene Test hat das
widerlegt: Bei 42,50 monatlich liegen 420 innerhalb von 20 Prozent des
Jahresbetrags von 510 - ausgerechnet der Fall aus der Aufgabenstellung
waere durchgerutscht. Jetzt wird stur gegen den hinterlegten Beitrag
verglichen. Bucht die Bank anders ab, stimmen die Vertragsdaten nicht,
und das soll auffallen.

Behoben: Die Buchungsliste hatte eine eigene, fast gleiche Datenabfrage
neben der aus berichte/gemeinsam.ts. Nur eine von beiden wurde
nachgezogen, in der Liste stand weiter "Beleg fehlt". Beide benutzen
jetzt BUCHUNG_EINBEZUG und zuBuchungEingabe - das kann nicht halb
vergessen werden. Gefunden hat es der Browsertest.

Nebenbei: Die Roadmap trug noch "Aktuelle Fassung 1.1.2" - Nachwirkung
der parallelen Bearbeitung von #3 und #10. Nachgezogen wie zugesagt.

Geprueft: 23 neue Einheitstests, die Haelfte davon darauf gerichtet, dass
die Anerkennung auch wirklich wegfaellt. Fuenf End-to-End-Tests auf
beiden Geraeteprofilen. 560 Unit-Tests, 63 e2e, null Typfehler.

Refs #11
2026-08-23 09:00:46 +02:00

398 lines
16 KiB
Markdown

# Roadmap
Was als Nächstes drankommt, und warum in dieser Reihenfolge.
**Maßstab ist der Alltag, nicht die Vollständigkeit.** Ein Punkt steht
weit oben, wenn er entweder etwas Falsches richtigstellt oder jeden Monat
Zeit spart. Er steht weit unten, wenn er nur schön wäre.
Diese Datei ist eine Absichtserklärung, kein Vertrag. Was sich im Betrieb
als wichtiger herausstellt, rutscht nach oben.
Stand: 23.08.2026 · Aktuelle Fassung: **1.3.0** ([CHANGELOG](../CHANGELOG.md))
---
## Woher die Punkte kommen
Beim Bauen sind **44 Schema-Wünsche** aufgelaufen — Stellen, an denen das
Datenmodell etwas nicht abbildet, was die Fachlogik gebraucht hätte. Sie
liegen einzeln und begründet in [`schema-wuensche/`](schema-wuensche/),
nach Modul getrennt. Diese Roadmap sortiert sie nach Dringlichkeit und
bündelt sie zu Releases, die sich in einem Rutsch migrieren lassen.
Dazu kommen die bekannten Einschränkungen aus dem Changelog und das, was
sich im Betrieb noch zeigen wird.
---
## 1.1 — Was heute noch falsch sein kann
**Ziel:** Kein Wert in der Anwendung soll unter ungünstigen Umständen
falsch sein, ohne dass man es merkt. Das ist die einzige Art von Fehler,
die man einem Betreuungsgericht nicht erklären kann.
### Kostenkonto der Immobilie richtigstellen
`Buchung` hat kein `immobilieId`. Das Kostenkonto wertet deshalb über
Buchungskategorien aus — bei **einem** Grundstück richtig, bei einem
zweiten still falsch. Die Oberfläche sagt das derzeit an der Auswertung
dazu; das ist ein Pflaster, keine Lösung.
*Aufwand: klein. Migration: ein Feld, ein Index.*
### Umbuchungen kennen ihr Gegenkonto
Eine Umbuchung zwischen zwei Konten erscheint heute als zwei unverbundene
Buchungen. In der Rechnungslegung sieht das aus wie eine Ausgabe und eine
Einnahme — und wer nachrechnet, fragt zu Recht nach.
*Aufwand: klein. Migration: ein selbstbezüglicher Fremdschlüssel.*
### Dublettenschutz beim Import ohne Konto
Der Schutz vor Doppelbuchungen greift über `(kontoId, importReferenz)`.
Ist kein Konto zugeordnet, greift er nicht — ein zweimal eingelesener
Auszug erzeugt dann doppelte Buchungen.
*Aufwand: klein. Migration: partieller eindeutiger Index.*
### Rückkaufswert am Vertrag
Der Wert hängt heute am Vermögensposten. In der Vertragsübersicht steht
deshalb kein Betrag — ausgerechnet dort, wo man ihn beim Telefonat mit dem
Versicherer braucht. Es ist derselbe Wert, um den es im Anschreiben an den
Versicherer geht — siehe 1.2a.
*Aufwand: klein. Issue: [#8](https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/issues/8).*
### Genau eine Zielspalte je Dokumentverknüpfung
`DokumentVerknuepfung` hat zwölf mögliche Zielspalten; dass genau eine
gesetzt ist, erzwingt bisher nur die Anwendung. Ein CHECK-Constraint macht
daraus eine Zusage, die auch bei direktem Datenbankzugriff hält.
*Aufwand: klein. Migration: ein Constraint.*
### Papierkorb für Saldo- und Wertstände
Beide Modelle haben kein `geloeschtAm`. Ein versehentlich eingetragener
Kontostand lässt sich nur endgültig löschen — was der Zusage widerspricht,
dass Löschen 30 Tage rückgängig zu machen ist.
*Aufwand: klein.*
### Aufgaben aus Vorlagen entfernen können
Passt eine Aufgabe aus einer Vorgangs-Vorlage im Einzelfall nicht, bleibt
sie dauerhaft offen stehen und verfälscht jede Fortschrittsanzeige.
*Aufwand: klein.*
---
## 1.2 — Weniger tippen
**Ziel:** Die Handgriffe, die sich jeden Monat wiederholen, kürzer machen.
### Nachforderungen mit stabilem Schlüssel
Der Dublettenschutz beim Übernehmen der Standardcheckliste läuft über die
Bezeichnung. Wer eine Zeile umbenennt, bekommt sie beim nächsten Mal
doppelt.
### Bescheid und Frist verbinden
Aus einem Bescheid entsteht die Widerspruchsfrist heute über einen
Textschlüssel statt über einen Fremdschlüssel. Ändert sich das
Zugangsdatum, wandert die Frist nicht mit.
### Statuswechsel eines Vorgangs als eigene Tabelle
Der Zeitstrahl liest Statuswechsel aus dem entschlüsselten Audit-Log. Das
funktioniert, ist aber langsam und hängt an einem Format, das eigentlich
nur Nachweis sein soll.
### Wer hat was erfasst
Fristen, Saldo- und Wertstände tragen kein Feld für den erfassenden
Benutzer. Bei einer Betreuung zu zweit ist das die erste Frage.
### Ansprechpartner am Vorgang
Die Sachstandsanfrage kann namentlich anreden, bekommt den Ansprechpartner
mangels Feld aber nicht übergeben. Gehört zum Schriftverkehr in 1.2a: dort
entsteht das Schreiben, hier fehlt ihm die Anrede.
*Issue: [#9](https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/issues/9).*
### Inventarliste als eigenes Modell
Wertgegenstände hängen heute an Freitext und Fotos. Für die
Wohnungsauflösung wäre eine Liste mit Bezeichnung, Raum, geschätztem Wert
und Verbleib das richtige Werkzeug.
### Pflegegrad-Historie
Der Pflegegrad steht als einzelnes Feld in den Stammdaten. Frühere Grade
mit ihren Zeiträumen gehören in eine Historie — sie werden im
Jahresbericht und bei einer Höherstufung gebraucht.
---
## 1.2a — Schriftverkehr, der sich nicht wiederholt
**Ziel:** Ein Schreiben wird einmal geschrieben, einmal ausgegeben und
einmal abgelegt — statt viermal angefasst.
Die Anschreiben an Versicherer und Behörden gibt es heute nur als Text zum
Markieren und Kopieren. Was danach kommt, macht man von Hand: in Word
nachbauen, ausdrucken, abschicken und anschließend noch einmal als Dokument
in die Akte legen. Vergessen wird regelmäßig der letzte Schritt — und dann
fehlt der Nachweis genau dort, wo er später gebraucht wird.
Nach der Priorisierungsregel am Ende dieser Datei ist das Kriterium 2: Es
kostet jeden Monat Zeit, und einmal im Jahr — vor Vermögensverzeichnis und
Jahresbericht — besonders viel. Bisher stand das Thema als einzelne Zeile
unter „Später, ohne Datum", also unter „wäre schön, und ehrlich gesagt
vielleicht nie". Das war zu tief gehängt.
Die Punkte bauen aufeinander auf und stehen deshalb in dieser Reihenfolge.
### Verträge überhaupt erst finden
Am Anfang einer Betreuung weiß niemand, welche Verträge es gibt; es liegt
kein Ordner bereit, und die betreute Person kann es oft selbst nicht mehr
sagen. Die Antwort steht aber schon im System: **Wer regelmäßig abbucht,
hat einen Vertrag.** Eine Auswertung der Gegenstellen nach wiederkehrenden
Zahlungen macht aus hunderten Buchungszeilen eine Liste von Gesellschaften,
an die zu schreiben ist. Solange die fehlt, nützt die beste Briefvorlage
nichts — deshalb steht dieser Punkt vor allen anderen.
*Issue: [#3](https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/issues/3).*
### Schreiben erzeugen, ablegen, nachhalten
Das Kernstück: eine Word-Datei statt Text zum Kopieren, Ablage als
Ausgangsdokument mit Empfänger und Versanddatum, Wiedervorlage mit
vorbelegter Frist. Dazu Empfänger, zu denen es noch keinen Datensatz gibt —
am Anfang schreibt man ja gerade an Stellen, von denen man erst erfahren
will, ob dort etwas besteht. Der Text bleibt vor der Ausgabe änderbar, weil
jeder Fall eine Besonderheit hat, die in den Brief gehört. Die Bausteine
liegen bereits im Code; was fehlt, ist der durchgehende Weg. Alles Weitere
in diesem Abschnitt setzt darauf auf.
*Issue: [#4](https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/issues/4).*
### Dasselbe Schreiben als E-Mail
Vieles geht per Mail raus, nicht per Brief. Dafür müssen Betreff und Text
getrennt vorliegen und Absenderblock, Anschrift und Datumszeile
verschwinden. Auseinandergebaut wird das heute von Hand, und dabei fällt
regelmäßig etwas heraus, das drinbleiben sollte.
*Issue: [#5](https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/issues/5).*
### Rückkaufswerte in einem Zug anfragen
Vor Vermögensverzeichnis und Jahresbericht sind es jedes Mal dieselben fünf
bis zehn Briefe an dieselben Gesellschaften — einzeln erzeugt, einzeln
nachgehalten, und bei zwei Dritteln muss nachgefasst werden. Das ist der
Handgriff, der im Jahr am meisten Zeit kostet, und derjenige, der sich am
einfachsten bündeln lässt, sobald ein Schreiben ohnehin auf Knopfdruck
entsteht.
*Issue: [#6](https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/issues/6).*
### Eigene Vorlagen
Die Brieftexte stehen fest im Programmcode. Formulierungen, die sich bei
einer bestimmten Stelle bewährt haben, lassen sich nicht hinterlegen, und
für Schreiben ohne mitgelieferte Vorlage — Auskunftsersuchen,
Vollmachtsnachweis, Adressänderung — fängt man bei null an. Wer eine
Vorlage selbst schreibt, vergisst als Erstes den Bestellungsabsatz; ohne
den antwortet keine Versicherung, und dann ist ein Monat vergangen. Die
Vorlagenverwaltung muss ihn deshalb einfordern, statt ihn nur anzubieten.
*Issue: [#7](https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/issues/7).*
### Dauerzahlungen gelten als belegt
Ist ein Vertrag erst erfasst, ist er auch der Beleg für die Zahlungen
daraus. Für zwölf gleiche Lastschriften will niemand zwölf Quittungen
sehen, sondern die Police. Heute bleibt dafür nur ein Freitextfeld je
Buchung — stumpfe Arbeit mit einem Ergebnis, das schwächer aussieht als
die Aktenlage tatsächlich ist. Das Feld gehört in dieselbe Migration wie
`Buchung.immobilieId` aus 1.1; zwei Wanderungen an derselben Tabelle wären
Verschwendung.
*Issue: [#11](https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/issues/11). Migration: ein Feld, ein Index — gebündelt mit 1.1.*
### Was in 1.1 und 1.2 dazugehört
Zwei Punkte weiter oben sind Teil derselben Sache und bleiben trotzdem
stehen, wo sie stehen: „Rückkaufswert am Vertrag" ist ein möglicher
Fehler und deshalb 1.1, „Ansprechpartner am Vorgang" ein Handgriff und
deshalb 1.2. Gelesen gehören sie hierher — der eine liefert den Wert, um
den das Anschreiben bittet, der andere die namentliche Anrede.
*Issues: [#8](https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/issues/8) und [#9](https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/issues/9).*
---
## 1.2b — Passkeys abrunden
Der Grundstock steht seit 1.1.0. Was noch fehlt, ist Bequemlichkeit, nicht
Sicherheit.
### Passkey direkt im Anmeldefeld anbieten
Browser können einen Passkey im Ausfüllvorschlag des E-Mail-Feldes
anbieten (*conditional UI*), statt hinter einem eigenen Knopf. Ein Schritt
weniger. Braucht einen zweiten Challenge-Weg und sorgfältiges Abbrechen,
wenn stattdessen doch das Passwort getippt wird.
### Passkey umbenennen
Heute geht nur anlegen und entfernen. Wer sein Gerät „Handy" genannt hat
und inzwischen zwei hat, muss den Passkey neu einrichten.
### Warnen, wenn der letzte Passkey nur auf einem Gerät liegt
Die Liste sagt bereits, ob ein Schlüssel gesichert ist. Wer ausschließlich
ungesicherte Passkeys hat und dazu keine Wiederherstellungscodes mehr,
sollte das deutlicher zu sehen bekommen als in einer Zeile Kleingedrucktem.
---
## 1.3 — Belastbarkeit
**Ziel:** Die Stellen absichern, die bisher nur unter Laborbedingungen
geprüft sind.
### Texterkennung gegen echtes Tesseract
Bisher ist nur der Weg „nicht verfügbar, Upload funktioniert trotzdem"
getestet. Ein Test im Container gegen echte Schreiben — auch schlechte
Handyfotos, auch mehrseitige Bescheide — fehlt.
### CAMT.053 gegen einen echten Bankauszug
Der Leser ist gegen selbst gebaute Beispiele geprüft. Ein echter Auszug
der Sparkasse ist der eigentliche Test.
### Suche und Belegmappe gegen Postgres
Beide sind nur in Einzelteilen geprüft, nicht end-to-end gegen die
Datenbank mit einigen hundert Dokumenten.
### Wiederherstellung als Test
Die Anleitung dafür steht in der README. Ein Skript, das sie einmal im
Monat automatisch durchspielt — Sicherung zurückspielen, Diagnosen im
Klartext prüfen, Testdatenbank verwerfen — wäre der Beweis statt der
Absichtserklärung.
### Passkey-Ablehnung ohne Browser nachstellen
Die Prüfung „Passkey ohne Nutzerverifikation wird abgewiesen" ist im Code
doppelt abgesichert und im Browsertest belegt — dort weist allerdings
schon der Browser ab, der Server kommt gar nicht dran. Ein Test, der die
Antwort von Hand baut und den Browser umgeht, würde den serverseitigen
Rückhalt tatsächlich beweisen.
### Barrierefreiheits-Durchgang mit einem Screenreader
Semantik, Fokusreihenfolge und Kontraste sind beim Bauen beachtet und in
Teilen getestet. Ein Durchgang mit NVDA oder VoiceOver ist etwas anderes
als eine Testzusicherung.
### `@react-pdf/renderer` ohne Krücke
`src/lib/pdf/standardschrift.ts` gleicht aus, dass die Unterabhängigkeiten
für Standardschriften kein Schriftobjekt mehr liefern. Ein `overrides`-
Eintrag in der `package.json` oder eine neuere Fassung macht die Datei
überflüssig — sie baut sich dann selbst ab.
---
## 2.0 — Mehr als eine Betreuung
**Ziel:** Was sich nur mit einem Bruch lösen lässt. Deshalb eine eigene
Hauptversion — und deshalb nicht vorher.
### Zweite betreute Person im Alltag erprobt
Das Datenmodell trägt es von Anfang an: Alles hängt an einer `betreuteId`,
der Zugriff wird gegen sie geprüft, die Auswahl steht in der Seitenleiste.
**Gelaufen ist es bisher nur mit einer.** Was fehlt, ist Erfahrung — und
vermutlich ein Dashboard, das über beide hinwegsieht.
### Heimkostenmodell entwirren
Der einrichtungseinheitliche Eigenanteil auf der Heimrechnung ist bereits
um die Leistung der Pflegekasse gekürzt. Das Modul rechnet deshalb
ausdrücklich nach der Lesart `EIGENANTEIL_NETTO` und warnt, wenn die
Pflegekassenleistung zusätzlich erfasst wird.
Sauberer wäre, die beiden Lesarten im Modell zu trennen, statt sie im Kopf
auseinanderzuhalten. Das ändert bestehende Datensätze — also 2.0.
### Mehrere Fassungen je Bericht
Heute verdrängt die DOCX-Ausgabe die abgegebene PDF-Fassung. Was einmal
beim Gericht lag, sollte unverändert nachweisbar bleiben.
### Verschlüsselte Ablage auch bei S3
Beim Dateitreiber liegen Dokumente zusätzlich AES-256-GCM-verschlüsselt.
Bei S3 geht das nicht, weil signierte URLs am Server vorbei ausgeliefert
werden. Der Ausweg wäre, Dateien durch die Anwendung zu reichen — das
kostet Durchsatz und ist eine bewusste Abwägung, keine Selbstverständlichkeit.
---
## Später, ohne Datum
Sinnvoll, aber nicht dringend:
- **Kalendarische Wiedervorlage per E-Mail als Wochenübersicht** statt
einzelner Erinnerungen.
- **Import eines Grundbuchauszugs** als strukturierte Daten statt als PDF.
- **Mehrere Betreuungsgerichte** je betreuter Person (bei Umzug).
- **Zwei-Personen-Prinzip** für besonders sensible Aktionen — technisch
vorbereitet durch die erneute Anmeldung, fachlich noch nicht gebraucht.
- **Statistik über mehrere Betreuungsjahre** für den eigenen Überblick.
---
## Bewusst nicht geplant
Damit klar ist, worauf niemand warten muss:
| Was | Warum nicht |
|---|---|
| **Automatische Rechtsberatung** | Die Anwendung kennt den Einzelfall nicht. Sie rechnet und dokumentiert; entscheiden tun Gericht, Träger und im Zweifel das Sozialgericht. |
| **Prognosen zu Bewilligungschancen** | Eine Zahl, die niemand belegen kann, wird trotzdem geglaubt. Das ist schlimmer als keine Zahl. |
| **Direkte Bankanbindung** | Ein dauerhafter Kontozugriff ist ein Risiko, das der Bequemlichkeit nicht wert ist. CSV und CAMT reichen. |
| **Mehrmandantenfähigkeit für fremde Betreuungen** | Sobald mehrere Betreuer mit fremden Fällen auf derselben Installation arbeiten, ändert sich die datenschutzrechtliche Lage grundlegend. Mehrere Betreute **einer** Person bleiben möglich. |
| **Native App für Handy und Tablet** | Die Web-Anwendung ist am Telefon vollwertig bedienbar. Eine zweite Oberfläche wäre eine zweite Oberfläche, die veraltet. |
| **Cloud-Angebot für andere Betreuer** | Dann wäre ich Auftragsverarbeiter für fremde Gesundheitsdaten. Eine andere Aufgabe als die, für die das hier gebaut wurde. |
| **KI-Auswertung der Akte** | Gesundheitsdaten einer nicht entscheidungsfähigen Person verlassen diesen Server nicht. Die Texterkennung läuft lokal, und dabei bleibt es. |
---
## Wie hier priorisiert wird
Drei Fragen, in dieser Reihenfolge:
1. **Kann daraus ein falscher Wert in einem Bericht ans Gericht werden?**
Dann sofort — auch wenn es unbequem ist.
2. **Kostet es jeden Monat Zeit?** Dann bald.
3. **Wäre es schön?** Dann irgendwann, und ehrlich gesagt vielleicht nie.
Fällt ein Punkt in Kategorie 1 und wird trotzdem nicht sofort behoben,
steht der Grund dabei — und die Oberfläche sagt an der betroffenen Stelle,
worauf man achten muss. Ein stillschweigend falscher Wert ist das
Schlimmste, was diese Anwendung produzieren kann.