# KPI 看板 H2 数据流修复（2026-08-08）

## 核心架构

```
ERP 导出 Excel → 上传 → 质检 → 识别月份 → 路由更新
                                      │
                    ┌─────────────────┴─────────────────┐
                    ▼                                      ▼
            当前月 (8月)                           历史月 (7月)
           kpi_progress.json                    three_year_monthly.json
           (当月KPI, 18人)                      (7月=353.6万, 8月=115.7万)
                    │                                      │
                    └──────────────┬──────────────────────┘
                                   ▼
                          kpi_dashboard.json
                   (total_h2_actual = 7月+8月 = 469.3万)
                                   │
                                   ▼
                        merge_workbench_data.py
                                   │
                                   ▼
                        workbench_data.json → CloudBase
```

## 三层数据：前端消费路径

| 数据 | 前端来源 | 当前值 | 更新方式 |
|------|---------|--------|---------|
| 累计达成 | `kpiDashboard.total_h1_h2` | 2633.3万 | merge时自动计算 |
| 当月KPI | `kpiProgress.total` | 118.4万 | MCP cron每日刷新 |
| H2月度图表 | `threeYearMonthly['2026']['7']`~`['12']` | 7月353.6,8月115.7 | 上传ERP后更新 |

## 已修复的 6 个 Bug

### 1. `mcp_kpi_pipeline.py:115` — total_h2_actual 只取单月
```python
# ❌ 只取当前月索引（如8月=115.7万），丢失7月
kpi['total_h2_actual'] = sum(p['h2_actual_months'][month_idx] for p in kpi['people'])

# ✅ 取每人累计 H2
kpi['total_h2_actual'] = sum(p.get('h2_actual', 0) for p in kpi['people'])
```

### 2. `index.html getKPI()` — h2Actuals 把当月放第一位
```javascript
// ❌ prog.total(8月)塞进7月位置
h2Actuals: [current, 0, 0, 0, 0, 0]

// ✅ 从 threeYearMonthly 按月份取
var tym = d.threeYearMonthly || {};
var t2026 = tym['2026'] || {};
var h2Actuals = [
  t2026['7'] || 0,  // 7月
  t2026['8'] || current,  // 8月
  t2026['9'] || 0,  // 9月
  ...
];
```

### 3. `index.html` — fullYearTax 用 H1+当月 缺7月
```javascript
// ❌ 缺7月 353.6万
var fullYearTax = filteredYtd + prog.total;  // H1 + 当月

// ✅ 无筛选时用权威累计值
if (!filteredSalesSet) fullYearTax = dash.total_h1_h2 || fullYearTax;
```

### 4. `cb_sync_data.sh` — 未同步 kpi_dashboard.json
前端 ENDPOINTS 直接读 `../数据/kpi_dashboard.json`（不是 workbench_data.json 内嵌），CloudBase 上缺失该文件导致看板显示旧数据。

修复：在 `cb_sync_data.sh` 的 FILES 列表中加入 `"kpi_dashboard.json"`

### 5. `process_uploaded_file` — 不识别月份，盲目覆盖
```python
# 旧逻辑：所有上传都写入 kpi_progress.json（当月）
# 新逻辑：从 单据编号 前缀检测月份（ZHBR2607=7月, ZHBR2608=8月）
# → 当前月 → kpi_progress.json
# → 历史月 → three_year_monthly + kpi_dashboard
```

### 6. `str(None) = 'None'` — 合计行不过滤
ERP 合计行的 单据编号 为 Python `None`，`str(None)` = `'None'`（字面值），不会被 `not bn` 跳过。
过滤条件：`not bn or bn == 'None' or '合计' in bn`

## 数据权威性

| 用途 | 权威源 |
|------|--------|
| H1 金额 | `kpi_dashboard.total_h1`（已审计） |
| 7月金额 | `three_year_monthly['2026']['7']`（上传ERP校准，353.6万） |
| 8月金额 | `three_year_monthly['2026']['8']`（上传ERP更新，逐次递增） |
| 当月MCP | `kpi_progress.total`（每日0点cron从MCP刷新，118.4万） |
| 累计总额 | `kpi_dashboard.total_h1_h2`（从threeYearMonthly计算，2633.3万） |

MCP vs ERP 的差异属正常（MCP订单不含全部ERP数据），累计以ERP上传为准。
