From ef3cbc1c6882786e8218b08be3e52ea44587f03b Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期日, 08 十一月 2026 09:45:42 +0800
Subject: [PATCH] feat(hrm): 请假批量导入、加班代申请人、批量排班与节假日区间联动
---
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmLeaveApplicationServiceImpl.java | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 110 insertions(+), 3 deletions(-)
diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmLeaveApplicationServiceImpl.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmLeaveApplicationServiceImpl.java
index 55ac560..a943b22 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmLeaveApplicationServiceImpl.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmLeaveApplicationServiceImpl.java
@@ -2,23 +2,31 @@
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
import cn.iocoder.yudao.module.bpm.service.definition.BpmCategoryService;
import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
+import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmLeaveApplicationImportExcelVO;
+import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmLeaveApplicationImportRespVO;
import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmLeaveApplicationPageReqVO;
import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmLeaveApplicationRespVO;
import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmLeaveApplicationSaveReqVO;
import cn.iocoder.yudao.module.hrm.dal.dataobject.approval.HrmLeaveApplicationDO;
+import cn.iocoder.yudao.module.hrm.dal.dataobject.employee.HrmEmployeeDO;
import cn.iocoder.yudao.module.hrm.dal.mysql.approval.HrmLeaveApplicationMapper;
+import cn.iocoder.yudao.module.hrm.dal.mysql.employee.HrmEmployeeMapper;
import cn.iocoder.yudao.module.hrm.dal.redis.HrmNoRedisDAO;
import cn.iocoder.yudao.module.hrm.enums.HrmAuditStatusEnum;
import cn.iocoder.yudao.module.hrm.enums.HrmLeaveTypeEnum;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
+import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import jakarta.annotation.Resource;
@@ -29,8 +37,10 @@
import org.springframework.validation.annotation.Validated;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -39,12 +49,13 @@
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.*;
/**
* 璇峰亣鐢宠 Service 瀹炵幇绫�
*
- * @author 鑺嬮亾婧愮爜
+ * @author 瓒呯骇绠$悊鍛�
*/
@Service
@Validated
@@ -64,7 +75,11 @@
@Resource
private BpmCategoryService bpmCategoryService;
@Resource
+ private StorageAttachmentApi storageAttachmentApi;
+ @Resource
private BpmProcessDefinitionService bpmProcessDefinitionService;
+ @Resource
+ private HrmEmployeeMapper employeeMapper;
@Override
@Transactional(rollbackFor = Exception.class)
@@ -87,12 +102,14 @@
application.setDeptId(createReqVO.getDeptId() != null ? createReqVO.getDeptId() : user.getDeptId());
application.setStatus(HrmAuditStatusEnum.DRAFT.getStatus());
leaveApplicationMapper.insert(application);
+ // 缁戝畾闄勪欢
+ storageAttachmentApi.bindAttachments("file", "hrm_leave_application",
+ application.getId(), createReqVO.getBlobIds());
return application.getId();
}
private Long getCurrentUserId() {
- // TODO: 鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛ID
- return 1L;
+ return SecurityFrameworkUtils.getLoginUserId();
}
private String generateUniqueNo() {
@@ -115,6 +132,7 @@
// 鏇存柊
HrmLeaveApplicationDO updateObj = BeanUtils.toBean(updateReqVO, HrmLeaveApplicationDO.class);
leaveApplicationMapper.updateById(updateObj);
+ storageAttachmentApi.updateAttachments("file", "hrm_leave_application", updateReqVO.getId(), updateReqVO.getBlobIds());
}
@Override
@@ -125,6 +143,8 @@
if (!Objects.equals(application.getStatus(), HrmAuditStatusEnum.DRAFT.getStatus())) {
throw exception(LEAVE_APPLICATION_UPDATE_FAIL_NOT_DRAFT);
}
+ // 鍒犻櫎闄勪欢鍏宠仈
+ storageAttachmentApi.deleteAttachmentsByRecord("hrm_leave_application", id);
// 鍒犻櫎
leaveApplicationMapper.deleteById(id);
}
@@ -167,6 +187,8 @@
respVO.setLeaveTypeName(HrmLeaveTypeEnum.getNameByStatus(application.getLeaveType()));
// 濉厖瀹℃壒鐘舵�佸悕绉�
respVO.setStatusName(HrmAuditStatusEnum.getNameByStatus(application.getStatus()));
+ // 濉厖闄勪欢鍒楄〃
+ respVO.setAttachmentList(storageAttachmentApi.listAttachments("hrm_leave_application", id));
return respVO;
}
@@ -321,4 +343,89 @@
return leaveApplicationMapper.selectByProcessInstanceId(processInstanceId);
}
+ @Override
+ public HrmLeaveApplicationImportRespVO importLeaveApplicationList(List<HrmLeaveApplicationImportExcelVO> importList) {
+ // 1. 杩囨护绌鸿锛堟墜鏈哄彿涓虹┖鐨� Excel 琛岃涓虹┖琛岋級
+ importList = filterList(importList, item -> StrUtil.isNotBlank(item.getPhone()));
+ if (CollUtil.isEmpty(importList)) {
+ throw exception(LEAVE_APPLICATION_IMPORT_LIST_IS_EMPTY);
+ }
+
+ // 2. 閫愯瀵煎叆锛屽崟琛屽け璐ヤ笉褰卞搷鍏朵粬琛�
+ HrmLeaveApplicationImportRespVO respVO = HrmLeaveApplicationImportRespVO.builder()
+ .createNames(new ArrayList<>())
+ .failureNames(new LinkedHashMap<>())
+ .build();
+ for (int i = 0; i < importList.size(); i++) {
+ HrmLeaveApplicationImportExcelVO row = importList.get(i);
+ // Excel 绗� 1 琛屾槸琛ㄥご锛屾暟鎹粠绗� 2 琛屽紑濮�
+ String rowKey = "绗�" + (i + 2) + "琛�";
+ try {
+ HrmLeaveApplicationSaveReqVO saveReqVO = buildImportSaveReqVO(row);
+ createLeaveApplication(saveReqVO);
+ respVO.getCreateNames().add(row.getPhone() + " " + row.getStartTime().toLocalDate());
+ } catch (ServiceException ex) {
+ respVO.getFailureNames().put(rowKey, ex.getMessage());
+ } catch (Exception ex) {
+ respVO.getFailureNames().put(rowKey, "瀵煎叆澶辫触锛�" + ex.getMessage());
+ }
+ }
+ return respVO;
+ }
+
+ private HrmLeaveApplicationSaveReqVO buildImportSaveReqVO(HrmLeaveApplicationImportExcelVO row) {
+ String phone = row.getPhone().trim();
+ HrmEmployeeDO employee = employeeMapper.selectByPhone(phone);
+ if (employee == null) {
+ throw exception(LEAVE_APPLICATION_IMPORT_EMPLOYEE_NOT_EXISTS, phone);
+ }
+ if (employee.getUserId() == null) {
+ throw exception(LEAVE_APPLICATION_IMPORT_EMPLOYEE_NO_USER, employee.getName());
+ }
+ // 璇峰亣绫诲瀷锛氭寜鍚嶇О鍖归厤锛堝吋瀹圭洿鎺ュ~瀛楀吀鍊硷級锛屽尮閰嶄笉鍒版椂鍒楀嚭鍙~鍊�
+ List<String> leaveTypeNames = Arrays.stream(HrmLeaveTypeEnum.values())
+ .map(HrmLeaveTypeEnum::getName).toList();
+ String leaveTypeText = StrUtil.trim(row.getLeaveType());
+ if (StrUtil.isBlank(leaveTypeText)) {
+ throw exception(LEAVE_APPLICATION_IMPORT_FIELD_REQUIRED,
+ "璇峰亣绫诲瀷锛堝彲閫夛細" + String.join("銆�", leaveTypeNames) + "锛�");
+ }
+ Integer leaveType = Arrays.stream(HrmLeaveTypeEnum.values())
+ .filter(item -> item.getName().equals(leaveTypeText)
+ || String.valueOf(item.getType()).equals(leaveTypeText))
+ .map(HrmLeaveTypeEnum::getType)
+ .findFirst().orElse(null);
+ if (leaveType == null) {
+ throw exception(LEAVE_APPLICATION_IMPORT_FIELD_INVALID,
+ "璇峰亣绫诲瀷", leaveTypeText, String.join("銆�", leaveTypeNames));
+ }
+ if (row.getStartTime() == null) {
+ throw exception(LEAVE_APPLICATION_IMPORT_FIELD_REQUIRED, "寮�濮嬫椂闂�");
+ }
+ if (row.getEndTime() == null) {
+ throw exception(LEAVE_APPLICATION_IMPORT_FIELD_REQUIRED, "缁撴潫鏃堕棿");
+ }
+ if (!row.getStartTime().isBefore(row.getEndTime())) {
+ throw exception(LEAVE_APPLICATION_IMPORT_TIME_INVALID,
+ row.getStartTime(), row.getEndTime());
+ }
+ if (row.getDuration() == null || row.getDuration().signum() <= 0) {
+ throw exception(LEAVE_APPLICATION_IMPORT_FIELD_REQUIRED, "璇峰亣鏃堕暱锛堝ぉ锛屽繀椤诲ぇ浜� 0锛�");
+ }
+ if (StrUtil.isBlank(row.getReason())) {
+ throw exception(LEAVE_APPLICATION_IMPORT_FIELD_REQUIRED, "璇峰亣鍘熷洜");
+ }
+
+ HrmLeaveApplicationSaveReqVO saveReqVO = new HrmLeaveApplicationSaveReqVO();
+ saveReqVO.setUserId(employee.getUserId());
+ saveReqVO.setDeptId(employee.getDeptId());
+ saveReqVO.setLeaveType(leaveType);
+ saveReqVO.setStartTime(row.getStartTime());
+ saveReqVO.setEndTime(row.getEndTime());
+ saveReqVO.setDuration(row.getDuration());
+ saveReqVO.setReason(row.getReason().trim());
+ saveReqVO.setRemark(row.getRemark());
+ return saveReqVO;
+ }
+
}
\ No newline at end of file
--
Gitblit v1.9.3