mirror of
https://gitee.com/orangeform/orange-admin.git
synced 2026-01-17 02:26:28 +08:00
commit:支持服务、接收任务,支持串行会签
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
package com.orangeforms.common.flow.cmd;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.orangeforms.common.flow.constant.FlowConstant;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.flowable.bpmn.model.Activity;
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.bpmn.model.MultiInstanceLoopCharacteristics;
|
||||
import org.flowable.common.engine.api.FlowableException;
|
||||
import org.flowable.common.engine.impl.interceptor.Command;
|
||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||
import org.flowable.engine.RuntimeService;
|
||||
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager;
|
||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
|
||||
import org.flowable.engine.impl.util.TaskHelper;
|
||||
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||
import org.flowable.task.service.impl.persistence.entity.TaskEntityManager;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 串行会签任务前后加签的命令对象。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2024-04-15
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public class AddSequenceMultiInstanceCmd implements Command<List<String>> {
|
||||
|
||||
/**
|
||||
* 现有的Assignee列表,并逗号分隔。
|
||||
*/
|
||||
private String originalAssignees;
|
||||
/**
|
||||
* 当前任务编号。
|
||||
*/
|
||||
private String taskId;
|
||||
/**
|
||||
* 被加签人。
|
||||
*/
|
||||
private List<String> newAssignees;
|
||||
/**
|
||||
* 是否为前加签。
|
||||
*/
|
||||
private boolean before;
|
||||
|
||||
@Override
|
||||
public List<String> execute(CommandContext commandContext) {
|
||||
ProcessEngineConfigurationImpl processEngineConfiguration =
|
||||
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||
TaskEntityManager taskEntityManager =
|
||||
processEngineConfiguration.getTaskServiceConfiguration().getTaskEntityManager();
|
||||
ExecutionEntityManager executionEntityManager = processEngineConfiguration.getExecutionEntityManager();
|
||||
//根据任务id获取任务实例
|
||||
TaskEntity taskEntity = taskEntityManager.findById(taskId);
|
||||
//根据执行实例ID获取当前执行实例
|
||||
ExecutionEntity currentExecutionEntity = executionEntityManager.findById(taskEntity.getExecutionId());
|
||||
//获取多实例的根执行实例
|
||||
ExecutionEntity multiExecutionEntity = searchForMultiInstanceActivity(taskEntity, executionEntityManager);
|
||||
//判断当前执行实例的节点是否是多实例节点
|
||||
BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(multiExecutionEntity.getProcessDefinitionId());
|
||||
Activity miActivityElement = (Activity) bpmnModel.getFlowElement(multiExecutionEntity.getCurrentActivityId());
|
||||
MultiInstanceLoopCharacteristics loopCharacteristics = miActivityElement.getLoopCharacteristics();
|
||||
if (loopCharacteristics == null) {
|
||||
throw new FlowableException("此节点不是多实例节点");
|
||||
}
|
||||
//判断是否是串行行多实例
|
||||
if (!loopCharacteristics.isSequential()) {
|
||||
throw new FlowableException("此节点为串行节点");
|
||||
}
|
||||
RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
|
||||
//获取多实例用户的变量
|
||||
List<String> collectionUsers = StrUtil.split(this.originalAssignees, ",");
|
||||
//获取当前任务在多实例中的次序
|
||||
Integer loopCounter = currentExecutionEntity.getVariableLocal("loopCounter", Integer.class);
|
||||
//操作多实例用户的变量
|
||||
if (before) {
|
||||
collectionUsers.addAll(loopCounter, this.newAssignees);
|
||||
runtimeService.setVariable(taskEntity.getProcessInstanceId(), FlowConstant.MULTI_ASSIGNEE_LIST_VAR, collectionUsers);
|
||||
//更新任务办理人
|
||||
TaskHelper.changeTaskAssignee(taskEntity, newAssignees.get(0));
|
||||
} else {
|
||||
collectionUsers.addAll(loopCounter + 1, this.newAssignees);
|
||||
runtimeService.setVariable(taskEntity.getProcessInstanceId(), FlowConstant.MULTI_ASSIGNEE_LIST_VAR, collectionUsers);
|
||||
}
|
||||
//增加多实例实例数内置变量
|
||||
Integer nrOfInstances = (Integer) multiExecutionEntity.getVariableLocal(FlowConstant.NUMBER_OF_INSTANCES_VAR);
|
||||
multiExecutionEntity.setVariableLocal(FlowConstant.NUMBER_OF_INSTANCES_VAR, nrOfInstances + newAssignees.size());
|
||||
return collectionUsers;
|
||||
}
|
||||
|
||||
protected ExecutionEntity searchForMultiInstanceActivity(
|
||||
TaskEntity taskEntity, ExecutionEntityManager executionEntityManager) {
|
||||
ExecutionEntity miExecution = null;
|
||||
ExecutionEntity taskExecution =
|
||||
executionEntityManager.findById(taskEntity.getExecutionId());
|
||||
ExecutionEntity parentExecution =
|
||||
executionEntityManager.findById(taskExecution.getParentId());
|
||||
if (taskEntity.getTaskDefinitionKey().equals(parentExecution.getActivityId()) && parentExecution.isMultiInstanceRoot()) {
|
||||
miExecution = parentExecution;
|
||||
}
|
||||
if (miExecution == null) {
|
||||
throw new FlowableException("Multiple multi instance executions found for activity id " + taskEntity.getTaskDefinitionKey());
|
||||
}
|
||||
return miExecution;
|
||||
}
|
||||
}
|
||||
@@ -56,6 +56,14 @@ public final class FlowApprovalType {
|
||||
* 多实例减签。
|
||||
*/
|
||||
public static final String MULTI_MINUS_SIGN = "multi_minus_sign";
|
||||
/**
|
||||
* 串行多实例前加签。
|
||||
*/
|
||||
public static final String MULTI_BEFORE_CONSIGN = "multi_before_consign";
|
||||
/**
|
||||
* 串行多实例后加签。
|
||||
*/
|
||||
public static final String MULTI_AFTER_CONSIGN = "multi_after_consign";
|
||||
/**
|
||||
* 中止。
|
||||
*/
|
||||
|
||||
@@ -319,6 +319,41 @@ public class FlowOperationController {
|
||||
return ResponseResult.success(resultList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交串行多实例加签或减签。
|
||||
*
|
||||
* @param processInstanceId 流程实例Id。
|
||||
* @param taskId 当前多实例任务中正在审批的实例。
|
||||
* @param newAssignees 加签减签人列表,多个指派人之间逗号分隔。
|
||||
* @param before 是否为前加签,true是前加签,否则后加签。
|
||||
* @return 应答结果。
|
||||
*/
|
||||
@PostMapping("/submitSequenceConsign")
|
||||
public ResponseResult<Void> submitSequenceConsign(
|
||||
@MyRequestBody(required = true) String processInstanceId,
|
||||
@MyRequestBody(required = true) String taskId,
|
||||
@MyRequestBody(required = true) String newAssignees,
|
||||
@MyRequestBody(required = true) Boolean before) {
|
||||
String errorMessage;
|
||||
ResponseResult<Task> verifyResult = this.doVerifySequenceMultiSign(processInstanceId, taskId);
|
||||
if (!verifyResult.isSuccess()) {
|
||||
return ResponseResult.errorFrom(verifyResult);
|
||||
}
|
||||
Task activeMultiInstanceTask = verifyResult.getData();
|
||||
ResponseResult<Void> assigneeVerifyResult =
|
||||
this.doVerifyConsignAssignee(activeMultiInstanceTask, newAssignees, true);
|
||||
if (!assigneeVerifyResult.isSuccess()) {
|
||||
return ResponseResult.errorFrom(assigneeVerifyResult);
|
||||
}
|
||||
try {
|
||||
flowApiService.submitSequenceConsign(activeMultiInstanceTask, newAssignees, before);
|
||||
} catch (FlowOperationException e) {
|
||||
errorMessage = e.getMessage();
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
return ResponseResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交多实例加签或减签。
|
||||
* NOTE: 白名单接口。
|
||||
@@ -350,28 +385,10 @@ public class FlowOperationController {
|
||||
if (isAdd == null) {
|
||||
isAdd = true;
|
||||
}
|
||||
if (!isAdd) {
|
||||
List<FlowTaskComment> commentList =
|
||||
flowTaskCommentService.getFlowTaskCommentListByMultiInstanceExecId(multiInstanceExecId);
|
||||
if (CollUtil.isNotEmpty(commentList)) {
|
||||
Set<String> approvedAssigneeSet = commentList.stream()
|
||||
.map(FlowTaskComment::getCreateLoginName).collect(Collectors.toSet());
|
||||
String loginName = this.findExistAssignee(approvedAssigneeSet, assigneeArray);
|
||||
if (loginName != null) {
|
||||
errorMessage = "数据验证失败,用户 [" + loginName + "] 已经审批,不能减签该用户!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 避免同一人被重复加签。
|
||||
FlowMultiInstanceTrans trans =
|
||||
flowMultiInstanceTransService.getWithAssigneeListByMultiInstanceExecId(multiInstanceExecId);
|
||||
Set<String> assigneeSet = new HashSet<>(StrUtil.split(trans.getAssigneeList(), ","));
|
||||
String loginName = this.findExistAssignee(assigneeSet, assigneeArray);
|
||||
if (loginName != null) {
|
||||
errorMessage = "数据验证失败,用户 [" + loginName + "] 已经是会签人,不能重复指定!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
ResponseResult<Void> assigneeVerifyResult =
|
||||
this.doVerifyConsignAssignee(activeMultiInstanceTask, newAssignees, isAdd);
|
||||
if (!assigneeVerifyResult.isSuccess()) {
|
||||
return ResponseResult.errorFrom(assigneeVerifyResult);
|
||||
}
|
||||
try {
|
||||
flowApiService.submitConsign(taskInstance, activeMultiInstanceTask, newAssignees, isAdd);
|
||||
@@ -937,6 +954,58 @@ public class FlowOperationController {
|
||||
return taskCommentList;
|
||||
}
|
||||
|
||||
private ResponseResult<Void> doVerifyConsignAssignee(Task activeMultiInstanceTask, String newAssignees, Boolean isAdd) {
|
||||
String errorMessage;
|
||||
String multiInstanceExecId = flowApiService.getExecutionVariableStringWithSafe(
|
||||
activeMultiInstanceTask.getExecutionId(), FlowConstant.MULTI_SIGN_TASK_EXECUTION_ID_VAR);
|
||||
JSONArray assigneeArray = JSON.parseArray(newAssignees);
|
||||
if (BooleanUtil.isFalse(isAdd)) {
|
||||
List<FlowTaskComment> commentList =
|
||||
flowTaskCommentService.getFlowTaskCommentListByMultiInstanceExecId(multiInstanceExecId);
|
||||
if (CollUtil.isNotEmpty(commentList)) {
|
||||
Set<String> approvedAssigneeSet = commentList.stream()
|
||||
.map(FlowTaskComment::getCreateLoginName).collect(Collectors.toSet());
|
||||
String existAssignee = this.findExistAssignee(approvedAssigneeSet, assigneeArray);
|
||||
if (existAssignee != null) {
|
||||
errorMessage = "数据验证失败,用户 [" + existAssignee + "] 已经审批,不能减签该用户!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 避免同一人被重复加签。
|
||||
FlowMultiInstanceTrans trans =
|
||||
flowMultiInstanceTransService.getWithAssigneeListByMultiInstanceExecId(multiInstanceExecId);
|
||||
Set<String> assigneeSet = new HashSet<>(StrUtil.split(trans.getAssigneeList(), ","));
|
||||
String existAssignee = this.findExistAssignee(assigneeSet, assigneeArray);
|
||||
if (existAssignee != null) {
|
||||
errorMessage = "数据验证失败,用户 [" + existAssignee + "] 已经是会签人,不能重复指定!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
}
|
||||
return ResponseResult.success();
|
||||
}
|
||||
|
||||
private ResponseResult<Task> doVerifySequenceMultiSign(String processInstanceId, String taskId) {
|
||||
String errorMessage;
|
||||
if (!flowApiService.existActiveProcessInstance(processInstanceId)) {
|
||||
errorMessage = "数据验证失败,当前流程实例已经结束,不能执行加签!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
List<Task> activeTaskList = flowApiService.getProcessInstanceActiveTaskList(processInstanceId);
|
||||
Task task = activeTaskList.stream().filter(t -> t.getId().equals(taskId)).findFirst().orElse(null);
|
||||
if (task == null) {
|
||||
errorMessage = "数据验证失败,当前任务已经不是待审批任务!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
Map<String, UserTask> userTaskMap = flowApiService.getAllUserTaskMap(task.getProcessDefinitionId());
|
||||
UserTask userTask = userTaskMap.get(task.getTaskDefinitionKey());
|
||||
if (!userTask.hasMultiInstanceLoopCharacteristics() || !userTask.getLoopCharacteristics().isSequential()) {
|
||||
errorMessage = "数据验证失败,当前任务不是串行会签多实例任务!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
return ResponseResult.success(task);
|
||||
}
|
||||
|
||||
private ResponseResult<JSONObject> doVerifyMultiSign(String processInstanceId, String taskId) {
|
||||
String errorMessage;
|
||||
if (!flowApiService.existActiveProcessInstance(processInstanceId)) {
|
||||
@@ -959,7 +1028,7 @@ public class FlowOperationController {
|
||||
for (Task activeTask : activeTaskList) {
|
||||
UserTask userTask = userTaskMap.get(activeTask.getTaskDefinitionKey());
|
||||
if (!userTask.hasMultiInstanceLoopCharacteristics()) {
|
||||
errorMessage = "数据验证失败,指定加签任务不存在或已审批完毕!";
|
||||
errorMessage = "数据验证失败,当前任务不是会签多实例任务!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
String startTaskId = flowApiService.getTaskVariableStringWithSafe(
|
||||
|
||||
@@ -79,6 +79,15 @@ public interface FlowApiService {
|
||||
*/
|
||||
void submitConsign(HistoricTaskInstance startTaskInstance, Task multiInstanceActiveTask, String newAssignees, boolean isAdd);
|
||||
|
||||
/**
|
||||
* 串行多实例加签减签。
|
||||
*
|
||||
* @param multiInstanceActiveTask 正在执行的多实例任务对象。
|
||||
* @param newAssignees 新指派人,多个指派人之间逗号分隔。
|
||||
* @param before 是否为前加签,true是前加签,否则后加签。
|
||||
*/
|
||||
void submitSequenceConsign(Task multiInstanceActiveTask, String newAssignees, boolean before);
|
||||
|
||||
/**
|
||||
* 完成任务,同时提交审批数据。
|
||||
*
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.orangeforms.common.core.object.*;
|
||||
import com.orangeforms.common.core.util.DefaultDataSourceResolver;
|
||||
import com.orangeforms.common.core.util.MyCommonUtil;
|
||||
import com.orangeforms.common.core.util.MyDateUtil;
|
||||
import com.orangeforms.common.flow.cmd.AddSequenceMultiInstanceCmd;
|
||||
import com.orangeforms.common.flow.constant.FlowApprovalType;
|
||||
import com.orangeforms.common.flow.constant.FlowConstant;
|
||||
import com.orangeforms.common.flow.constant.FlowTaskStatus;
|
||||
@@ -206,6 +207,31 @@ public class FlowApiServiceImpl implements FlowApiService {
|
||||
flowTaskCommentService.saveNew(flowTaskComment);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void submitSequenceConsign(Task multiInstanceActiveTask, String newAssignees, boolean before) {
|
||||
JSONArray assigneeArray = JSON.parseArray(newAssignees);
|
||||
List<String> newAssigneeList = new LinkedList<>();
|
||||
for (int i = 0; i < assigneeArray.size(); i++) {
|
||||
newAssigneeList.add(assigneeArray.getString(i));
|
||||
}
|
||||
String multiInstanceExecId = this.getExecutionVariableStringWithSafe(
|
||||
multiInstanceActiveTask.getExecutionId(), FlowConstant.MULTI_SIGN_TASK_EXECUTION_ID_VAR);
|
||||
FlowMultiInstanceTrans trans =
|
||||
flowMultiInstanceTransService.getWithAssigneeListByMultiInstanceExecId(multiInstanceExecId);
|
||||
List<String> updatedAssignees = managementService.executeCommand(
|
||||
new AddSequenceMultiInstanceCmd(trans.getAssigneeList(), multiInstanceActiveTask.getId(), newAssigneeList, before));
|
||||
trans.setAssigneeList(StrUtil.join(",", updatedAssignees));
|
||||
flowMultiInstanceTransService.updateById(trans);
|
||||
FlowTaskComment flowTaskComment = new FlowTaskComment();
|
||||
flowTaskComment.fillWith(multiInstanceActiveTask);
|
||||
flowTaskComment.setApprovalType(before ? FlowApprovalType.MULTI_BEFORE_CONSIGN : FlowApprovalType.MULTI_AFTER_CONSIGN);
|
||||
String showName = TokenData.takeFromRequest().getLoginName();
|
||||
String comment = String.format("用户 [%s] [%s] [%s]。", before ? "前加签" : "后加签", showName, newAssignees);
|
||||
flowTaskComment.setTaskComment(comment);
|
||||
flowTaskCommentService.saveNew(flowTaskComment);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void completeTask(Task task, FlowTaskComment flowTaskComment, JSONObject taskVariableData) {
|
||||
|
||||
Reference in New Issue
Block a user