fix(alerts): cash_plan 到期未收款预警引擎修复 — entity归属/KPI实体感知/余额快照批次/去重刷新/端点鉴权 (dama-cashplan-alert-engine-fix-20260913)
F1 两处 KPIAlert 显式写 entity_id(列默认 1 → 博海预警错挂酣客);顺带修 deviation_engine/ alert_generator/deviation_push/bot_bridge/bot_bridge_v2 同表创建点 F2 KPI 选择实体感知:候选码 ∪ 实体前缀后缀码(_AR_BALANCE/_CASH_BALANCE/_AP_BALANCE) + 兜底 ORDER BY id(此前命中 uk_entity_kpi 必中 BH_ADM_EXPENSE 437 管理费用) F3 去重命中改为刷新 alert_message/等级/suggestion.days_late/归属(此前 continue → 文本冻结首版) F4 余额快照批次(bohai_*_20260630 / receivables_migrate)开关:默认 skip 不逐户,另备 aggregate(按批次聚合1条) / per_customer(旧行为) F5 POST /api/cma/admin/alerts/check 补鉴权(无 token 401)+ 可选 entity_id 只跑指定账套
This commit is contained in:
+36
-6
@@ -1,10 +1,12 @@
|
||||
"""管理会计OS — 主入口"""
|
||||
import logging
|
||||
from fastapi import FastAPI, Request, Depends
|
||||
from typing import Optional
|
||||
from fastapi import FastAPI, Request, Depends, HTTPException
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.responses import JSONResponse
|
||||
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
||||
from dotenv import load_dotenv
|
||||
from app.database import init_db
|
||||
from app.database import init_db, get_db
|
||||
from app.api import auth, kpis, kpi_governance, templates, maps, dashboard, data, alerts, ai_analysis, ai_suggestions, alert_rules, users, thresholds, notifications, permissions, action_plans, alignment, org, objectives, versions, budget, cost, predict, reports, security, knowledge, bot_bridge, bot_bridge_v2, bot_suggestions, lead, tenant, customer_dashboard, deviation_push, budget_generate, knowledge_articles, kpi_causality, data_quality, bi_reports, entities, bsc_layers, okr, okr_templates, subjects, driver_budget, bot_kpis, ontology, bot_iron_law, analysis_results, expenses, cash, tax_compliance, verify, growth_quality, products, data_classification, value_sources, zero_based, derivation_rules, cash_classify, cashflow_structure, cash_vouchers_json
|
||||
from app.utils.cache import clear_all as clear_cache, delete as delete_cache
|
||||
from scripts.erp_sync import run_sync as run_erp_sync
|
||||
@@ -114,6 +116,22 @@ _ERP_CHANNEL_DISABLED_REASON = ("ERP直连同步通道已于2026-08-31停用(e
|
||||
"财务原始数据真实通道为 zxt 智享通注入(source_type='zxt-sync'),本端点不再可用。")
|
||||
|
||||
|
||||
# ── admin 端点鉴权(2026-09-13)──────────────────────────────
|
||||
# 未带 token → 显式 401(缺少认证),校验逻辑仍完全委托 require_auth(无效 token → 401)。
|
||||
# 说明:FastAPI 的 HTTPBearer(auto_error=True) 对"缺 header"返回 403;本端点验收要求 401,
|
||||
# 故用 auto_error=False 的实例自行判空,不改动全局 require_auth(避免其他端点行为漂移)。
|
||||
_optional_bearer = HTTPBearer(auto_error=False)
|
||||
|
||||
|
||||
def require_auth_401(
|
||||
credentials: Optional[HTTPAuthorizationCredentials] = Depends(_optional_bearer),
|
||||
db=Depends(get_db),
|
||||
):
|
||||
if credentials is None or not credentials.credentials:
|
||||
raise HTTPException(status_code=401, detail="未认证:缺少 Bearer token")
|
||||
return require_auth(credentials=credentials, db=db)
|
||||
|
||||
|
||||
@app.post("/api/cma/admin/erp-sync")
|
||||
def admin_erp_sync(user=Depends(require_auth), kpi_codes: str = None):
|
||||
"""[已停用] 手动触发ERP数据同步 — ERP 直连通道 2026-08-31 停用,返回 410"""
|
||||
@@ -127,8 +145,12 @@ def admin_erp_sync_dry_run(user=Depends(require_auth), kpi_codes: str = None):
|
||||
|
||||
|
||||
@app.post("/api/cma/admin/alerts/check")
|
||||
def admin_check_alerts():
|
||||
"""手动触发预警检查(含资金管理预警:缺口前3天 + 到期未收款)"""
|
||||
def admin_check_alerts(entity_id: Optional[int] = None, user=Depends(require_auth_401)):
|
||||
"""手动触发预警检查(含资金管理预警:缺口前3天 + 到期未收款)
|
||||
- 2026-09-13 安全修复:补鉴权(与同文件 /admin/erp-sync 等 admin 端点一致);
|
||||
未带 token 显式返回 401(require_auth_401,语义修正:401=未认证 / 403=无权)
|
||||
- 新增可选 entity_id:只跑指定实体(不传=全部 active 实体,兼容原行为)
|
||||
"""
|
||||
from app.database import get_session_local
|
||||
from scripts.alert_generator import generate_and_push
|
||||
from app.utils.cash_forecast_engine import check_cash_alerts
|
||||
@@ -136,10 +158,18 @@ def admin_check_alerts():
|
||||
db = get_session_local()()
|
||||
try:
|
||||
result = generate_and_push(db)
|
||||
# 资金管理预警 — 对每个激活企业执行
|
||||
# 资金管理预警 — 指定实体或全部激活企业
|
||||
cash_result = None
|
||||
try:
|
||||
entities = db.query(Entity).filter(Entity.status == "active").all()
|
||||
if entity_id is not None:
|
||||
target = db.query(Entity).filter(
|
||||
Entity.id == entity_id, Entity.status == "active").first()
|
||||
if not target:
|
||||
return JSONResponse(status_code=404,
|
||||
content={"detail": f"企业不存在或未激活: entity_id={entity_id}"})
|
||||
entities = [target]
|
||||
else:
|
||||
entities = db.query(Entity).filter(Entity.status == "active").all()
|
||||
cash_list = []
|
||||
for e in entities:
|
||||
cash_list.append(check_cash_alerts(db, entity_id=e.id))
|
||||
|
||||
Reference in New Issue
Block a user