# Schema-Wünsche aus der Ausgabeschicht (Etappe 7) `prisma/schema.prisma` wurde nicht angefasst. Was beim Bauen der Berichte, des Exports und der Freigaben gefehlt hat, steht hier – mit Begründung und mit dem Behelf, der jetzt an seiner Stelle steht. --- ## 1. Mehrere Fassungen je Bericht **Jetzt:** `Bericht` trägt genau ein `objektSchluessel` / `dateiname` / `pruefsumme`. Wird das PDF nach einer Rückfrage des Gerichts neu erzeugt, überschreibt es die Angaben der Fassung, die bereits vorgelegt wurde. **Warum das stört:** Die Leitfrage der Tabelle ist „was habe ich wann in welcher Fassung abgegeben?“. Genau die lässt sich nach dem zweiten Erzeugen nicht mehr beantworten. Fragt der Rechtspfleger in zwei Jahren nach, welcher Text ihm vorlag, steht der neue da. **Wunsch:** ```prisma model Berichtsfassung { id String @id @default(cuid()) berichtId String bericht Bericht @relation(fields: [berichtId], references: [id], onDelete: Cascade) nummer Int // 1, 2, 3 … format String // "pdf" | "docx" objektSchluessel String dateiname String pruefsumme String erstelltAm DateTime @default(now()) abgegebenAm DateTime? @db.Date abgegebenAn String? @@unique([berichtId, nummer, format]) } ``` **Behelf bis dahin:** Die PDF-Fassung wird am `Bericht` vermerkt, die DOCX-Arbeitsfassung bewusst *nicht* – sonst verdrängte sie die abgegebene Fassung. Die Word-Datei liegt im Objektspeicher und taucht im Vollexport auf, ist aber über die Oberfläche nur bis zum nächsten Erzeugen erreichbar. --- ## 2. Zusammenhang zwischen Unterlagenpaket und Nachforderung **Jetzt:** Beim Erzeugen eines Pakets werden die beigefügten `Nachforderung`-Zeilen auf `UEBERSANDT` gesetzt und bekommen ein `uebersandtAm`. In welchem Paket sie mitgegangen sind, steht nirgends. **Warum das stört:** Der Träger fragt regelmäßig nach einer einzelnen Position („zu Nr. 7 fehlt uns noch etwas“). Ohne Rückbezug muss man raten, welches Anschreiben Nr. 7 enthielt. **Wunsch:** `Nachforderung.uebersandtMitBerichtId String?` mit Relation auf `Bericht`. **Behelf:** Das Anschreiben nennt die laufende Nummer, und der `Bericht`-Datensatz trägt Datum und Positionsanzahl im Titel. --- ## 3. Betreuungsjahr am Bericht **Wunsch:** `Bericht.betreuungsjahr Int?` – die laufende Nummer des Betreuungsjahres, aus dem der Jahresbericht stammt. **Warum:** Das Betreuungsjahr läuft ab dem Tag der Bestellung. Zeiträume allein sind für die Dublettenprüfung unhandlich, sobald jemand den Vorschlag im Formular um einen Tag verschiebt. **Behelf:** Geprüft wird auf `art + zeitraumVon + zeitraumBis`. Ein um einen Tag verschobener Zeitraum erzeugt deshalb einen zweiten Entwurf. --- ## 4. Index für die Dublettenprüfung **Wunsch:** `@@index([betreuteId, art, zeitraumVon, zeitraumBis])` auf `Bericht`. Vorhanden ist nur `@@index([betreuteId, art])`. --- ## 5. Aufbewahrungsfrist am Papierkorb **Wunsch:** `geloeschtVonId String?` auf allen Modellen mit `geloeschtAm`. **Warum:** Das Audit-Log weiß, wer gelöscht hat, aber die Papierkorbliste müsste dafür je Zeile einen Log-Eintrag suchen. Für die Frage „wer hat das weggeräumt?“ direkt an der Zeile wäre ein Feld billiger. --- # Entscheidungen, die keine Schemaänderung brauchen ## Zwei gleichnamige Dateien: `jahresbericht.ts` und `jahresbericht.tsx` Der Bauplan verlangt beide. Beide nebeneinander sind aber eine Falle: Beim Import ohne Endung probiert Webpack `.tsx` vor `.ts`, TypeScript und Vitest umgekehrt. Derselbe Importpfad wäre je nach Werkzeug eine andere Datei – und ein `export * from './jahresbericht'` innerhalb der `.tsx` würde unter Webpack die Datei sich selbst importieren. Gelöst über eindeutige Namen für die Bausteine: | Datei | Inhalt | |---|---| | `jahresbericht.entwurf.ts` | Textbausteine, rein, ohne Datenbank – das, was getestet wird | | `jahresbericht.inhalt.tsx` | Satz für das PDF (React) | | `jahresbericht.ausgabe.ts` | Daten laden, PDF erzeugen | | `jahresbericht.ts` | reicht alle drei weiter | | `jahresbericht.tsx` | reicht alle drei weiter (identisch) | Damit bekommt jeder Aufrufer von `@/lib/berichte/jahresbericht` dieselbe Schnittstelle, gleich welches Werkzeug auflöst. Wer nur die Textbausteine braucht – die Tests, die DOCX-Ausgabe – importiert direkt `@/lib/berichte/jahresbericht.entwurf` und spart sich Datenbank und PDF-Bibliothek. **Alternative, falls das später stört:** `allowImportingTsExtensions: true` in der `tsconfig.json` (mit `noEmit: true` unbedenklich, das ist bereits gesetzt). Dann ließen sich die Endungen ausschreiben und die beiden weiterreichenden Dateien entfielen. ## Vollexport ohne Serverkopie Das ZIP wird als Strom ausgeliefert und **nicht** im Objektspeicher abgelegt. Ein `Bericht`-Datensatz der Art `VOLLEXPORT` hält nur fest, dass und wann exportiert wurde; `objektSchluessel` bleibt leer. Grund: Eine unverschlüsselte Vollkopie des gesamten Bestands dauerhaft auf dem Server liegen zu lassen, wäre die größte Angriffsfläche der ganzen Anwendung – und niemand bräuchte sie ein zweites Mal. ## Landesrecht ohne Bundesgesetz-Link Zwei Hinweiskarten betreffen bayerisches Landesrecht bzw. den Rundfunkbeitragsstaatsvertrag (`landespflegegeld`, `rundfunkbeitragsbefreiung`). Beides steht nicht auf `gesetze-im-internet.de`; die Karten verlinken deshalb auf `gesetze-bayern.de`. Das Schema verlangt nur einen `https`-Link.