diff --git a/docs/design/2026-03-23-credit-info-maintenance-design.md b/docs/design/2026-03-23-credit-info-maintenance-design.md new file mode 100644 index 00000000..94dc5f23 --- /dev/null +++ b/docs/design/2026-03-23-credit-info-maintenance-design.md @@ -0,0 +1,462 @@ +# 征信维护设计文档 + +## 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/` + +文档落点需遵循仓库目录规范,避免写入错误目录。 diff --git a/docs/reports/implementation/2026-03-23-credit-info-maintenance-design-record.md b/docs/reports/implementation/2026-03-23-credit-info-maintenance-design-record.md new file mode 100644 index 00000000..fe1f81d0 --- /dev/null +++ b/docs/reports/implementation/2026-03-23-credit-info-maintenance-design-record.md @@ -0,0 +1,23 @@ +# 2026-03-23 征信维护设计文档记录 + +## 本次产出 + +- 新增设计文档 `docs/design/2026-03-23-credit-info-maintenance-design.md` +- 固化“征信维护”菜单、批量上传、员工维度聚合列表、两张业务表落库与删除逻辑 + +## 关键确认结论 + +- 主列表按员工摘要展示 +- 负债表表名固定为 `ccdi_debts_info` +- 不新增征信主表,列表通过明细表实时聚合 +- 批量上传按员工维度原子化处理 +- 每个员工只保留最新征信信息 + +## 数据模型结论 + +- 负债明细表:`ccdi_debts_info` +- 负面信息表:`ccdi_credit_negative_info` + +## 后续动作 + +- 待用户审阅设计文档后,继续输出前端与后端实施计划