Files
alpenwerk-hr/supabase/functions_3.sql
Maximilian Stubhan 108da8d5e6 Phase 4: Org chart (Mitarbeiter/Positionen/Reorganisation) + one more RLS bugfix
- components/orgchart/: 3-way segmented view sharing one server fetch
  (switching tabs doesn't refetch):
  - EmployeeTree: expand/collapse hierarchy from the CEO down, search with
    auto-expand-to-match and highlighting, "Bereiche anzeigen" /
    "Alles einklappen".
  - PositionTree: models the org *structure* (GF -> Bereichsleitung ->
    Abteilung -> Teamleitung -> grouped IC positions by title, expandable
    to the actual holders) independent of who's currently in it, plus
    dashed rows for open requisitions linking to /positions.
  - ReorgWorkbench: batch multiple moves (employees / whole team / whole
    department / whole division as source, always a specific team as
    target), live headcount-impact table, apply via the existing
    apply_reorg RPC, and an undo card wired to undo_reorg.

Bug found via live apply+undo testing: undo_reorg's cleanup DELETE on
employee_history silently matched zero rows, because that table has no
DELETE policy at all (by design, for audit immutability) - RLS filters
DELETE-eligible rows to none rather than erroring. Added
supabase/functions_3.sql: a policy scoped to hr_admin deleting only rows
that carry a reorg_scenario_id, so every other history event type stays
genuinely immutable. Verified live: apply moves an employee and updates
the headcount table correctly; undo reverts team/division/manager AND
now actually removes the Reorganisation history entries it created.

Simplification flagged here (not hidden): the spec's "Ganzes Team /
Ganze Abteilung / Ganzer Bereich" reorg moves the structural org unit
itself to a new division; this implementation resolves all four move
kinds down to individual employee moves against a specific target team,
since the schema's team->department->division chain doesn't support
freely reparenting a team object without also picking a department. The
workbench UI, headcount-impact math, and apply/undo all work correctly
under this model - only the exact "move the team as a unit" semantics
differs from the literal spec wording.
2026-07-13 22:57:49 +02:00

16 lines
917 B
SQL

-- Addendum to supabase/schema.sql + functions.sql — run after those.
--
-- employee_history intentionally has no UPDATE/DELETE policy (§4.9's
-- "unveraenderbar" / append-only requirement). But undo_reorg needs to
-- remove the specific history rows a reorg created — found via live
-- testing: the DELETE inside undo_reorg silently matched 0 rows under RLS
-- (no error, since RLS just filters DELETE-eligible rows to none), leaving
-- Reorganisation entries behind after an otherwise-successful undo.
--
-- Scope the exception as narrowly as possible: hr_admin may delete a
-- history row only if it carries a reorg_scenario_id, i.e. only rows
-- apply_reorg created. Eintritt/Austritt/Beförderung/etc. rows (always
-- reorg_scenario_id IS NULL) remain fully immutable.
create policy "history_delete_admin_reorg_undo" on employee_history for delete
using (is_hr_admin() and reorg_scenario_id is not null);