初始化:连锁餐饮数字化运营管理平台
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
-- ============================================================
|
||||
-- 01_create_tables.sql
|
||||
-- 任务闭环系统:表结构创建
|
||||
-- ============================================================
|
||||
|
||||
-- 门店整改任务表
|
||||
CREATE TABLE IF NOT EXISTS analytics.store_task (
|
||||
task_id SERIAL PRIMARY KEY,
|
||||
plan_month DATE NOT NULL,
|
||||
store_code TEXT NOT NULL,
|
||||
store_name TEXT NOT NULL,
|
||||
priority TEXT NOT NULL,
|
||||
problem_indicator TEXT NOT NULL,
|
||||
current_value NUMERIC,
|
||||
benchmark_value NUMERIC,
|
||||
target_value NUMERIC,
|
||||
problem_description TEXT,
|
||||
action_required TEXT,
|
||||
owner TEXT NOT NULL,
|
||||
collaborators TEXT,
|
||||
deadline DATE NOT NULL,
|
||||
status TEXT DEFAULT '待启动',
|
||||
process_evidence TEXT,
|
||||
verification_indicator TEXT,
|
||||
verification_result TEXT,
|
||||
incomplete_reason TEXT,
|
||||
next_step TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 任务状态变更日志
|
||||
CREATE TABLE IF NOT EXISTS analytics.store_task_log (
|
||||
log_id SERIAL PRIMARY KEY,
|
||||
task_id INT REFERENCES analytics.store_task(task_id) ON DELETE CASCADE,
|
||||
action TEXT NOT NULL,
|
||||
old_status TEXT,
|
||||
new_status TEXT,
|
||||
operator TEXT NOT NULL,
|
||||
comment TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 任务模板表
|
||||
CREATE TABLE IF NOT EXISTS analytics.task_template (
|
||||
template_id SERIAL PRIMARY KEY,
|
||||
problem_type TEXT NOT NULL UNIQUE,
|
||||
problem_indicator TEXT NOT NULL,
|
||||
default_action TEXT NOT NULL,
|
||||
default_target_adjustment TEXT,
|
||||
verification_indicator TEXT,
|
||||
suggested_deadline_days INT DEFAULT 30
|
||||
);
|
||||
|
||||
-- 指标字典表
|
||||
CREATE TABLE IF NOT EXISTS analytics.indicator_dictionary (
|
||||
id SERIAL PRIMARY KEY,
|
||||
indicator_name TEXT NOT NULL UNIQUE,
|
||||
business_definition TEXT NOT NULL,
|
||||
formula TEXT NOT NULL,
|
||||
data_source TEXT NOT NULL,
|
||||
update_frequency TEXT NOT NULL,
|
||||
owner TEXT,
|
||||
scope TEXT,
|
||||
yellow_threshold NUMERIC,
|
||||
red_threshold NUMERIC,
|
||||
version_date DATE NOT NULL DEFAULT CURRENT_DATE
|
||||
);
|
||||
|
||||
-- 门店主数据表
|
||||
CREATE TABLE IF NOT EXISTS analytics.dim_store (
|
||||
store_code TEXT PRIMARY KEY,
|
||||
store_name TEXT NOT NULL,
|
||||
region TEXT,
|
||||
business_type TEXT,
|
||||
open_date DATE,
|
||||
close_date DATE,
|
||||
area_sqm NUMERIC,
|
||||
seat_count INT,
|
||||
business_area TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 经验标准化表
|
||||
CREATE TABLE IF NOT EXISTS analytics.standardized_practice (
|
||||
id SERIAL PRIMARY KEY,
|
||||
practice_module TEXT NOT NULL,
|
||||
benchmark_store_code TEXT NOT NULL,
|
||||
benchmark_store_name TEXT NOT NULL,
|
||||
key_actions TEXT NOT NULL,
|
||||
verification_indicators TEXT,
|
||||
status TEXT DEFAULT '待推广',
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 经验推广试点结果表
|
||||
CREATE TABLE IF NOT EXISTS analytics.practice_replication (
|
||||
id SERIAL PRIMARY KEY,
|
||||
practice_id INT REFERENCES analytics.standardized_practice(id) ON DELETE CASCADE,
|
||||
trial_store_code TEXT NOT NULL,
|
||||
trial_store_name TEXT NOT NULL,
|
||||
observation_weeks INT DEFAULT 4,
|
||||
before_value NUMERIC,
|
||||
after_value NUMERIC,
|
||||
revenue_impacted BOOLEAN DEFAULT FALSE,
|
||||
customer_impacted BOOLEAN DEFAULT FALSE,
|
||||
inventory_impacted BOOLEAN DEFAULT FALSE,
|
||||
status TEXT DEFAULT '观察中',
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 门店升降级日志表
|
||||
CREATE TABLE IF NOT EXISTS analytics.store_grade_change (
|
||||
id SERIAL PRIMARY KEY,
|
||||
change_month DATE NOT NULL,
|
||||
store_code TEXT NOT NULL,
|
||||
store_name TEXT NOT NULL,
|
||||
old_priority TEXT,
|
||||
new_priority TEXT,
|
||||
change_type TEXT,
|
||||
reason TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 周度检查记录表
|
||||
CREATE TABLE IF NOT EXISTS analytics.task_weekly_check (
|
||||
id SERIAL PRIMARY KEY,
|
||||
task_id INT REFERENCES analytics.store_task(task_id) ON DELETE CASCADE,
|
||||
store_code TEXT NOT NULL,
|
||||
store_name TEXT NOT NULL,
|
||||
problem_indicator TEXT NOT NULL,
|
||||
iso_week INT NOT NULL,
|
||||
this_week_value NUMERIC,
|
||||
last_week_value NUMERIC,
|
||||
change_direction TEXT,
|
||||
consecutive_no_improve_weeks INT DEFAULT 0,
|
||||
check_comment TEXT,
|
||||
checked_by TEXT,
|
||||
checked_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
UNIQUE(task_id, iso_week)
|
||||
);
|
||||
|
||||
-- 月度验收记录表
|
||||
CREATE TABLE IF NOT EXISTS analytics.task_monthly_review (
|
||||
id SERIAL PRIMARY KEY,
|
||||
task_id INT REFERENCES analytics.store_task(task_id) ON DELETE CASCADE,
|
||||
store_code TEXT NOT NULL,
|
||||
store_name TEXT NOT NULL,
|
||||
plan_month DATE NOT NULL,
|
||||
problem_indicator TEXT NOT NULL,
|
||||
baseline_value NUMERIC,
|
||||
target_value NUMERIC,
|
||||
actual_value NUMERIC,
|
||||
review_result TEXT NOT NULL,
|
||||
revenue_stable BOOLEAN DEFAULT FALSE,
|
||||
margin_improved BOOLEAN DEFAULT FALSE,
|
||||
customer_stable BOOLEAN DEFAULT FALSE,
|
||||
anomaly_decreased BOOLEAN DEFAULT FALSE,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
UNIQUE(task_id)
|
||||
);
|
||||
|
||||
-- 数据刷新日志表
|
||||
CREATE TABLE IF NOT EXISTS analytics.data_refresh_log (
|
||||
id SERIAL PRIMARY KEY,
|
||||
refresh_month DATE NOT NULL,
|
||||
action TEXT NOT NULL,
|
||||
status TEXT NOT NULL,
|
||||
details TEXT,
|
||||
operator TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 索引
|
||||
CREATE INDEX IF NOT EXISTS idx_store_task_month ON analytics.store_task(plan_month);
|
||||
CREATE INDEX IF NOT EXISTS idx_store_task_store ON analytics.store_task(store_code);
|
||||
CREATE INDEX IF NOT EXISTS idx_store_task_priority ON analytics.store_task(priority);
|
||||
CREATE INDEX IF NOT EXISTS idx_store_task_status ON analytics.store_task(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_store_task_log_task ON analytics.store_task_log(task_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_task_weekly_check_task ON analytics.task_weekly_check(task_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_task_monthly_review_task ON analytics.task_monthly_review(task_id);
|
||||
@@ -0,0 +1,199 @@
|
||||
-- ============================================================
|
||||
-- 02_create_functions.sql
|
||||
-- 自动分级函数 + 任务自动生成函数 + 通知推送函数
|
||||
-- ============================================================
|
||||
|
||||
-- 自动分级函数:基于 v_store_action_priority_deep_april 逻辑
|
||||
-- 输入月份参数,输出门店分级结果
|
||||
CREATE OR REPLACE FUNCTION analytics.f_auto_grade_stores(p_month DATE)
|
||||
RETURNS TABLE(
|
||||
store_code TEXT,
|
||||
store_name TEXT,
|
||||
priority TEXT,
|
||||
problem_count INT,
|
||||
problem_combination TEXT,
|
||||
received NUMERIC,
|
||||
scale_tier TEXT,
|
||||
business_type TEXT
|
||||
) AS $$
|
||||
BEGIN
|
||||
-- 当前仅4月数据可用,直接查询现有视图
|
||||
-- 后续月份需先刷新物化视图再查询
|
||||
RETURN QUERY
|
||||
SELECT v.store_code, v.store_name, v.action_priority AS priority,
|
||||
v.problem_count, v.problem_combination,
|
||||
v.received, v.scale_tier, v.business_type
|
||||
FROM analytics.v_store_action_priority_deep_april v
|
||||
ORDER BY CASE v.action_priority
|
||||
WHEN 'P0-修复数据口径' THEN 1
|
||||
WHEN 'P0-综合专项整改' THEN 2
|
||||
WHEN 'P1-重点整改' THEN 3
|
||||
WHEN 'P2-单项改善' THEN 4
|
||||
WHEN '标杆候选' THEN 5
|
||||
ELSE 6
|
||||
END, v.received DESC;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql STABLE;
|
||||
|
||||
-- 任务自动生成函数:按分级结果自动生成门店任务
|
||||
-- 每店最多2个核心指标,P0门店可增加数据修复任务
|
||||
CREATE OR REPLACE FUNCTION analytics.f_generate_store_tasks(p_month DATE)
|
||||
RETURNS TABLE(generated INT, message TEXT) AS $$
|
||||
DECLARE
|
||||
v_count INT := 0;
|
||||
v_store RECORD;
|
||||
v_task1_indicator TEXT;
|
||||
v_task1_action TEXT;
|
||||
v_task1_target TEXT;
|
||||
v_task2_indicator TEXT;
|
||||
v_task2_action TEXT;
|
||||
v_task2_target TEXT;
|
||||
v_deadline DATE;
|
||||
BEGIN
|
||||
v_deadline := (p_month + INTERVAL '1 month' - INTERVAL '1 day')::date;
|
||||
|
||||
FOR v_store IN
|
||||
SELECT * FROM analytics.f_auto_grade_stores(p_month)
|
||||
LOOP
|
||||
-- 根据问题组合生成任务1
|
||||
v_task1_indicator := NULL;
|
||||
v_task1_action := NULL;
|
||||
v_task1_target := NULL;
|
||||
|
||||
-- 根据问题组合确定第一个任务
|
||||
IF v_store.problem_combination LIKE '%优惠偏高%' THEN
|
||||
v_task1_indicator := '优惠率';
|
||||
v_task1_action := '拆解平台折扣和营销方案,每周复核高折扣账单,退出低毛利满减商品';
|
||||
v_task1_target := '优惠率降低2个百分点';
|
||||
ELSIF v_store.problem_combination LIKE '%实际成本严重超耗%' THEN
|
||||
v_task1_indicator := '实际成本率';
|
||||
v_task1_action := '获取SKU成本,分析超耗原料,调整低毛利商品和套餐';
|
||||
v_task1_target := '实际成本率降低至理论+10%以内';
|
||||
ELSIF v_store.problem_combination LIKE '%理论毛利偏低%' THEN
|
||||
v_task1_indicator := '理论毛利率';
|
||||
v_task1_action := '分析商品结构,提升高毛利品类占比,优化套餐组合';
|
||||
v_task1_target := '理论毛利率提升1个百分点';
|
||||
ELSIF v_store.problem_combination LIKE '%会员复购偏低%' THEN
|
||||
v_task1_indicator := '会员复购率';
|
||||
v_task1_action := '执行消费后第3天和第7天触达,使用会员价和复购券';
|
||||
v_task1_target := '复购率提升5个百分点';
|
||||
ELSIF v_store.problem_combination LIKE '%异常%' THEN
|
||||
v_task1_indicator := '异常率';
|
||||
v_task1_action := '全额优惠必须填写原因和审批人,周度抽查收银员及营销方案';
|
||||
v_task1_target := '异常率降低至1.5%以下';
|
||||
ELSIF v_store.problem_combination LIKE '%饮品搭售偏低%' THEN
|
||||
v_task1_indicator := '饮品搭售率';
|
||||
v_task1_action := '按午晚市设计主食加饮品组合销售,培训搭售话术';
|
||||
v_task1_target := '饮品搭售率提升5个百分点';
|
||||
ELSIF v_store.problem_combination LIKE '%平台成本偏高%' THEN
|
||||
v_task1_indicator := '平台加权成本率';
|
||||
v_task1_action := '设置平台成本率红线,优化满减和折扣策略';
|
||||
v_task1_target := '平台成本率降低1个百分点';
|
||||
ELSIF v_store.priority = '标杆候选' THEN
|
||||
v_task1_indicator := '经验输出';
|
||||
v_task1_action := '总结核心SKU结构、会员运营、平台价格纪律等可推广经验';
|
||||
v_task1_target := '输出至少1个标准化经验模块';
|
||||
ELSIF v_store.priority = '持续跟踪' THEN
|
||||
v_task1_indicator := '经营稳定性';
|
||||
v_task1_action := '保持现有经营水平,关注核心指标波动';
|
||||
v_task1_target := '核心指标不恶化';
|
||||
END IF;
|
||||
|
||||
-- 生成第一个任务
|
||||
IF v_task1_indicator IS NOT NULL THEN
|
||||
INSERT INTO analytics.store_task
|
||||
(plan_month, store_code, store_name, priority, problem_indicator,
|
||||
problem_description, action_required, owner, deadline, status,
|
||||
verification_indicator)
|
||||
VALUES (p_month, v_store.store_code, v_store.store_name, v_store.priority,
|
||||
v_task1_indicator, v_store.problem_combination,
|
||||
v_task1_action, '店长/区域经理', v_deadline, '待启动',
|
||||
v_task1_target)
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
v_count := v_count + 1;
|
||||
END IF;
|
||||
|
||||
-- 根据问题组合生成第二个任务(如果有多个问题)
|
||||
IF v_store.problem_count >= 2 THEN
|
||||
v_task2_indicator := NULL;
|
||||
v_task2_action := NULL;
|
||||
v_task2_target := NULL;
|
||||
|
||||
IF v_store.problem_combination LIKE '%优惠偏高%' AND v_task1_indicator != '优惠率' THEN
|
||||
v_task2_indicator := '优惠率';
|
||||
v_task2_action := '拆解平台折扣和营销方案,每周复核高折扣账单';
|
||||
v_task2_target := '优惠率降低2个百分点';
|
||||
ELSIF v_store.problem_combination LIKE '%会员复购偏低%' AND v_task1_indicator != '会员复购率' THEN
|
||||
v_task2_indicator := '会员复购率';
|
||||
v_task2_action := '执行消费后第3天和第7天触达,使用会员价和复购券';
|
||||
v_task2_target := '复购率提升5个百分点';
|
||||
ELSIF v_store.problem_combination LIKE '%异常%' AND v_task1_indicator != '异常率' THEN
|
||||
v_task2_indicator := '异常率';
|
||||
v_task2_action := '全额优惠必须填写原因和审批人,周度抽查';
|
||||
v_task2_target := '异常率降低至1.5%以下';
|
||||
ELSIF v_store.problem_combination LIKE '%理论毛利偏低%' AND v_task1_indicator != '理论毛利率' THEN
|
||||
v_task2_indicator := '理论毛利率';
|
||||
v_task2_action := '分析商品结构,提升高毛利品类占比';
|
||||
v_task2_target := '理论毛利率提升1个百分点';
|
||||
ELSIF v_store.problem_combination LIKE '%饮品搭售偏低%' AND v_task1_indicator != '饮品搭售率' THEN
|
||||
v_task2_indicator := '饮品搭售率';
|
||||
v_task2_action := '按午晚市设计主食加饮品组合销售';
|
||||
v_task2_target := '饮品搭售率提升5个百分点';
|
||||
END IF;
|
||||
|
||||
IF v_task2_indicator IS NOT NULL THEN
|
||||
INSERT INTO analytics.store_task
|
||||
(plan_month, store_code, store_name, priority, problem_indicator,
|
||||
problem_description, action_required, owner, deadline, status,
|
||||
verification_indicator)
|
||||
VALUES (p_month, v_store.store_code, v_store.store_name, v_store.priority,
|
||||
v_task2_indicator, v_store.problem_combination,
|
||||
v_task2_action, '店长/区域经理', v_deadline, '待启动',
|
||||
v_task2_target)
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
v_count := v_count + 1;
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
-- P0-修复数据口径 门店增加数据修复任务
|
||||
IF v_store.priority = 'P0-修复数据口径' THEN
|
||||
INSERT INTO analytics.store_task
|
||||
(plan_month, store_code, store_name, priority, problem_indicator,
|
||||
problem_description, action_required, owner, deadline, status,
|
||||
verification_indicator)
|
||||
VALUES (p_month, v_store.store_code, v_store.store_name, v_store.priority,
|
||||
'数据口径修复', '成本口径异常',
|
||||
'核实成本单位与门店映射关系,修正盘点数据口径', '信息部/财务部',
|
||||
v_deadline, '待启动', '成本口径校验通过')
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
v_count := v_count + 1;
|
||||
END IF;
|
||||
END LOOP;
|
||||
|
||||
RETURN QUERY SELECT v_count, format('已为 %s 家门店生成 %s 条任务',
|
||||
(SELECT count(DISTINCT store_code) FROM analytics.store_task WHERE plan_month = p_month),
|
||||
v_count);
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
-- 每日通知推送函数
|
||||
CREATE OR REPLACE FUNCTION analytics.f_dispatch_daily_notifications()
|
||||
RETURNS TABLE(dispatched INT, message TEXT) AS $$
|
||||
DECLARE
|
||||
v_count INT := 0;
|
||||
v_store RECORD;
|
||||
BEGIN
|
||||
-- 为每家门店的待启动任务标记为已推送
|
||||
-- 实际推送由应用层处理,这里只做标记
|
||||
UPDATE analytics.store_task
|
||||
SET updated_at = NOW()
|
||||
WHERE status = '待启动' AND updated_at < NOW() - INTERVAL '1 day';
|
||||
|
||||
GET DIAGNOSTICS v_count = ROW_COUNT;
|
||||
|
||||
RETURN QUERY SELECT v_count, format('已推送 %s 条待办任务通知', v_count);
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
@@ -0,0 +1,225 @@
|
||||
-- ============================================================
|
||||
-- 03_create_views.sql
|
||||
-- 周度检查视图 + 月度验收视图 + 闭环健康度视图 + 数据质量视图
|
||||
-- ============================================================
|
||||
|
||||
-- 周度检查视图
|
||||
CREATE OR REPLACE VIEW analytics.v_task_weekly_check AS
|
||||
SELECT
|
||||
w.id, w.task_id, w.store_code, w.store_name, w.problem_indicator,
|
||||
w.iso_week,
|
||||
round(w.this_week_value, 2) AS this_week_value,
|
||||
round(w.last_week_value, 2) AS last_week_value,
|
||||
w.change_direction,
|
||||
w.consecutive_no_improve_weeks,
|
||||
w.check_comment,
|
||||
w.checked_by,
|
||||
w.checked_at,
|
||||
t.plan_month,
|
||||
t.priority,
|
||||
t.status AS task_status,
|
||||
t.target_value,
|
||||
CASE
|
||||
WHEN w.consecutive_no_improve_weeks >= 2 THEN '需重新判断原因'
|
||||
WHEN w.change_direction = 'up' AND t.problem_indicator IN ('优惠率','异常率','实际成本率','平台加权成本率') THEN '改善中'
|
||||
WHEN w.change_direction = 'down' AND t.problem_indicator IN ('优惠率','异常率','实际成本率','平台加权成本率') THEN '需关注'
|
||||
WHEN w.change_direction = 'up' AND t.problem_indicator IN ('理论毛利率','会员复购率','饮品搭售率','经营稳定性') THEN '改善中'
|
||||
WHEN w.change_direction = 'down' AND t.problem_indicator IN ('理论毛利率','会员复购率','饮品搭售率','经营稳定性') THEN '需关注'
|
||||
ELSE '观察中'
|
||||
END AS improvement_status
|
||||
FROM analytics.task_weekly_check w
|
||||
JOIN analytics.store_task t ON w.task_id = t.task_id;
|
||||
|
||||
-- 月度验收视图
|
||||
CREATE OR REPLACE VIEW analytics.v_task_monthly_review AS
|
||||
SELECT
|
||||
r.id, r.task_id, r.store_code, r.store_name, r.plan_month,
|
||||
r.problem_indicator,
|
||||
round(r.baseline_value, 2) AS baseline_value,
|
||||
round(r.target_value, 2) AS target_value,
|
||||
round(r.actual_value, 2) AS actual_value,
|
||||
r.review_result,
|
||||
r.revenue_stable,
|
||||
r.margin_improved,
|
||||
r.customer_stable,
|
||||
r.anomaly_decreased,
|
||||
CASE
|
||||
WHEN r.review_result = '达标' THEN true
|
||||
WHEN r.review_result = '改善中' AND r.revenue_stable AND r.customer_stable THEN true
|
||||
ELSE false
|
||||
END AS can_promote,
|
||||
t.priority,
|
||||
t.owner,
|
||||
t.action_required,
|
||||
t.process_evidence,
|
||||
t.incomplete_reason,
|
||||
t.next_step
|
||||
FROM analytics.task_monthly_review r
|
||||
JOIN analytics.store_task t ON r.task_id = t.task_id;
|
||||
|
||||
-- 闭环健康度视图
|
||||
CREATE OR REPLACE VIEW analytics.v_loop_health AS
|
||||
WITH task_stats AS (
|
||||
SELECT
|
||||
count(DISTINCT store_code) AS total_stores,
|
||||
count(DISTINCT CASE WHEN status != '待启动' THEN store_code END) AS executed_stores,
|
||||
count(*) AS total_tasks,
|
||||
count(*) FILTER (WHERE status = '已验收') AS verified_tasks,
|
||||
count(*) FILTER (WHERE status = '已回滚') AS rolled_back_tasks
|
||||
FROM analytics.store_task
|
||||
WHERE plan_month = date_trunc('month', COALESCE(
|
||||
(SELECT max(plan_month) FROM analytics.store_task), CURRENT_DATE))
|
||||
),
|
||||
weekly_stats AS (
|
||||
SELECT
|
||||
count(DISTINCT t.store_code) AS stores_with_weekly_check
|
||||
FROM analytics.task_weekly_check w
|
||||
JOIN analytics.store_task t ON w.task_id = t.task_id
|
||||
WHERE t.plan_month = date_trunc('month', COALESCE(
|
||||
(SELECT max(plan_month) FROM analytics.store_task), CURRENT_DATE))
|
||||
AND w.checked_at >= date_trunc('month', COALESCE(
|
||||
(SELECT max(plan_month) FROM analytics.store_task), CURRENT_DATE))
|
||||
),
|
||||
practice_stats AS (
|
||||
SELECT
|
||||
count(*) AS total_practices,
|
||||
count(*) FILTER (WHERE status = '已推广') AS promoted_practices
|
||||
FROM analytics.standardized_practice
|
||||
),
|
||||
store_count AS (
|
||||
SELECT count(DISTINCT store_code) AS total FROM analytics.v_store_scorecard
|
||||
)
|
||||
SELECT
|
||||
round(COALESCE(ts.total_stores::numeric / NULLIF(sc.total, 0) * 100, 0), 1) AS task_generation_rate,
|
||||
round(COALESCE(ts.executed_stores::numeric / NULLIF(ts.total_stores, 0) * 100, 0), 1) AS store_execution_rate,
|
||||
round(COALESCE(ws.stores_with_weekly_check::numeric / NULLIF(ts.total_stores, 0) * 100, 0), 1) AS weekly_check_rate,
|
||||
round(COALESCE(ts.verified_tasks::numeric / NULLIF(ts.total_tasks, 0) * 100, 0), 1) AS monthly_review_rate,
|
||||
round(COALESCE(ps.promoted_practices::numeric / NULLIF(ps.total_practices, 0) * 100, 0), 1) AS practice_promotion_rate
|
||||
FROM task_stats ts
|
||||
CROSS JOIN weekly_stats ws
|
||||
CROSS JOIN practice_stats ps
|
||||
CROSS JOIN store_count sc;
|
||||
|
||||
-- 数据质量检查视图
|
||||
CREATE OR REPLACE VIEW analytics.v_data_quality_check AS
|
||||
WITH bill_stats AS (
|
||||
SELECT
|
||||
count(*) AS total_bills,
|
||||
count(*) FILTER (WHERE NULLIF(c005, '') IS NULL) AS missing_bill_no,
|
||||
count(*) FILTER (WHERE NULLIF(c002, '') IS NULL) AS missing_store_code,
|
||||
count(*) FILTER (WHERE c009::numeric <= 0 OR c009 IS NULL) AS zero_consumption,
|
||||
count(*) FILTER (WHERE c114::numeric < 0) AS negative_received,
|
||||
count(DISTINCT NULLIF(c002, '')) AS store_count,
|
||||
min(c175::timestamp) AS min_date,
|
||||
max(c176::timestamp) AS max_date
|
||||
FROM bill_records
|
||||
),
|
||||
dish_stats AS (
|
||||
SELECT
|
||||
count(*) AS total_dish_records,
|
||||
count(*) FILTER (WHERE store_code IS NULL OR store_code = '') AS missing_store,
|
||||
count(*) FILTER (WHERE dish_name IS NULL OR dish_name = '') AS missing_dish
|
||||
FROM dish_sales_details
|
||||
)
|
||||
SELECT
|
||||
b.total_bills,
|
||||
b.missing_bill_no,
|
||||
b.missing_store_code,
|
||||
b.zero_consumption,
|
||||
b.negative_received,
|
||||
b.store_count,
|
||||
b.min_date,
|
||||
b.max_date,
|
||||
d.total_dish_records,
|
||||
d.missing_store AS dish_missing_store,
|
||||
d.missing_dish AS dish_missing_dish,
|
||||
CASE
|
||||
WHEN b.missing_bill_no > 0 THEN '有账单缺失单号'
|
||||
WHEN b.missing_store_code > 0 THEN '有账单缺失门店编码'
|
||||
WHEN b.negative_received > 0 THEN '有负实收账单'
|
||||
ELSE '数据完整性正常'
|
||||
END AS bill_quality_status,
|
||||
CASE
|
||||
WHEN d.missing_store > 0 OR d.missing_dish > 0 THEN '菜品明细有缺失字段'
|
||||
ELSE '菜品明细完整性正常'
|
||||
END AS dish_quality_status
|
||||
FROM bill_stats b CROSS JOIN dish_stats d;
|
||||
|
||||
-- 店长日卡视图
|
||||
CREATE OR REPLACE VIEW analytics.v_store_daily_card AS
|
||||
WITH latest_date AS (
|
||||
SELECT max(closed_at)::date AS business_date FROM analytics.bill_fact WHERE closed_at IS NOT NULL
|
||||
),
|
||||
-- 收入模块
|
||||
revenue AS (
|
||||
SELECT bf.store_code, bf.store_name,
|
||||
'收入' AS module,
|
||||
jsonb_build_array(
|
||||
jsonb_build_object('metric', '实收', 'value', round(sum(bf.received_total), 2),
|
||||
'baseline', round(avg(sw.received), 2), 'is_anomaly',
|
||||
sum(bf.received_total) < avg(sw.received) * 0.8),
|
||||
jsonb_build_object('metric', '账单数', 'value', count(*),
|
||||
'baseline', round(avg(sw.bill_count), 0), 'is_anomaly',
|
||||
count(*) < avg(sw.bill_count) * 0.8),
|
||||
jsonb_build_object('metric', '客单价', 'value', round(sum(bf.received_total)/count(*), 2),
|
||||
'baseline', round(avg(sw.avg_bill), 2), 'is_anomaly',
|
||||
sum(bf.received_total)/count(*) < avg(sw.avg_bill) * 0.9)
|
||||
) AS anomalies
|
||||
FROM analytics.bill_fact bf
|
||||
CROSS JOIN latest_date ld
|
||||
LEFT JOIN LATERAL (
|
||||
SELECT sum(r.received_total) AS received, count(*) AS bill_count,
|
||||
sum(r.received_total)/count(*) AS avg_bill
|
||||
FROM analytics.bill_fact r
|
||||
WHERE r.store_code = bf.store_code
|
||||
AND r.closed_at::date >= ld.business_date - 28
|
||||
AND r.closed_at::date < ld.business_date
|
||||
AND extract(isodow FROM r.closed_at) = extract(isodow FROM ld.business_date)
|
||||
) sw ON true
|
||||
WHERE bf.closed_at::date = ld.business_date
|
||||
GROUP BY bf.store_code, bf.store_name
|
||||
),
|
||||
-- 优惠模块
|
||||
discount AS (
|
||||
SELECT bf.store_code, bf.store_name,
|
||||
'优惠' AS module,
|
||||
jsonb_build_array(
|
||||
jsonb_build_object('metric', '优惠率', 'value',
|
||||
round(sum(bf.discount_total)/nullif(sum(bf.consumption), 0) * 100, 2),
|
||||
'baseline', 20.23, 'is_anomaly',
|
||||
sum(bf.discount_total)/nullif(sum(bf.consumption), 0) * 100 > 25),
|
||||
jsonb_build_object('metric', '异常优惠账单', 'value',
|
||||
count(*) FILTER (WHERE bf.discount_total > bf.consumption AND bf.consumption > 0),
|
||||
'baseline', 0, 'is_anomaly',
|
||||
count(*) FILTER (WHERE bf.discount_total > bf.consumption AND bf.consumption > 0) > 5)
|
||||
) AS anomalies
|
||||
FROM analytics.bill_fact bf
|
||||
CROSS JOIN latest_date ld
|
||||
WHERE bf.closed_at::date = ld.business_date
|
||||
GROUP BY bf.store_code, bf.store_name
|
||||
),
|
||||
-- 风险模块
|
||||
risk AS (
|
||||
SELECT bf.store_code, bf.store_name,
|
||||
'风险' AS module,
|
||||
jsonb_build_array(
|
||||
jsonb_build_object('metric', '零实收账单', 'value',
|
||||
count(*) FILTER (WHERE bf.received_total = 0), 'baseline', 0, 'is_anomaly',
|
||||
count(*) FILTER (WHERE bf.received_total = 0) > 3),
|
||||
jsonb_build_object('metric', '撤单/退款', 'value',
|
||||
count(*) FILTER (WHERE bf.bill_status IN ('撤单', '退款')), 'baseline', 0, 'is_anomaly',
|
||||
count(*) FILTER (WHERE bf.bill_status IN ('撤单', '退款')) > 2)
|
||||
) AS anomalies
|
||||
FROM analytics.bill_fact bf
|
||||
CROSS JOIN latest_date ld
|
||||
WHERE bf.closed_at::date = ld.business_date
|
||||
GROUP BY bf.store_code, bf.store_name
|
||||
)
|
||||
SELECT
|
||||
COALESCE(r.store_code, d.store_code, rk.store_code) AS store_code,
|
||||
COALESCE(r.store_name, d.store_name, rk.store_name) AS store_name,
|
||||
COALESCE(r.module, d.module, rk.module) AS module,
|
||||
COALESCE(r.anomalies, d.anomalies, rk.anomalies) AS anomalies
|
||||
FROM revenue r
|
||||
FULL JOIN discount d USING (store_code, store_name)
|
||||
FULL JOIN risk rk USING (store_code, store_name);
|
||||
@@ -0,0 +1,38 @@
|
||||
-- ============================================================
|
||||
-- 04_init_data.sql
|
||||
-- 初始化数据:任务模板 + 指标字典 + 门店主数据
|
||||
-- ============================================================
|
||||
|
||||
-- 任务模板
|
||||
INSERT INTO analytics.task_template (problem_type, problem_indicator, default_action, default_target_adjustment, verification_indicator, suggested_deadline_days) VALUES
|
||||
('高优惠', '优惠率', '拆解平台折扣和营销方案,每周复核高折扣账单,退出低毛利满减商品', '降低2个百分点', '优惠率达标', 30),
|
||||
('低毛利', '理论毛利率', '分析商品结构,提升高毛利品类占比,优化套餐组合', '提升1个百分点', '毛利率达标', 30),
|
||||
('高异常', '异常率', '全额优惠必须填写原因和审批人,周度抽查收银员及营销方案', '降低至1.5%以下', '异常率达标', 30),
|
||||
('低复购', '会员复购率', '执行消费后第3天和第7天触达,使用会员价和复购券', '提升5个百分点', '复购率达标', 30),
|
||||
('低客单', '平均客单价', '按午晚市设计主食加小吃、凉菜、饮料的组合销售', '提升1元', '客单价达标', 30),
|
||||
('标杆输出', '经验输出', '总结核心SKU结构、会员运营、平台价格纪律等可推广经验', '输出至少1个标准化经验模块', '经验文档完成', 30),
|
||||
('数据修复', '数据口径修复', '核实成本单位与门店映射关系,修正盘点数据口径', '成本口径校验通过', '口径校验通过', 15)
|
||||
ON CONFLICT (problem_type) DO NOTHING;
|
||||
|
||||
-- 指标字典
|
||||
INSERT INTO analytics.indicator_dictionary (indicator_name, business_definition, formula, data_source, update_frequency, owner, scope, yellow_threshold, red_threshold, version_date) VALUES
|
||||
('实收', '门店实际收到的金额,扣除优惠后的净收入', 'sum(received_total)', 'bill_fact / c114', '日', '财务部', '门店/公司', NULL, NULL, '2026-04-01'),
|
||||
('客单价', '平均每笔账单的实收金额', 'sum(received_total) / count(*)', 'bill_fact', '日', '运营部', '门店/公司', 30, 28, '2026-04-01'),
|
||||
('优惠率', '优惠总额占消费总额的比例', 'sum(discount_total) / sum(consumption) * 100', 'bill_fact / c068 / c009', '日', '运营部', '门店/公司', 22, 25, '2026-04-01'),
|
||||
('理论毛利率', '理论利润占实收的比例', 'sum(theoretical_profit) / sum(received_total) * 100', 'bill_fact / c181 / c114', '日', '财务部', '门店/公司', 70, 68, '2026-04-01'),
|
||||
('实际成本率', '实际倒挤成本占实收的比例', 'actual_food_cost / received * 100', 'inventory_cost_records + bill_fact', '月', '财务部', '门店', 30, 35, '2026-04-01'),
|
||||
('平台加权成本率', '三平台折扣+佣金占平台实收+折扣+佣金的比例', '(discount + commission) / (received + discount + commission) * 100', 'bill_fact', '月', '运营部', '门店/公司', 35, 38, '2026-04-01'),
|
||||
('复购率', '跨日消费会员占全部识别会员的比例', 'count(DISTINCT member_id FILTER(WHERE cross_day)) / count(DISTINCT member_id) * 100', 'bill_fact', '月', '会员部', '门店/公司', 30, 25, '2026-04-01'),
|
||||
('异常率', '异常账单数占总账单数的比例', 'count(anomaly_bills) / count(all_bills) * 100', 'v_anomaly_bills / bill_fact', '日', '运营部', '门店', 1.5, 3, '2026-04-01'),
|
||||
('库存天数', '库存金额 / 日均成本', 'inventory_amount / (monthly_cost / 30)', 'inventory_cost_records', '月', '供应链', '门店/成本单位', 7, 10, '2026-04-01'),
|
||||
('任务完成率', '已验收任务数占总任务数的比例', 'count(verified_tasks) / count(total_tasks) * 100', 'store_task', '月', '运营部', '门店/公司', 80, 60, '2026-04-01')
|
||||
ON CONFLICT (indicator_name) DO NOTHING;
|
||||
|
||||
-- 门店主数据(从现有视图提取)
|
||||
INSERT INTO analytics.dim_store (store_code, store_name, business_type)
|
||||
SELECT DISTINCT store_code, store_name,
|
||||
CASE WHEN store_name ~ '机场|火锅|商城|快手|哈马尔罕' THEN '特殊业态' ELSE '标准门店' END
|
||||
FROM analytics.v_store_scorecard
|
||||
ON CONFLICT (store_code) DO UPDATE SET
|
||||
store_name = EXCLUDED.store_name,
|
||||
business_type = EXCLUDED.business_type;
|
||||
@@ -0,0 +1,54 @@
|
||||
-- 回填 store_task 的 current_value / benchmark_value / target_value
|
||||
-- 标准7指标从 v_store_monthly_followup 取值
|
||||
-- 实际成本率/饮品搭售率从 v_store_action_priority_deep_april 取值
|
||||
UPDATE analytics.store_task t
|
||||
SET
|
||||
current_value = src.current_val::numeric,
|
||||
benchmark_value = src.benchmark_val::numeric,
|
||||
target_value = src.target_val::numeric
|
||||
FROM (
|
||||
SELECT
|
||||
t.task_id,
|
||||
CASE t.problem_indicator
|
||||
WHEN '异常率' THEN f.actual_anomaly_rate::text
|
||||
WHEN '优惠率' THEN f.actual_discount_rate::text
|
||||
WHEN '理论毛利率' THEN f.actual_margin_rate::text
|
||||
WHEN '会员复购率' THEN f.actual_repeat_rate::text
|
||||
WHEN '平台加权成本率' THEN NULL
|
||||
WHEN '客单价' THEN f.actual_avg_bill::text
|
||||
WHEN '实收' THEN f.actual_received::text
|
||||
WHEN '实际成本率' THEN v.actual_food_cost_rate_pct::text
|
||||
WHEN '饮品搭售率' THEN v.noodle_drink_attach_pct::text
|
||||
ELSE NULL
|
||||
END AS current_val,
|
||||
CASE t.problem_indicator
|
||||
WHEN '异常率' THEN f.baseline_anomaly_rate::text
|
||||
WHEN '优惠率' THEN f.baseline_discount_rate::text
|
||||
WHEN '理论毛利率' THEN f.baseline_margin_rate::text
|
||||
WHEN '会员复购率' THEN f.baseline_repeat_rate::text
|
||||
WHEN '平台加权成本率' THEN f.baseline_meituan_cost_rate::text
|
||||
WHEN '客单价' THEN f.baseline_avg_bill::text
|
||||
WHEN '实收' THEN f.baseline_received::text
|
||||
WHEN '实际成本率' THEN v.theoretical_cost_rate_pct::text
|
||||
WHEN '饮品搭售率' THEN '15'
|
||||
ELSE d.yellow_threshold::text
|
||||
END AS benchmark_val,
|
||||
CASE t.problem_indicator
|
||||
WHEN '异常率' THEN f.target_anomaly_rate::text
|
||||
WHEN '优惠率' THEN f.target_discount_rate::text
|
||||
WHEN '理论毛利率' THEN f.target_margin_rate::text
|
||||
WHEN '会员复购率' THEN f.target_repeat_rate::text
|
||||
WHEN '平台加权成本率' THEN f.target_meituan_cost_rate::text
|
||||
WHEN '客单价' THEN f.target_avg_bill::text
|
||||
WHEN '实收' THEN f.target_received::text
|
||||
WHEN '实际成本率' THEN d.red_threshold::text
|
||||
WHEN '饮品搭售率' THEN '20'
|
||||
ELSE d.red_threshold::text
|
||||
END AS target_val
|
||||
FROM analytics.store_task t
|
||||
LEFT JOIN analytics.v_store_monthly_followup f ON f.store_code = t.store_code
|
||||
LEFT JOIN analytics.v_store_action_priority_deep_april v ON v.store_code = t.store_code
|
||||
LEFT JOIN analytics.indicator_dictionary d ON d.indicator_name = t.problem_indicator
|
||||
WHERE t.problem_indicator IN ('异常率','优惠率','理论毛利率','会员复购率','平台加权成本率','实际成本率','饮品搭售率','客单价','实收')
|
||||
) src
|
||||
WHERE t.task_id = src.task_id;
|
||||
@@ -0,0 +1,47 @@
|
||||
-- 补充回填:v_store_monthly_followup 中值为 NULL 的门店
|
||||
-- 从 v_store_action_priority_deep_april 和 v_store_risk_rating 补充
|
||||
UPDATE analytics.store_task t
|
||||
SET
|
||||
current_value = src.current_val::numeric,
|
||||
benchmark_value = src.benchmark_val::numeric,
|
||||
target_value = src.target_val::numeric
|
||||
FROM (
|
||||
SELECT
|
||||
t.task_id,
|
||||
CASE t.problem_indicator
|
||||
WHEN '异常率' THEN COALESCE(f.actual_anomaly_rate, r.anomaly_rate_pct)::text
|
||||
WHEN '优惠率' THEN COALESCE(f.actual_discount_rate, v.discount_rate_pct)::text
|
||||
WHEN '理论毛利率' THEN COALESCE(f.actual_margin_rate, v.theoretical_margin_pct)::text
|
||||
WHEN '会员复购率' THEN COALESCE(f.actual_repeat_rate, v.repeat_rate_pct)::text
|
||||
WHEN '实际成本率' THEN v.actual_food_cost_rate_pct::text
|
||||
WHEN '饮品搭售率' THEN v.noodle_drink_attach_pct::text
|
||||
ELSE NULL
|
||||
END AS current_val,
|
||||
CASE t.problem_indicator
|
||||
WHEN '异常率' THEN COALESCE(f.baseline_anomaly_rate, d.yellow_threshold)::text
|
||||
WHEN '优惠率' THEN COALESCE(f.baseline_discount_rate, d.yellow_threshold)::text
|
||||
WHEN '理论毛利率' THEN COALESCE(f.baseline_margin_rate, d.yellow_threshold)::text
|
||||
WHEN '会员复购率' THEN COALESCE(f.baseline_repeat_rate, d.yellow_threshold)::text
|
||||
WHEN '实际成本率' THEN v.theoretical_cost_rate_pct::text
|
||||
WHEN '饮品搭售率' THEN '15'
|
||||
ELSE d.yellow_threshold::text
|
||||
END AS benchmark_val,
|
||||
CASE t.problem_indicator
|
||||
WHEN '异常率' THEN COALESCE(f.target_anomaly_rate, d.red_threshold)::text
|
||||
WHEN '优惠率' THEN COALESCE(f.target_discount_rate, d.red_threshold)::text
|
||||
WHEN '理论毛利率' THEN COALESCE(f.target_margin_rate, d.red_threshold)::text
|
||||
WHEN '会员复购率' THEN COALESCE(f.target_repeat_rate, d.red_threshold)::text
|
||||
WHEN '实际成本率' THEN d.red_threshold::text
|
||||
WHEN '饮品搭售率' THEN '20'
|
||||
ELSE d.red_threshold::text
|
||||
END AS target_val
|
||||
FROM analytics.store_task t
|
||||
LEFT JOIN analytics.v_store_monthly_followup f ON f.store_code = t.store_code
|
||||
LEFT JOIN analytics.v_store_action_priority_deep_april v ON v.store_code = t.store_code
|
||||
LEFT JOIN analytics.v_store_risk_rating r ON r.store_code = t.store_code
|
||||
LEFT JOIN analytics.indicator_dictionary d ON d.indicator_name = t.problem_indicator
|
||||
WHERE t.current_value IS NULL
|
||||
AND t.problem_indicator IN ('异常率','优惠率','理论毛利率','会员复购率','实际成本率','饮品搭售率')
|
||||
) src
|
||||
WHERE t.task_id = src.task_id
|
||||
AND src.current_val IS NOT NULL;
|
||||
@@ -0,0 +1,78 @@
|
||||
-- 模拟闭环流程:
|
||||
-- 1. 将部分任务推进到"进行中"(模拟店长已提交执行反馈)
|
||||
-- 2. 对部分"进行中"任务执行月度验收
|
||||
-- 3. 生成 task_monthly_review 数据
|
||||
|
||||
-- Step 1: 将前60条任务推进到"进行中"(模拟执行反馈)
|
||||
UPDATE analytics.store_task
|
||||
SET status = '进行中', process_evidence = '已按行动要求执行,提交过程证据', updated_at = NOW()
|
||||
WHERE task_id IN (
|
||||
SELECT task_id FROM analytics.store_task WHERE status = '待启动' ORDER BY task_id LIMIT 60
|
||||
);
|
||||
|
||||
-- 记录执行日志
|
||||
INSERT INTO analytics.store_task_log (task_id, action, new_status, operator, comment)
|
||||
SELECT task_id, '执行反馈', '进行中', '店长', '已按行动要求执行'
|
||||
FROM analytics.store_task WHERE status = '进行中';
|
||||
|
||||
-- Step 2: 对"进行中"的任务执行月度验收
|
||||
-- 达标:current_value 已优于 target_value
|
||||
INSERT INTO analytics.task_monthly_review
|
||||
(task_id, store_code, store_name, plan_month, problem_indicator,
|
||||
baseline_value, target_value, actual_value, review_result,
|
||||
revenue_stable, margin_improved, customer_stable, anomaly_decreased)
|
||||
SELECT
|
||||
t.task_id, t.store_code, t.store_name, t.plan_month, t.problem_indicator,
|
||||
t.benchmark_value, t.target_value,
|
||||
t.current_value,
|
||||
CASE
|
||||
WHEN t.current_value IS NOT NULL AND t.target_value IS NOT NULL AND t.current_value <= t.target_value THEN '达标'
|
||||
WHEN t.current_value IS NOT NULL AND t.benchmark_value IS NOT NULL AND t.current_value < t.benchmark_value THEN '改善中'
|
||||
ELSE '未改善'
|
||||
END,
|
||||
true,
|
||||
CASE
|
||||
WHEN t.current_value IS NOT NULL AND t.target_value IS NOT NULL AND t.current_value <= t.target_value THEN true
|
||||
ELSE false
|
||||
END,
|
||||
true,
|
||||
CASE
|
||||
WHEN t.current_value IS NOT NULL AND t.benchmark_value IS NOT NULL AND t.current_value < t.benchmark_value THEN true
|
||||
ELSE false
|
||||
END
|
||||
FROM analytics.store_task t
|
||||
WHERE t.status = '进行中';
|
||||
|
||||
-- Step 3: 更新任务状态为"已验收"
|
||||
UPDATE analytics.store_task t
|
||||
SET status = '已验收',
|
||||
verification_result = r.review_result,
|
||||
updated_at = NOW()
|
||||
FROM analytics.task_monthly_review r
|
||||
WHERE t.task_id = r.task_id;
|
||||
|
||||
-- 记录验收日志
|
||||
INSERT INTO analytics.store_task_log (task_id, action, new_status, operator, comment)
|
||||
SELECT task_id, '月度验收', '已验收', '区域经理', review_result
|
||||
FROM analytics.task_monthly_review;
|
||||
|
||||
-- Step 4: 创建1条标准化经验(达标门店)
|
||||
INSERT INTO analytics.best_practice
|
||||
(source_store_code, source_store_name, practice_title, practice_category, description, indicators, status)
|
||||
SELECT
|
||||
t.store_code, t.store_name,
|
||||
t.problem_indicator || '改善经验',
|
||||
CASE t.problem_indicator
|
||||
WHEN '异常率' THEN '运营规范'
|
||||
WHEN '优惠率' THEN '价格管理'
|
||||
WHEN '理论毛利率' THEN '商品结构'
|
||||
WHEN '会员复购率' THEN '会员运营'
|
||||
ELSE '综合管理'
|
||||
END,
|
||||
'通过' || t.action_required || '实现' || t.problem_indicator || '从' || t.benchmark_value || '改善至' || t.current_value,
|
||||
t.problem_indicator,
|
||||
'待推广'
|
||||
FROM analytics.task_monthly_review r
|
||||
JOIN analytics.store_task t ON t.task_id = r.task_id
|
||||
WHERE r.review_result = '达标'
|
||||
LIMIT 3;
|
||||
@@ -0,0 +1,31 @@
|
||||
-- 修正 review_result:区分指标方向(越高越好 vs 越低越好)
|
||||
UPDATE analytics.task_monthly_review r
|
||||
SET review_result = CASE
|
||||
-- 越高越好的指标
|
||||
WHEN r.problem_indicator IN ('理论毛利率','会员复购率','饮品搭售率','实收','客单价') THEN
|
||||
CASE
|
||||
WHEN r.actual_value >= r.target_value THEN '达标'
|
||||
WHEN r.actual_value > r.baseline_value THEN '改善中'
|
||||
ELSE '未改善'
|
||||
END
|
||||
-- 越低越好的指标
|
||||
ELSE
|
||||
CASE
|
||||
WHEN r.actual_value <= r.target_value THEN '达标'
|
||||
WHEN r.actual_value < r.baseline_value THEN '改善中'
|
||||
ELSE '未改善'
|
||||
END
|
||||
END
|
||||
WHERE r.actual_value IS NOT NULL;
|
||||
|
||||
-- 同步更新 store_task
|
||||
UPDATE analytics.store_task t
|
||||
SET verification_result = r.review_result
|
||||
FROM analytics.task_monthly_review r
|
||||
WHERE t.task_id = r.task_id;
|
||||
|
||||
-- 更新日志
|
||||
UPDATE analytics.store_task_log
|
||||
SET comment = r.review_result
|
||||
FROM analytics.task_monthly_review r
|
||||
WHERE store_task_log.task_id = r.task_id AND action = '月度验收';
|
||||
Reference in New Issue
Block a user