259 lines
8.0 KiB
Markdown
259 lines
8.0 KiB
Markdown
|
|
# LSFX Mock LogId 主体账号绑定设计
|
||
|
|
|
||
|
|
## 背景
|
||
|
|
|
||
|
|
当前 `lsfx-mock-server` 的上传文件接口已经会为文件记录生成 `enterpriseNameList` 和 `accountNoList`,但银行流水查询接口 `getBSByLogId` 仍然在 `StatementService` 内独立随机或写死 `leName`、`accountMaskNo`。这导致同一个 `logId` 在不同接口里看到的“本方主体/本方账号”并不统一。
|
||
|
|
|
||
|
|
新增需求要求:
|
||
|
|
|
||
|
|
- 每次上传流水文件时,随机生成银行流水的本方主体和本方账号。
|
||
|
|
- 一个本方主体对应一个本方账号。
|
||
|
|
- 一个 `logId` 对应一组固定的本方主体和本方账号。
|
||
|
|
- 同样的逻辑也覆盖“拉取本行信息”链路产生的 `logId`。
|
||
|
|
|
||
|
|
## 目标
|
||
|
|
|
||
|
|
- 为每个新生成的 `logId` 绑定一组随机本方主体和本方账号。
|
||
|
|
- 上传文件、上传状态、银行流水查询三类接口对同一 `logId` 返回一致的主体账号信息。
|
||
|
|
- 保持现有接口出参结构兼容,不引入前端契约变更。
|
||
|
|
|
||
|
|
## 范围
|
||
|
|
|
||
|
|
### In Scope
|
||
|
|
|
||
|
|
- `lsfx-mock-server/services/file_service.py`
|
||
|
|
- `lsfx-mock-server/services/statement_service.py`
|
||
|
|
- 上传文件链路的 `logId` 绑定生成
|
||
|
|
- 拉取本行信息链路的 `logId` 绑定生成
|
||
|
|
- 对应测试和实施记录
|
||
|
|
|
||
|
|
### Out of Scope
|
||
|
|
|
||
|
|
- 前端页面或后端 Java 工程改造
|
||
|
|
- 一个 `logId` 下支持多个本方主体/账号
|
||
|
|
- 跨 `logId` 复用同一主体账号映射
|
||
|
|
|
||
|
|
## 设计原则
|
||
|
|
|
||
|
|
- 一个 `logId` = 一个本方主体 + 一个本方账号
|
||
|
|
- 同一个 `logId` 的所有流水记录都使用同一组 `leName/accountMaskNo`
|
||
|
|
- 外部响应兼容当前数组格式,但内部语义收敛为单值绑定
|
||
|
|
- 主体账号由 `FileService` 统一生成,`StatementService` 只消费,不再自行决定
|
||
|
|
|
||
|
|
## 现状问题
|
||
|
|
|
||
|
|
### 上传文件链路
|
||
|
|
|
||
|
|
`FileService.upload_file()` 在创建 `FileRecord` 时会随机生成:
|
||
|
|
|
||
|
|
- `account_no_list`
|
||
|
|
- `enterprise_name_list`
|
||
|
|
|
||
|
|
但它们只服务于上传接口和解析状态接口。
|
||
|
|
|
||
|
|
### 拉取本行信息链路
|
||
|
|
|
||
|
|
`FileService.fetch_inner_flow()` 目前仅返回随机 `logId`,不会创建 `FileRecord`,因此后续没有主体账号上下文可以复用。
|
||
|
|
|
||
|
|
### 流水查询链路
|
||
|
|
|
||
|
|
`StatementService._generate_random_statement()` 当前独立写死或随机:
|
||
|
|
|
||
|
|
- `accountMaskNo`
|
||
|
|
- `leName`
|
||
|
|
|
||
|
|
它不知道上传或拉取本行信息时已经生成了什么主体账号。
|
||
|
|
|
||
|
|
## 方案概览
|
||
|
|
|
||
|
|
将“本方主体/本方账号”的主数据收敛到 `FileService` 维护的 `FileRecord` 中,并让所有基于 `logId` 的接口围绕同一份绑定工作:
|
||
|
|
|
||
|
|
1. `FileService` 在生成新 `logId` 时,创建并保存一组主体账号绑定。
|
||
|
|
2. `upload_file()` 和 `fetch_inner_flow()` 都走这套绑定生成逻辑。
|
||
|
|
3. `StatementService` 根据 `logId` 读取绑定值,填入流水的 `leName/accountMaskNo`。
|
||
|
|
4. 对外仍然返回:
|
||
|
|
- `enterpriseNameList: [name]`
|
||
|
|
- `accountNoList: [account]`
|
||
|
|
5. 删除记录时,若 `logId` 绑定被删除,后续兼容逻辑生成的新记录也必须保持接口间自洽。
|
||
|
|
|
||
|
|
## 数据模型设计
|
||
|
|
|
||
|
|
## FileRecord 扩展
|
||
|
|
|
||
|
|
建议在现有 `FileRecord` 上明确单值语义字段:
|
||
|
|
|
||
|
|
- `primary_enterprise_name: str`
|
||
|
|
- `primary_account_no: str`
|
||
|
|
|
||
|
|
同时保留兼容字段:
|
||
|
|
|
||
|
|
- `enterprise_name_list`
|
||
|
|
- `account_no_list`
|
||
|
|
|
||
|
|
约束为:
|
||
|
|
|
||
|
|
- `enterprise_name_list == [primary_enterprise_name]`
|
||
|
|
- `account_no_list == [primary_account_no]`
|
||
|
|
|
||
|
|
这样既不破坏当前响应格式,也让内部逻辑不再把主体和账号当成可变长集合。
|
||
|
|
|
||
|
|
## 主体账号生成策略
|
||
|
|
|
||
|
|
新增统一生成方法,例如:
|
||
|
|
|
||
|
|
- `_generate_primary_account_binding()`
|
||
|
|
|
||
|
|
职责:
|
||
|
|
|
||
|
|
- 随机选取一个本方主体名称
|
||
|
|
- 随机生成一个本方账号
|
||
|
|
- 返回单一绑定对象
|
||
|
|
|
||
|
|
建议主体名称从固定 Mock 名称池中随机选择,例如:
|
||
|
|
|
||
|
|
- `测试主体A`
|
||
|
|
- `测试主体B`
|
||
|
|
- `测试主体C`
|
||
|
|
- `兰溪测试主体一部`
|
||
|
|
- `兰溪测试主体二部`
|
||
|
|
|
||
|
|
账号生成规则保持简单:
|
||
|
|
|
||
|
|
- 生成合法长度的纯数字字符串
|
||
|
|
- 作为单个 `logId` 的专属账号使用
|
||
|
|
|
||
|
|
本次不要求“同一主体跨所有 `logId` 始终映射同一账号”,只要求:
|
||
|
|
|
||
|
|
- 对单个 `logId` 而言,主体与账号是一对一且稳定的
|
||
|
|
|
||
|
|
## 接口联动设计
|
||
|
|
|
||
|
|
### 1. 上传文件接口
|
||
|
|
|
||
|
|
`upload_file()` 在创建 `FileRecord` 时:
|
||
|
|
|
||
|
|
- 生成 `logId`
|
||
|
|
- 生成主体账号绑定
|
||
|
|
- 回填:
|
||
|
|
- `primary_enterprise_name`
|
||
|
|
- `primary_account_no`
|
||
|
|
- `enterprise_name_list`
|
||
|
|
- `account_no_list`
|
||
|
|
|
||
|
|
上传响应里的:
|
||
|
|
|
||
|
|
- `accountsOfLog[*].accountName`
|
||
|
|
- `accountsOfLog[*].accountNo`
|
||
|
|
- `uploadLogList[*].enterpriseNameList`
|
||
|
|
- `uploadLogList[*].accountNoList`
|
||
|
|
|
||
|
|
都来自这组绑定。
|
||
|
|
|
||
|
|
### 2. 拉取本行信息接口
|
||
|
|
|
||
|
|
`fetch_inner_flow()` 不能再只返回裸 `logId`,需要同时:
|
||
|
|
|
||
|
|
- 生成新 `logId`
|
||
|
|
- 创建 `FileRecord`
|
||
|
|
- 生成主体账号绑定并落入 `self.file_records`
|
||
|
|
|
||
|
|
这样同一个 `logId` 后续再查上传状态或银行流水时,能拿到一致的本方主体和账号。
|
||
|
|
|
||
|
|
### 3. 上传状态接口
|
||
|
|
|
||
|
|
`check_parse_status()` 和 `get_upload_status()` 对已存在的 `FileRecord`,统一返回其中的绑定数据。
|
||
|
|
|
||
|
|
若 `get_upload_status()` 走兼容分支按 `logId` 现场生成记录,生成出的主体账号也必须写成单一绑定,并在该次响应内部保持自洽。
|
||
|
|
|
||
|
|
### 4. 银行流水查询接口
|
||
|
|
|
||
|
|
`StatementService` 不再自己决定:
|
||
|
|
|
||
|
|
- `leName`
|
||
|
|
- `accountMaskNo`
|
||
|
|
|
||
|
|
而是通过 `logId` 获取对应绑定:
|
||
|
|
|
||
|
|
- `leName = primary_enterprise_name`
|
||
|
|
- `accountMaskNo = primary_account_no`
|
||
|
|
|
||
|
|
同一 `logId` 下生成的所有流水记录都使用这一组值。
|
||
|
|
|
||
|
|
## 组件边界
|
||
|
|
|
||
|
|
### FileService
|
||
|
|
|
||
|
|
负责:
|
||
|
|
|
||
|
|
- 生成 `logId`
|
||
|
|
- 生成并保存主体账号绑定
|
||
|
|
- 对上传/拉取本行信息/上传状态返回统一绑定值
|
||
|
|
|
||
|
|
### StatementService
|
||
|
|
|
||
|
|
负责:
|
||
|
|
|
||
|
|
- 读取 `logId` 对应主体账号绑定
|
||
|
|
- 将绑定值注入每条流水记录
|
||
|
|
- 不再自行随机本方主体或本方账号
|
||
|
|
|
||
|
|
为避免重复造一份状态,`StatementService` 需要拿到查询绑定的方法或共享 `file_records` 访问能力,但不负责写绑定。
|
||
|
|
|
||
|
|
## 错误处理
|
||
|
|
|
||
|
|
- 若 `logId` 没有对应绑定记录,允许走兼容生成逻辑,但必须在当前响应范围内自洽。
|
||
|
|
- 不允许同一次 `getBSByLogId` 返回中出现多个本方主体或多个本方账号。
|
||
|
|
- 不允许上传响应和流水响应对同一 `logId` 返回不同主体账号。
|
||
|
|
|
||
|
|
## 测试设计
|
||
|
|
|
||
|
|
至少补 3 类测试:
|
||
|
|
|
||
|
|
### 1. 上传文件链路测试
|
||
|
|
|
||
|
|
验证上传接口返回中:
|
||
|
|
|
||
|
|
- `accountsOfLog` 的 `accountName/accountNo`
|
||
|
|
- `uploadLogList` 的 `enterpriseNameList/accountNoList`
|
||
|
|
|
||
|
|
三者一致,且数组长度为 `1`。
|
||
|
|
|
||
|
|
### 2. 拉取本行信息链路测试
|
||
|
|
|
||
|
|
验证 `fetch_inner_flow()` 返回 `logId` 后:
|
||
|
|
|
||
|
|
- `FileService` 内已存在对应 `FileRecord`
|
||
|
|
- 该记录带有主体账号绑定
|
||
|
|
- 后续查询上传状态或银行流水时能看到相同绑定
|
||
|
|
|
||
|
|
### 3. 银行流水链路测试
|
||
|
|
|
||
|
|
验证同一 `logId` 下:
|
||
|
|
|
||
|
|
- 第一页和第二页流水里的 `leName/accountMaskNo` 一致
|
||
|
|
- 重复查询结果中的本方主体账号不漂移
|
||
|
|
- 流水里的 `leName/accountMaskNo` 与 `FileRecord` 中的绑定完全一致
|
||
|
|
|
||
|
|
## 成功标准
|
||
|
|
|
||
|
|
- 上传文件和拉取本行信息产生的新 `logId` 都会绑定一组随机本方主体与账号。
|
||
|
|
- 同一 `logId` 的上传响应、上传状态、银行流水查询三处返回一致的主体账号。
|
||
|
|
- 同一 `logId` 的所有流水记录只出现一个 `leName` 和一个 `accountMaskNo`。
|
||
|
|
- 对外接口结构不变,前端无需因这次改动调整解析逻辑。
|
||
|
|
|
||
|
|
## 风险与约束
|
||
|
|
|
||
|
|
- 现有 `get_upload_status()` 存在按 `logId` 即时生成确定性记录的兼容路径,这部分要特别注意与 `file_records` 中真实记录的优先级。
|
||
|
|
- 若后续一个 `logId` 需要支持多个本方账号,本次设计需要重做,因为当前明确锁定为“一对一”。
|
||
|
|
- `StatementService` 新增对 `FileService` 绑定数据的依赖后,需要避免双向循环依赖,优先通过轻量查询函数或共享只读访问注入。
|
||
|
|
|
||
|
|
## 实施输出
|
||
|
|
|
||
|
|
实施阶段应至少产出:
|
||
|
|
|
||
|
|
- Mock 服务代码改动
|
||
|
|
- 对应 pytest 测试
|
||
|
|
- 一份后端实施计划
|
||
|
|
- 一份前端实施计划
|
||
|
|
- 一份实施记录文档
|