| | |
| | | import cn.hutool.core.util.NumberUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.hutool.json.JSONUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.framework.security.core.service.SecurityFrameworkService; |
| | | 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; |
| | |
| | | @Resource private BpmTaskService bpmTaskService; |
| | | @Resource private BpmCategoryService bpmCategoryService; |
| | | @Resource private BpmProcessDefinitionService bpmProcessDefinitionService; |
| | | @Resource private SecurityFrameworkService securityFrameworkService; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Long create(HrmOvertimeApplicationSaveReqVO reqVO, Long loginUserId) { |
| | | HrmEmployeeDO employee = requireEmployee(loginUserId); |
| | | HrmEmployeeDO employee = resolveApplicant(reqVO.getEmployeeId(), loginUserId); |
| | | HrmOvertimeApplicationDO application = BeanUtils.toBean(reqVO, HrmOvertimeApplicationDO.class); |
| | | applyApplicantAndCalculatedTime(application, employee); |
| | | application.setNo(noRedisDAO.generateOvertimeApplicationNo()); |
| | |
| | | public void update(HrmOvertimeApplicationSaveReqVO reqVO, Long loginUserId) { |
| | | HrmOvertimeApplicationDO existing = requireOwnedDraft(reqVO.getId(), loginUserId); |
| | | HrmOvertimeApplicationDO update = BeanUtils.toBean(reqVO, HrmOvertimeApplicationDO.class); |
| | | applyApplicantAndCalculatedTime(update, requireEmployee(loginUserId)); |
| | | // 未重新选择申请人时,沿用原申请人,避免代申请单被改回登录人 |
| | | Long requestedEmployeeId = reqVO.getEmployeeId() != null ? reqVO.getEmployeeId() : existing.getEmployeeId(); |
| | | applyApplicantAndCalculatedTime(update, resolveApplicant(requestedEmployeeId, loginUserId)); |
| | | update.setId(existing.getId()); |
| | | mapper.updateById(update); |
| | | } |
| | |
| | | HrmOvertimeApplicationDO application = require(id); |
| | | boolean deletable = Objects.equals(application.getStatus(), HrmAuditStatusEnum.DRAFT.getStatus()) |
| | | || Objects.equals(application.getStatus(), HrmAuditStatusEnum.CANCEL.getStatus()); |
| | | if (!Objects.equals(application.getUserId(), loginUserId) || !deletable) { |
| | | if (!Objects.equals(application.getUserId(), loginUserId) && !canManageOvertime()) { |
| | | throw exception(OVERTIME_APPLICATION_OPERATOR_NOT_ALLOWED); |
| | | } |
| | | if (!deletable) { |
| | | throw exception(OVERTIME_APPLICATION_UPDATE_FAIL_NOT_DRAFT); |
| | | } |
| | | mapper.deleteById(id); |
| | |
| | | if (definition == null || !BPM_PROCESS_DEFINITION_KEY.equals(definition.getKey())) { |
| | | throw exception(OVERTIME_APPLICATION_BPM_PROCESS_DEFINITION_NOT_EXISTS); |
| | | } |
| | | String processInstanceId = bpmProcessInstanceApi.createProcessInstance(loginUserId, |
| | | // 以申请人员工对应的系统账号发起流程,保证代申请单的审批人能看到正确的申请人 |
| | | String processInstanceId = bpmProcessInstanceApi.createProcessInstance(application.getUserId(), |
| | | new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(processDefinitionKey) |
| | | .setBusinessKey(String.valueOf(id))); |
| | | mapper.updateById(HrmOvertimeApplicationDO.builder().id(id).processInstanceId(processInstanceId) |
| | | .status(HrmAuditStatusEnum.PROCESS.getStatus()).build()); |
| | | .setBusinessKey(String.valueOf(id)) |
| | | .setVariables(Map.of("businessNo", application.getNo()))); |
| | | mapper.update(null, new LambdaUpdateWrapper<HrmOvertimeApplicationDO>() |
| | | .eq(HrmOvertimeApplicationDO::getId, id) |
| | | .set(HrmOvertimeApplicationDO::getProcessInstanceId, processInstanceId) |
| | | .set(HrmOvertimeApplicationDO::getStatus, HrmAuditStatusEnum.PROCESS.getStatus()) |
| | | .set(HrmOvertimeApplicationDO::getApproveTime, null)); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void cancel(Long id, Long loginUserId) { |
| | | HrmOvertimeApplicationDO application = require(id); |
| | | if (!Objects.equals(application.getUserId(), loginUserId) |
| | | || !Objects.equals(application.getStatus(), HrmAuditStatusEnum.PROCESS.getStatus())) { |
| | | if (!Objects.equals(application.getUserId(), loginUserId) && !canManageOvertime()) { |
| | | throw exception(OVERTIME_APPLICATION_OPERATOR_NOT_ALLOWED); |
| | | } |
| | | if (!Objects.equals(application.getStatus(), HrmAuditStatusEnum.PROCESS.getStatus())) { |
| | | throw exception(OVERTIME_APPLICATION_UPDATE_AUDIT_STATUS_FAIL_NOT_PROCESS); |
| | | } |
| | | bpmProcessInstanceService.cancelProcessInstanceByStartUser(loginUserId, |
| | | // 流程由申请人员工发起,撤销也必须以该员工账号作为发起人 |
| | | bpmProcessInstanceService.cancelProcessInstanceByStartUser(application.getUserId(), |
| | | new BpmProcessInstanceCancelReqVO().setId(application.getProcessInstanceId()).setReason("申请人撤销加班申请")); |
| | | } |
| | | |
| | |
| | | if (!Objects.equals(application.getStatus(), HrmAuditStatusEnum.PROCESS.getStatus())) { |
| | | throw exception(OVERTIME_APPLICATION_UPDATE_AUDIT_STATUS_FAIL_NOT_PROCESS); |
| | | } |
| | | mapper.updateById(HrmOvertimeApplicationDO.builder().id(id).status(status) |
| | | .approveTime(LocalDateTime.now()).build()); |
| | | mapper.update(null, new LambdaUpdateWrapper<HrmOvertimeApplicationDO>() |
| | | .eq(HrmOvertimeApplicationDO::getId, id) |
| | | .set(HrmOvertimeApplicationDO::getStatus, status) |
| | | .set(HrmOvertimeApplicationDO::getApproveTime, |
| | | Objects.equals(status, HrmAuditStatusEnum.APPROVE.getStatus()) |
| | | ? LocalDateTime.now() : null)); |
| | | } |
| | | |
| | | private void validateProcessDefinitions() { |
| | |
| | | |
| | | private HrmOvertimeApplicationDO requireOwnedDraft(Long id, Long userId) { |
| | | HrmOvertimeApplicationDO value = require(id); |
| | | if (!Objects.equals(value.getUserId(), userId) |
| | | || !Objects.equals(value.getStatus(), HrmAuditStatusEnum.DRAFT.getStatus())) { |
| | | // 持有 hrm:overtime:manage 权限可操作全部人的单子;否则只能操作本人单子 |
| | | if (!Objects.equals(value.getUserId(), userId) && !canManageOvertime()) { |
| | | throw exception(OVERTIME_APPLICATION_OPERATOR_NOT_ALLOWED); |
| | | } |
| | | if (!Objects.equals(value.getStatus(), HrmAuditStatusEnum.DRAFT.getStatus()) |
| | | && !Objects.equals(value.getStatus(), HrmAuditStatusEnum.REJECT.getStatus())) { |
| | | throw exception(OVERTIME_APPLICATION_UPDATE_FAIL_NOT_DRAFT); |
| | | } |
| | | return value; |
| | | } |
| | | |
| | | /** |
| | | * 解析本次申请对应的员工档案。 |
| | | * |
| | | * @param requestedEmployeeId 前端选择的申请人员工ID;为空表示本人 |
| | | * @param loginUserId 当前登录用户ID |
| | | * @return 申请人对应的员工档案 |
| | | */ |
| | | private HrmEmployeeDO resolveApplicant(Long requestedEmployeeId, Long loginUserId) { |
| | | HrmEmployeeDO self = employeeMapper.selectByUserId(loginUserId); |
| | | if (requestedEmployeeId == null || (self != null && Objects.equals(self.getId(), requestedEmployeeId))) { |
| | | if (self == null) { |
| | | throw exception(OVERTIME_APPLICATION_EMPLOYEE_NOT_EXISTS); |
| | | } |
| | | return self; |
| | | } |
| | | // 代申请:必须有管理权限 |
| | | if (!canManageOvertime()) { |
| | | throw exception(OVERTIME_APPLICATION_PROXY_NOT_ALLOWED); |
| | | } |
| | | HrmEmployeeDO target = employeeMapper.selectById(requestedEmployeeId); |
| | | if (target == null) { |
| | | throw exception(OVERTIME_APPLICATION_SELECTED_EMPLOYEE_NOT_EXISTS); |
| | | } |
| | | return target; |
| | | } |
| | | |
| | | private boolean canManageOvertime() { |
| | | return securityFrameworkService.hasPermission("hrm:overtime:manage"); |
| | | } |
| | | |
| | | private HrmEmployeeDO requireEmployee(Long userId) { |
| | | HrmEmployeeDO employee = employeeMapper.selectByUserId(userId); |
| | | if (employee == null) throw exception(OVERTIME_APPLICATION_EMPLOYEE_NOT_EXISTS); |