wip(strategy-map): V1+V3 合版 + v2/v3 口径(完备度/C1 hold/57 归档组)

This commit is contained in:
Hermes CI Fix
2026-10-19 10:33:40 +08:00
parent 0fc2c6109e
commit 4d20c27de4
16 changed files with 2116 additions and 89 deletions
+24 -1
View File
@@ -16,6 +16,15 @@ import logging
logger = logging.getLogger(__name__)
# ── C1 数据前置(改造单 v2 §3,硬约束)──────────────────────────────
# C_CUST_CONCENTRATION 的 69 个实测点含 2026-10 未来期与重复值;清理完成前:
# ① 相关目标节点显示「数据待核」、**不着色**(level=pending);
# ② 该 KPI 的实测值/达成率不得进入摘要条、节点详情、趋势图(96.3% 零出口)。
# 清理单据落地后删除本表即可恢复;不要在别处另写白名单。
DATA_HOLD_KPIS = {
"C_CUST_CONCENTRATION": "数据待核:C1 实测点含未来期与重复值,清理未完成",
}
router = APIRouter(prefix="/api/cma/maps", tags=["战略地图"],
dependencies=[Depends(require_role("ceo", "finance"))],
)
@@ -74,6 +83,18 @@ def list_maps(db: Session = Depends(get_db), entity_id: int = Depends(get_entity
maps = db.query(StrategicMap).filter(StrategicMap.entity_id == entity_id).order_by(StrategicMap.updated_at.desc()).all()
return {"data": [m_to_dict(m, db) for m in maps]}
@router.get("/strategy/revenue-caliber")
def strategy_revenue_caliber(entity_id: int = Depends(get_entity_id)):
"""战略地图摘要条 · 收入口径状态(真数据铁律:未闭合不出单一汇总数)。
2026-10-18 改造单 v2 §4:A1 收入口径未闭合前,前端只显示「口径待定」+
分业务位(酒类代销 / IT自营,amount=None ⇒ 显示「—/无数据」);
后端不得擅自选总额/净额,也不得把两块合并成一个「营业收入」。
"""
from app.data import revenue_caliber
return revenue_caliber.snapshot(entity_id)
@router.post("")
def create_map(data: dict, db: Session = Depends(get_db), entity_id: int = Depends(get_entity_id)):
# 空白地图默认四层空结构(避免dimensions=NULL导致加载报错)
@@ -1026,7 +1047,9 @@ def get_map_review(map_id: int, level: Optional[str] = None, db: Session = Depen
if level and kpi_def.kpi_level != level:
continue
lv = latest_values.get(kpi_def.id, {})
actual = lv.get("actual_value")
# C1 数据前置:held KPI 的实测值一律不外泄(96.3% 零出口)
held = code in DATA_HOLD_KPIS
actual = None if held else lv.get("actual_value")
# 多粒度目标优先: 月目标(多数KPI月度) → 兼容legacy target_value (OpenCode审查#5)
target = kpi_def.target_monthly or kpi_def.target_value
# 判断红黄绿灯(绿≥90% / 黄60-90% / 红<60%)