94 lines
4.2 KiB
PL/PgSQL
94 lines
4.2 KiB
PL/PgSQL
-- =====================================================
|
|
-- Module Notification Rules & Queue
|
|
-- Shared notification infrastructure for courses, events, bookings.
|
|
-- =====================================================
|
|
|
|
-- Notification rules: define what triggers notifications
|
|
CREATE TABLE IF NOT EXISTS public.module_notification_rules (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
account_id uuid NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
module text NOT NULL CHECK (module IN ('courses', 'events', 'bookings')),
|
|
trigger_event text NOT NULL CHECK (trigger_event IN (
|
|
'course.participant_enrolled', 'course.participant_waitlisted', 'course.participant_promoted',
|
|
'course.participant_cancelled', 'course.status_changed', 'course.session_reminder',
|
|
'event.registration_confirmed', 'event.registration_waitlisted', 'event.registration_promoted',
|
|
'event.registration_cancelled', 'event.status_changed', 'event.reminder',
|
|
'booking.confirmed', 'booking.check_in_reminder', 'booking.checked_in',
|
|
'booking.checked_out', 'booking.cancelled'
|
|
)),
|
|
channel text NOT NULL DEFAULT 'in_app' CHECK (channel IN ('in_app', 'email', 'both')),
|
|
recipient_type text NOT NULL DEFAULT 'admin' CHECK (recipient_type IN ('admin', 'participant', 'guest', 'instructor', 'specific_user')),
|
|
recipient_config jsonb NOT NULL DEFAULT '{}',
|
|
subject_template text,
|
|
message_template text NOT NULL,
|
|
is_active boolean NOT NULL DEFAULT true,
|
|
created_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS ix_module_notification_rules_lookup
|
|
ON public.module_notification_rules(account_id, module, trigger_event)
|
|
WHERE is_active = true;
|
|
|
|
ALTER TABLE public.module_notification_rules ENABLE ROW LEVEL SECURITY;
|
|
REVOKE ALL ON public.module_notification_rules FROM authenticated, service_role;
|
|
GRANT SELECT, INSERT, UPDATE, DELETE ON public.module_notification_rules TO authenticated;
|
|
GRANT ALL ON public.module_notification_rules TO service_role;
|
|
|
|
CREATE POLICY module_notification_rules_select ON public.module_notification_rules
|
|
FOR SELECT TO authenticated USING (public.has_role_on_account(account_id));
|
|
|
|
CREATE POLICY module_notification_rules_mutate ON public.module_notification_rules
|
|
FOR ALL TO authenticated USING (
|
|
public.has_permission(auth.uid(), account_id, 'settings.manage'::public.app_permissions)
|
|
) WITH CHECK (
|
|
public.has_permission(auth.uid(), account_id, 'settings.manage'::public.app_permissions)
|
|
);
|
|
|
|
-- Pending notifications queue
|
|
CREATE TABLE IF NOT EXISTS public.pending_module_notifications (
|
|
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
account_id uuid NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
module text NOT NULL CHECK (module IN ('courses', 'events', 'bookings')),
|
|
trigger_event text NOT NULL,
|
|
entity_id uuid NOT NULL,
|
|
context jsonb NOT NULL DEFAULT '{}',
|
|
processed_at timestamptz,
|
|
created_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS ix_pending_module_notifications_unprocessed
|
|
ON public.pending_module_notifications(created_at)
|
|
WHERE processed_at IS NULL;
|
|
|
|
ALTER TABLE public.pending_module_notifications ENABLE ROW LEVEL SECURITY;
|
|
REVOKE ALL ON public.pending_module_notifications FROM authenticated, service_role;
|
|
GRANT SELECT ON public.pending_module_notifications TO authenticated;
|
|
GRANT ALL ON public.pending_module_notifications TO service_role;
|
|
|
|
CREATE POLICY pending_module_notifications_select ON public.pending_module_notifications
|
|
FOR SELECT TO authenticated USING (public.has_role_on_account(account_id));
|
|
|
|
-- Enqueue helper
|
|
CREATE OR REPLACE FUNCTION public.enqueue_module_notification(
|
|
p_account_id uuid,
|
|
p_module text,
|
|
p_trigger_event text,
|
|
p_entity_id uuid,
|
|
p_context jsonb DEFAULT '{}'
|
|
)
|
|
RETURNS void
|
|
LANGUAGE plpgsql
|
|
SECURITY DEFINER
|
|
SET search_path = ''
|
|
AS $$
|
|
BEGIN
|
|
INSERT INTO public.pending_module_notifications
|
|
(account_id, module, trigger_event, entity_id, context)
|
|
VALUES
|
|
(p_account_id, p_module, p_trigger_event, p_entity_id, p_context);
|
|
END;
|
|
$$;
|
|
|
|
GRANT EXECUTE ON FUNCTION public.enqueue_module_notification(uuid, text, text, uuid, jsonb) TO authenticated;
|
|
GRANT EXECUTE ON FUNCTION public.enqueue_module_notification(uuid, text, text, uuid, jsonb) TO service_role;
|