-- ============================================================ -- 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;