feat: 预算按战略地图隔离(map_id) — 切换地图数据区分

问题: 预算数据无map_id, 两地图共用KPI时预算无法区分(切地图数据均显示)
修复:
- budget_plans 加 map_id 字段+索引
- list 支持 map_id 过滤(含NULL历史预算兼容迁移)
- create 收 map_id + 去重键含map_id(同KPI不同地图可各自预算)
- 前端: loadBudget/loadStrategyBudget 传 map_id, 保存带 map_id
- 端到端验证: 地图51 F_REVENUE 300(map_id=51) 地图51显示/地图32不显示 ✓
pytest 35+11 passed, 部署
This commit is contained in:
Hermes CI Fix
2026-08-27 17:33:57 +08:00
parent 3c64dc767e
commit fd814462a2
3 changed files with 15 additions and 6 deletions
+10 -2
View File
@@ -3,7 +3,7 @@
"""
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session
from sqlalchemy import func
from sqlalchemy import func, or_
from typing import Optional
from datetime import datetime
@@ -20,6 +20,7 @@ router = APIRouter(prefix="/api/cma/budget", tags=["预算管理"],
@router.get("/plans")
def list_budget_plans(
kpi_id: Optional[int] = Query(None),
map_id: Optional[int] = Query(None, description="按战略地图过滤预算"),
period: Optional[str] = Query(None),
year: Optional[int] = Query(None),
version: Optional[str] = Query(None),
@@ -32,6 +33,9 @@ def list_budget_plans(
KPIDefinition, BudgetPlan.kpi_id == KPIDefinition.id
).filter(KPIDefinition.entity_id == entity_id)
if map_id:
# 按地图隔离: 显示该地图的预算 + 未绑定地图的历史预算(NULL, 兼容迁移)
query = query.filter(or_(BudgetPlan.map_id == map_id, BudgetPlan.map_id.is_(None)))
if kpi_id:
query = query.filter(BudgetPlan.kpi_id == kpi_id)
if period:
@@ -51,6 +55,7 @@ def list_budget_plans(
result.append({
"id": p.id,
"kpi_id": p.kpi_id,
"map_id": p.map_id,
"kpi_code": kpi.kpi_code if kpi else "",
"kpi_name": kpi.kpi_name if kpi else "",
"dimension": kpi.dimension if kpi else "",
@@ -88,12 +93,14 @@ def create_budget_plan(
year, month = period.split("-")
version = data.get("version", "v1.0")
map_id = data.get("map_id") # 预算归属地图(2026-08-27: 按地图隔离)
# 检查是否已有记录(去重)
# 检查是否已有记录(去重, 含map_id
existing = db.query(BudgetPlan).filter(
BudgetPlan.kpi_id == kpi_id,
BudgetPlan.period == period,
BudgetPlan.version == version,
BudgetPlan.map_id == map_id,
BudgetPlan.status == "active",
).first()
@@ -106,6 +113,7 @@ def create_budget_plan(
else:
plan = BudgetPlan(
kpi_id=kpi_id,
map_id=map_id,
period=period,
budget_value=budget_value,
budget_year=int(year),