feat: KPI多粒度目标值补提交 — dashboard API + 前端3视图(目标值月/季/年)

已上线未提交的历史功能(2026-08-17): kpi_target_by_frequency + target_monthly/quarterly/yearly 字段透传
This commit is contained in:
Hermes CI Fix
2026-08-20 06:57:13 +08:00
parent bd9c70ea05
commit dd53212bcc
5 changed files with 244 additions and 7 deletions
+26 -1
View File
@@ -52,6 +52,24 @@ def period_prefix(period_type: str):
return str(datetime.now().year)
return None
def kpi_target_by_frequency(k):
"""按考核频率返回对应周期的目标值(多粒度改造)
monthly/weekly -> target_monthly; quarterly/half_year -> target_quarterly; yearly -> target_yearly
兼容: 对应列无值时回退 target_value
"""
freq = (k.frequency or "monthly").lower()
if freq in ("monthly", "weekly"):
val = getattr(k, "target_monthly", None)
elif freq in ("quarterly", "half_year"):
val = getattr(k, "target_quarterly", None)
elif freq == "yearly":
val = getattr(k, "target_yearly", None)
else:
val = None
if val is None:
val = k.target_value
return val
@router.get("/summary")
def get_dashboard_summary(role: str = Query("ceo"), period: str = Query("month"),
db: Session = Depends(get_db), entity_id: int = Depends(get_entity_id)):
@@ -143,6 +161,7 @@ def get_dashboard_kpis(role: str = Query("ceo"), period: str = Query("month"),
result.append({
"id": k.id, "kpi_code": k.kpi_code, "kpi_name": k.kpi_name,
"dimension": k.dimension, "unit": k.unit, "target_value": k.target_value,
"target_monthly": k.target_monthly, "target_quarterly": k.target_quarterly, "target_yearly": k.target_yearly,
"actual_value": latest.actual_value if latest else None,
"period": latest.period if latest else None,
"alert_level": alert.alert_level if alert else "none",
@@ -198,6 +217,7 @@ def get_my_kpis(
"id": k.id, "kpi_code": k.kpi_code, "kpi_name": k.kpi_name,
"dimension": k.dimension, "unit": k.unit,
"target_value": k.target_value,
"target_monthly": k.target_monthly, "target_quarterly": k.target_quarterly, "target_yearly": k.target_yearly,
"actual_value": latest.actual_value if latest else None,
"period": latest.period if latest else period_str,
"alert_level": alert.alert_level if alert else "none",
@@ -251,6 +271,7 @@ def get_finance_analysis(
kpi_data.append({
"id": k.id, "kpi_code": k.kpi_code, "kpi_name": k.kpi_name,
"unit": k.unit, "target_value": k.target_value,
"target_monthly": k.target_monthly, "target_quarterly": k.target_quarterly, "target_yearly": k.target_yearly,
"actual_value": latest.actual_value if latest else None,
"threshold_green": k.threshold_green,
"threshold_yellow": k.threshold_yellow,
@@ -414,7 +435,7 @@ def my_dashboard(
).order_by(KPIValue.calculated_at.desc()).first()
actual = latest_v.actual_value if latest_v else None
target = k.target_value
target = kpi_target_by_frequency(k)
level = "gray"
if actual is not None and target:
# 反向指标(越低越好):费用率/渠补率/应收天数/返利率/成本率
@@ -437,6 +458,10 @@ def my_dashboard(
"dimension": k.dimension,
"category": k.category,
"target_value": target,
"target_monthly": k.target_monthly,
"target_quarterly": k.target_quarterly,
"target_yearly": k.target_yearly,
"frequency": k.frequency,
"actual_value": actual,
"unit": k.unit,
"level": level,