From 73656461d1b1e01ef1b91ece9f9255e165ce959a Mon Sep 17 00:00:00 2001 From: Maximilian Stubhan Date: Mon, 3 Aug 2026 13:48:01 +0200 Subject: [PATCH] Catch a seed event dated before the entry it belongs to MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- supabase/seed.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/supabase/seed.ts b/supabase/seed.ts index 8588172..10d858a 100644 --- a/supabase/seed.ts +++ b/supabase/seed.ts @@ -835,6 +835,17 @@ function pruefeInvarianten() { for (const h of history) { 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`); + // 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}`); + } } }