diff --git a/docs/智脑实施方法论/01-总体框架与八步工作法.md b/docs/智脑实施方法论/01-总体框架与八步工作法.md new file mode 100644 index 0000000..e96797d --- /dev/null +++ b/docs/智脑实施方法论/01-总体框架与八步工作法.md @@ -0,0 +1,311 @@ +# 01 · 总体框架与八步工作法 + +## 1. 核心理念 + +玄谋智脑不是一套技术系统,而是一套**以经营战略为起点、以数据闭环为终点的企业管理方法论**。 + +### 1.1 借鉴FDE精神,适配中国国情 + +本框架借鉴 **FDE(Forward Deployed Engineer,前线部署工程)** 的核心理念,但并非照搬硅谷模式。中国连锁经营企业的现实是:预算有限(十万到百万级,非硅谷六七位数美元)、数字化基础薄弱、人员流动大、利润薄。需要做适配性改造。 + +> "中国FDE不是照搬硅谷岗位,而是企业在AI落地中,为模型能力与业务结果之间补上的一段责任。" —— 《FDE落地中国白皮书》 + +**借鉴什么**: +- 前线嵌入:深入业务现场,不闭门造车 +- 先跑通再优化:两周交付最小可用,而非半年画大饼 +- 双向沉淀:面向客户留能力,面向平台留模板 +- 结果负责:对业务结果负责,而非对"系统上线"负责 + +**不照搬什么**: +- 硅谷高客单价人海模式(中国连锁经营企业支撑不起) +- 全能FDE单人角色(中国更现实的是"AI+业务人员"组合) +- 重型工程底座(中国连锁经营IT基础设施简单,不需要Kubernetes级部署) +- Palantir式政府/金融级合规要求 + +### 1.2 中国适配:AI作为"虚拟FDE" + +中国连锁经营企业的现实解法——用AI替代部分FDE职能,降低对人力的依赖: + +| FDE职能 | 硅谷做法 | 中国适配做法 | +|---------|---------|-------------| +| 场景发现(Echo) | 行业专家驻场数周 | 老板/中层访谈 + AI整理提纲和指标草案 | +| 快速原型(Delta) | 工程师现场写代码 | AI生成SQL/API/前端代码,人审查验证 | +| 数据对接 | FDE手动打通系统 | AI辅助编写导入脚本和映射逻辑 | +| 持续迭代 | FDE长期驻场 | AI协同月度诊断 + 远程迭代 | +| 知识沉淀 | FDE带回经验形成产品 | AI辅助沉淀为文档/模板/Checklist | + +**核心思路**:AI承担Delta层80%的代码工作,人聚焦Echo层的业务判断和组织推动。这样即使预算有限,也能实现FDE式的深度交付。 + +### 1.3 Echo + Delta 双角色模型 + +借鉴Palantir的FDE实践,将部署团队分为两层角色,但在中国语境下重新定义: + +| 角色 | 定位 | 硅谷原版 | 中国适配 | +|------|------|---------|---------| +| **Echo**(该做什么) | 场景发现者、需求翻译者 | 退役军官/行业专家全职驻场 | 老板+中层访谈,AI辅助整理,业务人员兼职 | +| **Delta**(怎么做出来) | 快速构建者、现场交付者 | 工程师现场写代码 | AI生成代码为主,技术人员审查验证为辅 | + +**关键原则**:AI让Delta变便宜(代码生成、自动化测试),Echo更稀缺(识别高价值场景、理解行业、推动组织采纳)。在中国连锁经营企业,Echo层的核心是**老板本人的经营智慧和中层的管理经验**,而非外部专家。 + +### 1.4 总体循环 + +``` +老板战略 → 指标体系 → 数据本体 → 执行闭环 → AI协同构建 → 持续优化 + ↑ | + └────────────────── 反馈与优化 ←──────────────────────────┘ + +FDE双向沉淀: + 面向客户:业务经验 → AI知识库 → 工作流 → 应用能力 + 面向平台:行业场景 → 系统接口 → 测试方法 → 产品组件 + ↕ 共同载体:本体层(结构化业务知识图谱) +``` + +## 2. 八步工作法 + +> 每一步都标注FDE角色(Echo/Delta)和沉淀产出(面向客户/面向平台)。 + +### 步骤一:老板访谈与指挥层构建 `[Echo主导]` +> 从经营战略出发,定义"老板要看什么、管什么、决策什么" + +- FDE嵌入现场,访谈老板近期经营战略和目标(带提纲和示例) +- 将模糊战略翻译为可量化指标("我想看门店效率"→"日均产出/坪效/人效") +- 形成智脑指标体系(指挥层) +- **面向客户沉淀**:指标体系文档、老板驾驶舱原型 +- **面向平台沉淀**:行业指标模板(可复用于同类连锁经营企业) + +### 步骤二:数据现状与本体层构建 `[Echo+Delta]` +> 摸清家底,建立从数据到指标的映射——本体层是FDE双向沉淀的核心载体 + +- FDE深入客户数据现场,了解现有系统和数据情况 +- 针对指标体系的数据要求,盘点数据覆盖度 +- 构建智脑本体层(数据模型、物化视图、映射关系) +- **面向客户沉淀**:数据溯源文档、物化视图体系、数据质量报告 +- **面向平台沉淀**:本体设计模式(门店-账单-费用-考勤的通用关系模型) + +### 步骤三:中层访谈与执行层准备 `[Echo主导]` +> 明确"谁来做、做到什么程度、如何考核"——FDE不只是技术交付,更是组织流程改造 + +- FDE嵌入中层(区域经理、店长)工作现场,明确职权范围 +- 将指标体系拆解到岗位级执行动作 +- 准备智脑执行层(任务模板、考核标准、预警规则) +- **面向客户沉淀**:岗位-指标矩阵、任务闭环规则 +- **面向平台沉淀**:行业任务模板库(预警→任务→验收的标准流程) + +### 步骤四:AI协同模型设计与逻辑闭环验证 `[Echo+Delta]` +> 在写代码前,先用AI验证业务逻辑的完整性——FDE的"先想清楚再动手" + +- AI协同设计各层次的数据模型和业务逻辑 +- 验证"指标→数据→分析→预警→任务→执行→反馈"闭环 +- 发现逻辑断点并修复 +- **面向客户沉淀**:模型设计文档、闭环验证报告 +- **面向平台沉淀**:闭环验证Checklist(可复用于同类项目) + +### 步骤五:AI协同本体层构建 `[Delta主导]` +> AI参与数据层代码编写和验证——Delta层成本被AI大幅压缩 + +- AI协同编写物化视图SQL +- AI协同编写数据导入脚本 +- AI协同验证数据质量 +- **面向客户沉淀**:可运行的数据层 +- **面向平台沉淀**:物化视图SQL模板、数据校验脚本库 + +### 步骤六:AI协同后端API构建与验证 `[Delta主导]` +> AI参与API开发,逐个验证——快速交付能用的代码,不追求完美架构 + +- AI协同编写后端路由和SQL查询 +- curl + psql 双向验证每个API +- 修复SQL陷阱(schema、列名、日期格式) +- **面向客户沉淀**:可运行的API层 +- **面向平台沉淀**:API路由模板、SQL查询模式库 + +### 步骤七:AI协同前端UIUX设计与实现 `[Delta主导]` +> AI参与页面设计,参考典型页面模板——先交付能用的,再迭代好用的 + +- AI协同设计页面布局和交互 +- 基于组件规范实现前端页面 +- 联调API,处理空状态和加载状态 +- **面向客户沉淀**:可用的前端界面 +- **面向平台沉淀**:页面组件模板、行业Dashboard布局模板 + +### 步骤八:数据驱动闭环优化 `[Echo+Delta]` +> 上线不是终点,而是优化的起点——FDE持续驻场,把"不确定的机会"变成"可重复的流程" + +``` +数据采集 → 分析(基于模型)→ 发现问题 → 改进方案(AI协同) + → 实施 → 反馈 → 检验 → 优化 → 再循环 +``` + +- 基于模型分析数据,发现经营问题 +- AI协同生成改进方案 +- 落地实施,跟踪反馈 +- 检验效果,优化模型和参数 +- **面向客户沉淀**:持续运转的闭环机制、最佳实践库 +- **面向平台沉淀**:行业诊断模型、参数调优经验、可复制的改进方案模板 + +## 3. 三层架构与FDE本体层 + +``` +┌─────────────────────────────────────────┐ +│ 指挥层(老板) │ +│ - 战略目标 → 指标体系 │ +│ - 老板驾驶舱、总部驾驶舱 │ +│ - 关注:趋势、风险、机会 │ +│ - FDE角色:Echo发现场景、翻译需求 │ +├─────────────────────────────────────────┤ +│ 本体层(数据+模型) │ +│ - 原始数据 → 物化视图 → 指标计算 │ +│ - 数据溯源、口径一致性 │ +│ - 关注:数据质量、覆盖度、准确性 │ +│ - FDE角色:双向沉淀的核心载体 │ +│ - 本体 = 结构化业务知识图谱 │ +│ 面向客户:业务经验→AI知识库→工作流 │ +│ 面向平台:行业场景→产品组件→复用能力 │ +├─────────────────────────────────────────┤ +│ 执行层(中层+一线) │ +│ - 指标 → 任务 → 执行 → 反馈 │ +│ - 门店工作台、任务闭环 │ +│ - 关注:可执行、可考核、可追踪 │ +│ - FDE角色:嵌入现场、改造流程、推动采纳 │ +└─────────────────────────────────────────┘ +``` + +### 3.1 本体层的FDE价值 + +本体层不是简单的数据库设计,而是**从多个客户现场踩坑中提炼出来的通用业务知识结构**: + +- 第一个客户:花大量时间理解"门店-账单-费用-考勤"的关系,成本高 +- 第二个客户:本体层已稳定,只需适配新字段名和业务规则 +- 第十个客户:本体层成为行业模板,交付成本显著下降 + +> **规模化的核心度量**:如果第一个客户需要10人月,第十个同类客户仍然需要10人月,模式就没有跑通。 + +### 3.2 中国连锁经营企业的本体层特点 + +与硅谷FDE面向政府/金融的本体层不同,中国连锁经营企业的本体层有其特殊性: + +| 维度 | 硅谷FDE本体 | 中国连锁经营本体 | +|------|-----------|----------------| +| 数据源 | 多系统、高复杂度 | 收银+考勤+薪资+库存,3-5个Excel/CSV | +| 数据质量 | 有ETL管道,相对干净 | 原始数据脏,列名无含义(c001~c200) | +| 变更频率 | 低(制度稳定) | 高(门店开关、商品调整、人员流动) | +| 映射复杂度 | 系统间ID对接 | 门店名不一致("双安店"vs"双安总店") | +| 本体核心 | 权限+流程+合规 | 门店+账单+费用+考勤+库存的关系模型 | + +**连锁经营本体的核心资产**(跨品类通用:餐饮/零售/服务/教培): +1. 字段映射文档(c001=门店名,c114=实收...)——这是最宝贵的踩坑沉淀 +2. 门店名映射表——每个新客户都要重新建,但模式可复用 +3. 物化视图SQL模板——结构相同,表名和字段名适配即可 +4. 异常判断规则——"有消费无实收"等行业特定规则 +5. **门店-商品-供应链关系模型**——餐饮有BOM,零售有SKU,教培有课包,结构相似 + +## 4. AI协同模式与FDE角色分工 + +AI不是替代人,而是全程协同伙伴。FDE模式下,AI让Delta变便宜,Echo更稀缺: + +| 阶段 | FDE角色 | AI角色(Delta增强) | 人的角色(Echo主导) | 双向沉淀 | +|------|---------|-------------------|-------------------|---------| +| 老板访谈 | Echo | 整理提纲、记录要点、生成指标体系草案 | 引导访谈、确认战略方向、翻译模糊需求 | 行业指标模板 | +| 数据调研 | Echo+Delta | 分析数据质量、生成溯源文档、编写SQL | 确认数据含义、验证业务逻辑 | 本体设计模式 | +| 中层访谈 | Echo | 设计岗位-指标矩阵、生成任务模板 | 确认职权范围、考核标准、推动组织采纳 | 行业任务模板库 | +| 模型设计 | Echo+Delta | 设计数据模型、验证逻辑闭环 | 审查业务合理性、决策取舍 | 闭环验证Checklist | +| 本体构建 | Delta | 编写SQL和脚本、验证数据 | 审查代码、验证结果 | 物化视图SQL模板 | +| API构建 | Delta | 编写路由和查询、排查错误 | 验证API返回、确认业务逻辑 | API路由模板 | +| 前端实现 | Delta | 编写页面代码、设计交互 | 审查UI/UX、验证用户体验 | 页面组件模板 | +| 闭环优化 | Echo+Delta | 分析数据、生成改进方案 | 决策方案、推动实施、验收结果 | 行业诊断模型 | + +### 4.1 "先跑通再优化"原则 + +``` +传统交付:需求分析(1月) → 架构设计(1月) → 开发(3月) → 测试(1月) → 上线 +FDE交付:现场嵌入(1周) → 最小可用(2周) → 真实反馈(1周) → 快速迭代(持续) + +关键差异: +- 传统:追求完美架构,上线时需求已变 +- FDE:先交付能用的,在真实反馈中迭代 +- AI加持:Delta层(代码编写)成本大幅压缩,原型可在数小时内生成 +``` + +**中国连锁经营企业的特殊考量**: +- 老板耐心有限:两周看不到东西就会失去信任,所以第一版必须快速可见 +- 数据基础差:不要等数据完美了再开始,用现有脏数据先跑通,边用边治 +- 人员能力参差:第一版必须"傻瓜式"操作,不能要求店长学习复杂流程 +- 利润薄:每一步都要能算清ROI,老板才会继续投入 + +### 4.2 "从最小痛点开始"原则 + +不要上来做"大一统"方案。选一个最小痛点,两周内跑通: + +| 选择标准 | 示例 | +|---------|------| +| 业务痛点足够明确 | "13家门店亏损,不知道为什么亏" | +| 数据虽然不完美但够用 | bill_records有168万条,覆盖94家门店 | +| 效果可以量化 | 亏损门店数从13降到8 | +| 老板关心 | 直接关联L0战略指标 | +| 不依赖组织变革 | 不需要先改考核制度才能跑 | + +**中国连锁经营企业的典型最小痛点**: +1. **门店亏损诊断**:数据现成(账单+费用),老板最关心,两周可见 +2. **成本异动监控**:数据现成(账单+成本),痛点明确,容易量化 +3. **异常交易监控**:数据现成(账单/订单),风险可控,见效快 +4. **人效分析**:数据现成(考勤+营收),人力成本是连锁经营第二大成本 + +**不建议作为起点的场景**: +- 智能排班(需要考勤数据质量高+店长配合) +- 会员精准营销(需要会员数据积累+营销预算) +- 供应链优化(需要跨系统数据+供应商配合) + +跑通一个场景后,再复制到下一个——先铺石子路,再修高速公路。 + +## 5. 文档体系导航 + +### 方法论主体(八步) + +| 步骤 | 文件 | FDE角色 | 核心输出 | 平台沉淀 | +|------|------|---------|---------|---------| +| 一 | [02-步骤一-老板访谈与指挥层构建.md](02-步骤一-老板访谈与指挥层构建.md) | Echo | 指标体系、驾驶舱原型 | 行业指标模板 | +| 二 | [03-步骤二-数据现状与本体层构建.md](03-步骤二-数据现状与本体层构建.md) | Echo+Delta | 数据溯源、物化视图 | 本体设计模式 | +| 三 | [04-步骤三-中层访谈与执行层准备.md](04-步骤三-中层访谈与执行层准备.md) | Echo | 岗位-指标矩阵、任务模板 | 行业任务模板库 | +| 四 | [05-步骤四-AI协同模型设计与逻辑闭环.md](05-步骤四-AI协同模型设计与逻辑闭环.md) | Echo+Delta | 模型设计、闭环验证 | 闭环验证Checklist | +| 五 | [06-步骤五-AI协同本体层构建.md](06-步骤五-AI协同本体层构建.md) | Delta(AI为主) | 数据层代码 | 物化视图SQL模板 | +| 六 | [07-步骤六-AI协同后端API构建与验证.md](07-步骤六-AI协同后端API构建与验证.md) | Delta(AI为主) | API层代码 | API路由模板 | +| 七 | [08-步骤七-AI协同前端UIUX设计与实现.md](08-步骤七-AI协同前端UIUX设计与实现.md) | Delta(AI为主) | 前端界面 | 页面组件模板 | +| 八 | [09-步骤八-数据驱动闭环优化.md](09-步骤八-数据驱动闭环优化.md) | Echo+Delta | 优化闭环 | 行业诊断模型 | + +### 技术参考 + +| 文件 | 内容 | +|------|------| +| [10-技术参考-项目概述与架构.md](10-技术参考-项目概述与架构.md) | 技术架构、数据流、部署拓扑 | +| [11-技术参考-部署与运维.md](11-技术参考-部署与运维.md) | 部署脚本、FRP隧道、PM2 | +| [12-技术参考-调试排查手册.md](12-技术参考-调试排查手册.md) | 问题分类、排查流程、案例 | +| [13-技术参考-通用方法论与避坑指南.md](13-技术参考-通用方法论与避坑指南.md) | 核心原则、风险清单、Checklist | +| [14-技术参考-数据溯源与API全量清单.md](14-技术参考-数据溯源与API全量清单.md) | 逐页面→API→SQL→字段映射 | +| [15-技术参考-指标口径一致性分析.md](15-技术参考-指标口径一致性分析.md) | 跨页面口径对比、问题清单 | + +## 6. 规模化度量(中国适配版) + +硅谷FDE用"人月成本递减"衡量规模化。中国连锁经营企业更现实的度量方式: + +| 指标 | 定义 | 目标 | 中国适配说明 | +|------|------|------|-------------| +| 首次交付周期 | 从访谈到第一个可用版本 | <4周 | 老板耐心有限,超4周信任崩塌 | +| 同类客户交付周期 | 第二个同类客户 | <2周 | 本体层和模板复用后应大幅缩短 | +| AI代码占比 | AI生成的代码占总代码比例 | >70% | 降低对稀缺工程人才的依赖 | +| 客户自助率 | 客户独立完成的数据操作占比 | 逐月提升 | 中国连锁经营IT能力弱,需渐进式 | +| 闭环运转率 | 月度闭环实际执行率 | >80% | 闭环转起来才是真落地 | +| 沉淀复用率 | 可复用资产占项目总产出 | >40% | 没有沉淀就没有规模化 | + +### 6.1 中国连锁经营企业的规模化路径 + +``` +阶段一(单店验证):1个客户,4周交付,大量踩坑 + ↓ 沉淀:字段映射、物化视图SQL、页面模板 +阶段二(同品牌复制):同品牌不同月份,1周交付,验证稳定性 + ↓ 沉淀:数据校验脚本、异常规则库 +阶段三(同品类复制):同品类不同品牌(如餐饮A→餐饮B),2周交付,适配字段名和业务规则 + ↓ 沉淀:品类本体模板、指标体系模板 +阶段四(跨品类扩展):不同品类(餐饮→零售→服务→教培),3周交付,适配本体层 + ↓ 沉淀:连锁经营通用本体设计模式 +``` + +**关键**:每个阶段的沉淀质量决定下一阶段的速度。如果做完一个客户没有沉淀出可复用资产,下一个客户又从头开始,那就是传统外包,不是FDE。 diff --git a/docs/智脑实施方法论/02-步骤一-老板访谈与指挥层构建.md b/docs/智脑实施方法论/02-步骤一-老板访谈与指挥层构建.md new file mode 100644 index 0000000..c599817 --- /dev/null +++ b/docs/智脑实施方法论/02-步骤一-老板访谈与指挥层构建.md @@ -0,0 +1,147 @@ +# 02 · 步骤一:老板访谈与指挥层构建 + +> 目标:从老板的经营战略出发,定义智脑要呈现什么、预警什么、辅助决策什么。 `[Echo主导]` +> +> FDE角色:这一步是典型的Echo层工作——深入业务现场,把老板模糊的战略意图翻译为可量化的指标体系。AI辅助整理提纲和生成草案,但核心是人的业务判断。 + +## 1. 访谈准备 + +### 1.1 访谈提纲 + +``` +一、战略方向 +1. 今年最关注哪3个经营目标?(营收/利润/扩张/降本/品牌) +2. 当前最大的经营痛点是什么? +3. 觉得哪些决策缺乏数据支撑? + +二、管理范围 +4. 您平时看哪些报表?频率?哪些指标最关键? +5. 希望每天/每周/每月自动看到什么? +6. 哪些情况需要立即预警?(如某店连续3天营收下降) + +三、组织架构 +7. 下面管几层?(总部→区域→门店) +8. 区域经理和店长的核心考核指标是什么? +9. 哪些决策是您亲自做的?哪些授权下去了? + +四、数据现状 +10. 现在有哪些系统?(收银/考勤/薪资/供应链/会员) +11. 这些系统数据能打通吗? +12. 有没有以前想做但没做成的数据分析? + +五、期望与边界 +13. 希望智脑帮您做到什么程度?(看数据/给建议/自动执行) +14. 有哪些底线是不能碰的?(如不能自动调价) +15. 对数据安全有什么要求? +``` + +### 1.2 示例引导 + +老板可能说:"我就是想看哪家店在亏钱,为什么亏,怎么改" + +拆解为: +- **指标**:门店贡献利润、食材成本率、人工费率、费用率 +- **预警**:连续亏损、成本率超标、费用率异常 +- **决策**:关店/整改/换人/降本 +- **执行**:任务派发给区域经理→店长→跟踪反馈 + +## 2. 指标体系构建 + +### 2.1 指标分层 + +``` +L0: 战略指标(老板关注) + ├── 营收总额、利润总额、门店数、客单价 + ├── 同比/环比趋势 + └── 盈利/亏损门店数 + +L1: 经营指标(管理层关注) + ├── 优惠率、毛利率、会员占比 + ├── 食材成本率、人工费率、房租费率、水电费率 + ├── 外卖佣金占比 + └── 平台经济性(美团/饿了么/抖音成本率) + +L2: 执行指标(门店关注) + ├── 日均实收、账单数、客单价 + ├── 风险评级(红/黄/绿) + ├── 异常账单数、零实收数 + ├── 客流-人力匹配度 + └── 任务完成率 +``` + +### 2.2 指标卡设计 + +基于访谈结果,设计老板驾驶舱的指标卡: + +| 指标 | 数据来源 | 展示形式 | 预警阈值 | +|------|---------|---------|---------| +| 营业收入 | bill_fact.consumption | MetricCard (currency) | 环比下降>10% | +| 实收 | bill_fact.received_total | MetricCard (currency) | — | +| 门店贡献利润 | received - food_cost - operating_expense | MetricCard (currency) | <0 标红 | +| 贡献率 | profit / matched_received * 100 | MetricCard (percent) | <5% 标黄 | +| 盈利门店数 | count FILTER(contribution > 0) | MetricCard (number) | — | +| 亏损门店数 | count FILTER(contribution <= 0) | MetricCard (number) | >5 标红 | +| 食材成本率 | food_cost / received * 100 | MetricCard (percent) | >40% 标红 | +| 人工费率 | wage / received * 100 | MetricCard (percent) | >25% 标红 | + +### 2.3 预警规则设计 + +| 预警类型 | 触发条件 | 级别 | 推送对象 | +|---------|---------|------|---------| +| 营收异动 | 日营收环比下降>20% | 红色 | 老板+区域经理 | +| 成本异动 | 食材成本率>45% | 红色 | 老板+区域经理 | +| 人力异动 | 人工费率>30%或客流-人力严重不匹配 | 橙色 | 区域经理 | +| 平台依赖 | 单平台占比>70%且成本率>25% | 橙色 | 老板 | +| 任务逾期 | 整改任务超7天未完成 | 橙色 | 区域经理 | + +## 3. 指挥层原型 + +### 3.1 老板驾驶舱 + +``` +┌─────────────────────────────────────────────────┐ +│ 老板驾驶舱 [2026年4月] │ +├─────────────────────────────────────────────────┤ +│ [营收] [实收] [利润] [贡献率] [盈利/亏损] │ +│ 6420万 6369万 698万 10.96% 78家/13家 │ +├─────────────────────────────────────────────────┤ +│ 📊 利润瀑布图 📊 日度实收趋势 │ +│ (实收→食材→人工→房租 (折线图,环比标注) │ +│ →水电→佣金→利润) │ +├─────────────────────────────────────────────────┤ +│ 📊 门店风险分布 📊 P0/P1重点门店 │ +│ (红/黄/绿饼图) (表格,含问题组合) │ +├─────────────────────────────────────────────────┤ +│ 📊 平台成本率TOP15 📊 门店经营象限 │ +│ (美团/饿了么/抖音) (散点图:日均实收vs毛利率) │ +├─────────────────────────────────────────────────┤ +│ 📋 利润机会池 📋 月度趋势 │ +│ (可改善空间排序) (实收+账单数双轴) │ +└─────────────────────────────────────────────────┘ +``` + +### 3.2 总部驾驶舱 + +比老板驾驶舱更详细,增加: +- 态势感知预警卡片(5类预警合并) +- 闭环健康度(5项rate指标) +- 同比/环比对比 +- 利润趋势(月度贡献利润走势) + +## 4. 访谈输出物 + +| 输出物 | 说明 | 后续步骤使用 | +|--------|------|-------------| +| 战略目标清单 | 老板关注的3-5个核心目标 | 步骤四模型设计的输入 | +| 指标体系文档 | L0/L1/L2分层指标定义 | 步骤二数据覆盖度盘点 | +| 驾驶舱原型 | 页面布局和指标卡设计 | 步骤七前端实现 | +| 预警规则 | 触发条件、级别、推送对象 | 步骤四闭环验证 | +| 管理层级图 | 总部→区域→门店的决策权分布 | 步骤三中层访谈 | + +## 5. 关键注意事项 + +1. **不要一上来谈技术**:先聊经营,再聊数据,最后才聊系统 +2. **指标要可量化**:老板说"想看门店效率",要追问"效率具体指什么?人均产出?坪效?" +3. **预警要可执行**:预警必须关联到具体动作,否则只是噪音 +4. **分清"看的"和"管的"**:老板看趋势和异常,管理层管过程和整改 +5. **留出迭代空间**:第一版不需要完美,先上线核心指标,后续根据反馈迭代 diff --git a/docs/智脑实施方法论/02-数据接入与治理.md b/docs/智脑实施方法论/03-步骤二-数据现状与本体层构建.md similarity index 96% rename from docs/智脑实施方法论/02-数据接入与治理.md rename to docs/智脑实施方法论/03-步骤二-数据现状与本体层构建.md index 9ad1069..2b49051 100644 --- a/docs/智脑实施方法论/02-数据接入与治理.md +++ b/docs/智脑实施方法论/03-步骤二-数据现状与本体层构建.md @@ -1,4 +1,6 @@ -# 02 · 数据接入与治理 +# 03 · 步骤二:数据现状与本体层构建 + +> 目标:摸清数据家底,建立从原始数据到指标体系的映射——本体层是FDE双向沉淀的核心载体。 `[Echo+Delta]` ## 1. 原始数据导入 diff --git a/docs/智脑实施方法论/04-步骤三-中层访谈与执行层准备.md b/docs/智脑实施方法论/04-步骤三-中层访谈与执行层准备.md new file mode 100644 index 0000000..0858b27 --- /dev/null +++ b/docs/智脑实施方法论/04-步骤三-中层访谈与执行层准备.md @@ -0,0 +1,176 @@ +# 04 · 步骤三:中层访谈与执行层准备 + +> 目标:将指标体系从"老板看的"落地为"中层和一线执行的",明确谁来做、做到什么程度、如何考核。 `[Echo主导]` +> +> FDE角色:这一步是Echo层在组织中的延伸——不只是技术交付,更是流程改造。需要嵌入中层和一线的工作现场,理解真实痛点,才能设计出可执行的任务闭环。 + +## 1. 中层访谈准备 + +### 1.1 访谈对象 + +| 角色 | 人数 | 关注重点 | +|------|------|---------| +| 区域经理 | 3-5人 | 区域整体经营、门店评级、人员调配 | +| 店长代表 | 5-8人(红/黄/绿各选) | 门店日常运营、成本控制、任务执行 | +| 商品部/供应链 | 1-2人 | 菜品成本、BOM、采购、配送 | +| 财务 | 1人 | 费用归集、成本核算口径 | + +### 1.2 访谈提纲 + +``` +一、职权范围 +1. 你日常负责哪些门店/区域?核心KPI是什么? +2. 哪些决策你能直接做?哪些需要上报? +3. 你希望看到哪些数据来辅助你的日常决策? + +二、执行痛点 +4. 总部下发的任务,你觉得哪些好执行、哪些难落地? +5. 你觉得目前哪些指标考核不合理? +6. 如果系统能自动帮你发现一个问题并派发任务,你最希望是什么? + +三、数据使用习惯 +7. 你现在每天/每周看什么报表? +8. 哪些数据你觉得不准或滞后? +9. 如果有一个"门店工作台",你最希望它包含什么功能? + +四、闭环反馈 +10. 整改任务从下发到完成,通常需要多久? +11. 执行中最大的阻力是什么? +12. 如何验证整改效果? +``` + +### 1.3 典型回答与拆解 + +**区域经理说**:"我最头疼的是有些店长不主动整改,等我去检查才发现问题" + +拆解: +- 系统需求:自动预警→自动派发任务→跟踪完成率→逾期上报 +- 指标关联:任务生成率、店长执行率、区域周检率 +- 执行层设计:预警触发→任务模板→店长接收→限期完成→区域验收 + +**店长说**:"我不知道自己店在区域排第几,也不知道哪里做得不好" + +拆解: +- 系统需求:门店工作台→对标分析→偏差诊断→改进建议 +- 指标关联:日均实收、客单价、成本率、风险评级 +- 执行层设计:店长打开页面即可看到本店vs区域均值偏差 + +## 2. 岗位-指标矩阵 + +### 2.1 矩阵设计 + +| 指标 | 老板 | 区域经理 | 店长 | 商品部 | +|------|------|---------|------|--------| +| 营收总额 | 👁️ 看 | 👁️ 看 | — | — | +| 门店贡献利润 | 👁️ 看 | 👁️ 看 | 👁️ 看 | — | +| 食材成本率 | 👁️ 看 | 👁️ 看 | 👁️ 看 | 👁️ 看 | +| 人工费率 | — | 👁️ 看 | 👁️ 看 | — | +| 风险评级 | 👁️ 看 | 🔄 管 | 🔄 管 | — | +| 客流-人力匹配 | — | 👁️ 看 | 🔄 管 | — | +| 异常账单 | — | 🔄 管 | 🔄 管 | — | +| 菜品成本方差 | — | — | — | 🔄 管 | +| 任务完成率 | 👁️ 看 | 🔄 管 | 🔄 做 | — | +| BOM准确率 | — | — | — | 🔄 管 | + +- 👁️ 看:只看数据,不直接操作 +- 🔄 管:负责监督和整改 +- 🔄 做:负责执行和反馈 + +### 2.2 数据权限设计 + +```typescript +// 后端 getDataScope 实现 +interface DataScope { + role: 'hq' | 'regional' | 'store' | 'dept' + store_names: string[] | null // null = 全部门店 + region?: string // 区域经理管辖区域 + store_code?: string // 店长所属门店 +} +``` + +| 角色 | 可见范围 | 可操作范围 | +|------|---------|-----------| +| 总部管理员 | 全部门店 | 全部 | +| 区域经理 | 本区域门店 | 本区域 | +| 店长 | 本店 | 本店 | +| 商品部 | 全部门店(只读) | 菜品/BOM相关 | + +## 3. 执行层设计 + +### 3.1 任务闭环模型 + +``` +预警触发 → 任务生成 → 店长接收 → 整改执行 → + 区域验收 → 效果检验 → 经验沉淀 → 关闭/重开 +``` + +### 3.2 任务模板 + +| 预警类型 | 任务标题 | 责任人 | 期限 | 验收标准 | +|---------|---------|--------|------|---------| +| 食材成本率>45% | "XX店食材成本率超标,请分析原因并提交整改方案" | 店长 | 7天 | 成本率降至40%以下 | +| 连续亏损 | "XX店连续2月亏损,请制定扭亏方案" | 店长+区域经理 | 14天 | 当月贡献利润转正 | +| 异常账单增多 | "XX店异常账单数异常,请核查收银流程" | 店长 | 3天 | 异常账单数下降50% | +| 客流-人力不匹配 | "XX店高峰人手不足,请调整排班" | 店长 | 3天 | 高峰时段人均产出<15单 | +| 任务逾期 | "XX店有N项整改任务逾期,请督促完成" | 区域经理 | 3天 | 逾期任务清零 | + +### 3.3 闭环健康度指标 + +| 指标 | 计算方式 | 目标值 | +|------|---------|--------| +| 任务生成率 | 已生成任务数 / 应生成预警数 | >80% | +| 店长执行率 | 已完成任务数 / 已接收任务数 | >70% | +| 区域周检率 | 本周已检查门店数 / 本周应检查门店数 | >90% | +| 月度验收率 | 本月已验收任务数 / 本月已完成任务数 | >80% | +| 经验推广率 | 已推广最佳实践数 / 已沉淀最佳实践数 | >50% | + +## 4. 门店工作台设计 + +### 4.1 页面结构 + +``` +┌─────────────────────────────────────────────────┐ +│ 门店工作台 - 潘家园店 [2026年4月] │ +├─────────────────────────────────────────────────┤ +│ [日均实收] [客单价] [优惠率] [毛利率] [风险等级] │ +│ 20,144 36.8 20.5% 61.8% 🟢 绿色 │ +│ (vs区域均值) (+5%) (-2%) (+1%) (持平) │ +├─────────────────────────────────────────────────┤ +│ Tab1: 日报卡 Tab2: 风险 Tab3: 成本 │ +│ Tab4: 会员 Tab5: 排班 Tab6: 任务 │ +├─────────────────────────────────────────────────┤ +│ 📋 今日待办任务(3项) │ +│ □ 食材成本率超标整改(还剩5天) │ +│ □ 异常账单核查(还剩2天) │ +│ □ 排班优化(今日截止) │ +├─────────────────────────────────────────────────┤ +│ 📊 餐段分析(早/午/晚各时段实收vs区域均值) │ +│ 📊 品类结构(各品类销售占比) │ +│ 📋 异常账单明细 │ +└─────────────────────────────────────────────────┘ +``` + +### 4.2 店长视角的核心需求 + +1. **对标定位**:本店 vs 区域均值,一眼看出哪里偏差大 +2. **任务驱动**:打开就有待办,不用自己去翻报表找问题 +3. **一键诊断**:点击偏差指标,自动展开原因分析 +4. **整改跟踪**:任务有期限、有验收、有效果检验 + +## 5. 访谈输出物 + +| 输出物 | 说明 | 后续步骤使用 | +|--------|------|-------------| +| 岗位-指标矩阵 | 每个岗位看什么、管什么、做什么 | 步骤四模型设计、步骤七页面权限 | +| 任务模板库 | 预警→任务→验收的标准流程 | 步骤四闭环验证、步骤六API开发 | +| 门店工作台原型 | 店长页面的布局和功能 | 步骤七前端实现 | +| 数据权限规则 | 各角色的数据可见范围 | 步骤六API的getDataScope | +| 闭环健康度指标 | 5项rate指标定义和目标值 | 步骤六API、步骤七总部驾驶舱 | + +## 6. 关键注意事项 + +1. **不要跳过中层直接到一线**:区域经理是承上启下的关键环节 +2. **任务模板要具体**:不能是"请改进",必须是"请将食材成本率从45%降至40%" +3. **考核要联动**:系统指标要与现有KPI考核挂钩,否则没人会用 +4. **店长的声音很重要**:选红/黄/绿各色门店的店长,了解不同状态下的痛点 +5. **执行层不是管控工具**:是帮中层和一线更好地工作的工具,定位要正确 diff --git a/docs/智脑实施方法论/05-步骤四-AI协同模型设计与逻辑闭环.md b/docs/智脑实施方法论/05-步骤四-AI协同模型设计与逻辑闭环.md new file mode 100644 index 0000000..6432d32 --- /dev/null +++ b/docs/智脑实施方法论/05-步骤四-AI协同模型设计与逻辑闭环.md @@ -0,0 +1,202 @@ +# 05 · 步骤四:AI协同模型设计与逻辑闭环验证 + +> 目标:在写代码前,用AI验证从战略指标到数据执行的全链路逻辑完整性,发现并修复断点。 `[Echo+Delta]` +> +> FDE角色:这是"先想清楚再动手"的关键步骤。Echo层定义业务逻辑闭环,Delta层用AI验证技术可行性。逻辑断点在这一步修复,成本远低于编码后返工。 + +## 1. 模型设计框架 + +### 1.1 三层模型映射 + +``` +指挥层模型(战略→指标) + 战略目标 → 核心指标 → 展示形式 → 预警规则 + ↓ +本体层模型(数据→指标) + 原始表 → 物化视图 → API字段 → 前端变量 + ↓ +执行层模型(指标→任务→闭环) + 指标偏差 → 预警触发 → 任务生成 → 执行反馈 → 效果检验 +``` + +### 1.2 AI协同设计流程 + +``` +1. 输入:指标体系 + 数据现状 + 岗位矩阵 +2. AI生成:完整的数据模型设计草案 + - 每个指标的计算公式 + - 数据源映射 + - 物化视图设计 + - API设计 + - 预警规则 + - 任务模板 +3. 人工审查:业务逻辑是否正确 +4. AI验证:逻辑闭环是否完整 +5. 输出:可执行的技术方案 +``` + +## 2. 指标计算模型 + +### 2.1 核心指标公式 + +| 指标 | 公式 | 数据源 | 注意事项 | +|------|------|--------|---------| +| 营业收入 | `sum(consumption)` | bill_fact.consumption | — | +| 优惠 | `sum(discount_total)` | bill_fact.discount_total | — | +| 实收 | `sum(received_total)` | bill_fact.received_total | — | +| 客单价 | `sum(received) / sum(bill_count)` | bill_fact | 注意:不是avg(received_total) | +| 优惠率 | `avg(discount_total / consumption * 100)` | bill_fact | 逐单计算再平均 | +| 理论毛利率 | `sum(theoretical_profit) / sum(received) * 100` | bill_fact | — | +| 会员占比 | `sum(received) FILTER(member_id非空) / sum(received) * 100` | bill_fact | — | +| 食材成本率 | `sum(actual_food_cost) / sum(matched_received) * 100` | mv_store_operating_expense_monthly | 分母必须用matched口径 | +| 人工费率 | `sum(wage_expense) / sum(matched_received) * 100` | 同上 | 同上 | +| 贡献利润 | `sum(received) FILTER(has_expense) - food_cost - operating_expense` | 多表JOIN | FILTER vs COALESCE口径要统一 | + +### 2.2 口径一致性规则 + +**核心原则**:同一指标在多个页面展示时,必须使用同一数据源和同一计算方式。 + +```sql +-- 正确:费用率分母统一为matched_received +sum(operating_expense) / sum(received) FILTER(WHERE has_expense) * 100 + +-- 错误:分母包含无费用门店 +sum(operating_expense) / sum(received) * 100 +``` + +**FILTER vs COALESCE**: +- `sum(x) FILTER(WHERE has_expense)` — 排除无费用门店的整行 +- `sum(COALESCE(x, 0))` — 无费用门店的x视为0,但received仍计入分母 +- 两者在计算金额时结果相同,但在计算比率时分母不同 + +## 3. 物化视图模型 + +### 3.1 设计原则 + +1. **预聚合到月度+门店粒度**:原始表千万级,API不能直接查 +2. **一个视图服务多个API**:避免为每个API建一个视图 +3. **字段命名统一**:`received`、`consumption`、`bill_count`在各视图中保持一致 +4. **刷新机制明确**:每个视图有对应的刷新脚本 + +### 3.2 核心视图清单 + +| 视图 | 粒度 | 用途 | 关键字段 | +|------|------|------|---------| +| mv_store_risk_rating_monthly | 月×门店 | 门店评级 | risk_level, received, bill_count | +| mv_store_operating_expense_monthly | 月×门店 | 费用分析 | food_cost, wage, rent, utility | +| mv_store_platform_economics_monthly | 月×门店 | 平台经济性 | meituan_received, eleme_cost_rate | +| mv_bill_hourly | 月×门店×小时 | 客流分析 | bills, avg_guests | +| mv_overview_daily | 日 | 日度概览 | received, bill_count | +| mv_overview_monthly | 月 | 月度概览 | received, bill_count, avg_bill_value | +| mv_risk_anomaly | 月×门店×账单 | 异常账单 | anomaly_reason, consumption | +| mv_risk_cashier | 月×门店×收银员 | 收银员风险 | bill_count, anomaly_bills | + +### 3.3 AI协同验证 + +``` +AI Prompt示例: +"请检查以下物化视图设计是否覆盖了指标体系中的所有L0和L1指标。 +指标体系:[附上指标体系文档] +物化视图清单:[附上视图清单] +输出:覆盖度矩阵 + 缺失指标 + 建议" +``` + +## 4. 逻辑闭环验证 + +### 4.1 闭环图 + +``` +数据采集 → 物化视图 → API查询 → 前端展示 → 人工决策 + ↑ ↓ +效果检验 ← 任务关闭 ← 执行反馈 ← 任务接收 ← 预警触发 +``` + +### 4.2 AI验证清单 + +| 验证项 | 检查内容 | 方法 | +|--------|---------|------| +| 数据覆盖度 | 每个指标是否有数据源 | 指标→视图→表→字段 逐项追溯 | +| 计算正确性 | 公式是否正确 | 用已知数据验证计算结果 | +| 口径一致性 | 跨页面同一指标是否一致 | 对比不同API的返回值 | +| 预警完整性 | 每个预警是否有触发条件和任务模板 | 逐条检查预警规则 | +| 任务闭环 | 任务从生成到关闭是否有完整流程 | 模拟走一遍流程 | +| 权限正确性 | 各角色是否只看到应有数据 | 模拟不同角色登录验证 | +| 空状态处理 | 无数据时是否优雅降级 | 测试新月份/新门店场景 | + +### 4.3 逻辑断点示例 + +**断点1**:预警"食材成本率>45%"已配置,但没有对应的任务模板 +``` +修复:添加任务模板"食材成本率超标整改" +``` + +**断点2**:任务"排班优化"已配置,但系统没有客流-人力匹配数据 +``` +修复:补充attendance_records解析逻辑,生成客流-人力匹配指标 +``` + +**断点3**:店长能看到本店数据,但无法看到区域均值对标 +``` +修复:在/stores/:code API中增加区域均值字段 +``` + +**断点4**:利润瀑布图的received包含无费用门店,导致费率偏低 +``` +修复:received改为FILTER(WHERE has_expense)口径 +``` + +## 5. AI协同设计输出 + +### 5.1 技术方案文档 + +``` +1. 数据模型设计 + - 原始表ER图 + - 物化视图清单和SQL + - 门店名映射表 + +2. API设计 + - 路由清单 + - 每个API的SQL查询 + - 请求参数和响应格式 + - 数据权限规则 + +3. 前端设计 + - 页面清单 + - 每个页面的组件布局 + - 指标卡配置 + - 图表配置 + +4. 预警与任务设计 + - 预警规则清单 + - 任务模板库 + - 闭环健康度指标 +``` + +### 5.2 验证报告 + +``` +1. 覆盖度报告 + - 指标覆盖率:X/Y + - 数据覆盖率:哪些指标有数据,哪些缺数据 + +2. 口径一致性报告 + - 跨页面指标对比表 + - 不一致项及修复方案 + +3. 闭环验证报告 + - 预警→任务→执行→反馈 全链路测试结果 + - 发现的断点及修复方案 + +4. 性能预估 + - 各API预估响应时间 + - 物化视图刷新耗时 +``` + +## 6. 关键注意事项 + +1. **先验证再编码**:这一步的目的是在写代码前发现逻辑问题,避免返工 +2. **AI是协同不是替代**:AI生成方案,人审查业务合理性 +3. **闭环比单点重要**:一个指标算错了是bug,一个闭环断了是系统失效 +4. **口径要从一开始统一**:后期修复口径不一致的成本远高于初期统一 +5. **留出迭代空间**:第一版不需要覆盖所有指标,先跑通核心闭环 diff --git a/docs/智脑实施方法论/06-步骤五-AI协同本体层构建.md b/docs/智脑实施方法论/06-步骤五-AI协同本体层构建.md new file mode 100644 index 0000000..6ca59a3 --- /dev/null +++ b/docs/智脑实施方法论/06-步骤五-AI协同本体层构建.md @@ -0,0 +1,192 @@ +# 06 · 步骤五:AI协同本体层构建 + +> 目标:AI参与数据层代码编写——物化视图SQL、导入脚本、数据质量校验,并逐项验证。 `[Delta主导,AI为主]` +> +> FDE角色:这一步是Delta层的核心工作。AI承担80%的代码生成(SQL、脚本),人聚焦审查和验证。本体层的沉淀质量直接决定下一个同类客户的交付速度。 + +## 1. AI协同模式 + +### 1.1 工作流程 + +``` +1. 人工提供:数据现状(表结构、样本数据、数据量) +2. AI生成:物化视图SQL草案 +3. 人工审查:业务逻辑是否正确 +4. AI执行:在数据库上创建视图 + 验证数据 +5. 人工确认:抽查数据准确性 +6. 迭代:发现问题→AI修复→再验证 +``` + +### 1.2 AI Prompt模式 + +``` +"请基于以下原始表设计物化视图: +- 原始表:bill_records(字段:c003门店, c009消费, c068优惠, c114实收, c175下单时间, c176结账时间, c191收银员) +- 需求:按月×门店×小时聚合账单数、消费、优惠、实收 +- 注意:c114可能为空字符串,需COALESCE处理 +输出:CREATE MATERIALIZED VIEW SQL + 索引SQL" +``` + +## 2. 物化视图构建 + +### 2.1 构建顺序 + +``` +1. 基础视图(不依赖其他视图) + ├── mv_bill_hourly(账单小时聚合) + ├── mv_overview_daily(日度概览) + └── mv_overview_monthly(月度概览) + +2. 门店评级视图(依赖基础视图) + ├── mv_store_risk_rating_monthly(门店风险评级) + └── mv_store_benchmark_composite_monthly(门店对标) + +3. 费用视图(依赖外部费用数据) + └── mv_store_operating_expense_monthly(门店费用) + +4. 风险明细视图(依赖原始表) + ├── mv_risk_anomaly(异常账单) + ├── mv_risk_zero(零实收) + └── mv_risk_cashier(收银员风险) + +5. 平台视图 + └── mv_store_platform_economics_monthly(平台经济性) +``` + +### 2.2 AI协同编写物化视图 + +**典型交互**: + +``` +人:bill_records中c003是门店名,c114是实收金额,但有些是空字符串 +AI:生成SQL: + CREATE MATERIALIZED VIEW mv_bill_hourly AS + SELECT + c003 AS store_name, + EXTRACT(HOUR FROM c176::timestamp) AS hour, + to_char(c176::timestamp, 'YYYY-MM') AS month, + count(*) AS bills, + sum(COALESCE(NULLIF(c009,'')::numeric, 0)) AS consumption, + sum(COALESCE(NULLIF(c114,'')::numeric, 0)) AS received + FROM bill_records + WHERE c176 IS NOT NULL + GROUP BY 1, 2, 3; + +人:门店名需要和费用表对齐,有些名字不一样 +AI:补充映射逻辑,使用store_name_mapping +``` + +### 2.3 异常账单视图设计 + +```sql +-- AI协同设计的异常判断逻辑 +CASE + WHEN consumption > 0 AND received = 0 THEN '有消费无实收' + WHEN discount > consumption THEN '优惠大于消费' + WHEN abs(consumption - discount - received) > 1 THEN '消费-优惠与实收不平' + ELSE NULL +END +``` + +**关键教训**:阈值0.05元太严格,会将浮点舍入差异标为异常。AI建议初始阈值设为1元,后续根据数据分布调整。 + +## 3. 数据导入脚本 + +### 3.1 AI协同编写导入脚本 + +``` +人:这是4月的薪资Excel,列名是中文,需要导入salary_detail_records +AI:生成Python/SQL导入脚本,包含: + - 列名映射(中文→英文字段名) + - 数据类型转换 + - 空值处理 + - 去重逻辑 + - 进度输出 +``` + +### 3.2 导入关键点 + +| 数据源 | 关键问题 | 解决方案 | +|--------|---------|---------| +| bill_records | c001~c200列名无含义 | 建立字段映射文档 | +| salary_detail_records | salary_period格式"2026年4月" | 查询时用to_char中文格式 | +| attendance_records | department是路径字符串 | extractStore从后往前找"店" | +| 费用数据 | 门店名与账单系统不一致 | store_name_mapping映射表 | + +## 4. 数据质量校验 + +### 4.1 AI协同校验 + +``` +AI Prompt: +"请对以下物化视图进行数据质量校验: +1. 记录数是否合理(与原始表对比) +2. 金额加总是否一致(物化视图 vs 原始表) +3. 是否有NULL或异常值 +4. 门店数是否完整 +输出:校验SQL + 预期结果 + 实际结果" +``` + +### 4.2 校验清单 + +| 校验项 | SQL | 预期 | +|--------|-----|------| +| 门店数 | `SELECT count(DISTINCT store_name) FROM mv_bill_hourly WHERE month='2026-04'` | ~94家 | +| 实收总额 | `SELECT sum(received) FROM mv_bill_hourly WHERE month='2026-04'` | ~6369万 | +| 账单总数 | `SELECT sum(bills) FROM mv_bill_hourly WHERE month='2026-04'` | ~168万 | +| 异常账单占比 | `SELECT count(*) FROM mv_risk_anomaly / SELECT count(*) FROM bill_records` | <5% | +| 物化视图新鲜度 | 对比物化视图和原始表的count | 一致 | + +## 5. 门店名映射 + +### 5.1 映射表构建 + +```sql +CREATE TABLE public.store_name_mapping ( + salary_name TEXT, -- 薪资/考勤系统中的名称 + bill_name TEXT -- 账单系统中的名称 +); +``` + +### 5.2 AI协同发现映射 + +``` +AI Prompt: +"请对比以下两个数据源的门店名,找出不一致的: +- 账单系统:SELECT DISTINCT store_name FROM mv_bill_hourly +- 考勤系统:SELECT DISTINCT extractStore(department) FROM attendance_records +输出:需要映射的对照表" +``` + +### 5.3 代码中的映射查找模式 + +```typescript +// 构建查找表:同时用原名和映射名 +const staffLookup: Record = {} +for (const [store, data] of Object.entries(staffSummary)) { + staffLookup[store] = data // 原名 + const mapped = nameMap[store] + if (mapped && mapped !== store) { + staffLookup[mapped] = data // 映射名 + } +} +``` + +## 6. 输出物 + +| 输出物 | 说明 | 验证方式 | +|--------|------|---------| +| 物化视图SQL | 所有视图的CREATE语句 | psql执行成功 | +| 索引SQL | 每个视图的索引 | 查询性能达标 | +| 导入脚本 | 各数据源的导入脚本 | 导入后数据量正确 | +| 映射表 | store_name_mapping | 所有门店能匹配 | +| 数据质量报告 | 校验结果汇总 | 人工抽查确认 | +| 刷新脚本 | 物化视图刷新流程 | 执行后数据更新 | + +## 7. 关键注意事项 + +1. **先查数据再写SQL**:AI生成SQL前,先让它查实际表结构和样本数据 +2. **物化视图必须建索引**:无索引的物化视图查询比原始表还慢 +3. **刷新脚本要完整**:遗漏任何一个视图的刷新都会导致数据不一致 +4. **映射表要持续维护**:新开门店时需要补充映射 +5. **AI生成的SQL必须人工审查**:AI可能忽略业务约束(如空值处理、日期格式) diff --git a/docs/智脑实施方法论/03-指标体系与API开发.md b/docs/智脑实施方法论/07-步骤六-AI协同后端API构建与验证.md similarity index 64% rename from docs/智脑实施方法论/03-指标体系与API开发.md rename to docs/智脑实施方法论/07-步骤六-AI协同后端API构建与验证.md index 8974418..45ae40e 100644 --- a/docs/智脑实施方法论/03-指标体系与API开发.md +++ b/docs/智脑实施方法论/07-步骤六-AI协同后端API构建与验证.md @@ -1,4 +1,6 @@ -# 03 · 指标体系与API开发 +# 07 · 步骤六:AI协同后端API构建与验证 + +> 目标:AI参与API开发,逐个验证——快速交付能用的代码,不追求完美架构。 `[Delta主导,AI为主]` ## 1. 指标分层设计 @@ -12,9 +14,34 @@ L2: API层 (后端路由,SQL查询 + 业务逻辑) L3: 展示层 (前端页面,图表 + 表格) ``` -## 2. 后端API规范 +## 2. 页面与API总览 -### 2.1 路由组织 +| 页面 | 文件 | 调用的 API | +|------|------|-----------| +| 总部驾驶舱 | DashboardPage.tsx | /overview, /overview/daily, /stores/risk, /stores/priority, /tasks/loop-health, /stores/quadrant, /platform/economics, /situational-awareness/alerts, /store-expense/overview, /overview/yoy, /overview/mom, /overview/trend, /overview/profit-trend | +| 老板驾驶舱 | BossPage.tsx | /overview, /overview/daily, /store-expense/overview, /overview/profit-waterfall, /stores/risk, /stores/priority, /cost-analysis/store-overview, /store-expense/expense-structure, /overview/store-profit-ranking, /overview/profit-opportunity | +| 门店工作台 | StorePage.tsx | /stores/risk, /stores/priority, /tasks/stores/:code/daily-card, /tasks, /stores/:code/daily, /tasks/followup, /sku/attach, /sku/abc, /stores/:code, /situational-awareness/health-score, /stores/:code/meal-period, /stores/:code/category-mix, /stores/:code/cost, /stores/:code/member, /stores/:code/anomalies, /stores/:code/staffing | +| 成本分析 | CostPage.tsx | /cost/comparison, /cost/inventory, /cost/category-benchmark | +| 成本分析(Tab) | cost-analysis/*.tsx | /cost-analysis/overview, /category-comparison, /margin-deviation, /variance-top, /menu-engineering, /profitability, /pricing, /store-overview, /store-ranking, /bom-*, /packaging-*, /material-*, /data-quality, /unmatched-* | +| 费用分析(Tab) | store-expense/*.tsx | /store-expense/overview, /expense-structure, /store-ranking, /store-contribution, /break-even, /loss-diagnosis, /delivery-commission, /rent-risk, /fixed-variable, /efficiency, /store-evaluation | +| 风险监控 | RiskPage.tsx | /risk/anomaly, /risk/zero-received, /risk/cashier | +| 态势感知 | SituationalAwarenessPage.tsx | /situational-awareness/health-score, /alerts, /correlation, /forecast | +| 会员复购 | MemberPage.tsx | /member/comparison, /member/repeat | +| SKU分析 | SKUPage.tsx | /sku/abc, /sku/category | +| 菜单工程 | MenuEngineeringPage.tsx | /analytics-enhanced/menu-engineering/actions | +| 产品生命周期 | ProductLifecyclePage.tsx | /product/products, /product/reviews/overview, /product/reviews | +| BOM穿透 | BomPenetrationPage.tsx | /central-kitchen/bom-penetration | +| 分销对账 | DistributionReconciliationPage.tsx | /distribution/reconciliation | +| 生产计划 | ProductionPlanPage.tsx | /sales-driven/production-plan | +| 任务闭环 | TasksPage.tsx | /tasks | +| 数据导入 | DataImportPage.tsx | /product/import-logs, /product/quality-rules | +| 本体浏览 | OntologyPage.tsx | /tasks/ontology/* | + +> 详细的逐页面→API→SQL→数据源字段映射,见 [08-数据溯源与API全量清单.md](08-数据溯源与API全量清单.md) + +## 3. 后端API规范 + +### 3.1 路由组织 ``` server/src/routes/ diff --git a/docs/智脑实施方法论/04-前端页面开发.md b/docs/智脑实施方法论/08-步骤七-AI协同前端UIUX设计与实现.md similarity index 95% rename from docs/智脑实施方法论/04-前端页面开发.md rename to docs/智脑实施方法论/08-步骤七-AI协同前端UIUX设计与实现.md index a70ebe3..0311648 100644 --- a/docs/智脑实施方法论/04-前端页面开发.md +++ b/docs/智脑实施方法论/08-步骤七-AI协同前端UIUX设计与实现.md @@ -1,4 +1,6 @@ -# 04 · 前端页面开发 +# 08 · 步骤七:AI协同前端UIUX设计与实现 + +> 目标:AI参与页面设计,参考典型页面模板——先交付能用的,再迭代好用的。 `[Delta主导,AI为主]` ## 1. 技术栈 diff --git a/docs/智脑实施方法论/09-步骤八-数据驱动闭环优化.md b/docs/智脑实施方法论/09-步骤八-数据驱动闭环优化.md new file mode 100644 index 0000000..b503023 --- /dev/null +++ b/docs/智脑实施方法论/09-步骤八-数据驱动闭环优化.md @@ -0,0 +1,230 @@ +# 09 · 步骤八:数据驱动闭环优化 + +> 目标:上线不是终点,而是持续优化的起点。建立"数据→分析→问题→方案→实施→反馈→检验→优化"的循环。 `[Echo+Delta]` +> +> FDE角色:这一步体现FDE"把不确定的机会变成可重复的流程"的核心理念。Echo层判断改进方向,Delta层用AI生成方案。闭环转起来才是真落地,否则只是交付了一个系统。 + +## 1. 闭环模型 + +``` +┌─────────────────────────────────────────────────────┐ +│ │ +│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ +│ │ 数据采集 │───→│ 分析诊断 │───→│ 发现问题 │ │ +│ └──────────┘ └──────────┘ └──────────┘ │ +│ ↑ │ │ +│ │ ↓ │ +│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ +│ │ 优化模型 │←──│ 检验效果 │←──│ 实施改进 │ │ +│ └──────────┘ └──────────┘ └──────────┘ │ +│ ↑ │ │ +│ │ ↓ │ +│ ┌──────────┐ ┌──────────┐ │ +│ │ 参数调优 │←─────────────────│ AI协同方案 │ │ +│ └──────────┘ └──────────┘ │ +│ │ +└─────────────────────────────────────────────────────┘ +``` + +## 2. 各阶段详解 + +### 2.1 数据采集 + +| 数据源 | 频率 | 内容 | 质量要求 | +|--------|------|------|---------| +| 收银系统 | 日 | 账单明细 | 完整性>99% | +| 考勤系统 | 月 | 打卡记录 | 覆盖率>95% | +| 薪资系统 | 月 | 薪资明细 | 准确性100% | +| 费用系统 | 月 | 门店费用 | 及时性<5日 | +| 用户行为 | 实时 | 页面访问、任务执行 | — | + +### 2.2 分析诊断 + +**AI协同分析模式**: +``` +输入:本月数据 + 上月数据 + 同比数据 +AI输出: + 1. 整体经营诊断(营收/利润/成本趋势) + 2. 异常门店清单(附原因分析) + 3. 改善机会排序(按预期收益) + 4. 风险预警(下月可能恶化的门店) +``` + +**分析维度**: +- 趋势分析:月度环比、同比、近6月走势 +- 结构分析:品类占比、时段占比、平台占比 +- 对标分析:门店vs区域均值、vs标杆店 +- 归因分析:利润下降→成本率上升→食材成本上升→哪类菜品 + +### 2.3 发现问题 + +**问题分类**: + +| 类别 | 典型问题 | 发现方式 | 严重度 | +|------|---------|---------|--------| +| 经营异常 | 门店连续亏损 | 月度贡献利润<0 | 高 | +| 成本失控 | 食材成本率>45% | 月度成本分析 | 高 | +| 人力浪费 | 低谷时段人员冗余 | 客流-人力匹配 | 中 | +| 风险事件 | 异常账单激增 | 异常账单监控 | 高 | +| 执行不力 | 整改任务逾期 | 任务闭环跟踪 | 中 | +| 数据质量 | 物化视图stale | 数据校验脚本 | 低 | + +### 2.4 AI协同改进方案 + +**AI生成方案模板**: +``` +问题:XX店食材成本率45%(超标5pp) +AI分析: + 1. 原因诊断: + - 牛肉类菜品成本率58%(高于均值12pp) + - 损耗率8%(高于均值3pp) + - 采购单价上涨15% + 2. 改进建议: + - 调整牛肉类菜品BOM(预计降本3pp) + - 加强损耗管理(预计降本1pp) + - 评估替代供应商(预计降本1pp) + 3. 预期效果:成本率降至40% + 4. 跟踪指标:下周成本率、损耗率 +``` + +### 2.5 实施改进 + +| 改进类型 | 责任人 | 期限 | 跟踪方式 | +|---------|--------|------|---------| +| BOM调整 | 商品部+店长 | 7天 | 下月成本率 | +| 排班优化 | 店长 | 3天 | 客流-人力匹配度 | +| 收银规范 | 店长 | 3天 | 异常账单数 | +| 供应商切换 | 商品部 | 14天 | 采购单价 | +| 人员调整 | 区域经理 | 30天 | 人工费率 | + +### 2.6 反馈与检验 + +**检验方式**: +1. **定量对比**:改进前后指标值对比 +2. **趋势验证**:连续2-3周数据是否持续改善 +3. **对标验证**:与区域均值/标杆店对比是否缩小差距 +4. **副作用检查**:改进某指标是否导致其他指标恶化 + +**反馈机制**: +- 改进有效 → 沉淀为最佳实践 → 推广到其他门店 +- 改进无效 → 重新分析原因 → 调整方案 +- 改进有副作用 → 权衡取舍 → 优化方案 + +### 2.7 优化模型与参数 + +**需要持续优化的参数**: + +| 参数 | 初始值 | 优化依据 | 影响范围 | +|------|--------|---------|---------| +| 异常账单阈值 | 1元 | 误报率<5% | 异常账单数 | +| 高峰人手不足阈值 | 15单/人 | 业务峰值评估 | 客流-人力匹配 | +| 低谷冗余阈值 | 3人 | 门店规模调整 | 客流-人力匹配 | +| 风险评级阈值 | 红/黄/绿规则 | 管理层确认 | 门店评级 | +| 预警触发条件 | 各类规则 | 误报率/漏报率 | 预警数量 | +| 任务期限 | 3/7/14天 | 历史完成率 | 任务逾期率 | + +## 3. 闭环运转机制 + +### 3.1 日循环 + +``` +每日: + - 收银数据自动入库 + - 日度概览自动更新 + - 营收异动预警检查 + - 店长查看日报卡 + - 当日任务执行与反馈 +``` + +### 3.2 周循环 + +``` +每周: + - 区域经理周检 + - 周度趋势分析 + - 任务完成率统计 + - 预警处理情况汇总 + - AI协同生成周报 +``` + +### 3.3 月循环 + +``` +每月: + - 月度数据导入(考勤/薪资/费用) + - 物化视图刷新 + - 月度经营分析(老板驾驶舱) + - 门店评级更新 + - 任务闭环健康度评估 + - AI协同生成月度诊断报告 + - 参数调优评审 + - 最佳经验沉淀与推广 +``` + +## 4. AI协同优化模式 + +### 4.1 AI角色 + +| 阶段 | AI能力 | 人的角色 | +|------|--------|---------| +| 分析诊断 | 自动生成诊断报告 | 审查判断 | +| 发现问题 | 异常检测、趋势预警 | 确认严重度 | +| 改进方案 | 生成方案草案 | 决策取舍 | +| 效果检验 | 对比分析、副作用检测 | 确认结论 | +| 经验沉淀 | 提炼最佳实践 | 确认可推广性 | + +### 4.2 AI Prompt示例 + +``` +"基于以下月度数据,请生成经营诊断报告: +- 本月营收6420万,环比下降3% +- 13家门店亏损,比上月增加2家 +- 食材成本率35.3%,上升1.2pp +- 人工费率18.5%,上升0.5pp +- 异常账单3.2万笔,占比1.9% +请输出: +1. 整体诊断(3-5个关键发现) +2. 重点关注门店(附原因) +3. 改进建议(按预期收益排序) +4. 下月风险预警" +``` + +## 5. 持续优化的关键指标 + +### 5.1 系统健康度 + +| 指标 | 目标 | 监控频率 | +|------|------|---------| +| API平均响应时间 | <500ms | 实时 | +| 物化视图刷新耗时 | <5min | 月度 | +| 数据质量校验通过率 | >99% | 月度 | +| 页面加载时间 | <3s | 实时 | + +### 5.2 业务价值度 + +| 指标 | 目标 | 监控频率 | +|------|------|---------| +| 老板驾驶舱月活 | >20次/月 | 月度 | +| 店长工作台日活 | >80%店长 | 日度 | +| 预警处理率 | >90% | 月度 | +| 任务完成率 | >70% | 月度 | +| 整改有效率 | >60% | 月度 | + +### 5.3 闭环成熟度 + +| 等级 | 特征 | 目标 | +|------|------|------| +| L1 起步 | 有数据、无分析 | — | +| L2 可视 | 有Dashboard、无预警 | 本项目已达到 | +| L3 预警 | 有预警、有任务 | 目标状态 | +| L4 闭环 | 任务→执行→反馈→检验 | 持续优化中 | +| L5 智能 | AI自动诊断+推荐方案 | 长期目标 | + +## 6. 关键注意事项 + +1. **闭环不是一次性项目**:是持续运转的管理机制,需要组织保障 +2. **数据质量是生命线**:垃圾数据进→垃圾结论出→错误决策→失去信任 +3. **不要追求完美模型**:先跑通闭环,再逐步优化参数 +4. **人的参与不可少**:AI辅助决策,人做最终判断 +5. **经验沉淀最重要**:每次改进的有效经验要沉淀为可复制的最佳实践 +6. **定期回顾参数**:业务变化后,预警阈值和评级规则需要调整 diff --git a/docs/智脑实施方法论/01-项目概述与架构.md b/docs/智脑实施方法论/10-技术参考-项目概述与架构.md similarity index 97% rename from docs/智脑实施方法论/01-项目概述与架构.md rename to docs/智脑实施方法论/10-技术参考-项目概述与架构.md index 0e382f8..943e92a 100644 --- a/docs/智脑实施方法论/01-项目概述与架构.md +++ b/docs/智脑实施方法论/10-技术参考-项目概述与架构.md @@ -1,8 +1,8 @@ -# 01 · 项目概述与架构 +# 10 · 技术参考:项目概述与架构 ## 1. 项目背景 -为连锁餐饮企业(西部马华,100+门店)构建数据分析智脑平台,覆盖: +为连锁经营企业(西部马华,100+门店)构建数据分析智脑平台,覆盖: - **老板驾驶舱**:门店风险评级、营收概览、平台经济性 - **门店分级**:红/黄/绿三色风险评级与明细 - **态势感知**:健康度评分、自动化预警、跨模块关联分析、趋势预测 diff --git a/docs/智脑实施方法论/05-部署与运维.md b/docs/智脑实施方法论/11-技术参考-部署与运维.md similarity index 98% rename from docs/智脑实施方法论/05-部署与运维.md rename to docs/智脑实施方法论/11-技术参考-部署与运维.md index 13ed8f1..b9e7044 100644 --- a/docs/智脑实施方法论/05-部署与运维.md +++ b/docs/智脑实施方法论/11-技术参考-部署与运维.md @@ -1,4 +1,4 @@ -# 05 · 部署与运维 +# 11 · 技术参考:部署与运维 ## 1. 部署脚本 diff --git a/docs/智脑实施方法论/06-调试排查手册.md b/docs/智脑实施方法论/12-技术参考-调试排查手册.md similarity index 99% rename from docs/智脑实施方法论/06-调试排查手册.md rename to docs/智脑实施方法论/12-技术参考-调试排查手册.md index b55d008..4622b13 100644 --- a/docs/智脑实施方法论/06-调试排查手册.md +++ b/docs/智脑实施方法论/12-技术参考-调试排查手册.md @@ -1,4 +1,4 @@ -# 06 · 调试排查手册 +# 12 · 技术参考:调试排查手册 ## 1. 问题分类与排查流程 diff --git a/docs/智脑实施方法论/07-通用方法论.md b/docs/智脑实施方法论/13-技术参考-通用方法论与避坑指南.md similarity index 98% rename from docs/智脑实施方法论/07-通用方法论.md rename to docs/智脑实施方法论/13-技术参考-通用方法论与避坑指南.md index 1f1eb80..d8c4de5 100644 --- a/docs/智脑实施方法论/07-通用方法论.md +++ b/docs/智脑实施方法论/13-技术参考-通用方法论与避坑指南.md @@ -1,4 +1,4 @@ -# 07 · 通用方法论 +# 13 · 技术参考:通用方法论与避坑指南 > 从智脑项目实践中提炼的核心原则和可复制方法论,适用于类似的连锁企业数据产品建设。 diff --git a/docs/智脑实施方法论/14-技术参考-数据溯源与API全量清单.md b/docs/智脑实施方法论/14-技术参考-数据溯源与API全量清单.md new file mode 100644 index 0000000..fce741b --- /dev/null +++ b/docs/智脑实施方法论/14-技术参考-数据溯源与API全量清单.md @@ -0,0 +1,3504 @@ +# 14 · 技术参考:全页面数据溯源审计报告 + +> 目标:逐页面、逐指标追溯显示名称 → API → SQL → 数据源表字段,标出跨页面重复指标口径是否一致。 + +## 一、页面与 API 总览 + +| 页面 | 文件 | 调用的 API | +|------|------|-----------| +| 总部驾驶舱 | DashboardPage.tsx | /overview, /overview/daily, /stores/risk, /stores/priority, /tasks/loop-health, /stores/quadrant, /platform/economics, /situational-awareness/alerts, /store-expense/overview, /overview/yoy, /overview/mom, /overview/trend, /overview/profit-trend | +| 老板驾驶舱 | BossPage.tsx | /overview, /overview/daily, /store-expense/overview, /overview/profit-waterfall, /stores/risk, /stores/priority, /cost-analysis/store-overview, /store-expense/expense-structure, /overview/store-profit-ranking, /overview/profit-opportunity | +| 门店工作台 | StorePage.tsx | /stores/risk, /stores/priority, /tasks/stores/:code/daily-card, /tasks, /stores/:code/daily, /tasks/followup, /sku/attach, /sku/abc, /stores/:code, /situational-awareness/health-score, /stores/:code/meal-period, /stores/:code/category-mix, /stores/:code/cost, /stores/:code/member, /stores/:code/anomalies, /stores/:code/staffing | +| 成本分析 | CostPage.tsx | /cost/comparison, /cost/inventory, /cost/category-benchmark | +| 成本分析(Tab) | cost-analysis/*.tsx | /cost-analysis/overview, /category-comparison, /margin-deviation, /variance-top, /menu-engineering, /profitability, /pricing, /store-overview, /store-ranking, /bom-*, /packaging-*, /material-*, /data-quality, /unmatched-* | +| 费用分析(Tab) | store-expense/*.tsx | /store-expense/overview, /expense-structure, /store-ranking, /store-contribution, /break-even, /loss-diagnosis, /delivery-commission, /rent-risk, /fixed-variable, /efficiency, /store-evaluation | +| 风险监控 | RiskPage.tsx | /risk/anomaly, /risk/zero-received, /risk/cashier | +| 会员复购 | MemberPage.tsx | /member/comparison, /member/repeat | +| SKU分析 | SKUPage.tsx | /sku/abc, /sku/category | +| 菜单工程 | MenuEngineeringPage.tsx | /analytics-enhanced/menu-engineering/actions | +| 产品生命周期 | ProductLifecyclePage.tsx | /product/products, /product/reviews/overview, /product/reviews | +| BOM穿透 | BomPenetrationPage.tsx | /central-kitchen/bom-penetration | +| 分销对账 | DistributionReconciliationPage.tsx | /distribution/reconciliation | +| 生产计划 | ProductionPlanPage.tsx | /sales-driven/production-plan | +| 任务闭环 | TasksPage.tsx | /tasks | +| 数据导入 | DataImportPage.tsx | /product/import-logs, /product/quality-rules | +| 本体浏览 | OntologyPage.tsx | /tasks/ontology/* | + +--- + +## 二、页面1:总部驾驶舱 DashboardPage + +> 无Tab,用 CollapsibleSection 分区。共调用13个API。 + +### 区块①:门店风险分布条 + +| 显示指标 | 前端变量 | API | API字段 | SQL来源 | 数据源表.字段 | +|---------|---------|-----|---------|---------|-------------| +| 红色门店数 | `riskSummary['红色']` | /stores/risk | `risk_level` | `SELECT * FROM mv_store_risk_rating_monthly` | analytics.mv_store_risk_rating_monthly.risk_level | +| 黄色门店数 | `riskSummary['黄色']` | 同上 | 同上 | 同上 | 同上 | +| 绿色门店数 | `riskSummary['绿色']` | 同上 | 同上 | 同上 | 同上 | +| 总门店数 | `totalStores = riskRows.length` | 同上 | 行数 | 同上 | 同上 | + +### 区块②:态势感知预警 + +| 显示指标 | 前端变量 | API | API字段 | SQL来源 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 红色预警数 | `alertSummary.red` | /situational-awareness/alerts | `red` | 5类预警合并: 营收异动/成本异动/人力异动/平台依赖/任务逾期 | mv_daily_revenue, dish_cost_analysis_summary, salary_detail_records, mv_store_platform_economics_monthly, store_task | +| 橙色预警数 | `alertSummary.orange` | 同上 | `orange` | 同上 | 同上 | +| 预警总数 | `alertSummary.total` | 同上 | `total` | 同上 | 同上 | +| 预警列表(前6条) | `alerts.slice(0,6)` | 同上 | `alerts[]` | 同上,每条含 title/detail/level | 同上 | + +### 区块③:经营指标 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表.字段 | +|---------|---------|-----|---------|---------|-------------| +| 营业收入 | `od?.consumption` | /overview | `consumption` | `sum(consumption)` | analytics.bill_fact.consumption | +| 优惠 | `od?.discount` | /overview | `discount` | `sum(discount_total)` | analytics.bill_fact.discount_total | +| 实收 | `od?.received` | /overview | `received` | `sum(received_total)` | analytics.bill_fact.received_total | +| 账单数 | `od?.bill_count` | /overview | `bill_count` | `count(*)` | analytics.bill_fact | +| 客单价 | `od?.avg_bill_value` | /overview | `avg_bill_value` | `avg(received_total)` | analytics.bill_fact.received_total | +| P0+P1门店数 | `p0p1Stores.length` | /stores/priority | 行数过滤 | `action_priority LIKE 'P0%' OR 'P1%'` | analytics.mv_store_action_priority_deep_monthly.action_priority | +| 实收环比趋势 | `trendReceived` | /overview/daily | 前端计算 | `(last7days.received - prev7days.received) / prev7days.received * 100` | analytics.mv_overview_daily.received | +| 账单数环比趋势 | `trendBills` | /overview/daily | 前端计算 | 同上,用 bill_count | analytics.mv_overview_daily.bill_count | +| 客单价环比趋势 | `trendAvgBill` | /overview/daily | 前端计算 | `last7.avg - prev7.avg` | analytics.mv_overview_daily | + +### 区块④:运营指标 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表.字段 | +|---------|---------|-----|---------|---------|-------------| +| 优惠率 | `od?.discount_rate_pct` | /overview | `discount_rate_pct` | `avg(discount_total / consumption * 100)` per bill | analytics.bill_fact.discount_total, consumption | +| 理论毛利率 | `od?.theoretical_margin_pct` | /overview | `theoretical_margin_pct` | `sum(theoretical_profit) / sum(received_total) * 100` | analytics.bill_fact.theoretical_profit, received_total | +| 会员占比 | `od?.member_share_pct` | /overview | `member_share_pct` | `sum(received_total) FILTER(member_id非空) / sum(received_total) * 100` | analytics.bill_fact.received_total, member_id | + +### 区块⑤:同比/环比对比 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 实收同比% | `yoyData_.received_change_pct` | /overview/yoy | `yoy.received_change_pct` | `(当月received - 去年同月received) / |去年同月received| * 100` | analytics.mv_overview_monthly.received | +| 实收环比% | `momData_.received_change_pct` | /overview/mom | `mom.received_change_pct` | `(当月received - 上月received) / |上月received| * 100` | analytics.mv_overview_monthly.received | +| 账单数同比% | `yoyData_.bill_count_change_pct` | /overview/yoy | `yoy.bill_count_change_pct` | 同上,用 bill_count | analytics.mv_overview_monthly.bill_count | +| 账单数环比% | `momData_.bill_count_change_pct` | /overview/mom | `mom.bill_count_change_pct` | 同上 | analytics.mv_overview_monthly.bill_count | +| 客单价同比% | `yoyData_.avg_bill_value_change_pct` | /overview/yoy | `yoy.avg_bill_value_change_pct` | 同上,用 avg_bill_value | analytics.mv_overview_monthly.avg_bill_value | +| 客单价环比% | `momData_.avg_bill_value_change_pct` | /overview/mom | `mom.avg_bill_value_change_pct` | 同上 | analytics.mv_overview_monthly.avg_bill_value | +| 优惠率同比变化 | `yoyData_.discount_rate_change` | /overview/yoy | `yoy.discount_rate_change` | `当月discount_rate_pct - 去年同月discount_rate_pct` | analytics.mv_overview_monthly.discount_rate_pct | +| 优惠率环比变化 | `momData_.discount_rate_change` | /overview/mom | `mom.discount_rate_change` | `当月 - 上月` | analytics.mv_overview_monthly.discount_rate_pct | + +### 区块⑥:利润与成本 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 理论贡献利润 | `ex.theoretical_net_profit` | /store-expense/overview | `theoretical_net_profit` | `sum(received) FILTER(费用匹配) - sum(theoretical_cost) - sum(operating_expense)` | mv_store_risk_rating_monthly.received + mv_store_operating_expense_monthly | +| 理论贡献率 | `ex.theoretical_net_margin_pct` | 同上 | `theoretical_net_margin_pct` | `theoretical_net_profit / matched_received * 100` | 同上 | +| 实际贡献利润 | `ex.actual_net_profit` | 同上 | `actual_net_profit` | `sum(received) FILTER(费用匹配) - sum(actual_food_cost) - sum(operating_expense)` | 同上 | +| 实际贡献率 | `ex.actual_net_margin_pct` | 同上 | `actual_net_margin_pct` | `actual_net_profit / matched_received * 100` | 同上 | +| 盈利门店数 | `ex.profitable_stores` | 同上 | `profitable_stores` | `count(*) FILTER(actual_store_contribution > 0)` | 同上 | +| 亏损门店数 | `ex.loss_stores` | 同上 | `loss_stores` | `count(*) FILTER(actual_store_contribution <= 0 AND received > 0)` | 同上 | +| 食材成本 | `ex.total_food_cost` | 同上 | `total_food_cost` | `sum(actual_food_cost)` | mv_store_operating_expense_monthly.actual_food_cost | +| 实际食材成本率 | `ex.actual_food_cost_rate_pct` | 同上 | `actual_food_cost_rate_pct` | `sum(actual_food_cost) / matched_received * 100` | 同上 | +| 理论食材成本率 | `ex.theoretical_food_cost_rate_pct` | 同上 | `theoretical_food_cost_rate_pct` | `sum(theoretical_cost) / matched_received * 100` | 同上 | +| 经营费用 | `ex.total_expense` | 同上 | `total_expense` | `sum(operating_expense)` | mv_store_operating_expense_monthly.operating_expense | +| 费用率 | `ex.overall_expense_rate_pct` | 同上 | `overall_expense_rate_pct` | `sum(operating_expense) / matched_received * 100` | 同上 | +| 人工费用 | `ex.total_wage` | 同上 | `total_wage` | `sum(wage_expense)` | mv_store_operating_expense_monthly.wage_expense | +| 人工费率 | `ex.overall_wage_rate_pct` | 同上 | `overall_wage_rate_pct` | `sum(wage_expense) / matched_received * 100` | 同上 | +| 房租费用 | `ex.total_rent` | 同上 | `total_rent` | `sum(rent_expense)` | mv_store_operating_expense_monthly.rent_expense | +| 房租费率 | `ex.overall_rent_rate_pct` | 同上 | `overall_rent_rate_pct` | `sum(rent_expense) / matched_received * 100` | 同上 | +| 水电费用 | `ex.total_utility` | 同上 | `total_utility` | `sum(utility_expense)` | mv_store_operating_expense_monthly.utility_expense | +| 水电费率 | `ex.overall_utility_rate_pct` | 同上 | `overall_utility_rate_pct` | `sum(utility_expense) / matched_received * 100` | 同上 | +| 外卖佣金 | `ex.total_commission` | 同上 | `total_commission` | `sum(delivery_commission_expense)` | mv_store_operating_expense_monthly.delivery_commission_expense | +| 外卖佣金占实收 | 前端计算 | 同上 | 前端除法 | `total_commission / total_received * 100` | 同上 | + +### 区块⑦:闭环健康度 + +| 显示指标 | 前端变量 | API | API字段 | 数据源表 | +|---------|---------|-----|---------|---------| +| 综合得分 | `loopScore` (前端5项平均) | /tasks/loop-health | 5个rate字段 | analytics.mv_loop_health | +| 任务生成率 | `lh.task_generation_rate` | 同上 | `task_generation_rate` | analytics.mv_loop_health.task_generation_rate | +| 店长执行率 | `lh.store_execution_rate` | 同上 | `store_execution_rate` | analytics.mv_loop_health.store_execution_rate | +| 区域周检率 | `lh.weekly_check_rate` | 同上 | `weekly_check_rate` | analytics.mv_loop_health.weekly_check_rate | +| 月度验收率 | `lh.monthly_review_rate` | 同上 | `monthly_review_rate` | analytics.mv_loop_health.monthly_review_rate | +| 经验推广率 | `lh.practice_promotion_rate` | 同上 | `practice_promotion_rate` | analytics.mv_loop_health.practice_promotion_rate | + +### 区块⑧:图表区 - 日度实收趋势 + +| 显示指标 | 前端变量 | API | API字段 | 数据源表 | +|---------|---------|-----|---------|---------| +| 日度实收折线 | `dailyRows[].received` | /overview/daily | `received` | analytics.mv_overview_daily.received (无scope) 或 bill_fact (有scope) | +| 日期 | `dailyRows[].business_date` | 同上 | `business_date` | analytics.mv_overview_daily.business_date | + +### 区块⑨:图表区 - 门店风险分级分布 + +| 显示指标 | 前端变量 | API | API字段 | 数据源表 | +|---------|---------|-----|---------|---------| +| 风险分布饼图 | `riskPieData` | /stores/risk | `risk_level` | analytics.mv_store_risk_rating_monthly.risk_level | + +### 区块⑩:图表区 - 门店经营象限 + +| 显示指标 | 前端变量 | API | API字段 | 数据源表 | +|---------|---------|-----|---------|---------| +| X轴: 日均实收 | `quadrantScatterData.x = r.avg_daily_received` | /stores/quadrant | `avg_daily_received` | analytics.mv_store_benchmark_composite_monthly.avg_daily_received | +| Y轴: 毛利率 | `quadrantScatterData.y = r.theoretical_margin_pct` | 同上 | `theoretical_margin_pct` | analytics.mv_store_benchmark_composite_monthly.theoretical_margin_pct | +| 象限分类 | `r.management_quadrant` | 同上 | `management_quadrant` | analytics.mv_store_benchmark_composite_monthly.management_quadrant | + +### 区块⑪:图表区 - P0/P1实收覆盖瀑布图 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| P0门店实收 | `p0Received` | /stores/priority | `received` | `sum(received) FILTER(action_priority LIKE 'P0%')` | analytics.mv_store_action_priority_deep_monthly.received | +| P1门店实收 | `p1Received` | /stores/priority | `received` | `sum(received) FILTER(action_priority LIKE 'P1%')` | 同上 | +| 其他门店实收 | `otherReceived = od.received - p0Received - p1Received` | /overview + /stores/priority | 前端计算 | `总实收 - P0 - P1` | bill_fact + mv_store_action_priority_deep_monthly | +| 合计实收 | `od?.received` | /overview | `received` | `sum(received_total)` | analytics.bill_fact.received_total | + +### 区块⑫:图表区 - 平台成本率TOP15 + +| 显示指标 | 前端变量 | API | API字段 | 数据源表 | +|---------|---------|-----|---------|---------| +| 美团成本率 | `r.meituan_cost_rate_pct` | /platform/economics | `meituan_cost_rate_pct` | analytics.mv_store_platform_economics_monthly.meituan_cost_rate_pct | +| 饿了么成本率 | `r.eleme_cost_rate_pct` | 同上 | `eleme_cost_rate_pct` | analytics.mv_store_platform_economics_monthly.eleme_cost_rate_pct | +| 抖音成本率 | `r.douyin_cost_rate_pct` | 同上 | `douyin_cost_rate_pct` | analytics.mv_store_platform_economics_monthly.douyin_cost_rate_pct | + +### 区块⑬:月度经营趋势 + +| 显示指标 | 前端变量 | API | API字段 | 数据源表 | +|---------|---------|-----|---------|---------| +| 月度实收折线 | `trendRows[].received` | /overview/trend | `received` | analytics.mv_overview_monthly.received | +| 月度账单数柱状 | `trendRows[].bill_count` | 同上 | `bill_count` | analytics.mv_overview_monthly.bill_count | + +### 区块⑭:利润趋势 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 月度实收 | `profitTrendRows[].received` | /overview/profit-trend | `received` | `sum(r.received)` | v_store_scorecard.received | +| 食材成本 | `profitTrendRows[].food_cost` | 同上 | `food_cost` | `sum(COALESCE(e.actual_food_cost, 0))` | mv_store_operating_expense_monthly.actual_food_cost | +| 人工 | `profitTrendRows[].wage` | 同上 | `wage` | `sum(COALESCE(e.wage_expense, 0))` | mv_store_operating_expense_monthly.wage_expense | +| 房租 | `profitTrendRows[].rent` | 同上 | `rent` | `sum(COALESCE(e.rent_expense, 0))` | mv_store_operating_expense_monthly.rent_expense | +| 水电 | `profitTrendRows[].utility` | 同上 | `utility` | `sum(COALESCE(e.utility_expense, 0))` | mv_store_operating_expense_monthly.utility_expense | +| 贡献利润 | `profitTrendRows[].store_contribution` | 同上 | `store_contribution` | `sum(r.received) - sum(food_cost) - sum(operating_expense)` | 同上 | + +> ⚠️ **profit-trend 口径注意**:该API用 `v_store_scorecard` JOIN `mv_store_operating_expense_monthly`,WHERE `e.report_month >= $1 AND <= $2`。LEFT JOIN后WHERE过滤掉无费用门店(e.report_month IS NULL),所以实际只含费用匹配门店,口径与 store-expense/overview 一致。但COALESCE(...,0)是多余的(不会出现NULL行)。 + +### 区块⑮:P0/P1重点整改门店列表 + +| 显示指标 | 前端变量 | API | API字段 | 数据源表 | +|---------|---------|-----|---------|---------| +| 门店名 | `r.store_name` | /stores/priority | `store_name` | analytics.mv_store_action_priority_deep_monthly.store_name | +| 优先级 | `r.action_priority` | 同上 | `action_priority` | 同上 | +| 问题数 | `r.problem_count` | 同上 | `problem_count` | 同上 | +| 问题组合 | `r.problem_combination` | 同上 | `problem_combination` | 同上 | +| 实收 | `r.received` | 同上 | `received` | 同上 | + +--- + +## 三、跨页面核心指标溯源与口径对比 + +### 3.1 营业收入(消费金额) + +| 页面 | 前端变量 | API | API字段 | SQL来源 | 数据源表.字段 | +|------|---------|-----|---------|---------|-------------| +| 总部驾驶舱 | `od?.consumption` | /overview | `consumption` | `sum(consumption)` from bill_fact | analytics.bill_fact.consumption | +| 老板驾驶舱 | `od?.consumption` | /overview | `consumption` | 同上 | 同上 | +| 费用总览Tab | `ov.total_consumption` | /store-expense/overview | `total_consumption` | `sum(consumption)` from bill_fact CTE | analytics.bill_fact.consumption | + +**口径:一致 ✅** — 三个页面均来自 `analytics.bill_fact.consumption` 的月度汇总。 + +### 3.2 优惠 + +| 页面 | 前端变量 | API | API字段 | SQL来源 | 数据源表.字段 | +|------|---------|-----|---------|---------|-------------| +| 总部驾驶舱 | `od?.discount` | /overview | `discount` | `sum(discount_total)` from bill_fact | analytics.bill_fact.discount_total | +| 老板驾驶舱 | `od?.discount` | /overview | `discount` | 同上 | 同上 | +| 费用总览Tab | `ov.total_discount` | /store-expense/overview | `total_discount` | `sum(discount_total)` from bill_fact CTE | analytics.bill_fact.discount_total | + +**口径:一致 ✅**(已修复,BossPage 之前用 `ex?.total_discount` 也一致) + +### 3.3 实收 + +| 页面 | 前端变量 | API | API字段 | SQL来源 | 数据源表.字段 | +|------|---------|-----|---------|---------|-------------| +| 总部驾驶舱 | `od?.received` | /overview | `received` | `sum(received_total)` from bill_fact | analytics.bill_fact.received_total | +| 老板驾驶舱 | `od?.received` | /overview | `received` | 同上 | 同上 | +| 费用总览Tab | `ov.total_received` | /store-expense/overview | `total_received` | `sum(r.received)` from mv_store_risk_rating_monthly | analytics.mv_store_risk_rating_monthly.received | +| 利润瀑布 | `wf.received` | /overview/profit-waterfall | `received` | `sum(r.received)` from mv_store_risk_rating_monthly | analytics.mv_store_risk_rating_monthly.received | + +**口径:一致 ✅**(已修复)— `bill_fact.received_total` 汇总和 `mv_store_risk_rating_monthly.received` 汇总结果相同(均为 64,409,339.09),因为后者物化视图就来自前者。 + +### 3.4 账单数 + +| 页面 | 前端变量 | API | API字段 | SQL来源 | 数据源表.字段 | +|------|---------|-----|---------|---------|-------------| +| 总部驾驶舱 | `od?.bill_count` | /overview | `bill_count` | `count(*)` from bill_fact | analytics.bill_fact | +| 老板驾驶舱 | `ex?.total_bills` | /store-expense/overview | `total_bills` | `sum(bill_count)` from mv_store_risk_rating_monthly | analytics.mv_store_risk_rating_monthly.bill_count | + +**口径:一致 ✅** — 值均为 1,682,360。 + +### 3.5 客单价 + +| 页面 | 前端变量 | API | API字段 | 计算方式 | +|------|---------|-----|---------|---------| +| 总部驾驶舱 | `od?.avg_bill_value` | /overview | `avg_bill_value` | `avg(received_total)` from bill_fact = 38.29 | +| 老板驾驶舱 | `ex?.avg_bill_value` | /store-expense/overview | `avg_bill_value` | `sum(received)/sum(bill_count)` = 38.29 | + +**口径:一致 ✅** — 数学结果相同。 + +### 3.6 优惠率 + +| 页面 | 前端变量 | API | API字段 | 计算方式 | +|------|---------|-----|---------|---------| +| 总部驾驶舱 | `od?.discount_rate_pct` | /overview | `discount_rate_pct` | `avg(discount_total/consumption*100)` from bill_fact = 19.52% | +| 老板驾驶舱 | 无(不显示此指标) | - | - | - | + +**口径:N/A** — 仅总部驾驶舱显示。 + +### 3.7 理论毛利率 + +| 页面 | 前端变量 | API | API字段 | 计算方式 | +|------|---------|-----|---------|---------| +| 总部驾驶舱 | `od?.theoretical_margin_pct` | /overview | `theoretical_margin_pct` | `sum(theoretical_profit)/sum(received)*100` from bill_fact = 61.84% | + +**口径:N/A** — 仅总部驾驶舱显示。(已修复,之前硬编码为0) + +### 3.8 会员占比 + +| 页面 | 前端变量 | API | API字段 | 计算方式 | +|------|---------|-----|---------|---------| +| 总部驾驶舱 | `od?.member_share_pct` | /overview | `member_share_pct` | `sum(received_total) FILTER(member_id非空)/sum(received_total)*100` = 14.25% | + +**口径:N/A** — 仅总部驾驶舱显示。(已修复,之前硬编码为0) + +### 3.9 门店贡献利润(实际) + +| 页面 | 前端变量 | API | API字段 | 计算方式 | 值 | +|------|---------|-----|---------|---------|-----| +| 总部驾驶舱 | `ex?.actual_net_profit` | /store-expense/overview | `actual_net_profit` | `sum(received) FILTER(费用匹配) - sum(food_cost) - sum(operating_expense)` | 6,982,110.42 | +| 老板驾驶舱(指标卡) | `ex?.actual_net_profit` | /store-expense/overview | `actual_net_profit` | 同上 | 6,982,110.42 | +| 老板驾驶舱(瀑布图) | `wf.store_contribution` | /overview/profit-waterfall | `store_contribution` | `sum(received) FILTER(has_expense) - sum(food_cost) - sum(operating_expense)` | 6,982,110.42 | + +**口径:一致 ✅**(已修复)— 瀑布图已改为仅含 has_expense 门店。 + +### 3.10 贡献率(实际) + +| 页面 | 前端变量 | API | API字段 | 计算方式 | 值 | +|------|---------|-----|---------|---------|-----| +| 总部驾驶舱 | `ex?.actual_net_margin_pct` | /store-expense/overview | `actual_net_margin_pct` | `(matched_received - food_cost - operating_expense)/matched_received*100` | 10.96% | +| 老板驾驶舱(指标卡) | `ex?.actual_net_margin_pct` | /store-expense/overview | `actual_net_margin_pct` | 同上 | 10.96% | +| 老板驾驶舱(瀑布图) | 前端计算 `wf.store_contribution/wf.received*100` | /overview/profit-waterfall | 前端除法 | `6982110/63687977*100` | 10.96% | + +**口径:一致 ✅**(已修复)— 瀑布图 received 和 contribution 均改为仅含 has_expense 门店。 + +### 3.11 食材成本 + +| 页面 | 前端变量 | API | API字段 | 计算方式 | +|------|---------|-----|---------|---------| +| 总部驾驶舱 | `ex?.total_food_cost` | /store-expense/overview | `total_food_cost` | `sum(actual_food_cost)` from mv_store_operating_expense_monthly | +| 老板驾驶舱(瀑布图) | `wf.food_cost` | /overview/profit-waterfall | `food_cost` | `sum(COALESCE(actual_food_cost,0))` — 含2家0值门店 | +| 费用总览Tab | `ov.total_food_cost` | /store-expense/overview | `total_food_cost` | 同总部 | + +**口径:一致 ✅** — 2家无费用门店的 food_cost 为 NULL,`sum(NULL)` 忽略,`sum(COALESCE(NULL,0))` 加0,结果相同。 + +### 3.12 食材成本率 + +| 页面 | 前端变量 | API | API字段 | 计算方式 | 值 | +|------|---------|-----|---------|---------|-----| +| 总部驾驶舱 | `ex?.actual_food_cost_rate_pct` | /store-expense/overview | `actual_food_cost_rate_pct` | `sum(food_cost)/matched_received*100` | 35.26% | +| 老板驾驶舱(瀑布图) | 前端计算 `wf.food_cost/wf.received*100` | /overview/profit-waterfall | 前端除法 | `22459074/63687977*100` | 35.26% | + +**口径:一致 ✅**(已修复)— 瀑布图 received 改为 matched 口径。 + +### 3.13 经营费用 + +| 页面 | 前端变量 | API | API字段 | 计算方式 | +|------|---------|-----|---------|---------| +| 总部驾驶舱 | `ex?.total_expense` | /store-expense/overview | `total_expense` | `sum(operating_expense)` — NULL被sum忽略 | +| 老板驾驶舱(瀑布图) | `wf.total_expense` | /overview/profit-waterfall | `total_expense` | `sum(COALESCE(operating_expense,0))` — 2家为0 | +| 费用总览Tab | `ov.total_expense` | /store-expense/overview | `total_expense` | 同总部 | + +**口径:一致 ✅** — sum忽略NULL vs COALESCE加0,结果相同。 + +### 3.14 费用率 + +| 页面 | 前端变量 | API | API字段 | 计算方式 | 值 | +|------|---------|-----|---------|---------|-----| +| 总部驾驶舱 | `ex?.overall_expense_rate_pct` | /store-expense/overview | `overall_expense_rate_pct` | `sum(operating_expense)/matched_received*100` | 53.77% | +| 老板驾驶舱(瀑布图) | 前端计算 `wf.total_expense/wf.received*100` | /overview/profit-waterfall | 前端除法 | `34246793/63687977*100` | 53.77% | +| 费用总览Tab | `ov.overall_expense_rate_pct` | /store-expense/overview | `overall_expense_rate_pct` | 同总部 | 53.77% | + +**口径:一致 ✅**(已修复)— 瀑布图分母改为 matched 口径。 + +### 3.15 人工费用 / 人工费率 + +| 页面 | 前端变量 | API | API字段 | 计算方式 | +|------|---------|-----|---------|---------| +| 总部驾驶舱 | `ex?.total_wage` / `ex?.overall_wage_rate_pct` | /store-expense/overview | `total_wage` / `overall_wage_rate_pct` | `sum(wage_expense)` / `sum(wage)/matched_received*100` | +| 老板驾驶舱(瀑布图) | `wf.wage` | /overview/profit-waterfall | `wage` | `sum(COALESCE(wage_expense,0))` | +| 费用总览Tab | `ov.total_wage` / `ov.overall_wage_rate_pct` | /store-expense/overview | 同总部 | 同总部 | + +**金额口径:一致 ✅** — sum忽略NULL vs COALESCE加0结果相同。 +**费率口径:一致 ✅**(已修复)— 瀑布图 received 改为 matched 口径后,前端除法分母一致。 + +### 3.16 房租费用 / 房租费率 + +同 3.15,金额一致,费率已修复一致。 + +### 3.17 水电费用 / 水电费率 + +同 3.15,金额一致,费率已修复一致。 + +### 3.18 外卖佣金 + +| 页面 | 前端变量 | API | API字段 | 计算方式 | +|------|---------|-----|---------|---------| +| 总部驾驶舱 | `ex?.total_commission` | /store-expense/overview | `total_commission` | `sum(delivery_commission_expense)` | +| 老板驾驶舱(瀑布图) | `wf.commission` | /overview/profit-waterfall | `commission` | `sum(COALESCE(delivery_commission_expense,0))` | + +**口径:一致 ✅** — 金额相同。 + +### 3.19 门店数 + +| 页面 | 前端变量 | API | API字段 | 计算方式 | +|------|---------|-----|---------|---------| +| 总部驾驶舱 | `riskRows.length` | /stores/risk | count of rows | `count(*)` from mv_store_risk_rating_monthly | +| 老板驾驶舱 | `ex?.total_stores` | /store-expense/overview | `total_stores` | `count(*)` from full_scope (mv_store_risk_rating_monthly) | + +**口径:一致 ✅** — 均为94家。 + +### 3.20 盈利/亏损门店数 + +| 页面 | 前端变量 | API | API字段 | 计算方式 | +|------|---------|-----|---------|---------| +| 总部驾驶舱 | `ex?.profitable_stores` / `ex?.loss_stores` | /store-expense/overview | `profitable_stores` / `loss_stores` | `count(*) FILTER(actual_store_contribution>0)` / `count(*) FILTER(<=0 AND received>0)` | +| 老板驾驶舱 | 同上 | 同上 | 同上 | 同上 | + +**口径:一致 ✅** — 盈利78家/亏损13家。 + +### 3.21 门店风险分布 + +| 页面 | 前端变量 | API | 数据源 | +|------|---------|-----|--------| +| 总部驾驶舱 | `riskSummary` | /stores/risk | analytics.mv_store_risk_rating_monthly.risk_level | +| 老板驾驶舱 | `riskSummary` | /stores/risk | 同上 | + +**口径:一致 ✅** + +### 3.22 P0/P1 门店 + +| 页面 | 前端变量 | API | 数据源 | +|------|---------|-----|--------| +| 总部驾驶舱 | `priorityRows` | /stores/priority | analytics.mv_store_action_priority_deep_monthly | +| 老板驾驶舱 | `priorityRows` | /stores/priority | 同上 | + +**口径:一致 ✅** + +### 3.23 成本异常分布 + +| 页面 | 前端变量 | API | 数据源 | +|------|---------|-----|--------| +| 老板驾驶舱 | `costOv.red_count` 等 | /cost-analysis/store-overview | analytics.mv_store_theoretical_actual_cost_monthly | +| 成本分析Tab | 同上 | 同上 | 同上 | + +**口径:一致 ✅** + +### 3.24 利润机会池 + +| 页面 | 前端变量 | API | 数据源 | +|------|---------|-----|--------| +| 老板驾驶舱 | `profitOpp` | /overview/profit-opportunity | analytics.mv_store_risk_rating_monthly + mv_store_operating_expense_monthly | + +**口径:N/A** — 仅老板驾驶舱显示。 + +### 3.25 日度趋势 + +| 页面 | 前端变量 | API | 数据源 | +|------|---------|-----|--------| +| 总部驾驶舱 | `dailyRows` | /overview/daily | analytics.mv_overview_daily 或 bill_fact | +| 老板驾驶舱 | `dailyRows` | /overview/daily | 同上 | + +**口径:一致 ✅** + +--- + +## 三、发现的问题汇总 + +### 问题1:利润瀑布 store_contribution 口径不一致 ✅ 已修复 + +**位置**:`/overview/profit-waterfall` API (`data.ts:1082`) + +**已修复**:received/consumption/discount/store_contribution 均改为 `FILTER (WHERE has_expense)`,仅含92家匹配门店,与 store-expense/overview 一致。 + +### 问题2:利润瀑布各项费率分母不一致 ✅ 已修复 + +**已修复**:瀑布图 received 改为 matched 口径后,前端除法分母与 store-expense/overview 一致。 + +### 问题3:mv_overview_monthly 刷新机制不完整 ✅ 已修复 + +**现状**:`mv_overview_monthly` 是普通表(非物化视图),之前刷新脚本未包含它的更新步骤,导致数据导入后该表不更新。 + +**已修复**:刷新脚本已加入 DELETE+INSERT 步骤。 + +### 问题4:KPI达成率利润口径不一致 ⚠️ 待确认 + +**位置**:`/analytics-enhanced/kpi` API (`analytics-enhanced.ts:944-953`) + +**现状**: +- `actual_revenue = sum(r.received)` — 包含全部94家门店 +- `actual_profit = sum(e.actual_store_contribution)` — LEFT JOIN后NULL被sum忽略,实际只含92家有费用门店 +- `profit_margin_pct = actual_profit / actual_revenue * 100` — 分子92家/分母94家,偏低 + +**影响**:利润率指标偏低(分母多含2家无费用门店的实收429万),但影响较小(~0.7pp)。 + +### 问题5:store-profit-ranking 用COALESCE导致无费用门店排名异常 ⚠️ 待确认 + +**位置**:`/overview/store-profit-ranking` API (`data.ts:1094-1112`) + +**现状**:`store_contribution = r.received - COALESCE(e.actual_food_cost,0) - COALESCE(e.operating_expense,0)`,2家无费用门店的贡献利润 = received - 0 - 0 = received(全部实收算作利润),会排在利润TOP5最前面。 + +**影响**:BossPage利润排名TOP5可能包含无费用门店,显示"贡献利润=实收"的异常数据。 + +### 问题6:StorePage公司均值硬编码 ⚠️ 待确认 + +**位置**:`StorePage.tsx:188` — `companyAvg` 对象 + +**现状**:8个指标的公司均值全部硬编码(日均营收20144、客单价36.8、优惠率20.5%等),不随数据更新而变化。 + +**影响**:如果实际公司均值发生变化,偏差对比将不准确。建议改为API动态获取。 + +### 问题7:StorePage scorecard 直接查bill_records而非物化视图 ⚠️ 待确认 + +**位置**:`/stores/:code` API (`data.ts:177-196`) + +**现状**:scorecard 直接从 `bill_records` 原始表聚合查询,而其他页面用 `mv_store_risk_rating_monthly` 物化视图。 + +**影响**:两表同月数据应一致,但若物化视图刷新不及时可能存在差异。且直接查原始表性能较差。 + +--- + +## 四、页面2:老板驾驶舱 BossPage + +> 无Tab,用区块布局。共调用10个API + KPISection组件1个API。 + +### 区块①:核心经营指标(6个MetricCard) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 营业收入 | `od?.consumption` | /overview | `consumption` | `sum(consumption)` | analytics.bill_fact.consumption | +| 优惠 | `od?.discount` | /overview | `discount` | `sum(discount_total)` | analytics.bill_fact.discount_total | +| 实收总额 | `od?.received` | /overview | `received` | `sum(received_total)` | analytics.bill_fact.received_total | +| 实收环比趋势 | `trendReceived` | /overview/daily | 前端计算 | `(last7.received - prev7.received) / prev7.received * 100` | analytics.mv_overview_daily.received | +| 门店贡献利润估算 | `ex?.actual_net_profit` | /store-expense/overview | `actual_net_profit` | `sum(received) FILTER(费用匹配) - sum(food_cost) - sum(operating_expense)` | mv_store_risk_rating_monthly + mv_store_operating_expense_monthly | +| 贡献率(描述) | `ex?.actual_net_margin_pct` | /store-expense/overview | `actual_net_margin_pct` | `actual_net_profit / matched_received * 100` | 同上 | +| 门店数 | `ex?.total_stores` | /store-expense/overview | `total_stores` | `count(*)` | mv_store_risk_rating_monthly | +| 盈利门店数(描述) | `ex?.profitable_stores` | /store-expense/overview | `profitable_stores` | `count(*) FILTER(actual_store_contribution > 0)` | 同上 | +| 亏损门店数(描述) | `ex?.loss_stores` | /store-expense/overview | `loss_stores` | `count(*) FILTER(<=0 AND received>0)` | 同上 | +| 客单价 | `ex?.avg_bill_value` | /store-expense/overview | `avg_bill_value` | `sum(received) / sum(bill_count)` | 同上 | +| 客单价环比趋势 | 前端计算 | /overview/daily | 前端计算 | `last7.avg - prev7.avg` | analytics.mv_overview_daily | +| 账单数(描述) | `ex?.total_bills` | /store-expense/overview | `total_bills` | `sum(bill_count)` | mv_store_risk_rating_monthly.bill_count | + +### 区块①b:KPI达成率(KPISection组件) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 收入达成率 | `kpi.revenue_achievement_pct` | /analytics-enhanced/kpi | `revenue_achievement_pct` | `sum(r.received) / sum(t.revenue_target) * 100` | mv_store_risk_rating_monthly.received + dim_store_target.revenue_target | +| 利润达成率 | `kpi.profit_achievement_pct` | 同上 | `profit_achievement_pct` | `sum(e.actual_store_contribution) / sum(t.profit_target) * 100` | mv_store_operating_expense_monthly.actual_store_contribution + dim_store_target.profit_target | +| 目标收入 | `kpi.revenue_target` | 同上 | `revenue_target` | `sum(t.revenue_target)` | dim_store_target.revenue_target | +| 利润率 | `kpi.profit_margin_pct` | 同上 | `profit_margin_pct` | `sum(actual_store_contribution) / sum(received) * 100` | 同上 | +| 目标利润(图表) | `kpi.profit_target` | 同上 | `profit_target` | `sum(t.profit_target)` | dim_store_target.profit_target | +| 实际收入(图表) | `kpi.actual_revenue` | 同上 | `actual_revenue` | `sum(r.received)` | mv_store_risk_rating_monthly.received | +| 实际利润(图表) | `kpi.actual_profit` | 同上 | `actual_profit` | `sum(e.actual_store_contribution)` | mv_store_operating_expense_monthly.actual_store_contribution | + +> ⚠️ **KPI口径注意**:`actual_profit` 用 `sum(e.actual_store_contribution)`,LEFT JOIN 费用表后无费用门店的 `actual_store_contribution` 为 NULL,`sum(NULL)` 忽略,所以实际只含有费用的门店。但 `actual_revenue` 用 `sum(r.received)` 包含全部94家。利润率分母含全部门店收入,分子仅含费用匹配门店利润,可能偏低。 + +### 区块②:利润结构(瀑布图) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 营业收入 | `wf.consumption` | /overview/profit-waterfall | `consumption` | `sum(consumption) FILTER(has_expense)` | bill_fact.consumption | +| 优惠 | `wf.discount` | 同上 | `discount` | `sum(discount) FILTER(has_expense)` | bill_fact.discount_total | +| 实收 | `wf.received` | 同上 | `received` | `sum(received) FILTER(has_expense)` | mv_store_risk_rating_monthly.received | +| 食材成本 | `wf.food_cost` | 同上 | `food_cost` | `sum(actual_food_cost)` | mv_store_operating_expense_monthly.actual_food_cost | +| 人工 | `wf.wage` | 同上 | `wage` | `sum(wage_expense)` | mv_store_operating_expense_monthly.wage_expense | +| 房租 | `wf.rent` | 同上 | `rent` | `sum(rent_expense)` | mv_store_operating_expense_monthly.rent_expense | +| 水电 | `wf.utility` | 同上 | `utility` | `sum(utility_expense)` | mv_store_operating_expense_monthly.utility_expense | +| 宿舍 | `wf.dorm` | 同上 | `dorm` | `sum(dorm_expense)` | mv_store_operating_expense_monthly.dorm_expense | +| 外卖佣金 | `wf.commission` | 同上 | `commission` | `sum(delivery_commission_expense)` | mv_store_operating_expense_monthly.delivery_commission_expense | +| 其他费用 | `wf.other_expense` | 同上 | `other_expense` | `sum(card_fee + repair_clean)` | mv_store_operating_expense_monthly.card_fee_expense + repair_clean_expense | +| 门店贡献利润 | `wf.store_contribution` | 同上 | `store_contribution` | `sum(received) FILTER(has_expense) - sum(food_cost) - sum(operating_expense)` | 同上 | +| 食材成本率(占比条) | 前端计算 | 同上 | 前端除法 | `wf.food_cost / wf.received * 100` | 同上 | +| 人工费率(占比条) | 前端计算 | 同上 | 前端除法 | `wf.wage / wf.received * 100` | 同上 | +| 房租费率(占比条) | 前端计算 | 同上 | 前端除法 | `wf.rent / wf.received * 100` | 同上 | +| 水电费率(占比条) | 前端计算 | 同上 | 前端除法 | `wf.utility / wf.received * 100` | 同上 | +| 其他费率(占比条) | 前端计算 | 同上 | 前端除法 | `(dorm+commission+other) / wf.received * 100` | 同上 | +| 贡献率(占比条) | 前端计算 | 同上 | 前端除法 | `wf.store_contribution / wf.received * 100` | 同上 | +| 费用率(汇总) | 前端计算 | 同上 | 前端除法 | `wf.total_expense / wf.received * 100` | 同上 | + +> ✅ **口径已修复**:所有指标均基于 `FILTER(has_expense)` 的92家门店,与 store-expense/overview 一致。 + +### 区块②b:利润机会池 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 机会类别 | `o.category` | /overview/profit-opportunity | `items[].category` | 5类: 食材成本差异/人工优化/水电节能/优惠管控/外卖佣金/SKU精简 | 多表 | +| 机会金额 | `o.opportunity` | 同上 | `items[].opportunity` | 各类不同公式,如食材=diff*30% | mv_store_risk_rating_monthly + mv_store_operating_expense_monthly + mv_dish_sku_abc_monthly | +| 基线值 | `o.baseline` | 同上 | `items[].baseline` | 各类基线值 | 同上 | +| 信心度 | `o.confidence` | 同上 | `items[].confidence` | 中高/中/低 | — | +| 责任方 | `o.owner` | 同上 | `items[].owner` | 静态文本 | — | +| 验收标准 | `o.evidence` | 同上 | `items[].evidence` | 静态文本 | — | +| 详情 | `o.detail` | 同上 | `items[].detail` | 动态拼接TOP5门店数据 | 同上 | +| 机会合计 | `totalOpportunity` | 前端计算 | — | `sum(items[].opportunity)` | 同上 | +| 30天承诺值 | 静态文本 | — | — | `≥ 150万元`(硬编码) | — | +| 占比 | `pct` | 前端计算 | — | `opp / totalOpportunity * 100` | 同上 | + +### 区块③:风险态势(3个卡片) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 红色门店数 | `riskSummary['红色']` | /stores/risk | `risk_level` count | `count(*) FILTER(risk_level='红色')` | mv_store_risk_rating_monthly.risk_level | +| 红色门店实收 | `riskRevSummary['红色']` | 同上 | `received` sum | `sum(received) FILTER(risk_level='红色')` | mv_store_risk_rating_monthly.received | +| 红色实收占比 | 前端计算 | 同上 | 前端除法 | `riskRevSummary['红色'] / od.received * 100` | 同上 | +| 黄色门店数 | `riskSummary['黄色']` | 同上 | 同上 | 同上 | 同上 | +| 黄色门店实收 | `riskRevSummary['黄色']` | 同上 | 同上 | 同上 | 同上 | +| 黄色实收占比 | 前端计算 | 同上 | 前端除法 | 同上 | 同上 | +| 绿色门店数 | `riskSummary['绿色']` | 同上 | 同上 | 同上 | 同上 | +| 绿色门店实收 | `riskRevSummary['绿色']` | 同上 | 同上 | 同上 | 同上 | +| 绿色实收占比 | 前端计算 | 同上 | 前端除法 | 同上 | 同上 | + +> ✅ **口径已修复**:实收占比分母用 `od.received`(/overview API),与DashboardPage一致。 + +### 区块③b:重点整改门店清单 + +| 显示指标 | 前端变量 | API | API字段 | 数据源表 | +|---------|---------|-----|---------|---------| +| 门店名 | `s.store_name` | /stores/priority | `store_name` | mv_store_action_priority_deep_monthly.store_name | +| 实收 | `s.received` | 同上 | `received` | 同上.received | +| 优先级 | `s.action_priority` | 同上 | `action_priority` | 同上.action_priority | +| 风险等级 | `s.risk_level` | 同上 | `risk_level` | 同上.risk_level | +| 问题组合 | `s.problem_combination` | 同上 | `problem_combination` | 同上.problem_combination | + +### 区块④:成本异常分布 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 严重超耗门店数 | `costOv.red_count` | /cost-analysis/store-overview | `red_count` | `count(*) FILTER(variance_level='红色-严重超耗')` | mv_store_theoretical_actual_cost_monthly.variance_level | +| 明显超耗门店数 | `costOv.orange_count` | 同上 | `orange_count` | `count(*) FILTER(variance_level='橙色-明显超耗')` | 同上 | +| 基本正常门店数 | `costOv.green_count` | 同上 | `green_count` | `count(*) FILTER(variance_level='绿色-基本正常')` | 同上 | +| 总差异金额 | `costOv.total_variance` | 同上 | `total_variance` | `sum(food_cost_variance)` | mv_store_theoretical_actual_cost_monthly.food_cost_variance | + +### 区块④b:费用结构(饼图) + +| 显示指标 | 前端变量 | API | API字段 | 数据源表 | +|---------|---------|-----|---------|---------| +| 费用科目名 | `r.account_name` | /store-expense/expense-structure | `account_name` | v_operating_expense_account_monthly.account_name | +| 费用金额 | `r.amount` | 同上 | `amount` | v_operating_expense_account_monthly.amount | +| 费用占比 | `r.expense_share_pct` | 同上 | `expense_share_pct` | v_operating_expense_account_monthly.expense_share_pct | + +### 区块⑤:门店营收排名 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| TOP5门店名 | `r.store_name` | /stores/risk | `store_name` | 前端按 received 降序取前5 | mv_store_risk_rating_monthly | +| TOP5实收 | `r.received` | 同上 | `received` | 同上 | mv_store_risk_rating_monthly.received | +| BOTTOM5门店名 | 同上 | 同上 | 同上 | 前端按 received 升序取末5(received>0) | 同上 | +| BOTTOM5实收 | 同上 | 同上 | 同上 | 同上 | 同上 | + +### 区块⑤b:门店利润排名 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 门店名 | `s.store_name` | /overview/store-profit-ranking | `store_name` | — | mv_store_risk_rating_monthly.store_name | +| 实收 | `s.received` | 同上 | `received` | `r.received` | mv_store_risk_rating_monthly.received | +| 贡献利润 | `s.store_contribution` | 同上 | `store_contribution` | `r.received - COALESCE(e.actual_food_cost,0) - COALESCE(e.operating_expense,0)` | 同上 + mv_store_operating_expense_monthly | +| 贡献率 | `s.contribution_margin_pct` | 同上 | `contribution_margin_pct` | `store_contribution / received * 100` | 同上 | + +> ⚠️ **store-profit-ranking 口径注意**:用 `COALESCE(...,0)` 处理无费用门店,2家无费用门店的贡献利润 = received - 0 - 0 = received(全部实收算作利润),这会导致排名中这2家门店排在最前面。与 store-expense/overview 的 `actual_net_profit` 口径不一致。 + +### 区块⑥:日度实收趋势 + +| 显示指标 | 前端变量 | API | API字段 | 数据源表 | +|---------|---------|-----|---------|---------| +| 日度实收折线 | `dailyRows[].received` | /overview/daily | `received` | analytics.mv_overview_daily.received | +| 日期 | `dailyRows[].business_date` | 同上 | `business_date` | analytics.mv_overview_daily.business_date | +| 环比上周% | `trendReceived` | 前端计算 | — | `(last7 - prev7) / prev7 * 100` | + +### 区块⑦:本月经营态势弹窗(BusinessReportDialog) + +> 该弹窗接收 BossPage 已加载的数据(od, ex, wf, riskRows, priorityRows, costOv, profitOpp, trendReceived)进行语音播报,不额外调用API。仅调用 `/tts` API进行语音合成。 + +--- + +## 五、页面3:门店工作台 StorePage + +> 7个Tab + 概览折叠区。共调用13个API(含KPISection组件1个)。 + +### 概览折叠区(门店概况与经营概览) + +#### 门店概况(4个卡片) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 门店名称 | `storeName` | /stores/risk | `store_name` | — | mv_store_risk_rating_monthly.store_name | +| 风险等级 | `storeInfo.risk` | 同上 | `risk_level` | — | mv_store_risk_rating_monthly.risk_level | +| 主要问题 | `primaryIssue` | /stores/priority | `problem_combination` | — | mv_store_action_priority_deep_monthly.problem_combination | +| 任务完成率 | 前端计算 | /tasks | `status` count | `doneTasks / tasks * 100` | analytics.store_task.status | +| 已完成/总数(描述) | 前端计算 | 同上 | 同上 | `doneTasks.length / tasks.length` | 同上 | + +#### KPI达成率(KPISection组件,level=store) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 收入达成率 | `kpi.revenue_achievement_pct` | /analytics-enhanced/kpi | `revenue_achievement_pct` | `r.received / t.revenue_target * 100` | mv_store_risk_rating_monthly.received + dim_store_target.revenue_target | +| 利润达成率 | `kpi.profit_achievement_pct` | 同上 | `profit_achievement_pct` | `e.actual_store_contribution / t.profit_target * 100` | mv_store_operating_expense_monthly.actual_store_contribution + dim_store_target.profit_target | +| 目标收入 | `kpi.revenue_target` | 同上 | `revenue_target` | `t.revenue_target` | dim_store_target.revenue_target | +| 利润率 | `kpi.profit_margin_pct` | 同上 | `profit_margin_pct` | `e.actual_store_contribution / r.received * 100` | 同上 | + +#### 最新经营日概览(daily-card) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 营业收入(当日) | `item.value`(metric=营业收入) | /tasks/stores/:code/daily-card | `anomalies[].value` | `sum(c009)` 当日 | bill_records.c009 | +| 营业收入基准 | `item.baseline` | 同上 | `anomalies[].baseline` | `sum(c009)` 一周前同日 | bill_records.c009 | +| 营业收入异常 | `item.is_anomaly` | 同上 | `anomalies[].is_anomaly` | `value < baseline * 0.8` | — | +| 优惠(当日) | `item.value`(metric=优惠) | 同上 | 同上 | `sum(c068)` 当日 | bill_records.c068 | +| 优惠异常 | 同上 | 同上 | 同上 | `value > baseline * 1.2` | — | +| 实收(当日) | `item.value`(metric=实收) | 同上 | 同上 | `sum(c114)` 当日 | bill_records.c114 | +| 实收异常 | 同上 | 同上 | 同上 | `value < baseline * 0.8` | — | +| 账单数(当日) | `item.value`(metric=账单数) | 同上 | 同上 | `count(*)` 当日 | bill_records | +| 账单数异常 | 同上 | 同上 | 同上 | `value < baseline * 0.8` | — | +| 客单价(当日) | `item.value`(metric=客单价) | 同上 | 同上 | `sum(c114)/count(*)` 当日 | bill_records | +| 客单价异常 | 同上 | 同上 | 同上 | `value < baseline * 0.9` | — | +| 异常项数 | `anomalyCount` | 前端计算 | — | `count(is_anomaly=true)` | — | +| 对比日期 | `card.target_date` / `card.baseline_date` | 同上 | `target_date` / `baseline_date` | `max(c176::date)` / `target_date - 7天` | bill_records.c176 | + +#### 本周指标进度(followup) + +| 显示指标 | 前端变量 | API | API字段 | 数据源表 | +|---------|---------|-----|---------|---------| +| 实收(基线/目标/实际) | `followup.baseline_received` / `target_received` / `actual_received` | /tasks/followup | 同名 | analytics.mv_store_monthly_followup | +| 客单价(基线/目标/实际) | `followup.baseline_avg_bill` / `target_avg_bill` / `actual_avg_bill` | 同上 | 同名 | 同上 | +| 优惠率(基线/目标/实际) | `followup.baseline_discount_rate` / `target_discount_rate` / `actual_discount_rate` | 同上 | 同名 | 同上 | +| 毛利率(基线/目标/实际) | `followup.baseline_margin_rate` / `target_margin_rate` / `actual_margin_rate` | 同上 | 同名 | 同上 | +| 达成率 | 前端计算 | — | — | `actual / target * 100` | +| 异常率(基线/目标/实际) | `followup.baseline_anomaly_rate` / `target_anomaly_rate` / `actual_anomaly_rate` | 同上 | 同名 | 同上 | +| 会员占比(基线/目标/实际) | `followup.baseline_member_share` / `target_member_share` / `actual_member_share` | 同上 | 同名 | 同上 | +| 工作重点 | `followup.work_focus` | 同上 | `work_focus` | 同上 | +| 行动计划 | `followup.action_plan` | 同上 | `action_plan` | 同上 | + +#### 日度实收趋势 + +| 显示指标 | 前端变量 | API | API字段 | 数据源表 | +|---------|---------|-----|---------|---------| +| 日度实收折线 | `dailyRows[].received` | /stores/:code/daily | `received` | bill_records.c114 (按c176::date分组) | +| 日期 | `dailyRows[].business_date` | 同上 | `business_date` | bill_records.c176::date | + +#### 核心SKU备货提醒 + +| 显示指标 | 前端变量 | API | API字段 | 数据源表 | +|---------|---------|-----|---------|---------| +| SKU名称 | `s.dish_name` | /sku/abc | `dish_name` | analytics.mv_dish_sku_abc_monthly.dish_name | +| ABC等级 | `s.abc_class` | 同上 | `abc_class` | 同上.abc_class | +| 营收占比 | `s.revenue_share_pct` | 同上 | `revenue_share_pct` | 同上.revenue_share_pct | +| 累计占比 | `s.cumulative_revenue_share_pct` | 同上 | `cumulative_revenue_share_pct` | 同上.cumulative_revenue_share_pct | + +> 前端过滤 `abc_class === 'A'` 取前10条。 + +#### 待办/已完成任务 + +| 显示指标 | 前端变量 | API | API字段 | 数据源表 | +|---------|---------|-----|---------|---------| +| 优先级 | `t.priority` | /tasks | `priority` | analytics.store_task.priority | +| 问题指标 | `t.problem_indicator` | 同上 | `problem_indicator` | 同上.problem_indicator | +| 状态 | `t.status` | 同上 | `status` | 同上.status | +| 行动要求 | `t.action_required` | 同上 | `action_required` | 同上.action_required | +| 截止日 | `t.deadline` | 同上 | `deadline` | 同上.deadline | +| 验收结果 | `t.verification_result` | 同上 | `verification_result` | 同上.verification_result | +| 执行证据 | `t.process_evidence` | 同上 | `process_evidence` | 同上.process_evidence | +| 后续计划 | `t.next_step` | 同上 | `next_step` | 同上.next_step | + +### 核心指标行(8个MetricCard,scorecard) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 营业收入 | `sc.consumption` | /stores/:code | `scorecard.consumption` | `sum(c009)` | bill_records.c009 | +| 优惠 | `sc.discount` | 同上 | `scorecard.discount` | `sum(c068)` | bill_records.c068 | +| 月度实收 | `sc.received` | 同上 | `scorecard.received` | `sum(c114)` | bill_records.c114 | +| 月度账单数 | `sc.bill_count` | 同上 | `scorecard.bill_count` | `count(*)` | bill_records | +| 客单价 | `sc.avg_bill_value` | 同上 | `scorecard.avg_bill_value` | `sum(c114)/count(*)` | bill_records | +| 优惠率 | `sc.discount_rate_pct` | 同上 | `scorecard.discount_rate_pct` | `sum(c068)/sum(c009)*100` | bill_records | +| 理论毛利率 | `sc.theoretical_margin_pct` | 同上 | `scorecard.theoretical_margin_pct` | `sum(c181)/sum(c114)*100` | bill_records.c181/c114 | +| 会员占比 | `sc.member_bill_share_pct` | 同上 | `scorecard.member_bill_share_pct` | `count(c185非空)/count(*)*100` | bill_records.c185 | + +> ⚠️ **scorecard数据源注意**:`/stores/:code` 的 scorecard 直接从 `bill_records` 原始表查询(非物化视图),而其他页面用 `mv_store_risk_rating_monthly`。两表同月数据应一致,但若刷新不及时可能存在差异。 + +### 风险与经营状态说明 + +| 显示指标 | 前端变量 | API | API字段 | 数据源表 | +|---------|---------|-----|---------|---------| +| 风险等级 | `risk.risk_level` | /stores/:code | `risk.risk_level` | mv_store_risk_rating_monthly.risk_level | +| 问题组合 | `action.problem_combination` | 同上 | `action.problem_combination` | mv_store_action_priority_deep_monthly.problem_combination | +| 经营象限 | `action.management_quadrant` | 同上 | `action.management_quadrant` | 后端计算:日均营收 vs 中位18642 & 毛利率 vs 中位70% | +| 规模层级 | `action.scale_tier` | 同上 | `action.scale_tier` | mv_store_action_priority_deep_monthly.scale_tier | +| 综合基准分 | `action.benchmark_score` | 同上 | `benchmark.benchmark_score` | mv_store_benchmark_composite_monthly | +| 行动优先级 | `action.action_priority` | 同上 | `action.action_priority` | mv_store_action_priority_deep_monthly.action_priority | +| 成本差异率 | `action.variance_to_theoretical_pct` | 同上 | `action.variance_to_theoretical_pct` | 同上.variance_to_theoretical_pct | +| 成本差异等级 | `action.variance_level` | 同上 | `action.variance_level` | 同上.variance_level | + +#### 月度指标偏差对比(vs 公司均值,硬编码) + +| 显示指标 | 前端变量 | 门店值来源 | 公司均值 | 数据源表 | +|---------|---------|-----------|---------|---------| +| 日均营收 | `risk.avg_daily_received` | /stores/:code → risk | 20144(硬编码) | mv_store_risk_rating_monthly.avg_daily_received | +| 客单价 | `risk.avg_bill_value` | 同上 | 36.8(硬编码) | 同上.avg_bill_value | +| 优惠率 | `risk.discount_rate_pct` | 同上 | 20.5(硬编码) | 同上.discount_rate_pct | +| 毛利率 | `risk.theoretical_margin_pct` | 同上 | 71.5(硬编码) | 同上.theoretical_margin_pct | +| 会员占比 | `risk.member_bill_share_pct` | 同上 | 15.9(硬编码) | 同上.member_bill_share_pct | +| 复购率 | `action.repeat_rate_pct` | 同上 → action | 37.0(硬编码) | mv_store_action_priority_deep_monthly.repeat_rate_pct | +| 外卖占比 | `action.delivery_bill_share_pct` | 同上 | 36.1(硬编码) | 同上.delivery_bill_share_pct | +| 成本差异率 | `action.variance_to_theoretical_pct` | 同上 | 20(硬编码) | 同上.variance_to_theoretical_pct | + +> ⚠️ **公司均值硬编码**:`companyAvg` 对象中的值是硬编码的,不随数据更新而变化。如果实际公司均值发生变化,偏差对比将不准确。 + +--- + +### Tab1:概览 + +#### 健康度评分维度(雷达图 + 进度条) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 健康总分 | `health.health_score` | /situational-awareness/health-score | `health_score` | 8维加权总分(0-100) | 多表联合计算 | +| 营收规模得分 | `health.score_revenue` | 同上 | `score_revenue` | `20 * LEAST(1.0, avg_daily_received/30000)` | mv_store_risk_rating_monthly.avg_daily_received | +| 成本控制得分 | `health.score_cost` | 同上 | `score_cost` | `20 * GREATEST(0, 1 - LEAST(variance,50)/50)` | mv_store_theoretical_actual_cost_monthly.variance_to_theoretical_pct | +| 毛利率得分 | `health.score_margin` | 同上 | `score_margin` | `15 * LEAST(1.0, GREATEST(0, margin-60)/15)` | mv_store_risk_rating_monthly.theoretical_margin_pct | +| 风险控制得分 | `health.score_risk` | 同上 | `score_risk` | 绿色=10, 黄色=6, 红色=2 | mv_store_risk_rating_monthly.risk_level | +| 复购率得分 | `health.score_repeat` | 同上 | `score_repeat` | `10 * LEAST(1.0, repeat_rate/40)` | mv_store_repeat_summary_monthly.repeat_rate_pct | +| 会员占比得分 | `health.score_member` | 同上 | `score_member` | `10 * LEAST(1.0, member_share/20)` | mv_store_risk_rating_monthly.member_bill_share_pct | +| 任务完成得分 | `health.score_task` | 同上 | `score_task` | `10 * completion_rate/100` | analytics.store_task | +| 客单价得分 | `health.score_bill` | 同上 | `score_bill` | `5 * LEAST(1.0, avg_bill_value/40)` | mv_store_risk_rating_monthly.avg_bill_value | +| 健康状态 | `health.health_status` | 同上 | `health_status` | ≥75=健康, ≥55=亚健康, <55=需干预 | — | + +#### 平台经济性 + +| 显示指标 | 前端变量 | API | API字段 | 数据源表 | +|---------|---------|-----|---------|---------| +| 美团实收 | `sd.platform.meituan_received` | /stores/:code | `platform.meituan_received` | mv_store_platform_economics_monthly.meituan_received | +| 饿了么实收 | `sd.platform.eleme_received` | 同上 | `platform.eleme_received` | 同上.eleme_received | +| 抖音实收 | `sd.platform.douyin_received` | 同上 | `platform.douyin_received` | 同上.douyin_received | +| 平台加权成本率 | `sd.platform.weighted_cost_rate_pct` | 同上 | `platform.weighted_cost_rate_pct` | 同上.weighted_cost_rate_pct | + +--- + +### Tab2:餐段分析 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 餐段 | `mealRows[].meal_period` | /stores/:code/meal-period | `meal_period` | — | analytics.bill_fact.meal_period | +| 账单数 | `mealRows[].bill_count` | 同上 | `bill_count` | `count(*)` | analytics.bill_fact | +| 实收 | `mealRows[].received` | 同上 | `received` | `sum(received_total)` | analytics.bill_fact.received_total | +| 平均单价 | `mealRows[].avg_bill` | 同上 | `avg_bill` | `sum(received_total)/count(*)` | 同上 | +| 全网均价 | `mealRows[].network_avg_bill` | 同上 | `network_avg_bill` | 全门店同餐段 `sum(received)/count(*)` | analytics.bill_fact | +| vs全网% | `mealRows[].vs_network_pct` | 同上 | `vs_network_pct` | `(store.avg / network.avg - 1) * 100` | — | + +--- + +### Tab3:品类结构 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 门店各品类金额 | `s.lanzhou_noodle` 等 | /stores/:code/category-mix | `store.*` | 各品类 `sum(consumption)` | mv_store_category_mix_monthly | +| 公司各品类金额 | `c.total_noodle` 等 | 同上 | `company.*` | 全门店 `sum(各品类)` | 同上 | +| 门店品类占比 | 前端计算 | — | — | `品类金额 / 门店总金额 * 100` | — | +| 公司品类占比 | 前端计算 | — | — | `品类金额 / 公司总金额 * 100` | — | +| 主力品类 | `s.top_category` | 同上 | `store.top_category` | — | mv_store_category_mix_monthly.top_category | +| 主力品类占比 | `s.top_category_share_pct` | 同上 | `store.top_category_share_pct` | — | 同上.top_category_share_pct | +| 面食占比 | `s.noodle_share_pct` | 同上 | `store.noodle_share_pct` | — | 同上.noodle_share_pct | +| 外卖占比 | `s.delivery_package_share_pct` | 同上 | `store.delivery_package_share_pct` | — | 同上.delivery_package_share_pct | + +--- + +### Tab4:成本分析 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 理论成本率 | `cost.cost.theoretical_cost_rate_pct` | /stores/:code/cost | `cost.theoretical_cost_rate_pct` | — | mv_store_theoretical_actual_cost_monthly | +| 实际成本率 | `cost.cost.actual_food_cost_rate_pct` | 同上 | `cost.actual_food_cost_rate_pct` | — | 同上 | +| 差异率 | `cost.cost.variance_to_theoretical_pct` | 同上 | `cost.variance_to_theoretical_pct` | — | 同上 | +| 差异等级 | `cost.cost.variance_level` | 同上 | `cost.variance_level` | — | 同上 | +| 原料分类名 | `cost.categories[].category_name` | 同上 | `categories[].category_name` | `finance_category` | mv_inventory_cost_classified_monthly.finance_category | +| 消耗金额 | `cost.categories[].consumption_amount` | 同上 | `categories[].consumption_amount` | `sum(consumption_amount)` | 同上.consumption_amount | +| 实际占比 | `cost.categories[].actual_cost_rate_pct` | 同上 | `categories[].actual_cost_rate_pct` | `分类消耗/总消耗*100` | — | +| 公司基准 | `cost.categories[].benchmark_rate_pct` | 同上 | `categories[].benchmark_rate_pct` | 全门店同分类占比 | — | +| 差异 | `cost.categories[].variance_pct` | 同上 | `categories[].variance_pct` | `actual - benchmark` | — | + +--- + +### Tab5:会员分析 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 会员占比 | `member.opportunity.member_share_pct` | /stores/:code/member | `opportunity.member_share_pct` | — | mv_store_member_opportunity_monthly | +| 公司均值会员占比 | `member.opportunity.company_member_share_pct` | 同上 | `opportunity.company_member_share_pct` | — | 同上 | +| 复购率 | `member.repeat.repeat_rate_pct` | 同上 | `repeat.repeat_rate_pct` | — | mv_store_repeat_summary_monthly | +| 复购收入占比 | `member.repeat.repeat_revenue_share_pct` | 同上 | `repeat.repeat_revenue_share_pct` | — | 同上 | +| 活跃会员数 | `member.monthly.member_count` | 同上 | `monthly.member_count` | `count(*)` | v_store_member_monthly_activity | +| 总订单数 | `member.monthly.total_orders` | 同上 | `monthly.total_orders` | `sum(orders)` | 同上 | +| 人均订单 | `member.monthly.avg_orders` | 同上 | `monthly.avg_orders` | `avg(orders)` | 同上 | +| 人均消费 | `member.monthly.avg_received` | 同上 | `monthly.avg_received` | `avg(received)` | 同上 | +| 提升机会(文本) | `member.opportunity.conversion_bill_scenario` | 同上 | `opportunity.conversion_bill_scenario` | — | mv_store_member_opportunity_monthly | +| 收入提升场景(文本) | `member.opportunity.revenue_uplift_scenario` | 同上 | `opportunity.revenue_uplift_scenario` | — | 同上 | + +--- + +### Tab6:异常账单 + +| 显示指标 | 前端变量 | API | API字段 | 数据源表 | +|---------|---------|-----|---------|---------| +| 账单号 | `r.bill_no` | /stores/:code/anomalies | `bill_no` | mv_risk_anomaly.bill_no | +| 餐段 | `r.meal_period` | 同上 | `meal_period` | 同上.meal_period | +| 消费额 | `r.consumption` | 同上 | `consumption` | 同上.consumption | +| 优惠 | `r.discount_total` | 同上 | `discount_total` | 同上.discount_total | +| 实收 | `r.received_total` | 同上 | `received_total` | 同上.received_total | +| 异常原因 | `r.anomaly_reason` | 同上 | `anomaly_reason` | 同上.anomaly_reason | +| 结账时间 | `r.closed_at` | 同上 | `closed_at` | 同上.closed_at | +| 总数 | `anomalyDetailTotal` | 同上 | `meta.total` | — | + +> ⚠️ **anomalies数据源注意**:`/stores/:code/anomalies` 通过 `store_name`(非 `store_code`)关联 `mv_risk_anomaly` 视图,需先查 `dim_store` 获取 `store_name` 再查异常表。 + +--- + +### Tab7:人力排班 + +#### 人力成本概览(6个MetricCard) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 人工成本 | `staffing.summary.wage_expense` | /stores/:code/staffing | `summary.wage_expense` | — | mv_store_operating_expense_monthly.wage_expense | +| 人工成本率 | `staffing.summary.wage_rate_pct` | 同上 | `summary.wage_rate_pct` | — | 同上.wage_rate_pct | +| 公司均值人工率 | `staffing.summary.avg_wage_rate` | 同上 | `summary.avg_wage_rate` | `avg(wage_rate_pct)` 排除>100% | 同上 | +| 人效 | `staffing.summary.revenue_per_wage` | 同上 | `summary.revenue_per_wage` | `received / wage_expense` | 同上 | +| 每单人工成本 | `staffing.summary.wage_per_bill` | 同上 | `summary.wage_per_bill` | `wage_expense / bill_count` | 同上 | +| 公司均值人效 | `staffing.summary.avg_rev_per_wage` | 同上 | `summary.avg_rev_per_wage` | `avg(received/wage_expense)` | 同上 | + +#### 人力成本优化空间 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 建议人工成本 | `staffing.summary.suggested_wage` | 同上 | `summary.suggested_wage` | `received * max(20%, avgWageRate-3%) / 100` | 后端计算 | +| 可节省金额 | `staffing.summary.wage_savings` | 同上 | `summary.wage_savings` | `wage_expense - suggested_wage` | 后端计算 | +| 节省比例 | `staffing.summary.savings_pct` | 同上 | `summary.savings_pct` | `wage_savings / wage_expense * 100` | 后端计算 | + +#### 按星期排班分析 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 星期 | `weekdays[].weekday` | 同上 | `weekdays[].weekday` | — | v_store_daily | +| 日均实收 | `weekdays[].avg_received` | 同上 | 同上 | `avg(received)` 按星期分组 | v_store_daily.received | +| 日均账单 | `weekdays[].avg_bills` | 同上 | 同上 | `avg(bill_count)` | v_store_daily.bill_count | +| 最高实收 | `weekdays[].max_received` | 同上 | 同上 | `max(received)` | v_store_daily.received | +| 最低实收 | `weekdays[].min_received` | 同上 | 同上 | `min(received)` | v_store_daily.received | +| 建议排班比 | `weekdays[].suggested_headcount_ratio` | 同上 | 同上 | `avg_received / 全周日均 * 100` | 后端计算 | +| 排班等级 | `weekdays[].staffing_level` | 同上 | 同上 | >110%=高峰, <85%=低谷, else=正常 | — | +| 排班建议 | `weekdays[].staffing_action` | 同上 | 同上 | 静态文本 | — | + +#### 餐段排班分析 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 餐段 | `meals[].meal_period` | 同上 | `meals[].meal_period` | — | v_store_meal_opportunity | +| 账单数 | `meals[].bill_count` | 同上 | 同上 | — | 同上 | +| 实收 | `meals[].received` | 同上 | 同上 | — | 同上 | +| 客单价 | `meals[].avg_bill` | 同上 | 同上 | — | 同上 | +| 账单占比 | `meals[].bill_share_pct` | 同上 | 同上 | `餐段账单/总账单*100` | 后端计算 | +| 排班等级 | `meals[].staffing_level` | 同上 | 同上 | >40%=主力, >20%=次高峰, >5%=辅助, else=低谷 | — | +| 排班建议 | `meals[].staffing_action` | 同上 | 同上 | 静态文本 | — | + +#### 日营收明细(排班参考) + +| 显示指标 | 前端变量 | API | API字段 | 数据源表 | +|---------|---------|-----|---------|---------| +| 日期 | `daily[].business_date` | 同上 | `daily[].business_date` | v_store_daily.business_date | +| 实收 | `daily[].received` | 同上 | 同上 | v_store_daily.received | + +--- + +## 六、页面4:菜品成本 CostAnalysisPage + +> 10个Tab,每个Tab独立组件。共调用22个API(含1个POST、1个PUT)。 +> 核心数据源:`public.dish_cost_analysis_summary`(菜品成本汇总表,按月导入)+ `public.dish_cost_analysis_material_detail`(原料明细表)+ `analytics.fact_recipe_bom`(BOM配方表)。 + +### Tab1:成本总览(OverviewTab) + +#### 概览指标(8个MetricCard) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 总销售额 | `ov.total_sales` | /cost-analysis/overview | `total_sales` | `sum(sales_amount)` | dish_cost_analysis_summary.sales_amount | +| 理论成本合计 | `ov.total_theo_cost` | 同上 | `total_theo_cost` | `sum(theoretical_cost)` | 同上.theoretical_cost | +| 实际成本合计 | `ov.total_actual_cost` | 同上 | `total_actual_cost` | `sum(actual_cost)` | 同上.actual_cost | +| 成本差异 | `ov.total_variance` | 同上 | `total_variance` | `sum(cost_variance_amount)` | 同上.cost_variance_amount | +| 平均理论毛利率 | `ov.avg_theo_margin` | 同上 | `avg_theo_margin` | `(1 - sum(theoretical_cost)/sum(sales_amount)) * 100` | 同上 | +| 平均实际毛利率 | `ov.avg_actual_margin` | 同上 | `avg_actual_margin` | `(1 - sum(actual_cost)/sum(sales_amount)) * 100` | 同上 | +| 低毛利菜品数 | `ov.low_margin_dishes` | 同上 | `low_margin_dishes` | `count(*) FILTER(theoretical_margin_rate_pct < 50)` | 同上.theoretical_margin_rate_pct | +| 超理论菜品数 | `ov.over_cost_dishes` | 同上 | `over_cost_dishes` | `count(*) FILTER(cost_variance_amount > 0)` | 同上.cost_variance_amount | + +> **数据导入机制**:所有查询通过 `import_id` 关联 `dish_cost_analysis_import_log` 取最新月度导入批次。 + +#### 品类成本对比 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 品类 | `cats[].category_level1` | /cost-analysis/category-comparison | `category_level1` | — | dish_cost_analysis_summary.category_level1 | +| 菜品数 | `cats[].dishes` | 同上 | `dishes` | `count(*)` | 同上 | +| 理论毛利率 | `cats[].avg_theo_margin` | 同上 | `avg_theo_margin` | `(1 - sum(theoretical_cost)/sum(sales_amount)) * 100` | 同上 | +| 实际毛利率 | `cats[].avg_actual_margin` | 同上 | `avg_actual_margin` | `(1 - sum(actual_cost)/sum(sales_amount)) * 100` | 同上 | +| 销售额 | `cats[].total_sales` | 同上 | `total_sales` | `sum(sales_amount)` | 同上 | +| 成本差异 | `cats[].total_variance` | 同上 | `total_variance` | `sum(cost_variance_amount)` | 同上 | + +#### 毛利率偏差分布 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 偏差区间 | `devs[].deviation_band` | /cost-analysis/margin-deviation | `deviation_band` | CASE分组:实际-理论偏差 | dish_cost_analysis_summary | +| 菜品数 | `devs[].cnt` | 同上 | `cnt` | `count(*)` | 同上 | + +#### 成本差异TOP榜 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 菜品 | `tops[].dish_name` | /cost-analysis/variance-top | `dish_name` | — | dish_cost_analysis_summary.dish_name | +| 品类 | `tops[].category_level1` | 同上 | `category_level1` | — | 同上 | +| 理论毛利率 | `tops[].theo_margin` | 同上 | `theo_margin` | `theoretical_margin_rate_pct` | 同上 | +| 实际毛利率 | `tops[].actual_margin` | 同上 | `actual_margin` | `actual_margin_rate_pct` | 同上 | +| 成本差异 | `tops[].cost_variance` | 同上 | `cost_variance` | `cost_variance_amount` | 同上 | +| 销售额 | `tops[].sales_amount` | 同上 | `sales_amount` | — | 同上 | +| 分层 | `tops[].cost_tier` | 同上 | `cost_tier` | CASE:>20%=紧急, >10%=整改, >0=关注, else=正常 | — | + +--- + +### Tab2:菜品盈利(ProfitabilityTab) + +#### 菜单工程矩阵(散点图) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 菜品 | `matrixData[].dish_name` | /cost-analysis/menu-engineering | `dish_name` | — | dish_cost_analysis_summary | +| 销量 | `matrixData[].sales_quantity` | 同上 | `sales_quantity` | — | 同上.sales_quantity | +| 实际毛利率 | `matrixData[].actual_margin` | 同上 | `actual_margin` | `actual_margin_rate_pct` | 同上 | +| 销售额 | `matrixData[].sales_amount` | 同上 | `sales_amount` | — | 同上 | +| 菜单类型 | `matrixData[].menu_type` | 同上 | `menu_type` | 双中位分割:销量&毛利率各取中位数 → 明星/高销低利/低销高利/低销低利/数据异常 | — | + +#### 菜品盈利明细(服务端分页) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 菜品 | `profitData[].dish_name` | /cost-analysis/profitability | `dish_name` | — | dish_cost_analysis_summary | +| 品类 | `profitData[].category_level1` | 同上 | `category_level1` | — | 同上 | +| 销量 | `profitData[].sales_quantity` | 同上 | `sales_quantity` | — | 同上 | +| 销售额 | `profitData[].sales_amount` | 同上 | `sales_amount` | — | 同上 | +| 理论毛利 | `profitData[].theo_profit` | 同上 | `theo_profit` | `sales_amount - theoretical_cost` | 同上 | +| 实际毛利 | `profitData[].actual_profit` | 同上 | `actual_profit` | `sales_amount - actual_cost` | 同上 | +| 理论毛利率 | `profitData[].theo_margin` | 同上 | `theo_margin` | `theoretical_margin_rate_pct` | 同上 | +| 实际毛利率 | `profitData[].actual_margin` | 同上 | `actual_margin` | `actual_margin_rate_pct` | 同上 | +| 收入贡献度 | `profitData[].revenue_contribution` | 同上 | `revenue_contribution` | `sales_amount / sum(sales_amount) OVER() * 100` | 同上 | + +#### 低毛利菜品预警 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 菜品 | `pricingData[].dish_name` | /cost-analysis/pricing | `dish_name` | — | dish_cost_analysis_summary | +| 售价 | `pricingData[].price` | 同上 | `price` | — | 同上.price | +| 理论成本 | `pricingData[].theo_cost` | 同上 | `theo_cost` | `theoretical_cost` | 同上 | +| 理论成本率 | `pricingData[].theo_cost_rate` | 同上 | `theo_cost_rate` | `theoretical_cost / price * 100` | 同上 | +| 理论毛利率 | `pricingData[].theo_margin` | 同上 | `theo_margin` | `theoretical_margin_rate_pct` | 同上 | +| 实际毛利率 | `pricingData[].actual_margin` | 同上 | `actual_margin` | `actual_margin_rate_pct` | 同上 | +| 销售额 | `pricingData[].sales_amount` | 同上 | `sales_amount` | — | 同上 | + +> 筛选条件:`theoretical_margin_rate_pct < 50 AND sales_amount > 1000`。 + +--- + +### Tab3:原料差异(MaterialTab) + +#### 菜品原料差异分解(按菜品编码查询) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 原料 | `varianceData[].material_name` | /cost-analysis/material-variance | `material_name` | — | dish_cost_analysis_material_detail.material_name | +| 单位 | `varianceData[].material_unit` | 同上 | `material_unit` | — | 同上.material_unit | +| 理论用量 | `varianceData[].theo_qty` | 同上 | `theo_qty` | `theoretical_quantity` | 同上.theoretical_quantity | +| 实际用量 | `varianceData[].actual_qty` | 同上 | `actual_qty` | `actual_quantity` | 同上.actual_quantity | +| 数量差异 | `varianceData[].loss_qty` | 同上 | `loss_qty` | `loss_quantity` | 同上.loss_quantity | +| 损耗率 | `varianceData[].loss_rate` | 同上 | `loss_rate` | `loss_quantity_rate_pct` | 同上.loss_quantity_rate_pct | +| 金额差异 | `varianceData[].loss_amount` | 同上 | `loss_amount` | `loss_amount` | 同上.loss_amount | +| 原因 | `varianceData[].reason` | 同上 | `reason` | CASE:<-100%=分摊遗漏, <-30%=份量超标, =0=未使用, else=正常损耗 | — | + +#### 物料损耗率分布 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 损耗区间 | `distData[].loss_band` | /cost-analysis/loss-distribution | `loss_band` | CASE分档:无损耗/轻微/轻度/中度/严重/极重/正向 | dish_cost_analysis_material_detail | +| 明细数 | `distData[].cnt` | 同上 | `cnt` | `count(*)` | 同上 | + +#### 超耗物料TOP榜 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 物料 | `topData[].material_name` | /cost-analysis/material-loss-top | `material_name` | — | dish_cost_analysis_material_detail | +| 类型 | `topData[].material_type` | 同上 | `material_type` | — | 同上 | +| 涉及菜品数 | `topData[].dish_count` | 同上 | `dish_count` | `count(DISTINCT summary_id)` | 同上 | +| 总损耗量 | `topData[].total_loss_qty` | 同上 | `total_loss_qty` | `sum(loss_quantity)` | 同上 | +| 平均损耗率 | `topData[].avg_loss_rate` | 同上 | `avg_loss_rate` | `sum(loss_quantity)/sum(theoretical_quantity)*100` | 同上 | +| 最大损耗率 | `topData[].max_loss_rate` | 同上 | `max_loss_rate` | `max(loss_quantity_rate_pct)` | 同上 | +| 损耗金额 | `topData[].total_loss_amount` | 同上 | `total_loss_amount` | `sum(loss_amount)` | 同上 | + +#### 物料类型损耗对比 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 物料类型 | `typeData[].material_type` | /cost-analysis/material-type-loss | `material_type` | — | dish_cost_analysis_material_detail | +| 明细数 | `typeData[].cnt` | 同上 | `cnt` | `count(*)` | 同上 | +| 物料种类 | `typeData[].unique_materials` | 同上 | `unique_materials` | `count(DISTINCT material_name)` | 同上 | +| 平均损耗率 | `typeData[].avg_loss_rate` | 同上 | `avg_loss_rate` | `sum(loss_quantity)/sum(theoretical_quantity)*100` | 同上 | +| 损耗金额 | `typeData[].total_loss_amount` | 同上 | `total_loss_amount` | `sum(loss_amount)` | 同上 | + +--- + +### Tab4:BOM与配方(BomTab) + +#### BOM总览(6个MetricCard) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| BOM覆盖率 | `ov.coverage_pct` | /cost-analysis/bom-overview | `coverage_pct` | `count(DISTINCT sku_code in BOM) / count(dim_sku) * 100` | fact_recipe_bom + dim_sku | +| 有BOM的SKU | `ov.sku_with_bom` | 同上 | `sku_with_bom` | `count(DISTINCT sku_code)` | fact_recipe_bom.sku_code | +| 缺BOM的SKU | `ov.sku_without_bom` | 同上 | `sku_without_bom` | `total_sku - sku_with_bom` | dim_sku - fact_recipe_bom | +| BOM总行数 | `ov.total_bom_rows` | 同上 | `total_bom_rows` | `count(*)` | fact_recipe_bom | +| 高损耗BOM数 | `ov.high_loss_bom` | 同上 | `high_loss_bom` | `count(*) FILTER(waste_rate > 20)` | fact_recipe_bom.waste_rate | +| 平均物料数/SKU | `ov.avg_materials_per_sku` | 同上 | `avg_materials_per_sku` | `avg(count per sku)` | 同上 | + +> ⚠️ **bom-overview 无月份参数**:该API不接收month参数,BOM数据不按月区分。 + +#### BOM复杂度明细(服务端分页) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| SKU编码 | `compData[].sku_code` | /cost-analysis/bom-complexity | `sku_code` | — | fact_recipe_bom.sku_code | +| 菜品名 | `compData[].dish_name` | 同上 | `dish_name` | `dim_sku.standard_name` | dim_sku.standard_name | +| 品类 | `compData[].category_l1` | 同上 | `category_l1` | — | dim_sku.category_l1 | +| 原料数 | `compData[].material_count` | 同上 | `material_count` | `count(*)` | fact_recipe_bom | +| 半成品数 | `compData[].semi_finished_count` | 同上 | `semi_finished_count` | `count(*) FILTER(major_category='半成品')` | fact_recipe_bom + dim_material | +| 独有原料 | `compData[].unique_material_count` | 同上 | `unique_material_count` | `count(*) FILTER(ref_count=1)` | fact_recipe_bom(子查询ref_count) | +| 高损耗原料 | `compData[].high_loss_count` | 同上 | `high_loss_count` | `count(*) FILTER(waste_rate > 20)` | fact_recipe_bom.waste_rate | +| 复杂度 | `compData[].complexity_level` | 同上 | `complexity_level` | CASE:≤5=低, ≤10=正常, ≤15=较复杂, >15=重点评审 | — | + +#### 菜品物料构成(按SKU查询) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 物料 | `compDetail[].material_name` | /cost-analysis/bom-composition | `material_name` | — | dim_material.material_name | +| 类型 | `compDetail[].material_type` | 同上 | `material_type` | `dim_material.major_category` | dim_material.major_category | +| 标准毛用量 | `compDetail[].gross_qty` | 同上 | `gross_qty` | `standard_gross_quantity` | fact_recipe_bom.standard_gross_quantity | +| 标准净用量 | `compDetail[].net_qty` | 同上 | `net_qty` | `standard_net_quantity` | fact_recipe_bom.standard_net_quantity | +| 损耗率 | `compDetail[].waste_rate` | 同上 | `waste_rate` | — | fact_recipe_bom.waste_rate | +| 成本占比 | `compDetail[].cost_share` | 同上 | `cost_share` | `theoretical_amount / sum(theoretical_amount) OVER(PARTITION BY summary_id) * 100` | dish_cost_analysis_material_detail | + +#### 高损耗BOM预警 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 菜品 | `lossData[].dish_name` | /cost-analysis/bom-high-loss | `dish_name` | `dim_sku.standard_name` | dim_sku | +| 物料 | `lossData[].material_name` | 同上 | `material_name` | — | dim_material | +| 损耗率 | `lossData[].waste_rate` | 同上 | `waste_rate` | — | fact_recipe_bom.waste_rate | +| 出成率 | `lossData[].yield_rate` | 同上 | `yield_rate` | — | fact_recipe_bom.yield_rate | +| 预警级别 | `lossData[].alert_level` | 同上 | `alert_level` | CASE:>100%=极端, >50%=严重, else=关注 | — | + +> 筛选条件:`waste_rate >= 20`。无月份参数。 + +#### 缺BOM的SKU清单(服务端分页) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| SKU编码 | `missData[].sku_code` | /cost-analysis/bom-missing | `sku_code` | — | dim_sku.sku_code | +| 菜品名 | `missData[].dish_name` | 同上 | `dish_name` | `standard_name` | dim_sku.standard_name | +| 品类 | `missData[].category_l1` | 同上 | `category_l1` | — | dim_sku.category_l1 | +| 销售额 | `missData[].sales_amount` | 同上 | `sales_amount` | `COALESCE(dish_cost_analysis_summary.sales_amount, 0)` | dish_cost_analysis_summary | +| 销量 | `missData[].sales_quantity` | 同上 | `sales_quantity` | `COALESCE(dish_cost_analysis_summary.sales_quantity, 0)` | 同上 | + +> 筛选条件:`sku_code NOT IN (SELECT DISTINCT sku_code FROM fact_recipe_bom)`。 + +--- + +### Tab5:供应链与精简(SupplyTab) + +#### 原料共用度 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 物料 | `sharingData[].material_name` | /cost-analysis/material-sharing | `material_name` | — | dim_material.material_name | +| 类型 | `sharingData[].major_category` | 同上 | `major_category` | — | dim_material.major_category | +| 被引用SKU数 | `sharingData[].sku_count` | 同上 | `sku_count` | `count(DISTINCT sku_code)` | fact_recipe_bom.sku_code | +| 分类 | `sharingData[].sharing_type` | 同上 | `sharing_type` | CASE:>50=核心原料, =1=独有原料, else=普通共用 | — | + +#### 独有原料风险(服务端分页) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| SKU编码 | `riskData[].sku_code` | /cost-analysis/unique-material-risk | `sku_code` | — | fact_recipe_bom | +| 菜品名 | `riskData[].dish_name` | 同上 | `dish_name` | `dim_sku.standard_name` | dim_sku | +| 品类 | `riskData[].category_l1` | 同上 | `category_l1` | — | dim_sku | +| 销售额 | `riskData[].sales_amount` | 同上 | `sales_amount` | `COALESCE(dish_cost_analysis_summary.sales_amount, 0)` | dish_cost_analysis_summary | +| 独有原料数 | `riskData[].unique_material_count` | 同上 | `unique_material_count` | `count(*) where ref_count=1` | fact_recipe_bom | +| 风险等级 | `riskData[].risk_level` | 同上 | `risk_level` | CASE:sales<5000 & count>3=高, sales<5000=中, else=低 | — | + +#### SKU精简模拟器(POST) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 收入影响 | `simResult.summary.revenue_impact` | POST /cost-analysis/sku-simplify-simulate | `summary.revenue_impact` | `sum(sales_amount) for target SKUs` | dish_cost_analysis_summary | +| 毛利影响 | `simResult.summary.profit_impact` | 同上 | `summary.profit_impact` | `sum(sales_amount - actual_cost)` | 同上 | +| 可减少原料数 | `simResult.summary.releasable_materials` | 同上 | `summary.releasable_materials` | `count(DISTINCT material_code) 独有原料` | fact_recipe_bom | +| 仍需采购的共用原料 | `simResult.summary.shared_materials` | 同上 | `summary.shared_materials` | `count(DISTINCT material_code) 共用原料` | 同上 | +| 负毛利菜品数 | `simResult.summary.negative_margin_count` | 同上 | `summary.negative_margin_count` | `count(*) where actual_margin_rate_pct < 0` | dish_cost_analysis_summary | +| 可释放物料 | `simResult.releasable_materials` | 同上 | `releasable_materials` | 独有物料明细 | fact_recipe_bom + dim_material | +| 库存金额 | `releasable_materials[].inventory_value` | 同上 | `inventory_value` | `sum(actual_amount)` | dish_cost_analysis_material_detail | + +#### BOM驱动物料需求预测 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 物料 | `rawDemandData[].material_name` | /cost-analysis/material-demand | `material_name` | — | dim_material | +| 类型 | `rawDemandData[].major_category` | 同上 | `major_category` | — | dim_material.major_category | +| 单位 | `rawDemandData[].base_unit` | 同上 | `base_unit` | — | dim_material.base_unit | +| 预计需求量 | `rawDemandData[].estimated_demand` | 同上 | `estimated_demand` | `sum(standard_gross_quantity * sales_quantity)` | fact_recipe_bom × dish_cost_analysis_summary | +| 涉及菜品数 | `rawDemandData[].dish_count` | 同上 | `dish_count` | `count(DISTINCT sku_code)` | fact_recipe_bom | + +--- + +### Tab6:包装耗材(PackagingTab) + +#### 包装总览(4个MetricCard) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 包装物料种类 | `ovData.packaging_types` | /cost-analysis/packaging-overview | `packaging_types` | `count(DISTINCT material_name)` | dish_cost_analysis_material_detail | +| 包装总成本 | `ovData.total_cost` | 同上 | `total_cost` | `sum(theoretical_amount)` | 同上.theoretical_amount | +| 总损耗量 | `ovData.total_loss_qty` | 同上 | `total_loss_qty` | `sum(loss_quantity)` | 同上.loss_quantity | +| 高损耗包装数 | `ovData.high_loss_count` | 同上 | `high_loss_count` | `count(*) FILTER(loss_rate < -20%)` | 同上 | + +> 筛选条件:`material_name ~* '餐盒|餐具|打包|纸巾|碗|袋|杯|盒'`(正则匹配包装物料名称)。 + +#### 包装物料明细(服务端分页) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 物料 | `detailData[].material_name` | /cost-analysis/packaging-detail | `material_name` | — | dish_cost_analysis_material_detail | +| 涉及菜品数 | `detailData[].dish_count` | 同上 | `dish_count` | `count(DISTINCT summary_id)` | 同上 | +| 总用量 | `detailData[].total_qty` | 同上 | `total_qty` | `sum(theoretical_quantity)` | 同上 | +| 总成本 | `detailData[].total_cost` | 同上 | `total_cost` | `sum(theoretical_amount)` | 同上 | +| 损耗量 | `detailData[].loss_qty` | 同上 | `loss_qty` | `sum(loss_quantity)` | 同上 | +| 平均损耗率 | `detailData[].avg_loss_rate` | 同上 | `avg_loss_rate` | `sum(loss_quantity)/sum(theoretical_quantity)*100` | 同上 | +| 状态 | `detailData[].status` | 同上 | `status` | CASE:<-20%=核查, <-5%=关注, else=正常 | — | + +--- + +### Tab7:数据质量(QualityTab) + +#### 数据质量总览(3个MetricCard + 6项检查) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| BOM覆盖率 | `ovData.bom_coverage` | /cost-analysis/data-quality | `bom_coverage` | `count(DISTINCT sku_code in BOM) / count(dim_sku) * 100` | fact_recipe_bom + dim_sku | +| 菜品匹配率 | 前端计算 | 同上 | `matched_dishes / total_dishes` | `matched_dishes / total_dishes * 100` | dish_cost_analysis_summary + dish_sales_details | +| 物料匹配率 | 前端计算 | 同上 | `matched_materials / total_materials` | `matched_materials / total_materials * 100` | dish_cost_analysis_material_detail + inventory_cost_records | +| 零实际用量BOM | `ovData.zero_actual_bom` | 同上 | `zero_actual_bom` | `count(*) WHERE standard_net_quantity = 0` | fact_recipe_bom | +| 负毛利率菜品 | `ovData.negative_margin_count` | 同上 | `negative_margin_count` | `count(*) WHERE actual_margin_rate_pct < 0` | dish_cost_analysis_summary | +| 理论负毛利菜品 | `ovData.negative_theo_margin_count` | 同上 | `negative_theo_margin_count` | `count(*) WHERE theoretical_margin_rate_pct < 0` | 同上 | + +#### 未匹配菜品清单(服务端分页) + +| 显示指标 | 前端变量 | API | API字段 | 数据源表 | +|---------|---------|-----|---------|---------| +| 菜品名 | `dishData[].dish_name` | /cost-analysis/unmatched-dishes | `dish_name` | dish_cost_analysis_summary | +| 编码 | `dishData[].dish_code` | 同上 | `dish_code` | 同上 | +| 品类 | `dishData[].category_level1` | 同上 | `category_level1` | 同上 | +| 销售额 | `dishData[].sales_amount` | 同上 | `sales_amount` | 同上 | + +> 筛选条件:`NOT EXISTS (SELECT 1 FROM dish_sales_details WHERE dish_name = s.dish_name)`。 + +#### 未匹配物料清单(服务端分页) + +| 显示指标 | 前端变量 | API | API字段 | 数据源表 | +|---------|---------|-----|---------|---------| +| 物料名 | `matData[].material_name` | /cost-analysis/unmatched-materials | `material_name` | dish_cost_analysis_material_detail | +| 类型 | `matData[].material_type` | 同上 | `material_type` | 同上 | +| 涉及菜品数 | `matData[].dish_count` | 同上 | `dish_count` | `count(DISTINCT summary_id)` | +| 损耗金额 | `matData[].loss_amount` | 同上 | `loss_amount` | `sum(loss_amount)` | + +> 筛选条件:`NOT EXISTS (SELECT 1 FROM inventory_cost_records WHERE material_name = m.material_name)`。 + +--- + +### Tab8:门店成本(StoreTab) + +#### 门店成本总览(6个MetricCard) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 门店总数 | `ovData.total_stores` | /cost-analysis/store-overview | `total_stores` | `count(*)` | mv_store_theoretical_actual_cost_monthly | +| 红色-严重超耗 | `ovData.red_count` | 同上 | `red_count` | `count(*) FILTER(variance_level='红色-严重超耗')` | 同上.variance_level | +| 橙色-明显超耗 | `ovData.orange_count` | 同上 | `orange_count` | `count(*) FILTER(variance_level='橙色-明显超耗')` | 同上 | +| 绿色-基本正常 | `ovData.green_count` | 同上 | `green_count` | `count(*) FILTER(variance_level='绿色-基本正常')` | 同上 | +| 灰色-口径异常 | `ovData.gray_count` | 同上 | `gray_count` | `count(*) FILTER(variance_level='灰色-口径异常')` | 同上 | +| 总超耗金额 | `ovData.total_variance` | 同上 | `total_variance` | `sum(food_cost_variance)` | 同上.food_cost_variance | + +#### 门店超耗排名(服务端分页) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 门店 | `rankData[].store_name` | /cost-analysis/store-ranking | `store_name` | — | mv_store_theoretical_actual_cost_monthly | +| 理论成本率 | `rankData[].theo_cost_rate` | 同上 | `theo_cost_rate` | `theoretical_cost_rate_pct` | 同上 | +| 实际成本率 | `rankData[].actual_cost_rate` | 同上 | `actual_cost_rate` | `actual_food_cost_rate_pct` | 同上 | +| 偏差 | `rankData[].variance_pct` | 同上 | `variance_pct` | `variance_to_theoretical_pct` | 同上 | +| 超耗金额 | `rankData[].variance_amount` | 同上 | `variance_amount` | `food_cost_variance` | 同上 | +| 负库存项 | `rankData[].negative_item_lines` | 同上 | `negative_item_lines` | — | 同上.negative_item_lines | +| 分级 | `rankData[].variance_level` | 同上 | `variance_level` | — | 同上.variance_level | + +--- + +### Tab9:可视化探索(ExploreTab) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 菜品 | `scatterData[].dish_name` | /cost-analysis/scatter | `dish_name` | — | dish_cost_analysis_summary | +| 品类 | `scatterData[].category_level1` | 同上 | `category_level1` | — | 同上 | +| 销量(X轴) | `scatterData[].x` | 同上 | `x` | `sales_quantity` | 同上 | +| 成本差异(Y轴) | `scatterData[].y` | 同上 | `y` | `cost_variance_amount` | 同上 | +| 销售额(气泡大小) | `scatterData[].size` | 同上 | `size` | `sales_amount` | 同上 | + +--- + +### Tab10:调整管理(AdjustmentTab) + +#### 子Tab:待处理建议 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 菜品 | `diagData[].dish_name` | /cost-analysis/diagnosis | `dish_name` | — | dish_diagnosis_snapshot | +| 品类 | `diagData[].category_l1` | 同上 | `category_l1` | — | 同上 | +| 诊断类型 | `diagData[].diagnosis_type` | 同上 | `diagnosis_type` | — | 同上(生成时计算) | +| 诊断详情 | `diagData[].diagnosis_detail` | 同上 | `diagnosis_detail` | — | 同上 | +| 理论毛利率 | `diagData[].theoretical_margin_pct` | 同上 | `theoretical_margin_pct` | — | 同上 | +| 实际毛利率 | `diagData[].actual_margin_pct` | 同上 | `actual_margin_pct` | — | 同上 | +| 成本差异 | `diagData[].cost_variance_amount` | 同上 | `cost_variance_amount` | — | 同上 | +| 建议动作 | `diagData[].suggested_action` | 同上 | `suggested_action` | — | 同上 | +| 优先级 | `diagData[].priority` | 同上 | `priority` | P0/P1/P2/P3 | 同上 | + +> **诊断生成**:POST `/cost-analysis/diagnosis/generate` 从 `dish_cost_analysis_summary` + BOM数据生成快照写入 `dish_diagnosis_snapshot`。 + +#### 子Tab:调整记录 + +| 显示指标 | 前端变量 | API | API字段 | 数据源表 | +|---------|---------|-----|---------|---------| +| 菜品 | `adjData[].dish_name` | /cost-analysis/adjustment | `dish_name` | dish_adjustment_log | +| 调整类型 | `adjData[].adjustment_type` | 同上 | `adjustment_type` | 同上 | +| 执行日期 | `adjData[].effective_date` | 同上 | `effective_date` | 同上 | +| 调整前毛利率 | `adjData[].before_theoretical_margin` | 同上 | `before_theoretical_margin` | 同上 | +| 目标毛利率 | `adjData[].after_target_margin` | 同上 | `after_target_margin` | 同上 | +| 决策人 | `adjData[].decided_by` | 同上 | `decided_by` | 同上 | +| 状态 | `adjData[].status` | 同上 | `status` | 同上 | + +> **创建调整**:POST `/cost-analysis/adjustment` → INSERT INTO dish_adjustment_log。 +> **更新状态**:PUT `/cost-analysis/adjustment/:id` → UPDATE status。 + +#### 子Tab:效果验证 + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 调整前日均销量 | `verifyData.before_avg_daily` | /cost-analysis/adjustment/:id/verify | `before_avg_daily` | `avg(bills) 前7天` | dish_sales_details | +| 调整后日均销量 | `verifyData.after_avg_daily` | 同上 | `after_avg_daily` | `avg(bills) 后7天` | 同上 | +| 销量变化率 | `verifyData.sales_change_pct` | 同上 | `sales_change_pct` | `(afterAvg - beforeAvg) / beforeAvg * 100` | — | +| 日销量趋势 | `verifyData.before/after` | 同上 | `before/after` | `count(*) per day` | dish_sales_details | + +--- + +## 七、页面5:门店营业费用 StoreExpensePage + +> 10个Tab,每个Tab独立组件。共调用11个API(全部GET)。 +> 核心数据源:`analytics.mv_store_operating_expense_monthly`(门店营业费用月度物化视图)+ `analytics.mv_store_risk_rating_monthly`(门店风险评级月度物化视图)+ `analytics.v_operating_expense_account_monthly`(费用科目月度视图)。 + +### Tab1:费用总览(ExpenseOverviewTab) + +#### 概览指标(6个MetricCard) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 营业收入 | `ov.total_consumption` | /store-expense/overview | `total_consumption` | `sum(consumption)` | bill_fact.consumption + mv_store_risk_rating_monthly | +| 优惠 | `ov.total_discount` | 同上 | `total_discount` | `sum(discount)` | 同上 | +| 实收合计 | `ov.total_received` | 同上 | `total_received` | `sum(received)` | mv_store_risk_rating_monthly.received | +| 门店贡献利润 | `ov.total_contribution` | 同上 | `total_contribution` | `sum(received - actual_food_cost - operating_expense)` | mv_store_operating_expense_monthly | +| 经营门店 | `ov.total_stores` | 同上 | `total_stores` | `count(*)` | mv_store_risk_rating_monthly | +| 费用率 | `ov.overall_expense_rate_pct` | 同上 | `overall_expense_rate_pct` | `sum(operating_expense) / sum(received) * 100` | 同上 | + +> **数据关联机制**:overview API通过CTE `full_scope` 关联 `mv_store_risk_rating_monthly`(主表,按month_start过滤)LEFT JOIN `mv_store_operating_expense_monthly`(费用明细,按report_month过滤)LEFT JOIN `bill_fact`(消费/优惠金额)。 + +#### 费用结构分析(PieChart + 明细表) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 费用科目 | `structureData[].account_name` | /store-expense/expense-structure | `account_name` | — | v_operating_expense_account_monthly.account_name | +| 金额 | `structureData[].amount` | 同上 | `amount` | — | 同上.amount | +| 占比 | `structureData[].expense_share_pct` | 同上 | `expense_share_pct` | — | 同上.expense_share_pct | +| 门店数 | `structureData[].nonzero_cost_unit_count` | 同上 | `nonzero_cost_unit_count` | — | 同上.nonzero_cost_unit_count | + +> ⚠️ **CollapsibleSection subtitle 硬编码日期**:`subtitle="2026年4月各费用科目占比"` 硬编码了月份,应使用 `month` 变量动态显示。 + +--- + +### Tab2:门店费用率排名(StoreRankingTab) + +#### 门店费用率排名(服务端分页) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 门店 | `rows[].sales_store_name` | /store-expense/store-ranking | `sales_store_name` | — | mv_store_operating_expense_monthly | +| 实收 | `rows[].received` | 同上 | `received` | — | 同上.received | +| 费用合计 | `rows[].operating_expense` | 同上 | `operating_expense` | — | 同上.operating_expense | +| 费用率 | `rows[].operating_expense_rate_pct` | 同上 | `operating_expense_rate_pct` | — | 同上 | +| 人工率 | `rows[].wage_rate_pct` | 同上 | `wage_rate_pct` | — | 同上 | +| 租金率 | `rows[].rent_rate_pct` | 同上 | `rent_rate_pct` | — | 同上 | +| 水电率 | `rows[].utility_rate_pct` | 同上 | `utility_rate_pct` | — | 同上 | +| 贡献利润 | `rows[].actual_store_contribution` | 同上 | `actual_store_contribution` | — | 同上 | +| 贡献率 | `rows[].actual_store_contribution_rate_pct` | 同上 | `actual_store_contribution_rate_pct` | — | 同上 | +| 坪效 | `rows[].received_per_sqm` | 同上 | `received_per_sqm` | — | 同上 | + +> 筛选条件:filter支持 profitable/loss/zero_sales。排序白名单校验。 + +--- + +### Tab3:门店贡献利润(ContributionTab) + +#### 门店贡献利润分析(服务端分页) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 门店 | `rows[].sales_store_name` | /store-expense/store-contribution | `sales_store_name` | — | mv_store_operating_expense_monthly | +| 实收 | `rows[].received` | 同上 | `received` | — | 同上 | +| 理论食材成本 | `rows[].theoretical_cost` | 同上 | `theoretical_cost` | — | 同上.theoretical_cost | +| 实际食材成本 | `rows[].actual_food_cost` | 同上 | `actual_food_cost` | — | 同上.actual_food_cost | +| 营业费用 | `rows[].operating_expense` | 同上 | `operating_expense` | — | 同上 | +| 理论贡献 | `rows[].theoretical_store_contribution` | 同上 | `theoretical_store_contribution` | — | 同上 | +| 理论贡献率 | `rows[].theoretical_store_contribution_rate_pct` | 同上 | `theoretical_store_contribution_rate_pct` | — | 同上 | +| 实际贡献 | `rows[].actual_store_contribution` | 同上 | `actual_store_contribution` | `received - actual_food_cost - operating_expense` | 同上 | +| 实际贡献率 | `rows[].actual_store_contribution_rate_pct` | 同上 | `actual_store_contribution_rate_pct` | — | 同上 | +| 贡献差异 | `rows[].contribution_variance` | 同上 | `contribution_variance` | `actual_store_contribution - theoretical_store_contribution` | 同上 | + +> ⚠️ **ContributionTab 默认排序方向问题**:前端 `order` 初始值为 `'asc'`(升序),但后端 `/store-contribution` 的 `order` 参数处理为 `=== 'desc' ? 'DESC' : 'ASC'`,即非'desc'均为'ASC'。这意味着默认按贡献率升序(最差门店在前),这是合理的行为。但前端 `defaultOrder="asc"` 与 `ContributionTab` 的 `useState<'asc' | 'desc'>('asc')` 一致,无问题。 + +--- + +### Tab4:房租及租约风险(RentRiskTab) + +#### 房租及租约风险(服务端分页 + riskOnly切换) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 门店 | `rows[].sales_store_name` | /store-expense/rent-risk | `sales_store_name` | — | mv_store_operating_expense_monthly | +| 实收 | `rows[].received` | 同上 | `received` | — | 同上 | +| 租金 | `rows[].rent_expense` | 同上 | `rent_expense` | — | 同上 | +| 租金率 | `rows[].rent_rate_pct` | 同上 | `rent_rate_pct` | — | 同上 | +| 面积(㎡) | `rows[].area_sqm` | 同上 | `area_sqm` | — | 同上 | +| 坪效 | `rows[].received_per_sqm` | 同上 | `received_per_sqm` | — | 同上 | +| 租约到期 | `rows[].lease_expiry_date` | 同上 | `lease_expiry_date` | — | 同上.lease_expiry_date | +| 风险等级 | `rows[].risk_level` | 同上 | `risk_level` | CASE:≤3月=即将到期, ≤12月=年内到期, ≤18月=明年上半年到期, rent>20%=租金占比偏高, else=正常 | — | +| 建议 | `rows[].suggestion` | 同上 | `suggestion` | CASE:按到期/租金率生成建议文本 | — | + +> **riskOnly 筛选**:`lease_expiry_date <= month + 12 months OR rent_rate_pct > 20`。 +> ⚠️ **租约到期日期显示**:前端使用 `new Date(r.lease_expiry_date).toLocaleDateString('zh-CN')`,后端返回的是日期类型,可能包含时间部分。根据规范应使用 `substring(0, 10)` 格式化。 + +--- + +### Tab5:外卖佣金分析(DeliveryTab) + +#### 外卖佣金分析(服务端分页) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 门店 | `rows[].sales_store_name` | /store-expense/delivery-commission | `sales_store_name` | — | mv_store_operating_expense_monthly | +| 实收 | `rows[].received` | 同上 | `received` | — | 同上 | +| 外卖收入 | `rows[].delivery_received` | 同上 | `delivery_received` | — | 同上 | +| 外卖占比 | `rows[].delivery_sales_share_pct` | 同上 | `delivery_sales_share_pct` | — | 同上 | +| 佣金支出 | `rows[].delivery_commission_expense` | 同上 | `delivery_commission_expense` | — | 同上 | +| 佣金率 | `rows[].commission_to_delivery_sales_pct` | 同上 | `commission_to_delivery_sales_pct` | — | 同上 | +| 综合平台成本率 | `rows[].combined_platform_cost_rate_pct` | 同上 | `combined_platform_cost_rate_pct` | — | 同上 | +| 外卖类型 | `rows[].delivery_type` | 同上 | `delivery_type` | CASE:>40%=重度依赖, >25%=外卖占比较高, >10%=正常, else=以堂食为主 | — | +| 建议 | `rows[].suggestion` | 同上 | `suggestion` | CASE:按佣金率/外卖占比/综合成本率生成建议 | — | + +> 筛选条件:`delivery_received > 0`。 + +--- + +### Tab6:人效坪效(EfficiencyTab) + +#### 人效坪效分析(服务端分页) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 门店 | `rows[].sales_store_name` | /store-expense/efficiency | `sales_store_name` | — | mv_store_operating_expense_monthly | +| 实收 | `rows[].received` | 同上 | `received` | — | 同上 | +| 面积(㎡) | `rows[].area_sqm` | 同上 | `area_sqm` | — | 同上 | +| 坪效 | `rows[].received_per_sqm` | 同上 | `received_per_sqm` | — | 同上 | +| 人工成本 | `rows[].wage_expense` | 同上 | `wage_expense` | — | 同上 | +| 人工成本率 | `rows[].wage_rate_pct` | 同上 | `wage_rate_pct` | — | 同上 | +| 人效(元/元人工) | `rows[].revenue_per_wage` | 同上 | `revenue_per_wage` | `received / wage_expense` | 同上 | +| 账单数 | `rows[].bill_count` | 同上 | `bill_count` | — | 同上 | +| 客单价 | `rows[].avg_ticket_size` | 同上 | `avg_ticket_size` | `received / bill_count` | 同上 | +| 效率等级 | `rows[].efficiency_level` | 同上 | `efficiency_level` | CASE:<1000=坪效偏低, <2000=坪效一般, <4000=坪效良好, else=坪效优秀 | — | +| 建议 | `rows[].suggestion` | 同上 | `suggestion` | CASE:按人工率/坪效/面积生成建议 | — | + +> 筛选条件:`received > 0 AND area_sqm IS NOT NULL`。 +> ⚠️ **效率等级缺少"坪效极低"档位**:后端 `efficiency_level` CASE 只有4档(偏低/一般/良好/优秀),但前端 `EfficiencyTab` 的颜色判断有5档(极低<500/偏低<1000/一般/良好/优秀),前端 `efficiency_level === '坪效极低'` 永远不会匹配。后端 loss-diagnosis 中的 `efficiency_status` 才有"坪效极低"档(<500)。 + +--- + +### Tab7:固定/变动费用(FixedVariableTab) + +#### 固定/变动费用拆分(服务端分页) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 门店 | `rows[].sales_store_name` | /store-expense/fixed-variable | `sales_store_name` | — | mv_store_operating_expense_monthly | +| 实收 | `rows[].received` | 同上 | `received` | — | 同上 | +| 固定费用 | `rows[].fixed_expense` | 同上 | `fixed_expense` | `rent_expense + dorm_expense + repair_clean_expense * 0.5` | 同上 | +| 固定费用率 | `rows[].fixed_rate_pct` | 同上 | `fixed_rate_pct` | `fixed_expense / received * 100` | 同上 | +| 变动费用 | `rows[].variable_expense` | 同上 | `variable_expense` | `wage_expense + utility_expense + delivery_commission_expense + card_fee_expense + repair_clean_expense * 0.5` | 同上 | +| 变动费用率 | `rows[].variable_rate_pct` | 同上 | `variable_rate_pct` | `variable_expense / received * 100` | 同上 | +| 边际贡献(扣变动) | `rows[].contribution_after_variable` | 同上 | `contribution_after_variable` | `received - actual_food_cost - wage_expense - utility_expense - delivery_commission_expense - card_fee_expense - repair_clean_expense * 0.5` | 同上 | +| 盈亏平衡销售额 | `rows[].break_even_sales` | 同上 | `break_even_sales` | `fixed_expense`(即 rent_expense + dorm_expense + repair_clean_expense * 0.5) | 同上 | + +> ⚠️ **盈亏平衡销售额计算错误**:后端 `break_even_sales` 直接等于 `fixed_expense`(固定费用),但正确的盈亏平衡公式应为 `固定费用 ÷ (1 - 食材成本率)` 或 `固定费用 ÷ 边际贡献率`。当前计算仅返回固定费用金额本身,并非真正的盈亏平衡点。Tab8 `break-even` 中的计算才是正确的。 + +--- + +### Tab8:盈亏平衡分析(BreakEvenTab) + +#### 盈亏平衡分析(服务端分页) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 门店 | `rows[].sales_store_name` | /store-expense/break-even | `sales_store_name` | — | mv_store_operating_expense_monthly | +| 实收 | `rows[].received` | 同上 | `received` | — | 同上 | +| 食材成本 | `rows[].actual_food_cost` | 同上 | `actual_food_cost` | — | 同上 | +| 食材成本率 | `rows[].food_cost_rate_pct` | 同上 | `food_cost_rate_pct` | `actual_food_cost / received * 100` | 同上 | +| 营业费用 | `rows[].operating_expense` | 同上 | `operating_expense` | — | 同上 | +| 费用率 | `rows[].expense_rate_pct` | 同上 | `expense_rate_pct` | `operating_expense / received * 100` | 同上 | +| 盈亏平衡销售额 | `rows[].break_even_sales` | 同上 | `break_even_sales` | `operating_expense / (1 - actual_food_cost/received)` | 同上 | +| 销售缺口 | `rows[].sales_gap` | 同上 | `sales_gap` | `received - break_even_sales` | 同上 | +| 安全边际率 | `rows[].safety_margin_pct` | 同上 | `safety_margin_pct` | `(received - break_even_sales) / break_even_sales * 100` | 同上 | +| 安全状态 | `rows[].safety_status` | 同上 | `safety_status` | CASE:贡献边际≤0=无法盈利, received<平衡点=未达盈亏平衡, <15%=接近, <30%=较低, else=充足 | — | + +> **正确的盈亏平衡公式**:`break_even_sales = operating_expense / (1 - food_cost_ratio)`,即 `营业费用 ÷ (1 - 食材成本率)`。与Tab7的简单固定费用公式不同。 + +--- + +### Tab9:亏损门店诊断(LossDiagnosisTab) + +#### 概览指标(4个MetricCard) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 亏损门店数 | `meta.total` | /store-expense/loss-diagnosis | `meta.total` | `count(*) WHERE actual_store_contribution <= 0 AND received > 0` | mv_store_operating_expense_monthly | +| P0 紧急 | `p0Count` | 同上 | 前端计算 | `rows.filter(priority === 'P0').length` | — | +| P1 整改 | `p1Count` | 同上 | 前端计算 | `rows.filter(priority === 'P1').length` | — | +| 亏损金额合计 | `totalLoss` | 同上 | 前端计算 | `rows.reduce(sum + actual_store_contribution)` | — | + +> ⚠️ **P0/P1/亏损金额仅统计当前页**:`p0Count`、`p1Count`、`totalLoss` 是从当前页 `rows` 计算的,而非全量数据。当翻页时这些指标会变化,不具备全局统计意义。应在后端返回全量统计或单独查询。 + +#### 亏损门店诊断明细(服务端分页 + 弹窗详情) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 门店 | `rows[].sales_store_name` | /store-expense/loss-diagnosis | `sales_store_name` | — | mv_store_operating_expense_monthly | +| 优先级 | `rows[].priority` | 同上 | 后端计算 | CASE:贡献率<-20%=P0, <-5%=P1, <0=P2, else=P3 | — | +| 亏损类型 | `rows[].loss_type` | 同上 | `loss_type` | CASE:理论贡献≤0=理论即亏损, 实际超耗=实际超耗导致亏损, else=费用过高导致亏损 | — | +| 实收 | `rows[].received` | 同上 | `received` | — | 同上 | +| 贡献利润 | `rows[].actual_store_contribution` | 同上 | `actual_store_contribution` | — | 同上 | +| 贡献率 | `rows[].actual_store_contribution_rate_pct` | 同上 | `actual_store_contribution_rate_pct` | — | 同上 | +| 人工率 | `rows[].wage_rate_pct` | 同上 | `wage_rate_pct` | — | 同上 | +| 租金率 | `rows[].rent_rate_pct` | 同上 | `rent_rate_pct` | — | 同上 | +| 坪效 | `rows[].received_per_sqm` | 同上 | `received_per_sqm` | — | 同上 | +| 亏损原因 | `rows[].diagnosis_reasons` | 同上 | 后端JS生成 | 按收入/食材/人工/租金/水电/外卖/坪效/租约/亏损类型多维度拼接 | — | +| 建议动作 | `rows[].suggested_actions` | 同上 | 后端JS生成 | 对应改进建议动作列表 | — | + +> **诊断状态字段**(弹窗详情):`revenue_status`、`food_cost_status`、`wage_status`、`rent_status`、`utility_status`、`delivery_status`、`efficiency_status`、`lease_status` 均由后端SQL CASE生成。 +> ⚠️ **租约到期日期显示**:弹窗中使用 `new Date(store.lease_expiry_date).toLocaleDateString('zh-CN')`,应使用 `substring(0, 10)` 规范格式。 + +--- + +### Tab10:关停/续租/改造评估(StoreEvaluationTab) + +#### 概览指标(4个MetricCard) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 关停评估 | `evalStats['关停评估']` | /store-expense/store-evaluation | `meta.evalStats.关停评估` | 后端全量统计 | mv_store_operating_expense_monthly | +| 改造评估 | `evalStats['改造评估']` | 同上 | `meta.evalStats.改造评估` | 后端全量统计 | 同上 | +| 续租评估 | `evalStats['续租评估']` | 同上 | `meta.evalStats.续租评估` | 后端全量统计 | 同上 | +| 关注观察 | `evalStats['关注观察']` | 同上 | `meta.evalStats.关注观察` | 后端全量统计 | 同上 | + +> **evalStats 全量统计**:后端在返回分页数据的同时,额外执行一条全量统计SQL获取各评估类型数量,不受分页影响。与Tab9的仅当前页统计形成对比。 + +#### 门店评估明细(服务端分页 + 弹窗详情) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 门店 | `rows[].sales_store_name` | /store-expense/store-evaluation | `sales_store_name` | — | mv_store_operating_expense_monthly | +| 优先级 | `rows[].priority` | 同上 | `priority` | CASE:received<5000=P0, 贡献率<-20%=P0, <-10%=P1, <0=P2, <10=P3, else=P4 | — | +| 评估类型 | `rows[].evaluation_type` | 同上 | `evaluation_type` | CASE:received<5000=关停评估, 贡献率<-20%&租约到期=关停评估, 贡献率<-10%&坪效<1000=关停评估, 贡献率<0&租约到期=关停或迁址评估, 贡献率<0&坪效<1000&面积>400=改造评估, 贡献率<0&人工率>35=改造评估, 贡献率<0=关注观察, 租约≤3月=续租评估, 贡献率<10=关注观察, else=正常经营 | — | +| 实收 | `rows[].received` | 同上 | `received` | — | 同上 | +| 贡献利润 | `rows[].actual_store_contribution` | 同上 | `actual_store_contribution` | — | 同上 | +| 贡献率 | `rows[].actual_store_contribution_rate_pct` | 同上 | `actual_store_contribution_rate_pct` | — | 同上 | +| 坪效 | `rows[].received_per_sqm` | 同上 | `received_per_sqm` | — | 同上 | +| 租约到期 | `rows[].lease_expiry_date` | 同上 | `lease_expiry_date` | 后端格式化为 `toISOString().split('T')[0]` | 同上 | +| 评估详情 | `rows[].evaluation_detail` | 同上 | 后端JS生成 | 按评估类型生成详细说明 | — | + +--- + +## 八、页面6:风险与内控 RiskPage + +> 单页面无子组件文件,4个Tab切换(异常账单/全额优惠/空单/收银员风险),3个API(全部GET)。 +> 核心数据源:`mv_risk_anomaly`(异常账单物化视图)、`mv_risk_zero`(零实收账单物化视图)、`mv_risk_cashier`(收银员风险物化视图)。均按 `month = to_char($1::date, 'YYYY-MM')` 过滤。 + +### 概览指标(5个MetricCard) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 异常账单数 | `totalAnomaly` | /risk/anomaly | `meta.total` | `count(*)` | mv_risk_anomaly | +| 全额优惠账单 | `zeroMeta.full_discount` | /risk/zero-received | `meta.full_discount` | `count(*) FILTER (zero_received_type='全额优惠')` | mv_risk_zero | +| 空单账单 | `zeroMeta.empty_bill` | 同上 | `meta.empty_bill` | `count(*) FILTER (zero_received_type='无消费无优惠')` | 同上 | +| 高风险收银员(≥10%) | `highRiskCashiers` | /risk/cashier | 前端计算 | `cashierRows.filter(anomaly_rate_pct >= 10).length` | mv_risk_cashier | +| 平均异常率 | `avgAnomalyRate` | 同上 | 前端计算 | `sum(anomaly_rate_pct) / cashierRows.length` | 同上 | + +> ⚠️ **highRiskCashiers 和 avgAnomalyRate 基于全量收银员数据计算**:`/risk/cashier` 不分页,返回全量收银员列表,所以这两个指标是全局准确的。与StoreExpensePage Tab9的当前页统计问题不同。 + +### 收银员异常账单数TOP15(BarChart) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 收银员 | `cashierChartData[].cashier` | /risk/cashier | `cashier` | — | mv_risk_cashier | +| 异常账单数 | `cashierChartData[].anomaly_bills` | 同上 | `anomaly_bills` | `anomaly_no_received + anomaly_discount_over + anomaly_unbalanced` | 同上 | + +> 图表数据:取 `cashierRows` 按 `anomaly_bills` 降序排列前15条。 + +### Tab1:异常账单(anomaly) + +#### 异常账单明细(服务端分页 + 多维筛选) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 门店 | `anomalyRows[].store_name` | /risk/anomaly | `store_name` | — | mv_risk_anomaly | +| 账单号 | `anomalyRows[].bill_no` | 同上 | `bill_no` | — | 同上 | +| 餐段 | `anomalyRows[].meal_period` | 同上 | `meal_period` | — | 同上 | +| 消费额 | `anomalyRows[].consumption` | 同上 | `consumption` | — | 同上 | +| 优惠 | `anomalyRows[].discount_total` | 同上 | `discount_total` | — | 同上 | +| 实收 | `anomalyRows[].received_total` | 同上 | `received_total` | — | 同上 | +| 异常原因 | `anomalyRows[].anomaly_reason` | 同上 | `anomaly_reason` | — | 同上 | +| 收银员 | `anomalyRows[].cashier` | 同上 | `cashier` | — | 同上 | +| 结账时间 | `anomalyRows[].closed_at` | 同上 | `closed_at` | — | 同上 | + +> **筛选条件**:store(门店精确匹配)、reason(异常原因精确匹配)、cashier(ILIKE模糊搜索,前端400ms debounce)。 +> **排序白名单**:`consumption`、`discount_total`、`received_total`、`closed_at`。 +> **筛选合计**:后端在count查询中同时返回 `sum_consumption`、`sum_discount`、`sum_received`,前端显示筛选合计行。 +> **结账时间格式化**:前端使用 `r.closed_at?.substring(0, 16)` 截取前16位,符合日期格式化规范。 + +### Tab2:全额优惠(full_discount) + +#### 全额优惠账单(服务端分页) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 门店 | `zeroRows[].store_name` | /risk/zero-received | `store_name` | — | mv_risk_zero | +| 账单号 | `zeroRows[].bill_no` | 同上 | `bill_no` | — | 同上 | +| 餐段 | `zeroRows[].meal_period` | 同上 | `meal_period` | — | 同上 | +| 消费额 | `zeroRows[].consumption` | 同上 | `consumption` | — | 同上 | +| 优惠 | `zeroRows[].discount_total` | 同上 | `discount_total` | — | 同上 | +| 收银员 | `zeroRows[].cashier` | 同上 | `cashier` | — | 同上 | +| 结账时间 | `zeroRows[].closed_at` | 同上 | `closed_at` | — | 同上 | + +> API请求参数:`type='全额优惠'`,后端按 `zero_received_type = '全额优惠'` 过滤。 +> 排序:后端固定 `ORDER BY consumption DESC`,前端 `sortOptions` 不生效(未传sort参数到后端)。 + +### Tab3:空单(empty_bill) + +#### 空单账单(服务端分页) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 同Tab2 | 同上 | /risk/zero-received | 同上 | 同上 | mv_risk_zero | + +> API请求参数:`type='无消费无优惠'`,后端按 `zero_received_type = '无消费无优惠'` 过滤。 +> ⚠️ **Tab2和Tab3共用同一API和组件结构**:`zeroType` 切换时触发重新请求,`zeroPage` 重置为1。 + +### Tab4:收银员风险(cashier) + +#### 收银员风险明细(全量不分页) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 收银员 | `cashierRows[].cashier` | /risk/cashier | `cashier` | — | mv_risk_cashier | +| 账单数 | `cashierRows[].bill_count` | 同上 | `bill_count` | — | 同上 | +| 实收 | `cashierRows[].received` | 同上 | `received` | — | 同上 | +| 异常账单数 | `cashierRows[].anomaly_bills` | 同上 | `anomaly_bills` | `anomaly_no_received + anomaly_discount_over + anomaly_unbalanced` | 同上 | +| 异常率 | `cashierRows[].anomaly_rate_pct` | 同上 | `anomaly_rate_pct` | `(anomaly_bills / bill_count) * 100` | 同上 | +| 异常消费额 | `cashierRows[].anomaly_consumption` | 同上 | `consumption_total` | — | 同上 | + +> ⚠️ **前端字段名与后端不匹配**:前端列 `anomaly_consumption` 对应后端返回的 `consumption_total`,前端 `render: (r) => formatCurrency(r.anomaly_consumption)` 访问的 `r.anomaly_consumption` 在后端返回中不存在(后端返回 `consumption_total`),导致该列始终显示 ¥0.00。 +> **双击行跳转**:`onRowDoubleClick` 设置 `anomalyCashier` 并切换到 anomaly Tab,用收银员名筛选异常账单。 +> **排序**:前端 `sortOptions` 有5个选项,但后端固定 `ORDER BY anomaly_bills DESC`,前端排序不生效(未传sort参数到后端)。 + +--- + +## 九、页面7:成本与库存 CostPage + +> 单页面无子组件文件,4个区块(成本概览+散点图+成本对比表+库存效率+原料分类基准),3个API(全部GET)。 +> 核心数据源:`analytics.mv_store_theoretical_actual_cost_monthly`(理论vs实际成本月度物化视图)、`analytics.mv_inventory_cost_classified_monthly`(库存分类成本月度物化视图)、`analytics.mv_store_area_efficiency_monthly`(门店面积效率月度物化视图)。均按 `month_start = $1` 过滤。 + +### 区块1:成本概览(4个MetricCard) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 平均理论成本率 | `avgTheoreticalRate` | /cost/comparison | 前端计算 | `avg(theoretical_cost_rate_pct)` 排除口径异常 | mv_store_theoretical_actual_cost_monthly | +| 平均实际成本率 | `avgActualRate` | 同上 | 前端计算 | `avg(actual_food_cost_rate_pct)` 排除口径异常 | 同上 | +| 高偏差门店(>20%) | `highVarianceCount` | 同上 | 前端计算 | `filter(variance_to_theoretical_pct > 20).length` 排除口径异常 | 同上 | +| 口径异常门店 | `abnormalRows.length` | 同上 | 前端计算 | `filter(variance_level includes '口径异常').length` | 同上 | + +> **口径异常处理**:前端将 `variance_level` 包含"口径异常"的门店分离为 `abnormalRows`,不纳入平均成本率和高偏差统计。显示异常门店名称列表。 +> **全量数据**:`/cost/comparison` 不分页,返回全量门店数据,前端统计是全局准确的。 + +### 区块2:理论vs实际成本率散点图(ScatterChart) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 门店名 | `scatterData[].name` | /cost/comparison | `store_name` | — | mv_store_theoretical_actual_cost_monthly | +| 理论成本率 | `scatterData[].theoretical` | 同上 | `theoretical_cost_rate_pct` | — | 同上 | +| 实际成本率 | `scatterData[].actual` | 同上 | `actual_food_cost_rate_pct` | — | 同上 | +| 偏差 | `scatterData[].variance` | 同上 | `variance_to_theoretical_pct` | — | 同上 | + +> 散点图排除口径异常门店。X轴=理论成本率,Y轴=实际成本率,对角线参考线表示理论=实际。偏离对角线越多偏差越大。 +> **动态坐标轴**:`useMemo` 计算数据范围 ±1 作为domain,空数据时默认 [0,40]×[0,50]。 + +### 区块3:门店成本对比表(FilterableTable,全量不分页) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 门店 | `costRows[].store_name` | /cost/comparison | `store_name` | — | mv_store_theoretical_actual_cost_monthly | +| 理论成本率 | `costRows[].theoretical_cost_rate_pct` | 同上 | `theoretical_cost_rate_pct` | — | 同上 | +| 实际成本率 | `costRows[].actual_food_cost_rate_pct` | 同上 | `actual_food_cost_rate_pct` | — | 同上 | +| 偏差 | `costRows[].variance_to_theoretical_pct` | 同上 | `variance_to_theoretical_pct` | — | 同上 | +| 偏差等级 | `costRows[].variance_level` | 同上 | `variance_level` | — | 同上 | +| 实际食材成本 | `costRows[].actual_food_cost` | 同上 | `actual_food_cost` | — | 同上 | + +> **筛选**:`filterKey="variance_level"` 按偏差等级筛选。**排序**:前端 `sortOptions` 有5个选项,但后端固定 `ORDER BY variance_to_theoretical_pct DESC`,前端排序为客户端排序(全量数据)。 +> ⚠️ **前端排序 vs 后端排序**:`/cost/comparison` 不分页返回全量数据,`FilterableTable` 未设 `serverSide`,排序在前端完成,是有效的。 + +### 区块4:库存效率(FilterableTable,懒加载) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 门店 | `invRows[].store_name` | /cost/inventory | `store_name` | — | mv_store_area_efficiency_monthly + mv_store_theoretical_actual_cost_monthly | +| 业态 | `invRows[].business_type` | 同上 | `business_type` | — | mv_store_area_efficiency_monthly | +| 规模 | `invRows[].scale_tier` | 同上 | `scale_tier` | — | 同上 | +| 库存天数 | `invRows[].estimated_inventory_days` | 同上 | `estimated_inventory_days` | — | 同上 | +| 期末库存 | `invRows[].ending_inventory_amount` | 同上 | `ending_inventory_amount` | — | mv_store_theoretical_actual_cost_monthly | +| 负耗用行数 | `invRows[].negative_item_lines` | 同上 | `negative_item_lines` | — | 同上 | + +> **懒加载**:`enabled: invOpen`,仅在CollapsibleSection展开时请求。`onToggle={setInvOpen}` 控制展开状态。 +> **数据关联**:`mv_store_area_efficiency_monthly` LEFT JOIN `mv_store_theoretical_actual_cost_monthly` ON store_code + month_start。 + +### 区块5:原料分类成本基准(FilterableTable,懒加载) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 门店 | `catRows[].store_name` | /cost/category-benchmark | `store_name` | — | mv_inventory_cost_classified_monthly | +| 财务分类 | `catRows[].finance_category` | 同上 | `finance_category` | — | 同上 | +| 实际成本 | `catRows[].actual_category_cost` | 同上 | `actual_category_cost` | `sum(consumption_amount) GROUP BY store_name, finance_category` | 同上 | +| 每万元成本 | `catRows[].cost_per_10k_sales` | 同上 | `cost_per_10k_sales` | `actual_category_cost / sales_received * 10000` | 同上 + mv_store_theoretical_actual_cost_monthly | +| 同业中位 | `catRows[].peer_median_cost_per_10k` | 同上 | `peer_median_cost_per_10k` | `percentile_cont(0.5) WITHIN GROUP (ORDER BY cost_per_10k_sales)` 按分类 | — | +| 超出同业 | `catRows[].excess_vs_peer_per_10k` | 同上 | `excess_vs_peer_per_10k` | `cost_per_10k_sales - peer_median` | — | + +> **懒加载**:`enabled: catOpen`。**同业基准**:使用 `percentile_cont(0.5)` 计算各财务分类的每万元成本中位数作为同业基准。 + +--- + +## 十、页面8:会员与复购 MemberPage + +> 单页面无子组件文件,4个区块(会员概览+对比图+对比明细+复购率),2个API(全部GET)。 +> 核心数据源:`analytics.bill_fact`(账单事实表,按closed_at月份过滤)、`analytics.v_store_repeat_summary_monthly`(门店复购汇总月度视图,按month_start过滤)。 + +### 区块1:会员概览(4个MetricCard) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 会员账单占比 | `memberBillShare` | /member/comparison | 前端计算 | `memberRow.bill_count / (memberRow.bill_count + nonMemberRow.bill_count) * 100` | bill_fact | +| 会员收入占比 | `memberRevenueShare` | 同上 | 前端计算 | `memberRow.received / (memberRow.received + nonMemberRow.received) * 100` | 同上 | +| 平均复购率 | `avgRepeatRate` | /member/repeat | 前端计算 | `avg(repeat_rate_pct)` | v_store_repeat_summary_monthly | +| 低复购门店(<30%) | `lowRepeatCount` | 同上 | 前端计算 | `filter(repeat_rate_pct < 30).length` | 同上 | + +> **全量数据**:两个API均不分页,返回全量数据,前端统计全局准确。 + +### 区块2:会员vs非会员消费对比(BarChart + PieChart) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 客户类型 | `cmpChartData[].name` | /member/comparison | `customer_type` | `CASE WHEN member_id IS NULL THEN '非会员' ELSE '会员'` | bill_fact | +| 账单数 | `cmpChartData[].账单数` | 同上 | `bill_count` | `count(*)` | 同上 | +| 实收 | `cmpChartData[].实收` | 同上 | `received` | `sum(received_total)` | 同上 | +| 客单价 | `cmpChartData[].客单价` | 同上 | `avg_bill_value` | `avg(received_total)` | 同上 | + +> BarChart双Y轴:左轴=账单数+实收,右轴=客单价。PieChart显示会员/非会员账单数占比。 + +### 区块3:会员与非会员指标对比(FilterableTable,全量不分页) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 客户类型 | `cmpRows[].customer_type` | /member/comparison | `customer_type` | — | bill_fact | +| 账单数 | `cmpRows[].bill_count` | 同上 | `bill_count` | `count(*)` | 同上 | +| 实收 | `cmpRows[].received` | 同上 | `received` | `sum(received_total)` | 同上 | +| 客单价 | `cmpRows[].avg_bill_value` | 同上 | `avg_bill_value` | `avg(received_total)` | 同上 | +| 优惠率 | `cmpRows[].discount_rate_pct` | 同上 | `discount_rate_pct` | `sum(discount_total) / sum(consumption) * 100` | 同上 | +| 理论毛利率 | `cmpRows[].theoretical_margin_pct` | 同上 | `theoretical_margin_pct` | `sum(theoretical_profit) / sum(received_total) * 100` | 同上 | + +> 仅2行数据(会员/非会员),客户端排序有效。 + +### 区块4:门店复购率(FilterableTable,全量不分页) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 门店 | `repeatRows[].store_name` | /member/repeat | `store_name` | — | v_store_repeat_summary_monthly | +| 识别会员数 | `repeatRows[].identified_members` | 同上 | `identified_members` | — | 同上 | +| 复购会员数 | `repeatRows[].repeat_members` | 同上 | `repeat_members` | — | 同上 | +| 复购率 | `repeatRows[].repeat_rate_pct` | 同上 | `repeat_rate_pct` | — | 同上 | +| 人均消费次数 | `repeatRows[].avg_orders` | 同上 | `avg_orders` | — | 同上 | +| 复购收入占比 | `repeatRows[].repeat_revenue_share_pct` | 同上 | `repeat_revenue_share_pct` | — | 同上 | + +> **筛选**:`filterKey="store_name"` 按门店筛选。**排序**:前端 `sortOptions` 客户端排序(全量数据,有效)。后端固定 `ORDER BY repeat_rate_pct DESC`。 +> **复购率颜色**:≥50%绿色,≥30%黄色,<30%红色。 + +### 发现的问题汇总 + +> MemberPage 无发现新问题。页面结构简洁,API与前端字段匹配,全量数据统计准确,日期无特殊格式化需求。 + +--- + +## 十一、页面9:商品SKU管理 SKUPage + +> 单页面无子组件文件,5个区块(SKU概览+ABC分布图+品类分布+SKU明细+长尾治理),2个API(全部GET)。 +> 核心数据源:`analytics.mv_dish_sku_abc_monthly`(菜品SKU ABC分析月度物化视图,按month_start过滤)、`analytics.category_summary`(品类汇总表,无月份过滤)。 + +### 区块1:SKU概览(4个MetricCard) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 总SKU数 | `totalSku` | /sku/abc | 前端计算 | `data.length` | mv_dish_sku_abc_monthly | +| A类SKU(核心) | `abcSummary['A-核心']?.sku_count` | 同上 | 前端计算 | `reduce(abc_class='A-核心').count` | 同上 | +| C类SKU(长尾) | `cClassCount` | 同上 | 前端计算 | `abcSummary['C-长尾']?.sku_count` | 同上 | +| 低价值SKU(<¥1000) | `lowValueSku` | 同上 | 前端计算 | `filter(received_amount < 1000).length` | 同上 | + +> **全量数据**:`/sku/abc` 不分页,返回全量SKU列表,前端统计全局准确。 + +### 区块2:SKU ABC分布(PieChart) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| ABC分类 | `abcPieData[].name` | /sku/abc | `abc_class` | — | mv_dish_sku_abc_monthly | +| SKU数量 | `abcPieData[].value` | 同上 | 前端计算 | `reduce(sku_count++)` | 同上 | +| 实收 | `abcPieData[].received` | 同上 | 前端计算 | `reduce(received_amount +=)` | 同上 | + +> PieChart按ABC分类显示SKU数量分布,Tooltip同时显示SKU数和实收金额。 + +### 区块3:品类实收分布(BarChart) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 品类名 | `catRows[].category_name` | /sku/category | `category_name` | — | category_summary | +| 实收 | `catRows[].amount` | 同上 | `amount` | — | 同上 | + +> BarChart取 `catRows.slice(0, 10)` 前10个品类。水平柱状图,Y轴=品类名,X轴=金额。 +> ⚠️ **`/sku/category` 无月份过滤**:后端查询 `SELECT * FROM analytics.category_summary ORDER BY amount DESC`,不接受month参数,返回全量品类汇总。前端也未传month参数。如果品类数据需要按月过滤,此处存在口径不一致。 + +### 区块4:SKU明细(FilterableTable,全量不分页) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 菜品名称 | `skuRows[].dish_name` | /sku/abc | `dish_name` | — | mv_dish_sku_abc_monthly | +| 一级品类 | `skuRows[].category_level1` | 同上 | `category_level1` | — | 同上 | +| ABC分类 | `skuRows[].abc_class` | 同上 | `abc_class` | — | 同上 | +| 象限 | `skuRows[].sales_quadrant` | 同上 | `sales_quadrant` | — | 同上 | +| 覆盖门店 | `skuRows[].store_count` | 同上 | `store_count` | — | 同上 | +| 账单数 | `skuRows[].bill_count` | 同上 | `bill_count` | — | 同上 | +| 实收 | `skuRows[].received_amount` | 同上 | `received_amount` | — | 同上 | +| 占比 | `skuRows[].revenue_share_pct` | 同上 | `revenue_share_pct` | — | 同上 | +| 优惠率 | `skuRows[].discount_rate_pct` | 同上 | `discount_rate_pct` | — | 同上 | + +> **筛选**:`filterKey="abc_class"` 按ABC分类筛选。**排序**:前端客户端排序(全量数据,有效)。后端固定 `ORDER BY cumulative_revenue_share`。 + +### 区块5:长尾治理建议(3个可展开区块) + +#### 5a. 低价值SKU(received_amount < 1000) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 菜品名称 | `lowValueSkuRows[].dish_name` | /sku/abc | `dish_name` | — | mv_dish_sku_abc_monthly | +| 一级品类 | `lowValueSkuRows[].category_level1` | 同上 | `category_level1` | — | 同上 | +| ABC分类 | `lowValueSkuRows[].abc_class` | 同上 | `abc_class` | — | 同上 | +| 覆盖门店 | `lowValueSkuRows[].store_count` | 同上 | `store_count` | — | 同上 | +| 账单数 | `lowValueSkuRows[].bill_count` | 同上 | `bill_count` | — | 同上 | +| 实收 | `lowValueSkuRows[].received_amount` | 同上 | `received_amount` | — | 同上 | + +> 前端筛选:`received_amount < 1000`,按 `received_amount` 升序排列。`filterKey="category_level1"` 按品类筛选。 + +#### 5b. 单店专属SKU(store_count <= 1) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 同5a | `singleStoreSkuRows[]` | /sku/abc | 同上 | `filter(store_count <= 1)` | 同上 | + +#### 5c. 合并/归档候选(套餐/赠品/餐具类) + +| 显示指标 | 前端变量 | API | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------|---------| +| 同5a | `mergeCandidateRows[]` | /sku/abc | 同上 | `filter(dish_name includes 套餐/赠/餐具/打包/纸巾/调料包)` | 同上 | + +> 前端按菜品名称关键词筛选合并候选,按 `received_amount` 升序排列。 + +--- + +## 十二、页面10:企业协同管理 EnterprisePage + +> 单页面10个Tab,13个API(12个GET + 2个mutation),无MonthPicker。 +> 核心数据源:`analytics.v3_*` 系列业务管理表(供应商、采购订单、审批流、消息、HR、培训、营销、财务、闭环、审计)。 + +### Tab1:供应链SRM(supplier) + +| API | 数据源表 | 说明 | +|-----|---------|------| +| /enterprise/suppliers | analytics.v3_supplier_master | 供应商主数据,按overall_score降序 | +| /enterprise/purchase-orders | analytics.v3_purchase_order | 采购订单,按created_at降序,LIMIT 100 | + +> MetricCard:供应商总数、战略供应商、采购订单数、淘汰供应商。 +> PieChart:供应商分级分布(战略/优选/合格/淘汰)。 +> 日期格式化:`r.order_date?.substring(0, 10)` ✅ + +### Tab2:供应商对标(benchmark) + +| API | 数据源表 | 说明 | +|-----|---------|------| +| /enterprise/supplier-benchmark | v3_purchase_order_item + v3_purchase_order + v3_supplier_master | 跨供应商同SKU价格对比,CTE查询 | + +> MetricCard:对标SKU数、价格差异大(>20%)、有优化空间(10-20%)、潜在节约。 +> 后端返回 `{ summary, benchmarks }` 结构,前端正确解构。 + +### Tab3:审批流(approval) + +| API | 数据源表 | 说明 | +|-----|---------|------| +| /enterprise/approvals | analytics.v3_approval_request | 审批请求列表,LIMIT 100 | +| POST /enterprise/approvals/:id/approve | 同上 + v3_approval_step | 审批操作mutation | + +> MetricCard:审批总数、待审批、已审批。 +> 日期格式化:`(r.created_at || '').substring(0, 19).replace('T', ' ')` ✅ + +### Tab4:消息中心(notification) + +| API | 数据源表 | 说明 | +|-----|---------|------| +| /enterprise/notifications | analytics.v3_notification | 按user_id或user_role过滤,LIMIT 50 | +| PATCH /enterprise/notifications/:id/read | 同上 | 标记已读mutation | + +> MetricCard:消息总数、未读、已读。 + +### Tab5:HR人才(hr) + +| API | 数据源表 | 说明 | +|-----|---------|------| +| /enterprise/hr/talent-matrix | analytics.dim_employee + analytics.store_task | 人才九宫格(绩效×潜力),LIMIT 200 | + +> MetricCard:人才总数、明星员工、核心员工、潜力员工。 +> ⚠️ **potential_score 硬编码为60**:后端 `COALESCE(60, 60) AS potential_score`,这意味着所有员工的潜力分都是60,九宫格的"潜力"维度实际上没有区分度。只有performance_score有变化(基于store_task完成情况)。 + +### Tab6:培训LMS(lms) + +| API | 数据源表 | 说明 | +|-----|---------|------| +| /enterprise/training/courses | analytics.v3_training_course | 课程列表 | +| /enterprise/training/records | analytics.v3_learning_record | 学习记录,LIMIT 100 | + +> MetricCard:课程总数、学习记录数、已完成、未完成。 +> 日期格式化:`(r.created_at || '').substring(0, 10)` ✅ + +### Tab7:营销MA(marketing) + +| API | 数据源表 | 说明 | +|-----|---------|------| +| /enterprise/campaigns | analytics.v3_marketing_campaign | 营销活动列表,LIMIT 100 | +| /enterprise/coupons | analytics.v3_coupon | 券码列表,LIMIT 100 | + +> MetricCard:活动总数、进行中、券码总数、已核销。 +> 日期格式化:`(r.start_date || '').substring(0, 10)` ✅ + +### Tab8:财务ERP(finance) + +| API | 数据源表 | 说明 | +|-----|---------|------| +| /enterprise/budgets | analytics.v3_budget | 按年度过滤,默认当前年 | + +> MetricCard:预算总数、总预算、总实际。 +> 日期格式化:`r.month?.substring(0, 10)` ✅ + +### Tab9:闭环验证(loop) + +| API | 数据源表 | 说明 | +|-----|---------|------| +| /enterprise/loop-verification | analytics.v3_loop_verification | 闭环验证列表,LIMIT 100 | + +> MetricCard:验证总数、已完成、需升级。 +> 日期格式化:`(r.check_date || '').substring(0, 10)` ✅ + +### Tab10:审计日志(audit) + +| API | 数据源表 | 说明 | +|-----|---------|------| +| /enterprise/audit-logs | analytics.v3_audit_log | 审计日志,LIMIT 100 | + +> 日期格式化:`(r.created_at || '').substring(0, 19).replace('T', ' ')` ✅ + +--- + +## 十三、页面11:态势感知 SituationalAwarenessPage + +> 单页面4个Tab(健康度/预警/关联/趋势),4个API(全部GET),有MonthPicker。 +> 核心数据源:`analytics.mv_store_risk_rating_monthly`、`analytics.mv_store_theoretical_actual_cost_monthly`、`analytics.mv_store_repeat_summary_monthly`、`analytics.store_task`、`analytics.mv_daily_revenue`、`public.dish_cost_analysis_summary`、`salary_detail_records`、`analytics.mv_store_platform_economics_monthly`、`bill_records`、`mv_bill_hourly`、`mv_store_hourly_staffing`、`public.store_name_mapping`。 + +### Tab1:健康度评分(health) + +#### API: /situational-awareness/health-score + +| 显示指标 | 前端变量 | API字段 | 计算公式 | 数据源表 | +|---------|---------|---------|---------|---------| +| 门店 | `rows[].store_name` | `store_name` | — | mv_store_risk_rating_monthly | +| 健康分 | `rows[].health_score` | `health_score` | 8维加权求和(满分100) | 多表CTE | +| 状态 | `rows[].health_status` | `health_status` | ≥75健康, ≥55亚健康, <55需干预 | — | +| 风险 | `rows[].risk_level` | `risk_level` | — | mv_store_risk_rating_monthly | +| 实收 | `rows[].received` | `received` | — | 同上 | +| 客单价 | `rows[].avg_bill_value` | `avg_bill_value` | — | 同上 | +| 毛利率 | `rows[].avg_margin` | `avg_margin` | `COALESCE(theoretical_margin_pct, 0)` | 同上 | +| 成本差异率 | `rows[].avg_cost_variance_pct` | `avg_cost_variance_pct` | `avg(LEAST(variance_to_theoretical_pct, 50))` | mv_store_theoretical_actual_cost_monthly | +| 复购率 | `rows[].repeat_rate_pct` | `repeat_rate_pct` | `max(repeat_rate_pct)` | mv_store_repeat_summary_monthly | +| 任务完成率 | `rows[].task_completion_rate` | `task_completion_rate` | `count(status IN ('已验收','已回滚')) / count(*) * 100` | store_task | + +> **8维评分体系**:营收规模(20)、成本控制(20)、毛利率(15)、风险等级(10)、复购率(10)、会员占比(10)、任务完成(10)、客单价(5) = 100分。 +> **数据权限**:支持 `getDataScope` 按角色过滤门店。 +> **弹窗详情**:点击行展示RadarChart雷达图 + 各维度进度条 + 原始指标 + 跳转门店详情按钮。 +> **全量数据**:不分页,客户端排序和筛选。 + +### Tab2:预警中心(alerts) + +#### API: /situational-awareness/alerts + +| 显示指标 | 前端变量 | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------| +| 总预警 | `d.total` | `total` | `alerts.length` | 多源 | +| 红色预警 | `d.red` | `red` | `filter(level='red').length` | 多源 | +| 橙色预警 | `d.orange` | `orange` | `filter(level='orange').length` | 多源 | +| 预警列表 | `alerts[]` | `alerts` | 5类预警合并 | 多源 | + +> **5类预警**(Promise.all并行查询): +> 1. **营收异动**(revenue, red):日营收 < 月均70%,`mv_daily_revenue`,LIMIT 10 +> 2. **成本异动**(cost, red):成本差异率>30%,`dish_cost_analysis_summary`,LIMIT 10 +> 3. **人力异动**(hr, red/orange):考勤异常>3人,`salary_detail_records`,LIMIT 10 +> 4. **平台依赖**(platform, orange):外卖占比>40%,`mv_store_platform_economics_monthly`,LIMIT 10 +> 5. **任务逾期**(task, red/orange):逾期任务,`store_task`,LIMIT 10 +> +> **前端分页**:客户端分页 PAGE_SIZE=20,使用 `SearchSelect` 做门店/类型/等级三维筛选。 +> ⚠️ **预警查询部分不使用month参数**:revenue和cost预警查询不传month参数,使用全局最新数据。 + +### Tab3:关联分析(correlation) + +#### API: /situational-awareness/correlation + +返回4组关联分析数据: + +| 数据组 | 前端变量 | API字段 | 数据源表 | 说明 | +|--------|---------|---------|---------|------| +| 成本-风险 | `costRiskRows` | `cost_risk` | mv_store_risk_rating_monthly + mv_store_theoretical_actual_cost_monthly | 成本差异率×风险等级关联状态 | +| 渠道-会员 | `channelRiskRows` | `channel_risk` | mv_store_risk_rating_monthly + mv_store_platform_economics_monthly + mv_store_repeat_summary_monthly | 平台占比×会员占比三角分析 | +| 考勤-营收 | `hrRevenueRows` | `hr_revenue` | salary_detail_records + v_store_scorecard + store_name_mapping | 出勤率×营收人效关联 | +| 客流-人力 | `staffingRows` | `staffing_efficiency` | mv_bill_hourly + mv_store_hourly_staffing | 每小时账单×在岗人数匹配度 | + +> **散点图**:成本-风险关联,X=日均实收,Y=超耗率,颜色=风险等级。 +> **4个FilterableTable**:每个都有 `filterKey` + `sortOptions` + `statusFilterKey` + `statusOptions`,客户端排序。 +> ⚠️ **客流-人力匹配查询有容错处理**:`mv_store_hourly_staffing` 可能不存在,try-catch返回空数组。 +> ⚠️ **考勤-营收关联不使用month参数**:`salary_detail_records` 查询无month过滤,使用全量数据。`v_store_scorecard` 也无month过滤。 + +### Tab4:趋势预测(forecast) + +#### API: /situational-awareness/forecast + +| 数据组 | 前端变量 | API字段 | 数据源表 | 说明 | +|--------|---------|---------|---------|------| +| 客流预测 | `trafficRows` | `traffic_forecast` | bill_records | 按工作日/周末×小时P85分位预测 | +| 成本趋势 | `costTrendRows` | `cost_trend` | dish_cost_analysis_summary | 成本差异恶化TOP20 | +| 人员流失 | `turnoverRows` | `turnover_alert` | salary_detail_records | 有离职的门店流失率排名 | + +> **客流预测**:从 `bill_records` 按小时×日类型聚合,计算 avg/P50/P85/波动率,稳定性分级。 +> **LineChart**:工作日和周末分别画两条LineChart(avg_bills + p85_bills + p50_bills)。 +> ⚠️ **成本趋势查询不使用month参数**:`dish_cost_analysis_summary` 查询无month/import_id过滤,使用全量最新数据。LIMIT 20。 +> **人员流失**:按month参数过滤 leave_date 和 hire_date。 + +--- + +## 十四、页面12:门店详情 StoreDetailPage + +> 单页面7个Tab(概览/餐段/品类/成本/会员/异常/任务),8个API(全部GET),有MonthPicker。 +> 通过URL参数 `:code` 获取门店编码,复用 `/situational-awareness/health-score` API 获取健康度数据。 +> 核心数据源:`bill_records`、`analytics.mv_store_risk_rating_monthly`、`analytics.mv_store_platform_economics_monthly`、`analytics.mv_store_benchmark_composite_monthly`、`analytics.mv_store_action_priority_deep_monthly`、`analytics.bill_fact`、`analytics.mv_store_category_mix_monthly`、`analytics.mv_store_theoretical_actual_cost_monthly`、`analytics.mv_inventory_cost_classified_monthly`、`analytics.mv_store_member_opportunity_monthly`、`analytics.mv_store_repeat_summary_monthly`、`analytics.v_store_member_monthly_activity`、`mv_risk_anomaly`、`analytics.dim_store`。 + +### API总览 + +| API | Tab | 数据源表 | 说明 | +|-----|-----|---------|------| +| /stores/:code | 全局 | bill_records + mv_store_risk_rating_monthly + mv_store_platform_economics_monthly + mv_store_benchmark_composite_monthly + mv_store_action_priority_deep_monthly | 门店scorecard+风险+平台+基准+行动优先级 | +| /situational-awareness/health-score | 概览 | 同SituationalAwarenessPage Tab1 | 复用健康度API,前端filter by store_code | +| /stores/:code/daily | 概览 | bill_records | 日度实收趋势 | +| /stores/:code/meal-period | 餐段 | analytics.bill_fact | 餐段分析+全网对标 | +| /stores/:code/category-mix | 品类 | analytics.mv_store_category_mix_monthly | 门店vs公司品类结构 | +| /stores/:code/cost | 成本 | mv_store_theoretical_actual_cost_monthly + mv_inventory_cost_classified_monthly | 成本概览+原料分类对标 | +| /stores/:code/member | 会员 | mv_store_member_opportunity_monthly + mv_store_repeat_summary_monthly + v_store_member_monthly_activity | 会员占比+复购+月度活跃 | +| /stores/:code/anomalies | 异常 | mv_risk_anomaly | 异常账单分页查询 | +| /tasks | 任务 | analytics.store_task | 门店任务列表 | + +### Tab1:概览(overview) + +| 显示指标 | 前端变量 | API | API字段 | 数据源表 | +|---------|---------|-----|---------|---------| +| 门店名 | `sc.store_name` | /stores/:code | `scorecard.store_name` | bill_records | +| 健康分 | `health.health_score` | /situational-awareness/health-score | `health_score` | 多表CTE | +| 风险等级 | `risk.risk_level` | /stores/:code | `risk.risk_level` | mv_store_risk_rating_monthly | +| 经营象限 | `quadrant` | 同上 | 前端计算 | 日均营收≥18642 & 毛利率≥70% | +| 实收 | `sc.received` | 同上 | `scorecard.received` | bill_records | +| 账单数 | `sc.bill_count` | 同上 | `scorecard.bill_count` | 同上 | +| 客单价 | `sc.avg_bill_value` | 同上 | `scorecard.avg_bill_value` | 同上 | +| 优惠率 | `sc.discount_rate_pct` | 同上 | `scorecard.discount_rate_pct` | 同上 | +| 理论毛利率 | `sc.theoretical_margin_pct` | 同上 | `scorecard.theoretical_margin_pct` | 同上 | +| 会员占比 | `sc.member_bill_share_pct` | 同上 | `scorecard.member_bill_share_pct` | 同上 | +| 日均实收 | `risk.avg_daily_received` | 同上 | `risk.avg_daily_received` | mv_store_risk_rating_monthly | +| 平台实收 | `sd.platform.*` | 同上 | `platform.*` | mv_store_platform_economics_monthly | + +> **健康度雷达图**:复用SituationalAwarenessPage的8维评分体系,RadarChart + 进度条。 +> **日度趋势**:LineChart显示日实收和客单价。X轴 `business_date.substring(5, 10)` ✅。 +> **偏差指标**:前端硬编码公司均值 `{ daily_rev: 20144, bill: 36.8, ... }`,与后端计算的中位数(18642)不一致。 + +### Tab2:餐段分析(meal) + +| 显示指标 | 前端变量 | API字段 | 计算公式 | 数据源表 | +|---------|---------|-----|---------|---------| +| 餐段 | `mealRows[].meal_period` | `meal_period` | — | bill_fact | +| 账单数 | `mealRows[].bill_count` | `bill_count` | — | 同上 | +| 实收 | `mealRows[].received` | `received` | `sum(received_total)` | 同上 | +| 平均单价 | `mealRows[].avg_bill` | `avg_bill` | `sum(received_total)/count(*)` | 同上 | +| 全网均价 | `mealRows[].network_avg_bill` | `network_avg_bill` | 全网同餐段均值 | 同上 | +| vs全网 | `mealRows[].vs_network_pct` | `vs_network_pct` | `(avg_bill/network_avg_bill - 1) * 100` | — | + +> BarChart + FilterableTable,客户端排序。 + +### Tab3:品类结构(category) + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|-----|---------|---------| +| 门店品类 | `cat.store.*` | `store.*` | mv_store_category_mix_monthly | +| 公司品类 | `cat.company.*` | `company.*` | 同上(全量汇总) | + +> PieChart(门店品类占比) + BarChart(门店vs公司占比对比) + 4个MetricCard。 +> 品类包括:兰州拉面、西式简餐、外卖套餐、冷菜、丝路美食。 + +### Tab4:成本分析(cost) + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|-----|---------|---------| +| 理论成本率 | `cost.cost.theoretical_cost_rate_pct` | `theoretical_cost_rate_pct` | mv_store_theoretical_actual_cost_monthly | +| 实际成本率 | `cost.cost.actual_food_cost_rate_pct` | `actual_food_cost_rate_pct` | 同上 | +| 差异率 | `cost.cost.variance_to_theoretical_pct` | `variance_to_theoretical_pct` | 同上 | +| 差异等级 | `cost.cost.variance_level` | `variance_level` | 同上 | +| 原料分类 | `cost.categories[]` | `categories` | mv_inventory_cost_classified_monthly | + +> FilterableTable展示原料分类成本对标,含消耗金额、实际占比、公司基准、差异。 + +### Tab5:会员分析(member) + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|-----|---------|---------| +| 会员占比 | `member.opportunity.member_share_pct` | `opportunity.member_share_pct` | mv_store_member_opportunity_monthly | +| 公司均值 | `member.opportunity.company_member_share_pct` | `opportunity.company_member_share_pct` | 同上 | +| 复购率 | `member.repeat.repeat_rate_pct` | `repeat.repeat_rate_pct` | mv_store_repeat_summary_monthly | +| 复购收入占比 | `member.repeat.repeat_revenue_share_pct` | `repeat.repeat_revenue_share_pct` | 同上 | +| 活跃会员数 | `member.monthly.member_count` | `monthly.member_count` | v_store_member_monthly_activity | +| 人均订单 | `member.monthly.avg_orders` | `monthly.avg_orders` | 同上 | +| 人均消费 | `member.monthly.avg_received` | `monthly.avg_received` | 同上 | + +> 提升机会文案:`member.opportunity.conversion_bill_scenario` + `revenue_uplift_scenario`。 + +### Tab6:异常账单(anomaly) + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|-----|---------|---------| +| 账单号 | `anomalyRows[].bill_no` | `bill_no` | mv_risk_anomaly | +| 餐段 | `anomalyRows[].meal_period` | `meal_period` | 同上 | +| 消费额 | `anomalyRows[].consumption` | `consumption` | 同上 | +| 优惠 | `anomalyRows[].discount_total` | `discount_total` | 同上 | +| 实收 | `anomalyRows[].received_total` | `received_total` | 同上 | +| 异常原因 | `anomalyRows[].anomaly_reason` | `anomaly_reason` | 同上 | +| 结账时间 | `anomalyRows[].closed_at` | `closed_at` | 同上 | + +> 后端分页查询,前端 `page_size=200` 一次性加载。日期格式化:`r.closed_at?.substring(0, 16)` ✅。 + +### Tab7:任务列表(tasks) + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|-----|---------|---------| +| 问题指标 | `tasks[].problem_indicator` | `problem_indicator` | store_task | +| 优先级 | `tasks[].priority` | `priority` | 同上 | +| 行动要求 | `tasks[].action_required` | `action_required` | 同上 | +| 状态 | `tasks[].status` | `status` | 同上 | +| 截止日 | `tasks[].deadline` | `deadline` | 同上 | + +> 日期格式化:`r.deadline?.substring(0, 10)` ✅。点击行跳转 `/tasks/:task_id`。 + +--- + +## 十五、页面13:门店分级与风险等级 StoreGradePage + +> 单页面2个Tab(门店分级/关停测算),3个API(2 GET + 1 POST mutation),有月份选择器(原生 `` 而非 MonthPicker 组件)。 +> 核心数据源:`analytics.v3_store_grade`、`analytics.mv_store_risk_rating`、`analytics.v3_store_monthly_target`、`analytics.dim_store`、`analytics.mv_store_operating_expense_monthly`、`analytics.mv_store_area_efficiency_monthly`。 + +### API总览 + +| API | Tab | 方法 | 数据源表 | 说明 | +|-----|-----|------|---------|------| +| /store-grade/grades | 分级 | GET | v3_store_grade + mv_store_risk_rating | 分级列表+风险详情 | +| /store-grade/auto-grade | 分级 | POST | dim_store + mv_store_risk_rating + v3_store_monthly_target → v3_store_grade | 自动分级计算并写入 | +| /store-grade/closure-analysis | 关停 | GET | v3_store_grade + mv_store_risk_rating + mv_store_operating_expense_monthly + mv_store_area_efficiency_monthly | 关停成本测算 | + +### Tab1:门店分级(grade) + +#### API: /store-grade/grades + +| 显示指标 | 前端变量 | API字段 | 计算公式 | 数据源表 | +|---------|---------|---------|---------|---------| +| 门店编码 | `r.store_code` | `store_code` | — | v3_store_grade | +| 门店名称 | `r.store_name` | `store_name` | — | 同上 | +| 区域 | `r.region` | `region` | — | 同上 | +| 分级 | `r.grade` | `grade` | A≥85, B≥70, C≥50, D<50 | auto-grade计算 | +| 综合分 | `r.overall_score` | `overall_score` | 达成率×0.4+毛利率×0.25+会员占比×0.15+风险×0.2 | auto-grade计算 | +| 营收达成率 | `r.revenue_achievement_pct` | `revenue_achievement_pct` | `revenue / revenue_target × 100` | auto-grade计算 | +| 风险等级 | `r.risk_level` | `risk_level` | — | mv_store_risk_rating | +| 分级原因 | `r.reason` | `reason` | — | auto-grade写入 | +| 营收 | `r.revenue` | `revenue` | — | mv_store_risk_rating | +| 毛利率 | `r.margin_pct` | `margin_pct` | — | 同上 | +| 优惠率 | `r.discount_rate` | `discount_rate` | — | 同上 | +| 异常率 | `r.anomaly_rate` | `anomaly_rate` | — | 同上 | +| 会员占比 | `r.member_pct` | `member_pct` | — | 同上 | +| 客单价 | `r.avg_bill_value` | `avg_bill_value` | — | 同上 | +| 活跃天数 | `r.active_days` | `active_days` | — | 同上 | + +> **自动分级公式**:overallScore = achievementScore×0.4 + marginScore×0.25 + memberScore×0.15 + riskScore×0.2 +> - achievementScore = min(achievement, 100) +> - marginScore = min(margin_pct/50×100, 100) +> - memberScore = min(member_pct/50×100, 100) +> - riskScore = 红色30, 黄色60, 绿色100 +> +> **弹窗详情**:RadarChart 4维(达成率/综合分/毛利率/异常率) + 13项指标列表。 +> **PieChart**:分级分布 + 风险等级分布。 +> **FilterableTable**:filterKey=grade, sortOptions=综合分/达成率/门店。 + +#### API: /store-grade/auto-grade (POST mutation) + +> 前端点击"自动分级"按钮触发 POST,后端读取 `dim_store` + `mv_store_risk_rating` + `v3_store_monthly_target`,计算综合分和分级,写入 `v3_store_grade` 表(UPSERT)。成功后前端 invalidateQueries 刷新列表。 + +### Tab2:关停测算(closure) + +#### API: /store-grade/closure-analysis + +| 显示指标 | 前端变量 | API字段 | 计算公式 | 数据源表 | +|---------|---------|---------|---------|---------| +| 月收入 | `r.monthly_revenue` | `monthly_revenue` | — | mv_store_risk_rating | +| 月利润 | `r.monthly_profit` | `monthly_profit` | `actual_store_contribution` | mv_store_operating_expense_monthly | +| 月租 | `r.monthly_rent` | `monthly_rent` | `rent_expense` | 同上 | +| 月人工 | `r.monthly_wage` | `monthly_wage` | `wage_expense` | 同上 | +| 关停成本 | `r.total_closure_cost` | `total_closure_cost` | `wage×1.5 + rent×2 + revenue×0.05` | — | +| 遣散费 | — | `severance_cost` | `monthly_wage × 1.5` | — | +| 违约金 | — | `lease_termination_cost` | `monthly_rent × 2` | — | +| 资产处置 | — | `asset_disposal_cost` | `monthly_revenue × 0.05` | — | +| 12月亏损 | `r.projected_12m_loss` | `projected_12m_loss` | `monthly_profit < 0 ? monthly_profit × 12 : 0` | — | +| 月节省 | `r.monthly_savings_if_closed` | `monthly_savings_if_closed` | `monthly_profit < 0 ? abs(monthly_profit) : 0` | — | +| 回本月数 | `r.payback_months` | `payback_months` | `total_closure_cost / abs(monthly_profit)` | — | +| 建议 | `r.recommendation` | `recommendation` | 亏损+D级→关停, 亏损+C级→整改, 微利+低分→重点整改, else→持续经营 | — | +| 原因 | `r.reason` | `reason` | — | — | + +> **汇总指标**:total_stores, recommend_close, recommend_rectify, total_closure_cost, total_projected_loss, total_monthly_savings。 +> **PieChart**:关停建议分布(建议关停/整改观察/持续经营)。 +> **FilterableTable**:filterKey=recommendation, sortOptions=月利润/关停成本/12月亏损/回本月数/综合分。 + +--- + +## 十六、页面14:平台与优惠管理 PlatformPage + +> 单页面无Tab,2个API(全部GET),有MonthPicker。 +> 核心数据源:`analytics.mv_store_platform_economics_monthly`、`analytics.bill_fact`。 + +### API总览 + +| API | 数据源表 | 说明 | +|-----|---------|------| +| /platform/economics | mv_store_platform_economics_monthly | 门店三平台经济性数据 | +| /marketing/plans | bill_fact | 营销方案聚合分析 | + +### Block1:平台概览 + +#### API: /platform/economics + +| 显示指标 | 前端变量 | API字段 | 计算公式 | 数据源表 | +|---------|---------|---------|---------|---------| +| 平台总实收 | `totalPlatformReceived` | — | 前端聚合:`Σ(meituan+taobao+jd)` | mv_store_platform_economics_monthly | +| 合并加权成本率 | `blendedCostRate` | — | 前端计算:`(Σ折扣+Σ佣金) / Σ实收 × 100` | 同上 | +| 高成本门店 | `highCostStores.length` | — | 前端过滤:任一平台cost_rate≥38% | 同上 | +| 营销方案数 | `marketingRows.length` | — | 来自/marketing/plans | bill_fact | + +> 后端 `SELECT *` 返回全字段,前端聚合计算。无分页,全量返回。 +> **平台字段**:`meituan_received/discount/commission/cost_rate_pct`、`taobao_*`、`jd_*`。 + +### Block2:三平台对比图 + +> BarChart:美团/淘宝/京东三组,每组3条柱(实收/折扣/佣金)。前端聚合 `storesWithPlatform` 数据。 + +### Block3:门店平台经济性明细 + +> FilterableTable:filterKey=store_name, sortOptions=美团实收/美团成本率/淘宝实收/京东实收/门店。 +> **成本率颜色**:≥38%红色, 35-38%黄色, <35%绿色。 +> **经济性最优列**:前端计算三平台中成本率最低的平台,显示名称和与最高的差距。 + +### Block4:营销方案ROI + +#### API: /marketing/plans + +| 显示指标 | 前端变量 | API字段 | 计算公式 | 数据源表 | +|---------|---------|---------|---------|---------| +| 营销方案 | `r.marketing_plan` | `marketing_plan` | — | bill_fact | +| 账单数 | `r.bill_count` | `bill_count` | `count(*)` | 同上 | +| 消费额 | `r.consumption` | `consumption` | `sum(consumption)` | 同上 | +| 优惠额 | `r.discounts` | `discounts` | `sum(discount_total)` | 同上 | +| 实收 | `r.received` | `received` | `sum(received_total)` | 同上 | +| 客单价 | `r.avg_bill_value` | `avg_bill_value` | `avg(received_total)` | 同上 | +| 优惠率 | `r.discount_rate_pct` | `discount_rate_pct` | `sum(discount_total)/sum(consumption)×100` | — | +| 理论毛利率 | `r.theoretical_margin_pct` | `theoretical_margin_pct` | `sum(theoretical_profit)/sum(received_total)×100` | — | + +> 前端Top5营销方案卡片展示 + FilterableTable完整列表。 +> **优惠率颜色**:≥25%红色, 15-25%黄色, <15%绿色。 +> **毛利率颜色**:≥70%绿色, 60-70%黄色, <60%红色。 + +--- + +## 十七、页面15:营收分析 RevenuePage + +> 单页面无Tab,4个API(全部GET),有MonthPicker。 +> 核心数据源:`analytics.v_store_daily`、`analytics.v_channel_daily`、`analytics.v_meal_period_daily`。 + +### API总览 + +| API | 数据源表 | 说明 | +|-----|---------|------| +| /revenue/daily-summary | v_store_daily | 日度营收汇总(全门店合计) | +| /revenue/channel | v_channel_daily | 渠道日度收入结构 | +| /revenue/meal-period | v_meal_period_daily | 时段收入分布 | +| /revenue/store-ranking | v_store_daily | 门店营收排名 | + +### Block1:核心指标 + +#### API: /revenue/daily-summary + +| 显示指标 | 前端变量 | API字段 | 计算公式 | 数据源表 | +|---------|---------|---------|---------|---------| +| 营业收入 | `totalConsumption` | — | 前端聚合:`Σ consumption` | v_store_daily | +| 优惠总额 | `totalDiscounts` | — | 前端聚合:`Σ discounts` | 同上 | +| 实收总额 | `totalReceived` | — | 前端聚合:`Σ received` | 同上 | +| 账单数 | `totalBills` | — | 前端聚合:`Σ bill_count` | 同上 | +| 客单价 | `avgBillValue` | — | 前端计算:`totalReceived / totalBills` | — | +| 优惠率 | `avgDiscountRate` | — | 前端计算:`totalDiscounts / (totalReceived + totalDiscounts) × 100` | — | +| 客流量 | `totalGuests` | — | 前端聚合:`Σ guests` | v_store_daily | +| 人均消费 | `avgGuestValue` | — | 前端计算:`totalReceived / totalGuests` | — | + +> 后端SQL:`sum(received + discounts) AS consumption, sum(received) AS received, sum(discounts) AS discounts, sum(bill_count), sum(guests)`,按 `business_date` 分组。 +> **环比趋势**:前端计算 last7 vs prev7 的实收和账单数环比。 + +### Block2:日度营收趋势 + +> ComposedChart:Bar(received) + Line(avg_bill) + Line(discount_rate),双Y轴。 +> X轴 `business_date.substring(5, 10)` ✅。 + +### Block3:渠道收入结构 + 渠道趋势 + +#### API: /revenue/channel + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------|---------| +| 微信 | `channelTotals.wechat` | `wechat` | v_channel_daily | +| 支付宝 | `channelTotals.alipay` | `alipay` | 同上 | +| 美团外卖 | `channelTotals.meituan_delivery` | `meituan_delivery` | 同上 | +| 美团堂食 | `channelTotals.meituan` | `meituan` | 同上 | +| 淘宝外卖 | `channelTotals.taobao_delivery` | `taobao_delivery` | 同上 | +| 抖音 | `channelTotals.douyin` | `douyin` | 同上 | +| 现金 | `channelTotals.cash` | `cash` | 同上 | +| 京东外卖 | `channelTotals.jd_delivery` | `jd_delivery` | 同上 | +| 银联 | `channelTotals.unionpay` | `unionpay` | 同上 | +| 挂账 | `channelTotals.credit` | `credit` | 同上 | + +> PieChart(渠道占比) + LineChart(前5大渠道日度趋势)。 +> 前端聚合日度数据为渠道总量,按值排序。 + +### Block4:时段收入分布 + +#### API: /revenue/meal-period + +| 显示指标 | 前端变量 | API字段 | 计算公式 | 数据源表 | +|---------|---------|---------|---------|---------| +| 餐段 | `r.meal_period` | `meal_period` | — | v_meal_period_daily | +| 账单数 | `r.bill_count` | `bill_count` | `sum(bill_count)` | 同上 | +| 实收 | `r.received` | `received` | `sum(received)` | 同上 | +| 客单价 | `r.avg_bill_value` | `avg_bill_value` | `sum(received)/sum(bill_count)` | — | + +> PieChart + 卡片列表展示各餐段收入和占比。 + +### Block5:门店营收排名 + +#### API: /revenue/store-ranking + +| 显示指标 | 前端变量 | API字段 | 计算公式 | 数据源表 | +|---------|---------|---------|---------|---------| +| 门店 | `r.store_name` | `store_name` | — | v_store_daily | +| 实收 | `r.received` | `received` | `sum(received)` | 同上 | +| 账单数 | `r.bill_count` | `bill_count` | `sum(bill_count)` | 同上 | +| 客单价 | `r.avg_bill_value` | `avg_bill_value` | `sum(received)/sum(bill_count)` | — | +| 优惠率 | `r.avg_discount_rate_pct` | `avg_discount_rate_pct` | `sum(discounts)/(sum(received)+sum(discounts))×100` | — | +| 客流量 | `r.guests` | `guests` | `sum(guests)` | 同上 | +| 理论毛利率 | `r.avg_theoretical_margin_pct` | `avg_theoretical_margin_pct` | `avg(theoretical_margin_pct)` | 同上 | + +> TOP10/BOTTOM10 水平BarChart(点击跳转门店详情) + FilterableTable完整列表。 +> **优惠率颜色**:>25%红色, >20%黄色。 +> 后端 `ORDER BY sum(received) DESC`,前端 slice(0,10) 和 slice(-10).reverse()。 + +--- + +## 十八、页面16:区域经理工作台 RegionalPage + +> 单页面无Tab,5个API(4 GET + 1 PUT mutation),有MonthPicker。 +> 核心数据源:`analytics.mv_store_risk_rating_monthly`、`analytics.mv_store_action_priority_deep_monthly`、`analytics.mv_store_benchmark_composite_monthly`、`analytics.bill_fact`、`analytics.dim_store`、`analytics.v_task_weekly_check`、`analytics.store_task`、`analytics.task_weekly_check`。 + +### API总览 + +| API | 方法 | 数据源表 | 说明 | +|-----|------|---------|------| +| /stores/risk | GET | mv_store_risk_rating_monthly | 门店风险分级列表 | +| /stores/priority | GET | mv_store_action_priority_deep_monthly | 门店行动优先级 | +| /benchmark/composite | GET | mv_store_benchmark_composite_monthly | 同类门店基准对比 | +| /region/summary | GET | bill_fact + dim_store + mv_store_risk_rating_monthly | 区域经营汇总 | +| /tasks/weekly-check | GET | v_task_weekly_check | 周检任务列表 | +| /tasks/:id/weekly-check | PUT | store_task + store_task_log + task_weekly_check | 周检录入 | + +### Block1:汇总卡片 + +| 显示指标 | 前端变量 | 数据来源 | 计算公式 | +|---------|---------|---------|---------| +| 营业收入 | `Σ regionRows.total_consumption` | /region/summary | 前端聚合 | +| 优惠 | `Σ regionRows.total_discount` | 同上 | 前端聚合 | +| 实收 | `Σ regionRows.total_received` | 同上 | 前端聚合 | +| 红黄门店数 | `riskRows.filter(risk_level !== '绿色').length` | /stores/risk | 前端过滤 | +| P0+P1门店 | `p0p1.length` | /stores/priority | 前端过滤 action_priority.startsWith('P0'/'P1') | +| 需到店检查 | `needCheck.length` | /tasks/weekly-check | 前端过滤 consecutive_no_improve_weeks ≥ 2 | +| 周检待录入 | `weeklyRows.filter(!last_check_date).length` | 同上 | 前端过滤 | + +### Block2:区域经营汇总 + +#### API: /region/summary + +| 显示指标 | 前端变量 | API字段 | 计算公式 | 数据源表 | +|---------|---------|---------|---------|---------| +| 区域 | `r.region` | `region` | — | dim_store | +| 门店数 | `r.store_count` | `store_count` | `count(DISTINCT store_code)` | bill_fact | +| 营业收入 | `r.total_consumption` | `total_consumption` | `sum(consumption)` | 同上 | +| 优惠 | `r.total_discount` | `total_discount` | `sum(discount_total)` | 同上 | +| 实收 | `r.total_received` | `total_received` | `sum(received_total)` | 同上 | +| 客单价 | `r.avg_bill_value` | `avg_bill_value` | `avg(received_total)` | 同上 | +| 优惠率 | `r.avg_discount_rate` | `avg_discount_rate` | `sum(discount_total)/sum(consumption)×100` | — | +| 毛利率 | `r.avg_margin_rate` | `avg_margin_rate` | `sum(theoretical_profit)/sum(received_total)×100` | — | +| 异常率 | `r.avg_anomaly_rate` | `avg_anomaly_rate` | **硬编码 0** | — | +| 红数 | `r.red_count` | `red_count` | `count(DISTINCT CASE WHEN risk_level='红色')` | mv_store_risk_rating_monthly | +| 黄数 | `r.yellow_count` | `yellow_count` | 同上黄色 | 同上 | +| 绿数 | `r.green_count` | `green_count` | 同上绿色 | 同上 | + +> FilterableTable,sortOptions=区域/营业收入/优惠/实收/客单价/门店数。 +> **数据权限**:使用 `getDataScope(req)` + `scopeStoreFilter` 实现区域经理只能看自己区域。 + +### Block3:门店风险分级 + +#### API: /stores/risk + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 门店 | `r.store_name` | `store_name` | mv_store_risk_rating_monthly | +| 风险 | `r.risk_level` | `risk_level` | 同上 | +| 实收 | `r.received` | `received` | 同上 | +| 优惠率 | `r.discount_rate_pct` | `discount_rate_pct` | 同上 | +| 毛利率 | `r.theoretical_margin_pct` | `theoretical_margin_pct` | 同上 | +| 异常率 | `r.anomaly_rate_pct` | `anomaly_rate_pct` | 同上 | + +> 后端 `SELECT *` + `ORDER BY risk_level, received DESC`。前端风险筛选按钮(全部/红色/黄色/绿色)+ FilterableTable。 +> 点击行跳转 `/stores/:store_code`。 + +### Block4:需到店检查门店 + +#### API: /tasks/weekly-check + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 门店 | `r.store_name` | `store_name` | v_task_weekly_check | +| 问题指标 | `r.problem_indicator` | `problem_indicator` | 同上 | +| 连续未改善周数 | `r.consecutive_no_improve_weeks` | `consecutive_no_improve_weeks` | 同上 | +| 任务状态 | `r.status` | `status` | 同上 | + +> 前端过滤 `consecutive_no_improve_weeks ≥ 2`。点击"录入周检"打开弹窗。 +> **PUT API**:`/tasks/:id/weekly-check`,更新 `store_task.process_evidence/next_step`,插入 `store_task_log` 和 `task_weekly_check` 记录。 + +### Block5:同类门店基准对比 + +#### API: /benchmark/composite + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 门店 | `r.store_name` | `store_name` | mv_store_benchmark_composite_monthly | +| 标杆得分 | `r.benchmark_score` | `benchmark_score` | 同上 | +| 实收 | `r.received` | `received` | 同上 | +| 客单价 | `r.avg_bill_value` | `avg_bill_value` | 同上 | +| 优惠率 | `r.discount_rate_pct` | `discount_rate_pct` | 同上 | +| 毛利率 | `r.theoretical_margin_pct` | `theoretical_margin_pct` | 同上 | +| 会员占比 | `r.member_bill_share_pct` | `member_bill_share_pct` | 同上 | + +> 后端 `SELECT * ORDER BY benchmark_score DESC`。**标杆得分颜色**:≥80绿色, ≥60黄色, <60红色。 + +--- + +## 十九、页面17:门店选址分析 SiteSelectionPage + +> 单页面4个Tab(分段基准/复制评分/重叠风险/区域基准),5个API(全部GET),有MonthPicker。 +> 核心数据源:`analytics.mv_store_site_profile_monthly`、`analytics.mv_site_segment_benchmark_monthly`、`analytics.mv_store_site_replication_monthly`、`analytics.mv_store_overlap_risk_monthly`、`analytics.mv_district_site_benchmark_monthly`。 + +### API总览 + +| API | Tab | 数据源表 | 说明 | +|-----|-----|---------|------| +| /site-selection/profile | 全局 | mv_store_site_profile_monthly | 门店选址画像 | +| /site-selection/segment-benchmark | 分段基准 | mv_site_segment_benchmark_monthly | 场景×面积分段基准 | +| /site-selection/replication | 复制评分 | mv_store_site_replication_monthly | 门店复制评分 | +| /site-selection/overlap-risk | 重叠风险 | mv_store_overlap_risk_monthly | 门店空间重叠风险 | +| /site-selection/district-benchmark | 区域基准 | mv_district_site_benchmark_monthly | 区域选址基准 | + +### 全局:概览指标 + 散点图 + 地图 + +#### API: /site-selection/profile + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 标准门店数 | `profileRows.length` | — | mv_store_site_profile_monthly | +| 场景类型数 | `totalScenes` | — | 前端聚合 site_scene 去重 | +| 高风险重叠对 | `highRiskCount` | — | 来自 /overlap-risk 前端过滤 | +| 优先提炼原型 | `topReplication` | — | 来自 /replication 前端过滤 | + +> **StoreMap**:自定义地图组件,按场景类型颜色标注门店位置。 +> **ScatterChart**:X=面积(㎡), Y=月坪效(元/㎡), Z=实收(气泡大小),按场景颜色区分。 +> 后端 `WHERE business_type='标准门店' AND received>0`,`ORDER BY received DESC`。 + +### Tab1:分段基准(benchmark) + +#### API: /site-selection/segment-benchmark + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 场景 | `r.site_scene` | `site_scene` | mv_site_segment_benchmark_monthly | +| 面积段 | `r.area_band` | `area_band` | 同上 | +| 门店数 | `r.store_count` | `store_count` | 同上 | +| 平均面积 | `r.avg_area_sqm` | `avg_area_sqm` | 同上 | +| 平均实收 | `r.avg_received` | `avg_received` | 同上 | +| 中位实收 | `r.median_received` | `median_received` | 同上 | +| 平均坪效 | `r.avg_received_per_sqm` | `avg_received_per_sqm` | 同上 | +| 中位坪效 | `r.median_received_per_sqm` | `median_received_per_sqm` | 同上 | +| 客单价 | `r.avg_bill_value` | `avg_bill_value` | 同上 | +| 复购率 | `r.avg_repeat_rate_pct` | `avg_repeat_rate_pct` | 同上 | + +> FilterableTable,filterKey=site_scene,sortOptions=平均坪效/中位坪效/平均实收/场景。 +> 后端 `ORDER BY avg_received_per_sqm DESC`。 +> **门店画像明细**:同 profile API 数据,filterKey=site_scene,点击行跳转门店详情。 + +### Tab2:复制评分(replication) + +#### API: /site-selection/replication + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 门店 | `r.store_name` | `store_name` | mv_store_site_replication_monthly | +| 场景 | `r.site_scene` | `site_scene` | 同上 | +| 面积 | `r.area_sqm` | `area_sqm` | 同上 | +| 实收 | `r.received` | `received` | 同上 | +| 坪效 | `r.monthly_received_per_sqm` | `monthly_received_per_sqm` | 同上 | +| 最近门店 | `r.nearest_store_name` | `nearest_store_name` | 同上 | +| 距离 | `r.nearest_distance_km` | `nearest_distance_km` | 同上 | +| 复制评分 | `r.site_replication_score` | `site_replication_score` | 同上 | +| 复制建议 | `r.replication_recommendation` | `replication_recommendation` | 同上 | +| 空间建议 | `r.spatial_recommendation` | `spatial_recommendation` | 同上 | + +> FilterableTable,filterKey=replication_recommendation,sortOptions=复制评分/实收/坪效/距离。 +> **复制评分颜色**:≥75绿色, ≥60蓝色, <40红色。 +> **复制建议标签**:优先提炼选址原型(绿)、不宜作为选址标杆(红)、其他(蓝)。 +> 后端 `ORDER BY site_replication_score DESC`。 + +### Tab3:重叠风险(overlap) + +#### API: /site-selection/overlap-risk + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 门店A | `r.store_name_a` | `store_name_a` | mv_store_overlap_risk_monthly | +| 门店B | `r.store_name_b` | `store_name_b` | 同上 | +| 距离 | `r.distance_km` | `distance_km` | 同上 | +| A实收 | `r.received_a` | `received_a` | 同上 | +| B实收 | `r.received_b` | `received_b` | 同上 | +| 风险等级 | `r.overlap_risk` | `overlap_risk` | 同上 | + +> 3个MetricCard(<1km/1-2km/2-3km)+ FilterableTable。 +> filterKey=overlap_risk,sortOptions=距离/A实收/B实收。 +> 后端 `ORDER BY distance_km`。 + +### Tab4:区域基准(district) + +#### API: /site-selection/district-benchmark + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 区域 | `r.district` | `district` | mv_district_site_benchmark_monthly | +| 门店数 | `r.store_count` | `store_count` | 同上 | +| 平均面积 | `r.avg_area_sqm` | `avg_area_sqm` | 同上 | +| 总实收 | `r.total_received` | `total_received` | 同上 | +| 平均实收 | `r.avg_received` | `avg_received` | 同上 | +| 中位实收 | `r.median_received` | `median_received` | 同上 | +| 平均坪效 | `r.avg_received_per_sqm` | `avg_received_per_sqm` | 同上 | +| 客单价 | `r.avg_bill_value` | `avg_bill_value` | 同上 | +| 复购率 | `r.avg_repeat_rate_pct` | `avg_repeat_rate_pct` | 同上 | +| P0数 | `r.p0_count` | `p0_count` | 同上 | +| P1数 | `r.p1_count` | `p1_count` | 同上 | + +> BarChart(前15区域平均/中位实收对比) + FilterableTable。 +> sortOptions=平均实收/平均坪效/总实收/区域。 +> 后端 `ORDER BY total_received DESC`。 + +--- + +## 二十、页面18:时间维度分析 TimePage + +> 单页面无Tab,3个API(全部GET),有MonthPicker。 +> 核心数据源:`mv_time_weekday`、`mv_time_hourly`、`mv_channel_daily`。 + +### API总览 + +| API | 数据源表 | 说明 | +|-----|---------|------| +| /time/weekday | mv_time_weekday | 星期维度分析 | +| /time/hourly | mv_time_hourly | 小时维度分析 | +| /channel | mv_channel_daily | 渠道日度趋势 | + +### Block1:时间概览 + +| 显示指标 | 前端变量 | 数据来源 | 计算公式 | +|---------|---------|---------|---------| +| 高峰日 | `peakWeekday.weekday` | /time/weekday | 前端 reduce 找最大 received | +| 低谷日 | `lowWeekday.weekday` | 同上 | 前端 reduce 找最小 received | +| 高峰时段 | `peakHour.closing_hour` | /time/hourly | 前端 reduce 找最大 bill_count | +| 渠道数 | `channelTotals.length` | /channel | 前端聚合非零渠道数 | + +### Block2:星期维度分析 + +#### API: /time/weekday + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 星期 | `r.weekday` | `weekday` | mv_time_weekday | +| 实收 | `r.received` | `received` | 同上 | +| 账单数 | `r.bill_count` | `bill_count` | 同上 | +| 客单价 | `r.avg_bill_value` | `avg_bill_value` | 同上 | + +> BarChart(实收+账单数)+ Line(客单价),双Y轴。后端 `WHERE month = to_char($1::date, 'YYYY-MM')`。 + +### Block3:小时维度分析 + +#### API: /time/hourly + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 小时 | `r.closing_hour` | `closing_hour` | mv_time_hourly | +| 账单数 | `r.bill_count` | `bill_count` | 同上 | +| 实收 | `r.received` | `received` | 同上 | +| 客单价 | `r.avg_bill_value` | `avg_bill_value` | 同上 | + +> AreaChart(实收+账单数),双Y轴。后端 `WHERE month = to_char($1::date, 'YYYY-MM')`。 + +### Block4:渠道趋势 + 渠道汇总 + +#### API: /channel + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 日期 | `r.business_date` | `business_date` | mv_channel_daily | +| 现金 | `r.cash` | `cash` | 同上 | +| 支付宝 | `r.alipay` | `alipay` | 同上 | +| 微信 | `r.wechat` | `wechat` | 同上 | +| 美团到店 | `r.meituan` | `meituan` | 同上 | +| 银联 | `r.unionpay` | `unionpay` | 同上 | +| 抖音 | `r.douyin` | `douyin` | 同上 | +| 挂账 | `r.credit` | `credit` | 同上 | +| 京东到家 | `r.jd_delivery` | `jd_delivery` | 同上 | +| 美团外卖 | `r.meituan_delivery` | `meituan_delivery` | 同上 | +| 淘宝外卖 | `r.taobao_delivery` | `taobao_delivery` | 同上 | + +> LineChart(前6大渠道日度趋势)+ 渠道汇总卡片。X轴 `business_date.substring(5, 10)` ✅。 +> **注意**:此API与 RevenuePage 的 `/revenue/channel` 数据源相同(`mv_channel_daily`),但查询无 schema 前缀(`mv_channel_daily` vs `analytics.v_channel_daily`)。 + +--- + +## 二十一、页面19:指标字典 IndicatorsPage + +> 单页面无Tab,1个API(GET),无MonthPicker。 +> 核心数据源:`analytics.indicator_dictionary`。 + +### API: /tasks/indicators + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 指标名称 | `r.indicator_name` | `indicator_name` | indicator_dictionary | +| 业务定义 | `r.business_definition` | `business_definition` | 同上 | +| 计算公式 | `r.formula` | `formula` | 同上 | +| 更新频率 | `r.update_frequency` | `update_frequency` | 同上 | +| 负责人 | `r.owner` | `owner` | 同上 | +| 黄线 | `r.yellow_threshold` | `yellow_threshold` | 同上 | +| 红线 | `r.red_threshold` | `red_threshold` | 同上 | +| 版本日期 | `r.version_date` | `version_date` | 同上 | + +> FilterableTable,filterKey=update_frequency,sortOptions=指标名称/更新频率/负责人。 +> `version_date?.substring(0, 10)` ✅。后端 `SELECT * ORDER BY id`,无分页。 + +--- + +## 二十二、页面20:任务管理 TasksPage + +> 单页面无Tab,1个API(GET),有MonthPicker + 优先级/状态筛选。 +> 核心数据源:`analytics.store_task`。 + +### API: /tasks + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 问题指标 | `r.problem_indicator` | `problem_indicator` | store_task | +| 行动要求 | `r.action_required` | `action_required` | 同上 | +| 负责人 | `r.owner` | `owner` | 同上 | +| 截止日 | `r.deadline?.substring(0,10)` | `deadline` | 同上 | +| 状态 | `r.status` | `status` | 同上 | +| 优先级 | `r.priority` | `priority` | 同上 | +| 门店 | `r.store_name` | `store_name` | 同上 | +| 门店编码 | `r.store_code` | `store_code` | 同上 | + +> 后端支持分页(`parsePagination`),前端传 `page_size: 200`。 +> 前端按 `store_code` 分组展示,每组内 FilterableTable。 +> **筛选**:priority + status 参数传递到后端 WHERE 条件。 +> `deadline?.substring(0, 10)` ✅。 + +--- + +## 二十三、页面21:任务详情 TaskDetailPage + +> 单页面无Tab,2个API(1 GET + 1 GET indicators)+ 3个mutation(PUT execute, PUT verify, POST rollback)。 +> 核心数据源:`analytics.store_task`、`analytics.store_task_log`、`analytics.indicator_dictionary`。 + +### API: /tasks/:id (GET) + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 门店名 | `task.store_name` | `store_name` | store_task | +| 问题指标 | `task.problem_indicator` | `problem_indicator` | 同上 | +| 优先级 | `task.priority` | `priority` | 同上 | +| 状态 | `task.status` | `status` | 同上 | +| 当前值 | `task.current_value` | `current_value` | 同上 | +| 基准值 | `task.benchmark_value` | `benchmark_value` | 同上 | +| 目标值 | `task.target_value` | `target_value` | 同上 | +| 问题描述 | `task.problem_description` | `problem_description` | 同上 | +| 验收指标 | `task.verification_indicator` | `verification_indicator` | 同上 | +| 行动要求 | `task.action_required` | `action_required` | 同上 | +| 负责人 | `task.owner` | `owner` | 同上 | +| 截止日 | `task.deadline?.substring(0,10)` | `deadline` | 同上 | +| 过程证据 | `task.process_evidence` | `process_evidence` | 同上 | +| 未完成原因 | `task.incomplete_reason` | `incomplete_reason` | 同上 | +| 验收结果 | `task.verification_result` | `verification_result` | 同上 | +| 操作日志 | `logs` | — | store_task_log | + +> 后端 `SELECT * FROM store_task WHERE task_id = $1` + `SELECT * FROM store_task_log WHERE task_id = $1`。 +> `deadline?.substring(0, 10)` ✅,`log.created_at?.substring(0, 19)` ✅。 + +### Mutations + +| Mutation | API | 说明 | +|----------|-----|------| +| executeMutation | PUT /tasks/:id/execute | 提交执行反馈,状态改为"进行中" | +| verifyMutation | PUT /tasks/:id/verify | 月度验收,传 review_result/actual_value 等 | +| rollbackMutation | POST /tasks/:id/rollback | 回滚任务 | + +> **指标说明**:从 `/tasks/indicators` 获取指标字典,匹配 `problem_indicator` 显示业务定义、计算公式、黄线/红线阈值。 + +--- + +## 二十四、页面22:月度验收与复盘 MonthlyReviewPage + +> 7个Tab(验收汇总/升降级/任务完成率/活动清单/SKU治理/经验标准化/复盘优化),7个API(6 GET + 1 POST mutation),有MonthPicker。 +> 核心数据源:`analytics.v_task_monthly_review`、`analytics.store_grade_change`、`analytics.store_task`、`analytics.bill_fact`、`analytics.mv_dish_sku_abc_monthly`、`analytics.standardized_practice`。 + +### API总览 + +| API | Tab | 数据源表 | 说明 | +|-----|-----|---------|------| +| /tasks/monthly-review | 验收汇总 | v_task_monthly_review | 验收汇总+明细 | +| /tasks/grade-change | 升降级 | store_grade_change | P0/P1/P2升降级 | +| /tasks/monthly-review/completion | 完成率 | store_task | 按优先级汇总完成率 | +| /tasks/monthly-review/activity-list | 活动清单 | bill_fact | 平台活动停/改/留 | +| /tasks/monthly-review/sku-governance | SKU治理 | mv_dish_sku_abc_monthly | ABC分类+长尾清单 | +| /tasks/practices | 经验标准化 | standardized_practice | 标准化经验列表 | +| POST /tasks/practices | 经验标准化 | standardized_practice | 新增经验 | + +### Tab1:验收汇总 + +#### API: /tasks/monthly-review + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 总任务数 | `summary.total` | — | 后端计算 result.rows.length | +| 达标 | `summary.passed` | — | 后端 filter review_result='达标' | +| 改善中 | `summary.improving` | — | 同上 | +| 未改善 | `summary.failed` | — | 同上 | +| 门店 | `r.store_name` | `store_name` | v_task_monthly_review | +| 问题指标 | `r.problem_indicator` | `problem_indicator` | 同上 | +| 基线 | `r.baseline_value` | `baseline_value` | 同上 | +| 目标 | `r.target_value` | `target_value` | 同上 | +| 实际 | `r.actual_value` | `actual_value` | 同上 | +| 结果 | `r.review_result` | `review_result` | 同上 | + +> PieChart(验收结果分布)+ FilterableTable。后端 `SELECT * WHERE plan_month = $1`。 + +### Tab2:升降级面板 + +#### API: /tasks/grade-change + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 月份 | `r.change_month?.substring(0,7)` | `change_month` | store_grade_change | +| 门店 | `r.store_name` | `store_name` | 同上 | +| 原级别 | `r.old_priority` | `old_priority` | 同上 | +| 新级别 | `r.new_priority` | `new_priority` | 同上 | +| 变化 | `r.change_type` | `change_type` | 同上 | +| 原因 | `r.reason` | `reason` | 同上 | + +> `change_month?.substring(0, 7)` ✅。后端 `SELECT * WHERE change_month = $1::date`。 + +### Tab3:任务完成率 + +#### API: /tasks/monthly-review/completion + +| 显示指标 | 前端变量 | API字段 | 计算公式 | 数据源表 | +|---------|---------|---------|---------|---------| +| 优先级 | `c.priority` | `priority` | — | store_task | +| 总数 | `c.total` | `total` | `count(*)` | 同上 | +| 已完成 | `c.completed` | `completed` | `count FILTER(status='已验收'/'已回滚')` | 同上 | +| 达标 | `c.passed` | `passed` | `count FILTER(verification_result='达标')` | 同上 | +| 改善中 | `c.improving` | `improving` | 同上 | 同上 | +| 未改善 | `c.failed` | `failed` | 同上 | 同上 | +| 完成率 | `c.completion_rate` | `completion_rate` | `completed/total×100` | 同上 | + +> 进度条卡片 + FilterableTable。后端 `GROUP BY priority`。 + +### Tab4:活动清单 + +#### API: /tasks/monthly-review/activity-list + +| 显示指标 | 前端变量 | API字段 | 计算公式 | 数据源表 | +|---------|---------|---------|---------|---------| +| 活动方案 | `r.marketing_plan` | `marketing_plan` | — | bill_fact | +| 账单数 | `r.bill_count` | `bill_count` | `count(*)` | 同上 | +| 消费额 | `r.consumption` | `consumption` | `sum(consumption)` | 同上 | +| 优惠额 | `r.discounts` | `discounts` | `sum(discount_total)` | 同上 | +| 实收 | `r.received` | `received` | `sum(received_total)` | 同上 | +| 优惠成本率 | `r.discount_cost_rate` | `discount_cost_rate` | `discounts/consumption×100` | — | +| 净贡献 | `r.net_contribution` | `net_contribution` | `received - discounts` | — | +| 建议 | 前端计算 | — | net>0 && rate<15→留, rate>30→停, else→改 | — | + +> FilterableTable,sortOptions=净贡献/实收/优惠成本率/账单数。 + +### Tab5:SKU治理 + +#### API: /tasks/monthly-review/sku-governance + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| ABC分类 | `s.abc_class` | `abc_class` | mv_dish_sku_abc_monthly | +| SKU数 | `s.sku_count` | `sku_count` | 同上 | +| 营收占比 | `s.total_revenue_share` | `total_revenue_share` | 同上 | +| 菜品名 | `r.dish_name` | `dish_name` | 同上(C类) | +| 分类 | `r.category_level1` | `category_level1` | 同上 | +| 账单数 | `r.bill_count` | `bill_count` | 同上 | +| 实收 | `r.received_amount` | `received_amount` | 同上 | +| 营收占比 | `r.revenue_share_pct` | `revenue_share_pct` | 同上 | + +> 后端返回 `{ summary, longtail }`,longtail `LIMIT 50`。 + +### Tab6:经验标准化 + +#### API: /tasks/practices (GET + POST) + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 模块 | `p.practice_module` | `practice_module` | standardized_practice | +| 标杆门店 | `p.benchmark_store_name` | `benchmark_store_name` | 同上 | +| 关键动作 | `p.key_actions` | `key_actions` | 同上 | +| 状态 | `p.status` | `status` | 同上 | + +> POST 新增经验,字段 `practice_module/benchmark_store_code/benchmark_store_name/key_actions/verification_indicators`。 + +### Tab7:复盘优化 + +#### API: /tasks/monthly-review/indicator-effectiveness + +| 显示指标 | 前端变量 | API字段 | 计算公式 | 数据源表 | +|---------|---------|---------|---------|---------| +| 指标 | `r.problem_indicator` | `problem_indicator` | — | store_task | +| 任务数 | `r.task_count` | `task_count` | `count(*)` | 同上 | +| 达标 | `r.passed` | `passed` | `count FILTER(verification_result='达标')` | 同上 | +| 改善中 | `r.improving` | `improving` | 同上 | 同上 | +| 未改善 | `r.failed` | `failed` | 同上 | 同上 | +| 达标率 | `r.pass_rate` | `pass_rate` | `passed/task_count×100` | — | +| 评价 | 前端计算 | — | ≥50%有效, ≥30%待观察, <30%低效 | — | + +> 后端 `GROUP BY problem_indicator ORDER BY pass_rate DESC`。 + +--- + +## 二十五、页面23:数据质量看板 DataQualityPage + +> 单页面无Tab,1个API(GET),有MonthPicker。 +> 核心数据源:`analytics.bill_fact`、`public.dish_sales_details`、`analytics.mv_inventory_cost_classified_monthly`。 + +### API: /data-quality + +| 显示指标 | 前端变量 | API字段 | 计算公式 | 数据源表 | +|---------|---------|---------|---------|---------| +| 总账单数 | `totalBills` | `total_bills` | `count(*)` | bill_fact | +| 覆盖门店数 | `storeCount` | `store_count` | `count(DISTINCT store_code)` | 同上 | +| 缺失账单号 | `missingBillNo` | `missing_bill_no` | `count FILTER(bill_no IS NULL/='')` | 同上 | +| 缺失门店编码 | `missingStoreCode` | `missing_store_code` | 同上 | 同上 | +| 零消费账单 | `zeroConsumption` | `zero_consumption` | `count FILTER(consumption=0/NULL)` | 同上 | +| 负实收账单 | `negativeReceived` | `negative_received` | `count FILTER(received_total<0)` | 同上 | +| 零实收账单 | `zeroReceived` | `zero_received` | `count FILTER(received_total=0/NULL)` | 同上 | +| 优惠大于消费 | `discountGtConsumption` | `discount_gt_consumption` | `count FILTER(discount_total>consumption AND consumption>0)` | 同上 | +| 日期范围 | `dq.min_date?.substring(0,10)` | `min_date/max_date` | `min/max(closed_at)` | 同上 | +| 总菜品记录数 | `totalDishRecords` | `total_dish_records` | `count(*)` | dish_sales_details | +| 缺失门店(菜品) | `dishMissingStore` | `dish_missing_store` | `count FILTER(store_code IS NULL/='')` | 同上 | +| 缺失菜品名 | `dishMissingDish` | `dish_missing_dish` | `count FILTER(dish_name IS NULL/='')` | 同上 | +| 负耗用记录数 | `negativeConsumptionCount` | `negative_consumption_count` | `count FILTER(consumption_amount<0)` | mv_inventory_cost_classified_monthly | +| 负耗用金额 | `negativeConsumptionAmount` | `negative_consumption_amount` | `sum(consumption_amount) FILTER(<0)` | 同上 | + +> **注意**:账单和菜品统计无月份过滤(全量扫描),仅库存统计按 `month_start` 过滤。 +> `min_date/max_date?.substring(0, 10)` ✅。 +> **四层状态**:完整性/准确性/一致性/时效性,前端根据指标值计算。 +> **置信等级**:A(正常)/B(待桥接)/C(异常)。 + +--- + +## 二十六、页面24:银行授信数据报告 BankPage + +> 单页面无Tab,1个API(GET),有MonthPicker + 评分规则配置面板。 +> 核心数据源:`analytics.mv_overview_monthly`、`analytics.mv_overview_daily`、`analytics.bill_fact`、`analytics.mv_store_operating_expense_monthly`、`analytics.mv_store_risk_rating_monthly`、`analytics.v_channel_daily`。 + +### API: /bank/report + +后端 `Promise.all` 并发6个查询,返回 `{ overview, daily, waterfall, risk, channel, stores, stability }`。 + +### Block1:银行授信评估摘要 + +| 评分指标 | 前端变量 | 数据来源 | 计算公式 | +|---------|---------|---------|---------| +| 净利率 | `metrics.netMargin` | waterfall | `store_contribution/received×100` | +| 营收稳定性 | `metrics.cv` | stability | `stdDev/meanDailyRevenue` | +| 门店健康度 | `metrics.redPct` | risk | `红色门店数/总门店数×100` | +| 规模体量 | `metrics.scale` | overview | `ov.received` | +| 优惠率 | `metrics.discountRate` | overview | `ov.discount_rate_pct` | +| 会员占比 | `metrics.memberShare` | overview | `ov.member_share_pct` | + +> **评分规则**:可配置权重和阈值,localStorage 持久化。单项得分 0-100,加权总分 → 信用等级 A(≥85)/B(≥70)/C(≥50)/D(<50)。 + +### Block2:企业经营概况 + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 营业收入 | `wf.consumption` | `waterfall.consumption` | bill_fact | +| 优惠 | `wf.discount` | `waterfall.discount` | 同上 | +| 月度实收 | `ov.received` | `overview.received` | mv_overview_monthly | +| 客单价 | `ov.avg_bill_value` | `overview.avg_bill_value` | 同上 | +| 理论毛利率 | `ov.theoretical_margin_pct` | `overview.theoretical_margin_pct` | 同上 | +| 门店数量 | `stores.length` | — | mv_store_risk_rating_monthly | +| 日实收趋势 | `dailyChart` | `daily` | mv_overview_daily | + +> `business_date?.substring(5, 10)` ✅。 + +### Block3:盈利能力分析(利润瀑布) + +| 显示指标 | 前端变量 | API字段 | 计算公式 | 数据源表 | +|---------|---------|---------|---------|---------| +| 营业收入 | `wf.consumption` | `consumption` | `sum(consumption)` | bill_fact | +| 优惠 | `wf.discount` | `discount` | `sum(discount_total)` | 同上 | +| 实收 | `wf.received` | `received` | `sum(received)` | mv_store_risk_rating_monthly | +| 食材 | `wf.food_cost` | `food_cost` | `sum(actual_food_cost)` | mv_store_operating_expense_monthly | +| 人工 | `wf.wage` | `wage` | `sum(wage_expense)` | 同上 | +| 房租 | `wf.rent` | `rent` | `sum(rent_expense)` | 同上 | +| 水电 | `wf.utility` | `utility` | `sum(utility_expense)` | 同上 | +| 其他 | `wf.dorm+commission+other` | `dorm/commission/other_expense` | `sum(dorm+commission+card_fee+repair)` | 同上 | +| 门店贡献利润 | `wf.store_contribution` | `store_contribution` | `received - food_cost - operating_expense` | — | + +> 自定义 BarChart shape 实现瀑布图效果。 + +### Block4:门店资产质量 + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 风险分布 | `riskPie` | `risk` | mv_store_risk_rating_monthly | +| TOP10门店 | `top10` | `stores` | 同上 | + +> PieChart(风险等级分布)+ 横向 BarChart(TOP10门店实收)。 + +### Block5:经营稳定性指标 + +| 显示指标 | 前端变量 | API字段 | 计算公式 | 数据源表 | +|---------|---------|---------|---------|---------| +| 日度营收波动率 | `stability.cv` | `stability.cv` | `stdDev/mean` | mv_overview_daily | +| 日均收入 | `stability.mean_daily_revenue` | `stability.mean_daily_revenue` | — | 同上 | +| 优惠率 | `ov.discount_rate_pct` | `overview.discount_rate_pct` | — | mv_overview_monthly | +| 会员消费占比 | `ov.member_share_pct` | `overview.member_share_pct` | — | 同上 | +| 活跃渠道数 | `channelPie.length` | `channel` | 前端非零渠道数 | v_channel_daily | + +> 渠道 PieChart,标签显示渠道名称和占比。 + +--- + +## 二十七、页面25:本体标准 OntologyPage + +> 5个Tab(概览/维度主数据/事实表/枚举标准/指标标准),5个API(全部GET),无MonthPicker。 +> 核心数据源:`information_schema.columns`、`analytics.indicator_dictionary`、各 dim_/fact_/enum_ 表。 + +### API总览 + +| API | Tab | 数据源 | 说明 | +|-----|-----|--------|------| +| /tasks/ontology/overview | 概览 | information_schema + indicator_dictionary | 表统计概览 | +| /tasks/ontology/dim/:table | 维度主数据 | 对应 dim_ 表 | 维度表数据+字段定义 | +| /tasks/ontology/fact/:table | 事实表 | 对应 fact_ 表 | 事实表字段定义 | +| /tasks/ontology/enum/:table | 枚举标准 | 对应 enum_ 表 | 枚举值列表 | +| /tasks/ontology/metrics | 指标标准 | indicator_dictionary | 指标字典 | + +### Tab1:概览 + +> 显示维度表数、事实表数、枚举表数、指标标准数。点击可跳转到对应Tab。 + +### Tab2-4:维度/事实/枚举 + +> 列表→详情模式。列表显示表名、字段数、行数。点击进入详情,FilterableTable 展示数据(pageSize=20),下方显示字段定义表。 +> 后端使用正则校验表名 `^dim_\w+$` / `^fact_\w+$` / `^enum_\w+$` 防注入。 +> 时间戳字段 `String(val).substring(0, 19)` ✅。 + +### Tab5:指标标准 + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 指标编码 | `r.metric_code` | `metric_code` | indicator_dictionary | +| 指标名称 | `r.indicator_name` | `indicator_name` | 同上 | +| 分类 | `r.metric_category` | `metric_category` | 同上 | +| 业务定义 | `r.business_definition` | `business_definition` | 同上 | +| 计算公式 | `r.formula` | `formula` | 同上 | +| 单位 | `r.unit` | `unit` | 同上 | +| 方向 | `r.direction` | `direction` | 同上 | +| 负责人 | `r.owner` | `owner` | 同上 | +| 黄线 | `r.yellow_threshold` | `yellow_threshold` | 同上 | +| 红线 | `r.red_threshold` | `red_threshold` | 同上 | +| 更新频率 | `r.update_frequency` | `update_frequency` | 同上 | +| 版本 | `r.version` | `version` | 同上 | + +> 前端分类筛选(全部/收入/成本/优惠/会员/商品/库存/风险)+ FilterableTable。 + +--- + +## 二十八、页面26:中央厨房成本驾驶舱 CentralKitchenPage + +> 单页面无Tab,1个API(GET),有MonthPicker。 +> 核心数据源:`analytics.v_central_kitchen_product_full_cost`、`central_kitchen_processing_cost`、`central_kitchen_recipe_consumption`、`central_kitchen_manufacturing_cost_pool`、`central_kitchen_finished_receipt`。 + +### API: /central-kitchen/dashboard + +后端 `Promise.all` 并发7个查询,返回 `{ summary, reconciliation, products, categoryCost, recipeEfficiency, mfgPool, yieldAnalysis }`。 + +### Block1:核心指标卡片 + +| 显示指标 | 前端变量 | API字段 | 计算公式 | 数据源表 | +|---------|---------|---------|---------|---------| +| 产品数 | `summary.product_count` | `product_count` | `count(*)` | v_central_kitchen_product_full_cost | +| 完工入库量 | `summary.total_inbound_qty` | `total_inbound_qty` | `sum(inbound_quantity)` | 同上 | +| 理论材料成本 | `summary.theoretical_cost` | `theoretical_cost` | `sum(theoretical_cost)` | 同上 | +| 实际材料成本 | `summary.material_actual_cost` | `material_actual_cost` | `sum(material_actual_cost)` | 同上 | +| 完整制造成本 | `summary.full_manufacturing_cost` | `full_manufacturing_cost` | `sum(full_manufacturing_cost)` | 同上 | +| 材料效率差异 | `summary.efficiency_variance_pct` | `efficiency_variance_pct` | `(实际-理论)/理论×100` | — | +| 制造费用率 | `summary.mfg_cost_rate` | `mfg_cost_rate` | `制造费用池/实际材料×100` | — | + +> 后端 `WHERE report_month = $1::date`。 + +### Block2:成本对账瀑布 + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 理论成本 | `reconciliation.theoretical_cost` | `theoretical_cost` | v_central_kitchen_product_full_cost | +| 标准成本 | `reconciliation.standard_cost` | `standard_cost` | 同上 | +| 实际材料 | `reconciliation.material_actual_cost` | `material_actual_cost` | 同上 | +| 制造费用池 | `reconciliation.manufacturing_cost_pool` | `manufacturing_cost_pool` | 同上 | +| 全制造成本 | `reconciliation.full_manufacturing_cost` | `full_manufacturing_cost` | 同上 | +| 入库价值 | `reconciliation.calculated_inbound_value` | `calculated_inbound_value` | central_kitchen_processing_cost | +| 制造毛利 | `reconciliation.manufacturing_margin` | `manufacturing_margin` | 入库价值-全制造成本 | + +> 后端 JOIN `central_kitchen_processing_cost c ON p.report_month = c.report_month AND p.product_code = c.product_code`。 +> 自定义 BarChart shape 实现瀑布图效果。 + +### Block3:品类成本结构 + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 品类 | `c.category_minor` | `category_minor` | v_central_kitchen_product_full_cost | +| 产品数 | `c.product_count` | `product_count` | 同上 | +| 入库量 | `c.total_qty` | `total_qty` | 同上 | +| 理论成本 | `c.theoretical_cost` | `theoretical_cost` | 同上 | +| 实际材料 | `c.material_actual_cost` | `material_actual_cost` | 同上 | +| 制造费用 | `c.allocated_mfg_cost` | `allocated_mfg_cost` | 同上 | +| 全成本 | `c.full_cost` | `full_cost` | 同上 | +| 效率差异 | `c.efficiency_var_pct` | `efficiency_var_pct` | 同上 | + +> 堆叠 BarChart(材料成本+制造费用)+ FilterableTable。后端 `GROUP BY category_minor ORDER BY full_cost DESC`。 + +### Block4:产品成本偏差散点图 + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 产品名 | `p.product_name` | `product_name` | v_central_kitchen_product_full_cost | +| 理论成本(X) | `p.theoretical_cost` | `theoretical_cost` | 同上 | +| 实际成本(Y) | `p.material_actual_cost` | `material_actual_cost` | 同上 | +| 偏差率(颜色) | `p.efficiency_variance_pct` | `efficiency_variance_pct` | 同上 | + +> ScatterChart,颜色按偏差率分4档:节约(≤-5%)/正常(-5%~0%)/轻微超耗(0~5%)/严重超耗(≥5%)。 + +### Block5:产品成本明细表 + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 编码 | `p.product_code` | `product_code` | v_central_kitchen_product_full_cost | +| 产品名 | `p.product_name` | `product_name` | 同上 | +| 品类 | `p.category_minor` | `category_minor` | 同上 | +| 入库量 | `p.inbound_quantity` | `inbound_quantity` | 同上 | +| 理论成本 | `p.theoretical_cost` | `theoretical_cost` | 同上 | +| 标准成本 | `p.standard_cost` | `standard_cost` | 同上 | +| 实际材料 | `p.material_actual_cost` | `material_actual_cost` | 同上 | +| 制造费用 | `p.allocated_manufacturing_cost` | `allocated_manufacturing_cost` | 同上 | +| 全成本 | `p.full_manufacturing_cost` | `full_manufacturing_cost` | 同上 | +| 单位成本 | `p.full_unit_cost` | `full_unit_cost` | 同上 | +| 效率差异 | `p.efficiency_variance_pct` | `efficiency_variance_pct` | 同上 | +| 标准差异 | `p.standard_variance_pct` | `standard_variance_pct` | 同上 | +| 入库价值 | `p.inbound_value` | `inbound_value` | central_kitchen_processing_cost | +| 产品毛利 | `p.product_margin` | `product_margin` | 入库价值-全制造成本 | + +> FilterableTable,searchKeys=product_code/product_name/category_minor。后端 `ORDER BY p.full_manufacturing_cost DESC`。 + +### Block6:配方效率分析 TOP20 + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 配方 | `r.recipe_name` | `recipe_name` | central_kitchen_recipe_consumption | +| 物料 | `r.item_name` | `item_name` | 同上 | +| 规格 | `r.specification` | `specification` | 同上 | +| 理论用量 | `r.theoretical_qty` | `theoretical_qty` | 同上 | +| 实际用量 | `r.actual_qty` | `actual_qty` | 同上 | +| 理论金额 | `r.theoretical_amt` | `theoretical_amt` | 同上 | +| 实际金额 | `r.actual_amt` | `actual_amt` | 同上 | +| 差异率 | `r.variance_pct` | `variance_pct` | 同上 | +| 实际出成率 | `r.avg_actual_yield` | `avg_actual_yield` | 同上 | +| 标准出成率 | `r.avg_recipe_yield` | `avg_recipe_yield` | 同上 | +| 出成差异 | `r.yield_diff` | `yield_diff` | 同上 | + +> 后端 `WHERE business_date >= $1 AND business_date < ($1 + INTERVAL '1 month')`,`GROUP BY recipe_name, item_name, specification, unit`,`LIMIT 20`。 + +### Block7:出成率分析 TOP20 + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 配方 | `y.recipe_name` | `recipe_name` | central_kitchen_finished_receipt | +| 产品名 | `y.product_name` | `product_name` | 同上 | +| 理论入库量 | `y.theoretical_inbound_qty` | `theoretical_inbound_qty` | 同上 | +| 实际入库量 | `y.actual_inbound_qty` | `actual_inbound_qty` | 同上 | +| 达成率 | `y.avg_achievement_rate` | `avg_achievement_rate` | 同上 | +| 预期偏差率 | `y.avg_expected_var_rate` | `avg_expected_var_rate` | 同上 | +| 入库金额 | `y.total_inbound_amt` | `total_inbound_amt` | 同上 | +| 退库量 | `y.total_return_qty` | `total_return_qty` | 同上 | +| 退库率 | `y.return_rate` | `return_rate` | 同上 | + +> 后端 `WHERE receipt_date >= $1 AND receipt_date < ($1 + INTERVAL '1 month')`,`LIMIT 20`。 + +### Block8:制造费用池明细 + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 费用类型 | `m.cost_type` | `cost_type` | central_kitchen_manufacturing_cost_pool | +| 费用子类 | `m.cost_subtype` | `cost_subtype` | 同上 | +| 来源 | `m.source_type` | `source_type` | 同上 | +| 原始金额 | `m.source_amount` | `source_amount` | 同上 | +| 分摊比例 | `m.share_pct` | `share_pct` | 同上 | +| 分摊金额 | `m.allocated_amount` | `allocated_amount` | 同上 | +| 分摊方法 | `m.allocation_method` | `allocation_method` | 同上 | +| 计入重建 | `m.include_in_rebuilt_cost` | `include_in_rebuilt_cost` | 同上 | +| 临时 | `m.is_provisional` | `is_provisional` | 同上 | + +> 后端 `WHERE report_month = $1::date ORDER BY include_in_rebuilt_cost DESC, allocated_amount DESC`。 + +--- + +## 二十九、页面27:配送—倒挤成本对账 DistributionReconciliationPage + +> 单页面无Tab,1个API(GET),有MonthPicker。 +> 核心数据源:`mv_distribution_monthly`、`analytics.fact_inventory_snapshot`。 + +### API: /distribution/reconciliation + +后端先检查 `mv_distribution_monthly` 是否包含当月数据,如缺失则 `REFRESH MATERIALIZED VIEW CONCURRENTLY`。然后 `Promise.all` 并发5个查询,返回 `{ summary, storeReconciliation, topVariances, unmatchedItems, categoryReconciliation }`。 + +### Block1:核心指标卡片 + +| 显示指标 | 前端变量 | API字段 | 计算公式 | 数据源表 | +|---------|---------|---------|---------|---------| +| 对账品项行 | `summary.total_lines` | `total_lines` | `count(*)` | mv_distribution_monthly + fact_inventory_snapshot | +| 匹配行数 | `summary.matched_lines` | `matched_lines` | `count FILTER(dist>0 AND consumption>0)` | 同上 | +| 配送总额 | `summary.total_dist_amt` | `total_dist_amt` | `sum(dist_amt)` | mv_distribution_monthly | +| 实际耗用 | `summary.total_consumption_amt` | `total_consumption_amt` | `sum(consumption_amt)` | fact_inventory_snapshot | +| 倒挤应耗用 | `summary.reverse_consumption_amt` | `reverse_consumption_amt` | `期初+配送-期末` | — | +| 差异金额 | `summary.variance_amt` | `variance_amt` | `实际耗用-倒挤应耗用` | — | +| 差异率 | `summary.variance_pct` | `variance_pct` | `差异/实际耗用×100` | — | + +> 倒挤公式:应耗用 = 期初 + 配送 - 期末 | 差异 = 实际 - 应耗用。 + +### Block2:倒挤成本对账瀑布 + +> 自定义 BarChart shape 实现瀑布图:期初库存→配送入库→应耗用(倒挤)→实际耗用→期末库存→差异金额。 + +### Block3:品类维度对账 + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 品类 | `c.minor_category` | `minor_category` | mv_distribution_monthly | +| 品项数 | `c.item_count` | `item_count` | 同上 | +| 配送量 | `c.dist_qty` | `dist_qty` | 同上 | +| 配送金额 | `c.dist_amt` | `dist_amt` | 同上 | +| 不含税成本 | `c.dist_cost_excl_tax` | `dist_cost_excl_tax` | 同上 | +| 耗用金额 | `c.consumption_amt` | `consumption_amt` | fact_inventory_snapshot | +| 期末库存 | `c.ending_amt` | `ending_amt` | 同上 | +| 差异金额 | `c.variance_amt` | `variance_amt` | — | +| 差异率 | `c.variance_pct` | `variance_pct` | — | + +> 分组 BarChart(配送金额/耗用金额/期末库存)+ FilterableTable。 +> 后端使用 CTE:dist(按 minor_category 汇总配送)+ item_cat(品项分类映射)+ inv(库存按品项分类汇总),`FULL OUTER JOIN`。 + +### Block4:门店差异散点图 + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 门店名 | `s.store_name` | `store_name` | mv_distribution_monthly | +| 配送金额(X) | `s.dist_amt` | `dist_amt` | 同上 | +| 差异率(Y) | `s.variance_pct` | `variance_pct` | — | + +> ScatterChart,颜色按差异率分3档:正常(±3%)/关注(3~10%)/异常(>10%)。 + +### Block5:门店对账明细 + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 门店编码 | `s.store_code` | `store_code` | mv_distribution_monthly + fact_inventory_snapshot | +| 门店名称 | `s.store_name` | `store_name` | mv_distribution_monthly | +| 配送金额 | `s.dist_amt` | `dist_amt` | 同上 | +| 不含税成本 | `s.dist_cost_excl_tax` | `dist_cost_excl_tax` | 同上 | +| 期初库存 | `s.opening_amt` | `opening_amt` | fact_inventory_snapshot | +| 实际耗用 | `s.consumption_amt` | `consumption_amt` | 同上 | +| 期末库存 | `s.ending_amt` | `ending_amt` | 同上 | +| 倒挤应耗用 | `s.reverse_consumption_amt` | `reverse_consumption_amt` | — | +| 差异金额 | `s.variance_amt` | `variance_amt` | — | +| 差异率 | `s.variance_pct` | `variance_pct` | — | +| 负库存数 | `s.neg_inventory_count` | `neg_inventory_count` | fact_inventory_snapshot | + +> 后端 CTE:dist(按 store_code 汇总)+ inv(按 store_code 汇总,含 `count FILTER(is_negative)`)+ store_names,`FULL OUTER JOIN`。 +> `ORDER BY abs(差异金额) DESC`。 + +### Block6:Top30差异品项 + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 门店 | `v.store_code` | `store_code` | mv_distribution_monthly | +| 品项编码 | `v.item_code` | `item_code` | 同上 | +| 品项名称 | `v.item_name` | `item_name` | 同上 | +| 品类 | `v.minor_category` | `minor_category` | 同上 | +| 配送量 | `v.dist_qty` | `dist_qty` | 同上 | +| 配送金额 | `v.dist_amt` | `dist_amt` | 同上 | +| 期初 | `v.opening_amt` | `opening_amt` | fact_inventory_snapshot | +| 实际耗用 | `v.consumption_amt` | `consumption_amt` | 同上 | +| 期末 | `v.ending_amt` | `ending_amt` | 同上 | +| 倒挤应耗用 | `v.reverse_consumption_amt` | `reverse_consumption_amt` | — | +| 差异金额 | `v.variance_amt` | `variance_amt` | — | +| 差异率 | `v.variance_pct` | `variance_pct` | — | + +> 后端 CTE:dist(按 store_code+item_code 汇总,含 item_name/unit/category)+ inv,`LEFT JOIN`,`WHERE consumption_amt > 0`,`LIMIT 30`。 + +### Block7:未匹配品项(有配送无库存耗用) + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 品项编码 | `u.item_code` | `item_code` | mv_distribution_monthly | +| 品项名称 | `u.item_name` | `item_name` | 同上 | +| 品类 | `u.minor_category` | `minor_category` | 同上 | +| 配送量 | `u.dist_qty` | `dist_qty` | 同上 | +| 配送金额 | `u.dist_amt` | `dist_amt` | 同上 | +| 涉及门店数 | `u.store_count` | `store_count` | 同上 | + +> 后端 CTE:dist_items(按 item_code 汇总,含 `count(DISTINCT store_code)`)+ inv_items(库存中的 material_code),`WHERE d.item_code NOT IN (SELECT material_code FROM inv_items)`,`LIMIT 20`。 + +--- + +## 三十、页面28:多级BOM成本穿透 BomPenetrationPage + +> 单页面无Tab,2个API(GET overview + GET product detail),有MonthPicker。 +> 核心数据源:`central_kitchen_processing_cost`、`central_kitchen_recipe_consumption`、`analytics.fact_recipe_bom`、`analytics.dim_material`。 + +### API总览 + +| API | 触发条件 | 数据源表 | 说明 | +|-----|---------|---------|------| +| /central-kitchen/bom-penetration | 页面加载 | central_kitchen_processing_cost + recipe_consumption | 概览:产品列表+BOM汇总+多级链 | +| /central-kitchen/bom-penetration?productCode=xxx | 点击产品 | 同上 | BOM树递归展开 | + +### Block1:核心指标卡片 + +| 显示指标 | 前端变量 | 计算公式 | 数据来源 | +|---------|---------|---------|---------| +| 完工产品数 | `totalProducts` | `productList.length` | /central-kitchen/bom-penetration | +| 含多级BOM | `multiLevelProducts` | `productList.filter(has_multi_level_bom).length` | 同上 | +| BOM理论成本 | `totalBomTheoretical` | `bomSummary.reduce(bom_theoretical_amt)` | 同上 | +| BOM领用成本 | `totalBomIssue` | `bomSummary.reduce(bom_issue_amt)` | 同上 | +| 差异金额 | `totalVariance` | `bomSummary.reduce(variance_amt)` | 同上 | +| 半成品依赖链 | `multiLevelChains.length` | — | 同上 | + +### Block2:BOM成本结构Top15 + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 产品编码 | `b.product_code` | `product_code` | central_kitchen_processing_cost | +| 产品名称 | `b.product_name` | `product_name` | 同上 | +| 材料数 | `b.material_count` | `material_count` | central_kitchen_recipe_consumption | +| 半成品数 | `b.sub_product_count` | `sub_product_count` | 同上 | +| 理论成本 | `b.bom_theoretical_amt` | `bom_theoretical_amt` | 同上 | +| 领用成本 | `b.bom_issue_amt` | `bom_issue_amt` | 同上 | +| 单位理论成本 | `b.bom_unit_theoretical_cost` | `bom_unit_theoretical_cost` | — | +| 单位领用成本 | `b.bom_unit_issue_cost` | `bom_unit_issue_cost` | — | +| 差异金额 | `b.variance_amt` | `variance_amt` | — | +| 差异率 | `b.variance_pct` | `variance_pct` | — | + +> 分组 BarChart(理论成本+领用成本)+ FilterableTable,点击行可打开BOM树弹窗。 +> 后端 CTE:bom(JOIN recipe_consumption + LEFT JOIN processing_cost 判断半成品),`GROUP BY product_code, product_name, inbound_quantity`。 + +### Block3:BOM成本分布Treemap + +> Treemap,size=bom_theoretical_amt,颜色按差异率分3档。 +> 数据来源同 Block2 的 bomSummary。 + +### Block4:产品列表 + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 产品编码 | `p.product_code` | `product_code` | central_kitchen_processing_cost | +| 产品名称 | `p.product_name` | `product_name` | 同上 | +| 品类 | `p.category_minor` | `category_minor` | 同上 | +| 入库量 | `p.inbound_quantity` | `inbound_quantity` | 同上 | +| 理论成本 | `p.theoretical_cost` | `theoretical_cost` | 同上 | +| 实际成本 | `p.actual_cost` | `actual_cost` | 同上 | +| 材料数 | `p.material_count` | `material_count` | central_kitchen_recipe_consumption | +| 多级BOM | `p.has_multi_level_bom` | `has_multi_level_bom` | — | + +> 后端 CTE:bom_materials(recipe_consumption 中的 material_code)+ finished_products(processing_cost 中的 product_code)+ multi_level(bom_materials JOIN finished_products),判断产品是否为半成品。 + +### Block5:半成品依赖链 + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 成品编码 | `c.finished_code` | `finished_code` | central_kitchen_processing_cost | +| 成品名称 | `c.finished_name` | `finished_name` | 同上 | +| 成品配方 | `c.finished_recipe` | `finished_recipe` | 同上 | +| 半成品编码 | `c.sub_product_code` | `sub_product_code` | central_kitchen_recipe_consumption | +| 半成品名称 | `c.sub_product_finished_name` | `sub_product_finished_name` | central_kitchen_processing_cost | +| 半成品配方 | `c.sub_product_recipe` | `sub_product_recipe` | 同上 | + +> 后端 CTE:bom_materials + finished_products,`WHERE bm.material_code IN (SELECT product_code FROM finished_products)`。 + +### Block6:BOM树弹窗(选中产品后) + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 物料名称 | `node.material_name` | `material_name` | central_kitchen_recipe_consumption | +| 编码 | `node.material_code` | `material_code` | 同上 | +| 单位 | `node.unit` | `unit` | 同上 | +| 理论量 | `node.theoretical_qty` | `theoretical_qty` | 同上 | +| 领用量 | `node.issue_qty` | `issue_qty` | 同上 | +| 理论金额 | `node.theoretical_amt` | `theoretical_amt` | 同上 | +| 领用金额 | `node.issue_amt` | `issue_amt` | 同上 | +| 差异金额 | 前端计算 | — | `issue_amt - theoretical_amt` | + +> 后端使用 `WITH RECURSIVE bom_tree` 递归展开BOM,最大5层。 +> Level 1:直接原材料(JOIN recipe_agg ON pc.recipe_name = ra.recipe_name)。 +> Level 2+:递归展开半成品(`WHERE bt.is_finished_product AND bt.level < 5`)。 +> 无 productCode 时 `LIMIT 200`,有 productCode 时按指定产品展开。 +> 前端 `buildTree()` 将扁平数据构建为树结构,支持懒加载子节点。 + +--- + +## 三十一、页面29:销量驱动生产与要货计划 ProductionPlanPage + +> 单页面无Tab,1个API(GET),有MonthPicker。 +> 核心数据源:`mv_dish_sales_monthly`、`analytics.fact_recipe_bom`、`analytics.dim_sku`、`analytics.dim_material`、`mv_distribution_monthly`、`analytics.fact_inventory_snapshot`、`central_kitchen_processing_cost`、`inventory_store_mapping`。 + +### API: /sales-driven/production-plan + +后端使用单一连接(`pool.connect()`),先检查并刷新 `mv_dish_sales_monthly` 和 `mv_distribution_monthly` 物化视图,然后创建临时表 `tmp_sales_agg`(从物化视图导入销量数据并建索引),再 `Promise.all` 并发6个查询,返回 `{ summary, skuSales, materialDemand, storeDemand, ckProductionPlan, productionCoord }`。 + +### Block1:核心指标卡片 + +| 显示指标 | 前端变量 | API字段 | 计算公式 | 数据源表 | +|---------|---------|---------|---------|---------| +| 总菜品数 | `summary.total_dish_count` | `total_dish_count` | `count(DISTINCT dish_name)` | mv_dish_sales_monthly | +| 有BOM菜品 | `summary.matched_sku_count` | `matched_sku_count` | `count(*) JOIN fact_recipe_bom` | 同上 + fact_recipe_bom | +| BOM覆盖率 | `summary.bom_coverage_pct` | `bom_coverage_pct` | `matched/total×100` | — | +| BOM原料数 | `summary.total_bom_materials` | `total_bom_materials` | `count(DISTINCT material_code)` | fact_recipe_bom | +| 匹配销售额 | `summary.matched_amt` | `matched_amt` | `sum(amt) JOIN bom` | mv_dish_sales_monthly + fact_recipe_bom | +| 总销售额 | `summary.total_sales_amt` | `total_sales_amt` | `sum(amt)` | mv_dish_sales_monthly | +| CK生产计划 | 前端计算 | — | `ckProductionPlan.filter(demand_qty>0).length` | — | + +### Block2:BOM覆盖率饼图 + Top15原料需求 + +> PieChart(有BOM vs 无BOM菜品数)。 +> BarChart(Top15原料需求量),数据来自 materialDemand。 + +### Block3:中央厨房生产计划 + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 产品编码 | `r.product_code` | `product_code` | central_kitchen_processing_cost | +| 产品名称 | `r.product_name` | `product_name` | 同上 | +| 需求量 | `r.demand_qty` | `demand_qty` | mv_dish_sales_monthly × fact_recipe_bom | +| 实际入库 | `r.actual_inbound_qty` | `actual_inbound_qty` | central_kitchen_processing_cost | +| 差异量 | `r.variance_qty` | `variance_qty` | 需求-实际入库 | +| 差异率 | `r.variance_pct` | `variance_pct` | 差异/实际入库×100 | +| 涉及门店 | `r.store_count` | `store_count` | — | +| 实际成本 | `r.actual_cost` | `actual_cost` | central_kitchen_processing_cost | + +> 后端 CTE:ck_demand(销量×BOM 中 material_name IN processing_cost.product_name 的记录)+ ck_actual(processing_cost 按产品汇总),`LEFT JOIN` + `UNION ALL`(补全有实际无需求的产品)。 +> **注意**:需求与实际通过 `material_name = product_name` 名称匹配,非编码匹配。 + +### Block4:生产与配送协同 + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 产品编码 | `r.product_code` | `product_code` | central_kitchen_processing_cost | +| 产品名称 | `r.product_name` | `product_name` | 同上 | +| 完工入库 | `r.inbound_qty` | `inbound_qty` | 同上 | +| 实际成本 | `r.actual_cost` | `actual_cost` | 同上 | +| 理论成本 | `r.theoretical_cost` | `theoretical_cost` | 同上 | +| 配送量 | `r.dist_qty` | `dist_qty` | mv_distribution_monthly (DC=2) | +| 配送金额 | `r.dist_amt` | `dist_amt` | 同上 | +| 中央厨房出库 | `r.ck_consumption_qty` | `ck_consumption_qty` | fact_inventory_snapshot (store_code='2') | +| 中央厨房期末 | `r.ck_ending_qty` | `ck_ending_qty` | 同上 | +| 其他仓库消耗 | `r.other_wh_consumption_qty` | `other_wh_consumption_qty` | fact_inventory_snapshot (非门店非CK) | +| 其他仓库期末 | `r.other_wh_ending_qty` | `other_wh_ending_qty` | 同上 | +| 门店消耗 | `r.consumption_qty` | `consumption_qty` | fact_inventory_snapshot (门店) | +| 门店期末库存 | `r.ending_qty` | `ending_qty` | 同上 | +| 完工配送率 | `r.completion_distribution_rate` | `completion_distribution_rate` | 配送/完工×100 | +| 配送消耗率 | `r.distribution_consumption_rate` | `distribution_consumption_rate` | 门店消耗/配送×100 | +| 库存积压率 | `r.inventory_accumulation_rate` | `inventory_accumulation_rate` | 门店期末/门店消耗×100 | + +> 后端 CTE:ck_production + ck_distribution(DC=2) + ck_inventory(store=2) + other_wh_inventory + store_consumption,4个 `FULL OUTER JOIN`。 +> 其他仓库定义:`inventory_store_mapping WHERE sales_store_code IS NULL OR = ''` 且 `store_code != '2'`。 +> 门店定义:`store_code NOT IN (非门店的 cost_unit_code)`。 +> `LIMIT 50`。 + +### Block5:门店要货建议 + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 门店编码 | `r.store_code` | `store_code` | mv_dish_sales_monthly | +| 门店名称 | `r.store_name` | `store_name` | 同上 | +| 有BOM菜品数 | `r.sku_count` | `sku_count` | 同上 + fact_recipe_bom | +| 销量 | `r.total_qty` | `total_qty` | mv_dish_sales_monthly | +| 销售额 | `r.total_amt` | `total_amt` | 同上 | +| 原料需求量 | `r.total_material_demand_qty` | `total_material_demand_qty` | 同上 × fact_recipe_bom | +| 期末库存量 | `r.ending_inventory_qty` | `ending_inventory_qty` | fact_inventory_snapshot | +| 期末库存额 | `r.ending_inventory_amt` | `ending_inventory_amt` | 同上 | +| 建议要货量 | `r.suggested_order_qty` | `suggested_order_qty` | 原料需求-期末库存 | + +> 后端 CTE:store_demand(按 store_code 汇总销量+BOM展开)+ inv(按 store_code 汇总期末库存),`LEFT JOIN`。 + +### Block6:原料需求明细 + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 原料编码 | `r.material_code` | `material_code` | fact_recipe_bom | +| 原料名称 | `r.material_name` | `material_name` | dim_material | +| 单位 | `r.unit` | `unit` | fact_recipe_bom | +| 总需求量 | `r.total_demand_qty` | `total_demand_qty` | mv_dish_sales_monthly × fact_recipe_bom | +| 总需求金额 | `r.total_demand_amt` | `total_demand_amt` | 同上(含配送单价) | +| 涉及门店数 | `r.store_count` | `store_count` | — | +| 门店均需求 | `r.avg_store_demand` | `avg_store_demand` | — | + +> 后端 CTE:demand(tmp_sales_agg JOIN fact_recipe_bom LEFT JOIN dim_material LEFT JOIN mv_distribution_monthly 获取单价),`LIMIT 100`。 +> **注意**:原料单价通过 `m.material_name = ic.item_name` 名称匹配配送记录。 + +### Block7:SKU销量Top50 + +| 显示指标 | 前端变量 | API字段 | 数据源表 | +|---------|---------|---------|---------| +| 菜品名称 | `r.dish_name` | `dish_name` | mv_dish_sales_monthly | +| SKU编码 | `r.sku_code` | `sku_code` | dim_sku | +| 销量 | `r.qty` | `qty` | mv_dish_sales_monthly | +| 销售额 | `r.amt` | `amt` | 同上 | +| 门店数 | `r.store_count` | `store_count` | 同上 | +| 均价 | `r.avg_unit_price` | `avg_unit_price` | 同上 | +| 有BOM | `r.has_bom` | `has_bom` | fact_recipe_bom | +| 材料数 | `r.material_count` | `material_count` | 同上 | + +> 后端 CTE:sales(按 dish_name 汇总)LEFT JOIN dim_sku ON `s.dish_name = sk.standard_name` LEFT JOIN fact_recipe_bom,`LIMIT 50`。 +> **注意**:SKU匹配通过 `dish_name = standard_name` 名称匹配。 + +--- diff --git a/docs/智脑实施方法论/15-技术参考-指标口径一致性分析.md b/docs/智脑实施方法论/15-技术参考-指标口径一致性分析.md new file mode 100644 index 0000000..62ad1aa --- /dev/null +++ b/docs/智脑实施方法论/15-技术参考-指标口径一致性分析.md @@ -0,0 +1,154 @@ +# 15 · 技术参考:指标口径一致性分析 + +> 从数据溯源审计中提取的跨页面重复指标口径对比,以及已发现和待修复的问题清单。 + +## 1. 跨页面核心指标口径对比 + +### 1.1 营业收入(消费金额) + +| 页面 | 前端变量 | API | API字段 | 数据源表.字段 | +|------|---------|-----|---------|-------------| +| 总部驾驶舱 | `od?.consumption` | /overview | `consumption` | analytics.bill_fact.consumption | +| 老板驾驶舱 | `od?.consumption` | /overview | `consumption` | 同上 | +| 费用总览Tab | `ov.total_consumption` | /store-expense/overview | `total_consumption` | analytics.bill_fact.consumption | + +**口径:一致 ✅** + +### 1.2 优惠 + +| 页面 | 前端变量 | API | API字段 | 数据源表.字段 | +|------|---------|-----|---------|-------------| +| 总部驾驶舱 | `od?.discount` | /overview | `discount` | analytics.bill_fact.discount_total | +| 老板驾驶舱 | `od?.discount` | /overview | `discount` | 同上 | +| 费用总览Tab | `ov.total_discount` | /store-expense/overview | `total_discount` | 同上 | + +**口径:一致 ✅** + +### 1.3 实收 + +| 页面 | 前端变量 | API | API字段 | 数据源表.字段 | +|------|---------|-----|---------|-------------| +| 总部驾驶舱 | `od?.received` | /overview | `received` | analytics.bill_fact.received_total | +| 老板驾驶舱 | `od?.received` | /overview | `received` | 同上 | +| 费用总览Tab | `ov.total_received` | /store-expense/overview | `total_received` | analytics.mv_store_risk_rating_monthly.received | +| 利润瀑布 | `wf.received` | /overview/profit-waterfall | `received` | analytics.mv_store_risk_rating_monthly.received | + +**口径:一致 ✅** — `bill_fact.received_total` 汇总和物化视图汇总结果相同。 + +### 1.4 账单数 + +| 页面 | 前端变量 | API | API字段 | 数据源表.字段 | +|------|---------|-----|---------|-------------| +| 总部驾驶舱 | `od?.bill_count` | /overview | `bill_count` | analytics.bill_fact (count(*)) | +| 老板驾驶舱 | `ex?.total_bills` | /store-expense/overview | `total_bills` | analytics.mv_store_risk_rating_monthly.bill_count | + +**口径:一致 ✅** + +### 1.5 客单价 + +| 页面 | 计算方式 | 值 | +|------|---------|-----| +| 总部驾驶舱 | `avg(received_total)` from bill_fact | 38.29 | +| 老板驾驶舱 | `sum(received)/sum(bill_count)` | 38.29 | + +**口径:一致 ✅** — 数学结果相同。 + +### 1.6 门店贡献利润(实际) + +| 页面 | API | 计算方式 | 值 | +|------|-----|---------|-----| +| 总部驾驶舱 | /store-expense/overview | `sum(received) FILTER(费用匹配) - food_cost - operating_expense` | 6,982,110.42 | +| 老板驾驶舱(指标卡) | 同上 | 同上 | 同上 | +| 老板驾驶舱(瀑布图) | /overview/profit-waterfall | `sum(received) FILTER(has_expense) - food_cost - operating_expense` | 同上 | + +**口径:一致 ✅**(已修复) + +### 1.7 食材成本 + +| 页面 | API | 计算方式 | +|------|-----|---------| +| 总部驾驶舱 | /store-expense/overview | `sum(actual_food_cost)` | +| 老板驾驶舱(瀑布图) | /overview/profit-waterfall | `sum(COALESCE(actual_food_cost,0))` | +| 费用总览Tab | /store-expense/overview | 同总部 | + +**口径:一致 ✅** — `sum(NULL)` 忽略 vs `sum(COALESCE(NULL,0))` 加0,结果相同。 + +### 1.8 费用率 + +| 页面 | 计算方式 | 值 | +|------|---------|-----| +| 总部驾驶舱 | `sum(operating_expense)/matched_received*100` | 53.77% | +| 老板驾驶舱(瀑布图) | `wf.total_expense/wf.received*100`(matched口径) | 53.77% | +| 费用总览Tab | 同总部 | 53.77% | + +**口径:一致 ✅**(已修复) + +### 1.9 门店风险分布 / P0+P1门店 / 盈利亏损数 + +| 指标 | 页面 | API | 数据源 | +|------|------|-----|--------| +| 风险分布 | 总部/老板 | /stores/risk | mv_store_risk_rating_monthly.risk_level | +| P0/P1 | 总部/老板 | /stores/priority | mv_store_action_priority_deep_monthly | +| 盈利/亏损 | 总部/老板 | /store-expense/overview | count FILTER(actual_store_contribution > 0) | + +**口径:一致 ✅** + +## 2. 口径一致性保障原则 + +1. **同一指标多页面展示时,必须使用同一数据源**(物化视图或原始表,不能混用) +2. **分母口径必须一致**:如"费用率"分母必须统一为 matched_received(仅含费用匹配门店) +3. **FILTER vs COALESCE**:`sum(x) FILTER(WHERE has_expense)` 与 `sum(COALESCE(x,0))` 在无NULL行时结果相同,但语义不同——FILTER排除整行,COALESCE只替换NULL值 +4. **物化视图 vs 原始表**:优先用物化视图,避免直接查原始表(性能差 + 可能stale不一致) +5. **新增页面时**:如果复用已有指标,必须检查数据源是否一致,避免口径分裂 + +## 3. 已发现问题清单 + +### 已修复 ✅ + +| # | 问题 | 位置 | 修复方式 | +|---|------|------|---------| +| 1 | 利润瀑布 store_contribution 口径不一致 | /overview/profit-waterfall | received等改为 `FILTER(WHERE has_expense)` | +| 2 | 瀑布图费率分母不一致 | 前端除法 | received改为matched口径后分母一致 | +| 3 | mv_overview_monthly 刷新缺失 | 刷新脚本 | 加入DELETE+INSERT步骤 | +| 4 | 优惠率/毛利率/会员占比硬编码为0 | /overview API | 修正SQL计算 | +| 5 | Schema前缀错误 | /channel API | 移除analytics.前缀 | +| 6 | 列名不存在 | /stores/risk等 | SELECT * 或0 AS替代 | +| 7 | 日期格式不匹配 | 考勤相关API | to_char改中文格式 | +| 8 | 客流-人力匹配在岗人数不合理 | /situational-awareness/correlation | 改用打卡数据解析 | +| 9 | 客流月度汇总vs日均未对齐 | 同上 | 客流除以30天 | + +### 待确认 ⚠️ + +| # | 问题 | 位置 | 影响 | 建议 | +|---|------|------|------|------| +| 1 | KPI达成率利润口径不一致 | /analytics-enhanced/kpi | 利润率偏低~0.7pp | 分母改为matched_received | +| 2 | store-profit-ranking COALESCE导致无费用门店排名异常 | /overview/store-profit-ranking | 利润TOP5可能含无费用门店 | 加FILTER(has_expense) | +| 3 | StorePage公司均值硬编码 | StorePage.tsx:188 | 不随数据更新 | 改为API动态获取 | +| 4 | StorePage scorecard直接查bill_records | /stores/:code | 可能与物化视图不一致 | 改用物化视图 | + +## 4. 口径检查方法论 + +### 4.1 新增指标时的检查流程 + +``` +1. 该指标是否在其他页面已存在? + → 是:检查数据源是否一致(表、字段、过滤条件) + → 否:记录到溯源文档 +2. 分子分母的过滤条件是否一致? + → 如:费用率分母是否都用了matched_received +3. 是否用了物化视图? + → 优先用物化视图,避免直接查原始表 +4. 是否有NULL处理差异? + → sum(x) vs sum(COALESCE(x,0)) 在有NULL行时结果不同 +5. curl + psql 双向验证 + → API返回值与直查数据库一致 +``` + +### 4.2 定期口径审计 + +``` +1. 运行溯源文档中的"跨页面对比"部分 +2. 对每个指标,在所有出现的页面验证值是否一致 +3. 不一致的,定位差异原因(数据源、过滤条件、计算方式) +4. 修复并更新文档 +``` diff --git a/docs/智脑实施方法论/README.md b/docs/智脑实施方法论/README.md index e3a6836..3db0ceb 100644 --- a/docs/智脑实施方法论/README.md +++ b/docs/智脑实施方法论/README.md @@ -1,22 +1,56 @@ # 玄谋智脑 · 实施方法论与执行手册 -> 本文档体系总结"连锁餐饮企业智脑"项目的全部工作步骤、关键决策点和通用方法论,目标是形成可复制的执行手册,对类似项目快速落地。 +> 以经营战略为起点、以数据闭环为终点的企业管理方法论。借鉴FDE(前线部署工程)精神,适配中国连锁经营企业国情——用AI替代部分FDE职能,降低对人力的依赖。 -## 文档结构 +## 核心理念 + +玄谋智脑不是一套技术系统,而是**战略驱动→数据支撑→闭环执行→持续优化**的管理体系。 + +``` +老板战略 → 指标体系 → 数据本体 → 执行闭环 → AI协同构建 → 持续优化 + ↑ | + └────────────────── 反馈与优化 ←──────────────────────────┘ +``` + +## 八步工作法 + +| 步骤 | 文件 | 核心问题 | 输出 | +|------|------|---------|------| +| 一 | [02-步骤一-老板访谈与指挥层构建.md](02-步骤一-老板访谈与指挥层构建.md) | 老板要看什么、管什么、决策什么 | 指标体系、驾驶舱原型 | +| 二 | [03-步骤二-数据现状与本体层构建.md](03-步骤二-数据现状与本体层构建.md) | 现有数据能否支撑指标体系 | 数据溯源、物化视图 | +| 三 | [04-步骤三-中层访谈与执行层准备.md](04-步骤三-中层访谈与执行层准备.md) | 谁来做、做到什么程度、如何考核 | 岗位-指标矩阵、任务模板 | +| 四 | [05-步骤四-AI协同模型设计与逻辑闭环.md](05-步骤四-AI协同模型设计与逻辑闭环.md) | 业务逻辑闭环是否完整 | 模型设计、闭环验证 | +| 五 | [06-步骤五-AI协同本体层构建.md](06-步骤五-AI协同本体层构建.md) | 数据层代码和验证 | 物化视图、导入脚本 | +| 六 | [07-步骤六-AI协同后端API构建与验证.md](07-步骤六-AI协同后端API构建与验证.md) | API层代码和验证 | 可运行的API | +| 七 | [08-步骤七-AI协同前端UIUX设计与实现.md](08-步骤七-AI协同前端UIUX设计与实现.md) | 前端界面实现 | 可用的Dashboard | +| 八 | [09-步骤八-数据驱动闭环优化.md](09-步骤八-数据驱动闭环优化.md) | 持续优化循环 | 闭环运转机制 | + +> 总览见 [01-总体框架与八步工作法.md](01-总体框架与八步工作法.md) + +## 技术参考 | 文件 | 内容 | |------|------| -| [01-项目概述与架构.md](01-项目概述与架构.md) | 项目背景、技术架构、数据流、部署拓扑 | -| [02-数据接入与治理.md](02-数据接入与治理.md) | 原始数据导入、物化视图体系、数据质量校验、映射表管理 | -| [03-指标体系与API开发.md](03-指标体系与API开发.md) | 指标分层设计、后端API规范、常见SQL陷阱与修复模式 | -| [04-前端页面开发.md](04-前端页面开发.md) | 页面模板、组件规范、月份参数管理、数据展示约定 | -| [05-部署与运维.md](05-部署与运维.md) | 部署脚本、数据库备份、FRP隧道、PM2进程管理 | -| [06-调试排查手册.md](06-调试排查手册.md) | 常见问题分类、排查流程、修复模式速查 | -| [07-通用方法论.md](07-通用方法论.md) | 可复制的核心原则、风险清单、快速复制Checklist | +| [10-技术参考-项目概述与架构.md](10-技术参考-项目概述与架构.md) | 技术架构、数据流、部署拓扑 | +| [11-技术参考-部署与运维.md](11-技术参考-部署与运维.md) | 部署脚本、FRP隧道、PM2 | +| [12-技术参考-调试排查手册.md](12-技术参考-调试排查手册.md) | 问题分类、排查流程、实际案例 | +| [13-技术参考-通用方法论与避坑指南.md](13-技术参考-通用方法论与避坑指南.md) | 核心原则、风险清单、Checklist | +| [14-技术参考-数据溯源与API全量清单.md](14-技术参考-数据溯源与API全量清单.md) | 逐页面→API→SQL→字段映射(3500行) | +| [15-技术参考-指标口径一致性分析.md](15-技术参考-指标口径一致性分析.md) | 跨页面口径对比、问题清单 | + +## 阅读建议 + +- **新项目启动**:按 01→09 顺序阅读八步工作法 +- **新成员上手**:先读 01 了解框架,再读 10 了解架构,最后查 14 了解API全量映射 +- **排查问题**:直接查 12 调试排查手册 +- **口径审计**:查 15 指标口径一致性分析 +- **快速复制**:查 13 通用方法论中的 Checklist ## 适用场景 -- 连锁餐饮/零售企业的数据分析平台建设 +- 连锁经营企业(餐饮/零售/服务/教培)的数据分析平台建设 - 基于PostgreSQL物化视图的BI系统 - Express + React + Recharts 技术栈的Dashboard项目 - 多租户SaaS架构的垂直行业数据产品 +- AI协同的企业数字化转型项目 +- FDE模式在中国连锁经营行业的适配性落地