114 lines
3.9 KiB
PL/PgSQL
114 lines
3.9 KiB
PL/PgSQL
-- Migration kept minimal because `swap_requests` & participants already exist in many deployments.
|
|
-- This migration ensures the RPCs are present and aligns behavior with the existing schema
|
|
-- (no `approved_by` column on `swap_requests`; approvals are tracked in `swap_request_participants`).
|
|
|
|
-- Ensure chat_thread_id column exists (no-op if already present)
|
|
ALTER TABLE public.swap_requests
|
|
ADD COLUMN IF NOT EXISTS chat_thread_id uuid;
|
|
|
|
-- Idempotent RPC: request_shift_swap(shift_id, recipient_id) -> uuid
|
|
CREATE OR REPLACE FUNCTION public.request_shift_swap(p_shift_id uuid, p_recipient_id uuid)
|
|
RETURNS uuid LANGUAGE plpgsql AS $$
|
|
DECLARE
|
|
v_shift_record RECORD;
|
|
v_recipient RECORD;
|
|
v_new_id uuid;
|
|
BEGIN
|
|
-- shift must exist and be owned by caller
|
|
SELECT * INTO v_shift_record FROM public.duty_schedules WHERE id = p_shift_id;
|
|
IF NOT FOUND THEN
|
|
RAISE EXCEPTION 'shift not found';
|
|
END IF;
|
|
IF v_shift_record.user_id <> auth.uid() THEN
|
|
RAISE EXCEPTION 'permission denied: only shift owner may request swap';
|
|
END IF;
|
|
|
|
-- recipient must exist and be it_staff
|
|
SELECT id, role INTO v_recipient FROM public.profiles WHERE id = p_recipient_id;
|
|
IF NOT FOUND THEN
|
|
RAISE EXCEPTION 'recipient not found';
|
|
END IF;
|
|
IF v_recipient.role <> 'it_staff' THEN
|
|
RAISE EXCEPTION 'recipient must be it_staff';
|
|
END IF;
|
|
|
|
INSERT INTO public.swap_requests(requester_id, recipient_id, shift_id, status, created_at, updated_at)
|
|
VALUES (auth.uid(), p_recipient_id, p_shift_id, 'pending', now(), now())
|
|
RETURNING id INTO v_new_id;
|
|
|
|
RETURN v_new_id;
|
|
END;
|
|
$$;
|
|
|
|
-- Idempotent RPC: respond_shift_swap(p_swap_id, p_action)
|
|
-- Updates status and records approver in swap_request_participants (no approved_by column required)
|
|
CREATE OR REPLACE FUNCTION public.respond_shift_swap(p_swap_id uuid, p_action text)
|
|
RETURNS void LANGUAGE plpgsql AS $$
|
|
DECLARE
|
|
v_swap RECORD;
|
|
BEGIN
|
|
SELECT * INTO v_swap FROM public.swap_requests WHERE id = p_swap_id;
|
|
IF NOT FOUND THEN
|
|
RAISE EXCEPTION 'swap request not found';
|
|
END IF;
|
|
|
|
IF p_action NOT IN ('accepted','rejected','admin_review') THEN
|
|
RAISE EXCEPTION 'invalid action';
|
|
END IF;
|
|
|
|
IF p_action = 'accepted' THEN
|
|
-- only recipient or admin/dispatcher can accept
|
|
IF NOT (
|
|
v_swap.recipient_id = auth.uid()
|
|
OR EXISTS (SELECT 1 FROM public.profiles p WHERE p.id = auth.uid() AND p.role IN ('admin','dispatcher'))
|
|
) THEN
|
|
RAISE EXCEPTION 'permission denied';
|
|
END IF;
|
|
|
|
-- ensure the shift is still owned by the requester before swapping
|
|
UPDATE public.duty_schedules
|
|
SET user_id = v_swap.recipient_id
|
|
WHERE id = v_swap.shift_id AND user_id = v_swap.requester_id;
|
|
IF NOT FOUND THEN
|
|
RAISE EXCEPTION 'shift ownership changed, cannot accept swap';
|
|
END IF;
|
|
|
|
UPDATE public.swap_requests
|
|
SET status = 'accepted', updated_at = now()
|
|
WHERE id = p_swap_id;
|
|
|
|
-- record approver/participant
|
|
INSERT INTO public.swap_request_participants(swap_request_id, user_id, role)
|
|
VALUES (p_swap_id, auth.uid(), 'approver')
|
|
ON CONFLICT DO NOTHING;
|
|
|
|
ELSIF p_action = 'rejected' THEN
|
|
-- only recipient or admin/dispatcher can reject
|
|
IF NOT (
|
|
v_swap.recipient_id = auth.uid()
|
|
OR EXISTS (SELECT 1 FROM public.profiles p WHERE p.id = auth.uid() AND p.role IN ('admin','dispatcher'))
|
|
) THEN
|
|
RAISE EXCEPTION 'permission denied';
|
|
END IF;
|
|
|
|
UPDATE public.swap_requests
|
|
SET status = 'rejected', updated_at = now()
|
|
WHERE id = p_swap_id;
|
|
|
|
INSERT INTO public.swap_request_participants(swap_request_id, user_id, role)
|
|
VALUES (p_swap_id, auth.uid(), 'approver')
|
|
ON CONFLICT DO NOTHING;
|
|
|
|
ELSE -- admin_review
|
|
-- only requester may escalate for admin review
|
|
IF NOT (v_swap.requester_id = auth.uid()) THEN
|
|
RAISE EXCEPTION 'permission denied';
|
|
END IF;
|
|
|
|
UPDATE public.swap_requests
|
|
SET status = 'admin_review', updated_at = now()
|
|
WHERE id = p_swap_id;
|
|
END IF;
|
|
END;
|
|
$$;
|