463 lines
13 KiB
Markdown
463 lines
13 KiB
Markdown
# 征信维护设计文档
|
||
|
||
## 1. 背景
|
||
|
||
当前仓库已经具备两项征信解析基础能力:
|
||
|
||
- `ccdi-lsfx` 已提供 `POST /lsfx/credit/parse` 征信解析联调接口,可接收 HTML 并返回 `lx_header`、`lx_debt`、`lx_publictype`
|
||
- `lsfx-mock-server` 已支持从征信 HTML 中解析员工姓名和身份证号,能够稳定返回本地联调 payload
|
||
|
||
本次需求是在“信息维护”菜单下新增“征信维护”菜单,支持批量导入员工征信 HTML 文件并提交上传。系统需要调用现有征信解析接口完成数据解析,并把返回结果批量落库。页面同时要展示当前已维护的员工征信信息,并支持删除现有征信数据。
|
||
|
||
## 2. 已确认约束
|
||
|
||
- 菜单挂在“信息维护”下,页面为独立菜单,不挂到员工维护弹窗内
|
||
- 页面主列表按员工维度展示摘要,一行一个员工
|
||
- 批量上传按员工维度原子化处理,一个员工失败不影响其他员工
|
||
- 负债明细表名固定为 `ccdi_debts_info`
|
||
- 负债信息按照 `assets/征信解析/ccdi_debts_info.xlsx` 设计
|
||
- 负面信息按照接口字段单独设计一张表
|
||
- 每个员工只保留最新的征信信息
|
||
- 列表操作列支持删除现有征信信息
|
||
- 不新增征信主表,主列表通过明细表实时聚合
|
||
|
||
## 3. 目标
|
||
|
||
- 在“信息维护”下新增“征信维护”菜单与页面
|
||
- 支持一次上传多个 `.html/.htm` 征信文件
|
||
- 上传后逐文件调用征信解析接口
|
||
- 按员工身份证号归户,并按“最新征信优先”规则覆盖写入
|
||
- 在页面展示员工维度的征信摘要列表
|
||
- 在详情中展示负债明细和负面信息
|
||
- 支持按员工删除当前已维护的征信数据
|
||
|
||
## 4. 非目标
|
||
|
||
- 不改造现有 `POST /lsfx/credit/parse` 的协议语义
|
||
- 不新增异步任务、轮询状态页或上传历史模块
|
||
- 不保存多版本征信记录
|
||
- 不保存原始 HTML 文件或原始 payload JSON
|
||
- 不增加说明书之外的补丁性兜底方案
|
||
|
||
## 5. 方案对比
|
||
|
||
### 5.1 方案 A:三张业务表,增加征信主表
|
||
|
||
新增征信主表保存员工最新摘要,再配合负债表和负面信息表。
|
||
|
||
优点:
|
||
|
||
- 列表查询简单
|
||
- 聚合逻辑更少
|
||
|
||
缺点:
|
||
|
||
- 引入额外主表,超出本次最短路径
|
||
- 同一份摘要数据会与明细形成重复维护
|
||
|
||
### 5.2 方案 B:仅保留两张业务表,列表实时聚合
|
||
|
||
只建设 `ccdi_debts_info` 与负面信息表,主列表按员工维度实时聚合展示。
|
||
|
||
优点:
|
||
|
||
- 满足“负债表固定命名”和“负面信息单独建表”
|
||
- 不引入额外主表,路径最短
|
||
- 删除和覆盖逻辑仍然清晰,按员工清空两张表即可
|
||
|
||
缺点:
|
||
|
||
- 列表查询需要做员工维度聚合
|
||
|
||
### 5.3 方案 C:两张业务表加原始 payload 存档
|
||
|
||
在方案 B 基础上额外保存原始 payload 或原始 HTML。
|
||
|
||
优点:
|
||
|
||
- 排查解析问题时信息更全
|
||
|
||
缺点:
|
||
|
||
- 增加冗余与维护成本
|
||
- 超出当前需求
|
||
|
||
## 6. 最终方案
|
||
|
||
采用方案 B:仅新增 `ccdi_debts_info` 和 `ccdi_credit_negative_info` 两张业务表,列表按员工维度实时聚合,不新增征信主表。
|
||
|
||
选择原因:
|
||
|
||
- 满足“每个员工只保留最新征信信息”的要求
|
||
- 满足“负债信息按 Excel 设计、负面信息单独建表”的要求
|
||
- 不额外增加主表,保持最短路径实现
|
||
- 删除逻辑直接按员工清理两张业务表,语义明确
|
||
|
||
## 7. 总体架构
|
||
|
||
业务链路如下:
|
||
|
||
`征信维护页面 -> 征信维护业务接口 -> 征信维护服务 -> /lsfx/credit/parse -> 征信解析服务`
|
||
|
||
职责拆分如下:
|
||
|
||
- 征信维护页面
|
||
- 选择多个 HTML 文件并提交上传
|
||
- 展示员工维度征信摘要列表
|
||
- 打开详情弹窗查看负债明细与负面信息
|
||
- 删除员工当前征信数据
|
||
|
||
- 征信维护业务接口
|
||
- 对外提供上传、列表、详情、删除接口
|
||
- 不直接把前端耦合到 `ccdi-lsfx`
|
||
|
||
- 征信维护服务
|
||
- 逐文件调用征信解析接口
|
||
- 根据员工身份证号归户
|
||
- 校验“是否为最新征信”
|
||
- 单员工事务覆盖写入两张业务表
|
||
|
||
- `ccdi-lsfx`
|
||
- 保持现有征信解析客户端能力
|
||
- 继续作为外部征信解析接入边界
|
||
|
||
## 8. 数据模型设计
|
||
|
||
### 8.1 负债明细表 `ccdi_debts_info`
|
||
|
||
一条记录表示一条负债明细,字段按 `assets/征信解析/ccdi_debts_info.xlsx` 设计:
|
||
|
||
- `debt_id`:`BIGINT` 主键,自增
|
||
- `person_id`:`VARCHAR(18)`,员工身份证号
|
||
- `person_name`:`VARCHAR(100)`,员工姓名
|
||
- `query_date`:`DATE`,征信查询日期
|
||
- `debt_main_type`:`VARCHAR(50)`,负债大类
|
||
- `debt_sub_type`:`VARCHAR(50)`,负债小类
|
||
- `creditor_type`:`VARCHAR(50)`,债权人类型
|
||
- `debt_name`:`VARCHAR(100)`,负债名称
|
||
- `principal_balance`:`DECIMAL(18,2)`,负债本金余额
|
||
- `debt_total_amount`:`DECIMAL(18,2)`,负债总额
|
||
- `debt_status`:`VARCHAR(20)`,负债状态
|
||
- `create_by`:`VARCHAR(64)`
|
||
- `create_time`:`DATETIME`
|
||
- `update_by`:`VARCHAR(64)`
|
||
- `update_time`:`DATETIME`
|
||
|
||
建议索引:
|
||
|
||
- `idx_person_id(person_id)`
|
||
- `idx_query_date(query_date)`
|
||
- `idx_person_query_date(person_id, query_date)`
|
||
|
||
### 8.2 负面信息表 `ccdi_credit_negative_info`
|
||
|
||
一条记录表示一个员工当前最新征信对应的负面信息汇总:
|
||
|
||
- `negative_id`:`BIGINT` 主键,自增
|
||
- `person_id`:`VARCHAR(18)`,员工身份证号
|
||
- `person_name`:`VARCHAR(100)`,员工姓名
|
||
- `query_date`:`DATE`,征信查询日期
|
||
- `civil_cnt`:`INT`,民事案件笔数
|
||
- `enforce_cnt`:`INT`,强制执行笔数
|
||
- `adm_cnt`:`INT`,行政处罚笔数
|
||
- `civil_lmt`:`DECIMAL(18,2)`,民事案件金额
|
||
- `enforce_lmt`:`DECIMAL(18,2)`,强制执行金额
|
||
- `adm_lmt`:`DECIMAL(18,2)`,行政处罚金额
|
||
- `create_by`:`VARCHAR(64)`
|
||
- `create_time`:`DATETIME`
|
||
- `update_by`:`VARCHAR(64)`
|
||
- `update_time`:`DATETIME`
|
||
|
||
建议索引:
|
||
|
||
- `uk_person_id(person_id)` 唯一索引
|
||
|
||
## 9. 解析字段映射设计
|
||
|
||
### 9.1 归户字段
|
||
|
||
从解析结果 `lx_header` 中读取:
|
||
|
||
- `query_cert_no` -> 员工身份证号 `person_id`
|
||
- `query_cust_name` -> 员工姓名 `person_name`
|
||
- `report_time` -> 征信查询日期 `query_date`
|
||
|
||
`query_cert_no` 作为员工唯一归户标识,并校验该身份证号必须存在于 `ccdi_base_staff`。
|
||
|
||
### 9.2 `lx_debt` 到 `ccdi_debts_info` 的映射
|
||
|
||
`lx_debt` 当前为 7 组固定字段,每组映射成一条负债明细:
|
||
|
||
| 接口前缀 | 负债大类 | 负债小类 | 债权人类型 | 负债名称 |
|
||
| --- | --- | --- | --- | --- |
|
||
| `uncle_bank_house` | 银行 | 住房贷款 | 银行 | 未结清银行住房贷款 |
|
||
| `uncle_bank_car` | 银行 | 汽车贷款 | 银行 | 未结清银行汽车贷款 |
|
||
| `uncle_bank_manage` | 银行 | 经营贷款 | 银行 | 未结清银行经营贷款 |
|
||
| `uncle_bank_consume` | 银行 | 消费贷款 | 银行 | 未结清银行消费贷款 |
|
||
| `uncle_bank_other` | 银行 | 其他贷款 | 银行 | 未结清银行其他贷款 |
|
||
| `uncle_not_bank` | 非银 | 非银行贷款 | 非银 | 未结清非银行贷款 |
|
||
| `uncle_credit_cart` | 银行 | 信用卡 | 银行 | 未结清信用卡 |
|
||
|
||
字段映射规则:
|
||
|
||
- `*_bal` -> `principal_balance`
|
||
- `*_lmt` -> `debt_total_amount`
|
||
- `*_state` -> `debt_status`
|
||
|
||
落库过滤规则:
|
||
|
||
- 当某组 `principal_balance`、`debt_total_amount` 都为空或 `0`,且 `debt_status` 为空时,不生成明细记录
|
||
- 其余情况生成一条明细
|
||
|
||
### 9.3 `lx_publictype` 到 `ccdi_credit_negative_info` 的映射
|
||
|
||
按接口字段直接映射:
|
||
|
||
- `civil_cnt` -> `civil_cnt`
|
||
- `enforce_cnt` -> `enforce_cnt`
|
||
- `adm_cnt` -> `adm_cnt`
|
||
- `civil_lmt` -> `civil_lmt`
|
||
- `enforce_lmt` -> `enforce_lmt`
|
||
- `adm_lmt` -> `adm_lmt`
|
||
|
||
## 10. 最新征信判定与覆盖策略
|
||
|
||
系统只保留员工最新征信,规则如下:
|
||
|
||
- 以 `person_id` 作为员工唯一标识
|
||
- 以 `query_date` 作为征信最新时间判定字段
|
||
- 员工上传新文件时:
|
||
- 若库中无现有征信数据,直接写入
|
||
- 若新 `query_date` 大于等于现有 `query_date`,覆盖旧数据
|
||
- 若新 `query_date` 小于现有 `query_date`,该员工本次文件判定为失败,不覆盖
|
||
|
||
单员工覆盖写入步骤:
|
||
|
||
1. 删除 `ccdi_debts_info` 中该员工旧记录
|
||
2. 删除 `ccdi_credit_negative_info` 中该员工旧记录
|
||
3. 插入本次解析后的最新负债明细
|
||
4. 插入本次解析后的最新负面信息
|
||
|
||
以上 4 步置于同一事务中,保证员工维度原子化。
|
||
|
||
## 11. 页面设计
|
||
|
||
### 11.1 菜单
|
||
|
||
在“信息维护”下新增菜单:
|
||
|
||
- 菜单名称:`征信维护`
|
||
- 路由:`creditInfo`
|
||
- 组件:`ccdiCreditInfo/index`
|
||
- 权限前缀:`ccdi:creditInfo:*`
|
||
|
||
### 11.2 顶部操作区
|
||
|
||
- 批量上传征信 HTML 按钮
|
||
- 查询条件:
|
||
- 员工姓名
|
||
- 柜员号
|
||
- 身份证号
|
||
- 是否已维护征信
|
||
|
||
上传弹窗要求:
|
||
|
||
- 仅允许选择 `.html/.htm`
|
||
- 支持一次选择多个文件
|
||
- 提交后调用业务上传接口
|
||
- 接口返回后直接展示成功/失败汇总及失败清单
|
||
|
||
### 11.3 主列表
|
||
|
||
主列表按员工一行展示,字段建议:
|
||
|
||
- 员工姓名
|
||
- 柜员号
|
||
- 身份证号
|
||
- 所属部门
|
||
- 最近征信查询日期
|
||
- 负债笔数
|
||
- 负债总额
|
||
- 民事案件笔数
|
||
- 强制执行笔数
|
||
- 行政处罚笔数
|
||
- 操作
|
||
|
||
聚合规则:
|
||
|
||
- 基础信息来自 `ccdi_base_staff`
|
||
- 最近征信查询日期、负债笔数、负债总额来自 `ccdi_debts_info`
|
||
- 三类负面计数来自 `ccdi_credit_negative_info`
|
||
- 任一业务表存在数据,即视为“已维护征信”
|
||
|
||
### 11.4 详情弹窗
|
||
|
||
详情弹窗分为两部分:
|
||
|
||
- 摘要区域
|
||
- 员工姓名
|
||
- 身份证号
|
||
- 征信查询日期
|
||
- 负债总额
|
||
- 负债笔数
|
||
- 民事案件笔数
|
||
- 强制执行笔数
|
||
- 行政处罚笔数
|
||
|
||
- 明细区域
|
||
- 负债信息表格
|
||
- 负面信息汇总卡片
|
||
|
||
负债表格字段:
|
||
|
||
- 负债大类
|
||
- 负债小类
|
||
- 债权人类型
|
||
- 负债名称
|
||
- 负债本金余额
|
||
- 负债总额
|
||
- 负债状态
|
||
|
||
负面信息展示字段:
|
||
|
||
- 民事案件笔数 / 金额
|
||
- 强制执行笔数 / 金额
|
||
- 行政处罚笔数 / 金额
|
||
|
||
### 11.5 删除交互
|
||
|
||
列表点击删除时,提示:
|
||
|
||
`确认删除该员工当前已维护的征信信息吗?`
|
||
|
||
确认后删除该员工在两张业务表中的全部数据。
|
||
|
||
## 12. 接口设计
|
||
|
||
新增业务接口,前端不直接调用 `/lsfx/credit/parse`:
|
||
|
||
### 12.1 批量上传
|
||
|
||
- 方法:`POST`
|
||
- 路径:`/ccdi/creditInfo/upload`
|
||
- 入参:多个 HTML 文件
|
||
- 返回:
|
||
- 总文件数
|
||
- 成功数
|
||
- 失败数
|
||
- 失败明细列表
|
||
|
||
失败明细建议字段:
|
||
|
||
- `fileName`
|
||
- `personId`
|
||
- `personName`
|
||
- `reason`
|
||
|
||
### 12.2 列表分页查询
|
||
|
||
- 方法:`GET`
|
||
- 路径:`/ccdi/creditInfo/list`
|
||
- 功能:分页查询员工征信摘要列表
|
||
|
||
### 12.3 详情查询
|
||
|
||
- 方法:`GET`
|
||
- 路径:`/ccdi/creditInfo/{personId}`
|
||
- 功能:查询员工征信摘要、负债明细和负面信息
|
||
|
||
### 12.4 删除
|
||
|
||
- 方法:`DELETE`
|
||
- 路径:`/ccdi/creditInfo/{personId}`
|
||
- 功能:删除员工当前征信数据
|
||
|
||
## 13. 后端设计
|
||
|
||
建议改动集中在 `ccdi-info-collection` 模块,新增独立征信维护资源。
|
||
|
||
建议新增:
|
||
|
||
- `controller/CcdiCreditInfoController.java`
|
||
- `service/ICcdiCreditInfoService.java`
|
||
- `service/impl/CcdiCreditInfoServiceImpl.java`
|
||
- `domain/CcdiCreditNegativeInfo.java`
|
||
- `domain/dto/CreditInfoUploadResultDTO.java`
|
||
- `domain/vo/CreditInfoListVO.java`
|
||
- `domain/vo/CreditInfoDetailVO.java`
|
||
- `mapper/CcdiCreditNegativeInfoMapper.java`
|
||
- `mapper/CcdiCreditInfoQueryMapper.java`
|
||
- `resources/mapper/...`
|
||
|
||
职责说明:
|
||
|
||
- `CcdiCreditInfoController`
|
||
- 暴露上传、列表、详情、删除接口
|
||
|
||
- `CcdiCreditInfoService`
|
||
- 协调解析、归户、最新记录校验、覆盖写入
|
||
|
||
- `CcdiCreditNegativeInfoMapper`
|
||
- 维护负面信息表增删查
|
||
|
||
- `CcdiCreditInfoQueryMapper`
|
||
- 承担员工维度列表聚合查询和详情聚合查询
|
||
|
||
## 14. 异常处理
|
||
|
||
上传过程中逐文件处理,失败不影响其他员工成功:
|
||
|
||
- 文件后缀非法:失败原因为“文件格式不支持”
|
||
- 解析接口调用失败:失败原因为“征信解析失败”
|
||
- 解析成功但身份证号为空:失败原因为“未解析到员工身份证号”
|
||
- 身份证号未匹配到员工:失败原因为“未匹配到员工信息”
|
||
- 上传征信日期早于当前最新记录:失败原因为“上传征信日期早于当前已维护最新记录”
|
||
- 员工覆盖写入事务失败:失败原因为“征信数据保存失败”
|
||
|
||
删除接口按幂等处理:
|
||
|
||
- 即使员工当前无征信数据,也返回删除成功
|
||
|
||
## 15. 测试方案
|
||
|
||
### 15.1 后端测试
|
||
|
||
- 上传服务测试
|
||
- 单文件解析成功后正确写入两张业务表
|
||
- 同员工新日期文件覆盖旧数据
|
||
- 同员工旧日期文件被拒绝覆盖
|
||
- 一个员工失败不影响其他员工成功
|
||
- 删除后两张表数据均被清空
|
||
|
||
- 聚合查询测试
|
||
- 只有负债信息
|
||
- 只有负面信息
|
||
- 两者都有
|
||
- 两者都没有
|
||
- 分页下聚合字段正确
|
||
|
||
- 控制器测试
|
||
- 批量上传成功
|
||
- 混合成功/失败上传
|
||
- 详情查询成功/无数据
|
||
- 删除接口幂等
|
||
|
||
### 15.2 前端验证
|
||
|
||
- 上传多个 HTML 文件并查看结果提示
|
||
- 列表按员工维度展示聚合摘要
|
||
- 详情弹窗正确显示负债表和负面信息
|
||
- 删除后该员工征信摘要即时消失
|
||
- 前端生产构建通过
|
||
|
||
## 16. 文档与脚本产出要求
|
||
|
||
本次实施阶段需同步补充:
|
||
|
||
- 后端实施计划:`docs/plans/backend/`
|
||
- 前端实施计划:`docs/plans/frontend/`
|
||
- SQL 脚本:`sql/` 或 `sql/migration/`
|
||
- 实施记录:`docs/reports/implementation/`
|
||
|
||
文档落点需遵循仓库目录规范,避免写入错误目录。
|