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

16 KiB
Raw Blame History

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

1. 背景

本设计用于修复以下后端问题:

  1. 【员工信息维护】双 Sheet 导入时,员工资产信息 Sheet 只能通过数据库已有员工反查归属,不能识别同一个导入文件中刚成功导入的员工。
  2. 【员工亲属关系维护】双 Sheet 导入时,亲属资产信息 Sheet 只能通过数据库已有亲属关系反查归属,不能识别同一个导入文件中刚成功导入的亲属关系。
  3. 关联业务自动补入实体库能力在当前主工作区未完整接回,员工亲属、信贷客户、中介、供应商四类业务成功关联后,缺失企业需要统一补入 ccdi_enterprise_base_info

本次设计只涉及后端。不调整前端页面结构、上传入口、模板样式和前端轮询字段。

2. 目标

  • 双 Sheet 导入时,主 Sheet 与资产 Sheet 在后端按业务依赖顺序执行。
  • 资产 Sheet 可关联数据库已有主数据,也可关联同一文件中本轮主 Sheet 成功导入的数据。
  • 主 Sheet 失败行不能作为资产归属依据。
  • 继续返回当前前端已支持的两个任务 ID
    • 员工信息维护:staffTaskIdassetTaskId
    • 员工亲属关系维护:relationTaskIdassetTaskId
  • 恢复统一 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

实体库缺失时最小插入;已存在时不更新。

供应商来源需要同步新增后端枚举 EnterpriseSource.SUPPLIER("SUPPLIER", "供应商"),并补充 /ccdi/enum/enterpriseSource 枚举接口测试。前端继续通过现有枚举接口展示来源,不需要调整页面结构。

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 是正常导入场景,不因 员工信息 Sheet 为空或未填写而拦截。
  • 两个 Sheet 都填:返回 staffTaskIdassetTaskId,后台保证员工先处理、资产后处理。
  • 员工主 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. 亲属资产归属候选来源为:
    • 数据库已有员工亲属关系,沿用现有 owner 查询条件
    • 本轮亲属关系 Sheet 成功导入的员工亲属关系
  8. 亲属资产落库继续保持:
    • family_id = 员工身份证号
    • person_id = 亲属身份证号

6.3 任务状态

  • 只填亲属关系 Sheet只返回 relationTaskId
  • 只填亲属资产 Sheet只返回 assetTaskId,只按数据库已有员工亲属关系校验,并沿用现有 owner 查询条件。
  • 只填亲属资产 Sheet 是正常导入场景,不因 员工亲属关系信息 Sheet 为空或未填写而拦截。
  • 两个 Sheet 都填:返回 relationTaskIdassetTaskId,后台保证亲属关系先处理、资产后处理。
  • 亲属关系主 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 = 企业名称;中介实体关联缺失实体时允许为 NULL
    • ent_source = 来源
    • data_source = MANUAL 或 IMPORT
    • risk_level = 来源规则值
    • created_by/updated_by = 当前用户
  5. 中介实体关联缺失实体时不要求提供机构名称,补入实体的 enterprise_name 可以为 NULL
  6. 中介来源 INTERMEDIARYrisk_level = 1
  7. 员工亲属、信贷客户、供应商来源写 risk_level = NULL
  8. 并发导致主键重复时,按“已存在实体”处理。
  9. 其他数据库异常抛出,让当前业务事务失败。

7.3 四类业务接入点

员工亲属实体关联:

  • 手工新增:校验有效亲属和组合不重复后、插入关联表前补入。
  • 导入:只对校验成功并即将插入的记录批量补入。
  • 来源:EMP_RELATION
  • 数据来源:手工新增为 MANUAL,导入为 IMPORT
  • 风险等级:NULL

信贷客户实体关联:

  • 手工新增:校验通过后、插入关联表前补入。
  • 导入:只对校验成功并即将插入的记录批量补入。
  • 来源:CREDIT_CUSTOMER
  • 数据来源:手工新增为 MANUAL,导入为 IMPORT
  • 风险等级:NULL

中介实体关联:

  • 手工新增:字段校验和重复关系校验通过后,取消或替换“实体库必须已存在”校验,先补入实体库,再插入关联关系。
  • 导入:字段校验和重复关系校验通过后,取消或替换“实体库必须已存在”失败条件,只对即将插入的成功记录批量补入。
  • 来源:INTERMEDIARY
  • 数据来源:手工新增为 MANUAL,导入为 IMPORT
  • 风险等级:1

招投标供应商:

  • 手工新增或保存招投标主信息时,只对 supplierUscc 非空且通过现有格式校验的供应商补入。
  • 导入:只对成功采购事项中 supplierUscc 非空且通过现有格式校验的供应商批量补入,失败采购事项不补入。
  • 导入中 supplierUscc 为空的供应商保持现有保存规则,但不补入实体库。
  • 来源:SUPPLIER
  • 数据来源:手工新增为 MANUAL,导入为 IMPORT
  • 风险等级:NULL

8. 错误处理与边界

8.1 双 Sheet 导入边界

  • 主 Sheet 失败行不能进入资产归属候选。
  • 主 Sheet 文件内重复行不能进入资产归属候选。
  • 主 Sheet 数据库重复行不能进入资产归属候选。
  • 主 Sheet 为空但资产 Sheet 有数据时,资产 Sheet 必须按现有独立资产导入规则正常执行。
  • 资产 Sheet 仍按自身失败记录任务记录 sheetNamerowNumerrorMessage
  • 员工资产找不到员工时继续报“员工资产导入仅支持员工本人证件号”。
  • 亲属资产找不到归属时继续报“未找到亲属资产归属员工”。
  • 亲属资产命中多个归属时继续报“亲属资产归属员工不唯一”。
  • 亲属资产数据库归属查询条件沿用当前实现,不因本次编排新增额外状态过滤。

8.2 自动补入边界

  • 只处理业务校验成功、即将落库的记录。
  • 失败业务行不能产生实体库记录。
  • 已存在实体不更新,避免覆盖人工维护数据。
  • 不增加默认企业名称、默认来源、默认风险等级等兜底逻辑。
  • 不改变实体库导入的严格新增规则。
  • 中介实体关联的“实体库必须已存在”校验需要被自动补入替换,否则缺失实体无法进入补入链路。
  • 中介实体关联不新增机构名称入参;缺失实体补入时允许 enterprise_name = NULL
  • 供应商自动补入只处理非空统一社会信用代码,空统一社会信用代码不改变原导入保存规则。

9. 测试设计

9.1 单元测试

员工信息维护双 Sheet

  • 同一模板中新员工和员工资产同时导入,资产引用新员工身份证号,资产成功。
  • 员工 Sheet 行校验失败,资产引用该身份证号且数据库不存在,资产失败。
  • 员工信息 Sheet 为空或未填写,员工资产 Sheet 引用数据库已有员工时,资产成功导入。
  • 只导员工资产,数据库已有员工时成功。
  • 只导员工资产,数据库无员工时失败。
  • 资产重复命中数据库或当前文件重复时失败。

员工亲属关系维护双 Sheet

  • 同一模板中新亲属关系和亲属资产同时导入,资产引用新亲属证件号,资产成功。
  • 亲属关系 Sheet 行校验失败,资产引用该亲属证件号且数据库不存在,资产失败。
  • 员工亲属关系信息 Sheet 为空或未填写,亲属资产 Sheet 引用数据库已有员工亲属关系时,资产成功导入。
  • 只导亲属资产,数据库已有唯一员工亲属关系时成功。
  • 只导亲属资产,数据库不存在亲属关系时失败。
  • 同一亲属证件号命中多个员工归属时失败。

实体库自动补入:

  • 已存在实体不插入、不更新。
  • 缺失实体插入最小记录。
  • 同批多个成功行引用同一统一社会信用代码,只补入一次。
  • 中介来源写 riskLevel=1
  • 员工亲属、信贷客户、供应商来源写 riskLevel=null
  • 后端枚举接口返回 SUPPLIER/供应商
  • 并发重复主键按已存在处理。

四类业务接入:

  • 手工新增成功时调用自动补入。
  • 导入成功行进入自动补入集合。
  • 导入失败行不进入自动补入集合。

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 失败行放入资产归属上下文,否则会产生脏资产。
  • 不能更新已存在实体库记录,否则会覆盖人工维护的企业名称、风险等级和来源。
  • 自动补入必须在业务记录落库前执行,并与业务事务保持一致。
  • 四类自动补入必须只处理成功业务行,失败行不能污染实体库。