Files
ccdi/docs/plans/backend/2026-05-06-staff-asset-import-and-enterprise-autofill-fix-backend-solution.md

237 lines
13 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. 【员工信息维护】和【员工亲属关系维护】使用双 Sheet 模板导入时,第二个 Sheet 的资产信息只按数据库已有主数据反查归属,不能识别同一个导入文件中刚导入的员工或亲属关系,导致提示“未找到资产归属员工”等错误。
2. 【员工亲属实体关联】新增或导入关系人与企业关联后,只写入员工亲属实体关联表,没有同步生成实体库数据,导致企业名称和统一社会信用代码不能自动落入【实体库管理】。
本次解决方案只涉及后端,不调整前端页面结构、上传入口和模板样式。现有前端已经能接收员工任务 ID 与资产任务 ID并分别轮询失败记录因此后端需要保持现有返回字段兼容。
## 目标
- 双 Sheet 导入时,主 Sheet 和资产 Sheet 按同一个文件内的业务依赖顺序处理。
- 资产 Sheet 可以关联到数据库已存在的员工或亲属主数据,也可以关联到同一文件中本轮成功导入的员工或亲属主数据。
- 主 Sheet 校验失败的数据不能作为资产归属依据。
- 员工亲属实体关联新增和导入成功后,缺失的企业自动补入实体库。
- 实体库自动补入只插入缺失企业,不更新已存在实体。
## 方案一:员工信息维护双 Sheet 导入
### 当前问题链路
- `/ccdi/baseStaff/importData` 当前分别读取 `员工信息``员工资产信息` 两个 Sheet。
- 有员工数据时调用 `baseStaffService.importBaseStaff(staffList)`,有资产数据时调用 `baseStaffAssetImportService.importAssetInfo(assetList)`
- 两个任务独立异步执行,员工资产任务只通过 `ccdi_base_staff.id_card` 查询数据库已有员工。
- 当模板中员工和资产同时首次导入时,资产任务无法稳定看到本轮员工导入结果。
### 改造策略
保留接口路径、模板名称、返回结构和前端轮询模型,新增后端双 Sheet 编排能力。
1. 在员工导入服务中增加双 Sheet 提交方法:
- 输入:`List<CcdiBaseStaffExcel> staffList``List<CcdiBaseStaffAssetInfoExcel> assetList`
- 输出:`BaseStaffImportSubmitResultVO`
- 有员工 Sheet 时生成 `staffTaskId`
- 有资产 Sheet 时生成 `assetTaskId`
2. 新增一个统一异步编排方法,按顺序执行:
- 初始化员工导入任务状态
- 执行员工主数据校验和批量插入
- 收集本轮员工导入成功的 `idCard`
- 更新员工任务状态和失败记录
- 初始化员工资产导入任务状态
- 执行员工资产导入
- 员工资产归属候选来源为:
- 数据库已有 `ccdi_base_staff.id_card`
- 本轮员工 Sheet 成功导入的 `idCard`
- 更新员工资产任务状态和失败记录
3. 员工资产导入逻辑调整:
- 保留“员工资产只允许员工本人身份证号”的业务规则。
- 保留重复校验规则:`personId + assetMainType + assetSubType + assetName`
- `personId` 既可以命中数据库已有员工,也可以命中本轮成功导入员工。
- 只命中员工 Sheet 失败行、且数据库中也不存在该身份证号时,资产行进入失败记录。
4. `/ccdi/baseStaff/importData` 改为调用新的双 Sheet 提交方法,不再由 Controller 分别提交两个互相独立的异步任务。
### 结果状态
- 只填员工 Sheet只返回 `staffTaskId`,行为保持不变。
- 只填员工资产 Sheet只返回 `assetTaskId`,按数据库已有员工校验。
- 两个 Sheet 都填写:返回 `staffTaskId``assetTaskId`,但后端在同一个编排任务中先处理员工再处理资产。
## 方案二:员工亲属关系维护双 Sheet 导入
### 当前问题链路
- `/ccdi/staffFmyRelation/importData` 当前分别读取 `员工亲属关系信息``亲属资产信息` 两个 Sheet。
- 有亲属关系数据时调用 `relationService.importRelation(relationList)`,有亲属资产数据时调用 `assetInfoImportService.importAssetInfo(assetList)`
- 亲属资产导入只通过 `ccdi_staff_fmy_relation.relation_cert_no` 查询数据库已有亲属关系。
- 当模板中亲属关系和亲属资产同时首次导入时,资产任务无法稳定看到本轮亲属关系导入结果。
### 改造策略
保留接口路径、模板名称、返回结构和前端轮询模型,新增员工亲属关系双 Sheet 编排能力。
1. 在员工亲属关系导入服务中增加双 Sheet 提交方法:
- 输入:`List<CcdiStaffFmyRelationExcel> relationList``List<CcdiAssetInfoExcel> assetList`
- 输出:`StaffFmyRelationImportSubmitResultVO`
- 有亲属关系 Sheet 时生成 `relationTaskId`
- 有亲属资产 Sheet 时生成 `assetTaskId`
2. 新增一个统一异步编排方法,按顺序执行:
- 初始化亲属关系导入任务状态
- 执行亲属关系校验和批量插入
- 收集本轮成功导入且有效的亲属关系映射:
- `relationCertNo` 作为资产 Sheet 的 `personId`
- `personId` 作为资产落库的 `familyId`
- 更新亲属关系任务状态和失败记录
- 初始化亲属资产导入任务状态
- 执行亲属资产导入
- 亲属资产归属候选来源为:
- 数据库已有有效员工亲属关系
- 本轮亲属关系 Sheet 成功导入的有效员工亲属关系
- 更新亲属资产任务状态和失败记录
3. 亲属资产导入逻辑调整:
- 保留 `family_id = 员工身份证号``person_id = 亲属身份证号` 的落库规则。
- `personId` 命中唯一亲属关系时导入成功。
- `personId` 未命中数据库和本轮成功亲属关系时,失败原因为“未找到亲属资产归属员工”。
- `personId` 命中多个员工归属时,失败原因为“亲属资产归属员工不唯一”。
- 只命中亲属关系 Sheet 失败行、且数据库中也不存在有效亲属关系时,资产行进入失败记录。
4. `/ccdi/staffFmyRelation/importData` 改为调用新的双 Sheet 提交方法,不再由 Controller 分别提交两个互相独立的异步任务。
### 结果状态
- 只填亲属关系 Sheet只返回 `relationTaskId`,行为保持不变。
- 只填亲属资产 Sheet只返回 `assetTaskId`,按数据库已有亲属关系校验。
- 两个 Sheet 都填写:返回 `relationTaskId``assetTaskId`,但后端在同一个编排任务中先处理亲属关系再处理亲属资产。
## 方案三:员工亲属实体关联自动补入实体库
### 当前问题链路
- 员工亲属实体关联新增只写入 `ccdi_staff_enterprise_relation`
- 员工亲属实体关联导入成功行也只写入 `ccdi_staff_enterprise_relation`
- 当前源码中没有可复用的实体库自动补入服务实现。
### 改造策略
新增后端内部服务 `EnterpriseAutoFillService`,统一处理缺失企业的最小插入。
1. 新增服务文件:
- `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/support/EnterpriseAutoFillService.java`
2. 服务方法:
- `ensureExists(EnterpriseFillItem item)`
- `ensureExistsBatch(List<EnterpriseFillItem> items)`
3. `EnterpriseFillItem` 字段:
- `socialCreditCode`
- `enterpriseName`
- `entSource`
- `dataSource`
- `userName`
4. 插入规则:
-`socialCreditCode` 去重。
- 先批量查询 `ccdi_enterprise_base_info` 已存在记录。
- 已存在实体不更新。
- 缺失实体最小插入:
- `social_credit_code = 统一社会信用代码`
- `enterprise_name = 企业名称`
- `ent_source = EMP_RELATION`
- `data_source = MANUAL``IMPORT`
- `risk_level = NULL`
- `create_by/update_by = 当前用户`
- 不引入额外兜底字段,不改变实体库手工新增规则。
5. 接入员工亲属实体关联新增:
-`CcdiStaffEnterpriseRelationServiceImpl#insertRelation` 中,亲属有效性校验和组合查重通过后,写关联表前调用:
- `entSource = EnterpriseSource.EMP_RELATION.getCode()`
- `dataSource = DataSource.MANUAL.getCode()`
6. 接入员工亲属实体关联导入:
-`CcdiStaffEnterpriseRelationImportServiceImpl#importRelationAsync` 中,只对校验成功并即将插入的 `newRecords` 组装补入列表。
- 批量写关联表前调用 `ensureExistsBatch`
- 失败行不进入实体库补入集合。
- `dataSource = DataSource.IMPORT.getCode()`
## 测试方案
### 单元测试
1. 员工信息维护双 Sheet
- 同一模板中员工 Sheet 新增员工,员工资产 Sheet 使用该员工身份证号,资产应导入成功。
- 员工 Sheet 行校验失败,资产 Sheet 使用该失败员工身份证号且数据库不存在,资产应失败。
- 只导资产 Sheet数据库已有员工时资产成功。
- 只导资产 Sheet数据库无员工时资产失败。
- 资产重复命中数据库或当前文件重复时失败。
2. 员工亲属关系维护双 Sheet
- 同一模板中亲属关系 Sheet 新增亲属,亲属资产 Sheet 使用该亲属证件号,资产应导入成功,并落库 `family_id = 员工身份证号`
- 亲属关系 Sheet 行校验失败,亲属资产 Sheet 使用该失败亲属证件号且数据库不存在,资产应失败。
- 只导亲属资产 Sheet数据库已有唯一有效亲属关系时资产成功。
- 只导亲属资产 Sheet数据库不存在亲属关系时资产失败。
- 同一亲属证件号命中多个员工归属时资产失败。
3. 员工亲属实体关联自动补入:
- 手工新增员工亲属实体关联成功时,缺失企业自动插入实体库,来源为 `EMP_RELATION`,数据来源为 `MANUAL`
- 手工新增时实体库已存在该统一社会信用代码,不更新实体库旧记录。
- 导入成功行自动插入实体库,来源为 `EMP_RELATION`,数据来源为 `IMPORT`
- 导入失败行不插入实体库。
- 同一批多个成功行引用同一统一社会信用代码,只补入一次。
### 接口验证
1. 调用 `/ccdi/baseStaff/importTemplate` 下载真实模板,构造:
- `员工信息` 新员工
- `员工资产信息` 引用该员工身份证号
- 上传 `/ccdi/baseStaff/importData`
- 轮询员工任务与资产任务,确认都成功
- 查询 `ccdi_base_staff``ccdi_asset_info`,确认员工和资产落库
2. 调用 `/ccdi/staffFmyRelation/importTemplate` 下载真实模板,构造:
- `员工亲属关系信息` 新亲属
- `亲属资产信息` 引用该亲属证件号
- 上传 `/ccdi/staffFmyRelation/importData`
- 轮询亲属关系任务与亲属资产任务,确认都成功
- 查询 `ccdi_staff_fmy_relation``ccdi_asset_info`,确认亲属关系和资产落库
3. 调用员工亲属实体关联新增接口:
- 新增前确认 `ccdi_enterprise_base_info` 不存在该统一社会信用代码
- 新增关联成功后查询实体库,确认自动生成企业记录
- 校验 `ent_source = EMP_RELATION`
### 页面验证
完成后需要使用真实业务页面验证:
1. 【员工信息维护】页面下载模板,按模板填写员工和员工资产,上传后检查任务状态、失败记录和列表详情。
2. 【员工亲属关系维护】页面下载模板,按模板填写亲属关系和亲属资产,上传后检查任务状态、失败记录和详情资产列表。
3. 【员工亲属实体关联】页面新增关系人与企业关联后,进入【实体库管理】查询该统一社会信用代码,确认企业已自动生成且来源显示为员工关系人。
测试结束后清理本轮新增员工、亲属关系、资产、员工亲属实体关联和自动补入实体库数据,并关闭测试过程中启动的前后端进程。
## 实施顺序
1. 抽取员工导入和亲属关系导入的可复用执行方法,返回成功主数据上下文和失败记录。
2. 新增员工信息维护双 Sheet 后端编排方法,接入 Controller。
3. 新增员工亲属关系维护双 Sheet 后端编排方法,接入 Controller。
4. 新增 `EnterpriseAutoFillService`
5. 员工亲属实体关联新增链路接入实体库自动补入。
6. 员工亲属实体关联导入链路接入实体库自动补入。
7. 补充单元测试。
8. 执行接口验证和真实页面验证。
9. 新增实施记录到 `docs/reports/implementation/`
## 风险点
- 双 Sheet 导入不能继续使用两个互相独立的异步任务,否则仍然存在主数据与资产任务执行顺序不确定的问题。
- 资产归属上下文必须只使用“数据库已有数据”和“本轮主 Sheet 成功数据”,不能把失败主数据作为资产归属。
- 实体库自动补入不能更新已存在企业,避免覆盖人工维护的企业名称、风险等级和来源信息。
- 员工亲属实体关联自动补入必须只处理成功行,失败行不能产生实体库记录。