feat: Implement external job import functionality
- Add ExternalJobSourceAliasRequest class for managing source alias requests. - Create ExternalUploadClient to interact with external Excel upload system. - Introduce ExternalUploadFileMetadata to represent metadata of uploaded files. - Define IExternalJobImportService interface for external job import operations. - Update JobDataTrendServiceImpl to support dynamic source code filtering. - Modify PublicJobFairMapper.xml to ensure proper query handling. - Add unit tests for ExternalJobExcelParser and ExternalJobFingerprint. - Create script for applying external job import migrations. - Implement SQL migration for external job import, including new tables and columns.
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
package com.ruoyi.cms.externalimport;
|
||||
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class ExternalJobExcelParserTest {
|
||||
@Test
|
||||
void parsesExcelDatesAndLocationFallback() throws Exception {
|
||||
byte[] data = workbookBytes();
|
||||
List<ExternalJobCandidate> rows = new ExternalJobExcelParser().parse(new ByteArrayInputStream(data));
|
||||
|
||||
assertEquals(1, rows.size());
|
||||
ExternalJobCandidate row = rows.get(0);
|
||||
assertEquals("2026-07-14", row.getPostingDate());
|
||||
assertEquals("2026-07-20", row.getCollectDate());
|
||||
assertEquals("石河子市", row.getLocation());
|
||||
assertEquals("Java 工程师", row.getJobTitle());
|
||||
}
|
||||
|
||||
private byte[] workbookBytes() throws Exception {
|
||||
String[] headers = {"Aca112", "Acb22a", "SalaryLow", "SalaryHight", "Aae397", "AAB004", "ORG", "ACE760", "Collect_time", "City"};
|
||||
try (XSSFWorkbook workbook = new XSSFWorkbook(); ByteArrayOutputStream output = new ByteArrayOutputStream()) {
|
||||
Row header = workbook.createSheet("合并数据").createRow(0);
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
header.createCell(i).setCellValue(headers[i]);
|
||||
}
|
||||
Row data = workbook.getSheetAt(0).createRow(1);
|
||||
CellStyle dateStyle = workbook.createCellStyle();
|
||||
dateStyle.setDataFormat(workbook.getCreationHelper().createDataFormat().getFormat("yyyy-mm-dd"));
|
||||
data.createCell(0).setCellValue("Java 工程师");
|
||||
data.createCell(1).setCellValue("负责平台开发");
|
||||
data.createCell(2).setCellValue(5000);
|
||||
data.createCell(3).setCellValue(10000);
|
||||
data.createCell(4).setCellValue(Date.from(LocalDate.of(2026, 7, 14).atStartOfDay(java.time.ZoneId.systemDefault()).toInstant()));
|
||||
data.getCell(4).setCellStyle(dateStyle);
|
||||
data.createCell(5).setCellValue("示例企业");
|
||||
data.createCell(6).setCellValue("智联招聘");
|
||||
data.createCell(7).setCellValue("https://www.zhaopin.com/job/42");
|
||||
data.createCell(8).setCellValue(Date.from(LocalDate.of(2026, 7, 20).atStartOfDay(java.time.ZoneId.systemDefault()).toInstant()));
|
||||
data.getCell(8).setCellStyle(dateStyle);
|
||||
data.createCell(9).setCellValue("石河子市");
|
||||
workbook.write(output);
|
||||
return output.toByteArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.ruoyi.cms.externalimport;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
|
||||
class ExternalJobFingerprintTest {
|
||||
@Test
|
||||
void identityFingerprintIgnoresTrackingParametersAndMutableContent() {
|
||||
ExternalJobCandidate first = candidate("https://www.zhaopin.com/job/42/?utm_source=test&from=feed", "5000", "岗位描述一");
|
||||
ExternalJobCandidate changed = candidate("https://www.zhaopin.com/job/42?utm_campaign=summer", "7000", "岗位描述二");
|
||||
|
||||
assertEquals(ExternalJobFingerprint.identity(first), ExternalJobFingerprint.identity(changed));
|
||||
assertNotEquals(ExternalJobFingerprint.content(first), ExternalJobFingerprint.content(changed));
|
||||
}
|
||||
|
||||
@Test
|
||||
void identityFingerprintSeparatesDifferentSources() {
|
||||
ExternalJobCandidate zhaopin = candidate("https://www.zhaopin.com/job/42", "5000", "岗位描述");
|
||||
ExternalJobCandidate liepin = candidate("https://www.zhaopin.com/job/42", "5000", "岗位描述");
|
||||
liepin.setSourceCode("liepin");
|
||||
|
||||
assertNotEquals(ExternalJobFingerprint.identity(zhaopin), ExternalJobFingerprint.identity(liepin));
|
||||
}
|
||||
|
||||
private ExternalJobCandidate candidate(String url, String salary, String description) {
|
||||
ExternalJobCandidate candidate = new ExternalJobCandidate();
|
||||
candidate.setSourceCode("zhaopin");
|
||||
candidate.setCompanyName("石河子示例企业");
|
||||
candidate.setJobTitle("Java 工程师");
|
||||
candidate.setLocation("石河子市");
|
||||
candidate.setJobUrl(url);
|
||||
candidate.setSalaryLow(salary);
|
||||
candidate.setSalaryHigh("10000");
|
||||
candidate.setDescription(description);
|
||||
candidate.setEducationCode("3");
|
||||
candidate.setExperienceCode("4");
|
||||
candidate.setPostingDate("2026-07-20");
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user