Merge #40: Ausschlussfristen nur bei Fälligkeit hervorheben
This commit was merged in pull request #47.
This commit is contained in:
@@ -24,6 +24,42 @@ export const WARTEZEIT_DRINGEND_TAGE = 21
|
||||
/** Wie viele Ausschlussfristen zeigt die Warnung hoechstens? */
|
||||
const AUSSCHLUSSFRISTEN_MAX = 3
|
||||
|
||||
/**
|
||||
* Wie weit im Voraus eine Ausschlussfrist die Warnung ausloest.
|
||||
*
|
||||
* Frueher gab es diese Grenze nicht: Der Warnblock fragte nur, OB etwas
|
||||
* eine Ausschlussfrist ist, nie WANN sie faellig wird. Auf dem Dashboard
|
||||
* standen deshalb dauerhaft drei rote Kaesten mit Warndreieck - fuer
|
||||
* Aufwandspauschalen, die 2027, 2028 und 2029 ablaufen. Die Pflichtfristen
|
||||
* werden bewusst drei Jahre im Voraus angelegt (jahreVoraus in
|
||||
* pflichtfristen.ts), und alle landeten ungefiltert in der Warnung.
|
||||
*
|
||||
* Das ist nicht nur laestig, sondern gefaehrlich: Eine Warnung, die
|
||||
* monatelang dasteht und nichts von einem will, stumpft ab. Man uebersieht
|
||||
* die vierte, die etwas will - und bei § 1878 BGB ist das die
|
||||
* Jahrespauschale, die ersatzlos erlischt.
|
||||
*
|
||||
* 90 Tage, weil die kuerzeste hier vorkommende Ausschlussfrist sechs
|
||||
* Monate Zeit laesst. Drei Monate Vorlauf sind reichlich, und solange
|
||||
* nichts ansteht, bleibt der Kasten leer - dann bedeutet er etwas.
|
||||
*
|
||||
* Verschwinden tut nichts: Was ausserhalb des Horizonts liegt, steht
|
||||
* weiterhin in der Fristenliste.
|
||||
*/
|
||||
const AUSSCHLUSSFRIST_HORIZONT_TAGE = 90
|
||||
|
||||
/**
|
||||
* Gehoert diese Frist in den hervorgehobenen Warnblock?
|
||||
*
|
||||
* Abgelaufenes immer - eine versaeumte Ausschlussfrist bleibt eine
|
||||
* schlechte Nachricht, auch wenn sie lange zurueckliegt. Sonst nur, was
|
||||
* innerhalb des Horizonts faellig wird.
|
||||
*/
|
||||
function warntJetzt(eintrag: { ausschlussfrist: boolean; tage: number }): boolean {
|
||||
if (!eintrag.ausschlussfrist) return false
|
||||
return eintrag.tage < 0 || eintrag.tage <= AUSSCHLUSSFRIST_HORIZONT_TAGE
|
||||
}
|
||||
|
||||
/**
|
||||
* Datumsfelder ohne Uhrzeit (@db.Date) kommen als UTC-Mitternacht aus der
|
||||
* Datenbank. Wer sie unbesehen mit einem lokalen "heute" vergleicht,
|
||||
@@ -126,7 +162,7 @@ export function fristenEinordnen(fristen: FristRoh[], heute: Date): FristenAmpel
|
||||
dieseWoche: eintraege.filter((e) => e.stufe === 'orange'),
|
||||
diesenMonat: eintraege.filter((e) => e.stufe === 'gelb'),
|
||||
weitereOffen: eintraege.filter((e) => e.stufe === 'gruen').length,
|
||||
ausschlussfristen: eintraege.filter((e) => e.ausschlussfrist).slice(0, AUSSCHLUSSFRISTEN_MAX),
|
||||
ausschlussfristen: eintraege.filter(warntJetzt).slice(0, AUSSCHLUSSFRISTEN_MAX),
|
||||
gesamtOffen: eintraege.length,
|
||||
}
|
||||
}
|
||||
|
||||
+77
-1
@@ -92,9 +92,10 @@ describe('Fristen-Ampel', () => {
|
||||
[
|
||||
frist({ id: 'normal', datum: dbTag('2026-08-20') }),
|
||||
frist({
|
||||
// Weit genug weg fuer "gruen", nah genug fuer die Warnung.
|
||||
id: 'pauschale',
|
||||
titel: 'Aufwandspauschale 2026',
|
||||
datum: dbTag('2026-12-31'),
|
||||
datum: dbTag('2026-10-15'),
|
||||
ausschlussfrist: true,
|
||||
rechtsgrundlage: '§ 1878 BGB',
|
||||
}),
|
||||
@@ -103,6 +104,81 @@ describe('Fristen-Ampel', () => {
|
||||
)
|
||||
|
||||
expect(daten.ausschlussfristen.map((e) => e.id)).toEqual(['pauschale'])
|
||||
// Nicht in einem der Faelligkeitstoepfe - der Warnblock steht daneben.
|
||||
expect(daten.weitereOffen).toBe(1)
|
||||
})
|
||||
|
||||
describe('Ausschlussfristen: nur warnen, wenn es etwas zu tun gibt', () => {
|
||||
/**
|
||||
* Der Anlass: Auf dem Dashboard standen dauerhaft drei rote Kaesten mit
|
||||
* Warndreieck - Aufwandspauschalen mit Verfall 2027, 2028 und 2029. Die
|
||||
* Pflichtfristen werden bewusst drei Jahre im Voraus angelegt, und der
|
||||
* Warnblock fragte nur, OB etwas eine Ausschlussfrist ist, nie WANN sie
|
||||
* faellig wird.
|
||||
*
|
||||
* Eine Warnung, die monatelang dasteht und nichts von einem will,
|
||||
* stumpft ab. Genau davor schuetzen diese Tests.
|
||||
*/
|
||||
function pauschale(id: string, datum: string) {
|
||||
return frist({
|
||||
id,
|
||||
titel: `Aufwandspauschale ${id}`,
|
||||
datum: dbTag(datum),
|
||||
ausschlussfrist: true,
|
||||
rechtsgrundlage: '§ 1878 BGB',
|
||||
})
|
||||
}
|
||||
|
||||
it('lässt Fristen weit in der Zukunft aus der Warnung heraus', () => {
|
||||
const daten = fristenEinordnen(
|
||||
[
|
||||
pauschale('2027', '2027-05-06'),
|
||||
pauschale('2028', '2028-05-06'),
|
||||
pauschale('2029', '2029-05-06'),
|
||||
],
|
||||
HEUTE,
|
||||
)
|
||||
|
||||
expect(daten.ausschlussfristen).toEqual([])
|
||||
// Verschwunden sind sie deshalb nicht - sie stehen in der Liste.
|
||||
expect(daten.weitereOffen).toBe(3)
|
||||
expect(daten.gesamtOffen).toBe(3)
|
||||
})
|
||||
|
||||
it('warnt, sobald eine in den Horizont rückt', () => {
|
||||
// 90 Tage nach dem 19.08.2026 ist der 17.11.2026.
|
||||
const daten = fristenEinordnen([pauschale('bald', '2026-11-17')], HEUTE)
|
||||
|
||||
expect(daten.ausschlussfristen.map((e) => e.id)).toEqual(['bald'])
|
||||
})
|
||||
|
||||
it('warnt einen Tag davor noch nicht', () => {
|
||||
const daten = fristenEinordnen([pauschale('knapp-drueber', '2026-11-18')], HEUTE)
|
||||
|
||||
expect(daten.ausschlussfristen).toEqual([])
|
||||
})
|
||||
|
||||
it('warnt bei einer versäumten Frist immer, egal wie lange sie zurückliegt', () => {
|
||||
// Eine verfallene Aufwandspauschale bleibt eine schlechte Nachricht.
|
||||
// Sie stillschweigend aus der Warnung zu nehmen, waere das Gegenteil
|
||||
// von dem, was hier gewollt ist.
|
||||
const daten = fristenEinordnen([pauschale('verpasst', '2024-05-06')], HEUTE)
|
||||
|
||||
expect(daten.ausschlussfristen.map((e) => e.id)).toEqual(['verpasst'])
|
||||
})
|
||||
|
||||
it('mischt Fälliges und Fernes richtig', () => {
|
||||
const daten = fristenEinordnen(
|
||||
[
|
||||
pauschale('verpasst', '2025-05-06'),
|
||||
pauschale('bald', '2026-10-01'),
|
||||
pauschale('fern', '2029-05-06'),
|
||||
],
|
||||
HEUTE,
|
||||
)
|
||||
|
||||
expect(daten.ausschlussfristen.map((e) => e.id)).toEqual(['verpasst', 'bald'])
|
||||
})
|
||||
})
|
||||
|
||||
it('warnt bei einer Ausschlussfrist ausdrücklich vor dem ersatzlosen Verfall', () => {
|
||||
|
||||
Reference in New Issue
Block a user