Merge branch 'feat/staff-transfer-staff-id-validation' into dev_1
功能: 员工调动导入员工ID校验 新增功能: - 批量预验证员工ID存在性(1次数据库查询) - 错误信息包含Excel行号 - 主循环跳过已失败记录 - 完整的日志记录 技术实现: - 添加 CcdiBaseStaffMapper 依赖注入 - 新增 batchValidateStaffIds() 方法 - 新增 isRowAlreadyFailed() 方法 - 修改 importTransferAsync() 主流程 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -29,6 +29,14 @@ public class StaffTransferImportFailureVO implements Serializable {
|
||||
@Schema(description = "员工姓名")
|
||||
private String staffName;
|
||||
|
||||
/** 调动前部门ID */
|
||||
@Schema(description = "调动前部门ID")
|
||||
private Long deptIdBefore;
|
||||
|
||||
/** 调动后部门ID */
|
||||
@Schema(description = "调动后部门ID")
|
||||
private Long deptIdAfter;
|
||||
|
||||
/** 调动类型 */
|
||||
@Schema(description = "调动类型")
|
||||
private String transferType;
|
||||
|
||||
@@ -2,12 +2,14 @@ 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.CcdiStaffTransfer;
|
||||
import com.ruoyi.ccdi.domain.dto.CcdiStaffTransferAddDTO;
|
||||
import com.ruoyi.ccdi.domain.excel.CcdiStaffTransferExcel;
|
||||
import com.ruoyi.ccdi.domain.vo.ImportResult;
|
||||
import com.ruoyi.ccdi.domain.vo.ImportStatusVO;
|
||||
import com.ruoyi.ccdi.domain.vo.StaffTransferImportFailureVO;
|
||||
import com.ruoyi.ccdi.mapper.CcdiBaseStaffMapper;
|
||||
import com.ruoyi.ccdi.mapper.CcdiStaffTransferMapper;
|
||||
import com.ruoyi.ccdi.service.ICcdiStaffTransferImportService;
|
||||
import com.ruoyi.ccdi.utils.ImportLogUtils;
|
||||
@@ -16,8 +18,7 @@ import com.ruoyi.common.utils.DictUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.system.mapper.SysDeptMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
@@ -35,12 +36,11 @@ import java.util.stream.Collectors;
|
||||
* @author ruoyi
|
||||
* @date 2026-02-10
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@EnableAsync
|
||||
public class CcdiStaffTransferImportServiceImpl implements ICcdiStaffTransferImportService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(CcdiStaffTransferImportServiceImpl.class);
|
||||
|
||||
@Resource
|
||||
private CcdiStaffTransferMapper transferMapper;
|
||||
|
||||
@@ -50,6 +50,9 @@ public class CcdiStaffTransferImportServiceImpl implements ICcdiStaffTransferImp
|
||||
@Resource
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Resource
|
||||
private CcdiBaseStaffMapper baseStaffMapper;
|
||||
|
||||
@Override
|
||||
@Async
|
||||
@Transactional
|
||||
@@ -62,6 +65,9 @@ public class CcdiStaffTransferImportServiceImpl implements ICcdiStaffTransferImp
|
||||
List<CcdiStaffTransfer> newRecords = new ArrayList<>();
|
||||
List<StaffTransferImportFailureVO> failures = new ArrayList<>();
|
||||
|
||||
// 批量验证员工ID是否存在
|
||||
Set<Long> existingStaffIds = batchValidateStaffIds(excelList, taskId, failures);
|
||||
|
||||
// 批量查询已存在的唯一键组合
|
||||
ImportLogUtils.logBatchQueryStart(log, taskId, "已存在的调动记录", excelList.size());
|
||||
Set<String> existingKeys = getExistingTransferKeys(excelList);
|
||||
@@ -74,6 +80,11 @@ public class CcdiStaffTransferImportServiceImpl implements ICcdiStaffTransferImp
|
||||
for (int i = 0; i < excelList.size(); i++) {
|
||||
CcdiStaffTransferExcel excel = excelList.get(i);
|
||||
|
||||
// 跳过已在预验证阶段失败的记录
|
||||
if (isRowAlreadyFailed(excel, failures)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
// 转换为AddDTO进行验证
|
||||
CcdiStaffTransferAddDTO addDTO = new CcdiStaffTransferAddDTO();
|
||||
@@ -344,4 +355,75 @@ 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()));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user