Schreiben erzeugen: Word-Datei, Ablage in der Akte, Wiedervorlage #4

Closed
opened 2026-08-22 23:27:22 +00:00 by florian.wilde · 3 comments
Owner

Problem

Die Anschreiben an Versicherer und Behörden (Rückkaufswert, Kündigung,
Sachstandsanfrage) gibt es nur als Text zum Markieren und Kopieren. Danach
sind sie weg: in Word nachbauen, ausdrucken, abschicken — und dann noch
einmal von Hand als Dokument in die Akte legen, damit sie im Bericht
auftauchen. Vier Schritte, von denen regelmäßig einer vergessen wird.
Meistens der letzte, und dann fehlt der Nachweis.

Dazu kommt: Schreiben lassen sich heute nur zu einem Vertrag oder einem
Vorgang erzeugen.
Am Anfang einer Betreuung schreibt man aber gerade an
Stellen, zu denen es noch keinen Datensatz gibt — man fragt ja erst an, um
zu erfahren, ob dort etwas besteht.

Was ich will

Ein Schreiben lässt sich an drei Arten von Empfängern richten:

  1. an einen Vertrag (Gesellschaft und Vertragsnummer sind bekannt)
  2. an einen Kontakt (Anschrift steht schon im System)
  3. an eine frei erfasste Stelle — Name und Anschrift von Hand, mit der
    Möglichkeit, daraus gleich einen Kontakt anzulegen

Und darunter jeweils:

  • Text bearbeitbar vor der Ausgabe
  • Als Word-Datei (.docx) herunterladen
  • In die Akte legen — Dokument mit Richtung „Ausgang", Empfänger,
    Versanddatum, verknüpft mit Vertrag bzw. Vorgang, falls vorhanden
  • Wiedervorlage anlegen — mit vorbelegter Frist, änderbar

Der Text bleibt bearbeitbar, weil jeder Fall eine Besonderheit hat, die in
den Brief gehört. Ein Formulartext, den man nicht mehr ändern kann, wird
früher oder später falsch abgeschickt.

Akzeptanzkriterien

  • Beim Vertrag erzeugt „Rückkaufswert anfordern" eine .docx-Datei, die
    sich in Word öffnen lässt
  • Änderungen am Text im Browser landen in der Datei
  • Ein Schreiben lässt sich auch ohne Vertrag erzeugen: an einen
    Kontakt oder an eine frei eingegebene Anschrift
  • Aus einer frei eingegebenen Anschrift lässt sich mit einem Klick ein
    Kontakt anlegen, damit man sie beim nächsten Mal nicht neu tippt
  • „In die Akte legen" erzeugt ein Dokument mit richtung=AUSGANG,
    gesetztem versandAm und empfaenger
  • Besteht ein Bezug zu Vertrag oder Vorgang, wird das Dokument damit
    verknüpft; ohne Bezug wird es trotzdem abgelegt
  • Das Schreiben erscheint in der Dokumentenliste mit dem Abzeichen
    „Ausgang" und ist über den Richtungsfilter findbar
  • Es wird eine Wiedervorlage angelegt (Rückkaufswert 28 Tage,
    Sachstandsanfrage 42 Tage), das Datum ist vorher änderbar
  • Auf „Heute" steht der Vorgang danach unter „Wartet auf andere"
  • Dasselbe funktioniert für Kündigung (Vertrag) und Sachstandsanfrage
    (Vorgang)
  • Der Bestellungsabsatz ist in jedem Schreiben enthalten
  • Jede Ablage steht im Protokoll

Hinweise zur Umsetzung

  • docxErzeugen(kopf, text) in src/lib/berichte/docx.ts existiert
    bereits und wird für den Jahresbericht benutzt — muss nur angebunden
    werden
  • Die Bausteine für den Briefkopf liegen in
    src/lib/vertraege/anschreiben.ts samt bestellungsAbsatz()
  • Dokument.richtung / versandAm / empfaenger sind im Modell
    vorhanden, die Oberfläche kann sie bereits
  • Die Wiedervorlage-Konstanten stehen in rueckkaufswert.ts (28) und
    sachstandsanfrage.ts (42)
  • Kontakt hat Organisation, Anschrift und E-Mail — als Empfänger direkt
    verwendbar

Nicht Teil dieser Aufgabe

Kein E-Mail-Versand aus der Anwendung heraus. Was rausgeht, unterschreibe
ich selbst; ein automatisch versendetes Schreiben ans Betreuungsgericht ist
ein Risiko ohne Gegenwert.

Angelegt auf Zuruf im Chat, nicht aus dem Dashboard — bitte in Nebula
nachtragen.

## Problem Die Anschreiben an Versicherer und Behörden (Rückkaufswert, Kündigung, Sachstandsanfrage) gibt es nur als Text zum Markieren und Kopieren. Danach sind sie weg: in Word nachbauen, ausdrucken, abschicken — und dann noch einmal von Hand als Dokument in die Akte legen, damit sie im Bericht auftauchen. Vier Schritte, von denen regelmäßig einer vergessen wird. Meistens der letzte, und dann fehlt der Nachweis. Dazu kommt: **Schreiben lassen sich heute nur zu einem Vertrag oder einem Vorgang erzeugen.** Am Anfang einer Betreuung schreibt man aber gerade an Stellen, zu denen es noch keinen Datensatz gibt — man fragt ja erst an, um zu erfahren, ob dort etwas besteht. ## Was ich will Ein Schreiben lässt sich an **drei Arten von Empfängern** richten: 1. an einen **Vertrag** (Gesellschaft und Vertragsnummer sind bekannt) 2. an einen **Kontakt** (Anschrift steht schon im System) 3. an eine **frei erfasste Stelle** — Name und Anschrift von Hand, mit der Möglichkeit, daraus gleich einen Kontakt anzulegen Und darunter jeweils: - **Text bearbeitbar** vor der Ausgabe - **Als Word-Datei** (.docx) herunterladen - **In die Akte legen** — Dokument mit Richtung „Ausgang", Empfänger, Versanddatum, verknüpft mit Vertrag bzw. Vorgang, falls vorhanden - **Wiedervorlage anlegen** — mit vorbelegter Frist, änderbar Der Text bleibt bearbeitbar, weil jeder Fall eine Besonderheit hat, die in den Brief gehört. Ein Formulartext, den man nicht mehr ändern kann, wird früher oder später falsch abgeschickt. ## Akzeptanzkriterien - [ ] Beim Vertrag erzeugt „Rückkaufswert anfordern" eine .docx-Datei, die sich in Word öffnen lässt - [ ] Änderungen am Text im Browser landen in der Datei - [ ] Ein Schreiben lässt sich auch **ohne Vertrag** erzeugen: an einen Kontakt oder an eine frei eingegebene Anschrift - [ ] Aus einer frei eingegebenen Anschrift lässt sich mit einem Klick ein Kontakt anlegen, damit man sie beim nächsten Mal nicht neu tippt - [ ] „In die Akte legen" erzeugt ein Dokument mit `richtung=AUSGANG`, gesetztem `versandAm` und `empfaenger` - [ ] Besteht ein Bezug zu Vertrag oder Vorgang, wird das Dokument damit verknüpft; ohne Bezug wird es trotzdem abgelegt - [ ] Das Schreiben erscheint in der Dokumentenliste mit dem Abzeichen „Ausgang" und ist über den Richtungsfilter findbar - [ ] Es wird eine Wiedervorlage angelegt (Rückkaufswert 28 Tage, Sachstandsanfrage 42 Tage), das Datum ist vorher änderbar - [ ] Auf „Heute" steht der Vorgang danach unter „Wartet auf andere" - [ ] Dasselbe funktioniert für Kündigung (Vertrag) und Sachstandsanfrage (Vorgang) - [ ] Der Bestellungsabsatz ist in jedem Schreiben enthalten - [ ] Jede Ablage steht im Protokoll ## Hinweise zur Umsetzung - `docxErzeugen(kopf, text)` in `src/lib/berichte/docx.ts` existiert bereits und wird für den Jahresbericht benutzt — muss nur angebunden werden - Die Bausteine für den Briefkopf liegen in `src/lib/vertraege/anschreiben.ts` samt `bestellungsAbsatz()` - `Dokument.richtung` / `versandAm` / `empfaenger` sind im Modell vorhanden, die Oberfläche kann sie bereits - Die Wiedervorlage-Konstanten stehen in `rueckkaufswert.ts` (28) und `sachstandsanfrage.ts` (42) - `Kontakt` hat Organisation, Anschrift und E-Mail — als Empfänger direkt verwendbar ## Nicht Teil dieser Aufgabe Kein E-Mail-Versand aus der Anwendung heraus. Was rausgeht, unterschreibe ich selbst; ein automatisch versendetes Schreiben ans Betreuungsgericht ist ein Risiko ohne Gegenwert. _Angelegt auf Zuruf im Chat, nicht aus dem Dashboard — bitte in Nebula nachtragen._
florian.wilde added the in-arbeit label 2026-08-23 07:20:33 +00:00
florian.wilde started working 2026-08-23 07:20:51 +00:00
Author
Owner

🤖 Claude Code hat mit der Umsetzung begonnen.

  • Branch: feat/4-schreiben-erzeugen
  • Verstanden als: Ein erzeugtes Schreiben soll den Weg bis zum Ende gehen — bearbeiten, als Word-Datei herunterladen, als Ausgangsdokument in die Akte legen und eine Wiedervorlage hinterlassen. Und es muss auch an Stellen gehen, zu denen es noch keinen Datensatz gibt.
  • Geplantes Vorgehen:
    • Eine eigene Seite fürs Schreiben, die alle drei Empfängerarten kennt — statt die Bearbeitung dreimal an Vertrag, Vorgang und Freitext nachzubauen
    • Brieflayout für die Word-Ausgabe (siehe unten), Download über eine Route
    • „In die Akte legen": Datei in den Objektspeicher, Dokument mit richtung=AUSGANG, Verknüpfung, Wiedervorlage, Protokolleintrag — in einem Zug
    • Die vorhandenen Seiten verlinken dorthin, statt weiter nur Text zum Kopieren zu zeigen

Eine Richtigstellung zu meinem eigenen Umsetzungshinweis: Im Issue steht, docxErzeugen(kopf, text) müsse „nur angebunden werden". Das stimmt so nicht. Die Funktion setzt einen Bericht: Titel, Kopfzeilen mit betreuter Person, Aktenzeichen und Berichtszeitraum, am Ende ein Unterschriftenblock. Ein Brief braucht etwas anderes — Absender, Anschriftenfeld, Datumszeile rechts, Betreff, Anrede, Grußformel.

Ich schreibe deshalb einen eigenen Brief-Satz auf derselben Grundlage (docx-Bibliothek, gleiche Schrift, gleiche Bausteine). Der Berichtssatz bleibt unangetastet — ihn umzubiegen würde beide Ausgaben schlechter machen.

Zeiterfassung läuft.

🤖 **Claude Code hat mit der Umsetzung begonnen.** - Branch: `feat/4-schreiben-erzeugen` - Verstanden als: Ein erzeugtes Schreiben soll den Weg bis zum Ende gehen — bearbeiten, als Word-Datei herunterladen, als Ausgangsdokument in die Akte legen und eine Wiedervorlage hinterlassen. Und es muss auch an Stellen gehen, zu denen es noch keinen Datensatz gibt. - Geplantes Vorgehen: - Eine eigene Seite fürs Schreiben, die alle drei Empfängerarten kennt — statt die Bearbeitung dreimal an Vertrag, Vorgang und Freitext nachzubauen - Brieflayout für die Word-Ausgabe (siehe unten), Download über eine Route - „In die Akte legen": Datei in den Objektspeicher, Dokument mit `richtung=AUSGANG`, Verknüpfung, Wiedervorlage, Protokolleintrag — in einem Zug - Die vorhandenen Seiten verlinken dorthin, statt weiter nur Text zum Kopieren zu zeigen **Eine Richtigstellung zu meinem eigenen Umsetzungshinweis:** Im Issue steht, `docxErzeugen(kopf, text)` müsse „nur angebunden werden". Das stimmt so nicht. Die Funktion setzt einen **Bericht**: Titel, Kopfzeilen mit betreuter Person, Aktenzeichen und Berichtszeitraum, am Ende ein Unterschriftenblock. Ein Brief braucht etwas anderes — Absender, Anschriftenfeld, Datumszeile rechts, Betreff, Anrede, Grußformel. Ich schreibe deshalb einen eigenen Brief-Satz auf derselben Grundlage (`docx`-Bibliothek, gleiche Schrift, gleiche Bausteine). Der Berichtssatz bleibt unangetastet — ihn umzubiegen würde beide Ausgaben schlechter machen. Zeiterfassung läuft.
florian.wilde worked for 53 minutes 2026-08-23 08:14:37 +00:00
florian.wilde added zu-testen and removed in-arbeit labels 2026-08-23 08:15:51 +00:00
Author
Owner

✅ Umsetzung abgeschlossen — bereit zum Testen.

Was geändert wurde

  • Neue Seite /schreiben/neu: Text bearbeiten, Word-Datei herunterladen, in die Akte legen, Wiedervorlage setzen.
  • Drei Empfängerwege: Vertrag, Kontakt, frei getippte Anschrift — aus letzterer entsteht mit einem Klick ein Kontakt.
  • Ablage erzeugt ein Dokument mit richtung=AUSGANG, versandAm, empfaenger, verknüpft mit Vertrag bzw. Vorgang, plus Wiedervorlage und Protokolleintrag.
  • Bei der Sachstandsanfrage wird zusätzlich letzterKontaktAm am Vorgang nachgezogen, damit Wartet auf andere stimmt.
  • Vertrag, Kündigungsassistent und Vorgang verlinken dorthin.
  • Version 1.4.0.

Geänderte Dateien

  • src/lib/schreiben/{arten,entwurf,docx,pdf}.ts(x) (neu)
  • src/server/actions/schreiben.ts (neu), src/app/(app)/schreiben/** (neu)
  • src/components/schreiben/schreiben-editor.tsx (neu)
  • src/components/vertraege/{rueckkaufswert,kuendigungs-assistent}.tsx, src/app/(app)/vorgaenge/[id]/page.tsx
  • tests/schreiben.test.ts (neu), e2e/schreiben.spec.ts (neu), Changelog, README, Installationsanleitung, Roadmap

So testest du es

  1. git switch feat/4-schreiben-erzeugen und npm run dev
  2. Verträge → einen Vertrag öffnen → „Rückkaufswert anfordern" → dort steht jetzt Bearbeiten, als Word-Datei und in die Akte
  3. Text ändern, dann Als Word-Datei — die Datei heißt 2026-08-23_Auskunft-ueber-Rueckkaufswert_….docx und öffnet sich in Word
  4. In die Akte legen → Erwartet: Bestätigung mit zwei Punkten (Dokument abgelegt, Wiedervorlage angelegt)
  5. Dokumente → Richtung „Ausgang": Das Schreiben steht dort, als PDF, mit Empfänger und Versanddatum
  6. Fristen: Es gibt eine Wiedervorlage „Antwort abwarten: …"
  7. Der neue Fall: /schreiben/neu?art=FREI — ohne Vertrag, ohne Vorgang. Name und Anschrift eintragen, Als Kontakt merken, Seite neu laden: Der Kontakt steht in der Auswahl
  8. Gegenprobe: /schreiben/neu?art=RUECKKAUFSWERT&vertragId=unsinn → freundlicher Hinweis statt Fehlerseite

Aufgewendete Zeit: 00:54
Pull Request: #15


Zwei Abweichungen vom Issue, beide begründet

Die Akte bekommt ein PDF, heruntergeladen wird .docx. Der Objektspeicher nimmt nur PDF und Bilder an, geprüft an den Magic Bytes. Eine .docx ist ein ZIP-Archiv; sie durchzulassen hieße jedes ZIP durchzulassen — und diese Prüfung ist eine bewusste Zusage der Anwendung. Sachlich ist PDF für den Nachweis ohnehin richtiger. Folge, die in der Oberfläche steht: Wer die Word-Datei danach noch ändert, hat in der Akte eine andere Fassung.

Der Umsetzungshinweis im Issue war falsch — von mir selbst geschrieben. docxErzeugen() setzt einen Bericht, keinen Brief; es „nur anzubinden" ging nicht. Der Brief hat jetzt einen eigenen Satz, der Berichtssatz bleibt unangetastet.

Nebenbei aufgefallen (gehört ins Dashboard, nicht Teil dieses PR):

  1. Die Dokumentenliste rendert Tabelle und Karten doppelt, je nach Bildschirmbreite ist eine versteckt. Das ist eine gängige Lösung, aber sie hat mich hier zweimal in die Irre geführt: Ein Test greift die unsichtbare Fassung ab und meldet einen Fehler, den es nicht gibt. Wer künftig Tests dagegen schreibt, sollte es wissen — vielleicht lohnt ein Kommentar an der Komponente.
  2. Die Anschrift des Betreuers steht nirgends im Datenmodell. briefkopfBauen() lässt Straße, PLZ und Ort deshalb leer, und in jedem erzeugten Brief fehlt der Absenderblock bis auf den Namen. Bisher fiel das nicht auf, weil man den Text ohnehin in den eigenen Briefkopf kopiert hat. Jetzt, wo eine fertige Datei herauskommt, fehlt es sichtbar.
  3. prisma migrate diff und die Trigramm-Indizes — diesmal nicht aufgetreten (keine Migration), der Punkt aus #3 und #11 bleibt aber offen.

Nach Freigabe: /issue-freigabe 4

✅ **Umsetzung abgeschlossen — bereit zum Testen.** <!-- claude-status branch: feat/4-schreiben-erzeugen pr: 15 zeit_sekunden: 3225 --> **Was geändert wurde** - Neue Seite `/schreiben/neu`: Text bearbeiten, Word-Datei herunterladen, in die Akte legen, Wiedervorlage setzen. - Drei Empfängerwege: Vertrag, Kontakt, frei getippte Anschrift — aus letzterer entsteht mit einem Klick ein Kontakt. - Ablage erzeugt ein Dokument mit `richtung=AUSGANG`, `versandAm`, `empfaenger`, verknüpft mit Vertrag bzw. Vorgang, plus Wiedervorlage und Protokolleintrag. - Bei der Sachstandsanfrage wird zusätzlich `letzterKontaktAm` am Vorgang nachgezogen, damit *Wartet auf andere* stimmt. - Vertrag, Kündigungsassistent und Vorgang verlinken dorthin. - Version 1.4.0. **Geänderte Dateien** - `src/lib/schreiben/{arten,entwurf,docx,pdf}.ts(x)` *(neu)* - `src/server/actions/schreiben.ts` *(neu)*, `src/app/(app)/schreiben/**` *(neu)* - `src/components/schreiben/schreiben-editor.tsx` *(neu)* - `src/components/vertraege/{rueckkaufswert,kuendigungs-assistent}.tsx`, `src/app/(app)/vorgaenge/[id]/page.tsx` - `tests/schreiben.test.ts` *(neu)*, `e2e/schreiben.spec.ts` *(neu)*, Changelog, README, Installationsanleitung, Roadmap **So testest du es** 1. `git switch feat/4-schreiben-erzeugen` und `npm run dev` 2. **Verträge → einen Vertrag öffnen → „Rückkaufswert anfordern"** → dort steht jetzt *Bearbeiten, als Word-Datei und in die Akte* 3. Text ändern, dann **Als Word-Datei** — die Datei heißt `2026-08-23_Auskunft-ueber-Rueckkaufswert_….docx` und öffnet sich in Word 4. **In die Akte legen** → Erwartet: Bestätigung mit zwei Punkten (Dokument abgelegt, Wiedervorlage angelegt) 5. **Dokumente → Richtung „Ausgang"**: Das Schreiben steht dort, als PDF, mit Empfänger und Versanddatum 6. **Fristen**: Es gibt eine Wiedervorlage „Antwort abwarten: …" 7. **Der neue Fall:** `/schreiben/neu?art=FREI` — ohne Vertrag, ohne Vorgang. Name und Anschrift eintragen, *Als Kontakt merken*, Seite neu laden: Der Kontakt steht in der Auswahl 8. Gegenprobe: `/schreiben/neu?art=RUECKKAUFSWERT&vertragId=unsinn` → freundlicher Hinweis statt Fehlerseite **Aufgewendete Zeit:** 00:54 **Pull Request:** #15 --- **Zwei Abweichungen vom Issue, beide begründet** **Die Akte bekommt ein PDF, heruntergeladen wird `.docx`.** Der Objektspeicher nimmt nur PDF und Bilder an, geprüft an den Magic Bytes. Eine `.docx` ist ein ZIP-Archiv; sie durchzulassen hieße jedes ZIP durchzulassen — und diese Prüfung ist eine bewusste Zusage der Anwendung. Sachlich ist PDF für den Nachweis ohnehin richtiger. **Folge, die in der Oberfläche steht:** Wer die Word-Datei danach noch ändert, hat in der Akte eine andere Fassung. **Der Umsetzungshinweis im Issue war falsch** — von mir selbst geschrieben. `docxErzeugen()` setzt einen Bericht, keinen Brief; es „nur anzubinden" ging nicht. Der Brief hat jetzt einen eigenen Satz, der Berichtssatz bleibt unangetastet. **Nebenbei aufgefallen** (gehört ins Dashboard, nicht Teil dieses PR): 1. **Die Dokumentenliste rendert Tabelle und Karten doppelt**, je nach Bildschirmbreite ist eine versteckt. Das ist eine gängige Lösung, aber sie hat mich hier zweimal in die Irre geführt: Ein Test greift die unsichtbare Fassung ab und meldet einen Fehler, den es nicht gibt. Wer künftig Tests dagegen schreibt, sollte es wissen — vielleicht lohnt ein Kommentar an der Komponente. 2. **Die Anschrift des Betreuers steht nirgends im Datenmodell.** `briefkopfBauen()` lässt Straße, PLZ und Ort deshalb leer, und in jedem erzeugten Brief fehlt der Absenderblock bis auf den Namen. Bisher fiel das nicht auf, weil man den Text ohnehin in den eigenen Briefkopf kopiert hat. Jetzt, wo eine fertige Datei herauskommt, fehlt es sichtbar. 3. **`prisma migrate diff` und die Trigramm-Indizes** — diesmal nicht aufgetreten (keine Migration), der Punkt aus #3 und #11 bleibt aber offen. Nach Freigabe: `/issue-freigabe 4`
Author
Owner

🚀 Freigegeben und nach main übernommen.

  • Merge-Commit: a52523f
  • Pull Request: #15 (gemergt)
  • Gesamtaufwand: 00:54
  • Veröffentlicht als v1.4.0 — keine Migration nötig.
cd /opt/docker/configs/betreuungs-cockpit
./scripts/update.sh

Damit sind #5 (E-Mail), #6 (Serienabfrage) und #7 (eigene Vorlagen) entsperrt.

Issue wird geschlossen.

🚀 **Freigegeben und nach `main` übernommen.** <!-- claude-status merge: a52523fc97f8736be001f172cafd9d19b29c5e66 pr: 15 zeit_sekunden: 3225 --> - Merge-Commit: `a52523f` - Pull Request: #15 (gemergt) - Gesamtaufwand: 00:54 - Veröffentlicht als **v1.4.0** — keine Migration nötig. ```bash cd /opt/docker/configs/betreuungs-cockpit ./scripts/update.sh ``` Damit sind #5 (E-Mail), #6 (Serienabfrage) und #7 (eigene Vorlagen) entsperrt. Issue wird geschlossen.
florian.wilde removed the zu-testen label 2026-08-23 08:19:14 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Total Time Spent: 53 minutes
florian.wilde
53 minutes
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: florian.wilde/betreuungs-cockpit#4