From d39e4f7d839167c16425086dfa2f8747bccfdff9 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期四, 05 十一月 2026 17:39:01 +0800
Subject: [PATCH] feat: 打通销售采购财务闭环并完成累计业务优化
---
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmResignationApplicationServiceImpl.java | 392 +++++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 362 insertions(+), 30 deletions(-)
diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmResignationApplicationServiceImpl.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmResignationApplicationServiceImpl.java
index df408d2..8b8fe32 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmResignationApplicationServiceImpl.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmResignationApplicationServiceImpl.java
@@ -2,25 +2,37 @@
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONUtil;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+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.controller.admin.task.vo.instance.BpmProcessInstanceCancelReqVO;
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.bpm.service.task.BpmProcessInstanceService;
import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmResignationApplicationPageReqVO;
import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmResignationApplicationRespVO;
import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmResignationApplicationSaveReqVO;
import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmResignationHandoverReqVO;
import cn.iocoder.yudao.module.hrm.dal.dataobject.approval.HrmResignationApplicationDO;
+import cn.iocoder.yudao.module.hrm.dal.dataobject.employee.HrmEmployeeDO;
import cn.iocoder.yudao.module.hrm.dal.mysql.approval.HrmResignationApplicationMapper;
+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.HrmResignationTypeEnum;
+import cn.iocoder.yudao.module.hrm.service.employee.HrmEmployeeService;
import cn.iocoder.yudao.module.hrm.service.handover.HrmUserHandoverService;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
+import cn.iocoder.yudao.module.system.api.dept.PostApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
+import cn.iocoder.yudao.module.system.api.dept.dto.PostRespDTO;
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;
@@ -31,6 +43,8 @@
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -59,12 +73,17 @@
private static final Integer HANDOVER_STATUS_IN_PROGRESS = 10;
private static final Integer HANDOVER_STATUS_COMPLETED = 20;
+ /** 鍛樺伐鐘舵�侊細绂昏亴 */
+ private static final Integer EMPLOYEE_STATUS_RESIGNED = 3;
+
@Resource
private HrmResignationApplicationMapper resignationApplicationMapper;
@Resource
private HrmNoRedisDAO noRedisDAO;
@Resource
private DeptApi deptApi;
+ @Resource
+ private PostApi postApi;
@Resource
private AdminUserApi adminUserApi;
@Resource
@@ -76,31 +95,40 @@
@Resource
private BpmProcessDefinitionService bpmProcessDefinitionService;
@Resource
+ private BpmProcessInstanceService bpmProcessInstanceService;
+ @Resource
private HrmUserHandoverService handoverService;
+ @Resource
+ private HrmEmployeeMapper employeeMapper;
+ @Resource
+ private HrmEmployeeService employeeService;
@Override
@Transactional(rollbackFor = Exception.class)
public Long createResignationApplication(HrmResignationApplicationSaveReqVO createReqVO) {
- Long userId = createReqVO.getUserId();
- if (userId == null) {
- userId = getCurrentUserId();
+ Long userId = createReqVO.getUserId() != null ? createReqVO.getUserId() : getCurrentUserId();
+ AdminUserRespDTO user = adminUserApi.getUser(userId);
+ if (user == null) {
+ throw new ServiceException(RESIGNATION_APPLICANT_NOT_EXISTS.getCode(),
+ String.format("鐢宠浜�(鐢ㄦ埛ID=%s)涓嶅瓨鍦紝璇烽噸鏂伴�夋嫨鐢宠浜哄悗閲嶈瘯", userId));
}
HrmResignationApplicationDO existing = resignationApplicationMapper.selectByUserIdAndStatusNot(userId,
HrmAuditStatusEnum.CANCEL.getStatus());
if (existing != null) {
- throw exception(RESIGNATION_APPLICATION_EXISTS);
- }
- String no = generateUniqueNo();
- AdminUserRespDTO user = adminUserApi.getUser(userId);
- if (user == null) {
- userId = getCurrentUserId();
+ throw new ServiceException(RESIGNATION_APPLICATION_EXISTS.getCode(),
+ String.format("鐢宠浜篬%s]宸插瓨鍦ㄦ湭鎾ら攢鐨勭鑱岀敵璇�(鍗曞彿=%s锛岀姸鎬�=%s)锛岃鍏堟挙閿�鎴栧垹闄ゅ師鐢宠鍚庡啀鏂板缓",
+ user.getNickname(), existing.getNo(),
+ HrmAuditStatusEnum.getNameByStatus(existing.getStatus())));
}
HrmResignationApplicationDO application = BeanUtils.toBean(createReqVO, HrmResignationApplicationDO.class);
- application.setNo(no);
+ application.setNo(generateUniqueNo());
application.setUserId(userId);
application.setDeptId(createReqVO.getDeptId() != null ? createReqVO.getDeptId() : user.getDeptId());
application.setStatus(HrmAuditStatusEnum.DRAFT.getStatus());
application.setHandoverStatus(HANDOVER_STATUS_NOT_STARTED);
+ application.setHandoverDataStatus(HANDOVER_STATUS_NOT_STARTED);
+ // 缁熶竴瑙f瀽浜ゆ帴鍛樺伐涓庣郴缁熺敤鎴凤紝纭繚鍛樺伐ID銆佺敤鎴稩D鎴愬钀藉簱
+ resolveHandoverTarget(application, userId);
resignationApplicationMapper.insert(application);
storageAttachmentApi.bindAttachments("file", "hrm_resignation_application",
application.getId(), createReqVO.getBlobIds());
@@ -108,7 +136,7 @@
}
private Long getCurrentUserId() {
- return 1L;
+ return SecurityFrameworkUtils.getLoginUserId();
}
private String generateUniqueNo() {
@@ -126,6 +154,22 @@
throw exception(RESIGNATION_APPLICATION_UPDATE_FAIL_NOT_DRAFT);
}
HrmResignationApplicationDO updateObj = BeanUtils.toBean(updateReqVO, HrmResignationApplicationDO.class);
+ // 涓嶈鐩栫敵璇蜂汉锛涗氦鎺ヤ汉缁熶竴瑙f瀽鎴愨�滃憳宸D + 鐢ㄦ埛ID鈥�
+ updateObj.setUserId(null);
+ boolean handoverProvided = updateReqVO.getHandoverEmployeeId() != null
+ || updateReqVO.getHandoverUserId() != null;
+ if (handoverProvided) {
+ resolveHandoverTarget(updateObj, application.getUserId());
+ Integer currentHandoverStatus = application.getHandoverStatus() != null
+ ? application.getHandoverStatus() : HANDOVER_STATUS_NOT_STARTED;
+ if (ObjUtil.notEqual(currentHandoverStatus, HANDOVER_STATUS_NOT_STARTED)
+ && !Objects.equals(updateObj.getHandoverEmployeeId(), application.getHandoverEmployeeId())) {
+ throw new ServiceException(RESIGNATION_HANDOVER_CHANGE_AFTER_START.getCode(),
+ String.format("褰撳墠浜ゆ帴鐘舵�佷负[%s]锛屼氦鎺ヤ汉[%s]涓嶈兘鍐嶆洿鎹紱璇峰厛灏嗕氦鎺ョ姸鎬佸洖閫�涓篬鏈紑濮媇锛涜嫢宸插畬鎴愪氦鎺ワ紝璇烽噸鏂版彁浜ょ鑱岀敵璇�",
+ getHandoverStatusName(currentHandoverStatus),
+ getEmployeeDisplayName(application.getHandoverEmployeeId())));
+ }
+ }
resignationApplicationMapper.updateById(updateObj);
storageAttachmentApi.updateAttachments("file", "hrm_resignation_application", updateReqVO.getId(), updateReqVO.getBlobIds());
}
@@ -161,6 +205,7 @@
}
HrmResignationApplicationRespVO respVO = BeanUtils.toBean(application, HrmResignationApplicationRespVO.class);
fillUserNames(respVO, application);
+ fillApplicantEmployeeInfo(respVO, application);
if (application.getDeptId() != null) {
DeptRespDTO dept = deptApi.getDept(application.getDeptId());
if (dept != null) {
@@ -169,14 +214,15 @@
}
respVO.setResignationTypeName(HrmResignationTypeEnum.getNameByStatus(application.getResignationType()));
respVO.setHandoverStatusName(getHandoverStatusName(application.getHandoverStatus()));
+ respVO.setHandoverDataStatusName(getHandoverStatusName(application.getHandoverDataStatus()));
respVO.setStatusName(HrmAuditStatusEnum.getNameByStatus(application.getStatus()));
respVO.setAttachmentList(storageAttachmentApi.listAttachments("hrm_resignation_application", id));
return respVO;
}
private void fillUserNames(HrmResignationApplicationRespVO respVO, HrmResignationApplicationDO application) {
- Set<Long> userIds = Set.of(application.getUserId(), application.getHandoverUserId())
- .stream().filter(Objects::nonNull).collect(Collectors.toSet());
+ Set<Long> userIds = Stream.of(application.getUserId(), application.getHandoverUserId())
+ .filter(Objects::nonNull).collect(Collectors.toSet());
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds);
if (application.getUserId() != null && userMap.containsKey(application.getUserId())) {
respVO.setUserName(userMap.get(application.getUserId()).getNickname());
@@ -184,6 +230,34 @@
if (application.getHandoverUserId() != null && userMap.containsKey(application.getHandoverUserId())) {
respVO.setHandoverUserName(userMap.get(application.getHandoverUserId()).getNickname());
}
+ }
+
+ /**
+ * 濉厖鐢宠浜哄憳宸ヤ俊鎭細鍛樺伐ID 涓庡矖浣嶅悕绉帮紝渚涘墠绔洖鏄�"鐢宠浜� + 宀椾綅"
+ */
+ private void fillApplicantEmployeeInfo(HrmResignationApplicationRespVO respVO,
+ HrmResignationApplicationDO application) {
+ if (application.getUserId() == null) {
+ return;
+ }
+ HrmEmployeeDO employee = employeeService.getEmployeeByUserId(application.getUserId());
+ if (employee == null) {
+ return;
+ }
+ respVO.setEmployeeId(employee.getId());
+ respVO.setEmployeeName(employee.getName());
+ if (StrUtil.isBlank(employee.getPostIds())) {
+ return;
+ }
+ List<Long> postIds = JSONUtil.toList(employee.getPostIds(), Long.class);
+ if (CollUtil.isEmpty(postIds)) {
+ return;
+ }
+ Map<Long, PostRespDTO> postMap = postApi.getPostMap(postIds);
+ respVO.setPostName(postIds.stream()
+ .filter(postMap::containsKey)
+ .map(id -> postMap.get(id).getName())
+ .collect(Collectors.joining(",")));
}
private String getHandoverStatusName(Integer handoverStatus) {
@@ -223,6 +297,13 @@
if (app.getUserId() != null && userMap.containsKey(app.getUserId())) {
vo.setUserName(userMap.get(app.getUserId()).getNickname());
}
+ // 鐢宠浜哄憳宸ヤ俊鎭細鍛樺伐鏈缓妗f椂淇濇寔涓虹┖
+ HrmEmployeeDO applicantEmployee = app.getUserId() == null ? null
+ : employeeService.getEmployeeByUserId(app.getUserId());
+ if (applicantEmployee != null) {
+ vo.setEmployeeId(applicantEmployee.getId());
+ vo.setEmployeeName(applicantEmployee.getName());
+ }
if (app.getHandoverUserId() != null && userMap.containsKey(app.getHandoverUserId())) {
vo.setHandoverUserName(userMap.get(app.getHandoverUserId()).getNickname());
}
@@ -231,6 +312,7 @@
}
vo.setResignationTypeName(HrmResignationTypeEnum.getNameByStatus(app.getResignationType()));
vo.setHandoverStatusName(getHandoverStatusName(app.getHandoverStatus()));
+ vo.setHandoverDataStatusName(getHandoverStatusName(app.getHandoverDataStatus()));
vo.setStatusName(HrmAuditStatusEnum.getNameByStatus(app.getStatus()));
return vo;
}).collect(Collectors.toList());
@@ -255,13 +337,9 @@
return;
}
- validateApproveCategoryAndProcessDefinition();
- ProcessDefinition processDefinition = bpmProcessDefinitionService.getActiveProcessDefinition(processDefinitionKey);
- if (processDefinition == null) {
- throw exception(RESIGNATION_APPLICATION_BPM_PROCESS_DEFINITION_NOT_EXISTS);
- }
+ ProcessDefinition processDefinition = resolveActiveProcessDefinition(processDefinitionKey);
String processInstanceId = bpmProcessInstanceApi.createProcessInstance(userId, new BpmProcessInstanceCreateReqDTO()
- .setProcessDefinitionKey(processDefinitionKey).setBusinessKey(String.valueOf(id)));
+ .setProcessDefinitionKey(processDefinition.getKey()).setBusinessKey(String.valueOf(id)));
resignationApplicationMapper.updateById(HrmResignationApplicationDO.builder()
.id(id)
.processInstanceId(processInstanceId)
@@ -286,6 +364,45 @@
if (!hasActiveDefinition) {
throw exception(RESIGNATION_APPLICATION_BPM_PROCESS_DEFINITION_NOT_EXISTS);
}
+ }
+
+ /**
+ * 瑙f瀽绂昏亴瀹℃壒鍙敤鐨勬祦绋嬪畾涔�
+ * <p>
+ * 鍓嶇鍘嗗彶鐗堟湰鎶婂垎绫荤紪鐮�(hrm_resignation_approve)褰撲綔娴佺▼ Key 浼犲叆锛�
+ * 杩欓噷浼樺厛浣跨敤浼犲叆 Key锛屽尮閰嶄笉鍒版椂鍥為��鍒版爣鍑� Key锛屽啀鍥為��鍒拌鍒嗙被涓嬪敮涓�鐨勬縺娲绘祦绋嬨��
+ */
+ private ProcessDefinition resolveActiveProcessDefinition(String processDefinitionKey) {
+ validateApproveCategoryAndProcessDefinition();
+ List<BpmProcessDefinitionInfoDO> definitionInfoList = bpmProcessDefinitionService
+ .getProcessDefinitionInfoListByCategory(APPROVE_CATEGORY_CODE);
+ Set<String> processDefinitionIds = convertSet(definitionInfoList, BpmProcessDefinitionInfoDO::getProcessDefinitionId);
+ List<ProcessDefinition> processDefinitions = bpmProcessDefinitionService.getProcessDefinitionList(processDefinitionIds);
+ Map<String, ProcessDefinition> latestVersionMap = new HashMap<>();
+ for (ProcessDefinition pd : processDefinitions) {
+ if (pd.isSuspended()) {
+ continue;
+ }
+ ProcessDefinition existing = latestVersionMap.get(pd.getKey());
+ if (existing == null || pd.getVersion() > existing.getVersion()) {
+ latestVersionMap.put(pd.getKey(), pd);
+ }
+ }
+ if (latestVersionMap.isEmpty()) {
+ throw exception(RESIGNATION_APPLICATION_BPM_PROCESS_DEFINITION_NOT_EXISTS);
+ }
+ if (StrUtil.isNotBlank(processDefinitionKey) && latestVersionMap.containsKey(processDefinitionKey)) {
+ return latestVersionMap.get(processDefinitionKey);
+ }
+ if (latestVersionMap.containsKey(BPM_PROCESS_DEFINITION_KEY)) {
+ return latestVersionMap.get(BPM_PROCESS_DEFINITION_KEY);
+ }
+ if (latestVersionMap.size() == 1) {
+ return latestVersionMap.values().iterator().next();
+ }
+ throw new ServiceException(RESIGNATION_APPLICATION_BPM_PROCESS_DEFINITION_NOT_EXISTS.getCode(),
+ String.format("绂昏亴瀹℃壒娴佺▼涓嶅敮涓�(鍒嗙被=%s锛屽彲鐢↘ey=%s)锛岃浼犲叆鍏蜂綋鐨勬祦绋嬪畾涔塊ey鍚庨噸璇�",
+ APPROVE_CATEGORY_CODE, String.join(",", latestVersionMap.keySet())));
}
@Override
@@ -338,18 +455,233 @@
@Transactional(rollbackFor = Exception.class)
public void updateHandoverStatus(HrmResignationHandoverReqVO reqVO) {
HrmResignationApplicationDO application = validateResignationApplicationExists(reqVO.getId());
- resignationApplicationMapper.updateById(HrmResignationApplicationDO.builder()
- .id(reqVO.getId())
- .handoverStatus(reqVO.getHandoverStatus())
- .build());
- // 浜ゆ帴瀹屾垚鏃讹紝鍒涘缓鐢ㄦ埛鏁版嵁浜ゆ帴鏄犲皠
- if (Objects.equals(reqVO.getHandoverStatus(), HANDOVER_STATUS_COMPLETED)
- && application.getHandoverUserId() != null) {
- handoverService.createHandover(
- application.getUserId(),
- application.getHandoverUserId(),
- application.getId());
+ Integer targetStatus = reqVO.getHandoverStatus();
+ if (!Objects.equals(targetStatus, HANDOVER_STATUS_NOT_STARTED)
+ && !Objects.equals(targetStatus, HANDOVER_STATUS_IN_PROGRESS)
+ && !Objects.equals(targetStatus, HANDOVER_STATUS_COMPLETED)) {
+ throw new ServiceException(RESIGNATION_HANDOVER_STATUS_INVALID.getCode(),
+ String.format("浜ゆ帴鐘舵�佸�糩%s]涓嶅悎娉曪紝浠呮敮鎸� 0(鏈紑濮�)銆�10(杩涜涓�)銆�20(宸插畬鎴�)", targetStatus));
}
+ if (!Objects.equals(application.getStatus(), HrmAuditStatusEnum.APPROVE.getStatus())) {
+ throw new ServiceException(RESIGNATION_HANDOVER_NOT_APPROVED.getCode(),
+ String.format("绂昏亴鐢宠[%s]褰撳墠瀹℃壒鐘舵�佷负[%s]锛屽鎵归�氳繃鍚庢墠鑳戒氦鎺ワ紱璇峰厛瀹屾垚瀹℃壒鍐嶆搷浣�",
+ application.getNo(), HrmAuditStatusEnum.getNameByStatus(application.getStatus())));
+ }
+ Integer currentStatus = application.getHandoverStatus() != null
+ ? application.getHandoverStatus() : HANDOVER_STATUS_NOT_STARTED;
+ if (Objects.equals(currentStatus, HANDOVER_STATUS_COMPLETED)
+ && !Objects.equals(targetStatus, HANDOVER_STATUS_COMPLETED)) {
+ throw new ServiceException(RESIGNATION_HANDOVER_COMPLETED_CANNOT_REVERT.getCode(),
+ String.format("褰撳墠浜ゆ帴鐘舵�佷负[宸插畬鎴怾锛屼笉鑳戒慨鏀逛负[%s]锛涘闇�閲嶆柊浜ゆ帴锛岃鍒犻櫎璇ョ鑱岀敵璇峰悗閲嶆柊鎻愪氦",
+ getHandoverStatusName(targetStatus)));
+ }
+ // 瀹℃壒閫氳繃鍚庡厑璁镐竴姝ュ畬鎴愪氦鎺ワ細鏈紑濮嬫垨杩涜涓潎鍙洿鎺ョ疆涓哄凡瀹屾垚锛岄伩鍏嶅涓�娆℃棤鎰忎箟鐨勭偣鍑�
+ if (Objects.equals(targetStatus, HANDOVER_STATUS_COMPLETED)) {
+ completeHandover(application);
+ return;
+ }
+ if (Objects.equals(targetStatus, HANDOVER_STATUS_NOT_STARTED)
+ && !Objects.equals(currentStatus, HANDOVER_STATUS_NOT_STARTED)
+ && !Objects.equals(currentStatus, HANDOVER_STATUS_IN_PROGRESS)) {
+ throw new ServiceException(RESIGNATION_HANDOVER_COMPLETED_CANNOT_REVERT.getCode(),
+ String.format("褰撳墠浜ゆ帴鐘舵�佷负[%s]锛屼笉鑳藉洖閫�涓篬鏈紑濮媇锛涘闇�閲嶆柊浜ゆ帴锛岃鍒犻櫎璇ョ鑱岀敵璇峰悗閲嶆柊鎻愪氦",
+ getHandoverStatusName(currentStatus)));
+ }
+ // 杩涜涓細蹇呴』宸叉寚瀹氫氦鎺ュ憳宸ワ紱鏈紑濮嬶細鍏佽鍦ㄦ湭鎸囧畾浜ゆ帴浜烘椂鍥為��
+ if (Objects.equals(targetStatus, HANDOVER_STATUS_IN_PROGRESS)) {
+ resolveStoredHandoverTarget(application);
+ }
+ resignationApplicationMapper.updateById(HrmResignationApplicationDO.builder()
+ .id(application.getId())
+ .handoverStatus(targetStatus)
+ .handoverDataStatus(targetStatus)
+ .build());
+ }
+
+ /**
+ * 瀹屾垚宸ヤ綔浜ゆ帴锛氬啓鍏� 鍛樺伐ID + 鐢ㄦ埛ID 浜ゆ帴鏄犲皠锛屼氦鎺ヤ汉閫氳繃 expandUserIds 鑾峰緱绂昏亴浜虹殑涓氬姟鏁版嵁
+ */
+ private void completeHandover(HrmResignationApplicationDO application) {
+ resolveStoredHandoverTarget(application);
+ // 鐢宠浜烘湭寤哄憳宸ユ。妗堟椂锛堝绠$悊鍛樿处鍙凤級锛屼粛寤虹珛鐢ㄦ埛绾т氦鎺ユ槧灏勶紝淇濊瘉鍏朵笟鍔℃暟鎹兘杞氦锛涘憳宸ヤ晶 ID 涓虹┖
+ HrmEmployeeDO fromEmployee = employeeService.getEmployeeByUserId(application.getUserId());
+ if (fromEmployee == null) {
+ log.warn("[completeHandover][绂昏亴鐢宠({}) 鐢宠浜�(鐢ㄦ埛ID={}) 鏈叧鑱斿憳宸ユ。妗堬紝浠呭缓绔嬬敤鎴风骇浜ゆ帴鏄犲皠]",
+ application.getNo(), application.getUserId());
+ }
+ handoverService.createHandover(fromEmployee != null ? fromEmployee.getId() : null,
+ application.getUserId(),
+ application.getHandoverEmployeeId(), application.getHandoverUserId(), application.getId());
+ resignationApplicationMapper.updateById(HrmResignationApplicationDO.builder()
+ .id(application.getId())
+ .handoverStatus(HANDOVER_STATUS_COMPLETED)
+ .handoverDataStatus(HANDOVER_STATUS_COMPLETED)
+ .build());
+ }
+
+ /**
+ * 鏍¢獙骞跺洖濉凡淇濆瓨鐨勪氦鎺ヤ汉锛堝吋瀹瑰巻鍙叉暟鎹彧瀛樹簡 handoverUserId 鐨勬儏鍐碉級
+ */
+ private void resolveStoredHandoverTarget(HrmResignationApplicationDO application) {
+ if (application.getHandoverEmployeeId() == null && application.getHandoverUserId() == null) {
+ throw new ServiceException(RESIGNATION_HANDOVER_TARGET_REQUIRED.getCode(),
+ String.format("绂昏亴鐢宠[%s]鏈寚瀹氫氦鎺ュ憳宸ワ紝鏃犳硶寮�濮嬫垨瀹屾垚浜ゆ帴锛涜鍏堢紪杈戠敵璇峰苟閫夋嫨浜ゆ帴浜�",
+ application.getNo()));
+ }
+ resolveHandoverTarget(application, application.getUserId());
+ resignationApplicationMapper.updateById(HrmResignationApplicationDO.builder()
+ .id(application.getId())
+ .handoverEmployeeId(application.getHandoverEmployeeId())
+ .handoverUserId(application.getHandoverUserId())
+ .build());
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void cancelResignationApplication(Long id, Long userId) {
+ HrmResignationApplicationDO application = validateResignationApplicationExists(id);
+ Integer status = application.getStatus();
+ if (Objects.equals(status, HrmAuditStatusEnum.DRAFT.getStatus())) {
+ resignationApplicationMapper.updateById(HrmResignationApplicationDO.builder()
+ .id(id)
+ .status(HrmAuditStatusEnum.CANCEL.getStatus())
+ .build());
+ return;
+ }
+ if (!Objects.equals(status, HrmAuditStatusEnum.PROCESS.getStatus())) {
+ throw new ServiceException(RESIGNATION_APPLICATION_CANCEL_FAIL_STATUS.getCode(),
+ String.format("绂昏亴鐢宠[%s]褰撳墠瀹℃壒鐘舵�佷负[%s]锛屼粎鑽夌鎴栧鎵逛腑鐘舵�佸彲浠ユ挙閿�",
+ application.getNo(), HrmAuditStatusEnum.getNameByStatus(status)));
+ }
+ if (StrUtil.isNotBlank(application.getProcessInstanceId())) {
+ BpmProcessInstanceCancelReqVO cancelReqVO = new BpmProcessInstanceCancelReqVO();
+ cancelReqVO.setId(application.getProcessInstanceId());
+ cancelReqVO.setReason("鐢宠浜烘挙閿�绂昏亴鐢宠锛�" + application.getNo());
+ Long startUserId = userId != null ? userId : application.getUserId();
+ bpmProcessInstanceService.cancelProcessInstanceByStartUser(startUserId, cancelReqVO);
+ // 娴佺▼鐩戝惉鍣ㄤ細鍚屾鏇存柊鐘舵�侊紱鍏滃簳澶勭悊鏈敹鍒板洖璋冪殑鍦烘櫙
+ HrmResignationApplicationDO latest = resignationApplicationMapper.selectById(id);
+ if (latest != null && Objects.equals(latest.getStatus(), HrmAuditStatusEnum.PROCESS.getStatus())) {
+ resignationApplicationMapper.updateById(HrmResignationApplicationDO.builder()
+ .id(id)
+ .status(HrmAuditStatusEnum.CANCEL.getStatus())
+ .build());
+ }
+ return;
+ }
+ // 鏃犳祦绋嬪疄渚嬶紙鍘嗗彶鍏嶅鎵规暟鎹級鐩存帴鎾ら攢
+ resignationApplicationMapper.updateById(HrmResignationApplicationDO.builder()
+ .id(id)
+ .status(HrmAuditStatusEnum.CANCEL.getStatus())
+ .build());
+ }
+
+ @Override
+ public int autoLeaveResignationApplication() {
+ LocalDate today = LocalDate.now();
+ List<HrmResignationApplicationDO> applications = resignationApplicationMapper
+ .selectListByStatusAndExpectedDateLe(HrmAuditStatusEnum.APPROVE.getStatus(), today);
+ int count = 0;
+ for (HrmResignationApplicationDO application : applications) {
+ if (application.getUserId() == null) {
+ log.warn("[autoLeaveResignationApplication][鐢宠({}) 缂哄皯鐢宠浜虹敤鎴稩D锛岃烦杩嘳", application.getId());
+ continue;
+ }
+ // 1. 鍋滅敤绯荤粺鐧诲綍璐﹀彿
+ AdminUserRespDTO user = adminUserApi.getUser(application.getUserId());
+ if (user == null) {
+ log.warn("[autoLeaveResignationApplication][鐢宠({}) 鐢宠浜�(鐢ㄦ埛ID={}) 涓嶅瓨鍦紝璺宠繃璐﹀彿鍋滅敤]",
+ application.getId(), application.getUserId());
+ } else if (!Objects.equals(user.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
+ adminUserApi.updateUserStatus(application.getUserId(), CommonStatusEnum.DISABLE.getStatus());
+ log.info("[autoLeaveResignationApplication][鐢ㄦ埛({}) 鍒拌揪绂昏亴鏃ユ湡({})锛岀郴缁熻处鍙峰凡鍋滅敤]",
+ application.getUserId(), application.getExpectedDate());
+ }
+ // 2. 鍛樺伐妗f缃负绂昏亴
+ HrmEmployeeDO employee = employeeService.getEmployeeByUserId(application.getUserId());
+ if (employee == null) {
+ log.warn("[autoLeaveResignationApplication][鐢宠({}) 鐢宠浜�(鐢ㄦ埛ID={}) 鏃犲憳宸ユ。妗堬紝璺宠繃锛涜鍏堝缓绔嬪憳宸ユ。妗圿",
+ application.getId(), application.getUserId());
+ continue;
+ }
+ if (!Objects.equals(employee.getEmployeeStatus(), EMPLOYEE_STATUS_RESIGNED)) {
+ employeeService.updateEmployeeStatusToResignedByUserId(application.getUserId(),
+ application.getExpectedDate());
+ log.info("[autoLeaveResignationApplication][鍛樺伐({}) 鍒拌揪绂昏亴鏃ユ湡({})锛岀姸鎬佸凡鏇存柊涓虹鑱宂",
+ employee.getId(), application.getExpectedDate());
+ }
+ resignationApplicationMapper.updateById(HrmResignationApplicationDO.builder()
+ .id(application.getId())
+ .actualDate(application.getExpectedDate())
+ .build());
+ count++;
+ }
+ return count;
+ }
+
+ /**
+ * 瑙f瀽浜ゆ帴鍛樺伐涓庣郴缁熺敤鎴凤紝淇濊瘉 handoverEmployeeId / handoverUserId 鎴愬涓旀湁鏁�
+ * <p>
+ * 鍏煎鍓嶇鎶娾�滀氦鎺ヤ汉鈥濅笅鎷夌殑鍛樺伐ID鍐欏叆 handoverUserId 鐨勫巻鍙叉彁浜ゆ柟寮忥細
+ * 鍏堟寜 handoverEmployeeId 瑙f瀽锛涙病鏈夋椂鎶� handoverUserId 褰撳憳宸D灏濊瘯锛涘啀鎸夌敤鎴稩D瑙f瀽銆�
+ */
+ private void resolveHandoverTarget(HrmResignationApplicationDO application, Long applyUserId) {
+ Long employeeId = application.getHandoverEmployeeId();
+ Long userId = application.getHandoverUserId();
+ if (employeeId == null && userId == null) {
+ return;
+ }
+ HrmEmployeeDO employee;
+ if (employeeId != null) {
+ employee = employeeMapper.selectById(employeeId);
+ if (employee == null) {
+ throw new ServiceException(RESIGNATION_HANDOVER_EMPLOYEE_NOT_EXISTS.getCode(),
+ String.format("浜ゆ帴鍛樺伐(ID=%s)涓嶅瓨鍦紝璇烽噸鏂伴�夋嫨浜ゆ帴鍛樺伐", employeeId));
+ }
+ } else {
+ // 鍘嗗彶鍓嶇锛歨andoverUserId 瀹為檯浼犵殑鏄憳宸D
+ employee = employeeMapper.selectById(userId);
+ if (employee == null) {
+ AdminUserRespDTO user = adminUserApi.getUser(userId);
+ if (user == null) {
+ throw new ServiceException(RESIGNATION_HANDOVER_EMPLOYEE_NOT_EXISTS.getCode(),
+ String.format("浜ゆ帴浜�(ID=%s)鍦ㄥ憳宸ユ。妗堝拰绯荤粺鐢ㄦ埛涓潎涓嶅瓨鍦紝璇烽噸鏂伴�夋嫨浜ゆ帴鍛樺伐", userId));
+ }
+ employee = employeeMapper.selectByUserId(userId);
+ if (employee == null) {
+ throw new ServiceException(RESIGNATION_HANDOVER_EMPLOYEE_NO_USER.getCode(),
+ String.format("浜ゆ帴浜篬%s](鐢ㄦ埛ID=%s)鏈叧鑱斿憳宸ユ。妗堬紝鏃犳硶纭畾浜ゆ帴鍛樺伐锛涜鍏堝湪鍛樺伐绠$悊涓负璇ョ敤鎴峰缓绔嬪憳宸ユ。妗�",
+ user.getNickname(), userId));
+ }
+ }
+ employeeId = employee.getId();
+ }
+ if (employee.getUserId() == null) {
+ throw new ServiceException(RESIGNATION_HANDOVER_EMPLOYEE_NO_USER.getCode(),
+ String.format("浜ゆ帴鍛樺伐[%s](鍛樺伐ID=%s)鏈叧鑱旂郴缁熺敤鎴凤紝鏃犳硶杞Щ鍏剁敤鎴锋暟鎹紱璇峰厛鍦ㄥ憳宸ョ鐞嗕腑鍏宠仈绯荤粺鐢ㄦ埛",
+ employee.getName(), employee.getId()));
+ }
+ if (applyUserId != null && Objects.equals(employee.getUserId(), applyUserId)) {
+ throw new ServiceException(RESIGNATION_HANDOVER_SELF.getCode(),
+ String.format("浜ゆ帴浜篬%s](鍛樺伐ID=%s)涓庣敵璇蜂汉鏄悓涓�浜猴紝璇烽�夋嫨鍏朵粬鍛樺伐",
+ employee.getName(), employee.getId()));
+ }
+ if (Objects.equals(employee.getEmployeeStatus(), EMPLOYEE_STATUS_RESIGNED)) {
+ throw new ServiceException(RESIGNATION_HANDOVER_EMPLOYEE_RESIGNED.getCode(),
+ String.format("浜ゆ帴鍛樺伐[%s](鍛樺伐ID=%s)褰撳墠宸叉槸绂昏亴鐘舵�侊紝璇烽噸鏂伴�夋嫨鍦ㄨ亴鍛樺伐",
+ employee.getName(), employee.getId()));
+ }
+ application.setHandoverEmployeeId(employeeId);
+ application.setHandoverUserId(employee.getUserId());
+ }
+
+ private String getEmployeeDisplayName(Long employeeId) {
+ if (employeeId == null) {
+ return "鏈�夋嫨";
+ }
+ HrmEmployeeDO employee = employeeMapper.selectById(employeeId);
+ return employee != null ? String.format("%s(ID=%s)", employee.getName(), employeeId)
+ : String.format("ID=%s", employeeId);
}
}
\ No newline at end of file
--
Gitblit v1.9.3