fix(kpi): 阈值红黄绿读写/填写规则修复 — 统一解析器+红灯优先+建议可解析+前端校验+存量修正 (project-20260911-threshold-fix)

① 新建 app/utils/threshold_parser.py 统一解析/判定(单一事实源):
   - 支持负数(>=-100000)、闭区间 A~B、多条件 C1|C2;空串=未设置
   - 判定顺序 red→green→yellow:红灯优先(消除宽黄灯遮蔽红灯),
     green 先于 yellow(green 是主条件,yellow 是更宽兜底带)
② kpis.py / alert_generator.py 双实现收敛到统一解析器(消除重复维护)
③ thresholds.py suggest 输出可解析表达式(原黄色/适中型生成 `52.33~107.67`、`偏离55%` 等
   区间/文字 → 用户点"自动建议"填入后静默失效;另修复大数目标生成 1.6e+06 科学计数法)
④ KPIDetail.vue 三个阈值输入加 placeholder/tooltip/帮助文案 + 保存前格式校验(非法即拒)
⑤ 存量 4 个不可解析表达式修正(id=46 C_REBATE_RATE / id=327 BH_SALES_10),
   改前 mysqldump 备份 backend/scripts/backups/kpi_definitions.bak-20260911.sql +
   threshold_rows_before_20260911.json(可回滚);不可解析 5→0
⑥ 单测 97 条 + 红黄绿判定回归 367 判定点(旧→新差异 14 条,含差异说明)
This commit is contained in:
Hermes CI Fix
2026-09-11 17:25:24 +08:00
parent f61b6ce604
commit 4c6fb85cf5
11 changed files with 1981 additions and 122 deletions
@@ -0,0 +1,751 @@
{
"samples": 367,
"count_old": {
"red": 120,
"yellow": 17,
"green": 46,
"info": 184
},
"count_new": {
"red": 126,
"yellow": 12,
"green": 54,
"info": 175
},
"diff_ab": [
{
"kpi_id": 6,
"kpi_code": "F_AR_DAYS",
"period": "2026-04",
"actual": 152.62,
"old": "yellow",
"new": "red",
"severity_order": "red",
"G": "<=76",
"Y": ">76",
"R": ">91"
},
{
"kpi_id": 6,
"kpi_code": "F_AR_DAYS",
"period": "2026-05",
"actual": 105.47,
"old": "yellow",
"new": "red",
"severity_order": "red",
"G": "<=76",
"Y": ">76",
"R": ">91"
},
{
"kpi_id": 6,
"kpi_code": "F_AR_DAYS",
"period": "2026-07",
"actual": 116.5,
"old": "yellow",
"new": "red",
"severity_order": "red",
"G": "<=76",
"Y": ">76",
"R": ">91"
},
{
"kpi_id": 6,
"kpi_code": "F_AR_DAYS",
"period": "2026-08",
"actual": 610.2,
"old": "yellow",
"new": "red",
"severity_order": "red",
"G": "<=76",
"Y": ">76",
"R": ">91"
},
{
"kpi_id": 46,
"kpi_code": "C_REBATE_RATE",
"period": "2026-01",
"actual": 124.1,
"old": "info",
"new": "red",
"severity_order": "red",
"G": "52.33~107.67",
"Y": "<52.33|>107.67",
"R": "<=36|>=124"
},
{
"kpi_id": 46,
"kpi_code": "C_REBATE_RATE",
"period": "2026-02",
"actual": 84.0,
"old": "info",
"new": "green",
"severity_order": "green",
"G": "52.33~107.67",
"Y": "<52.33|>107.67",
"R": "<=36|>=124"
},
{
"kpi_id": 46,
"kpi_code": "C_REBATE_RATE",
"period": "2026-03",
"actual": 69.6,
"old": "info",
"new": "green",
"severity_order": "green",
"G": "52.33~107.67",
"Y": "<52.33|>107.67",
"R": "<=36|>=124"
},
{
"kpi_id": 46,
"kpi_code": "C_REBATE_RATE",
"period": "2026-04",
"actual": 81.7,
"old": "info",
"new": "green",
"severity_order": "green",
"G": "52.33~107.67",
"Y": "<52.33|>107.67",
"R": "<=36|>=124"
},
{
"kpi_id": 46,
"kpi_code": "C_REBATE_RATE",
"period": "2026-05",
"actual": 88.3,
"old": "info",
"new": "green",
"severity_order": "green",
"G": "52.33~107.67",
"Y": "<52.33|>107.67",
"R": "<=36|>=124"
},
{
"kpi_id": 46,
"kpi_code": "C_REBATE_RATE",
"period": "2026-06",
"actual": 52.8,
"old": "info",
"new": "green",
"severity_order": "green",
"G": "52.33~107.67",
"Y": "<52.33|>107.67",
"R": "<=36|>=124"
},
{
"kpi_id": 46,
"kpi_code": "C_REBATE_RATE",
"period": "2026-07",
"actual": 68.7,
"old": "info",
"new": "green",
"severity_order": "green",
"G": "52.33~107.67",
"Y": "<52.33|>107.67",
"R": "<=36|>=124"
},
{
"kpi_id": 46,
"kpi_code": "C_REBATE_RATE",
"period": "2026-08",
"actual": 75.0,
"old": "info",
"new": "green",
"severity_order": "green",
"G": "52.33~107.67",
"Y": "<52.33|>107.67",
"R": "<=36|>=124"
},
{
"kpi_id": 46,
"kpi_code": "C_REBATE_RATE",
"period": "2026-H1",
"actual": 86.4,
"old": "info",
"new": "green",
"severity_order": "green",
"G": "52.33~107.67",
"Y": "<52.33|>107.67",
"R": "<=36|>=124"
},
{
"kpi_id": 407,
"kpi_code": "F_REBATE_RATE",
"period": "2026-08",
"actual": 48.44,
"old": "yellow",
"new": "red",
"severity_order": "red",
"G": "<=10",
"Y": ">10",
"R": ">12"
}
],
"diff_bc": [
{
"kpi_id": 3,
"kpi_code": "F_NET_PROFIT",
"period": "2026-01",
"actual": 94.31,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=30",
"Y": ">=20",
"R": "<10"
},
{
"kpi_id": 4,
"kpi_code": "F_OP_CFLOW",
"period": "2026-01",
"actual": 65.2173,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=20",
"Y": ">=0",
"R": "<0"
},
{
"kpi_id": 4,
"kpi_code": "F_OP_CFLOW",
"period": "2026-02",
"actual": 78.4307,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=20",
"Y": ">=0",
"R": "<0"
},
{
"kpi_id": 4,
"kpi_code": "F_OP_CFLOW",
"period": "2026-04",
"actual": 124.422,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=20",
"Y": ">=0",
"R": "<0"
},
{
"kpi_id": 4,
"kpi_code": "F_OP_CFLOW",
"period": "2026-06",
"actual": 43.4998,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=20",
"Y": ">=0",
"R": "<0"
},
{
"kpi_id": 5,
"kpi_code": "F_COST_RATIO",
"period": "2026-01",
"actual": 15.8,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": "<=25",
"Y": "<=30",
"R": ">30"
},
{
"kpi_id": 5,
"kpi_code": "F_COST_RATIO",
"period": "2026-02",
"actual": 18.85,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": "<=25",
"Y": "<=30",
"R": ">30"
},
{
"kpi_id": 5,
"kpi_code": "F_COST_RATIO",
"period": "2026-06",
"actual": 24.8,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": "<=25",
"Y": "<=30",
"R": ">30"
},
{
"kpi_id": 5,
"kpi_code": "F_COST_RATIO",
"period": "2026-H1",
"actual": 24.9,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": "<=25",
"Y": "<=30",
"R": ">30"
},
{
"kpi_id": 8,
"kpi_code": "C_NEW_CLIENTS",
"period": "2026-07",
"actual": 88.8,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=10",
"Y": ">=5",
"R": "<5"
},
{
"kpi_id": 14,
"kpi_code": "F_REVENUE_GROWTH",
"period": "2026-05",
"actual": 48.91,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=20",
"Y": ">=15",
"R": "<15"
},
{
"kpi_id": 14,
"kpi_code": "F_REVENUE_GROWTH",
"period": "2026-06",
"actual": 43.54,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=20",
"Y": ">=15",
"R": "<15"
},
{
"kpi_id": 30,
"kpi_code": "F_DEBT_RATIO",
"period": "2026-01",
"actual": 37.01,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": "<50",
"Y": "<70",
"R": ">=70"
},
{
"kpi_id": 30,
"kpi_code": "F_DEBT_RATIO",
"period": "2026-02",
"actual": 38.33,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": "<50",
"Y": "<70",
"R": ">=70"
},
{
"kpi_id": 30,
"kpi_code": "F_DEBT_RATIO",
"period": "2026-04",
"actual": 42.02,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": "<50",
"Y": "<70",
"R": ">=70"
},
{
"kpi_id": 30,
"kpi_code": "F_DEBT_RATIO",
"period": "2026-05",
"actual": 41.49,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": "<50",
"Y": "<70",
"R": ">=70"
},
{
"kpi_id": 30,
"kpi_code": "F_DEBT_RATIO",
"period": "2026-06",
"actual": 39.0,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": "<50",
"Y": "<70",
"R": ">=70"
},
{
"kpi_id": 30,
"kpi_code": "F_DEBT_RATIO",
"period": "2026-07",
"actual": 38.8,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": "<50",
"Y": "<70",
"R": ">=70"
},
{
"kpi_id": 30,
"kpi_code": "F_DEBT_RATIO",
"period": "2026-08",
"actual": 39.9,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": "<50",
"Y": "<70",
"R": ">=70"
},
{
"kpi_id": 184,
"kpi_code": "FB_ANALYSIS_COUNT",
"period": "2026-07",
"actual": 18.0,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=12",
"Y": ">=8",
"R": "<4"
},
{
"kpi_id": 318,
"kpi_code": "BH_SALES_1",
"period": "2026-H1",
"actual": 754562.0,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=754562",
"Y": ">=603649",
"R": "<452737"
},
{
"kpi_id": 319,
"kpi_code": "BH_SALES_2",
"period": "2026-H1",
"actual": 579205.0,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=579205",
"Y": ">=463364",
"R": "<347523"
},
{
"kpi_id": 320,
"kpi_code": "BH_SALES_3",
"period": "2026-H1",
"actual": 209038.0,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=209038",
"Y": ">=167230",
"R": "<125422"
},
{
"kpi_id": 321,
"kpi_code": "BH_SALES_4",
"period": "2026-H1",
"actual": 285990.0,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=285990",
"Y": ">=228792",
"R": "<171594"
},
{
"kpi_id": 322,
"kpi_code": "BH_SALES_5",
"period": "2026-H1",
"actual": 372816.0,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=372816",
"Y": ">=298253",
"R": "<223690"
},
{
"kpi_id": 323,
"kpi_code": "BH_SALES_6",
"period": "2026-H1",
"actual": 229512.0,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=229512",
"Y": ">=183610",
"R": "<137707"
},
{
"kpi_id": 324,
"kpi_code": "BH_SALES_7",
"period": "2026-H1",
"actual": 35173.0,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=35173",
"Y": ">=28138",
"R": "<21104"
},
{
"kpi_id": 325,
"kpi_code": "BH_SALES_8",
"period": "2026-H1",
"actual": 2327.0,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=2327",
"Y": ">=1862",
"R": "<1396"
},
{
"kpi_id": 326,
"kpi_code": "BH_SALES_9",
"period": "2026-01",
"actual": 625983.0,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=1785",
"Y": ">=1428",
"R": "<1071"
},
{
"kpi_id": 326,
"kpi_code": "BH_SALES_9",
"period": "2026-02",
"actual": 253099.0,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=1785",
"Y": ">=1428",
"R": "<1071"
},
{
"kpi_id": 326,
"kpi_code": "BH_SALES_9",
"period": "2026-03",
"actual": 526357.0,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=1785",
"Y": ">=1428",
"R": "<1071"
},
{
"kpi_id": 326,
"kpi_code": "BH_SALES_9",
"period": "2026-H1",
"actual": 1785.0,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=1785",
"Y": ">=1428",
"R": "<1071"
},
{
"kpi_id": 327,
"kpi_code": "BH_SALES_10",
"period": "2026-02",
"actual": 1486.73,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=200",
"Y": ">=160",
"R": "<120"
},
{
"kpi_id": 327,
"kpi_code": "BH_SALES_10",
"period": "2026-03",
"actual": 2991.15,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=200",
"Y": ">=160",
"R": "<120"
},
{
"kpi_id": 327,
"kpi_code": "BH_SALES_10",
"period": "2026-H1",
"actual": 4180.0,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=200",
"Y": ">=160",
"R": "<120"
},
{
"kpi_id": 408,
"kpi_code": "F_FACTORY_REBATE_RATE",
"period": "2022",
"actual": 103.4,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=100",
"Y": ">=80",
"R": "<80"
},
{
"kpi_id": 408,
"kpi_code": "F_FACTORY_REBATE_RATE",
"period": "2025",
"actual": 107.6,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=100",
"Y": ">=80",
"R": "<80"
},
{
"kpi_id": 408,
"kpi_code": "F_FACTORY_REBATE_RATE",
"period": "2026-01",
"actual": 201.8,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=100",
"Y": ">=80",
"R": "<80"
},
{
"kpi_id": 408,
"kpi_code": "F_FACTORY_REBATE_RATE",
"period": "2026-04",
"actual": 120.5,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=100",
"Y": ">=80",
"R": "<80"
},
{
"kpi_id": 408,
"kpi_code": "F_FACTORY_REBATE_RATE",
"period": "2026-05",
"actual": 110.8,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=100",
"Y": ">=80",
"R": "<80"
},
{
"kpi_id": 408,
"kpi_code": "F_FACTORY_REBATE_RATE",
"period": "2026-08",
"actual": 278.7,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=100",
"Y": ">=80",
"R": "<80"
},
{
"kpi_id": 408,
"kpi_code": "F_FACTORY_REBATE_RATE",
"period": "2026-H1",
"actual": 106.8,
"old": "green",
"new": "green",
"severity_order": "yellow",
"G": ">=100",
"Y": ">=80",
"R": "<80"
}
],
"alert_only_old": [
[
6,
"2026-04",
"yellow"
],
[
6,
"2026-05",
"yellow"
],
[
6,
"2026-07",
"yellow"
],
[
6,
"2026-08",
"yellow"
],
[
407,
"2026-08",
"yellow"
]
],
"alert_only_new": [
[
6,
"2026-04",
"red"
],
[
6,
"2026-05",
"red"
],
[
6,
"2026-07",
"red"
],
[
6,
"2026-08",
"red"
],
[
46,
"2026-01",
"red"
],
[
407,
"2026-08",
"red"
]
],
"alert_gen_dry_run_new": 0
}
@@ -0,0 +1,32 @@
{
"created_at": "2026-09-11T17:11:24.159913",
"rows": [
{
"id": 46,
"kpi_code": "C_REBATE_RATE",
"kpi_name": "渠补率",
"target_value": 80.0,
"threshold_green": "52.33~107.67",
"threshold_yellow": "偏离55%",
"threshold_red": "偏离>55%"
},
{
"id": 327,
"kpi_code": "BH_SALES_10",
"kpi_name": "销售-任富海",
"target_value": 200.0,
"threshold_green": "",
"threshold_yellow": "偏离182878%",
"threshold_red": "偏离>182878%"
},
{
"id": 32,
"kpi_code": "F_EVA",
"kpi_name": "经济增加值(EVA)",
"target_value": 0.0,
"threshold_green": ">=0",
"threshold_yellow": ">=-100000",
"threshold_red": "<-100000"
}
]
}