feat(api): 实现代销平台 API v0.1,包括客户、产品、理财师、合规及员工接口

- 新增多个 API 路由:`/api/customers`, `/api/products`, `/api/advisors`, `/api/compliance`, `/api/staff`,支持客户信息、产品详情、理财师客户列表、合规判定及员工上下文查询。
- 引入平台服务层,封装核心只读操作,支持数据脱敏功能。
- 更新依赖注入,确保各 API 路由的权限控制与数据访问一致性。
- 添加相应的单元测试,确保新接口的功能完整性与稳定性。

此更新为代销平台提供了基础的 REST API 支持,增强了系统的可扩展性与可维护性。
This commit is contained in:
2026-09-08 21:01:07 +08:00
parent f0bce1270b
commit ef56c56435
25 changed files with 940 additions and 15 deletions
+1
View File
@@ -16,3 +16,4 @@
| 2026-09-08 | **前端接入方案 B/C**:chat 拉侧三端点 `8328c24` · SSE 流式 `01ec5fc` · 503→502 测试基线 | 前端联调前置 | MEMORY / TODO / chat / session_repository / agent_service |
| 2026-09-08 | **AL-09 合并接线完成**(`merger` 分支):JWT 统一 · 模块 chat/agent/memory 恢复 · auth_adapter S2 接缝 · trace 中间件 ApiError re-raise · test_module_boundary 绿 · **502 passed 1 skipped** | 风控模块并入宿主 Wave 0 | MEMORY / TODO / FRAMEWORK / FLOW / REQUIREMENTS / ENVIRONMENT / 合并注意事项 |
| 2026-09-08 | **代销平台 API 口径拍板**:路由 A(业务域)· 重复功能以平台 API 为准 · 《接口契约-代销平台API-v0.1》 | 统筹 P1 实现前定契约 | 04 / MEMORY / TODO / 接口契约 |
| 2026-09-08 | **代销平台 API v0.1 落地**:MVC 分层 api→service/platform→core_ro · 17 端点测试 · 519 pytest 绿 | v0.1 实现约定 | 接口契约 / 04 / ITERATION |
+1 -1
View File
@@ -9,7 +9,7 @@
## 待办(统筹 · P1 推荐顺序)
- [ ] **代销平台 API v0.1 实现**(契约:`docs/项目框架设计/接口契约-代销平台API-v0.1.md` — customers/products/advisors/compliance/staff + 补 `list_products` RO)
- [x] **代销平台 API v0.1 实现**(2026-09-08):`customers/products/advisors/staff/compliance` + `service/platform/` + `PLATFORM_RESPONSE_DESENSITIZE` · **519 passed 1 skipped**
- [ ] **接口契约发群**(login + 平台读 API + simulate/trade;强调重复功能以平台路径为准)
- [ ] 前端 React 多 Agent 入口(HashRouter,`web/` init)
- [ ] 同步 `MEMORY/REQUIREMENTS/FRAMEWORK` 与各 Agent 负责人联调节奏
@@ -1,6 +1,6 @@
# 接口契约 · 代销平台 API v0.1
> 状态:**已定口径(2026-09-08)** · 实现进行中
> 状态:**v0.1 已实现(2026-09-08)** · 519 pytest 绿
> 范围:**未接 Agent 前的 Core 代销平台 REST**(客户 App / 理财师工作台 / 内勤只读)
> 关联:[04-从需求到公共API开发方法.md](../项目管理/04-从需求到公共API开发方法.md) · [02-JWT-RBAC鉴权手册.md](./技术选型和版本/02-JWT-RBAC鉴权手册.md)
@@ -62,13 +62,38 @@
- 失败:手册 §10 结构(`ApiError`);403 归属/角色、404 资源不存在。
- 列表:`{ "items": [...], "total": n, "limit": ..., "offset": ... }`(与 chat sessions 对齐)。
### 2.4 Service / 代码包(实现侧)
**脱敏(2026-09-08 拍板):**
| 层 | 约定 |
| --- | --- |
| 路由 | `app/api/customers.py` `products.py` `advisors.py` `compliance.py` |
| 平台 Service | `app/service/platform/` 封装 `core_ro`,REST 与日后 Agent 适配 **共用一个 Service** |
| Repository | 仍只 `core_ro.py` SELECT;缺方法先补 RO 再暴露 API |
| 项 | v0.1 | 真库阶段 |
| --- | --- | --- |
| 开关 | `settings.platform_response_desensitize`(env:`PLATFORM_RESPONSE_DESENSITIZE`,**默认 `false`**) | 生产/真 Core 切 `true` |
| 行为 | **关闭**:L0 字段原样返回(模拟库联调) | **开启**:出参经 `app/utils/desensitize.py`(姓名/手机/证件/银行卡;`customer_id` 不脱敏) |
| 实现位置 | **Platform Service 层**统一处理(REST 与日后 Agent 适配共用同一出口) | 同上 |
### 2.4 Service / 代码包(实现侧 · 分层说明)
代销平台采用 **三层**,避免「REST 里写 SQL」或「Agent 合并时再抄一遍查数逻辑」:
```text
HTTP 请求
↓
app/api/customers.py 等 ← 薄路由:鉴权、参数校验、ok() 包装、HTTP 状态码
↓
app/service/platform/*.py ← Platform Service:归属无关的业务组装、脱敏开关、分页口径
↓
app/repository/core_ro.py ← 只读 SQL,不感知 HTTP/Agent
```
| 层 | 职责 | 谁调用 |
| --- | --- | --- |
| **api/** | FastAPI 路由;`Depends(get_platform_auth_context)`;调 Service | 前端、Postman |
| **service/platform/** | 封装 `core_ro`;统一脱敏、列表分页、字段映射 | **REST 只调这一层**;合并 Agent 时也调这一层(或同进程 import) |
| **repository/core_ro** | `SELECT` Core 模拟库 | 仅 Service / 风控等特殊路径 |
> **「REST 只调 Service」** = `customers.py` 里不出现 `CoreReadOnlyRepository()` 直调,而是 `platform_service.get_customer_l0(...)`。这样 Agent Tool 日后改调 Service 时,与 App 仪表盘 **同一套逻辑**,不会两套口径。
路由文件:`app/api/customers.py` `products.py` `advisors.py` `compliance.py` `staff.py`
Service 文件:`app/service/platform/customer_service.py` `product_service.py` …(按域拆分,可合并为一个 `platform_service.py` 若保持简单)
---
@@ -108,14 +133,25 @@
---
## 5. 归属规则摘要(G-01)
## 5. 归属规则摘要(G-01 · 平台 API)
| 角色 | 读 customer 维度数据 |
> **2026-09-08 统筹拍板:** 各角色权限不同;平台读接口 **不要求** `X-Agent-Type`(实现侧用 `get_platform_auth_context`)。
| 角色 | 读 `customers/{id}` 及子资源 |
| --- | --- |
| `customer` | 仅 `auth.customer_id == customer_id` |
| `advisor` | `customer_advisor_rel` active 归属 |
| `risk_officer` / 演示 | 全量(只读) |
| 其他 staff | 403 + audit |
| `advisor` | 仅 `core_customer_advisor` active 归属名下客户 |
| `analyst` | **全量只读**(支撑 D-01 内勤查数) |
| `risk_officer` | 全量只读(与现有 G-01 一致) |
| `risk_manager` | v0.1 **全量只读**(与台账只读定位一致;无写接口) |
| `risk_demo` | **全量只读**(与 risk_officer 一致,支撑 simulate/演示联调) |
| `compliance` / 其他 staff | **403**(客户 L0 不在其业务范围) |
**产品/净值**(`/api/products*`):任意已登录 staff 或 customer 可读(公开产品事实,无客户归属语义)。
**理财师客户列表**(`/api/advisors/{advisor_id}/customers`):`advisor` 仅 `advisor_id == auth.actor_id`;`analyst` / `risk_officer` / `risk_manager` 可查任意 advisor。
**`/api/staff/me`:** 仅 `token_type=staff`;customer token → 403。
---
@@ -124,3 +160,5 @@
| 日期 | 说明 |
| --- | --- |
| 2026-09-08 | v0.1 口径:路由 A · 平台 API 优先 · 命名规范 · 端点清单 · 迁移表 |
| 2026-09-08 | 实现前拍板:整包交付 · 适当性新旧并存 · analyst 全量只读 · 平台 JWT 免 X-Agent-Type |
| 2026-09-08 | 脱敏:`PLATFORM_RESPONSE_DESENSITIZE` 默认 false;真库再开 · risk_demo 全量只读 |
@@ -59,6 +59,7 @@
| Agent 隔离 | 四 Agent **不互调 LLM**;跨 Agent 走画像表与预警表 |
| 审计 | `audit_log` 等 **只 INSERT** |
| 合规 | 不代客交易、不营销式推荐、代理人草稿不自动外发 |
| 平台出参脱敏 | `PLATFORM_RESPONSE_DESENSITIZE`(默认 **关**);v0.1 模拟库原样返回;接真 Core 再开(Service 层统一出口) |
### 门闸 B · Wave / P0 裁剪