设计: 员工资产导入与实体库自动补入修复

This commit is contained in:
wkc
2026-05-06 17:18:21 +08:00
parent bbc6a2050b
commit 104e8697fe

View File

@@ -0,0 +1,325 @@
# 员工资产导入与实体库自动补入修复设计
## 1. 背景
本设计用于修复以下后端问题:
1. 【员工信息维护】双 Sheet 导入时,`员工资产信息` Sheet 只能通过数据库已有员工反查归属,不能识别同一个导入文件中刚成功导入的员工。
2. 【员工亲属关系维护】双 Sheet 导入时,`亲属资产信息` Sheet 只能通过数据库已有亲属关系反查归属,不能识别同一个导入文件中刚成功导入的亲属关系。
3. 关联业务自动补入实体库能力在当前主工作区未完整接回,员工亲属、信贷客户、中介、供应商四类业务成功关联后,缺失企业需要统一补入 `ccdi_enterprise_base_info`
本次设计只涉及后端。不调整前端页面结构、上传入口、模板样式和前端轮询字段。
## 2. 目标
- 双 Sheet 导入时,主 Sheet 与资产 Sheet 在后端按业务依赖顺序执行。
- 资产 Sheet 可关联数据库已有主数据,也可关联同一文件中本轮主 Sheet 成功导入的数据。
- 主 Sheet 失败行不能作为资产归属依据。
- 继续返回当前前端已支持的两个任务 ID
- 员工信息维护:`staffTaskId``assetTaskId`
- 员工亲属关系维护:`relationTaskId``assetTaskId`
- 恢复统一 `EnterpriseAutoFillService`,并接入员工亲属、信贷客户、中介、供应商四类业务。
- 实体库自动补入只插入缺失企业,不更新已存在实体。
## 3. 不在本次范围
- 不改前端上传入口、轮询逻辑、失败记录展示和模板下载样式。
- 不合并双 Sheet 导入任务 ID。
- 不改变员工、亲属关系、资产、实体关联现有字段校验规则。
- 不改变实体库手工新增、编辑、导入的既有业务规则。
- 不增加兜底来源、降级来源或兼容性分支。
## 4. 总体架构
本次后端设计分为两条链路。
### 4.1 双 Sheet 导入编排
`/ccdi/baseStaff/importData``/ccdi/staffFmyRelation/importData` 保持原接口、原模板、原返回字段。
Controller 继续负责读取两个 Sheet但不再分别提交两个彼此独立的异步任务。服务层新增提交编排方法
- 员工信息维护提交方法接收 `List<CcdiBaseStaffExcel>``List<CcdiBaseStaffAssetInfoExcel>`
- 员工亲属关系维护提交方法接收 `List<CcdiStaffFmyRelationExcel>``List<CcdiAssetInfoExcel>`
提交方法按实际存在的 Sheet 初始化对应任务状态,并启动一个后台编排任务。编排任务内部按顺序执行:
1. 主 Sheet 校验与插入。
2. 收集本轮主 Sheet 成功上下文。
3. 资产 Sheet 校验与插入。
### 4.2 实体库自动补入
新增或恢复统一内部服务:
`ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/support/EnterpriseAutoFillService.java`
该服务是关联业务补入实体库的唯一后端入口。四类业务在业务校验通过、业务记录落库前调用:
- 员工亲属实体关联:`EMP_RELATION`
- 信贷客户实体关联:`CREDIT_CUSTOMER`
- 中介实体关联:`INTERMEDIARY`
- 招投标供应商:`SUPPLIER`
实体库缺失时最小插入;已存在时不更新。
## 5. 员工信息维护双 Sheet 导入设计
### 5.1 当前问题
当前 `/ccdi/baseStaff/importData` 分别读取 `员工信息``员工资产信息`,然后分别调用:
- `baseStaffService.importBaseStaff(staffList)`
- `baseStaffAssetImportService.importAssetInfo(assetList)`
两个任务互相独立。员工资产导入只通过数据库 `ccdi_base_staff.id_card` 查找归属,无法稳定看到同一文件中刚导入成功的员工。
### 5.2 设计方案
新增员工信息维护双 Sheet 后端编排能力。
提交阶段:
1. Controller 读取两个 Sheet。
2. 若两个 Sheet 都无数据,仍返回“至少需要一条数据”。
3. 若存在员工 Sheet生成并初始化 `staffTaskId`
4. 若存在员工资产 Sheet生成并初始化 `assetTaskId`
5. 返回当前前端兼容的 `BaseStaffImportSubmitResultVO`
6. 后台启动一个编排任务。
编排阶段:
1. 先执行员工主数据导入。
2. 沿用现有员工必填、身份证号、部门、员工 ID、身份证号重复校验。
3. 批量插入员工成功记录。
4. 收集本轮成功员工的 `idCard`
5. 更新员工任务状态和失败记录。
6. 再执行员工资产导入。
7. 员工资产归属候选来源为:
- 数据库已有 `ccdi_base_staff.id_card`
- 本轮员工 Sheet 成功导入的 `idCard`
8. 员工资产落库继续保持:
- `family_id = 员工身份证号`
- `person_id = 员工身份证号`
9. 员工资产继续保持重复校验:`personId + assetMainType + assetSubType + assetName`
### 5.3 任务状态
- 只填员工 Sheet只返回 `staffTaskId`
- 只填员工资产 Sheet只返回 `assetTaskId`,只按数据库已有员工校验。
- 两个 Sheet 都填:返回 `staffTaskId``assetTaskId`,后台保证员工先处理、资产后处理。
- 员工主 Sheet 部分成功时,员工资产只能使用成功员工上下文。
- 员工主 Sheet 全部失败时,员工资产仍执行,但只能命中数据库已有员工。
## 6. 员工亲属关系维护双 Sheet 导入设计
### 6.1 当前问题
当前 `/ccdi/staffFmyRelation/importData` 分别读取 `员工亲属关系信息``亲属资产信息`,然后分别调用:
- `relationService.importRelation(relationList)`
- `assetInfoImportService.importAssetInfo(assetList)`
两个任务互相独立。亲属资产导入只通过数据库 `ccdi_staff_fmy_relation.relation_cert_no` 查找归属,无法稳定看到同一文件中刚导入成功的亲属关系。
### 6.2 设计方案
新增员工亲属关系维护双 Sheet 后端编排能力。
提交阶段:
1. Controller 读取两个 Sheet。
2. 若两个 Sheet 都无数据,仍返回“至少需要一条数据”。
3. 若存在亲属关系 Sheet生成并初始化 `relationTaskId`
4. 若存在亲属资产 Sheet生成并初始化 `assetTaskId`
5. 返回当前前端兼容的 `StaffFmyRelationImportSubmitResultVO`
6. 后台启动一个编排任务。
编排阶段:
1. 先执行亲属关系导入。
2. 沿用现有亲属关系必填、员工身份证号存在性、关系人证件号、重复组合校验。
3. 批量插入亲属关系成功记录。
4. 收集本轮成功亲属关系映射:
- `relationCertNo` 作为资产 Sheet 的 `personId`
- `personId` 作为资产落库的 `familyId`
5. 更新亲属关系任务状态和失败记录。
6. 再执行亲属资产导入。
7. 亲属资产归属候选来源为:
- 数据库已有有效员工亲属关系
- 本轮亲属关系 Sheet 成功导入的有效员工亲属关系
8. 亲属资产落库继续保持:
- `family_id = 员工身份证号`
- `person_id = 亲属身份证号`
### 6.3 任务状态
- 只填亲属关系 Sheet只返回 `relationTaskId`
- 只填亲属资产 Sheet只返回 `assetTaskId`,只按数据库已有有效亲属关系校验。
- 两个 Sheet 都填:返回 `relationTaskId``assetTaskId`,后台保证亲属关系先处理、资产后处理。
- 亲属关系主 Sheet 部分成功时,亲属资产只能使用成功亲属关系上下文。
- 亲属关系主 Sheet 全部失败时,亲属资产仍执行,但只能命中数据库已有有效亲属关系。
## 7. 实体库自动补入设计
### 7.1 服务职责
`EnterpriseAutoFillService` 只负责一件事:对关联业务成功记录中的企业,确保实体库存在对应统一社会信用代码。
服务接口:
- `ensureExists(EnterpriseFillItem item)`
- `ensureExistsBatch(List<EnterpriseFillItem> items)`
`EnterpriseFillItem` 字段:
- `socialCreditCode`
- `enterpriseName`
- `entSource`
- `dataSource`
- `userName`
### 7.2 插入规则
1.`socialCreditCode` 去重,同批次同一统一社会信用代码只处理一次。
2. 批量查询 `ccdi_enterprise_base_info` 已存在记录。
3. 已存在实体不更新。
4. 缺失实体最小插入:
- `social_credit_code = 统一社会信用代码`
- `enterprise_name = 企业名称`
- `ent_source = 来源`
- `data_source = MANUAL 或 IMPORT`
- `risk_level = 来源规则值`
- `create_by/update_by = 当前用户`
5. 中介来源 `INTERMEDIARY``risk_level = 1`
6. 员工亲属、信贷客户、供应商来源写 `risk_level = NULL`
7. 并发导致主键重复时,按“已存在实体”处理。
8. 其他数据库异常抛出,让当前业务事务失败。
### 7.3 四类业务接入点
员工亲属实体关联:
- 手工新增:校验有效亲属和组合不重复后、插入关联表前补入。
- 导入:只对校验成功并即将插入的记录批量补入。
- 来源:`EMP_RELATION`
- 数据来源:手工新增为 `MANUAL`,导入为 `IMPORT`
- 风险等级:`NULL`
信贷客户实体关联:
- 手工新增:校验通过后、插入关联表前补入。
- 导入:只对校验成功并即将插入的记录批量补入。
- 来源:`CREDIT_CUSTOMER`
- 数据来源:手工新增为 `MANUAL`,导入为 `IMPORT`
- 风险等级:`NULL`
中介实体关联:
- 手工新增:校验通过后、插入关联关系前补入实体库。
- 导入:只对校验成功并即将插入的记录批量补入。
- 来源:`INTERMEDIARY`
- 数据来源:手工新增为 `MANUAL`,导入为 `IMPORT`
- 风险等级:`1`
招投标供应商:
- 手工新增或保存招投标主信息时,只对有效供应商数据补入。
- 导入:只对成功采购事项中的供应商批量补入,失败采购事项不补入。
- 来源:`SUPPLIER`
- 数据来源:手工新增为 `MANUAL`,导入为 `IMPORT`
- 风险等级:`NULL`
## 8. 错误处理与边界
### 8.1 双 Sheet 导入边界
- 主 Sheet 失败行不能进入资产归属候选。
- 主 Sheet 文件内重复行不能进入资产归属候选。
- 主 Sheet 数据库重复行不能进入资产归属候选。
- 资产 Sheet 仍按自身失败记录任务记录 `sheetName``rowNum``errorMessage`
- 员工资产找不到员工时继续报“员工资产导入仅支持员工本人证件号”。
- 亲属资产找不到归属时继续报“未找到亲属资产归属员工”。
- 亲属资产命中多个归属时继续报“亲属资产归属员工不唯一”。
### 8.2 自动补入边界
- 只处理业务校验成功、即将落库的记录。
- 失败业务行不能产生实体库记录。
- 已存在实体不更新,避免覆盖人工维护数据。
- 不增加默认企业名称、默认来源、默认风险等级等兜底逻辑。
- 不改变实体库导入的严格新增规则。
## 9. 测试设计
### 9.1 单元测试
员工信息维护双 Sheet
- 同一模板中新员工和员工资产同时导入,资产引用新员工身份证号,资产成功。
- 员工 Sheet 行校验失败,资产引用该身份证号且数据库不存在,资产失败。
- 只导员工资产,数据库已有员工时成功。
- 只导员工资产,数据库无员工时失败。
- 资产重复命中数据库或当前文件重复时失败。
员工亲属关系维护双 Sheet
- 同一模板中新亲属关系和亲属资产同时导入,资产引用新亲属证件号,资产成功。
- 亲属关系 Sheet 行校验失败,资产引用该亲属证件号且数据库不存在,资产失败。
- 只导亲属资产,数据库已有唯一有效亲属关系时成功。
- 只导亲属资产,数据库不存在亲属关系时失败。
- 同一亲属证件号命中多个员工归属时失败。
实体库自动补入:
- 已存在实体不插入、不更新。
- 缺失实体插入最小记录。
- 同批多个成功行引用同一统一社会信用代码,只补入一次。
- 中介来源写 `riskLevel=1`
- 员工亲属、信贷客户、供应商来源写 `riskLevel=null`
- 并发重复主键按已存在处理。
四类业务接入:
- 手工新增成功时调用自动补入。
- 导入成功行进入自动补入集合。
- 导入失败行不进入自动补入集合。
### 9.2 接口验证
1. 下载真实 `/ccdi/baseStaff/importTemplate` 模板,构造 `员工信息` + `员工资产信息` 同文件导入,上传 `/ccdi/baseStaff/importData`,轮询两个任务并查询员工、资产落库。
2. 下载真实 `/ccdi/staffFmyRelation/importTemplate` 模板,构造 `员工亲属关系信息` + `亲属资产信息` 同文件导入,上传 `/ccdi/staffFmyRelation/importData`,轮询两个任务并查询亲属关系、资产落库。
3. 分别调用员工亲属、信贷客户、中介、供应商新增或导入接口,验证实体库自动补入来源、数据来源和风险等级。
4. 涉及中文清理 SQL 或验证 SQL 时使用 `bin/mysql_utf8_exec.sh`
### 9.3 页面验证
完成后必须进入真实业务页面验证,不打开 prototype
1. 【员工信息维护】下载模板,填写员工和员工资产,上传后检查任务状态、失败记录、列表和详情资产。
2. 【员工亲属关系维护】下载模板,填写亲属关系和亲属资产,上传后检查任务状态、失败记录、详情资产。
3. 四类实体自动补入完成后,进入【实体库管理】按统一社会信用代码查询。
4. 测试结束后清理本轮新增员工、亲属关系、资产、实体关联和自动补入实体库数据。
5. 测试结束后关闭测试过程中启动的前后端进程。
## 10. 实施顺序
1. 提炼员工主数据导入执行方法,返回成功员工上下文和失败记录。
2. 提炼员工资产导入执行方法,支持额外员工归属上下文。
3. 新增员工信息维护双 Sheet 编排方法并接入 Controller。
4. 提炼亲属关系导入执行方法,返回成功亲属关系上下文和失败记录。
5. 提炼亲属资产导入执行方法,支持额外亲属关系归属上下文。
6. 新增员工亲属关系维护双 Sheet 编排方法并接入 Controller。
7. 恢复或新增 `EnterpriseAutoFillService`
8. 接入员工亲属、信贷客户、中介、供应商四类自动补入。
9. 补充单元测试。
10. 执行接口验证和真实页面验证。
11. 新增实施记录到 `docs/reports/implementation/`
## 11. 风险与控制
- 不能继续由 Controller 分别提交两个独立异步任务,否则资产任务执行顺序仍不确定。
- 不能把主 Sheet 失败行放入资产归属上下文,否则会产生脏资产。
- 不能更新已存在实体库记录,否则会覆盖人工维护的企业名称、风险等级和来源。
- 自动补入必须在业务记录落库前执行,并与业务事务保持一致。
- 四类自动补入必须只处理成功业务行,失败行不能污染实体库。