# CMA本体三支柱：科目↔KPI↔OKR 三层互联 — 交付报告

> 任务：yanxue-cma-ontology-trilogy.md（2026-08-19 21:00 并发任务）
> 执行：项目Bot（wecom-project） | 完成：2026-08-19 22:56
> 优先级：P1（本体层核心补全）

## 交付内容

### 1. 数据层（3张新表 + 种子数据）
| 表 | 作用 | 数据量 | 验收 |
|:--|:--|:--|:--|
| `kpi_subject_map` | 科目↔KPI映射（指标→底层账） | **89条映射 / 24个KPI** | ≥10 ✓ |
| `objective_kpi` | KPI↔O支撑（目标→指标） | **3个O × 5个KPI** | 各≥3 ✓ |
| `krs` | 关键结果KR（OKR完整化） | **3个O × 3个KR** | 各2-3 ✓ |

- 备份：`backups/ontology-trilogy-backup-20260819.sql`（subjects/kpi_definitions/objectives 全量，135KB）
- 可重放脚本：`backend/scripts/seed_ontology_trilogy.sql`（DDL + 种子，幂等可重跑）

### 2. API层（`backend/app/api/ontology.py`）
- `GET /api/cma/ontology/trace?objective_id=N` — **本体追溯链**：O(目标) → KPI(指标) → 科目(数据)，含 KR 列表、KPI 支撑权重、科目 calc_type/weight
- `GET /api/cma/ontology/objectives` — 全部 OKR 三层链路概览（前端用）

### 3. 前端层（`OkrDetail.vue` + `api/index.ts`）
- OKR 详情新增「本体追溯链」页签：追溯链横幅 + KR 卡片（目标/当前值/进度）+ KPI→科目 标签流（calc_type/weight），非科目驱动指标明确标注"不追溯账本"

## 追溯链实测（O→KPI→科目）

```
O#11 优化成本结构 → 5 KPI → 24 科目
  费用率 → [6601销售费用, 6602管理费用, 6603财务费用, 6001收入(分母)]
  净利润 → [6001+6051+6011+6111收入 - 6401-6402成本 - 6601-6602-6603费用...12科目]
O#12 保障现金流 → 5 KPI → 16 科目
O#13 渠道关系改善 → 5 KPI → 7 科目
```

从任一 O 可逐层下钻到账本；反之从科目可上溯到目标。

## 验证记录（铁律七）

1. ✅ 备份完成（mysqldump 3表 135KB）
2. ✅ 每步 SQL 后 SELECT 验证（89/15/9 行确认）
3. ✅ 后端重启：`systemctl restart cma-backend`（systemd，非 restart.sh 的 pkill 模式）→ active + `/health` ok
4. ✅ 追溯链 API 3个O全部跑通（含 KR + 科目映射）
5. ✅ 前端 `npm run build` 13.89s 成功，已部署 `/var/www/cma/`
6. ✅ 回归门：`pytest tests/` → **409 passed, 1 xfailed, 0 failed**
   - 注：首次全量跑有 13 个 test_reports 失败，二次全量 + 单文件隔离均通过 → 属既有测试排序/状态污染，与本改动无关

## 遗留说明

- 业务/调研类 KPI（客户满意度、保留率等）非科目驱动，trace 中 subjects 为空数组并标注，符合本体语义（不强行虚构账本映射）
- `models/__init__.py` 同时含并发任务"KPI多粒度"未提交列（target_monthly/quarterly/yearly，2026-08-17已上线），本提交一并带入（同文件无法拆分，功能均已完成）
- 并发任务"自动化测试补覆盖"的 conftest/tests 改动未包含在本提交

## Git

- 提交：本体三支柱(科目↔KPI↔OKR)三层互联 + 追溯链API + OKR详情页签
- 推送：SSH 2222 → git.sxbh.ltd
