Files
ccdi/docs/design/2026-03-24-credit-info-direct-storage-design.md

254 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 征信维护直接入库改造设计文档
## 1. 背景
现有征信维护功能按员工维度设计:
- 上传时要求征信对象身份证号必须存在于 `ccdi_base_staff`
- 页面列表从 `ccdi_base_staff` 出发聚合,只展示员工本人
- 查询区保留了“柜员号”“是否已维护”两个员工口径字段
当前需求调整为:
- 征信维护页面移除“是否已维护”
- 导入时不需要关联柜员或亲属,解析后直接入库
- 页面允许展示导入的柜员亲属征信文件
- 页面不再展示“柜员号”
本次改造的核心是把“员工征信维护”收敛为“征信对象维护”。
## 2. 已确认约束
- 导入时不关联柜员,也不关联亲属
- 解析出征信对象后直接入库
- 页面按征信对象本人维度展示,一行一条征信对象记录
- 柜员亲属征信文件导入后需要单独展示
- 查询区移除“是否已维护”
- 列表移除“柜员号”
- 保持最短路径实现,不新增征信主表,不拆新页面
- 仍然只保留同一证件号的最新征信数据
## 3. 目标
- 将征信维护页从员工口径调整为征信对象口径
- 让任意征信对象在解析成功后都可以直接落库
- 保留现有上传、详情、删除的基本交互
- 保持现有两张征信业务表结构与覆盖写入模式
## 4. 非目标
- 不新增柜员与亲属归属映射字段
- 不新增征信主表或上传历史表
- 不新增异步任务、补偿任务或兜底逻辑
- 不扩展多版本征信存储
## 5. 方案对比
### 5.1 方案 A页面和上传都彻底去员工化
- 上传时只校验文件合法性和解析结果完整性
- 解析成功后按征信对象本人证件号直接写入
- 页面直接从征信表聚合,不再依赖员工表
优点:
- 完全符合当前需求
- 前后端语义一致
- 实现路径最短
缺点:
- 页面不再补充员工属性
### 5.2 方案 B上传去员工化列表保留员工补充信息
- 上传时不校验员工存在
- 列表查询时若命中员工表则补柜员信息,否则为空
优点:
- 能部分保留旧页面字段
缺点:
- 同一页面内记录语义不一致
- 会继续引入“员工口径”和“征信对象口径”混用问题
### 5.3 方案 C新增征信对象主表
- 上传后先写征信对象主表,再关联两张明细表
优点:
- 后续扩展空间更大
缺点:
- 超出当前需求,属于过度设计
## 6. 最终方案
采用方案 A页面和上传都彻底去员工化。
选择原因:
- 直接满足“导入时不需要关联柜员或者亲属,直接入库”
- 直接满足“柜员亲属征信文件可独立展示”
- 不新增表,不改菜单结构,保持最短路径
- 能一次性消除“柜员号”“是否已维护”这类旧口径残留
## 7. 总体链路
改造后的链路如下:
`征信维护页面 -> 征信维护接口 -> 征信维护服务 -> 征信解析接口 -> 两张征信业务表`
职责定义:
- 页面负责上传文件、查询列表、查看详情、删除记录
- 接口负责暴露统一的上传、列表、详情、删除能力
- 服务负责解析结果校验、最新日期判断、覆盖写入
- 数据库继续仅使用 `ccdi_debts_info``ccdi_credit_negative_info`
## 8. 数据口径设计
### 8.1 主键口径
- 统一以解析结果中的 `query_cert_no` 作为征信对象唯一标识,即 `person_id`
- `query_cust_name` 作为征信对象姓名,即 `person_name`
- `report_time` 作为征信查询日期,即 `query_date`
### 8.2 入库口径
- 不校验 `person_id` 是否存在于 `ccdi_base_staff`
- 不校验 `person_id` 是否存在于 `ccdi_staff_fmy_relation`
- 只要解析结果具备完整主键字段,即可继续写入
### 8.3 列表口径
- 页面主列表按征信对象维度展示
- 每个 `person_id` 对应一条摘要记录
- 不再要求该征信对象属于员工或亲属数据域
## 9. 前端页面设计
### 9.1 查询区
保留:
- 姓名
- 身份证号
移除:
- 柜员号
- 是否已维护
### 9.2 列表区
保留字段:
- 姓名
- 身份证号
- 最近征信查询日期
- 负债笔数
- 负债总额
- 民事案件笔数
- 强制执行笔数
- 行政处罚笔数
- 操作
移除字段:
- 柜员号
### 9.3 详情与删除
- 详情继续按 `person_id` 展示征信摘要、负面信息、负债明细
- 删除继续按 `person_id` 删除该征信对象的全部征信数据
## 10. 后端改造设计
### 10.1 上传服务
现状:
- 上传时调用 `ensureStaffExists(personId)`,非员工身份证号会失败
改造后:
- 删除员工存在性校验
- 解析出 `personId/personName/queryDate` 后直接进入最新日期判断
- 通过后继续覆盖写入两张业务表
### 10.2 列表查询
现状:
- 查询 SQL 从 `ccdi_base_staff` 出发
- 强依赖员工表字段
改造后:
- 查询 SQL 直接从征信表聚合
-`ccdi_debts_info` 的聚合结果为主
- 结合 `ccdi_credit_negative_info` 的负面统计
-`person_id` 汇总一条摘要记录
- 支持姓名、身份证号筛选
- 不再接收或使用 `staffId``maintained`
### 10.3 DTO 与 VO
- `CcdiCreditInfoQueryDTO` 删除 `staffId`
- `CcdiCreditInfoQueryDTO` 删除 `maintained`
- 列表 VO 不再要求返回柜员号
## 11. 覆盖写入规则
系统继续只保留同一证件号下的最新征信数据:
- 若库中不存在当前 `person_id` 记录,直接写入
- 若新 `query_date` 大于等于库中最新 `query_date`,覆盖旧数据
- 若新 `query_date` 小于库中最新 `query_date`,当前文件失败
覆盖步骤保持不变:
1. 删除 `ccdi_debts_info` 中该 `person_id` 的旧记录
2. 删除 `ccdi_credit_negative_info` 中该 `person_id` 的旧记录
3. 插入新的负债明细
4. 插入新的负面信息
以上步骤在同一事务内完成。
## 12. 测试设计
### 12.1 前端测试
- 查询区不再包含“柜员号”
- 查询区不再包含“是否已维护”
- 列表列定义不再包含“柜员号”
- 页面仍支持姓名、身份证号检索
### 12.2 后端测试
- 非员工身份证号征信可以上传成功
- 查询 DTO 不再包含 `staffId``maintained`
- 列表 SQL 不再依赖 `ccdi_base_staff`
- 详情和删除对纯征信对象记录仍然生效
- 旧日期上传仍会失败
## 13. 实施边界
本次改造只覆盖征信维护功能现有页面与接口:
- 不调整菜单权限编码
- 不改造征信解析接口协议
- 不补录柜员或亲属关系字段
- 不新增历史数据迁移脚本
## 14. 后续动作
- 待用户审阅本设计文档后,输出两份实施计划:
- `docs/plans/backend/` 后端实施计划
- `docs/plans/frontend/` 前端实施计划