Catch a seed event dated before the entry it belongs to

pruefeInvarianten() checked that no history event falls after an exit, but
not that none falls before an entry — and the database enforces exactly
that, in trg_history_not_before_entry.

That gap explains why the live database holds 852 people and no history at
all. employee_history is the last table the seed writes and insertInChunks
throws on the first rejected chunk, so everything before it was already
committed while every one of the ~950 events was lost. The result did not
look like an aborted run. It looked like an application that shows little
history.

The cause was the timezone bug in isoDate() that this seed already
documents: dates built from local parts but formatted through UTC land a day
early in Austria, which put every "Eintritt" one day before the entry date it
was derived from. That is fixed; the database was simply never rebuilt.

A dry run now reports 951 events and no violation, so the current code is
sound. The check stays because it turns this class of failure into a refusal
before the wipe instead of an abort halfway through it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-03 13:48:01 +02:00
parent 99e50fbbf9
commit 73656461d1

View File

@@ -835,6 +835,17 @@ function pruefeInvarianten() {
for (const h of history) { for (const h of history) {
const e = employees.find((x) => x.id === h.employee_id)!; const e = employees.find((x) => x.id === h.employee_id)!;
if (e.exit_date && h.event_date > e.exit_date) throw new Error(`${e.email}: Ereignis ${h.event_type} nach dem Austritt`); if (e.exit_date && h.event_date > e.exit_date) throw new Error(`${e.email}: Ereignis ${h.event_type} nach dem Austritt`);
// Die Gegenrichtung — und die hat gefehlt.
//
// trg_history_not_before_entry weist jede Zeile ab, deren event_date vor
// dem Eintritt liegt. insertInChunks bricht beim ersten Fehler ab, und
// employee_history ist die *letzte* Tabelle im Seed: alles davor war
// bereits geschrieben. Ergebnis war eine Datenbank mit 852 Personen und
// null Historie — und das sah nicht nach einem Abbruch aus, sondern nach
// einer Anwendung, die eben wenig Historie zeigt.
if (h.event_date < e.entry_date) {
throw new Error(`${e.email}: Ereignis ${h.event_type} am ${h.event_date} liegt vor dem Eintritt am ${e.entry_date}`);
}
} }
} }