Initial daily news digest web
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
-- Run this migration after the original schema.sql has already been created.
|
||||
-- PostgreSQL 12+; safe to run once on the existing database.
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS app_users (
|
||||
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||
email VARCHAR(320) NOT NULL,
|
||||
display_name VARCHAR(120),
|
||||
password_hash TEXT,
|
||||
role VARCHAR(20) NOT NULL DEFAULT 'user'
|
||||
CHECK (role IN ('user', 'admin')),
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
email_verified_at TIMESTAMPTZ,
|
||||
last_login_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT uq_app_users_email UNIQUE (email)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS newsletter_recipients (
|
||||
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||
user_id BIGINT REFERENCES app_users(id) ON DELETE SET NULL,
|
||||
email VARCHAR(320) NOT NULL,
|
||||
display_name VARCHAR(120),
|
||||
enabled BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
send_time TIME NOT NULL DEFAULT TIME '07:30',
|
||||
timezone VARCHAR(64) NOT NULL DEFAULT 'Asia/Shanghai',
|
||||
send_all_modules BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT uq_newsletter_recipients_email UNIQUE (email)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS newsletter_modules (
|
||||
module_key VARCHAR(40) PRIMARY KEY,
|
||||
module_name VARCHAR(120) NOT NULL,
|
||||
description TEXT,
|
||||
enabled BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
INSERT INTO newsletter_modules (module_key, module_name, description, sort_order)
|
||||
VALUES
|
||||
('general', '综合热点', '国内外综合资讯', 10),
|
||||
('ai_agent', 'AI 与 Agent', '大模型、AI 应用和 Agent', 20),
|
||||
('agri_hardware', '农业硬件', '传感器、无人机、机器人和农机', 30),
|
||||
('agri_solutions', '农业方案落地', '智慧农场、温室、灌溉和数字化方案', 40),
|
||||
('agri_services', '农业服务', '农业 SaaS、农技、托管、供应链和运维服务', 50),
|
||||
('policy_market', '政策与市场', '政策、补贴、投资、招标和市场动态', 60),
|
||||
('domestic', '国内资讯', '国内来源或国内市场相关资讯', 70),
|
||||
('international', '国际资讯', '国际来源或国际市场相关资讯', 80)
|
||||
ON CONFLICT (module_key) DO NOTHING;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS recipient_modules (
|
||||
recipient_id BIGINT NOT NULL REFERENCES newsletter_recipients(id) ON DELETE CASCADE,
|
||||
module_key VARCHAR(40) NOT NULL REFERENCES newsletter_modules(module_key) ON DELETE RESTRICT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
PRIMARY KEY (recipient_id, module_key)
|
||||
);
|
||||
|
||||
ALTER TABLE email_deliveries
|
||||
ADD COLUMN IF NOT EXISTS recipient_id BIGINT,
|
||||
ADD COLUMN IF NOT EXISTS modules TEXT[] NOT NULL DEFAULT '{}';
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'fk_email_deliveries_recipient'
|
||||
) THEN
|
||||
ALTER TABLE email_deliveries
|
||||
ADD CONSTRAINT fk_email_deliveries_recipient
|
||||
FOREIGN KEY (recipient_id) REFERENCES newsletter_recipients(id) ON DELETE SET NULL;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_newsletter_recipients_user
|
||||
ON newsletter_recipients (user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_newsletter_recipients_enabled
|
||||
ON newsletter_recipients (enabled, send_time);
|
||||
CREATE INDEX IF NOT EXISTS idx_recipient_modules_module
|
||||
ON recipient_modules (module_key);
|
||||
|
||||
COMMIT;
|
||||
Reference in New Issue
Block a user