fix(kpi): suggest 保留历史默认口径 middle_best — 修复未知编码被误判为 higher_better(C_REBATE_RATE/BH_SALES_10 建议退化) (project-20260911-threshold-fix)

This commit is contained in:
Hermes CI Fix
2026-09-11 17:27:12 +08:00
parent 4c6fb85cf5
commit e22093256b
2 changed files with 40 additions and 4 deletions
+12 -4
View File
@@ -94,11 +94,19 @@ def suggest_by_type(kpi):
def _kpi_type(kpi) -> str:
if kpi.kpi_code in KPI_TYPES["lower_better"]:
"""KPI → 推荐类型(**保持历史默认语义**)。
原实现为 if higher_better / elif lower_better / **else → middle_best**,
即「不在任何清单里的编码」默认走适中型(如 C_REBATE_RATE 渠补率、
BH_SALES_10 销售-任富海,其历史生成的 '52.33~107.67' / '偏离…%' 即出自该分支)。
此处默认值必须同为 middle_best,否则默认分支的推荐口径会被改变。
"""
code = getattr(kpi, "kpi_code", None)
if code in KPI_TYPES["higher_better"]:
return "higher_better"
if code in KPI_TYPES["lower_better"]:
return "lower_better"
if kpi.kpi_code in KPI_TYPES["middle_best"]:
return "middle_best"
return "higher_better"
return "middle_best"
def _sanity_check(suggestion: dict) -> dict:
+28
View File
@@ -185,6 +185,34 @@ class TestSuggestFormat:
for level in ("green", "yellow", "red"):
assert is_valid_threshold(s2[level]["label"]), s2[level]["label"]
def test_kpi_type_default_preserves_legacy_middle_best(self):
"""_kpi_type 默认分支必须保持历史语义 = middle_best(原实现的 else 分支)。"""
from app.api.thresholds import _kpi_type
class K:
def __init__(self, code):
self.kpi_code = code
assert _kpi_type(K("SALES_TOTAL")) == "higher_better"
assert _kpi_type(K("COST_CONTROL_RATE")) == "lower_better"
assert _kpi_type(K("C_REBATE_RATE")) == "middle_best" # 渠补率:历史为适中型
assert _kpi_type(K("BH_SALES_10")) == "middle_best" # 销售-任富海:历史为适中型
assert _kpi_type(K("MADE_UP_CODE")) == "middle_best" # 未知编码 → 默认适中型
def test_c_rebate_rate_suggestion_is_middle_best_range(self):
"""回归:C_REBATE_RATE 建议仍走适中型区间口径(不得退化为更高的单边界)。"""
from app.api.thresholds import _kpi_type, build_suggestion
class K:
kpi_code = "C_REBATE_RATE"
t = _kpi_type(K())
s = build_suggestion(t, 80.0, tolerance=27.67)
assert t == "middle_best"
assert s["green"]["label"] == "52.33~107.67"
assert is_valid_threshold(s["yellow"]["label"])
assert is_valid_threshold(s["red"]["label"])
def test_middle_best_zero_tolerance_guard(self):
"""容忍度退化时不得生成 A~A 之类不可用表达式"""
s = build_suggestion("middle_best", 0.0, tolerance=0.0)