fix(alerts): enforce caliber rulings R1-R4 for alert generation
R1: exclude status=demo entities from alert traversal (alert_generator / deviation_engine / kpi_bep_deriver / alert_rules / cash engine) R2: only generate alerts within the last 6 calendar months (incl. current) R3: only regular month periods (YYYY-MM) participate R4: decouple generation from push - empty notification_channels never blocks Single source of truth: app/utils/alert_entity_scope.py
This commit is contained in:
@@ -14,6 +14,10 @@ from typing import Optional
|
||||
|
||||
from app.database import get_session_local
|
||||
from app.models import KPIDefinition, KPIValue, KPIAlert, BudgetPlan, SystemConfig
|
||||
# 裁定 R1/R2/R3(2026-09-19 财务口径):demo 账套排除 / 期间窗口 / 规整月期间
|
||||
from app.utils.alert_entity_scope import (
|
||||
excluded_entity_ids, kpi_excluded, period_in_window, window_lower_period,
|
||||
)
|
||||
|
||||
logger = logging.getLogger("cma.deviation")
|
||||
|
||||
@@ -311,16 +315,31 @@ def build_deviation_alert(db, kpi, period: str, entity_id: int = 1, min_rate: fl
|
||||
|
||||
|
||||
def run_deviation_check(db_session, period: str = None) -> int:
|
||||
"""运行差异预警检查,返回新增预警数(统一走 build_deviation_alert,P2-⑤)"""
|
||||
"""运行差异预警检查,返回新增预警数(统一走 build_deviation_alert,P2-⑤)
|
||||
|
||||
2026-09-19 财务口径裁定 R1/R2/R3(`alert_entity_scope`):
|
||||
· R1 —— `status='demo'` 的账套不参与遍历(demo 仅演示,不产生业务预警);
|
||||
· R2/R3 —— 期间须为规整月 `YYYY-MM` 且落在窗口(当月往前 6 个自然月,含当月)内。
|
||||
"""
|
||||
if period is None:
|
||||
period = datetime.now().strftime("%Y-%m")
|
||||
if not period_in_window(period):
|
||||
logger.warning(" 差异预警跳过(R2/R3): 期间 %s 非规整月或早于窗口下限 %s",
|
||||
period, window_lower_period())
|
||||
return 0
|
||||
|
||||
excluded = excluded_entity_ids(db_session)
|
||||
kpis = db_session.query(KPIDefinition).filter(
|
||||
KPIDefinition.status == "active"
|
||||
).all()
|
||||
|
||||
new_count = 0
|
||||
skipped_demo = 0
|
||||
for kpi in kpis:
|
||||
# R1(裁定 2026-09-19):demo 演示账套不参与预警遍历
|
||||
if kpi_excluded(db_session, kpi, excluded):
|
||||
skipped_demo += 1
|
||||
continue
|
||||
# 1. 差异预警:实际 vs 预算(统一逻辑)
|
||||
result = build_deviation_alert(db_session, kpi, period)
|
||||
if result["triggered"]:
|
||||
@@ -375,6 +394,8 @@ def run_deviation_check(db_session, period: str = None) -> int:
|
||||
new_count += 1
|
||||
logger.info(f" 新增趋势预警 [{trend['level']}] {trend_alert_msg}")
|
||||
|
||||
if skipped_demo:
|
||||
logger.info(" 差异预警跳过 demo 账套 KPI %s 项(R1,裁定 2026-09-19)", skipped_demo)
|
||||
db_session.commit()
|
||||
return new_count
|
||||
|
||||
|
||||
Reference in New Issue
Block a user