fix(kpi): single source of truth for REVERSE_INDICATORS + drop F_FACTORY_REBATE_RATE from reverse set
P-6 (M2 gate 2, FIN-CE-REVIEW-20260915-01): kpis.REVERSE_INDICATORS is now the only authoritative direction definition; dashboard.py imports it instead of carrying a literal copy; bot_kpis.py derives REVERSE_BOT_INDICATORS from it (dead import removed). F_FACTORY_REBATE_RATE (upstream factory rebate rate, higher=better) was wrongly treated as reverse: 278.7% vs target 80 scored 1/danger, now 5/success and workbench three-color red -> green. No DB write, no scoring-engine logic change, no data_level/frontend touch.
This commit is contained in:
@@ -14,8 +14,17 @@ router = APIRouter(prefix="/api/cma/bot-kpis", tags=["Bot KPI管理"],
|
||||
dependencies=[Depends(require_auth)],
|
||||
)
|
||||
|
||||
# 反向指标编码(值越低越好)
|
||||
REVERSE_BOT_INDICATORS = ['FB_RESPONSE_TIME']
|
||||
# 反向指标编码(值越低越好)。
|
||||
# 方向权威源 = app.api.kpis.REVERSE_INDICATORS(2026-09-15 M2 准入2 收口):
|
||||
# 本文件原 import 了权威表却未使用、另立字面量 ['FB_RESPONSE_TIME'],会让同一 kpi_code
|
||||
# 在「能力评分」(取权威表=反向) 与「Bot 自评」(取本表=正向) 方向打架
|
||||
# (实测同一宇宙内 F_COST_RATIO / F_AR_DAYS / F_REBATE_RATE 三码即为此类)。
|
||||
# 现改为派生:权威表 ∪ Bot 专有反向指标(零漂移)。
|
||||
from app.api.kpis import REVERSE_INDICATORS as _AUTHORITATIVE_REVERSE_INDICATORS
|
||||
|
||||
BOT_ONLY_REVERSE_INDICATORS = ['FB_RESPONSE_TIME']
|
||||
REVERSE_BOT_INDICATORS = list(_AUTHORITATIVE_REVERSE_INDICATORS) + [
|
||||
c for c in BOT_ONLY_REVERSE_INDICATORS if c not in _AUTHORITATIVE_REVERSE_INDICATORS]
|
||||
|
||||
|
||||
def _calc_bot_kpi_score(current_value, target_value, is_reverse=False):
|
||||
@@ -68,8 +77,6 @@ def list_bot_kpis(
|
||||
"overall": None,
|
||||
}
|
||||
|
||||
from app.api.kpis import REVERSE_INDICATORS as _ri
|
||||
|
||||
result_kpis = []
|
||||
for k in kpis:
|
||||
# 取最新实际值
|
||||
|
||||
@@ -10,6 +10,9 @@ from app.deps import get_entity_id
|
||||
from app.models import KPIDefinition, KPIValue, KPIAlert, User, VoucherDetail
|
||||
from app.utils.cache import get as cache_get, set as cache_set
|
||||
from app.utils.voucher_guard import apply_voucher_guard
|
||||
# 指标方向(反向/正向)唯一权威源 = app.api.kpis.REVERSE_INDICATORS(2026-09-15 M2 准入2 收口)。
|
||||
# 本文件原自带一份字面量副本,与 kpis.py 漂移后会与「能力评分」判定相反,故改为导入。
|
||||
from app.api.kpis import REVERSE_INDICATORS
|
||||
import json
|
||||
import logging
|
||||
|
||||
@@ -619,12 +622,8 @@ def my_dashboard(
|
||||
target = kpi_target_by_frequency(k)
|
||||
level = "gray"
|
||||
if actual is not None and target:
|
||||
# 反向指标(越低越好):费用率/渠补率/应收天数/返利率/成本率/存货天数
|
||||
REVERSE_INDICATORS = {
|
||||
"F_COST_RATIO", "C_REBATE_RATE", "F_AR_DAYS",
|
||||
"F_REBATE_RATE", "F_FACTORY_REBATE_RATE", "F_COST_CONTROL_RATE",
|
||||
"F_INV_DAYS", "F_DEBT_RATIO", "P_BUG_RATE", "P_REWORK_PCT",
|
||||
}
|
||||
# 反向指标(越低越好)集合 = 单一权威源 app.api.kpis.REVERSE_INDICATORS
|
||||
# (2026-09-15 M2 准入2:删本文件原字面量副本,避免与能力评分引擎方向漂移)
|
||||
if k.kpi_code in REVERSE_INDICATORS:
|
||||
# 反向:实际≤目标=绿;实际≤目标*1.1=黄;否则红
|
||||
level = "green" if actual <= target else (
|
||||
|
||||
+13
-1
@@ -111,9 +111,21 @@ def get_kpi_categories(current_user = Depends(require_auth), db: Session = Depen
|
||||
# KPI-5: 五档评分引擎(静态路由必须在动态/{kpi_id}之前)
|
||||
# ============================================================
|
||||
|
||||
# ── 反向指标(值越低越好)· 单一事实源(single source of truth) ──
|
||||
# 本表是「指标方向」的唯一权威定义(2026-09-15 M2 准入2 收口):凡按方向判级别/评分的代码
|
||||
# 一律引用本表,禁止再复制字面量副本。
|
||||
# - app/api/dashboard.py「工作台三色」原自带一份副本 → 已改为 from app.api.kpis import
|
||||
# - app/api/bot_kpis.py 原 import 本表却未使用 → 已改为派生自本表
|
||||
# 判定语义:在内 = 越低越好(实际/目标 ≤0.5 → 5 分);不在内 = 越高越好(比值 ≥1.2 → 5 分)
|
||||
# 方向口径注意(两处「返补/返利」现金流方向相反,禁止误合并):
|
||||
# - C_REBATE_RATE / F_REBATE_RATE = 渠道返补(对外付出,越低越好 → 反向,留在本表)
|
||||
# - F_FACTORY_REBATE_RATE = 上游厂补率(厂补(捐赠收益)/主营成本,收到越多越好 → 正向,不属本表)
|
||||
# 2026-09-15 修正:原被误列入本表 → 现网 278.7%(target_value=80)被判 1 分"失效";
|
||||
# 与其三色阈值文本(green>=100=1.25×target / yellow>=80=target / red<80,越高越好)方向相反。
|
||||
# P-6 定稿 = 改方向(阈值文本保持不动),修正后同一实测值判 5 分。
|
||||
REVERSE_INDICATORS = ['C_REBATE_RATE', 'P_BUG_RATE', 'P_REWORK_PCT', 'F_DEBT_RATIO',
|
||||
'F_COST_RATIO', 'F_AR_DAYS', 'F_REBATE_RATE',
|
||||
'F_FACTORY_REBATE_RATE', 'F_COST_CONTROL_RATE', 'F_INV_DAYS']
|
||||
'F_COST_CONTROL_RATE', 'F_INV_DAYS']
|
||||
|
||||
|
||||
def _static_threshold_level(value, kpi) -> str:
|
||||
|
||||
Reference in New Issue
Block a user