# 全页面数据溯源审计报告 > 目标:逐页面、逐指标追溯显示名称 → 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/* | --- ## 二、核心指标溯源与口径对比 ### 2.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` 的月度汇总。 ### 2.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` 也一致) ### 2.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),因为后者物化视图就来自前者。 ### 2.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。 ### 2.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 | **口径:一致 ✅** — 数学结果相同。 ### 2.6 优惠率 | 页面 | 前端变量 | API | API字段 | 计算方式 | |------|---------|-----|---------|---------| | 总部驾驶舱 | `od?.discount_rate_pct` | /overview | `discount_rate_pct` | `avg(discount_total/consumption*100)` from bill_fact = 19.52% | | 老板驾驶舱 | 无(不显示此指标) | - | - | - | **口径:N/A** — 仅总部驾驶舱显示。 ### 2.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) ### 2.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) ### 2.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) - sum(COALESCE(food_cost,0)) - sum(COALESCE(operating_expense,0))` | **7,703,472.16** | **口径:不一致 ❌** — 瀑布图用 COALESCE(...,0) 包含2家无费用门店,导致利润虚高72万。需修复 profit-waterfall API。 ### 2.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 | 前端除法 | `7703472/64409339*100` | **11.96%** | **口径:不一致 ❌** — 同 2.9,瀑布图口径不同。 ### 2.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,结果相同。 ### 2.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/64409339*100` | **34.87%** | **口径:不一致 ❌** — 分母不同(matched_received 6369万 vs all_received 6441万)。 ### 2.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,结果相同。 ### 2.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/64409339*100` | **53.17%** | | 费用总览Tab | `ov.overall_expense_rate_pct` | /store-expense/overview | `overall_expense_rate_pct` | 同总部 | 53.77% | **口径:不一致 ❌** — 瀑布图分母含全部94家。 ### 2.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结果相同。 **费率口径:瀑布图不一致 ❌** — 前端用 `wf.wage/wf.received*100`(分母含94家)vs store-expense用 `matched_received`(92家)。 ### 2.16 房租费用 / 房租费率 同 2.15,金额一致,费率瀑布图分母不一致。 ### 2.17 水电费用 / 水电费率 同 2.15,金额一致,费率瀑布图分母不一致。 ### 2.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))` | **口径:一致 ✅** — 金额相同。 ### 2.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家。 ### 2.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家。 ### 2.21 门店风险分布 | 页面 | 前端变量 | API | 数据源 | |------|---------|-----|--------| | 总部驾驶舱 | `riskSummary` | /stores/risk | analytics.mv_store_risk_rating_monthly.risk_level | | 老板驾驶舱 | `riskSummary` | /stores/risk | 同上 | **口径:一致 ✅** ### 2.22 P0/P1 门店 | 页面 | 前端变量 | API | 数据源 | |------|---------|-----|--------| | 总部驾驶舱 | `priorityRows` | /stores/priority | analytics.mv_store_action_priority_deep_monthly | | 老板驾驶舱 | `priorityRows` | /stores/priority | 同上 | **口径:一致 ✅** ### 2.23 成本异常分布 | 页面 | 前端变量 | API | 数据源 | |------|---------|-----|--------| | 老板驾驶舱 | `costOv.red_count` 等 | /cost-analysis/store-overview | analytics.mv_store_theoretical_actual_cost_monthly | | 成本分析Tab | 同上 | 同上 | 同上 | **口径:一致 ✅** ### 2.24 利润机会池 | 页面 | 前端变量 | API | 数据源 | |------|---------|-----|--------| | 老板驾驶舱 | `profitOpp` | /overview/profit-opportunity | analytics.mv_store_risk_rating_monthly + mv_store_operating_expense_monthly | **口径:N/A** — 仅老板驾驶舱显示。 ### 2.25 日度趋势 | 页面 | 前端变量 | API | 数据源 | |------|---------|-----|--------| | 总部驾驶舱 | `dailyRows` | /overview/daily | analytics.mv_overview_daily 或 bill_fact | | 老板驾驶舱 | `dailyRows` | /overview/daily | 同上 | **口径:一致 ✅** --- ## 三、发现的问题汇总 ### 问题1:利润瀑布 store_contribution 口径不一致 ❌ **位置**:`/overview/profit-waterfall` API (`data.ts:1082`) **现状**: ```sql round(sum(received) - sum(actual_food_cost) - sum(operating_expense), 2) AS store_contribution ``` - `sum(received)` = 64,409,339(94家) - `sum(actual_food_cost)` = 22,459,074(92家,NULL被忽略) - `sum(operating_expense)` = 34,246,793(92家,NULL被忽略) - 结果 = 7,703,472(含2家无费用门店的实收429万作为"利润") **正确值**(与 store-expense/overview 一致):6,982,110(仅92家匹配门店) **影响**:BossPage 利润瀑布图和占比条显示的"门店贡献利润"比指标卡多72万,贡献率高1个百分点。 ### 问题2:利润瀑布各项费率分母不一致 ❌ **位置**:BossPage.tsx 前端计算 (line 296-318) **现状**:前端用 `wf.received`(64,409,339,94家)做分母计算食材成本率、费用率、贡献率,但 store-expense/overview 用 `matched_received`(63,687,977,92家)做分母。 | 指标 | 瀑布图口径 | store-expense口径 | 差异 | |------|-----------|------------------|------| | 食材成本率 | 34.87% | 35.26% | 0.39pp | | 费用率 | 53.17% | 53.77% | 0.60pp | | 贡献率 | 11.96% | 10.96% | 1.00pp | ### 问题3:mv_overview_monthly 刷新机制不完整 ⚠️ **现状**:`mv_overview_monthly` 是普通表(非物化视图),之前刷新脚本未包含它的更新步骤,导致数据导入后该表不更新。 **已修复**:刷新脚本已加入 DELETE+INSERT 步骤。 --- ## 四、修复方案 ### 修复问题1+2:统一利润瀑布口径 将 `/overview/profit-waterfall` 的 `store_contribution` 和 `received` 改为仅计算有费用门店,与 `/store-expense/overview` 保持一致。 **修改文件**:`server/src/routes/data.ts` profit-waterfall API **修改内容**: 1. `received` → `sum(received) FILTER (WHERE has_expense)` 2. `store_contribution` → `sum(received) FILTER (WHERE has_expense) - sum(actual_food_cost) - sum(operating_expense)` 3. `consumption` 和 `discount` 也改为 `FILTER (WHERE has_expense)` 保持同口径 这样瀑布图的 received、food_cost、expense、contribution 全部基于92家匹配门店,与 store-expense/overview 完全一致。