-- ============================================================ -- 12_v3_target_tables.sql -- V3.0 目标管理系统表族 + 调度任务表 + 预警规则表 -- ============================================================ -- ============================================================ -- 1. 目标管理系统表族 (T-101 ~ T-105) -- ============================================================ -- T-101: 年度战略目标 CREATE TABLE IF NOT EXISTS analytics.v3_annual_target ( id SERIAL PRIMARY KEY, year INT NOT NULL, metric TEXT NOT NULL, -- revenue / profit / store_count / member_count target_value NUMERIC(14,2) NOT NULL, description TEXT, created_by TEXT DEFAULT 'system', created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW(), UNIQUE(year, metric) ); -- T-102: 区域年度目标 CREATE TABLE IF NOT EXISTS analytics.v3_regional_target ( id SERIAL PRIMARY KEY, year INT NOT NULL, region TEXT NOT NULL, revenue_target NUMERIC(14,2) NOT NULL, profit_target NUMERIC(14,2), store_count_target INT, member_count_target INT, weight_pct NUMERIC(5,2) DEFAULT 100, -- 区域占比权重 created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW(), UNIQUE(year, region) ); -- T-103: 门店月度目标(兼容现有 dim_store_target) CREATE TABLE IF NOT EXISTS analytics.v3_store_monthly_target ( id SERIAL PRIMARY KEY, year INT NOT NULL, month DATE NOT NULL, -- YYYY-MM-01 store_code TEXT NOT NULL, store_name TEXT, region TEXT, grade TEXT DEFAULT 'B', -- A/B/C/D 分级 revenue_target NUMERIC(14,2) NOT NULL, bill_count_target INT, avg_bill_value_target NUMERIC(8,2), member_penetration_target NUMERIC(5,2), cost_rate_target NUMERIC(5,2), profit_target NUMERIC(14,2), created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW(), UNIQUE(month, store_code) ); -- T-104: 日级目标 CREATE TABLE IF NOT EXISTS analytics.v3_daily_target ( id SERIAL PRIMARY KEY, target_date DATE NOT NULL, store_code TEXT NOT NULL, store_name TEXT, revenue_target NUMERIC(12,2) NOT NULL, bill_count_target INT, avg_bill_value_target NUMERIC(8,2), package_target NUMERIC(12,2), -- 套餐目标 loss_target NUMERIC(8,2), -- 损耗目标 arrival_target NUMERIC(8,2), -- 到货目标 weight_pct NUMERIC(5,2) DEFAULT 0, -- 当日占月度权重 created_at TIMESTAMPTZ DEFAULT NOW(), UNIQUE(target_date, store_code) ); -- T-105: 个人任务 CREATE TABLE IF NOT EXISTS analytics.v3_personal_task ( id SERIAL PRIMARY KEY, target_date DATE NOT NULL, store_code TEXT NOT NULL, employee_name TEXT NOT NULL, position TEXT, -- 岗位 metric TEXT NOT NULL, -- 指标名 target_value NUMERIC(12,2) NOT NULL, actual_value NUMERIC(12,2), completion_rate NUMERIC(5,2), -- 完成率% status TEXT DEFAULT '待执行', created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); -- ============================================================ -- 2. 调度任务注册表 (T-121) -- ============================================================ CREATE TABLE IF NOT EXISTS analytics.v3_scheduled_task ( id SERIAL PRIMARY KEY, task_name TEXT NOT NULL UNIQUE, description TEXT, cron_expr TEXT NOT NULL, -- cron 表达式 handler TEXT NOT NULL, -- 处理函数标识 is_enabled BOOLEAN DEFAULT true, last_run_at TIMESTAMPTZ, next_run_at TIMESTAMPTZ, last_status TEXT, -- success / failed / running last_error TEXT, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); -- ============================================================ -- 3. 预警规则引擎表族 (T-130 ~ T-131) -- ============================================================ -- T-130: 预警规则 CREATE TABLE IF NOT EXISTS analytics.v3_alert_rule ( id SERIAL PRIMARY KEY, rule_name TEXT NOT NULL, description TEXT, metric TEXT NOT NULL, -- 监控指标 operator TEXT NOT NULL DEFAULT '<', -- < / <= / > / >= / = threshold NUMERIC(14,2) NOT NULL, -- 阈值 severity TEXT DEFAULT 'yellow', -- red / yellow push_targets TEXT, -- 推送对象(逗号分隔角色) escalation_path TEXT, -- 升级路径 is_enabled BOOLEAN DEFAULT true, check_interval TEXT DEFAULT 'hourly', -- hourly / daily / weekly / monthly created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); -- T-131: 预警日志 CREATE TABLE IF NOT EXISTS analytics.v3_alert_log ( id SERIAL PRIMARY KEY, rule_id INT REFERENCES analytics.v3_alert_rule(id) ON DELETE CASCADE, rule_name TEXT, store_code TEXT, store_name TEXT, metric_value NUMERIC(14,2), threshold NUMERIC(14,2), severity TEXT, push_status TEXT DEFAULT 'pending', -- pending / sent / failed handle_status TEXT DEFAULT 'pending', -- pending / handling / resolved / ignored handle_comment TEXT, triggered_at TIMESTAMPTZ DEFAULT NOW(), handled_at TIMESTAMPTZ ); -- ============================================================ -- 4. 门店自动分级表 (T-160) -- ============================================================ CREATE TABLE IF NOT EXISTS analytics.v3_store_grade ( id SERIAL PRIMARY KEY, grade_month DATE NOT NULL, store_code TEXT NOT NULL, store_name TEXT, region TEXT, grade TEXT NOT NULL, -- A / B / C / D revenue_achievement_pct NUMERIC(5,2), inspection_score NUMERIC(5,2), complaint_rate NUMERIC(5,2), overall_score NUMERIC(5,2), reason TEXT, created_at TIMESTAMPTZ DEFAULT NOW(), UNIQUE(grade_month, store_code) ); -- ============================================================ -- 索引 -- ============================================================ CREATE INDEX IF NOT EXISTS idx_v3_annual_target_year ON analytics.v3_annual_target(year); CREATE INDEX IF NOT EXISTS idx_v3_regional_target_year ON analytics.v3_regional_target(year); CREATE INDEX IF NOT EXISTS idx_v3_store_monthly_target_month ON analytics.v3_store_monthly_target(month); CREATE INDEX IF NOT EXISTS idx_v3_store_monthly_target_store ON analytics.v3_store_monthly_target(store_code); CREATE INDEX IF NOT EXISTS idx_v3_daily_target_date ON analytics.v3_daily_target(target_date); CREATE INDEX IF NOT EXISTS idx_v3_daily_target_store ON analytics.v3_daily_target(store_code); CREATE INDEX IF NOT EXISTS idx_v3_personal_task_date ON analytics.v3_personal_task(target_date); CREATE INDEX IF NOT EXISTS idx_v3_personal_task_store ON analytics.v3_personal_task(store_code); CREATE INDEX IF NOT EXISTS idx_v3_scheduled_task_enabled ON analytics.v3_scheduled_task(is_enabled); CREATE INDEX IF NOT EXISTS idx_v3_alert_rule_enabled ON analytics.v3_alert_rule(is_enabled); CREATE INDEX IF NOT EXISTS idx_v3_alert_log_rule ON analytics.v3_alert_log(rule_id); CREATE INDEX IF NOT EXISTS idx_v3_alert_log_triggered ON analytics.v3_alert_log(triggered_at); CREATE INDEX IF NOT EXISTS idx_v3_alert_log_handle_status ON analytics.v3_alert_log(handle_status); CREATE INDEX IF NOT EXISTS idx_v3_store_grade_month ON analytics.v3_store_grade(grade_month); CREATE INDEX IF NOT EXISTS idx_v3_store_grade_store ON analytics.v3_store_grade(store_code); -- ============================================================ -- 初始化默认调度任务 -- ============================================================ INSERT INTO analytics.v3_scheduled_task (task_name, description, cron_expr, handler, is_enabled) VALUES ('daily_report', '每日08:30生成昨日日报', '30 8 * * *', 'dailyReport', true), ('daily_target_card', '每日09:00生成日目标卡', '0 9 * * *', 'dailyTargetCard', true), ('hourly_achievement_check', '每小时比对日目标达成率', '0 * * * *', 'hourlyAchievementCheck', true), ('daily_review_template', '每日22:30生成日复盘模板', '30 22 * * *', 'dailyReviewTemplate', false), ('weekly_data_package', '每周一09:00生成上周数据包', '0 9 * * 1', 'weeklyDataPackage', false), ('monthly_business_report', '每月1日09:00生成月度经营分析报告', '0 9 1 * *', 'monthlyBusinessReport', false), ('monthly_mid_progress', '每月15日14:00生成月中进度报告', '0 14 15 * *', 'monthlyMidProgress', false), ('alert_engine_scan', '每5分钟扫描预警规则', '*/5 * * * *', 'alertEngineScan', true) ON CONFLICT (task_name) DO NOTHING; -- ============================================================ -- 初始化默认预警规则 -- ============================================================ INSERT INTO analytics.v3_alert_rule (rule_name, description, metric, operator, threshold, severity, push_targets, check_interval) VALUES ('营收达成率红灯', '日营收达成率低于80%触发红灯', 'revenue_achievement_pct', '<', 80, 'red', 'store,regional', 'hourly'), ('营收达成率黄灯', '日营收达成率低于90%触发黄灯', 'revenue_achievement_pct', '<', 90, 'yellow', 'store', 'hourly'), ('毛利率异常', '理论毛利率低于40%', 'theoretical_margin_pct', '<', 40, 'yellow', 'store,regional', 'daily'), ('会员渗透率低', '会员账单占比低于20%', 'member_bill_share_pct', '<', 20, 'yellow', 'store', 'daily'), ('客诉率偏高', '客诉率超过5%', 'complaint_rate', '>', 5, 'red', 'store,regional,hq', 'daily'), ('巡检低分', '食安巡检得分低于90', 'inspection_score', '<', 90, 'red', 'store,regional', 'daily'), ('离职率偏高', '月度离职率超过15%', 'turnover_rate', '>', 15, 'red', 'regional,hq', 'monthly') ON CONFLICT DO NOTHING;