- 后端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表
38 lines
1.3 KiB
Python
38 lines
1.3 KiB
Python
"""
|
|
KR完整修复(2026-08-27) 迁移脚本:
|
|
读 strategic_maps.dimensions JSON → 同步 objectives + krs 表
|
|
复用 maps.py 的 _sync_objectives_krs 逻辑
|
|
"""
|
|
import sys, os
|
|
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
|
|
|
from app.database import get_session_local
|
|
from app.models import StrategicMap, KR, Objective
|
|
from app.api.maps import _sync_objectives_krs
|
|
|
|
|
|
def migrate():
|
|
db = get_session_local()()
|
|
try:
|
|
maps = db.query(StrategicMap).all()
|
|
total_kr = 0
|
|
for m in maps:
|
|
before = db.query(KR).filter(KR.entity_id == (m.entity_id or 1)).count()
|
|
_sync_objectives_krs(m, db)
|
|
after = db.query(KR).filter(KR.entity_id == (m.entity_id or 1)).count()
|
|
total_kr += (after - before)
|
|
print(f"地图[{m.id}] {m.title} (entity={m.entity_id}): KR {before} → {after}")
|
|
# 汇总
|
|
print(f"\n迁移完成: krs表总记录 = {db.query(KR).count()}")
|
|
print(f"objectives表总记录 = {db.query(Objective).count()}")
|
|
# 显示样本
|
|
rows = db.query(KR).order_by(KR.id).limit(5).all()
|
|
for kr in rows:
|
|
print(f" KR#{kr.id}: {kr.title} | op={kr.operator} | target={kr.target_value} | weight={kr.weight} | obj={kr.objective_id}")
|
|
finally:
|
|
db.close()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
migrate()
|