/** * Platzhalter in Schreibvorlagen. * * Rein und ohne Datenbank. Der Vertrag ist einfach: {{name}} wird ersetzt, * und zwar nach drei Regeln, die alle demselben Grundsatz folgen - * NICHTS geht stillschweigend schief: * * 1. Bekannter Platzhalter, Daten vorhanden -> Wert eingesetzt. * 2. Bekannter Platzhalter, Daten fehlen -> sichtbare Luecke * "[Aktenzeichen]". Eine stille Leerstelle wuerde erst der Empfaenger * bemerken - oder niemand. * 3. Unbekannter Platzhalter -> markiert als * "[Unbekannter Platzhalter: {{xyz}}]". Kein Abbruch: Ein Tippfehler * in einer Vorlage darf das Schreiben nicht verhindern, aber er muss * ins Auge springen. Falsch ausgefuellt ist schlimmer als * offensichtlich leer. */ export type PlatzhalterName = | 'betreute_name' | 'betreute_geburtsdatum' | 'betreute_anschrift' | 'betreuer_name' | 'betreuer_anschrift' | 'betreuer_ort' | 'betreuungsgericht' | 'aktenzeichen_gericht' | 'bestellung_datum' | 'bestellungsabsatz' | 'vertrag_gesellschaft' | 'vertrag_nummer' | 'vertrag_bezeichnung' | 'stichtag' | 'datum_heute' export type PlatzhalterBeschreibung = { name: PlatzhalterName beschriftung: string /** Woher der Wert kommt - steht in der Hilfe neben dem Editor. */ quelle: string } /** * Die verfuegbaren Platzhalter, in der Reihenfolge der Anzeige. * * Diese Liste steht beim Bearbeiten NEBEN dem Editor - niemand soll * Platzhalternamen raten muessen. */ export const PLATZHALTER: readonly PlatzhalterBeschreibung[] = [ { name: 'betreute_name', beschriftung: 'Name der betreuten Person', quelle: 'Stammdaten' }, { name: 'betreute_geburtsdatum', beschriftung: 'Geburtsdatum', quelle: 'Stammdaten' }, { name: 'betreute_anschrift', beschriftung: 'Anschrift (Heim)', quelle: 'Stammdaten' }, { name: 'betreuer_name', beschriftung: 'Dein Name', quelle: 'Dein Zugang' }, { name: 'betreuer_anschrift', beschriftung: 'Deine Anschrift', quelle: 'Mein Konto', }, { name: 'betreuer_ort', beschriftung: 'Dein Ort', quelle: 'Mein Konto' }, { name: 'betreuungsgericht', beschriftung: 'Betreuungsgericht', quelle: 'Stammdaten' }, { name: 'aktenzeichen_gericht', beschriftung: 'Aktenzeichen des Gerichts', quelle: 'Stammdaten' }, { name: 'bestellung_datum', beschriftung: 'Datum der Bestellung', quelle: 'Stammdaten' }, { name: 'bestellungsabsatz', beschriftung: 'Der ganze Bestellungsabsatz', quelle: 'Aus Gericht, Aktenzeichen und Bestellungsdatum gebaut', }, { name: 'vertrag_gesellschaft', beschriftung: 'Gesellschaft', quelle: 'Vertrag, falls gewählt' }, { name: 'vertrag_nummer', beschriftung: 'Vertragsnummer', quelle: 'Vertrag, falls gewählt' }, { name: 'vertrag_bezeichnung', beschriftung: 'Vertragsbezeichnung', quelle: 'Vertrag, falls gewählt' }, { name: 'stichtag', beschriftung: 'Stichtag', quelle: 'Beim Erzeugen gewählt' }, { name: 'datum_heute', beschriftung: 'Heutiges Datum', quelle: 'Beim Erzeugen' }, ] const BEKANNT = new Set(PLATZHALTER.map((p) => p.name)) /** Die sichtbare Luecke, wenn Daten fehlen: "[Aktenzeichen des Gerichts]". */ function luecke(name: PlatzhalterName): string { const eintrag = PLATZHALTER.find((p) => p.name === name) return `[${eintrag?.beschriftung ?? name}]` } export type PlatzhalterWerte = Partial> export type ErsetzungsErgebnis = { text: string /** Bekannte Platzhalter ohne Daten - als Luecke eingesetzt. */ luecken: PlatzhalterName[] /** Unbekannte Platzhalter - markiert im Text. */ unbekannte: string[] } /** Findet alle {{...}}-Vorkommen. Grosszuegig beim Namen: auch Tippfehler * sollen gefunden (und dann markiert) werden. */ const MUSTER = /\{\{\s*([a-zA-Z0-9_äöüÄÖÜß-]+)\s*\}\}/g export function platzhalterErsetzen( vorlage: string, werte: PlatzhalterWerte, ): ErsetzungsErgebnis { const luecken = new Set() const unbekannte = new Set() const text = vorlage.replace(MUSTER, (treffer, roh: string) => { const name = roh.trim() if (!BEKANNT.has(name)) { unbekannte.add(name) return `[Unbekannter Platzhalter: {{${name}}}]` } const wert = werte[name as PlatzhalterName] if (wert === null || wert === undefined || wert.trim() === '') { luecken.add(name as PlatzhalterName) return luecke(name as PlatzhalterName) } return wert }) return { text, luecken: [...luecken], unbekannte: [...unbekannte] } } /** Welche Platzhalter benutzt eine Vorlage? Fuer die Anzeige in der Liste. */ export function benutztePlatzhalter(vorlage: string): string[] { const gefunden = new Set() for (const treffer of vorlage.matchAll(MUSTER)) { gefunden.add(treffer[1]!.trim()) } return [...gefunden] } /** * Fehlt der Bestellungsabsatz? * * Erfuellt ist die Pruefung durch den Platzhalter {{bestellungsabsatz}} * ODER durch einen von Hand geschriebenen Absatz, der erkennbar die * Bestellung nachweist (Beschluss + Betreuer im selben Text). Wer den * Absatz ausformuliert hat, soll nicht gegaengelt werden. * * Die Warnung ist eine Warnung, kein Verbot: Ein Schreiben an die eigene * Hausverwaltung braucht keinen Bestellungsnachweis. Aber wer ihn * weglaesst, soll es wissentlich tun. */ export function bestellungsabsatzFehlt(vorlage: string): boolean { if (/\{\{\s*bestellungsabsatz\s*\}\}/.test(vorlage)) return false const klein = vorlage.toLowerCase() const nennBestellung = klein.includes('beschluss') && (klein.includes('betreuer') || klein.includes('betreuung')) return !nennBestellung }