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:
@@ -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详情包含关联KR(KR完整修复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(
|
||||
|
||||
Reference in New Issue
Block a user