import type { AuditChange, HistoryEventType } from "./supabase/types"; // Welche Historieneinträge sich zurücknehmen lassen — und warum die übrigen // nicht. // // Dieselbe Regel steht in der Datenbank (delete_history_entry). Das ist eine // Doppelung, und zwar mit Absicht: die Datenbank ist die verbindliche Stelle, // weil sie die einzige ist, an der niemand vorbeikommt. Hier steht sie // nochmal, damit die Oberfläche einen Knopf nur dort zeigt, wo er auch // funktioniert, und daneben schreiben kann, woran es sonst liegt. Ein Knopf, // der erst nach dem Klick sagt „geht nicht", ist eine Falle. // // Läuft eine Seite der anderen davon, gewinnt die Datenbank: sie weist ab, // und die Oberfläche zeigt ihre Begründung. export type LoeschUrteil = { erlaubt: true } | { erlaubt: false; grund: string }; type Eintrag = { event_type: HistoryEventType; event_date: string; changes: AuditChange[] | null; }; export function darfGeloeschtWerden(eintrag: Eintrag, heute: string): LoeschUrteil { if (eintrag.event_type === "Eintritt") { return { erlaubt: false, grund: "Der Eintritt ist der Anfang der Zeitleiste und bleibt." }; } if (eintrag.event_type !== "Stammdatenänderung" && eintrag.event_type !== "Vertragsänderung") { return { erlaubt: false, grund: "Dieser Vorgang hat Planstellen oder den Status bewegt. Zurücknehmen lässt er sich nur über den passenden " + "Vorgang, nicht durch Löschen der Zeile.", }; } if (eintrag.event_date > heute) { return { erlaubt: false, grund: "Diese Änderung ist noch nicht wirksam und hängt an einem geplanten Vorgang. Sie muss dort abgebrochen werden.", }; } if (!eintrag.changes || eintrag.changes.length === 0) { return { erlaubt: false, grund: "Zu diesem Eintrag sind keine Feldwerte erfasst — es gibt nichts, worauf zurückgesetzt werden könnte.", }; } return { erlaubt: true }; } /** * Was das Löschen bewirken würde: je Feld entweder Zurücksetzen oder nicht, * weil ein späterer Eintrag dasselbe Feld angefasst hat. * * Dient allein der Ankündigung im Bestätigungsdialog — entschieden wird es * in der Datenbank, an denselben Daten, im selben Augenblick. */ export type Vorschau = { feld: string; von: string | null; auf: string | null; bleibt: boolean }; export function loeschVorschau( eintrag: Eintrag & { id: string; created_at: string }, alle: (Eintrag & { id: string; created_at: string })[] ): Vorschau[] { return (eintrag.changes ?? []).map((c) => { const spaeter = alle.some( (h) => h.id !== eintrag.id && (h.changes ?? []).some((a) => a.feld === c.feld) && (h.event_date > eintrag.event_date || (h.event_date === eintrag.event_date && h.created_at > eintrag.created_at)) ); return { feld: c.feld, von: c.nachher, auf: c.vorher, bleibt: spaeter }; }); }