完成招聘双Sheet导入改造

This commit is contained in:
wkc
2026-04-23 10:27:08 +08:00
parent 110817abba
commit a2ba044ebe
14 changed files with 838 additions and 467 deletions

View File

@@ -0,0 +1,64 @@
package com.ruoyi.info.collection.service;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Path;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
class CcdiStaffRecruitmentDualImportContractTest {
@Test
void shouldExposeSingleDualSheetImportEntry() throws Exception {
String controller = Files.readString(
Path.of("src/main/java/com/ruoyi/info/collection/controller/CcdiStaffRecruitmentController.java")
);
assertTrue(controller.contains("\"招聘信息\""));
assertTrue(controller.contains("\"历史工作经历\""));
assertFalse(controller.contains("workImportTemplate"));
assertFalse(controller.contains("importWorkData"));
String service = Files.readString(
Path.of("src/main/java/com/ruoyi/info/collection/service/ICcdiStaffRecruitmentService.java")
);
assertTrue(service.contains("String importRecruitment("));
assertTrue(service.contains("List<CcdiStaffRecruitmentExcel> recruitmentList"));
assertTrue(service.contains("List<CcdiStaffRecruitmentWorkExcel> workList"));
assertFalse(service.contains("importRecruitmentWork("));
String importService = Files.readString(
Path.of("src/main/java/com/ruoyi/info/collection/service/ICcdiStaffRecruitmentImportService.java")
);
assertTrue(importService.contains("void importRecruitmentAsync("));
assertTrue(importService.contains("List<CcdiStaffRecruitmentExcel> recruitmentList"));
assertTrue(importService.contains("List<CcdiStaffRecruitmentWorkExcel> workList"));
assertFalse(importService.contains("importRecruitmentWorkAsync("));
}
@Test
void shouldExposeFailureSheetFieldsAndSingleTaskInit() throws Exception {
assertHasField(
"com.ruoyi.info.collection.domain.vo.RecruitmentImportFailureVO",
"sheetName"
);
assertHasField(
"com.ruoyi.info.collection.domain.vo.RecruitmentImportFailureVO",
"sheetRowNum"
);
String serviceImpl = Files.readString(
Path.of("src/main/java/com/ruoyi/info/collection/service/impl/CcdiStaffRecruitmentServiceImpl.java")
);
assertTrue(serviceImpl.contains("recruitmentList.size() + workList.size()"));
assertFalse(serviceImpl.contains("importRecruitmentWork("));
}
private void assertHasField(String className, String fieldName) throws Exception {
Class<?> clazz = Class.forName(className);
Field field = clazz.getDeclaredField(fieldName);
assertNotNull(field);
}
}

View File

@@ -0,0 +1,98 @@
package com.ruoyi.info.collection.service;
import com.ruoyi.info.collection.domain.CcdiStaffRecruitment;
import com.ruoyi.info.collection.domain.excel.CcdiStaffRecruitmentWorkExcel;
import com.ruoyi.info.collection.domain.vo.RecruitmentImportFailureVO;
import com.ruoyi.info.collection.mapper.CcdiStaffRecruitmentMapper;
import com.ruoyi.info.collection.mapper.CcdiStaffRecruitmentWorkMapper;
import com.ruoyi.info.collection.service.impl.CcdiStaffRecruitmentImportServiceImpl;
import java.util.Collections;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class CcdiStaffRecruitmentImportServiceImplTest {
@InjectMocks
private CcdiStaffRecruitmentImportServiceImpl service;
@Mock
private CcdiStaffRecruitmentMapper recruitmentMapper;
@Mock
private CcdiStaffRecruitmentWorkMapper recruitmentWorkMapper;
@Mock
private RedisTemplate<String, Object> redisTemplate;
@Mock
private ValueOperations<String, Object> valueOperations;
@Mock
private HashOperations<String, Object, Object> hashOperations;
@Test
void shouldFailWholeWorkGroupWhenExistingHistoryExists() {
when(redisTemplate.opsForValue()).thenReturn(valueOperations);
when(redisTemplate.opsForHash()).thenReturn(hashOperations);
when(recruitmentMapper.selectBatchIds(any())).thenReturn(List.of(buildRecruitment("RC001")));
when(recruitmentWorkMapper.selectCount(any())).thenReturn(1L);
CcdiStaffRecruitmentWorkExcel workRow = new CcdiStaffRecruitmentWorkExcel();
workRow.setRecruitId("RC001");
workRow.setCandName("张三");
workRow.setRecruitName("社会招聘项目");
workRow.setPosName("Java工程师");
workRow.setSortOrder(1);
workRow.setCompanyName("测试科技");
workRow.setPositionName("开发工程师");
workRow.setJobStartMonth("2022-01");
service.importRecruitmentAsync(Collections.emptyList(), List.of(workRow), "task-1", "admin");
verify(recruitmentWorkMapper, never()).delete(any());
verify(recruitmentWorkMapper, never()).insert(any(com.ruoyi.info.collection.domain.CcdiStaffRecruitmentWork.class));
ArgumentCaptor<Object> failureCaptor = ArgumentCaptor.forClass(Object.class);
verify(valueOperations).set(eq("import:recruitment:task-1:failures"), failureCaptor.capture(), anyLong(), any());
Object rawFailures = failureCaptor.getValue();
assertNotNull(rawFailures);
assertInstanceOf(List.class, rawFailures);
List<?> failures = (List<?>) rawFailures;
assertFalse(failures.isEmpty());
RecruitmentImportFailureVO failure = (RecruitmentImportFailureVO) failures.get(0);
assertEquals("历史工作经历", failure.getSheetName());
assertEquals("2", failure.getSheetRowNum());
assertEquals("招聘记录编号[RC001]已存在历史工作经历,不允许重复导入", failure.getErrorMessage());
}
private CcdiStaffRecruitment buildRecruitment(String recruitId) {
CcdiStaffRecruitment recruitment = new CcdiStaffRecruitment();
recruitment.setRecruitId(recruitId);
recruitment.setRecruitType("SOCIAL");
recruitment.setCandName("张三");
recruitment.setRecruitName("社会招聘项目");
recruitment.setPosName("Java工程师");
return recruitment;
}
}

View File

@@ -4,6 +4,8 @@ import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.info.collection.domain.excel.CcdiBaseStaffExcel;
import com.ruoyi.info.collection.domain.excel.CcdiAssetInfoExcel;
import com.ruoyi.info.collection.domain.excel.CcdiStaffRecruitmentExcel;
import com.ruoyi.info.collection.domain.excel.CcdiStaffRecruitmentWorkExcel;
import com.ruoyi.info.collection.domain.excel.CcdiStaffFmyRelationExcel;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataValidation;
@@ -98,6 +100,35 @@ class EasyExcelUtilTemplateTest {
}
}
@Test
void importTemplateWithDictDropdown_shouldCreateRecruitmentDualSheetTemplate() throws Exception {
MockHttpServletResponse response = new MockHttpServletResponse();
try (MockedStatic<DictUtils> mocked = mockStatic(DictUtils.class)) {
mocked.when(() -> DictUtils.getDictCache("ccdi_admit_status"))
.thenReturn(List.of(
buildDictData("录用"),
buildDictData("未录用"),
buildDictData("放弃")
));
EasyExcelUtil.importTemplateWithDictDropdown(
response,
CcdiStaffRecruitmentExcel.class,
"招聘信息",
CcdiStaffRecruitmentWorkExcel.class,
"历史工作经历",
"招聘信息管理导入模板"
);
}
try (Workbook workbook = WorkbookFactory.create(new ByteArrayInputStream(response.getContentAsByteArray()))) {
assertEquals(2, workbook.getNumberOfSheets(), "招聘导入模板应输出双Sheet");
assertEquals("招聘信息", workbook.getSheetAt(0).getSheetName());
assertEquals("历史工作经历", workbook.getSheetAt(1).getSheetName());
}
}
private void assertTextColumn(Sheet sheet, int columnIndex) {
CellStyle style = sheet.getColumnStyle(columnIndex);
assertNotNull(style, "文本列应设置默认样式");