Zeilenenden der 24 verbliebenen Dateien normalisieren

Ausschliesslich Zeilenenden. Nachgewiesen mit
"git diff --cached --ignore-cr-at-eol": Der Diff ist leer, es hat sich
kein Zeichen Inhalt geaendert.

Deshalb ein eigener Commit: 7448 geaenderte Zeilen in einem Commit mit
echten Aenderungen zu verstecken, macht die Historie an dieser Stelle
unlesbar. So laesst er sich beim Durchsehen ueberspringen.

Refs #26
This commit is contained in:
Florian Wilde
2026-08-23 23:37:02 +02:00
parent 6a0db51e3b
commit 1ed19eb76e
24 changed files with 7448 additions and 7448 deletions
+343 -343
View File
@@ -1,343 +1,343 @@
import { describe, expect, it } from 'vitest'
import { tag } from '@/lib/fristen/datum'
import {
absendetagZu,
kuendigungsampel,
kuendigungsplan,
KUENDIGUNG_VORWARNUNG_TAGE,
laufzeitAusVertrag,
POSTLAUF_PUFFER_TAGE,
} from '@/lib/vertraege/kuendigung'
import { kuendigungsassistent, genehmigungsfrage } from '@/lib/vertraege/kuendigungsassistent'
import {
anfrageStatus,
juengsterWert,
rueckkaufswertAnschreiben,
wertHistorie,
wiedervorlageAm,
} from '@/lib/vertraege/rueckkaufswert'
import { jahresbeitragCent, kannRueckkaufswertHaben } from '@/lib/vertraege/konstanten'
const kopf = {
betreuerName: 'Florian Wilde',
betreuerStrasse: 'Musterweg 1',
betreuerPlz: '95444',
betreuerOrt: 'Bayreuth',
betreuteName: 'Erika Wilde',
betreuteGeburtsdatum: tag(1948, 5, 20),
betreuungsgericht: 'Amtsgericht Bayreuth',
aktenzeichenGericht: 'XVII 123/25',
bestellungAm: tag(2025, 11, 3),
}
describe('Kündigungstermin', () => {
it('rechnet den nächstmöglichen Termin über die Jahresgrenze', () => {
// Jahresvertrag seit dem 15.03.2020, drei Monate Kündigungsfrist.
// Für den Termin 15.03.2026 müsste der Zugang am 15.12.2025 vorliegen -
// der Absendetag ist Anfang Februar 2026 längst vorbei.
const plan = kuendigungsplan({
beginnAm: tag(2020, 3, 15),
laufzeitJahre: 1,
kuendigungsfristMonate: 3,
heute: tag(2026, 2, 1),
})
expect(plan.berechenbar).toBe(true)
expect(plan.naechsterTermin).toEqual(tag(2027, 3, 15))
expect(plan.zugangSpaetestensAm).toEqual(tag(2026, 12, 15))
expect(plan.spaetesterAbsendetag).toEqual(tag(2026, 12, 12))
expect(plan.verpasst).toBe(false)
})
it('rechnet über die Monatsgrenze kalendarisch, nicht in Tagen', () => {
// 31.05. minus drei Monate ist der 28.02. (2026 ist kein Schaltjahr),
// nicht der 02.03. oder 03.03.
const plan = kuendigungsplan({
beginnAm: tag(2019, 5, 31),
laufzeitJahre: 1,
kuendigungsfristMonate: 3,
heute: tag(2026, 1, 5),
})
expect(plan.naechsterTermin).toEqual(tag(2026, 5, 31))
expect(plan.zugangSpaetestensAm).toEqual(tag(2026, 2, 28))
expect(plan.spaetesterAbsendetag).toEqual(tag(2026, 2, 25))
})
it('trifft im Schaltjahr den 29. Februar', () => {
const plan = kuendigungsplan({
beginnAm: tag(2019, 5, 31),
laufzeitJahre: 1,
kuendigungsfristMonate: 3,
heute: tag(2024, 1, 5),
})
expect(plan.zugangSpaetestensAm).toEqual(tag(2024, 2, 29))
})
it('springt bei mehrjähriger Laufzeit um die volle Laufzeit weiter', () => {
const plan = kuendigungsplan({
beginnAm: tag(2018, 1, 1),
laufzeitJahre: 3,
kuendigungsfristMonate: 3,
heute: tag(2026, 2, 1),
})
// Termine: 2021, 2024, 2027 - für 2027 muss bis 30.09.2026 zugehen.
expect(plan.naechsterTermin).toEqual(tag(2027, 1, 1))
expect(plan.zugangSpaetestensAm).toEqual(tag(2026, 10, 1))
})
it('rechnet den Postlauf zwischen Absenden und Zugang ein', () => {
expect(absendetagZu(tag(2026, 6, 30), 3)).toEqual(tag(2026, 3, 27))
expect(POSTLAUF_PUFFER_TAGE).toBe(3)
})
it('warnt, wenn der Absendetag näher als 30 Tage rückt', () => {
const plan = kuendigungsplan({
beginnAm: tag(2020, 6, 30),
laufzeitJahre: 1,
kuendigungsfristMonate: 3,
heute: tag(2026, 3, 20),
})
expect(plan.spaetesterAbsendetag).toEqual(tag(2026, 3, 27))
expect(plan.tageBisAbsendetag).toBe(7)
expect(plan.vorwarnung).toBe(true)
expect(kuendigungsampel(plan)?.variante).toBe('rot')
})
it('warnt genau an der Grenze von 30 Tagen', () => {
const plan = kuendigungsplan({
beginnAm: tag(2020, 6, 30),
laufzeitJahre: 1,
kuendigungsfristMonate: 3,
heute: tag(2026, 2, 25),
})
expect(plan.tageBisAbsendetag).toBe(KUENDIGUNG_VORWARNUNG_TAGE)
expect(plan.vorwarnung).toBe(true)
expect(kuendigungsampel(plan)?.variante).toBe('orange')
})
it('warnt einen Tag vor der Grenze noch nicht', () => {
const plan = kuendigungsplan({
beginnAm: tag(2020, 6, 30),
laufzeitJahre: 1,
kuendigungsfristMonate: 3,
heute: tag(2026, 2, 24),
})
expect(plan.tageBisAbsendetag).toBe(31)
expect(plan.vorwarnung).toBe(false)
})
it('nimmt ohne hinterlegte Laufzeit ein Jahr an und sagt das dazu', () => {
const plan = kuendigungsplan({
beginnAm: tag(2020, 3, 15),
laufzeitJahre: null,
kuendigungsfristMonate: 3,
heute: tag(2026, 2, 1),
})
expect(plan.naechsterTermin).toEqual(tag(2027, 3, 15))
expect(plan.hinweise.some((h) => h.includes('keine Laufzeit'))).toBe(true)
})
it('meldet einen verpassten Termin, wenn sich der Vertrag nicht verlängert', () => {
const plan = kuendigungsplan({
beginnAm: tag(2010, 1, 1),
endeAm: tag(2026, 3, 1),
kuendigungsfristMonate: 3,
verlaengertSichAutomatisch: false,
heute: tag(2026, 2, 1),
})
expect(plan.verpasst).toBe(true)
expect(kuendigungsampel(plan)?.variante).toBe('rot')
})
it('rechnet gar nicht, wenn weder Beginn noch Ende bekannt sind', () => {
const plan = kuendigungsplan({
beginnAm: null,
kuendigungsfristMonate: 3,
heute: tag(2026, 2, 1),
})
expect(plan.berechenbar).toBe(false)
expect(plan.naechsterTermin).toBeNull()
expect(kuendigungsampel(plan)).toBeNull()
})
it('weist auf die fehlende Kündigungsfrist hin, statt still mit null zu rechnen', () => {
const plan = kuendigungsplan({
beginnAm: tag(2020, 3, 15),
kuendigungsfristMonate: null,
heute: tag(2026, 2, 1),
})
expect(plan.hinweise.some((h) => h.includes('keine Kündigungsfrist'))).toBe(true)
})
})
describe('Rückkaufswert-Anforderung', () => {
it('legt die Wiedervorlage vier Wochen nach der Anfrage', () => {
expect(wiedervorlageAm(tag(2026, 3, 2))).toEqual(tag(2026, 3, 30))
})
it('fragt Rückkaufswert und beitragsfreie Versicherungssumme zusammen ab', () => {
const brief = rueckkaufswertAnschreiben({
kopf,
empfaenger: { gesellschaft: 'Musterversicherung AG', anschrift: 'Postfach 1\n80000 München' },
vertragsbezeichnung: 'Sterbegeldversicherung',
vertragsnummer: 'LV-4711',
stichtag: tag(2026, 1, 1),
heute: tag(2026, 3, 2),
})
expect(brief).toContain('LV-4711')
expect(brief).toContain('Rückkaufswert')
expect(brief).toContain('beitragsfreie Versicherungssumme')
expect(brief).toContain('Amtsgericht Bayreuth')
expect(brief).toContain('XVII 123/25')
expect(brief).toContain('01.01.2026')
})
it('meldet die Erinnerung, sobald vier Wochen ohne Antwort vergangen sind', () => {
expect(anfrageStatus(tag(2026, 3, 2), tag(2026, 3, 29)).erinnerungFaellig).toBe(false)
expect(anfrageStatus(tag(2026, 3, 2), tag(2026, 3, 30)).erinnerungFaellig).toBe(true)
expect(anfrageStatus(null, tag(2026, 3, 30)).offen).toBe(false)
})
})
describe('Kündigungs-Assistent', () => {
const eingabe = {
kopf,
empfaenger: { gesellschaft: 'Musterversicherung AG', anschrift: null },
vertragsbezeichnung: 'Kapitallebensversicherung',
vertragsnummer: 'LV-4711',
art: 'LEBENSVERSICHERUNG' as const,
laufzeit: {
beginnAm: tag(2000, 4, 1),
laufzeitJahre: 1,
kuendigungsfristMonate: 3,
},
heute: tag(2026, 2, 1),
}
it('erzeugt ein Schreiben mit Vertragsnummer und Bestellungsnachweis', () => {
const paket = kuendigungsassistent(eingabe)
expect(paket.schreiben).toContain('LV-4711')
expect(paket.schreiben).toContain('kündige ich den oben genannten Vertrag')
expect(paket.schreiben).toContain('rechtlichen Betreuer')
expect(paket.schreiben).toContain('hilfsweise zum nächstmöglichen Zeitpunkt')
})
it('stellt bei einer Lebensversicherung die Genehmigungsfrage, ohne sie zu beantworten', () => {
const paket = kuendigungsassistent(eingabe)
expect(paket.genehmigung.stellen).toBe(true)
expect(paket.genehmigung.rechtsgrundlage).toBe('§ 1850 BGB')
expect(paket.genehmigung.frage).toMatch(/Rechtspfleger/)
expect(paket.genehmigung.hinweis).toMatch(/entscheidet das ausdrücklich nicht/)
})
it('stellt bei einer Hausratversicherung keine Genehmigungsfrage', () => {
expect(genehmigungsfrage('HAUSRAT').stellen).toBe(false)
expect(genehmigungsfrage('LEBENSVERSICHERUNG').stellen).toBe(true)
})
it('verlangt immer einen Versandnachweis', () => {
const paket = kuendigungsassistent(eingabe)
expect(paket.versandnachweis.verlangt).toBe(true)
expect(paket.versandnachweis.moeglichkeiten.join(' ')).toMatch(/Einschreiben/)
expect(paket.versandnachweis.moeglichkeiten.join(' ')).toMatch(/Fax/)
})
it('erinnert vor der Kündigung an die Beitragsfreistellung als Alternative', () => {
const paket = kuendigungsassistent(eingabe)
expect(paket.warnungen.some((w) => w.includes('beitragsfreie Versicherungssumme'))).toBe(true)
})
it('warnt bei einer Bestattungsvorsorge vor der vorschnellen Kündigung', () => {
const paket = kuendigungsassistent({ ...eingabe, art: 'BESTATTUNGSVORSORGE' })
expect(paket.warnungen.some((w) => w.includes('§ 90 Abs. 3 SGB XII'))).toBe(true)
})
it('warnt, wenn die Vertragsnummer fehlt', () => {
const paket = kuendigungsassistent({ ...eingabe, vertragsnummer: null })
expect(paket.warnungen.some((w) => w.includes('Vertragsnummer fehlt'))).toBe(true)
})
})
describe('Beiträge und Vertragsarten', () => {
it('rechnet den Jahresbeitrag aus Beitrag und Rhythmus', () => {
expect(jahresbeitragCent(2_500n, 'MONATLICH')).toBe(30_000n)
expect(jahresbeitragCent(2_500n, 'VIERTELJAEHRLICH')).toBe(10_000n)
expect(jahresbeitragCent(2_500n, 'JAEHRLICH')).toBe(2_500n)
expect(jahresbeitragCent(2_500n, 'EINMALIG')).toBeNull()
expect(jahresbeitragCent(null, 'MONATLICH')).toBeNull()
})
it('kennt die Verträge, bei denen ein Rückkaufswert überhaupt anfällt', () => {
expect(kannRueckkaufswertHaben('LEBENSVERSICHERUNG')).toBe(true)
expect(kannRueckkaufswertHaben('STERBEGELDVERSICHERUNG')).toBe(true)
expect(kannRueckkaufswertHaben('STROM')).toBe(false)
})
})
describe('Vertragsdauer aus Beginn und Ende', () => {
it('leitet die Laufzeit aus einem festen Vertragsende ab', () => {
expect(laufzeitAusVertrag(tag(2018, 1, 1), tag(2021, 1, 1))).toBe(3)
expect(laufzeitAusVertrag(tag(2020, 3, 15), tag(2021, 3, 15))).toBe(1)
})
it('gibt null zurück, wenn ein Datum fehlt oder die Spanne unter einem Jahr liegt', () => {
expect(laufzeitAusVertrag(tag(2020, 1, 1), null)).toBeNull()
expect(laufzeitAusVertrag(null, tag(2021, 1, 1))).toBeNull()
expect(laufzeitAusVertrag(tag(2020, 1, 1), tag(2020, 7, 1))).toBeNull()
})
it('lässt einen dreijährigen Vertrag um drei Jahre weiterspringen', () => {
const plan = kuendigungsplan({
beginnAm: tag(2018, 1, 1),
endeAm: tag(2021, 1, 1),
laufzeitJahre: laufzeitAusVertrag(tag(2018, 1, 1), tag(2021, 1, 1)),
kuendigungsfristMonate: 3,
heute: tag(2026, 2, 1),
})
expect(plan.naechsterTermin).toEqual(tag(2027, 1, 1))
})
})
describe('Rückkaufswert-Historie am Vertrag', () => {
const wert = (jahr: number, cent: number) => ({ stichtag: tag(jahr, 3, 1), wertCent: cent })
it('sortiert über alle verknüpften Posten hinweg, jüngster zuerst', () => {
// Zwei Posten am selben Vertrag: einer von Hand angelegt, einer beim
// ersten Erfassen entstanden. Der Vertrag zeigt beide Reihen als eine.
const historie = wertHistorie([
{ wertstaende: [wert(2024, 4000)] },
{ wertstaende: [wert(2026, 5200), wert(2025, 4600)] },
])
expect(historie.map((w) => w.wertCent)).toEqual([5200, 4600, 4000])
})
it('nennt den zuletzt mitgeteilten Wert', () => {
expect(juengsterWert([{ wertstaende: [wert(2025, 4600), wert(2026, 5200)] }])?.wertCent).toBe(
5200,
)
})
it('gibt ohne jeden Wert null zurück, statt eine Null zu behaupten', () => {
expect(juengsterWert([{ wertstaende: [] }])).toBeNull()
expect(juengsterWert([])).toBeNull()
})
})
import { describe, expect, it } from 'vitest'
import { tag } from '@/lib/fristen/datum'
import {
absendetagZu,
kuendigungsampel,
kuendigungsplan,
KUENDIGUNG_VORWARNUNG_TAGE,
laufzeitAusVertrag,
POSTLAUF_PUFFER_TAGE,
} from '@/lib/vertraege/kuendigung'
import { kuendigungsassistent, genehmigungsfrage } from '@/lib/vertraege/kuendigungsassistent'
import {
anfrageStatus,
juengsterWert,
rueckkaufswertAnschreiben,
wertHistorie,
wiedervorlageAm,
} from '@/lib/vertraege/rueckkaufswert'
import { jahresbeitragCent, kannRueckkaufswertHaben } from '@/lib/vertraege/konstanten'
const kopf = {
betreuerName: 'Florian Wilde',
betreuerStrasse: 'Musterweg 1',
betreuerPlz: '95444',
betreuerOrt: 'Bayreuth',
betreuteName: 'Erika Wilde',
betreuteGeburtsdatum: tag(1948, 5, 20),
betreuungsgericht: 'Amtsgericht Bayreuth',
aktenzeichenGericht: 'XVII 123/25',
bestellungAm: tag(2025, 11, 3),
}
describe('Kündigungstermin', () => {
it('rechnet den nächstmöglichen Termin über die Jahresgrenze', () => {
// Jahresvertrag seit dem 15.03.2020, drei Monate Kündigungsfrist.
// Für den Termin 15.03.2026 müsste der Zugang am 15.12.2025 vorliegen -
// der Absendetag ist Anfang Februar 2026 längst vorbei.
const plan = kuendigungsplan({
beginnAm: tag(2020, 3, 15),
laufzeitJahre: 1,
kuendigungsfristMonate: 3,
heute: tag(2026, 2, 1),
})
expect(plan.berechenbar).toBe(true)
expect(plan.naechsterTermin).toEqual(tag(2027, 3, 15))
expect(plan.zugangSpaetestensAm).toEqual(tag(2026, 12, 15))
expect(plan.spaetesterAbsendetag).toEqual(tag(2026, 12, 12))
expect(plan.verpasst).toBe(false)
})
it('rechnet über die Monatsgrenze kalendarisch, nicht in Tagen', () => {
// 31.05. minus drei Monate ist der 28.02. (2026 ist kein Schaltjahr),
// nicht der 02.03. oder 03.03.
const plan = kuendigungsplan({
beginnAm: tag(2019, 5, 31),
laufzeitJahre: 1,
kuendigungsfristMonate: 3,
heute: tag(2026, 1, 5),
})
expect(plan.naechsterTermin).toEqual(tag(2026, 5, 31))
expect(plan.zugangSpaetestensAm).toEqual(tag(2026, 2, 28))
expect(plan.spaetesterAbsendetag).toEqual(tag(2026, 2, 25))
})
it('trifft im Schaltjahr den 29. Februar', () => {
const plan = kuendigungsplan({
beginnAm: tag(2019, 5, 31),
laufzeitJahre: 1,
kuendigungsfristMonate: 3,
heute: tag(2024, 1, 5),
})
expect(plan.zugangSpaetestensAm).toEqual(tag(2024, 2, 29))
})
it('springt bei mehrjähriger Laufzeit um die volle Laufzeit weiter', () => {
const plan = kuendigungsplan({
beginnAm: tag(2018, 1, 1),
laufzeitJahre: 3,
kuendigungsfristMonate: 3,
heute: tag(2026, 2, 1),
})
// Termine: 2021, 2024, 2027 - für 2027 muss bis 30.09.2026 zugehen.
expect(plan.naechsterTermin).toEqual(tag(2027, 1, 1))
expect(plan.zugangSpaetestensAm).toEqual(tag(2026, 10, 1))
})
it('rechnet den Postlauf zwischen Absenden und Zugang ein', () => {
expect(absendetagZu(tag(2026, 6, 30), 3)).toEqual(tag(2026, 3, 27))
expect(POSTLAUF_PUFFER_TAGE).toBe(3)
})
it('warnt, wenn der Absendetag näher als 30 Tage rückt', () => {
const plan = kuendigungsplan({
beginnAm: tag(2020, 6, 30),
laufzeitJahre: 1,
kuendigungsfristMonate: 3,
heute: tag(2026, 3, 20),
})
expect(plan.spaetesterAbsendetag).toEqual(tag(2026, 3, 27))
expect(plan.tageBisAbsendetag).toBe(7)
expect(plan.vorwarnung).toBe(true)
expect(kuendigungsampel(plan)?.variante).toBe('rot')
})
it('warnt genau an der Grenze von 30 Tagen', () => {
const plan = kuendigungsplan({
beginnAm: tag(2020, 6, 30),
laufzeitJahre: 1,
kuendigungsfristMonate: 3,
heute: tag(2026, 2, 25),
})
expect(plan.tageBisAbsendetag).toBe(KUENDIGUNG_VORWARNUNG_TAGE)
expect(plan.vorwarnung).toBe(true)
expect(kuendigungsampel(plan)?.variante).toBe('orange')
})
it('warnt einen Tag vor der Grenze noch nicht', () => {
const plan = kuendigungsplan({
beginnAm: tag(2020, 6, 30),
laufzeitJahre: 1,
kuendigungsfristMonate: 3,
heute: tag(2026, 2, 24),
})
expect(plan.tageBisAbsendetag).toBe(31)
expect(plan.vorwarnung).toBe(false)
})
it('nimmt ohne hinterlegte Laufzeit ein Jahr an und sagt das dazu', () => {
const plan = kuendigungsplan({
beginnAm: tag(2020, 3, 15),
laufzeitJahre: null,
kuendigungsfristMonate: 3,
heute: tag(2026, 2, 1),
})
expect(plan.naechsterTermin).toEqual(tag(2027, 3, 15))
expect(plan.hinweise.some((h) => h.includes('keine Laufzeit'))).toBe(true)
})
it('meldet einen verpassten Termin, wenn sich der Vertrag nicht verlängert', () => {
const plan = kuendigungsplan({
beginnAm: tag(2010, 1, 1),
endeAm: tag(2026, 3, 1),
kuendigungsfristMonate: 3,
verlaengertSichAutomatisch: false,
heute: tag(2026, 2, 1),
})
expect(plan.verpasst).toBe(true)
expect(kuendigungsampel(plan)?.variante).toBe('rot')
})
it('rechnet gar nicht, wenn weder Beginn noch Ende bekannt sind', () => {
const plan = kuendigungsplan({
beginnAm: null,
kuendigungsfristMonate: 3,
heute: tag(2026, 2, 1),
})
expect(plan.berechenbar).toBe(false)
expect(plan.naechsterTermin).toBeNull()
expect(kuendigungsampel(plan)).toBeNull()
})
it('weist auf die fehlende Kündigungsfrist hin, statt still mit null zu rechnen', () => {
const plan = kuendigungsplan({
beginnAm: tag(2020, 3, 15),
kuendigungsfristMonate: null,
heute: tag(2026, 2, 1),
})
expect(plan.hinweise.some((h) => h.includes('keine Kündigungsfrist'))).toBe(true)
})
})
describe('Rückkaufswert-Anforderung', () => {
it('legt die Wiedervorlage vier Wochen nach der Anfrage', () => {
expect(wiedervorlageAm(tag(2026, 3, 2))).toEqual(tag(2026, 3, 30))
})
it('fragt Rückkaufswert und beitragsfreie Versicherungssumme zusammen ab', () => {
const brief = rueckkaufswertAnschreiben({
kopf,
empfaenger: { gesellschaft: 'Musterversicherung AG', anschrift: 'Postfach 1\n80000 München' },
vertragsbezeichnung: 'Sterbegeldversicherung',
vertragsnummer: 'LV-4711',
stichtag: tag(2026, 1, 1),
heute: tag(2026, 3, 2),
})
expect(brief).toContain('LV-4711')
expect(brief).toContain('Rückkaufswert')
expect(brief).toContain('beitragsfreie Versicherungssumme')
expect(brief).toContain('Amtsgericht Bayreuth')
expect(brief).toContain('XVII 123/25')
expect(brief).toContain('01.01.2026')
})
it('meldet die Erinnerung, sobald vier Wochen ohne Antwort vergangen sind', () => {
expect(anfrageStatus(tag(2026, 3, 2), tag(2026, 3, 29)).erinnerungFaellig).toBe(false)
expect(anfrageStatus(tag(2026, 3, 2), tag(2026, 3, 30)).erinnerungFaellig).toBe(true)
expect(anfrageStatus(null, tag(2026, 3, 30)).offen).toBe(false)
})
})
describe('Kündigungs-Assistent', () => {
const eingabe = {
kopf,
empfaenger: { gesellschaft: 'Musterversicherung AG', anschrift: null },
vertragsbezeichnung: 'Kapitallebensversicherung',
vertragsnummer: 'LV-4711',
art: 'LEBENSVERSICHERUNG' as const,
laufzeit: {
beginnAm: tag(2000, 4, 1),
laufzeitJahre: 1,
kuendigungsfristMonate: 3,
},
heute: tag(2026, 2, 1),
}
it('erzeugt ein Schreiben mit Vertragsnummer und Bestellungsnachweis', () => {
const paket = kuendigungsassistent(eingabe)
expect(paket.schreiben).toContain('LV-4711')
expect(paket.schreiben).toContain('kündige ich den oben genannten Vertrag')
expect(paket.schreiben).toContain('rechtlichen Betreuer')
expect(paket.schreiben).toContain('hilfsweise zum nächstmöglichen Zeitpunkt')
})
it('stellt bei einer Lebensversicherung die Genehmigungsfrage, ohne sie zu beantworten', () => {
const paket = kuendigungsassistent(eingabe)
expect(paket.genehmigung.stellen).toBe(true)
expect(paket.genehmigung.rechtsgrundlage).toBe('§ 1850 BGB')
expect(paket.genehmigung.frage).toMatch(/Rechtspfleger/)
expect(paket.genehmigung.hinweis).toMatch(/entscheidet das ausdrücklich nicht/)
})
it('stellt bei einer Hausratversicherung keine Genehmigungsfrage', () => {
expect(genehmigungsfrage('HAUSRAT').stellen).toBe(false)
expect(genehmigungsfrage('LEBENSVERSICHERUNG').stellen).toBe(true)
})
it('verlangt immer einen Versandnachweis', () => {
const paket = kuendigungsassistent(eingabe)
expect(paket.versandnachweis.verlangt).toBe(true)
expect(paket.versandnachweis.moeglichkeiten.join(' ')).toMatch(/Einschreiben/)
expect(paket.versandnachweis.moeglichkeiten.join(' ')).toMatch(/Fax/)
})
it('erinnert vor der Kündigung an die Beitragsfreistellung als Alternative', () => {
const paket = kuendigungsassistent(eingabe)
expect(paket.warnungen.some((w) => w.includes('beitragsfreie Versicherungssumme'))).toBe(true)
})
it('warnt bei einer Bestattungsvorsorge vor der vorschnellen Kündigung', () => {
const paket = kuendigungsassistent({ ...eingabe, art: 'BESTATTUNGSVORSORGE' })
expect(paket.warnungen.some((w) => w.includes('§ 90 Abs. 3 SGB XII'))).toBe(true)
})
it('warnt, wenn die Vertragsnummer fehlt', () => {
const paket = kuendigungsassistent({ ...eingabe, vertragsnummer: null })
expect(paket.warnungen.some((w) => w.includes('Vertragsnummer fehlt'))).toBe(true)
})
})
describe('Beiträge und Vertragsarten', () => {
it('rechnet den Jahresbeitrag aus Beitrag und Rhythmus', () => {
expect(jahresbeitragCent(2_500n, 'MONATLICH')).toBe(30_000n)
expect(jahresbeitragCent(2_500n, 'VIERTELJAEHRLICH')).toBe(10_000n)
expect(jahresbeitragCent(2_500n, 'JAEHRLICH')).toBe(2_500n)
expect(jahresbeitragCent(2_500n, 'EINMALIG')).toBeNull()
expect(jahresbeitragCent(null, 'MONATLICH')).toBeNull()
})
it('kennt die Verträge, bei denen ein Rückkaufswert überhaupt anfällt', () => {
expect(kannRueckkaufswertHaben('LEBENSVERSICHERUNG')).toBe(true)
expect(kannRueckkaufswertHaben('STERBEGELDVERSICHERUNG')).toBe(true)
expect(kannRueckkaufswertHaben('STROM')).toBe(false)
})
})
describe('Vertragsdauer aus Beginn und Ende', () => {
it('leitet die Laufzeit aus einem festen Vertragsende ab', () => {
expect(laufzeitAusVertrag(tag(2018, 1, 1), tag(2021, 1, 1))).toBe(3)
expect(laufzeitAusVertrag(tag(2020, 3, 15), tag(2021, 3, 15))).toBe(1)
})
it('gibt null zurück, wenn ein Datum fehlt oder die Spanne unter einem Jahr liegt', () => {
expect(laufzeitAusVertrag(tag(2020, 1, 1), null)).toBeNull()
expect(laufzeitAusVertrag(null, tag(2021, 1, 1))).toBeNull()
expect(laufzeitAusVertrag(tag(2020, 1, 1), tag(2020, 7, 1))).toBeNull()
})
it('lässt einen dreijährigen Vertrag um drei Jahre weiterspringen', () => {
const plan = kuendigungsplan({
beginnAm: tag(2018, 1, 1),
endeAm: tag(2021, 1, 1),
laufzeitJahre: laufzeitAusVertrag(tag(2018, 1, 1), tag(2021, 1, 1)),
kuendigungsfristMonate: 3,
heute: tag(2026, 2, 1),
})
expect(plan.naechsterTermin).toEqual(tag(2027, 1, 1))
})
})
describe('Rückkaufswert-Historie am Vertrag', () => {
const wert = (jahr: number, cent: number) => ({ stichtag: tag(jahr, 3, 1), wertCent: cent })
it('sortiert über alle verknüpften Posten hinweg, jüngster zuerst', () => {
// Zwei Posten am selben Vertrag: einer von Hand angelegt, einer beim
// ersten Erfassen entstanden. Der Vertrag zeigt beide Reihen als eine.
const historie = wertHistorie([
{ wertstaende: [wert(2024, 4000)] },
{ wertstaende: [wert(2026, 5200), wert(2025, 4600)] },
])
expect(historie.map((w) => w.wertCent)).toEqual([5200, 4600, 4000])
})
it('nennt den zuletzt mitgeteilten Wert', () => {
expect(juengsterWert([{ wertstaende: [wert(2025, 4600), wert(2026, 5200)] }])?.wertCent).toBe(
5200,
)
})
it('gibt ohne jeden Wert null zurück, statt eine Null zu behaupten', () => {
expect(juengsterWert([{ wertstaende: [] }])).toBeNull()
expect(juengsterWert([])).toBeNull()
})
})