fix(cma): 工作台跨实体污染治本 — 全局键拆账套 + 缺列收口 + 预警归属兜底
任务 dama-workbench-entity-isolation-fullstack-20260922(DAMA 诊断 / 项目Bot batch5 §B / 任总 2026-09-22「都批」) B1 现金基线拆账套(零 DDL) - cash_forecast_engine: 键 cash.current_balance → cash.current_balance.<entity_id>; 读只读本账套键、不做旧键回退;set_* 签名 entity_id 必传(漏传 TypeError) - cash.py: POST /balance 挂 get_entity_id;网银流水联动写回带账套 B3(a) alignment_config 拆账套(零 DDL) - alignment.py: GET/POST /config、GET /tree 只读 alignment_config.<entity_id>;未配置=configured:false B3(b) 预警 KPI 归属兜底 - bot_bridge_v2: 去掉 kpi_id or 1 兜底;本账套无 KPI 定义 → 跳过建预警 + OperationLog 留痕 (kpi_alerts.kpi_id NOT NULL ⇒ 方案A 置 NULL 不可行,走方案B 跳过+审计) B2 缺列五表分表处置 - notification_logs: 经 alert_id → kpi_alerts.entity_id join 归属(无父键行不返回) - notification_channels / okr_templates: 集团共享口径写入 docstring(有意不过滤) - system_configs: 由 B1/B3(a) 拆键覆盖;kpi_data_quality_logs 沿用 batch5 的 join 收口 P0 语义收敛 - tenant.py: current_tenant 收敛为项目Bot A2A 状态记录,GET 仅 it/ceo;POST 补 operation_logs 审计 证据:新增/改写用例 22 条;全量 1370 passed(基线 1348)
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from sqlalchemy.orm import Session
|
||||
from tests.conftest import create_test_user, get_token_for_user, auth_header
|
||||
from tests.conftest import create_test_user, create_test_kpi, get_token_for_user, auth_header
|
||||
|
||||
|
||||
class TestNotificationChannels:
|
||||
@@ -149,16 +149,32 @@ class TestNotificationLogs:
|
||||
assert resp.json()["total"] == 0
|
||||
|
||||
def test_logs_with_data(self, client: TestClient, db: Session):
|
||||
"""有了日志记录后可查询"""
|
||||
from app.models import NotificationLog
|
||||
"""有了日志记录后可查询
|
||||
|
||||
2026-09-22(dama-workbench-entity-isolation-fullstack-20260922 §四 B2)行为变更:
|
||||
`notification_logs` 无 entity_id 列 → 改为**经父键 join 归属**
|
||||
(`alert_id → kpi_alerts.id → kpi_alerts.entity_id`)。
|
||||
故日志必须挂到**本账套真实存在**的 KPIAlert 上才可见;
|
||||
`alert_id IS NULL` 或指向不存在父键的孤儿行**不返回**(宁少勿错)。
|
||||
"""
|
||||
from app.models import NotificationLog, KPIAlert
|
||||
from datetime import datetime
|
||||
|
||||
# 直接插入日志
|
||||
log = NotificationLog(
|
||||
alert_id=1, channel="wecom", recipient="测试群",
|
||||
title="测试通知", content="测试内容", status="sent", sent_at=datetime.now(),
|
||||
)
|
||||
db.add(log)
|
||||
kpi = create_test_kpi(db, kpi_code="NOTIF_LOG_KPI", entity_id=1)
|
||||
alert = KPIAlert(entity_id=1, kpi_id=kpi.id, alert_level="yellow",
|
||||
alert_message="通知日志用例预警", status="pending")
|
||||
db.add(alert)
|
||||
db.commit()
|
||||
db.refresh(alert)
|
||||
|
||||
db.add_all([
|
||||
NotificationLog(
|
||||
alert_id=alert.id, channel="wecom", recipient="测试群",
|
||||
title="测试通知", content="测试内容", status="sent", sent_at=datetime.now(),
|
||||
),
|
||||
# 孤儿行:无父键可归属 → 一律不返回
|
||||
NotificationLog(alert_id=None, channel="wecom", title="无归属通知", status="sent"),
|
||||
])
|
||||
db.commit()
|
||||
|
||||
create_test_user(db)
|
||||
@@ -166,8 +182,9 @@ class TestNotificationLogs:
|
||||
|
||||
resp = client.get("/api/cma/notifications/logs", headers=auth_header(token))
|
||||
assert resp.status_code == 200
|
||||
assert resp.json()["total"] >= 1
|
||||
assert len(resp.json()["data"]) >= 1
|
||||
assert resp.json()["total"] == 1, resp.json()
|
||||
assert len(resp.json()["data"]) == 1
|
||||
assert resp.json()["data"][0]["title"] == "测试通知"
|
||||
|
||||
|
||||
class TestAlertPush:
|
||||
|
||||
Reference in New Issue
Block a user