回测四类导入自动补入实体库
This commit is contained in:
@@ -1,14 +1,13 @@
|
||||
package com.ruoyi.info.collection.service;
|
||||
|
||||
import com.ruoyi.info.collection.domain.CcdiBizIntermediary;
|
||||
import com.ruoyi.info.collection.domain.CcdiEnterpriseBaseInfo;
|
||||
import com.ruoyi.info.collection.domain.CcdiIntermediaryEnterpriseRelation;
|
||||
import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryEnterpriseRelationExcel;
|
||||
import com.ruoyi.info.collection.domain.vo.IntermediaryEnterpriseRelationImportFailureVO;
|
||||
import com.ruoyi.info.collection.mapper.CcdiBizIntermediaryMapper;
|
||||
import com.ruoyi.info.collection.mapper.CcdiEnterpriseBaseInfoMapper;
|
||||
import com.ruoyi.info.collection.mapper.CcdiIntermediaryEnterpriseRelationMapper;
|
||||
import com.ruoyi.info.collection.service.impl.CcdiIntermediaryEnterpriseRelationImportServiceImpl;
|
||||
import com.ruoyi.info.collection.service.support.EnterpriseAutoFillService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
@@ -23,6 +22,7 @@ import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.never;
|
||||
@@ -42,7 +42,7 @@ class CcdiIntermediaryEnterpriseRelationImportServiceImplTest {
|
||||
private CcdiBizIntermediaryMapper intermediaryMapper;
|
||||
|
||||
@Mock
|
||||
private CcdiEnterpriseBaseInfoMapper enterpriseBaseInfoMapper;
|
||||
private EnterpriseAutoFillService enterpriseAutoFillService;
|
||||
|
||||
@Mock
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
@@ -58,11 +58,11 @@ class CcdiIntermediaryEnterpriseRelationImportServiceImplTest {
|
||||
CcdiIntermediaryEnterpriseRelationExcel excel = buildExcel("320101199001010014", "91330100MA27X12345");
|
||||
prepareFailureRedisMocks();
|
||||
when(intermediaryMapper.selectList(any())).thenReturn(List.of());
|
||||
when(enterpriseBaseInfoMapper.selectList(any())).thenReturn(List.of(enterprise("91330100MA27X12345")));
|
||||
|
||||
service.importAsync(List.of(excel), "task-owner-miss", "tester");
|
||||
|
||||
verify(relationMapper, never()).insertBatch(any());
|
||||
verify(enterpriseAutoFillService, never()).ensureExistsBatch(any());
|
||||
IntermediaryEnterpriseRelationImportFailureVO failure =
|
||||
firstFailure("import:intermediary-enterprise-relation:task-owner-miss:failures");
|
||||
assertEquals("320101199001010014", failure.getOwnerPersonId());
|
||||
@@ -70,20 +70,20 @@ class CcdiIntermediaryEnterpriseRelationImportServiceImplTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void importEnterpriseRelationAsync_shouldFailWhenEnterpriseDoesNotExist() {
|
||||
void importEnterpriseRelationAsync_shouldAutoFillWhenEnterpriseDoesNotExist() {
|
||||
CcdiIntermediaryEnterpriseRelationExcel excel = buildExcel("320101199001010014", "91330100MA27X12345");
|
||||
prepareFailureRedisMocks();
|
||||
prepareStatusRedisMock();
|
||||
when(intermediaryMapper.selectList(any())).thenReturn(List.of(owner("owner-biz", "320101199001010014")));
|
||||
when(enterpriseBaseInfoMapper.selectList(any())).thenReturn(List.of());
|
||||
when(relationMapper.batchExistsByCombinations(any())).thenReturn(List.of());
|
||||
|
||||
service.importAsync(List.of(excel), "task-ent-miss", "tester");
|
||||
|
||||
verify(relationMapper, never()).insertBatch(any());
|
||||
IntermediaryEnterpriseRelationImportFailureVO failure =
|
||||
firstFailure("import:intermediary-enterprise-relation:task-ent-miss:failures");
|
||||
assertEquals("91330100MA27X12345", failure.getSocialCreditCode());
|
||||
assertTrue(failure.getErrorMessage().contains("机构表"));
|
||||
ArgumentCaptor<List<CcdiIntermediaryEnterpriseRelation>> relationCaptor = ArgumentCaptor.forClass(List.class);
|
||||
verify(relationMapper).insertBatch(relationCaptor.capture());
|
||||
assertEquals(1, relationCaptor.getValue().size());
|
||||
assertEquals("owner-biz", relationCaptor.getValue().get(0).getIntermediaryBizId());
|
||||
assertEquals("91330100MA27X12345", relationCaptor.getValue().get(0).getSocialCreditCode());
|
||||
assertIntermediaryAutoFill("91330100MA27X12345");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -96,10 +96,6 @@ class CcdiIntermediaryEnterpriseRelationImportServiceImplTest {
|
||||
owner("owner-biz-1", "320101199001010014"),
|
||||
owner("owner-biz-2", "320101199003030035")
|
||||
));
|
||||
when(enterpriseBaseInfoMapper.selectList(any())).thenReturn(List.of(
|
||||
enterprise("91330100MA27X12345"),
|
||||
enterprise("91330100MA27X12346")
|
||||
));
|
||||
when(relationMapper.batchExistsByCombinations(any())).thenReturn(List.of("owner-biz-1|91330100MA27X12345"));
|
||||
|
||||
service.importAsync(List.of(duplicateInDb, duplicateInFile1, duplicateInFile2), "task-duplicate", "tester");
|
||||
@@ -108,6 +104,7 @@ class CcdiIntermediaryEnterpriseRelationImportServiceImplTest {
|
||||
verify(relationMapper).insertBatch(captor.capture());
|
||||
assertEquals(1, captor.getValue().size());
|
||||
assertEquals("owner-biz-2", captor.getValue().get(0).getIntermediaryBizId());
|
||||
assertIntermediaryAutoFill("91330100MA27X12346");
|
||||
IntermediaryEnterpriseRelationImportFailureVO failure =
|
||||
firstFailure("import:intermediary-enterprise-relation:task-duplicate:failures");
|
||||
assertTrue(failure.getErrorMessage().contains("重复") || failure.getErrorMessage().contains("已存在"));
|
||||
@@ -118,7 +115,6 @@ class CcdiIntermediaryEnterpriseRelationImportServiceImplTest {
|
||||
CcdiIntermediaryEnterpriseRelationExcel excel = buildExcel("320101199001010014", "91330100MA27X12345");
|
||||
prepareStatusRedisMock();
|
||||
when(intermediaryMapper.selectList(any())).thenReturn(List.of(owner("owner-biz", "320101199001010014")));
|
||||
when(enterpriseBaseInfoMapper.selectList(any())).thenReturn(List.of(enterprise("91330100MA27X12345")));
|
||||
when(relationMapper.batchExistsByCombinations(any())).thenReturn(List.of());
|
||||
|
||||
service.importAsync(List.of(excel), "task-success", "tester");
|
||||
@@ -127,6 +123,7 @@ class CcdiIntermediaryEnterpriseRelationImportServiceImplTest {
|
||||
verify(relationMapper).insertBatch(captor.capture());
|
||||
assertEquals(1, captor.getValue().size());
|
||||
assertEquals("owner-biz", captor.getValue().get(0).getIntermediaryBizId());
|
||||
assertIntermediaryAutoFill("91330100MA27X12345");
|
||||
verify(valueOperations, never()).set(any(), any(), any(Long.class), any(TimeUnit.class));
|
||||
}
|
||||
|
||||
@@ -163,10 +160,15 @@ class CcdiIntermediaryEnterpriseRelationImportServiceImplTest {
|
||||
return owner;
|
||||
}
|
||||
|
||||
private CcdiEnterpriseBaseInfo enterprise(String socialCreditCode) {
|
||||
CcdiEnterpriseBaseInfo enterprise = new CcdiEnterpriseBaseInfo();
|
||||
enterprise.setSocialCreditCode(socialCreditCode);
|
||||
enterprise.setEnterpriseName("机构" + socialCreditCode.substring(socialCreditCode.length() - 2));
|
||||
return enterprise;
|
||||
private void assertIntermediaryAutoFill(String socialCreditCode) {
|
||||
ArgumentCaptor<List<EnterpriseAutoFillService.EnterpriseFillItem>> captor = ArgumentCaptor.forClass(List.class);
|
||||
verify(enterpriseAutoFillService).ensureExistsBatch(captor.capture());
|
||||
assertEquals(1, captor.getValue().size());
|
||||
EnterpriseAutoFillService.EnterpriseFillItem item = captor.getValue().get(0);
|
||||
assertEquals(socialCreditCode, item.socialCreditCode());
|
||||
assertNull(item.enterpriseName());
|
||||
assertEquals("INTERMEDIARY", item.entSource());
|
||||
assertEquals("IMPORT", item.dataSource());
|
||||
assertEquals("tester", item.userName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
# 四类关联业务自动补入实体库回测记录
|
||||
|
||||
## 保存路径确认
|
||||
|
||||
- 本次实施记录保存于 `docs/reports/implementation/`。
|
||||
|
||||
## 回测范围
|
||||
|
||||
- 员工亲属实体关联自动补入实体库。
|
||||
- 信贷客户实体关联自动补入实体库。
|
||||
- 中介关联机构自动补入实体库。
|
||||
- 招投标供应商自动补入实体库。
|
||||
|
||||
## 本次调整
|
||||
|
||||
- 修正中介实体关联导入单元测试的旧断言:实体库缺失时不再失败,成功行应调用 `EnterpriseAutoFillService` 自动补入,失败行不补入。
|
||||
- 修正本地供应商契约测试在 Maven 模块目录下读取仓库根 SQL 的路径口径。
|
||||
- 业务代码未调整。
|
||||
|
||||
## 单元回归
|
||||
|
||||
执行命令:
|
||||
|
||||
```bash
|
||||
mvn -pl ccdi-info-collection -am -Dtest=CcdiStaffEnterpriseRelationServiceImplTest,CcdiStaffEnterpriseRelationImportServiceImplTest,CcdiIntermediaryEnterpriseRelationImportServiceImplTest,CcdiIntermediaryServiceImplTest,CcdiPurchaseTransactionFeatureContractTest,CcdiEnterpriseBaseInfoImportServiceImplTest -Dsurefire.failIfNoSpecifiedTests=false test
|
||||
```
|
||||
|
||||
执行结果:
|
||||
|
||||
- `Tests run: 24, Failures: 0, Errors: 0, Skipped: 0`
|
||||
- `BUILD SUCCESS`
|
||||
|
||||
## 真实接口回测
|
||||
|
||||
后端启动:
|
||||
|
||||
```bash
|
||||
sh bin/restart_java_backend.sh restart
|
||||
```
|
||||
|
||||
本轮使用测试前缀 `RT20260506`,先通过 `bin/mysql_utf8_exec.sh` 写入员工亲属、信贷客户关系人、中介本人三类前置数据,再调用真实后端接口:
|
||||
|
||||
| 来源 | 接口 | 统一社会信用代码 | 接口结果 |
|
||||
| --- | --- | --- | --- |
|
||||
| 员工亲属 | `POST /ccdi/staffEnterpriseRelation` | `91330100RT20260501` | 操作成功 |
|
||||
| 信贷客户 | `POST /ccdi/custEnterpriseRelation` | `91330100RT20260502` | 操作成功 |
|
||||
| 中介 | `POST /ccdi/intermediary/RT20260506IM001/enterprise-relation` | `91330100RT20260503` | 操作成功 |
|
||||
| 供应商 | `POST /ccdi/purchaseTransaction` | `91330100RT20260504` | 操作成功 |
|
||||
|
||||
## 数据库回查
|
||||
|
||||
实体库回查结果:
|
||||
|
||||
| social_credit_code | enterprise_name | ent_source | data_source | risk_level | created_by |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `91330100RT20260501` | 回测员工亲属自动补入企业 | `EMP_RELATION` | `MANUAL` | `NULL` | `admin` |
|
||||
| `91330100RT20260502` | 回测信贷客户自动补入企业 | `CREDIT_CUSTOMER` | `MANUAL` | `NULL` | `admin` |
|
||||
| `91330100RT20260503` | `NULL` | `INTERMEDIARY` | `MANUAL` | `1` | `admin` |
|
||||
| `91330100RT20260504` | 回测供应商自动补入企业 | `SUPPLIER` | `MANUAL` | `NULL` | `admin` |
|
||||
|
||||
关系表回查:
|
||||
|
||||
- `ccdi_staff_enterprise_relation`:1 条
|
||||
- `ccdi_cust_enterprise_relation`:1 条
|
||||
- `ccdi_intermediary_enterprise_relation`:1 条
|
||||
- `ccdi_purchase_transaction_supplier`:1 条
|
||||
|
||||
## 清理结果
|
||||
|
||||
执行 `bin/mysql_utf8_exec.sh output/sql/2026-05-06-enterprise-autofill-retrotest-cleanup.sql` 后回查:
|
||||
|
||||
- `enterprise_rows=0`
|
||||
- `staff_relation_rows=0`
|
||||
- `cust_relation_rows=0`
|
||||
- `intermediary_relation_rows=0`
|
||||
- `purchase_rows=0`
|
||||
- `supplier_rows=0`
|
||||
|
||||
## 结论
|
||||
|
||||
- 四类来源均可通过真实接口自动补入 `ccdi_enterprise_base_info`。
|
||||
- 来源映射符合预期:员工亲属 `EMP_RELATION`、信贷客户 `CREDIT_CUSTOMER`、中介 `INTERMEDIARY`、供应商 `SUPPLIER`。
|
||||
- 中介来源风险等级自动落为 `1`,其余三类风险等级为空,符合既定规则。
|
||||
@@ -0,0 +1,102 @@
|
||||
# 关联业务导入接口自动补入实体库回测记录
|
||||
|
||||
## 基本信息
|
||||
|
||||
- 回测日期:2026-05-06
|
||||
- 回测范围:员工亲属实体关联、信贷客户实体关联、中介实体关联、招投标供应商四个导入接口
|
||||
- 文档保存路径:`docs/reports/implementation/2026-05-06-enterprise-autofill-import-retrotest.md`
|
||||
- 测试文件目录:`output/spreadsheet/import-retrotest/`
|
||||
- SQL 文件目录:`output/sql/`
|
||||
|
||||
## 回测准备
|
||||
|
||||
1. 使用 `sh bin/restart_java_backend.sh restart` 启动后端,后端运行端口为 `62318`。
|
||||
2. 使用 `bin/mysql_utf8_exec.sh output/sql/2026-05-06-enterprise-autofill-import-retrotest-seed.sql` 写入前置数据。
|
||||
3. 通过 `/login/test` 获取 `admin` 登录态。
|
||||
4. 从真实后端接口下载当前导入模板,并基于模板填充第 2 行测试数据:
|
||||
- `/ccdi/staffEnterpriseRelation/importTemplate`
|
||||
- `/ccdi/custEnterpriseRelation/importTemplate`
|
||||
- `/ccdi/intermediary/importEnterpriseRelationTemplate`
|
||||
- `/ccdi/purchaseTransaction/importTemplate`
|
||||
|
||||
## 导入接口回测结果
|
||||
|
||||
| 类型 | 导入接口 | 任务 ID | 状态 | 成功数 | 失败数 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 员工亲属 | `/ccdi/staffEnterpriseRelation/importData` | `934cf8b8-de56-4478-be9c-e2261652c993` | `SUCCESS` | 1 | 0 |
|
||||
| 信贷客户 | `/ccdi/custEnterpriseRelation/importData` | `5f21cd94-307e-4681-9659-64f3d270ef0a` | `SUCCESS` | 1 | 0 |
|
||||
| 中介 | `/ccdi/intermediary/importEnterpriseRelationData` | `9738837f-d657-4078-9d1d-6269ac35ecdc` | `SUCCESS` | 1 | 0 |
|
||||
| 供应商 | `/ccdi/purchaseTransaction/importData` | `0cc37465-98b6-4c98-88be-8b28cbe0f8db` | `SUCCESS` | 1 | 0 |
|
||||
|
||||
四个接口均使用 multipart `file` 参数上传基于真实模板生成的 Excel 文件,并轮询对应 `importStatus` 接口至最终状态。
|
||||
|
||||
## 实体库回查结果
|
||||
|
||||
使用 `bin/mysql_utf8_exec.sh output/sql/2026-05-06-enterprise-autofill-import-retrotest-verify.sql` 回查实体库与业务表。
|
||||
|
||||
| 统一社会信用代码 | 企业名称 | 企业来源 | 数据来源 | 风险等级 | 创建人 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `91330100RT20260601` | 导入回测员工亲属自动补入企业 | `EMP_RELATION` | `IMPORT` | `NULL` | `admin` |
|
||||
| `91330100RT20260602` | 导入回测信贷客户自动补入企业 | `CREDIT_CUSTOMER` | `IMPORT` | `NULL` | `admin` |
|
||||
| `91330100RT20260603` | `NULL` | `INTERMEDIARY` | `IMPORT` | `1` | `admin` |
|
||||
| `91330100RT20260604` | 导入回测供应商自动补入企业 | `SUPPLIER` | `IMPORT` | `NULL` | `admin` |
|
||||
|
||||
业务表回查结果:
|
||||
|
||||
| 检查项 | 记录数 |
|
||||
| --- | --- |
|
||||
| `staff_relation` | 1 |
|
||||
| `cust_relation` | 1 |
|
||||
| `intermediary_relation` | 1 |
|
||||
| `purchase_supplier` | 1 |
|
||||
|
||||
## 清理结果
|
||||
|
||||
使用 `bin/mysql_utf8_exec.sh output/sql/2026-05-06-enterprise-autofill-import-retrotest-cleanup.sql` 删除本轮导入数据、实体库补入数据和测试前置数据。
|
||||
|
||||
| 检查项 | 剩余记录数 |
|
||||
| --- | --- |
|
||||
| `enterprise_base_info` | 0 |
|
||||
| `staff_relation` | 0 |
|
||||
| `cust_relation` | 0 |
|
||||
| `intermediary_relation` | 0 |
|
||||
| `purchase_supplier` | 0 |
|
||||
| `purchase_transaction` | 0 |
|
||||
| `staff_family_seed` | 0 |
|
||||
| `intermediary_seed` | 0 |
|
||||
|
||||
## 保留导入数据复测
|
||||
|
||||
按用户要求保留导入 Excel 模板文件与导入数据后,重新执行一轮导入。本轮没有执行清理 SQL。
|
||||
|
||||
1. 确认 `output/spreadsheet/import-retrotest/` 下模板文件和导入文件均保留。
|
||||
2. 使用 `bin/mysql_utf8_exec.sh output/sql/2026-05-06-enterprise-autofill-import-retrotest-seed-keep-data.sql` 仅补充导入所需前置数据,该脚本不包含删除语句。
|
||||
3. 复用已保留的四个导入 Excel 文件上传导入接口。
|
||||
4. 使用 `bin/mysql_utf8_exec.sh output/sql/2026-05-06-enterprise-autofill-import-retrotest-verify.sql` 回查实体库与业务表,确认导入数据保留。
|
||||
|
||||
| 类型 | 导入接口 | 任务 ID | 状态 | 成功数 | 失败数 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 员工亲属 | `/ccdi/staffEnterpriseRelation/importData` | `da75f851-bc25-4930-8e0f-81dbfeb7e658` | `SUCCESS` | 1 | 0 |
|
||||
| 信贷客户 | `/ccdi/custEnterpriseRelation/importData` | `7eaa18da-aa69-41f6-90f5-acb74d63d1e6` | `SUCCESS` | 1 | 0 |
|
||||
| 中介 | `/ccdi/intermediary/importEnterpriseRelationData` | `ed9931f2-950e-4778-bf5d-d57d702015b8` | `SUCCESS` | 1 | 0 |
|
||||
| 供应商 | `/ccdi/purchaseTransaction/importData` | `0582c091-785c-4c71-af24-9f03375b86ea` | `SUCCESS` | 1 | 0 |
|
||||
|
||||
当前保留数据回查结果:
|
||||
|
||||
| 统一社会信用代码 | 企业名称 | 企业来源 | 数据来源 | 风险等级 | 创建人 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `91330100RT20260601` | 导入回测员工亲属自动补入企业 | `EMP_RELATION` | `IMPORT` | `NULL` | `admin` |
|
||||
| `91330100RT20260602` | 导入回测信贷客户自动补入企业 | `CREDIT_CUSTOMER` | `IMPORT` | `NULL` | `admin` |
|
||||
| `91330100RT20260603` | `NULL` | `INTERMEDIARY` | `IMPORT` | `1` | `admin` |
|
||||
| `91330100RT20260604` | 导入回测供应商自动补入企业 | `SUPPLIER` | `IMPORT` | `NULL` | `admin` |
|
||||
|
||||
| 检查项 | 当前记录数 |
|
||||
| --- | --- |
|
||||
| `staff_relation` | 1 |
|
||||
| `cust_relation` | 1 |
|
||||
| `intermediary_relation` | 1 |
|
||||
| `purchase_supplier` | 1 |
|
||||
|
||||
## 结论
|
||||
|
||||
员工亲属、信贷客户、中介、供应商四个导入接口均可以正常触发实体库自动补入。实体库来源、数据来源和风险等级与当前实现一致。按最新要求,导入 Excel 模板文件与导入数据已保留。
|
||||
Reference in New Issue
Block a user