feat: KPI详情历史数据对齐元数据 — 目标值/偏差%/红黄绿判定/单位/数据批次
- 后端: get_kpi的values附带target_value/deviation_pct/level/score/unit 判定对齐工作台语义: 正向≥0.9绿/≥0.7黄/否则红; 反向≤目标绿/≤1.1倍黄/否则红 - 前端: 历史数据表格新增目标值/偏差/判定列, 实际值带单位+红黄着色, 新增数据批次列 - 验证: 渠补率2月84%=黄(超5%), 5月88.3%=红(超10.4%), 收入全部red(远低于1200万目标)
This commit is contained in:
+36
-5
@@ -485,21 +485,52 @@ def get_kpi(kpi_id: int, db: Session = Depends(get_db), entity_id: int = Depends
|
||||
result = kpi_to_dict(kpi)
|
||||
# 附带历史数据(前端KPI详情"历史数据"Tab依赖)
|
||||
# 2026-08-26修复: 原实现只返回定义信息,values缺失导致历史数据Tab空白
|
||||
# 2026-08-26增强: values对齐KPI元数据(目标值/偏差/红黄绿判定/单位)
|
||||
vals = db.query(KPIValue).filter(
|
||||
KPIValue.kpi_id == kpi_id,
|
||||
KPIValue.actual_value.isnot(None),
|
||||
).order_by(KPIValue.period.asc()).all()
|
||||
result["values"] = [
|
||||
{
|
||||
is_reverse = kpi.kpi_code in REVERSE_INDICATORS
|
||||
target = kpi.target_value
|
||||
result["values"] = []
|
||||
for v in vals:
|
||||
# 判定红黄绿(对齐工作台语义:正向≥0.9绿/≥0.7黄/否则红;反向≤目标绿/≤1.1倍黄/否则红)
|
||||
level = "info"
|
||||
score = None
|
||||
if target and v.actual_value is not None:
|
||||
if is_reverse:
|
||||
if v.actual_value <= target:
|
||||
level = "green"
|
||||
elif v.actual_value <= target * 1.1:
|
||||
level = "yellow"
|
||||
else:
|
||||
level = "red"
|
||||
else:
|
||||
ratio = v.actual_value / target
|
||||
if ratio >= 0.9:
|
||||
level = "green"
|
||||
elif ratio >= 0.7:
|
||||
level = "yellow"
|
||||
else:
|
||||
level = "red"
|
||||
score, _ = _calc_five_tier_score(v.actual_value, target, is_reverse=is_reverse)
|
||||
# 偏差率(相对目标)
|
||||
deviation = None
|
||||
if target and target != 0 and v.actual_value is not None:
|
||||
deviation = round((v.actual_value - target) / target * 100, 1)
|
||||
result["values"].append({
|
||||
"id": v.id,
|
||||
"period": v.period,
|
||||
"actual_value": v.actual_value,
|
||||
"target_value": target,
|
||||
"unit": kpi.unit or "",
|
||||
"deviation_pct": deviation,
|
||||
"level": level,
|
||||
"score": score,
|
||||
"source_type": v.source_type,
|
||||
"data_status": v.data_status,
|
||||
"source_batch": v.source_batch,
|
||||
}
|
||||
for v in vals
|
||||
]
|
||||
})
|
||||
return result
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user