# Schema-Wünsche: Vorgänge, Aufgaben, Genehmigungen Beim Bau von Etappe 2 („Vorgänge (Fallakte)“) sind vier Stellen aufgefallen, an denen das Datenmodell die Fachlichkeit nur mit Umwegen abbildet. Nichts davon blockiert die Umsetzung — alles ist im Code sauber umschifft. Die Umwege stehen unten mit dabei, damit man beim Ändern weiß, was wegfällt. `prisma/schema.prisma` wurde **nicht** angefasst. --- ## 1. `Genehmigung`: Die Versagung hat kein eigenes Datum **Ist**: `mitteilungAm`, `antragAm`, `anhoerungAm`, `beschlussAm`, `rechtskraftAm`, `vollzugAm` — für jede Stufe der Kette ein Feld. Nur der Seitenausgang `VERSAGT` hat keins. **Warum das stört**: Der Zeitstrahl der Fallakte baut die Chronik des Genehmigungsverfahrens aus genau diesen Datumsfeldern. Eine Versagung ist aber der Ausgang, der später am meisten Erklärung braucht — gegenüber dem Gericht, gegenüber Miterben, und für die Frage, ob eine Beschwerde noch läuft. **Wunsch**: ```prisma versagungAm DateTime? @db.Date versagungsgrund String? ``` **Umweg bis dahin**: `src/lib/vorgaenge/zeitstrahl.ts` zeigt eine Versagung am `beschlussAm` an — das Gericht versagt ja mit einem Beschluss. Der Grund landet in `notizenVerschluesselt`. --- ## 2. `Aufgabe`: kein Papierkorb **Ist**: `Aufgabe` hat kein `geloeschtAm`. Sie hängt per `onDelete: Cascade` am Vorgang. **Warum das stört**: Vorlagen bringen bis zu zehn Aufgaben mit. Manche davon passen im Einzelfall nicht („Rundfunkbeitrag“, wenn nie einer gezahlt wurde). Sie einfach abzuhaken ist unehrlich — sie wurden nicht erledigt, sie waren gegenstandslos. Löschen wiederum ist im Rest der Anwendung immer ein Papierkorb, hier wäre es endgültig. **Wunsch**: ```prisma geloeschtAm DateTime? entfaellt Boolean @default(false) entfallGrund String? ``` `entfaellt` wäre das Ehrlichere: Die Aufgabe bleibt in der Akte sichtbar, zählt aber nicht gegen den Fortschritt. **Umweg bis dahin**: Es gibt in dieser Etappe keine Möglichkeit, eine Aufgabe zu entfernen. Nicht passende Aufgaben bleiben offen stehen. --- ## 3. Statuswechsel des Vorgangs stehen nur im Audit-Log **Ist**: Der Zeitstrahl liest die Statuschronik eines Vorgangs aus `AuditLog`, entschlüsselt `aenderungVerschluesselt` und sucht darin das Feld `status`. **Warum das stört**: Drei Dinge auf einmal — 1. Es werden bis zu 200 Log-Einträge je Aufruf entschlüsselt, nur um ein Feld zu lesen. Das skaliert schlecht und lässt sich nicht filtern, weil der Umschlag nicht durchsuchbar ist. 2. Das Audit-Log ist ein Nachweis, keine Fachtabelle. Es fachlich auszuwerten vermischt zwei Zwecke. 3. Ein Log-Eintrag, der sich nicht entschlüsseln lässt (Schlüsselrotation), reißt still ein Loch in die Chronik. **Wunsch**: eine schmale Tabelle ```prisma model VorgangStatuswechsel { id String @id @default(cuid()) vorgangId String vorgang Vorgang @relation(fields: [vorgangId], references: [id], onDelete: Cascade) von VorgangStatus? nach VorgangStatus zeitpunkt DateTime @default(now()) userId String? userName String? @@index([vorgangId, zeitpunkt]) } ``` **Umweg bis dahin**: `src/app/(app)/vorgaenge/[id]/page.tsx` liest das Audit-Log und fängt unlesbare Einträge einzeln ab. Die Schnittstelle von `zeitstrahlBauen()` nimmt die Wechsel bereits als eigene Quelle entgegen — ein Umstieg auf die Tabelle wäre eine Änderung in einer Datei. --- ## 4. `Vorgang`: kein Feld für den Ansprechpartner bei der Gegenstelle **Ist**: `gegenstelle` (Text) und `aktenzeichen` (Text), dazu die n:m- Beziehung `kontakte`. Wer bei der Behörde konkret zuständig ist, steht nirgends direkt am Vorgang. **Warum das stört**: Die Sachstandsanfrage (`src/lib/vorgaenge/sachstandsanfrage.ts`) kann eine namentliche Anrede erzeugen — genau die, die erfahrungsgemäß schneller beantwortet wird. Sie bekommt den Namen aber nicht, ohne über `kontakte` zu raten, welcher der verknüpften Kontakte gemeint ist. **Wunsch**: ```prisma /// Der eine Kontakt, der diesen Vorgang bei der Gegenstelle führt. ansprechpartnerId String? ansprechpartner Kontakt? @relation("VorgangAnsprechpartner", fields: [ansprechpartnerId], references: [id], onDelete: SetNull) ``` **Umweg bis dahin**: `sachstandsanfrageErzeugen()` nimmt den Ansprechpartner als optionalen Parameter entgegen und fällt sonst auf „Sehr geehrte Damen und Herren“ zurück. Die Seite übergibt ihn derzeit nicht. --- ## Nicht gewünscht Ausdrücklich **kein** Wunsch ist ein Enum für `Genehmigung.rechtsgrundlage`. Der Freitext ist richtig: Die Auswahlliste in `src/lib/vorgaenge/genehmigungskette.ts` deckt den Alltag ab, aber seltene Tatbestände muss man eintragen können, ohne eine Migration zu schreiben.