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:
@@ -5,7 +5,7 @@ import { redirect } from 'next/navigation'
|
||||
import type { Prisma } from '@prisma/client'
|
||||
import { db, nichtGeloescht } from '@/lib/db'
|
||||
import { erfordereZugang } from '@/lib/auth/sitzung'
|
||||
import { aenderungErmitteln, protokollieren } from '@/lib/audit'
|
||||
import { aenderungErmitteln, protokollieren, type Aenderung } from '@/lib/audit'
|
||||
import { oeffnen, sealen } from '@/lib/crypto/feld'
|
||||
import {
|
||||
AufgabeAbhakenSchema,
|
||||
@@ -58,6 +58,45 @@ function pfadeAuffrischen(vorgangId?: string): void {
|
||||
// Anlegen
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/** Der Name eines Kontakts fuers Protokoll - null bleibt null. */
|
||||
async function kontaktnameZu(kontaktId: string | null): Promise<string | null> {
|
||||
if (!kontaktId) return null
|
||||
const kontakt = await db.kontakt.findUnique({
|
||||
where: { id: kontaktId },
|
||||
select: { name: true, organisation: true },
|
||||
})
|
||||
if (!kontakt) return null
|
||||
return [kontakt.name, kontakt.organisation].filter(Boolean).join(', ')
|
||||
}
|
||||
|
||||
/**
|
||||
* Gehoert der Ansprechpartner zu dieser Akte?
|
||||
*
|
||||
* Ohne die Pruefung koennte ein veraendertes Formular einen Kontakt aus
|
||||
* einer fremden Akte an den Vorgang haengen - und sein Name stuende
|
||||
* anschliessend im Briefkopf.
|
||||
*/
|
||||
async function ansprechpartnerPruefen(
|
||||
betreuteId: string,
|
||||
ansprechpartnerId: string | null,
|
||||
): Promise<{ ok: true } | { ok: false; zustand: Formularzustand }> {
|
||||
if (!ansprechpartnerId) return { ok: true }
|
||||
|
||||
const kontakt = await db.kontakt.findFirst({
|
||||
where: { id: ansprechpartnerId, betreuteId, geloeschtAm: null },
|
||||
select: { id: true },
|
||||
})
|
||||
if (kontakt) return { ok: true }
|
||||
|
||||
return {
|
||||
ok: false,
|
||||
zustand: {
|
||||
fehler: 'Diesen Kontakt gibt es nicht (mehr).',
|
||||
felder: { ansprechpartnerId: 'Bitte einen Kontakt aus dem Verzeichnis wählen.' },
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export async function vorgangAnlegen(
|
||||
_vorher: Formularzustand,
|
||||
formular: FormData,
|
||||
@@ -79,6 +118,10 @@ export async function vorgangAnlegen(
|
||||
}
|
||||
|
||||
const eingabe = gelesen.data
|
||||
|
||||
const geprueft = await ansprechpartnerPruefen(betreuteId, eingabe.ansprechpartnerId)
|
||||
if (!geprueft.ok) return geprueft.zustand
|
||||
|
||||
const jetzt = new Date()
|
||||
|
||||
// Aus der Vorlage entstehen Aufgaben und Fristen in einem Rutsch. Alles
|
||||
@@ -101,6 +144,7 @@ export async function vorgangAnlegen(
|
||||
prioritaet: eingabe.prioritaet,
|
||||
gegenstelle: eingabe.gegenstelle,
|
||||
aktenzeichen: eingabe.aktenzeichen,
|
||||
ansprechpartnerId: eingabe.ansprechpartnerId,
|
||||
verantwortlich: eingabe.verantwortlich ?? benutzer.name,
|
||||
naechsterSchritt:
|
||||
eingabe.naechsterSchritt ?? ergebnis?.aufgaben[0]?.titel ?? null,
|
||||
@@ -205,6 +249,10 @@ export async function vorgangAendern(
|
||||
}
|
||||
|
||||
const eingabe = gelesen.data
|
||||
|
||||
const geprueft = await ansprechpartnerPruefen(vorgang.betreuteId, eingabe.ansprechpartnerId)
|
||||
if (!geprueft.ok) return geprueft.zustand
|
||||
|
||||
const vorherOffen = oeffnen('Vorgang', vorgang)
|
||||
|
||||
const daten: Prisma.VorgangUpdateInput = {
|
||||
@@ -214,6 +262,11 @@ export async function vorgangAendern(
|
||||
prioritaet: eingabe.prioritaet,
|
||||
gegenstelle: eingabe.gegenstelle,
|
||||
aktenzeichen: eingabe.aktenzeichen,
|
||||
// Ueber die Beziehung, nicht ueber das Feld: connect/disconnect ist
|
||||
// das, was Prisma bei einer Update-Eingabe erwartet.
|
||||
ansprechpartner: eingabe.ansprechpartnerId
|
||||
? { connect: { id: eingabe.ansprechpartnerId } }
|
||||
: { disconnect: true },
|
||||
verantwortlich: eingabe.verantwortlich,
|
||||
naechsterSchritt: eingabe.naechsterSchritt,
|
||||
faelligAm: eingabe.faelligAm,
|
||||
@@ -227,6 +280,19 @@ export async function vorgangAendern(
|
||||
|
||||
const geaendert = await db.vorgang.update({ where: { id: vorgang.id }, data: daten })
|
||||
|
||||
// Der Wechsel des Ansprechpartners gehoert mit NAMEN ins Protokoll.
|
||||
// Zwei cuids nebeneinander sind protokolliert, aber nicht
|
||||
// nachvollziehbar - und nachvollziehbar war die Anforderung.
|
||||
const ansprechpartnerWechsel: Aenderung =
|
||||
vorgang.ansprechpartnerId !== geaendert.ansprechpartnerId
|
||||
? {
|
||||
ansprechpartner: {
|
||||
alt: await kontaktnameZu(vorgang.ansprechpartnerId),
|
||||
neu: await kontaktnameZu(geaendert.ansprechpartnerId),
|
||||
},
|
||||
}
|
||||
: {}
|
||||
|
||||
await protokollieren({
|
||||
aktion: 'GEAENDERT',
|
||||
entitaet: 'Vorgang',
|
||||
@@ -238,6 +304,7 @@ export async function vorgangAendern(
|
||||
userName: kontext.benutzer.name,
|
||||
aenderung: {
|
||||
...aenderungErmitteln(vorgang, geaendert),
|
||||
...ansprechpartnerWechsel,
|
||||
...(vorherOffen.beschreibung !== (eingabe.beschreibung ?? null)
|
||||
? { beschreibung: { alt: vorherOffen.beschreibung, neu: eingabe.beschreibung } }
|
||||
: {}),
|
||||
|
||||
Reference in New Issue
Block a user