Files
ccdi/assets/test-reports/2026-02-11-cust-fmy-relation-import-alignment-test.md
2026-03-03 16:14:16 +08:00

9.9 KiB

信贷客户家庭关系导入功能对齐测试报告

修改概述

本次修改将信贷客户家庭关系功能的导入实现完全对齐到员工亲属关系的成熟模式,提升了代码质量、性能和用户体验。

修改日期: 2026-02-11 参考模板: CcdiStaffEnterpriseRelationImportServiceImpl 修改对象: CcdiCustFmyRelationImportServiceImpl


修改文件清单

1. Mapper 层

文件: CcdiCustFmyRelationMapper.java

  • 新增 batchExistsByCombinations 方法接口
  • 支持批量查询已存在的关系组合

文件: CcdiCustFmyRelationMapper.xml

  • 实现 batchExistsByCombinations SQL
  • 优化:从 N 次查询减少到 1 次查询
<select id="batchExistsByCombinations" resultType="string">
    SELECT CONCAT(person_id, '|', relation_type, '|', relation_cert_no)
    FROM ccdi_cust_fmy_relation
    WHERE is_cust_family = 1 AND status = 1
      AND CONCAT(person_id, '|', relation_type, '|', relation_cert_no) IN
    <foreach collection="combinations" item="combo" open="(" separator="," close=")">
        #{combo}
    </foreach>
</select>

2. Service 层

文件: CcdiCustFmyRelationImportServiceImpl.java

  • 完全重构,参考员工亲属关系实现
  • 引入 ImportLogUtils 统一日志记录
  • 实现 getExistingCombinations 批量查询
  • 添加 Excel 内部重复检查
  • 优化 Redis 状态管理(Hash 结构)
  • 实现分批插入(每批500条)
  • 添加 getImportStatus 方法
  • 优化失败记录存储(JSON 序列化,7天过期)

文件: CcdiCustFmyRelationServiceImpl.java

  • 更新 importRelations 方法,传递 userName 参数
  • 初始化 Redis 状态为 Hash 结构
  • 使用 EasyExcelUtil 进行导出和模板下载
  • 添加数据量校验

3. Controller 层

文件: CcdiCustFmyRelationController.java

  • 导入接口返回 ImportResultVO 对象
  • 状态查询接口返回 ImportStatusVO 对象
  • 失败记录接口支持分页
  • 使用 EasyExcelUtil 工具类

4. VO 类

  • 复用 ImportStatusVO.java
  • 复用 ImportResultVO.java
  • 复用 CustFmyRelationImportFailureVO.java

5. Excel 实体

文件: CcdiCustFmyRelationExcel.java

  • 已包含完整的 @DictDropdown 注解
    • ccdi_relation_type (关系类型)
    • ccdi_indiv_gender (性别)
    • ccdi_certificate_type (证件类型)

核心改进点

1. 性能优化

项目 优化前 优化后 提升
唯一性检查 N 次数据库查询 1 次批量查询 约 90%
批量插入 无分批控制 每批 500 条 更稳定
导入1000条 预计 30-50秒 预计 10-15秒 约 60%

2. Redis 状态管理升级

优化前:

Key: import:custFmyRelation:{taskId}
Value: "COMPLETED:10:5"
TTL: 1 小时

优化后:

Key: import:custFmyRelation:{taskId}
Type: Hash
Fields:
  - taskId: "uuid"
  - status: "SUCCESS" | "PARTIAL_SUCCESS" | "PROCESSING"
  - totalCount: 100
  - successCount: 95
  - failureCount: 5
  - progress: 100
  - startTime: 1234567890
  - endTime: 1234567900
  - message: "成功95条,失败5条"
TTL: 7 天

3. 导入日志记录

使用 ImportLogUtils 统一记录:

  • 导入开始/结束
  • 批量查询日志
  • 进度跟踪
  • 验证错误详情
  • 批量操作日志
  • Redis 操作日志

4. 数据验证增强

  • 身份证号格式验证(18位)
  • 字段长度验证
  • Excel 内部重复检查
  • 数据库唯一性检查(批量)

测试指南

测试环境准备

  1. 启动后端服务 (mvn spring-boot:run)
  2. 确保数据库连接正常
  3. 确保 Redis 服务运行

测试步骤

1. 下载导入模板

POST /ccdi/custFmyRelation/importTemplate
Headers:
  Authorization: Bearer {token}

预期结果:

  • 返回 Excel 文件
  • 包含字典下拉框(关系类型、性别、证件类型)

2. 准备测试数据

创建包含以下字段的测试数据:

信贷客户身份证号 关系类型 关系人姓名 性别 关系人证件类型 关系人证件号码
110101199001011234 配偶 张三 身份证 110101199001011235
110101199001011234 子女 李四 身份证 110101201001011236

测试场景:

  • 正常数据导入
  • 重复数据导入(应返回错误)
  • Excel 内部重复(应检测并报错)
  • 必填字段缺失(应返回详细错误)

3. 提交导入任务

POST /ccdi/custFmyRelation/importData
Headers:
  Authorization: Bearer {token}
Form Data:
  file: 测试数据.xlsx

预期响应:

{
  "code": 200,
  "msg": "导入任务已提交,正在后台处理",
  "data": {
    "taskId": "uuid-string",
    "status": "PROCESSING",
    "message": "导入任务已提交,正在后台处理"
  }
}

4. 查询导入状态

GET /ccdi/custFmyRelation/importStatus/{taskId}
Headers:
  Authorization: Bearer {token}

预期响应:

{
  "taskId": "uuid-string",
  "status": "SUCCESS",
  "totalCount": 2,
  "successCount": 2,
  "failureCount": 0,
  "progress": 100,
  "message": "全部成功!共导入2条数据"
}

5. 查询失败记录

GET /ccdi/custFmyRelation/importFailures/{taskId}?pageNum=1&pageSize=10
Headers:
  Authorization: Bearer {token}

预期响应 (如果有失败):

{
  "total": 1,
  "rows": [
    {
      "rowNum": 2,
      "personId": "110101199001011234",
      "relationType": "配偶",
      "relationName": "张三",
      "errorMessage": "该关系已存在,请勿重复导入"
    }
  ],
  "code": 200,
  "msg": "查询成功"
}

自动化测试脚本

使用提供的测试脚本:

doc\test-scripts\test-cust-fmy-relation-import.bat

测试脚本功能:

  1. 登录获取 token
  2. 下载导入模板
  3. 提交导入任务
  4. 查询导入状态
  5. 查询失败记录
  6. 测试查询接口

验证清单

功能验证

  • 导入模板下载正常
  • 导入任务提交成功
  • 导入状态查询正常
  • 导入成功数据正确插入数据库
  • 重复数据被正确拦截
  • Excel 内部重复被检测
  • 失败记录正确保存到 Redis
  • 失败记录查询支持分页
  • 导入日志正常输出

性能验证

  • 导入 100 条数据 < 5 秒
  • 导入 1000 条数据 < 20 秒
  • 批量查询只执行 1 次 SQL
  • Redis 状态更新及时

日志验证

  • 导入开始日志
  • 批量查询日志
  • 进度日志
  • 验证错误日志
  • 批量操作日志
  • 导入完成日志

API 文档更新

导入相关接口

1. 下载导入模板

POST /ccdi/custFmyRelation/importTemplate
Authorization: Bearer {token}
Content-Type: application/json

Response: Excel 文件

2. 提交导入任务

POST /ccdi/custFmyRelation/importData
Authorization: Bearer {token}
Content-Type: multipart/form-data

Form Data:
  file: Excel 文件

Response:
{
  "code": 200,
  "msg": "导入任务已提交,正在后台处理",
  "data": {
    "taskId": "uuid",
    "status": "PROCESSING",
    "message": "导入任务已提交,正在后台处理"
  }
}

3. 查询导入状态

GET /ccdi/custFmyRelation/importStatus/{taskId}
Authorization: Bearer {token}

Response:
{
  "code": 200,
  "data": {
    "taskId": "uuid",
    "status": "SUCCESS",
    "totalCount": 100,
    "successCount": 95,
    "failureCount": 5,
    "progress": 100,
    "startTime": 1234567890,
    "endTime": 1234567900,
    "message": "成功95条,失败5条"
  }
}

4. 查询导入失败记录

GET /ccdi/custFmyRelation/importFailures/{taskId}?pageNum=1&pageSize=10
Authorization: Bearer {token}

Response:
{
  "code": 200,
  "total": 5,
  "rows": [...],
  "msg": "查询成功"
}

回归测试建议

测试场景

  1. 正常数据导入: 全部字段完整有效
  2. 必填字段缺失: 缺少 personId、relationType 等
  3. 格式错误: 身份证号格式不正确
  4. 数据重复:
    • 数据库中已存在
    • Excel 文件内重复
  5. 大数据量: 导入 1000+ 条数据
  6. 并发导入: 同时提交多个导入任务
  7. 边界情况: 空文件、单条数据、最大字段长度

性能基准

数据量 预期时间 最大内存
10 条 < 2 秒 < 50MB
100 条 < 5 秒 < 100MB
1000 条 < 20 秒 < 200MB
10000 条 < 3 分钟 < 500MB

注意事项

1. 字典配置

确保以下字典数据已配置:

  • ccdi_relation_type (关系类型)
  • ccdi_indiv_gender (性别)
  • ccdi_certificate_type (证件类型)

2. Redis 配置

  • 确保 Redis 服务运行
  • 检查 Redis 过期策略
  • 监控 Redis 内存使用

3. 异步配置

  • 确保 @EnableAsync 已启用
  • 检查异步线程池配置
  • 监控异步任务执行情况

4. 日志级别

  • 生产环境: INFO
  • 开发环境: DEBUG
  • 测试环境: DEBUG

后续优化建议

1. 导入进度实时推送

考虑使用 WebSocket 实现导入进度实时推送,替代轮询查询。

2. 导入历史记录

添加导入历史记录表,记录每次导入的详细信息,便于追溯。

3. 数据预校验

在前端添加数据预校验,提前发现格式错误,减少无效提交。

4. 导入模板智能生成

根据数据库字典动态生成导入模板,减少维护成本。

5. 批量操作优化

考虑使用 MyBatis Plus 的 SqlInjector 实现真正的批量插入。


创建日期

2026-02-11

相关文档