!631 【工作流】委派
Merge pull request !631 from Youkehai/feature/bpm-delegate
This commit is contained in:
commit
8649b285cf
@ -50,6 +50,8 @@ public interface ErrorCodeConstants {
|
|||||||
ErrorCode TASK_TARGET_NODE_NOT_EXISTS = new ErrorCode(1_009_005_004, " 目标节点不存在");
|
ErrorCode TASK_TARGET_NODE_NOT_EXISTS = new ErrorCode(1_009_005_004, " 目标节点不存在");
|
||||||
ErrorCode TASK_RETURN_FAIL_NO_RETURN_TASK = new ErrorCode(1_009_005_005, "回退任务失败,选择回退的节点没有需要回滚的任务!请重新选择其他任务节点");
|
ErrorCode TASK_RETURN_FAIL_NO_RETURN_TASK = new ErrorCode(1_009_005_005, "回退任务失败,选择回退的节点没有需要回滚的任务!请重新选择其他任务节点");
|
||||||
ErrorCode TASK_RETURN_FAIL_SOURCE_TARGET_ERROR = new ErrorCode(1_009_005_006, "回退任务失败,目标节点是在并行网关上或非同一路线上,不可跳转");
|
ErrorCode TASK_RETURN_FAIL_SOURCE_TARGET_ERROR = new ErrorCode(1_009_005_006, "回退任务失败,目标节点是在并行网关上或非同一路线上,不可跳转");
|
||||||
|
ErrorCode TASK_DELEGATE_USER_REPEAT = new ErrorCode(1_009_005_007, "任务委派失败,委派人和当前审批人为同一人");
|
||||||
|
ErrorCode TASK_DELEGATE_USER_NULL = new ErrorCode(1_009_005_008, "任务委派失败,被委派人不存在");
|
||||||
|
|
||||||
// ========== 流程任务分配规则 1-009-006-000 ==========
|
// ========== 流程任务分配规则 1-009-006-000 ==========
|
||||||
ErrorCode TASK_ASSIGN_RULE_EXISTS = new ErrorCode(1_009_006_000, "流程({}) 的任务({}) 已经存在分配规则");
|
ErrorCode TASK_ASSIGN_RULE_EXISTS = new ErrorCode(1_009_006_000, "流程({}) 的任务({}) 已经存在分配规则");
|
||||||
|
@ -20,7 +20,9 @@ public enum BpmProcessInstanceResultEnum {
|
|||||||
|
|
||||||
// ========== 流程任务独有的状态 ==========
|
// ========== 流程任务独有的状态 ==========
|
||||||
|
|
||||||
BACK(5, "退回/驳回");
|
BACK(5, "退回/驳回"),
|
||||||
|
|
||||||
|
DELEGATE(6, "委派");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 结果
|
* 结果
|
||||||
|
@ -91,4 +91,12 @@ public class BpmTaskController {
|
|||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PutMapping("/delegate")
|
||||||
|
@Operation(summary = "委派任务", description = "用于【流程详情】的【委派】按钮,和向前加签有点像,和向前加签的唯一的区别是没有单独创立任务")
|
||||||
|
@PreAuthorize("@ss.hasPermission('bpm:task:delegate')")
|
||||||
|
public CommonResult<Boolean> delegateTask(@Valid @RequestBody BpmTaskDelegateReqVO reqVO) {
|
||||||
|
taskService.delegateTask(reqVO,getLoginUserId());
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - 委派流程任务的 Request VO")
|
||||||
|
@Data
|
||||||
|
public class BpmTaskDelegateReqVO {
|
||||||
|
|
||||||
|
@Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||||
|
@NotEmpty(message = "任务编号不能为空")
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@Schema(description = "被委派人ID", requiredMode = Schema.RequiredMode.REQUIRED,example = "1")
|
||||||
|
@NotNull(message = "被委派人ID不能为空")
|
||||||
|
private Long delegateUserId;
|
||||||
|
|
||||||
|
@Schema(description = "委派原因", requiredMode = Schema.RequiredMode.REQUIRED,example = "做不了决定,需要你先帮忙瞅瞅")
|
||||||
|
@NotEmpty(message = "委派原因不能为空")
|
||||||
|
private String reason;
|
||||||
|
}
|
@ -137,4 +137,11 @@ public interface BpmTaskService {
|
|||||||
*/
|
*/
|
||||||
void returnTask(BpmTaskReturnReqVO reqVO);
|
void returnTask(BpmTaskReturnReqVO reqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将指定任务委派给其他人处理,等接收人处理后再回到原审批人手中审批
|
||||||
|
*
|
||||||
|
* @param reqVO 被委派人和被委派的任务编号理由参数
|
||||||
|
* @param userId 委派人ID
|
||||||
|
*/
|
||||||
|
void delegateTask(BpmTaskDelegateReqVO reqVO, Long userId);
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import cn.iocoder.yudao.framework.common.util.date.DateUtils;
|
|||||||
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.object.PageUtils;
|
import cn.iocoder.yudao.framework.common.util.object.PageUtils;
|
||||||
import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils;
|
import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils;
|
||||||
|
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
||||||
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
|
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
|
||||||
import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert;
|
import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert;
|
||||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
|
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
|
||||||
@ -29,6 +30,7 @@ import org.flowable.engine.RuntimeService;
|
|||||||
import org.flowable.engine.TaskService;
|
import org.flowable.engine.TaskService;
|
||||||
import org.flowable.engine.history.HistoricProcessInstance;
|
import org.flowable.engine.history.HistoricProcessInstance;
|
||||||
import org.flowable.engine.runtime.ProcessInstance;
|
import org.flowable.engine.runtime.ProcessInstance;
|
||||||
|
import org.flowable.task.api.DelegationState;
|
||||||
import org.flowable.task.api.Task;
|
import org.flowable.task.api.Task;
|
||||||
import org.flowable.task.api.TaskQuery;
|
import org.flowable.task.api.TaskQuery;
|
||||||
import org.flowable.task.api.history.HistoricTaskInstance;
|
import org.flowable.task.api.history.HistoricTaskInstance;
|
||||||
@ -37,6 +39,7 @@ import org.springframework.stereotype.Service;
|
|||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.transaction.support.TransactionSynchronization;
|
import org.springframework.transaction.support.TransactionSynchronization;
|
||||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
@ -193,7 +196,10 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
throw exception(PROCESS_INSTANCE_NOT_EXISTS);
|
throw exception(PROCESS_INSTANCE_NOT_EXISTS);
|
||||||
}
|
}
|
||||||
|
//被委派的任务,不调用 complete 去完成任务
|
||||||
|
if (DelegationState.PENDING.equals(task.getDelegationState())) {
|
||||||
|
this.approveDelegateTask(reqVO, task);
|
||||||
|
} else {
|
||||||
// 完成任务,审批通过
|
// 完成任务,审批通过
|
||||||
taskService.complete(task.getId(), instance.getProcessVariables());
|
taskService.complete(task.getId(), instance.getProcessVariables());
|
||||||
|
|
||||||
@ -202,6 +208,32 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||||||
new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.APPROVE.getResult())
|
new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.APPROVE.getResult())
|
||||||
.setReason(reqVO.getReason()));
|
.setReason(reqVO.getReason()));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审批被委派的任务
|
||||||
|
*
|
||||||
|
* @param reqVO 前端请求参数,包含当前任务ID,审批意见等
|
||||||
|
* @param task 当前被审批的任务
|
||||||
|
*/
|
||||||
|
private void approveDelegateTask(BpmTaskApproveReqVO reqVO, Task task) {
|
||||||
|
// 添加审批意见
|
||||||
|
AdminUserRespDTO currentUser = adminUserApi.getUser(WebFrameworkUtils.getLoginUserId());
|
||||||
|
//原审批人
|
||||||
|
AdminUserRespDTO sourceApproveUser = adminUserApi.getUser(NumberUtils.parseLong(task.getOwner()));
|
||||||
|
Assert.notNull(sourceApproveUser, "委派任务找不到原审批人,需要检查数据");
|
||||||
|
//添加审批意见
|
||||||
|
String comment = StrUtil.format("[{}]完成委派任务,任务重新回到[{}]手中,审批意见为:{}", currentUser.getNickname(),
|
||||||
|
sourceApproveUser.getNickname(), reqVO.getReason());
|
||||||
|
taskService.addComment(reqVO.getId(), task.getProcessInstanceId(), BpmProcessInstanceResultEnum.DELEGATE.getResult().toString(), comment);
|
||||||
|
//调用 resolveTask 完成任务,底层调用 TaskHelper.changeTaskAssignee(task, task.getOwner());
|
||||||
|
//将 owner 设置为 assignee
|
||||||
|
taskService.resolveTask(task.getId());
|
||||||
|
// 更新任务拓展表为【处理中】
|
||||||
|
taskExtMapper.updateByTaskId(
|
||||||
|
new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.PROCESS.getResult())
|
||||||
|
.setReason(reqVO.getReason()));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
@ -319,7 +351,11 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Task getTask(String id) {
|
private Task getTask(String id) {
|
||||||
return taskService.createTaskQuery().taskId(id).singleResult();
|
Task task = taskService.createTaskQuery().taskId(id).singleResult();
|
||||||
|
if (null == task) {
|
||||||
|
throw exception(TASK_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -351,6 +387,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||||||
if (task == null) {
|
if (task == null) {
|
||||||
throw exception(TASK_NOT_EXISTS);
|
throw exception(TASK_NOT_EXISTS);
|
||||||
}
|
}
|
||||||
|
// 根据流程定义获取流程模型信息
|
||||||
BpmnModel bpmnModel = bpmModelService.getBpmnModelByDefinitionId(task.getProcessDefinitionId());
|
BpmnModel bpmnModel = bpmModelService.getBpmnModelByDefinitionId(task.getProcessDefinitionId());
|
||||||
FlowElement source = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey());
|
FlowElement source = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey());
|
||||||
if (source == null) {
|
if (source == null) {
|
||||||
@ -445,4 +482,44 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||||||
.changeState();
|
.changeState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void delegateTask(BpmTaskDelegateReqVO reqVO,Long userId) {
|
||||||
|
// 校验任务
|
||||||
|
Task task = this.validateTaskDelegate(reqVO);
|
||||||
|
// 添加审批意见
|
||||||
|
AdminUserRespDTO currentUser = adminUserApi.getUser(userId);
|
||||||
|
AdminUserRespDTO delegateUser = adminUserApi.getUser(reqVO.getDelegateUserId());
|
||||||
|
if (delegateUser == null) {
|
||||||
|
throw exception(TASK_DELEGATE_USER_NULL);
|
||||||
|
}
|
||||||
|
String comment = StrUtil.format("[{}]将任务委派给[{}],委派理由为:{}", currentUser.getNickname(),
|
||||||
|
delegateUser.getNickname(), reqVO.getReason());
|
||||||
|
String taskId = reqVO.getId();
|
||||||
|
taskService.addComment(taskId, task.getProcessInstanceId(), BpmProcessInstanceResultEnum.DELEGATE.getResult().toString(), comment);
|
||||||
|
// 设置任务所有人 (owner) 为原任务的处理人 (assignee)
|
||||||
|
taskService.setOwner(taskId, task.getAssignee());
|
||||||
|
// 执行委派,将任务委派给 receiveId
|
||||||
|
taskService.delegateTask(taskId, reqVO.getDelegateUserId().toString());
|
||||||
|
// 更新任务拓展表为【委派】
|
||||||
|
taskExtMapper.updateByTaskId(
|
||||||
|
new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.DELEGATE.getResult())
|
||||||
|
.setReason(reqVO.getReason()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验任务委派参数
|
||||||
|
*
|
||||||
|
* @param reqVO 任务编号,接收人ID
|
||||||
|
* @return 当前任务信息
|
||||||
|
*/
|
||||||
|
private Task validateTaskDelegate(BpmTaskDelegateReqVO reqVO) {
|
||||||
|
// 校验任务
|
||||||
|
Task task = checkTask(WebFrameworkUtils.getLoginUserId(), reqVO.getId());
|
||||||
|
//校验当前审批人和被委派人不是同一人
|
||||||
|
if (task.getAssignee().equals(reqVO.getDelegateUserId().toString())) {
|
||||||
|
throw exception(TASK_DELEGATE_USER_REPEAT);
|
||||||
|
}
|
||||||
|
return task;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user