* feat(booking-templates): per-company opt-in hiding of system templates
Users cannot delete or hide the 26 standard konteringspaket, which clutter
the settings panel and every template picker. Deletion stays off the table
(shared global rows); instead a company can now hide individual system
templates for itself only.
- New booking_template_hidden table (insert=hide, delete=unhide), RLS gated
on active company + write role; nothing hidden by default
- POST/DELETE /api/settings/booking-templates/[id]/hide (system templates
only; company/team templates keep their real delete path)
- List route decorates rows with per-company is_hidden; pickers filter them
out; the settings panel shows hidden ones in a collapsed restore section
so hiding is never silent
- Classified in full-archive-export exclusions (UI preference, not
rakenskapsinformation)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PU1KN431c9gp5zKvFaa1NL
* fix(booking-templates): idempotent re-hide, system-only RLS insert, hidden filter in bulk-book
Skeptic + CodeRabbit findings on #2004, one pass:
- hide upsert now passes ignoreDuplicates (DO NOTHING): the table has no
UPDATE policy on purpose, so the DO UPDATE conflict arm turned a
concurrent re-hide into an RLS 42501/500; pg test pins the conflict shape
- bth_insert policy additionally requires the referenced template to be an
active system template (migration is unmerged, edited in place); negative
pg test for company templates
- BulkBookDialog excludes templates hidden by the company (was reading the
table directly and ignoring hides)
- panel shows the failure toast when the hide/unhide fetch itself rejects
- picker category chips built from the hidden-filtered list
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PU1KN431c9gp5zKvFaa1NL
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>