| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- # -*- coding: utf-8 -*-
- """P4-16 扩展:通知模板 / 通知渠道配置 冒烟验证(DB 侧)。
- 仅做结构与种子数据可用性检查,不依赖前后端 HTTP 联调:
- - T1:ApprovalFlowNotifyTemplate / ApprovalFlowNotifyConfig 两表存在,列齐。
- - T2:后端启动过至少一次后,系统预置模板应至少 9 条(NewTask / Urge / FlowCompleted / Transferred / Returned / AddSign / Withdrawn / Escalated / Timeout 的全局默认)。
- - T3:通知配置菜单 SysMenu Id=1310300010106 存在且已授权(RoleMenu + TenantMenu 有记录)。
- - T4:渲染兜底:模拟 BizType 级覆盖缺失,应能退回全局模板(通过 Python 端模拟 SELECT)。
- 使用方法:
- python _verify_notify_tpl_cfg.py
- 若 T2 失败(模板 0 条),说明后端尚未启动过(InitTables + EnsureSystemTemplates 未执行)。
- """
- from __future__ import annotations
- import pymysql
- import sys
- CONN_ARGS = dict(
- host='123.60.180.165', port=3306,
- user='aidopremote', password='1234567890aiDOP#',
- database='aidopdev', charset='utf8mb4', autocommit=True,
- )
- EXPECTED_TYPES = {"NewTask", "Urge", "FlowCompleted", "Transferred", "Returned", "AddSign", "Withdrawn", "Escalated", "Timeout"}
- def ok(name: str, cond: bool, detail: str = "") -> bool:
- flag = "PASS" if cond else "FAIL"
- print(f"[{flag}] {name}" + (f" - {detail}" if detail else ""))
- return cond
- def main() -> int:
- conn = pymysql.connect(**CONN_ARGS)
- passed = 0
- total = 0
- try:
- with conn.cursor(pymysql.cursors.DictCursor) as cur:
- # T1 表结构
- for t, expected_cols in [
- ("ApprovalFlowNotifyTemplate", {"NotifyType", "BizType", "Title", "Content", "IsEnabled", "IsSystem"}),
- ("ApprovalFlowNotifyConfig", {"ChannelKey", "Enabled", "WebhookUrl", "Secret", "TemplateId", "Remark"}),
- ]:
- total += 1
- cur.execute(f"SHOW TABLES LIKE '{t}'")
- has_tbl = bool(cur.fetchall())
- if not has_tbl:
- ok(f"T1 表 {t} 存在", False, "表不存在")
- continue
- cur.execute(f"DESC `{t}`")
- cols = {r["Field"] for r in cur.fetchall()}
- miss = expected_cols - cols
- if ok(f"T1 表 {t} 结构", not miss, f"缺字段: {miss}" if miss else f"列 {len(cols)} 个"):
- passed += 1
- # T2 默认模板种子
- total += 1
- cur.execute(
- "SELECT NotifyType, COUNT(*) AS n FROM ApprovalFlowNotifyTemplate "
- "WHERE BizType='' AND IsSystem=1 GROUP BY NotifyType"
- )
- rows = cur.fetchall()
- seed_types = {r["NotifyType"] for r in rows}
- miss = EXPECTED_TYPES - seed_types
- if ok(
- "T2 系统预置模板(全局)覆盖 9 类通知",
- not miss,
- f"缺: {miss}" if miss else f"已预置 {len(seed_types)} 类({len(rows)} 行)",
- ):
- passed += 1
- # T3 通知配置菜单
- total += 1
- cur.execute("SELECT Id, Title, Path FROM SysMenu WHERE Id=1310300010106")
- m = cur.fetchone()
- cur.execute("SELECT COUNT(*) AS n FROM SysRoleMenu WHERE MenuId=1310300010106")
- r = cur.fetchone()["n"]
- cur.execute("SELECT COUNT(*) AS n FROM SysTenantMenu WHERE MenuId=1310300010106")
- t_cnt = cur.fetchone()["n"]
- cond = bool(m) and r > 0 and t_cnt > 0
- detail = f"menu={bool(m)} RoleMenu={r} TenantMenu={t_cnt}"
- if ok("T3 通知配置菜单已挂载 + 授权", cond, detail):
- passed += 1
- # T4 渲染兜底(BizType 级不存在时回退全局)
- total += 1
- biz = "__VERIFY_NOT_EXIST_BIZ__"
- cur.execute(
- "SELECT Id FROM ApprovalFlowNotifyTemplate WHERE NotifyType='NewTask' AND BizType=%s",
- (biz,),
- )
- biz_hit = cur.fetchone()
- cur.execute(
- "SELECT Id FROM ApprovalFlowNotifyTemplate WHERE NotifyType='NewTask' AND BizType='' AND IsEnabled=1 LIMIT 1"
- )
- global_hit = cur.fetchone()
- fallback_ok = biz_hit is None and global_hit is not None
- if ok("T4 BizType 级缺失时可回退全局", fallback_ok):
- passed += 1
- print("\n==============================")
- print(f"结果:{passed}/{total} 通过")
- return 0 if passed == total else 1
- finally:
- conn.close()
- if __name__ == "__main__":
- sys.exit(main())
|