200 lines
8.8 KiB
PL/PgSQL
200 lines
8.8 KiB
PL/PgSQL
-- ============================================================
|
|
-- 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;
|