Ansprechpartner am Vorgang hinterlegen

Ein namentlich adressiertes Schreiben landet bei der Person, die den
Vorgang kennt, statt in der Poststelle. Am Vorgang laesst sich jetzt ein
Kontakt aus dem Verzeichnis als Ansprechpartner benennen; die
Sachstandsanfrage redet ihn an, und sein Name steht ueber der Behoerde.

Die Sachstandsanfrage konnte das schon - sie bekam den Namen nur nie
uebergeben. entwurf.ts lud einen der verknuepften Kontakte und verwarf
ihn wieder. Wer angeredet wird, ist jetzt eine Entscheidung und kein
Zufall.

Aufbau:
- Migration: ansprechpartnerId am Vorgang (SetNull - ein Vorgang darf
  nicht daran haengen, dass es den Kontakt noch gibt) und anrede am
  Kontakt.
- Die Anrede als reine Funktion in kontakte/anrede.ts. Geraten wird nie:
  ohne hinterlegte Anrede wird mit vollem Namen angeredet. Ein leerer
  Name mit gesetzter Anrede faellt auf die allgemeine Anrede zurueck -
  "Sehr geehrte Frau ," darf nie herausgehen.
- Der Wechsel des Ansprechpartners steht mit NAMEN im Protokoll. Zwei
  cuids nebeneinander waeren protokolliert, aber nicht nachvollziehbar,
  und nachvollziehbar war die Anforderung.
- Der Ansprechpartner wird gegen die Akte geprueft, bevor er gespeichert
  wird - sein Name steht anschliessend im Briefkopf.

Nebenbei behoben: Der Schreiben-Editor verwarf die empfaengerAnschrift
aus dem Entwurf, sein State startete immer leer. Jetzt kommt die
Anschrift des Ansprechpartners im Formular an.

Geprueft: neun Einheitstests fuer die Anrede, fuenf End-to-End-Tests von
der Auswahl bis zum Protokolleintrag.

Refs #9
This commit is contained in:
Florian Wilde
2026-08-23 16:31:10 +02:00
parent 5e7d88cf64
commit 9e68d10787
23 changed files with 651 additions and 31 deletions
+61
View File
@@ -0,0 +1,61 @@
import type { KontaktAnrede } from '@prisma/client'
/**
* Die Briefanrede eines Ansprechpartners.
*
* Ein namentlich adressiertes Schreiben landet bei der Person, die den
* Vorgang kennt, statt in der Poststelle. Beim Bezirk Oberfranken ist das
* der Unterschied zwischen zwei Wochen und zwei Monaten.
*
* Zwei Regeln, die hier nicht verhandelbar sind:
*
* 1. Es wird nie geraten. Ohne hinterlegte Anrede wird mit dem vollen
* Namen angeredet ("Sehr geehrte(r) Anna Schmitt,"). Eine falsch
* geratene Anrede faellt dem Empfaenger sofort auf und kostet genau
* die Aufmerksamkeit, die man gewinnen wollte.
* 2. Ohne Ansprechpartner bleibt es bei "Sehr geehrte Damen und Herren,".
* Ein halb gefuellter Name darf nie zu "Sehr geehrte Frau ," werden -
* lieber unpersoenlich als offensichtlich automatisch.
*/
export const ANREDE_BESCHRIFTUNG: Record<KontaktAnrede, string> = {
OHNE: 'keine Angabe',
FRAU: 'Frau',
HERR: 'Herr',
}
export const ALLGEMEINE_ANREDE = 'Sehr geehrte Damen und Herren,'
/**
* Der Nachname aus einem vollen Namen.
*
* Titel und Vornamen fallen weg: "Dr. Anna Schmitt" wird zu "Schmitt".
* Doppelnamen mit Bindestrich bleiben ganz, weil sie ein Wort sind.
*/
export function nachnameAus(name: string): string {
const teile = name.trim().split(/\s+/).filter(Boolean)
return teile.length > 0 ? teile[teile.length - 1]! : ''
}
export type Ansprechpartner = {
name: string
anrede: KontaktAnrede
}
/**
* Die Anredezeile fuer ein Schreiben, einschliesslich Komma.
*
* Ohne Ansprechpartner - oder mit einem, dessen Name leer ist - die
* allgemeine Anrede.
*/
export function anredeZeile(ansprechpartner: Ansprechpartner | null): string {
if (!ansprechpartner) return ALLGEMEINE_ANREDE
const name = ansprechpartner.name.trim()
if (!name) return ALLGEMEINE_ANREDE
if (ansprechpartner.anrede === 'FRAU') return `Sehr geehrte Frau ${nachnameAus(name)},`
if (ansprechpartner.anrede === 'HERR') return `Sehr geehrter Herr ${nachnameAus(name)},`
return `Sehr geehrte(r) ${name},`
}