-- Make reorg undo respect employee_history's append-only contract -- (spec §6.1: "append-only, keine normale -- Update-/Delete-Funktion"). -- -- The previous undo_reorg deleted the employee_history rows a reorg had -- created (functions.sql:549), which required a narrow RLS carve-out -- (functions_3.sql's "history_delete_admin_reorg_undo" policy) allowing -- hr_admin to delete reorg-tagged history rows. That is the one place in -- the whole schema where history was not actually immutable. Fixed by -- appending a compensating "Reorganisation rückgängig" history entry per -- affected employee instead of deleting anything — the original -- Reorganisation rows stay in the record, exactly like every other history -- event type. The now-unused delete policy is dropped. drop policy if exists "history_delete_admin_reorg_undo" on employee_history; create or replace function undo_reorg(payload jsonb) returns void language plpgsql as $$ declare v_scenario record; v_key text; v_val jsonb; v_name text; v_count int := 0; begin perform require_hr_admin(); select * into v_scenario from reorg_scenarios where id = (payload->>'scenario_id')::uuid and applied = true; if not found or v_scenario.undo_snapshot is null then raise exception 'Reorganisation kann nicht rückgängig gemacht werden (kein Snapshot vorhanden).'; end if; -- Any pending (not-yet-applied) deferred moves belonging to this scenario -- are cancelled rather than left to fire later against a since-reverted -- state. update pending_org_changes set status = 'cancelled' where reorg_scenario_id = v_scenario.id and status = 'pending'; for v_key, v_val in select * from jsonb_each(v_scenario.undo_snapshot) loop update employees set team_id = nullif(v_val->>'team_id','')::uuid, division_id = (v_val->>'division_id')::uuid, manager_id = nullif(v_val->>'manager_id','')::uuid where id = v_key::uuid; select first_name || ' ' || last_name into v_name from employees where id = v_key::uuid; insert into employee_history (employee_id, event_date, event_type, description, reorg_scenario_id) values (v_key::uuid, current_date, 'Reorganisation', 'Reorganisation "' || v_scenario.name || '" rückgängig gemacht — vorheriges Team wiederhergestellt', v_scenario.id); v_count := v_count + 1; end loop; update reorg_scenarios set applied = false where id = v_scenario.id; insert into audit_log (actor_user_id, actor_name, action, target_label, details) values (auth.uid(), current_actor_name(), 'Reorganisation rückgängig', v_scenario.name, v_count || ' Mitarbeiter:innen zurückgesetzt'); end; $$;