- _cron_generate: per-rule savepoint isolation (one bad rule can't abort the
whole daily batch)
- fclk_attach_recurrence: clear an existing recurrence first (no orphaned rule
generating forever)
- fclk_apply_planner_cell: collapse split rows (search was limit=1 after the
UNIQUE drop, orphaning extras)
- fclk_release_shift: reject non-posted/open shifts (raw-POST guard)
- delete_open_shift: report success=false when nothing was deleted + JS surfaces it
- _generate: log before removing an empty recurrence
Tests added for collapse, re-attach, draft-release.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Model: fclk_create_open_shifts/claim_open_shift/release_shift (days-before
cutoff + role eligibility)/bulk_apply. Planner: Open Shift… panel, open-shifts
strip with delete, Apply-to-dept; load includes open shifts. Portal: claim
open shifts + release own upcoming shifts with feedback banners. Tests for
claim/role-gate/release/bulk.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
is_open + crosses_midnight fields; employee_id optional (open shifts);
company_id computed w/ env.company fallback; drop hard one-per-day UNIQUE
(allow split + open). Overnight math in planned_hours/_check_schedule_times/
scheduled_times. _get_fclk_day_plan resolves multiple posted rows into ONE
work-window so penalties/overtime/absence stay correct. Migration drops the
old constraint defensively. Tests for overnight, window, open shifts.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>