feat(KR): KR完整修复 — krs表打通+方向符号operator+权重自由输入

- 后端okr.py: KR读取从ActionPlan改为krs表, 新增KR CRUD API(POST/PUT/DELETE /okr/{objective_id}/krs) + 批量sync
- operator方向符号: krs表加operator/tolerance/weight/sort_order/monthly_milestones列
- progress方向感知计算(>=/>: current/target, <=/<: target/current, =: 容差), 达成→status=achieved
- 关联KPI自动继承方向(threshold_green解析: F_COST_RATIO<=18等)
- maps.py: 保存地图时自动同步objectives+krs表, JSON→krs数据迁移脚本
- 前端: 权重下拉改自由数字输入(可小数33.33) + 方向选择器(≥/≤/>/</=) + 自动平分按钮 + KPI方向继承提示
- pytest: 10个新测试(krs CRUD/方向感知/权重校验/多租户隔离) + 更新旧KR测试
- 迁移: 现有strategic_maps JSON 12条KR已写入krs表
This commit is contained in:
Hermes CI Fix
2026-08-27 10:59:56 +08:00
parent 87cb9e7db2
commit 61936302b2
11 changed files with 1030 additions and 123 deletions
+20 -9
View File
@@ -10,7 +10,7 @@ from tests.conftest import (
create_test_user, get_token_for_user, auth_header,
create_test_kpi, create_test_map,
)
from app.models import Objective, ActionPlan, KPIDefinition, BscLayerConfig
from app.models import Objective, ActionPlan, KPIDefinition, BscLayerConfig, KR
# ============================================================
@@ -333,13 +333,21 @@ class TestOKRFullLifecycle:
assert kr_data["status"] == "pending"
def test_get_objective_with_krs(self, client: TestClient, db: Session):
"""TC11: 查看OKR详情包含关联KR"""
"""TC11: 查看OKR详情包含关联KRKR完整修复2026-08-27: 从krs表读取)"""
create_test_user(db)
token = get_token_for_user(client)
kpi = create_test_kpi(db, kpi_code="C_CHANNEL_REBATE")
obj = create_test_objective(db, title="优化成本结构")
kr = create_test_kr(db, kpi_id=kpi.id, objective_id=obj.id,
title="渠补率降到75%")
# KR落krs表(KR完整修复后,ActionPlan不再是KR存储)
kr = db.query(KR).filter(KR.objective_id == obj.id).first()
if not kr:
from app.models import KR as KRModel
kr = KRModel(entity_id=1, objective_id=obj.id, title="渠补率降到75%",
metric_kpi_id=kpi.id, operator="<=", target_value=75,
weight=33, status="pending", progress=0)
db.add(kr)
db.commit()
db.refresh(kr)
resp = client.get(
f"/api/cma/okr/{obj.id}",
@@ -353,15 +361,18 @@ class TestOKRFullLifecycle:
assert kr_found, "KR应出现在OKR详情中"
def test_objective_progress_from_krs(self, client: TestClient, db: Session):
"""TC12: OKR进度随KR进度自动计算"""
"""TC12: OKR进度随KR进度自动计算KR完整修复2026-08-27: krs表)"""
create_test_user(db)
token = get_token_for_user(client)
kpi = create_test_kpi(db)
obj = create_test_objective(db)
kr1 = create_test_kr(db, kpi_id=kpi.id, objective_id=obj.id,
title="KR1", progress=80)
kr2 = create_test_kr(db, kpi_id=kpi.id, objective_id=obj.id,
title="KR2", progress=40)
from app.models import KR as KRModel
kr1 = KRModel(entity_id=1, objective_id=obj.id, title="KR1",
metric_kpi_id=kpi.id, progress=80, weight=50)
kr2 = KRModel(entity_id=1, objective_id=obj.id, title="KR2",
metric_kpi_id=kpi.id, progress=40, weight=50)
db.add_all([kr1, kr2])
db.commit()
# 触发progress重算
resp = client.patch(