Record what a change was, not only which field it touched
The audit log said "Adresse, wirksam ab 30.07.2026". That names the field
and hides the answer: what did it say before? For a personnel record that is
the question the log exists to answer.
Both values are in hand at the moment of the change — v_old holds the row as
it was, the payload holds what is being written. change_employee_data
already compared them to decide whether to mention the field at all, then
dropped them. It now keeps them in audit_log.changes as
[{feld, vorher, nachher}], and derives the old one-line text from the same
array so existing views are unaffected.
Clicking a row opens the detail. Fields with no previous value read "leer"
rather than showing an empty cell, because "was not set" is itself a
statement.
Two honest limits, both stated in the panel rather than left to look like a
bug:
- Existing entries cannot be enriched. The values were never captured;
there is nothing to recover.
- Hire, exit and import record no individual fields, so they show none.
The rewritten function also drops auth.uid() for app_current_user_id(),
which works on either system — one of the last few call sites before #23.
Caught while writing this: my scripted edit of types.ts silently did nothing
and my own check reported success, because the pattern matched
pending_org_changes. Redone with the editor. That is the second time a
regex-driven edit has lied about its result in this project.
Not verified end to end: the migration needs privileges I no longer hold
after the database password was rotated. Until it is applied the audit page
will not load, since it selects a column that does not exist yet.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,16 @@ export type GenderType = "m" | "w";
|
||||
export type WorkerType = "Angestellte:r" | "Arbeiter:in";
|
||||
export type CollectiveAgreement = "Handel" | "Süßwaren";
|
||||
export type Weekday = "Mo" | "Di" | "Mi" | "Do" | "Fr" | "Sa" | "So";
|
||||
|
||||
/**
|
||||
* Eine einzelne Feldänderung im Protokoll.
|
||||
*
|
||||
* `vorher` und `nachher` sind bewusst Text: die Datenbank stellt jeden Typ
|
||||
* über ::text dar, damit ein Datum, eine Zahl und eine Liste von Arbeitstagen
|
||||
* in derselben Spalte nebeneinander stehen können. Für die Anzeige reicht
|
||||
* das; gerechnet wird damit nicht.
|
||||
*/
|
||||
export type AuditChange = { feld: string; vorher: string | null; nachher: string | null };
|
||||
export type RelationshipType = "Ehepartner:in" | "Lebenspartner:in" | "Kind" | "Sonstige";
|
||||
export type NoteCategory = "Allgemein" | "Vertraulich" | "Personalgespräch" | "Wiedervorlage" | "Lob / Anerkennung";
|
||||
// Single HR-only role (see docs/decisions/0001-hr-only-access.md). Kept as a
|
||||
@@ -267,6 +277,13 @@ export type Database = {
|
||||
target_label: string;
|
||||
target_employee_id: string | null;
|
||||
details: string | null;
|
||||
/**
|
||||
* Feldweise Änderungen. Null bei Einträgen aus der Zeit vor
|
||||
* 20260803140000_audit_changes_detail.sql — dort wurden nur die
|
||||
* Feldnamen behalten, nicht die Werte, und das lässt sich nicht
|
||||
* nachliefern.
|
||||
*/
|
||||
changes: AuditChange[] | null;
|
||||
};
|
||||
Insert: {
|
||||
id?: string;
|
||||
@@ -277,6 +294,7 @@ export type Database = {
|
||||
target_label: string;
|
||||
target_employee_id?: string | null;
|
||||
details?: string | null;
|
||||
changes?: AuditChange[] | null;
|
||||
};
|
||||
Update: Partial<Database["public"]["Tables"]["audit_log"]["Insert"]>;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user