feat: KPI多粒度目标值补提交 — dashboard API + 前端3视图(目标值月/季/年)
已上线未提交的历史功能(2026-08-17): kpi_target_by_frequency + target_monthly/quarterly/yearly 字段透传
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user