feat: 多租户隔离P2批1 — OKR域+kpi_values加entity_id列
- 模型: Objective/KR/ObjectiveKPI/KPIValue 加 entity_id - DB: 4表加列; kpi_values 1610条按kpi_id回填(1269酣客/341博海) - OKR域: 测试O删除重建; okr list/get/create + ontology trace/objectives 按token企业隔离(跨企业404) - KPIValue写入: data/bot_bridge/bot_kpis 创建时带entity_id - 验证: 酣客创建OKR博海不可见; 跨企业读404; pytest 451通过(expenses单跑37通过为既有排序flaky)
This commit is contained in:
+11
-8
@@ -7,8 +7,9 @@ from sqlalchemy import func
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Optional
|
||||
from app.database import get_db
|
||||
from app.deps import get_entity_id
|
||||
from app.auth_middleware import require_role
|
||||
from app.models import Objective, ActionPlan
|
||||
from app.models import Objective, ActionPlan, KR, ObjectiveKPI, KPIDefinition
|
||||
|
||||
router = APIRouter(prefix="/api/cma/okr", tags=["OKR目标管理"],
|
||||
dependencies=[Depends(require_role("ceo", "finance", "it"))],
|
||||
@@ -21,9 +22,10 @@ def list_objectives(
|
||||
dimension: Optional[str] = Query(None),
|
||||
status: Optional[str] = Query(None),
|
||||
db: Session = Depends(get_db),
|
||||
entity_id: int = Depends(get_entity_id),
|
||||
):
|
||||
"""列出OKR目标"""
|
||||
q = db.query(Objective)
|
||||
"""列出OKR目标(账套隔离: 按token企业, 2026-08-23 P2)"""
|
||||
q = db.query(Objective).filter(Objective.entity_id == entity_id)
|
||||
if quarter:
|
||||
q = q.filter(Objective.quarter == quarter)
|
||||
if dimension:
|
||||
@@ -55,8 +57,9 @@ def list_objectives(
|
||||
def create_objective(
|
||||
data: dict,
|
||||
db: Session = Depends(get_db),
|
||||
entity_id: int = Depends(get_entity_id),
|
||||
):
|
||||
"""创建OKR目标(支持JSON Body和Query参数两种方式)"""
|
||||
"""创建OKR目标(支持JSON Body和Query参数两种方式)— 账套隔离: 强制token企业"""
|
||||
# 兼容旧版Query参数
|
||||
title = data.get("title") or ""
|
||||
quarter = data.get("quarter") or ""
|
||||
@@ -66,7 +69,7 @@ def create_objective(
|
||||
if not title or not quarter:
|
||||
raise HTTPException(422, "缺少必填字段: title, quarter")
|
||||
obj = Objective(title=title, quarter=quarter, description=description,
|
||||
dimension=dimension, owner=owner)
|
||||
dimension=dimension, owner=owner, entity_id=entity_id)
|
||||
db.add(obj)
|
||||
db.commit()
|
||||
db.refresh(obj)
|
||||
@@ -74,9 +77,9 @@ def create_objective(
|
||||
|
||||
|
||||
@router.get("/{obj_id}")
|
||||
def get_objective(obj_id: int, db: Session = Depends(get_db)):
|
||||
"""获取单个OKR详情"""
|
||||
obj = db.query(Objective).filter(Objective.id == obj_id).first()
|
||||
def get_objective(obj_id: int, db: Session = Depends(get_db), entity_id: int = Depends(get_entity_id)):
|
||||
"""获取单个OKR详情(账套隔离: 跨企业404)"""
|
||||
obj = db.query(Objective).filter(Objective.id == obj_id, Objective.entity_id == entity_id).first()
|
||||
if not obj:
|
||||
raise HTTPException(404, "目标不存在")
|
||||
krs = db.query(ActionPlan).filter(ActionPlan.objective_id == obj_id).all()
|
||||
|
||||
Reference in New Issue
Block a user