Merge branch 'feat/staff-relation-import-person-id-validation' into dev_1

This commit is contained in:
wkc
2026-02-12 09:29:01 +08:00
6 changed files with 489 additions and 84 deletions

View File

@@ -1,12 +1,15 @@
package com.ruoyi.ccdi.service.impl;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.ccdi.domain.CcdiBaseStaff;
import com.ruoyi.ccdi.domain.CcdiStaffEnterpriseRelation;
import com.ruoyi.ccdi.domain.dto.CcdiStaffEnterpriseRelationAddDTO;
import com.ruoyi.ccdi.domain.excel.CcdiStaffEnterpriseRelationExcel;
import com.ruoyi.ccdi.domain.vo.ImportResult;
import com.ruoyi.ccdi.domain.vo.ImportStatusVO;
import com.ruoyi.ccdi.domain.vo.StaffEnterpriseRelationImportFailureVO;
import com.ruoyi.ccdi.mapper.CcdiBaseStaffMapper;
import com.ruoyi.ccdi.mapper.CcdiStaffEnterpriseRelationMapper;
import com.ruoyi.ccdi.service.ICcdiStaffEnterpriseRelationImportService;
import com.ruoyi.ccdi.utils.ImportLogUtils;
@@ -43,6 +46,9 @@ public class CcdiStaffEnterpriseRelationImportServiceImpl implements ICcdiStaffE
@Resource
private RedisTemplate<String, Object> redisTemplate;
@Resource
private CcdiBaseStaffMapper baseStaffMapper;
@Override
@Async
@Transactional
@@ -55,6 +61,28 @@ public class CcdiStaffEnterpriseRelationImportServiceImpl implements ICcdiStaffE
List<CcdiStaffEnterpriseRelation> newRecords = new ArrayList<>();
List<StaffEnterpriseRelationImportFailureVO> failures = new ArrayList<>();
// 批量验证员工身份证号是否存在
Set<String> excelPersonIds = excelList.stream()
.map(CcdiStaffEnterpriseRelationExcel::getPersonId)
.filter(StringUtils::isNotEmpty)
.collect(Collectors.toSet());
Set<String> existingPersonIds = new HashSet<>();
if (!excelPersonIds.isEmpty()) {
ImportLogUtils.logBatchQueryStart(log, taskId, "员工身份证号", excelPersonIds.size());
LambdaQueryWrapper<CcdiBaseStaff> wrapper = new LambdaQueryWrapper<>();
wrapper.select(CcdiBaseStaff::getIdCard)
.in(CcdiBaseStaff::getIdCard, excelPersonIds);
List<CcdiBaseStaff> existingStaff = baseStaffMapper.selectList(wrapper);
existingPersonIds = existingStaff.stream()
.map(CcdiBaseStaff::getIdCard)
.collect(Collectors.toSet());
ImportLogUtils.logBatchQueryComplete(log, taskId, "员工身份证号", existingPersonIds.size());
}
// 批量查询已存在的person_id + social_credit_code组合
ImportLogUtils.logBatchQueryStart(log, taskId, "已存在的员工企业关系组合", excelList.size());
Set<String> existingCombinations = getExistingCombinations(excelList);
@@ -75,6 +103,13 @@ public class CcdiStaffEnterpriseRelationImportServiceImpl implements ICcdiStaffE
// 验证数据
validateRelationData(addDTO);
// 身份证号存在性检查(在基本验证之后)
if (!existingPersonIds.contains(excel.getPersonId())) {
throw new RuntimeException(String.format(
"第%d行: 身份证号[%s]不存在于员工信息表中,请先添加员工信息",
i + 1, excel.getPersonId()));
}
String combination = excel.getPersonId() + "|" + excel.getSocialCreditCode();
CcdiStaffEnterpriseRelation relation = new CcdiStaffEnterpriseRelation();

View File

@@ -1,6 +1,8 @@
package com.ruoyi.ccdi.service.impl;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.ccdi.domain.CcdiBaseStaff;
import com.ruoyi.ccdi.domain.CcdiStaffFmyRelation;
import com.ruoyi.ccdi.domain.dto.CcdiStaffFmyRelationAddDTO;
import com.ruoyi.ccdi.domain.excel.CcdiStaffFmyRelationExcel;
@@ -8,6 +10,7 @@ import com.ruoyi.ccdi.domain.vo.ImportResult;
import com.ruoyi.ccdi.domain.vo.ImportStatusVO;
import com.ruoyi.ccdi.domain.vo.StaffFmyRelationImportFailureVO;
import com.ruoyi.ccdi.enums.GenderEnum;
import com.ruoyi.ccdi.mapper.CcdiBaseStaffMapper;
import com.ruoyi.ccdi.mapper.CcdiStaffFmyRelationMapper;
import com.ruoyi.ccdi.service.ICcdiStaffFmyRelationImportService;
import com.ruoyi.ccdi.utils.ImportLogUtils;
@@ -24,6 +27,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* 员工亲属关系异步导入服务层处理
@@ -43,6 +47,9 @@ public class CcdiStaffFmyRelationImportServiceImpl implements ICcdiStaffFmyRelat
@Resource
private RedisTemplate<String, Object> redisTemplate;
@Resource
private CcdiBaseStaffMapper baseStaffMapper;
@Override
@Async
@Transactional
@@ -55,14 +62,32 @@ public class CcdiStaffFmyRelationImportServiceImpl implements ICcdiStaffFmyRelat
List<CcdiStaffFmyRelation> newRecords = new ArrayList<>();
List<StaffFmyRelationImportFailureVO> failures = new ArrayList<>();
// 批量验证员工身份证号是否存在
Set<String> excelPersonIds = excelList.stream()
.map(CcdiStaffFmyRelationExcel::getPersonId)
.filter(StringUtils::isNotEmpty)
.collect(Collectors.toSet());
Set<String> existingPersonIds = new HashSet<>();
if (!excelPersonIds.isEmpty()) {
ImportLogUtils.logBatchQueryStart(log, taskId, "员工身份证号", excelPersonIds.size());
LambdaQueryWrapper<CcdiBaseStaff> wrapper = new LambdaQueryWrapper<>();
wrapper.select(CcdiBaseStaff::getIdCard)
.in(CcdiBaseStaff::getIdCard, excelPersonIds);
List<CcdiBaseStaff> existingStaff = baseStaffMapper.selectList(wrapper);
existingPersonIds = existingStaff.stream()
.map(CcdiBaseStaff::getIdCard)
.collect(Collectors.toSet());
ImportLogUtils.logBatchQueryComplete(log, taskId, "员工身份证号", existingPersonIds.size());
}
// ========== 第一步:批量唯一性校验 ==========
// 1. 提取Excel中所有的personId和relationCertNo
Set<String> excelPersonIds = new HashSet<>();
// 1. 提取Excel中所有的relationCertNopersonId已在前面提取
Set<String> excelRelationCertNos = new HashSet<>();
for (CcdiStaffFmyRelationExcel excel : excelList) {
if (StringUtils.isNotEmpty(excel.getPersonId())) {
excelPersonIds.add(excel.getPersonId());
}
if (StringUtils.isNotEmpty(excel.getRelationCertNo())) {
excelRelationCertNos.add(excel.getRelationCertNo());
}
@@ -70,7 +95,7 @@ public class CcdiStaffFmyRelationImportServiceImpl implements ICcdiStaffFmyRelat
// 2. 批量查询数据库中已存在的记录
Set<String> existingKeys = new HashSet<>();
if (!excelPersonIds.isEmpty() && !excelRelationCertNos.isEmpty()) {
if (!excelRelationCertNos.isEmpty()) {
ImportLogUtils.logBatchQueryStart(log, taskId, "已存在的亲属关系", excelList.size());
List<CcdiStaffFmyRelation> existingRecords = relationMapper.selectExistingRelations(
new ArrayList<>(excelPersonIds),
@@ -100,6 +125,13 @@ public class CcdiStaffFmyRelationImportServiceImpl implements ICcdiStaffFmyRelat
// 验证数据
validateRelationData(addDTO);
// 身份证号存在性检查(在基本验证之后)
if (!existingPersonIds.contains(excel.getPersonId())) {
throw new RuntimeException(String.format(
"第%d行: 身份证号[%s]不存在于员工信息表中,请先添加员工信息",
i + 1, excel.getPersonId()));
}
// 生成唯一键
String uniqueKey = excel.getPersonId() + "|" + excel.getRelationCertNo();

View File

@@ -65,8 +65,27 @@ public class CcdiStaffTransferImportServiceImpl implements ICcdiStaffTransferImp
List<CcdiStaffTransfer> newRecords = new ArrayList<>();
List<StaffTransferImportFailureVO> failures = new ArrayList<>();
// 批量验证员工ID是否存在
Set<Long> existingStaffIds = batchValidateStaffIds(excelList, taskId, failures);
// 批量查询员工ID存在
Set<Long> excelStaffIds = excelList.stream()
.map(CcdiStaffTransferExcel::getStaffId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
Set<Long> existingStaffIds = new HashSet<>();
if (!excelStaffIds.isEmpty()) {
ImportLogUtils.logBatchQueryStart(log, taskId, "员工ID", excelStaffIds.size());
LambdaQueryWrapper<CcdiBaseStaff> wrapper = new LambdaQueryWrapper<>();
wrapper.select(CcdiBaseStaff::getStaffId)
.in(CcdiBaseStaff::getStaffId, excelStaffIds);
List<CcdiBaseStaff> existingStaff = baseStaffMapper.selectList(wrapper);
existingStaffIds = existingStaff.stream()
.map(CcdiBaseStaff::getStaffId)
.collect(Collectors.toSet());
ImportLogUtils.logBatchQueryComplete(log, taskId, "员工ID", existingStaffIds.size());
}
// 批量查询已存在的唯一键组合
ImportLogUtils.logBatchQueryStart(log, taskId, "已存在的调动记录", excelList.size());
@@ -80,12 +99,14 @@ public class CcdiStaffTransferImportServiceImpl implements ICcdiStaffTransferImp
for (int i = 0; i < excelList.size(); i++) {
CcdiStaffTransferExcel excel = excelList.get(i);
// 跳过已在预验证阶段失败的记录
if (isRowAlreadyFailed(excel, failures)) {
continue;
}
try {
// 员工ID存在性检查
if (excel.getStaffId() != null && !existingStaffIds.contains(excel.getStaffId())) {
throw new RuntimeException(String.format(
"第%d行: 员工ID %s 不存在",
i + 1, excel.getStaffId()));
}
// 转换为AddDTO进行验证
CcdiStaffTransferAddDTO addDTO = new CcdiStaffTransferAddDTO();
BeanUtils.copyProperties(excel, addDTO);
@@ -356,75 +377,4 @@ public class CcdiStaffTransferImportServiceImpl implements ICcdiStaffTransferImp
return JSON.parseArray(JSON.toJSONString(failuresObj), StaffTransferImportFailureVO.class);
}
/**
* 批量验证员工ID是否存在
*
* @param excelList Excel数据列表
* @param taskId 任务ID
* @param failures 失败记录列表(会追加验证失败的记录)
* @return 存在的员工ID集合
*/
private Set<Long> batchValidateStaffIds(List<CcdiStaffTransferExcel> excelList,
String taskId,
List<StaffTransferImportFailureVO> failures) {
// 1. 提取并去重员工ID
Set<Long> allStaffIds = excelList.stream()
.map(CcdiStaffTransferExcel::getStaffId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
if (allStaffIds.isEmpty()) {
return Collections.emptySet();
}
// 2. 批量查询存在的员工ID
ImportLogUtils.logBatchQueryStart(log, taskId, "员工ID", allStaffIds.size());
LambdaQueryWrapper<CcdiBaseStaff> wrapper = new LambdaQueryWrapper<>();
wrapper.select(CcdiBaseStaff::getStaffId)
.in(CcdiBaseStaff::getStaffId, allStaffIds);
List<CcdiBaseStaff> existingStaff = baseStaffMapper.selectList(wrapper);
Set<Long> existingStaffIds = existingStaff.stream()
.map(CcdiBaseStaff::getStaffId)
.collect(Collectors.toSet());
ImportLogUtils.logBatchQueryComplete(log, taskId, "员工ID", existingStaffIds.size());
// 3. 预验证并标记不存在的员工ID
for (int i = 0; i < excelList.size(); i++) {
CcdiStaffTransferExcel excel = excelList.get(i);
Long staffId = excel.getStaffId();
if (staffId != null && !existingStaffIds.contains(staffId)) {
StaffTransferImportFailureVO failure = new StaffTransferImportFailureVO();
BeanUtils.copyProperties(excel, failure);
failure.setErrorMessage(String.format("第%d行: 员工ID %s 不存在", i + 1, staffId));
failures.add(failure);
String keyData = String.format("员工ID=%s", staffId);
ImportLogUtils.logValidationError(log, taskId, i + 1,
failure.getErrorMessage(), keyData);
}
}
return existingStaffIds;
}
/**
* 检查某行数据是否已在失败列表中
*
* @param excel Excel数据
* @param failures 失败记录列表
* @return true-已失败false-未失败
*/
private boolean isRowAlreadyFailed(CcdiStaffTransferExcel excel,
List<StaffTransferImportFailureVO> failures) {
return failures.stream()
.anyMatch(f -> Objects.equals(f.getStaffId(), excel.getStaffId())
&& Objects.equals(f.getTransferDate(), excel.getTransferDate())
&& Objects.equals(f.getDeptIdBefore(), excel.getDeptIdBefore())
&& Objects.equals(f.getDeptIdAfter(), excel.getDeptIdAfter()));
}
}