-- Migration: Pass slip requested_start column + expired pass slip notifications -- -- 1. Add optional requested_start column to pass_slips -- 2. Create enqueue_pass_slip_expired_notifications() for recurring reminders -- every 15 minutes after a pass slip exceeds its 1-hour limit -- 3. Update enqueue_all_notifications() master dispatcher -- ============================================================================ -- 1. SCHEMA: Add requested_start column -- ============================================================================ ALTER TABLE public.pass_slips ADD COLUMN IF NOT EXISTS requested_start timestamptz; -- ============================================================================ -- 2. ENQUEUE FUNCTION: Expired pass slip reminders (every 15 min after 1 hour) -- ============================================================================ -- Follows the end_hourly pattern: uses epoch for unique rows, checks latest -- scheduled notification to enforce a minimum gap between reminders. -- Caps at 24 hours to avoid processing ancient slips. CREATE OR REPLACE FUNCTION public.enqueue_pass_slip_expired_notifications() RETURNS void LANGUAGE plpgsql AS $$ DECLARE rec RECORD; v_intervals_since_expiry int; v_latest_expired timestamptz; BEGIN FOR rec IN SELECT ps.id AS pass_slip_id, ps.user_id, ps.slip_start FROM public.pass_slips ps WHERE ps.status = 'approved' AND ps.slip_end IS NULL AND ps.slip_start IS NOT NULL -- Expired: past the 1-hour mark AND ps.slip_start + interval '1 hour' <= now() -- Cap at 24 hours to avoid processing ancient slips AND ps.slip_start + interval '24 hours' > now() LOOP -- Calculate how many 15-min intervals since expiry (for unique epoch) v_intervals_since_expiry := GREATEST(1, EXTRACT(EPOCH FROM (now() - (rec.slip_start + interval '1 hour')))::int / 900 ); -- Check latest expired notification for this pass slip SELECT MAX(scheduled_for) INTO v_latest_expired FROM public.scheduled_notifications WHERE pass_slip_id = rec.pass_slip_id AND user_id = rec.user_id AND notify_type = 'pass_slip_expired_15'; -- Only enqueue if no prior expired reminder, or last one was >14 min ago IF v_latest_expired IS NULL OR v_latest_expired < now() - interval '14 minutes' THEN INSERT INTO public.scheduled_notifications (pass_slip_id, user_id, notify_type, scheduled_for, epoch) VALUES (rec.pass_slip_id, rec.user_id, 'pass_slip_expired_15', now(), v_intervals_since_expiry) ON CONFLICT DO NOTHING; END IF; END LOOP; END; $$; -- ============================================================================ -- 3. MASTER DISPATCHER: Add new function -- ============================================================================ CREATE OR REPLACE FUNCTION public.enqueue_all_notifications() RETURNS void LANGUAGE plpgsql AS $$ BEGIN PERFORM public.enqueue_due_shift_notifications(); PERFORM public.enqueue_overtime_idle_notifications(); PERFORM public.enqueue_overtime_checkout_notifications(); PERFORM public.enqueue_isr_event_notifications(); PERFORM public.enqueue_isr_evidence_notifications(); PERFORM public.enqueue_paused_task_notifications(); PERFORM public.enqueue_backlog_notifications(); PERFORM public.enqueue_pass_slip_expiry_notifications(); PERFORM public.enqueue_pass_slip_expired_notifications(); END; $$;