- Introduced `convert_meta_api` endpoint to fetch the latest NAV date for conversion processes, restricted to users with the "risk_officer" role. - Updated `created_at` field in `AgentMessage` to use UTC timezone for consistency in timestamp handling. - Added `get_max_product_nav_date` method in `CoreReadOnlyRepository` to support the new API functionality. - Enhanced Milvus template loading in `MilvusTemplateVectorStore` to ensure collections are loaded when they exist. This update improves the API's capability to handle conversion metadata and ensures accurate timestamp management across the application.
6.6 KiB
6.6 KiB
顾问前端 + 风控转换线 + 风控前端 端到端验收 · 设计
- 日期:2026-09-12
- 分支:
merger@c09b987 - 性质:验证轮。不改任何业务代码,产出可复现的通过矩阵与缺陷清单。
- 报告:
docs/memory/tests/2026-09-12-agent-frontend-e2e/TEST-LOG-2026-09-12-FE-001.md - 计划:
docs/superpowers/plans/2026-09-12-agent-frontend-e2e.md
1. 为什么要做这一轮
前三件事各自独立地把「上一轮的结论」推翻了:
| # | 事实 | 后果 |
|---|---|---|
| 1 | 顾问前端四页(合规 / 话术模板 / KYC / 市场异动)已就绪,但从未在真实浏览器里点过 | 前两轮都是 API-only,页面渲染、交互、默认值完全没覆盖 |
| 2 | 03fce88 把「基金转换 T+1」整条线并入 merger(110 文件,仅后端),c09b987 补上前端页 + 迁移 |
新功能从未做过端到端,前后端契约未对账 |
| 3 | 第一轮顾问报告写于 03fce88 之前,结论「D1/D2 未修 ⇒ 不建议合入」在当前 HEAD 上已不成立 |
旧报告失真,必须重跑改写 |
2. 范围
做
- A · 顾问前端:
/app/advisor/{home,compliance,templates,kyc,market-alerts}逐页点按 - B · 风控转换线:
POST /api/simulate/trade(convert) ·GET /api/simulate/trade/convert/{id}·.../cancel·POST /api/admin/convert/confirm,外加风控四端点 RBAC - C · 风控前端:
/app/risk/{home,alerts,suitability,aml-scan,simulate,convert}逐页点按
不做(明示)
- 两个 SSE 对话页(
/app/advisor/chat、/app/risk/chat)—— 依赖实时 LLM,不确定性强,标 SKIP 并写理由 app/service/agent_tools.py/agent_graph.py—— 经agent_graph.py:158引用但无任何 HTTP 路由可达,产生 0 个用例;只记录已知签名错配(D4)- 性能 / 响应式 / 可访问性专项
- 既有
test_sprint*红项(属 fixture 基建,另一条线)
3. 方法:两条独立跑道
Part A / C · 浏览器跑道 Part B · API 跑道
────────────────────────── ──────────────────────
Chromium (channel:'chrome') httpx.Client
↓ http://localhost:5173 ↓ http://127.0.0.1:8000
Vite dev server (proxy /api) uvicorn app.main:app
↓ ↓
└─────── 同一套 MySQL + Redis + Milvus + DeepSeek ───────┘
浏览器跑道必须走 Vite(5173),不能直连 8000:app/ 没有 CORS 中间件;且前端 sha256Hex 走 WebCrypto,需要安全上下文。
两条跑道同因同果才叫验证成立 —— 若浏览器侧失败而 API 侧同名用例通过,说明前端调用与文档契约有分歧,须单独成条。
3.1 关键设计决策
| 决策 | 理由 |
|---|---|
| 先跑 Part B,再跑 Part C | Part C 的转换页需要 B 造出的 convert_request / risk_alert 数据;反过来会空跑 |
| 断言后端与断言渲染必须拆成两条用例 | 例:模拟交易的 alert_ids,后端正确返回而页面渲染错误。合成一条会把渲染缺陷误记成接口缺陷(本轮 B5.1/B5.2 即此拆分) |
用轮询等真实行,不用固定 waitForTimeout 冒充空表判定 |
固定等待会把「还没加载出来」误判成「确实是空表」 |
切角色前清 localStorage |
不清则 #/login 会重定向回上个角色首页,后续用例全跑在错误身份上 |
| 登录用例带一次「去掉 reload 兜底」的回归 | reload 会掩盖登录崩溃回归(BUG-1);不能默认带着跑 |
| 已确认正确的行为要写成正反对照 | 例:复制门闸拒绝 BLOCK 内容是门闸生效,不是缺陷;只写负例容易把正确行为记成 FAIL |
3.2 环境前置自检(防假失败)
本轮开工时曾抓到 merge 前的旧 uvicorn 进程(PID 27348 启动于 16:55:24,早于代码落地 17:52–17:59)。若未重启,全部转换用例会假失败。
因此跑测前必须:/openapi.json 含 /api/admin/convert/confirm 等转换路径;/health 返回 {"status":"ok"}。
4. 契约口径(本轮实测固化,易误判)
| 场景 | 正确期望 | 常见误判 |
|---|---|---|
| 合法 convert 受理 | HTTP 202 + convert_group_id + status='accepted' |
误期 200 |
| 幂等重放 | 也是 202,同 convert_group_id,idempotent=true(首跑 false) |
误期 409 |
| 适当性阻断 | 200 + blocked=true |
误期 202 |
| 未确认单的字段 | 不得含 out_nav / convert_amount / in_qty / nav_date |
—— |
accept_date 格式非法 |
422 REQUEST_VALIDATION_FAILED(FastAPI 查询校验,pre-handler) |
误期 400 |
| 撤单顺序 | 必须在 confirm_batch 之前 —— 确认把单推进 nav_pending,而 nav_pending 不可撤(409 CANCEL_NOT_ALLOWED) |
先确认再撤 |
POST /api/simulate/trade 响应 |
裸 body,不套 {code,message,data,trace_id} 外壳;前端需 j?.data ?? j |
按统一外壳取 data |
X-Agent-Type |
JWT 通道下 /api/chat* 与 /api/risk/* 必填;缺失 401 / 域外值 400 / 跨域 403 |
—— |
| 基金转换业务约束 | 同销售机构 + 同管理人 + 同 TA;违约 400 CROSS_ENTITY_NOT_SUPPORTED |
—— |
5. 交付物
| 产物 | 位置 |
|---|---|
| 主报告(12 节模板) | docs/memory/tests/2026-09-12-agent-frontend-e2e/TEST-LOG-2026-09-12-FE-001.md |
| 包索引 | 同目录 README.md |
| 机器可读矩阵 | 同目录 _raw/{advisor-api,risk-api}.md |
| 风控 API 冒烟(64 用例) | scripts/dev/risk_e2e_smoke.py(仓库内) |
| 顾问 API 冒烟(63 用例) | scripts/dev/advisor_e2e_smoke.py(复用不改) |
| 浏览器 E2E(47 用例) | C:/Users/Windows/e2e-jinrong/{09,10,11}-*.mjs(仓库外) |
| 顾问报告 v1.1 | docs/memory/tests/2026-09-12-advisor-agent-e2e/TEST-LOG-2026-09-12-ADV-001.md |
6. 已知取舍
- 浏览器脚本在仓库外 —— 为不改
web/package.json而刻意如此。代价:他人 clone 拿不到这三支脚本,复现性有缺口。已挂docs/memory/TODO.md的「E2E 最小集进仓库」P0。 - 测试写脏开发库 —— 每轮新增
core_trade/convert_request/risk_alert/audit_log行,默认保留取证数据。转换用例会占用CUST-9527的PROD-110022可用份额,重跑前若耗尽需重灌。 - 不执行任何 DROP 重建 —— 不跑
prepare_all.ps1/reset.ps1,避免误删双库。