init: 管理会计OS初始代码
包含前后端完整代码: - 前端:Vue3+Vite+ElementPlus - 后端:FastAPI+SQLAlchemy - 模块:驾驶舱/KPI/战略地图/预警/预算/成本/预测/改善行动 - 当前版本:v1.0.0
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
"""预警规则配置"""
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.orm import Session
|
||||
from app.database import get_db
|
||||
from app.auth_middleware import require_auth, require_role
|
||||
from app.models import KPIAlert, KPIDefinition, KPIValue
|
||||
|
||||
router = APIRouter(prefix="/api/cma/alert-rules", tags=["预警规则"],
|
||||
dependencies=[Depends(require_role("ceo", "finance"))],
|
||||
)
|
||||
|
||||
@router.get("")
|
||||
def list_rules(kpi_id: int = None, db: Session = Depends(get_db)):
|
||||
"""获取预警规则(从KPI定义中读取阈值配置)"""
|
||||
query = db.query(KPIDefinition).filter(KPIDefinition.status == "active")
|
||||
if kpi_id:
|
||||
query = query.filter(KPIDefinition.id == kpi_id)
|
||||
rules = []
|
||||
for k in query.all():
|
||||
if k.threshold_green or k.threshold_yellow or k.threshold_red:
|
||||
rules.append({
|
||||
"kpi_id": k.id,
|
||||
"kpi_name": k.kpi_name,
|
||||
"threshold_green": k.threshold_green,
|
||||
"threshold_yellow": k.threshold_yellow,
|
||||
"threshold_red": k.threshold_red,
|
||||
})
|
||||
return {"data": rules}
|
||||
|
||||
@router.post("/check/{kpi_id}")
|
||||
def check_alert(kpi_id: int, db: Session = Depends(get_db)):
|
||||
"""检查指定KPI是否需要触发预警"""
|
||||
kpi = db.query(KPIDefinition).filter(KPIDefinition.id == kpi_id).first()
|
||||
if not kpi:
|
||||
raise HTTPException(404, "KPI不存在")
|
||||
|
||||
latest = db.query(KPIValue).filter(KPIValue.kpi_id == kpi_id).order_by(KPIValue.period.desc()).first()
|
||||
if not latest or not latest.actual_value:
|
||||
return {"alert": False, "message": "无数据"}
|
||||
|
||||
val = latest.actual_value
|
||||
level = "green"
|
||||
|
||||
# 简单阈值判定
|
||||
red = kpi.threshold_red
|
||||
yellow = kpi.threshold_yellow
|
||||
|
||||
# 红灯判断: <3000000 表示低于300万触发红灯
|
||||
if red:
|
||||
if "<" in red:
|
||||
limit = float(red.split("<")[1].strip())
|
||||
if val < limit: level = "red"
|
||||
elif ">" in red:
|
||||
limit = float(red.split(">")[1].strip())
|
||||
if val > limit: level = "red"
|
||||
|
||||
# 黄灯判断(红灯未触发时)
|
||||
if level == "green" and yellow:
|
||||
if "<" in yellow:
|
||||
limit = float(yellow.split("<")[1].strip())
|
||||
if val < limit: level = "yellow"
|
||||
elif ">" in yellow:
|
||||
limit = float(yellow.split(">")[1].strip())
|
||||
if val > limit: level = "yellow"
|
||||
|
||||
if level != "green":
|
||||
alert = KPIAlert(
|
||||
kpi_id=kpi_id, kpi_value_id=latest.id,
|
||||
alert_level=level,
|
||||
alert_message=f"{kpi.kpi_name}当前值为{val},触发{level}预警",
|
||||
)
|
||||
db.add(alert)
|
||||
db.commit()
|
||||
return {"alert": True, "level": level, "message": alert.alert_message}
|
||||
|
||||
return {"alert": False, "level": "green", "message": "正常"}
|
||||
Reference in New Issue
Block a user