Files
SBrainCO/server/sql/12_v3_target_tables.sql
freedakgmail d04e837d9c V3.0: 门店分级与风险等级页面、数据填充脚本、后端API
- 新增V3.0数据库表结构(12-15)和数据填充脚本(16)
- 新增后端路由: store-grade, enterprise, product, intelligence, alert, scheduler, target
- 新增前端页面: StoreGradePage, EnterprisePage, ProductLifecyclePage, IntelligencePage, AlertManagementPage, DataImportPage, SchedulerManagementPage, TargetManagementPage
- 门店分级: 自动分级算法(达成率40%+毛利率25%+会员15%+风险20%)
- 风险等级: 基于mv_store_risk_rating模型展示风险分布和原因
- 弹窗: 雷达图+详细指标+分级原因+风险原因(primary_issue)
- FilterableTable: filterOptions支持{value,label}对象格式
2026-08-05 20:09:39 +08:00

213 lines
9.5 KiB
SQL
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- ============================================================
-- 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;