feat: Immobilie, Versicherungen und Heim mit COPD-Verlauf
Etappe 6. Das leerstehende Haus, die Vertraege und der Gesundheitsverlauf - die drei Bereiche, in denen fuer diesen Fall das meiste Geld und das meiste Risiko liegt. Leerstands-Checkliste mit zehn Punkten, jeder mit Begruendung. Der wichtigste: den Gebaeudeversicherer ueber den Leerstand informieren - sonst droht Leistungsfreiheit, und zwar genau dann, wenn es brennt oder eine Leitung platzt. Dazu Verkehrssicherungspflicht, Frostschutz zum Oktober, Kontrollgaenge, Zaehlerstaende, Schluesselverzeichnis. Der Kuendigungsrechner nennt den spaetesten ABSENDETAG, nicht den Fristablauf: eine Kuendigung wirkt mit dem Zugang, nicht mit dem Abschicken. Drei Tage Postlaufpuffer sind einkalkuliert. Der Kuendigungs-Assistent beantwortet die Genehmigungsfrage nach § 1850 BGB nicht - er stellt sie und verlangt den Gang zum Rechtspfleger. Der Versandnachweis ist Pflichtfeld: ohne ihn kommt die Kuendigung nicht durch die Pruefung. Leistungszuschlag nach § 43c SGB XI mit Stand 01.01.2024 (15/30/50/75 Prozent nach Verweildauer, erst ab Pflegegrad 2). Die Oberflaeche zeigt, ab wann die naechste Stufe greift - das ist bares Geld und wird regelmaessig uebersehen. COPD-Schnellerfassung fuer Exazerbation, Sauerstoff, Sturz, Krankenhaus, Hilfsmittel und Impfungen, mit STIKO-Plan fuer COPD. Beschreibungen verschluesselt. Die Jahresauswertung ueber Exazerbationen und Krankenhaustage wandert in den Jahresbericht und begruendet eine Hoeherstufung. 74 Tests. Etappe: 6 Phase: Substanz
This commit is contained in:
+171
-172
@@ -1,172 +1,171 @@
|
||||
import { z } from 'zod'
|
||||
import {
|
||||
optionalerBetrag,
|
||||
optionalerText,
|
||||
optionaleZahl,
|
||||
optionalesDatum,
|
||||
pflichtBetrag,
|
||||
pflichtDatum,
|
||||
pflichtText,
|
||||
} from '@/lib/validierung/substanz'
|
||||
import { WERTQUELLEN_VERTRAG } from '@/lib/vertraege/konstanten'
|
||||
|
||||
/**
|
||||
* Eingabepruefung fuer Versicherungen und Vertraege.
|
||||
*/
|
||||
|
||||
export const VERTRAG_ARTEN = [
|
||||
'LEBENSVERSICHERUNG',
|
||||
'STERBEGELDVERSICHERUNG',
|
||||
'BESTATTUNGSVORSORGE',
|
||||
'RENTENVERSICHERUNG_PRIVAT',
|
||||
'UNFALLVERSICHERUNG',
|
||||
'HAFTPFLICHT',
|
||||
'HAUSRAT',
|
||||
'WOHNGEBAEUDE',
|
||||
'KRANKENZUSATZ',
|
||||
'PFLEGEZUSATZ',
|
||||
'RECHTSSCHUTZ',
|
||||
'STERBEKASSE',
|
||||
'STROM',
|
||||
'GAS',
|
||||
'WASSER',
|
||||
'TELEFON_INTERNET',
|
||||
'RUNDFUNKBEITRAG',
|
||||
'MITGLIEDSCHAFT',
|
||||
'ABONNEMENT',
|
||||
'SONSTIGES',
|
||||
] as const
|
||||
|
||||
export const VERTRAG_STATUS = [
|
||||
'AKTIV',
|
||||
'BEITRAGSFREI',
|
||||
'RUHEND',
|
||||
'GEKUENDIGT',
|
||||
'ABGETRETEN',
|
||||
'VERWERTET',
|
||||
'ABGELAUFEN',
|
||||
] as const
|
||||
|
||||
export const ZAHL_RHYTHMEN = [
|
||||
'MONATLICH',
|
||||
'VIERTELJAEHRLICH',
|
||||
'HALBJAEHRLICH',
|
||||
'JAEHRLICH',
|
||||
'EINMALIG',
|
||||
] as const
|
||||
|
||||
export const BEWERTUNGEN = ['UNGEPRUEFT', 'VERWERTBAR', 'GESCHUETZT', 'STRITTIG'] as const
|
||||
|
||||
export const VertragSchema = z
|
||||
.object({
|
||||
bezeichnung: pflichtText(
|
||||
150,
|
||||
'Bitte eine Bezeichnung angeben, z. B. „Sterbegeldversicherung Allianz“.',
|
||||
),
|
||||
gesellschaft: optionalerText(150),
|
||||
art: z.enum(VERTRAG_ARTEN),
|
||||
status: z.enum(VERTRAG_STATUS).default('AKTIV'),
|
||||
|
||||
/** Wird verschlüsselt gespeichert. */
|
||||
vertragsnummer: optionalerText(80),
|
||||
|
||||
beginnAm: optionalesDatum,
|
||||
endeAm: optionalesDatum,
|
||||
kuendigungsfristMonate: optionaleZahl(
|
||||
0,
|
||||
120,
|
||||
'Bitte die Kündigungsfrist in ganzen Monaten angeben.',
|
||||
),
|
||||
laufzeitJahre: optionaleZahl(1, 99, 'Bitte die Laufzeit in ganzen Jahren angeben.'),
|
||||
kuendigungZum: optionalesDatum,
|
||||
gekuendigtAm: optionalesDatum,
|
||||
|
||||
beitrag: optionalerBetrag,
|
||||
rhythmus: z.enum(ZAHL_RHYTHMEN).nullable().catch(null),
|
||||
|
||||
bewertungSozialhilfe: z.enum(BEWERTUNGEN).default('UNGEPRUEFT'),
|
||||
bewertungBegruendung: optionalerText(4000),
|
||||
|
||||
notizen: optionalerText(4000),
|
||||
})
|
||||
.superRefine((daten, kontext) => {
|
||||
if (daten.beginnAm && daten.endeAm && daten.endeAm.getTime() < daten.beginnAm.getTime()) {
|
||||
kontext.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ['endeAm'],
|
||||
message: 'Das Vertragsende liegt vor dem Beginn.',
|
||||
})
|
||||
}
|
||||
if (daten.beitrag !== null && !daten.rhythmus) {
|
||||
kontext.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ['rhythmus'],
|
||||
message: 'Zu einem Beitrag gehört der Zahlungsrhythmus — sonst lässt sich der Jahresbeitrag nicht rechnen.',
|
||||
})
|
||||
}
|
||||
if (daten.bewertungSozialhilfe !== 'UNGEPRUEFT' && !daten.bewertungBegruendung) {
|
||||
kontext.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ['bewertungBegruendung'],
|
||||
message:
|
||||
'Bitte begründen, warum du den Vertrag so einordnest. Der Bezirk fragt danach, ' +
|
||||
'und im Zweifel steht diese Begründung Jahre später im Widerspruchsverfahren.',
|
||||
})
|
||||
}
|
||||
if (daten.status === 'GEKUENDIGT' && !daten.gekuendigtAm) {
|
||||
kontext.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ['gekuendigtAm'],
|
||||
message: 'Bitte das Datum der Kündigung angeben.',
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
export type VertragEingabe = z.infer<typeof VertragSchema>
|
||||
|
||||
/** Rückkaufswert zu einem Stichtag - Historie, nichts wird überschrieben. */
|
||||
export const RueckkaufswertSchema = z.object({
|
||||
stichtag: pflichtDatum,
|
||||
wert: pflichtBetrag,
|
||||
wertquelle: z.enum(WERTQUELLEN_VERTRAG, {
|
||||
errorMap: () => ({ message: 'Bitte angeben, woher der Wert stammt.' }),
|
||||
}),
|
||||
bemerkung: optionalerText(1000),
|
||||
})
|
||||
|
||||
export type RueckkaufswertEingabe = z.infer<typeof RueckkaufswertSchema>
|
||||
|
||||
export const RueckkaufswertAnfrageSchema = z.object({
|
||||
stichtag: pflichtDatum,
|
||||
empfaengerAnschrift: optionalerText(500),
|
||||
})
|
||||
|
||||
export type RueckkaufswertAnfrageEingabe = z.infer<typeof RueckkaufswertAnfrageSchema>
|
||||
|
||||
/**
|
||||
* Kündigung vermerken. Der Versandnachweis ist Pflicht: Ohne ihn lässt
|
||||
* sich der Zugang nicht beweisen, und beweisen muss ihn derjenige, der
|
||||
* gekündigt hat.
|
||||
*/
|
||||
export const KuendigungVermerkenSchema = z
|
||||
.object({
|
||||
gekuendigtAm: pflichtDatum,
|
||||
kuendigungZum: optionalesDatum,
|
||||
versandart: pflichtText(100, 'Bitte angeben, wie die Kündigung versandt wurde.'),
|
||||
nachweisVorhanden: z.boolean().default(false),
|
||||
genehmigungGeklaert: z.boolean().default(false),
|
||||
bemerkung: optionalerText(2000),
|
||||
})
|
||||
.superRefine((daten, kontext) => {
|
||||
if (!daten.nachweisVorhanden) {
|
||||
kontext.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ['nachweisVorhanden'],
|
||||
message:
|
||||
'Ohne Versandnachweis wird die Kündigung nicht als erledigt geführt. ' +
|
||||
'Lade Einschreibenbeleg oder Faxprotokoll als Dokument hoch und hake dann an.',
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
export type KuendigungVermerkenEingabe = z.infer<typeof KuendigungVermerkenSchema>
|
||||
import { z } from 'zod'
|
||||
import {
|
||||
optionalerBetrag,
|
||||
optionalerText,
|
||||
optionaleZahl,
|
||||
optionalesDatum,
|
||||
pflichtBetrag,
|
||||
pflichtDatum,
|
||||
pflichtText,
|
||||
} from '@/lib/validierung/substanz'
|
||||
import { WERTQUELLEN_VERTRAG } from '@/lib/vertraege/konstanten'
|
||||
|
||||
/**
|
||||
* Eingabepruefung fuer Versicherungen und Vertraege.
|
||||
*/
|
||||
|
||||
export const VERTRAG_ARTEN = [
|
||||
'LEBENSVERSICHERUNG',
|
||||
'STERBEGELDVERSICHERUNG',
|
||||
'BESTATTUNGSVORSORGE',
|
||||
'RENTENVERSICHERUNG_PRIVAT',
|
||||
'UNFALLVERSICHERUNG',
|
||||
'HAFTPFLICHT',
|
||||
'HAUSRAT',
|
||||
'WOHNGEBAEUDE',
|
||||
'KRANKENZUSATZ',
|
||||
'PFLEGEZUSATZ',
|
||||
'RECHTSSCHUTZ',
|
||||
'STERBEKASSE',
|
||||
'STROM',
|
||||
'GAS',
|
||||
'WASSER',
|
||||
'TELEFON_INTERNET',
|
||||
'RUNDFUNKBEITRAG',
|
||||
'MITGLIEDSCHAFT',
|
||||
'ABONNEMENT',
|
||||
'SONSTIGES',
|
||||
] as const
|
||||
|
||||
export const VERTRAG_STATUS = [
|
||||
'AKTIV',
|
||||
'BEITRAGSFREI',
|
||||
'RUHEND',
|
||||
'GEKUENDIGT',
|
||||
'ABGETRETEN',
|
||||
'VERWERTET',
|
||||
'ABGELAUFEN',
|
||||
] as const
|
||||
|
||||
export const ZAHL_RHYTHMEN = [
|
||||
'MONATLICH',
|
||||
'VIERTELJAEHRLICH',
|
||||
'HALBJAEHRLICH',
|
||||
'JAEHRLICH',
|
||||
'EINMALIG',
|
||||
] as const
|
||||
|
||||
export const BEWERTUNGEN = ['UNGEPRUEFT', 'VERWERTBAR', 'GESCHUETZT', 'STRITTIG'] as const
|
||||
|
||||
export const VertragSchema = z
|
||||
.object({
|
||||
bezeichnung: pflichtText(
|
||||
150,
|
||||
'Bitte eine Bezeichnung angeben, z. B. „Sterbegeldversicherung Allianz“.',
|
||||
),
|
||||
gesellschaft: optionalerText(150),
|
||||
art: z.enum(VERTRAG_ARTEN),
|
||||
status: z.enum(VERTRAG_STATUS).default('AKTIV'),
|
||||
|
||||
/** Wird verschlüsselt gespeichert. */
|
||||
vertragsnummer: optionalerText(80),
|
||||
|
||||
beginnAm: optionalesDatum,
|
||||
endeAm: optionalesDatum,
|
||||
kuendigungsfristMonate: optionaleZahl(
|
||||
0,
|
||||
120,
|
||||
'Bitte die Kündigungsfrist in ganzen Monaten angeben.',
|
||||
),
|
||||
kuendigungZum: optionalesDatum,
|
||||
gekuendigtAm: optionalesDatum,
|
||||
|
||||
beitrag: optionalerBetrag,
|
||||
rhythmus: z.enum(ZAHL_RHYTHMEN).nullable().catch(null),
|
||||
|
||||
bewertungSozialhilfe: z.enum(BEWERTUNGEN).default('UNGEPRUEFT'),
|
||||
bewertungBegruendung: optionalerText(4000),
|
||||
|
||||
notizen: optionalerText(4000),
|
||||
})
|
||||
.superRefine((daten, kontext) => {
|
||||
if (daten.beginnAm && daten.endeAm && daten.endeAm.getTime() < daten.beginnAm.getTime()) {
|
||||
kontext.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ['endeAm'],
|
||||
message: 'Das Vertragsende liegt vor dem Beginn.',
|
||||
})
|
||||
}
|
||||
if (daten.beitrag !== null && !daten.rhythmus) {
|
||||
kontext.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ['rhythmus'],
|
||||
message: 'Zu einem Beitrag gehört der Zahlungsrhythmus — sonst lässt sich der Jahresbeitrag nicht rechnen.',
|
||||
})
|
||||
}
|
||||
if (daten.bewertungSozialhilfe !== 'UNGEPRUEFT' && !daten.bewertungBegruendung) {
|
||||
kontext.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ['bewertungBegruendung'],
|
||||
message:
|
||||
'Bitte begründen, warum du den Vertrag so einordnest. Der Bezirk fragt danach, ' +
|
||||
'und im Zweifel steht diese Begründung Jahre später im Widerspruchsverfahren.',
|
||||
})
|
||||
}
|
||||
if (daten.status === 'GEKUENDIGT' && !daten.gekuendigtAm) {
|
||||
kontext.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ['gekuendigtAm'],
|
||||
message: 'Bitte das Datum der Kündigung angeben.',
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
export type VertragEingabe = z.infer<typeof VertragSchema>
|
||||
|
||||
/** Rückkaufswert zu einem Stichtag - Historie, nichts wird überschrieben. */
|
||||
export const RueckkaufswertSchema = z.object({
|
||||
stichtag: pflichtDatum,
|
||||
wert: pflichtBetrag,
|
||||
wertquelle: z.enum(WERTQUELLEN_VERTRAG, {
|
||||
errorMap: () => ({ message: 'Bitte angeben, woher der Wert stammt.' }),
|
||||
}),
|
||||
bemerkung: optionalerText(1000),
|
||||
})
|
||||
|
||||
export type RueckkaufswertEingabe = z.infer<typeof RueckkaufswertSchema>
|
||||
|
||||
export const RueckkaufswertAnfrageSchema = z.object({
|
||||
stichtag: pflichtDatum,
|
||||
empfaengerAnschrift: optionalerText(500),
|
||||
})
|
||||
|
||||
export type RueckkaufswertAnfrageEingabe = z.infer<typeof RueckkaufswertAnfrageSchema>
|
||||
|
||||
/**
|
||||
* Kündigung vermerken. Der Versandnachweis ist Pflicht: Ohne ihn lässt
|
||||
* sich der Zugang nicht beweisen, und beweisen muss ihn derjenige, der
|
||||
* gekündigt hat.
|
||||
*/
|
||||
export const KuendigungVermerkenSchema = z
|
||||
.object({
|
||||
gekuendigtAm: pflichtDatum,
|
||||
kuendigungZum: optionalesDatum,
|
||||
versandart: pflichtText(100, 'Bitte angeben, wie die Kündigung versandt wurde.'),
|
||||
nachweisVorhanden: z.boolean().default(false),
|
||||
genehmigungGeklaert: z.boolean().default(false),
|
||||
bemerkung: optionalerText(2000),
|
||||
})
|
||||
.superRefine((daten, kontext) => {
|
||||
if (!daten.nachweisVorhanden) {
|
||||
kontext.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ['nachweisVorhanden'],
|
||||
message:
|
||||
'Ohne Versandnachweis wird die Kündigung nicht als erledigt geführt. ' +
|
||||
'Lade Einschreibenbeleg oder Faxprotokoll als Dokument hoch und hake dann an.',
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
export type KuendigungVermerkenEingabe = z.infer<typeof KuendigungVermerkenSchema>
|
||||
|
||||
Reference in New Issue
Block a user