-- Add insurance fields to vendors ALTER TABLE public.vendors ADD COLUMN IF NOT EXISTS insurance_carrier TEXT, ADD COLUMN IF NOT EXISTS insurance_policy_number TEXT, ADD COLUMN IF NOT EXISTS insurance_expiration_date DATE, ADD COLUMN IF NOT EXISTS insurance_document_url TEXT; -- Token table for public submission links CREATE TABLE IF NOT EXISTS public.vendor_insurance_requests ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), vendor_id UUID NOT NULL REFERENCES public.vendors(id) ON DELETE CASCADE, token TEXT NOT NULL UNIQUE DEFAULT encode(gen_random_bytes(24), 'hex'), sent_to_email TEXT, sent_at TIMESTAMPTZ NOT NULL DEFAULT now(), submitted_at TIMESTAMPTZ, expires_at TIMESTAMPTZ NOT NULL DEFAULT (now() + interval '30 days'), created_by UUID, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE INDEX IF NOT EXISTS idx_vendor_insurance_requests_token ON public.vendor_insurance_requests(token); CREATE INDEX IF NOT EXISTS idx_vendor_insurance_requests_vendor ON public.vendor_insurance_requests(vendor_id); ALTER TABLE public.vendor_insurance_requests ENABLE ROW LEVEL SECURITY; CREATE POLICY "Staff manage vendor insurance requests" ON public.vendor_insurance_requests FOR ALL TO authenticated USING (public.has_role(auth.uid(), 'admin'::public.app_role) OR public.has_role(auth.uid(), 'manager'::public.app_role)) WITH CHECK (public.has_role(auth.uid(), 'admin'::public.app_role) OR public.has_role(auth.uid(), 'manager'::public.app_role)); -- Public lookup (anonymous) by token to validate the link CREATE OR REPLACE FUNCTION public.lookup_vendor_insurance_request(p_token TEXT) RETURNS TABLE( request_id UUID, vendor_id UUID, vendor_name TEXT, vendor_email TEXT, expires_at TIMESTAMPTZ, submitted_at TIMESTAMPTZ ) LANGUAGE sql STABLE SECURITY DEFINER SET search_path = public AS $$ SELECT r.id, v.id, v.name, v.email, r.expires_at, r.submitted_at FROM public.vendor_insurance_requests r JOIN public.vendors v ON v.id = r.vendor_id WHERE r.token = p_token LIMIT 1; $$; GRANT EXECUTE ON FUNCTION public.lookup_vendor_insurance_request(TEXT) TO anon, authenticated; -- Public submit: updates vendor + marks request submitted CREATE OR REPLACE FUNCTION public.submit_vendor_insurance( p_token TEXT, p_carrier TEXT, p_policy_number TEXT, p_expiration_date DATE, p_document_url TEXT DEFAULT NULL ) RETURNS BOOLEAN LANGUAGE plpgsql SECURITY DEFINER SET search_path = public AS $$ DECLARE v_request RECORD; BEGIN SELECT * INTO v_request FROM public.vendor_insurance_requests WHERE token = p_token AND expires_at > now() AND submitted_at IS NULL LIMIT 1; IF v_request IS NULL THEN RETURN FALSE; END IF; UPDATE public.vendors SET insurance_carrier = p_carrier, insurance_policy_number = p_policy_number, insurance_expiration_date = p_expiration_date, insurance_document_url = COALESCE(p_document_url, insurance_document_url), updated_at = now() WHERE id = v_request.vendor_id; UPDATE public.vendor_insurance_requests SET submitted_at = now() WHERE id = v_request.id; RETURN TRUE; END; $$; GRANT EXECUTE ON FUNCTION public.submit_vendor_insurance(TEXT, TEXT, TEXT, DATE, TEXT) TO anon, authenticated;