41 lines
1.2 KiB
SQL
41 lines
1.2 KiB
SQL
CREATE TABLE IF NOT EXISTS scheduled_notifications (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
|
channel TEXT NOT NULL CHECK (channel IN ('email', 'sms', 'push')),
|
|
title TEXT,
|
|
message TEXT NOT NULL,
|
|
html TEXT,
|
|
|
|
scheduled_at TIMESTAMPTZ NOT NULL,
|
|
|
|
status TEXT NOT NULL DEFAULT 'pending'
|
|
CHECK (status IN ('pending', 'processing', 'sent', 'failed', 'cancelled')),
|
|
|
|
target_user_ids BIGINT[],
|
|
target_role TEXT,
|
|
target_raw JSONB,
|
|
|
|
attempt_count INT NOT NULL DEFAULT 0,
|
|
last_error TEXT,
|
|
processing_started_at TIMESTAMPTZ,
|
|
sent_at TIMESTAMPTZ,
|
|
cancelled_at TIMESTAMPTZ,
|
|
|
|
created_by BIGINT NOT NULL REFERENCES users(id),
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
CONSTRAINT scheduled_notifications_target_required CHECK (
|
|
(target_user_ids IS NOT NULL AND array_length(target_user_ids, 1) > 0)
|
|
OR target_role IS NOT NULL
|
|
OR target_raw IS NOT NULL
|
|
)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_scheduled_notifications_due
|
|
ON scheduled_notifications (scheduled_at)
|
|
WHERE status = 'pending';
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_scheduled_notifications_status
|
|
ON scheduled_notifications (status, scheduled_at);
|