From a7c6624c47ce2926244ae92c4c069924572df58c Mon Sep 17 00:00:00 2001 From: wangli <274027703@qq.com> Date: Tue, 3 Mar 2026 16:10:30 +0800 Subject: [PATCH] =?UTF-8?q?feat(REQ-7125)=20-=20=E6=8A=BD=E8=B1=A1?= =?UTF-8?q?=E8=8A=82=E7=82=B9=E9=87=8D=E7=BD=AE=E5=AE=A1=E6=89=B9=E4=BA=BA?= =?UTF-8?q?=E8=83=BD=E5=8A=9B=EF=BC=8C=E6=8F=90=E4=BE=9B=E4=B8=8A=E5=B1=82?= =?UTF-8?q?=E7=9A=84=E2=80=9C=E6=8F=90=E7=BA=A7=E5=AE=A1=E6=89=B9=E2=80=9D?= =?UTF-8?q?=E5=92=8C=E2=80=9C=E6=8C=87=E5=AE=9A=E5=AE=A1=E6=89=B9=E4=BA=BA?= =?UTF-8?q?=E2=80=9D=E4=B8=A4=E4=B8=AA=E5=8A=9F=E8=83=BD=EF=BC=8C=E5=B9=B6?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E7=9B=B8=E5=85=B3=20API=20=E3=80=81=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E7=AD=BE=E5=90=8D=E5=8F=8A=E5=86=85=E9=83=A8=20handle?= =?UTF-8?q?r?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/feign/bpmn/ProcessTaskApi.java | 15 ++- .../common/enums/ApprovalMethodEnum.java | 1 + .../enums/BpmnProcessInstanceResultEnum.java | 1 + .../task/BaseBpmnTaskDelegateAssigner.java | 2 +- .../bpmn/task/BpmnTaskResetApproversDTO.java | 3 +- .../core/conf/FlowableConfiguration.java | 5 + .../engine/cmd/CustomRepointTaskAsyncCmd.java | 95 +++++++++++++++++++ .../core/engine/cmd/CustomRepointTaskCmd.java | 72 ++++++++++++++ .../cmd/CustomResetTaskApproversAsyncCmd.java | 4 +- .../cmd/CustomResetTaskApproversCmd.java | 57 ++--------- .../engine/cmd/CustomUpgradeTaskAsyncCmd.java | 95 +++++++++++++++++++ .../core/engine/cmd/CustomUpgradeTaskCmd.java | 71 ++++++++++++++ .../job/AsyncRepointTaskJobHandler.java | 42 ++++++++ ...AsyncResetApproversUserTaskJobHandler.java | 13 ++- .../job/AsyncUpgradeTaskJobHandler.java | 42 ++++++++ .../core/service/BpmnProcessTaskService.java | 26 ++++- .../impl/BpmnProcessInstanceServiceImpl.java | 32 +++++-- .../impl/BpmnProcessTaskServiceImpl.java | 26 +++-- .../web/bpmn/BpmnProcessTaskController.java | 35 ++++++- 19 files changed, 558 insertions(+), 79 deletions(-) create mode 100644 workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomRepointTaskAsyncCmd.java create mode 100644 workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomRepointTaskCmd.java create mode 100644 workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomUpgradeTaskAsyncCmd.java create mode 100644 workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomUpgradeTaskCmd.java create mode 100644 workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/job/AsyncRepointTaskJobHandler.java create mode 100644 workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/job/AsyncUpgradeTaskJobHandler.java diff --git a/workflow-engine-api/src/main/java/cn/axzo/workflow/client/feign/bpmn/ProcessTaskApi.java b/workflow-engine-api/src/main/java/cn/axzo/workflow/client/feign/bpmn/ProcessTaskApi.java index e7690efe3..848baf7f5 100644 --- a/workflow-engine-api/src/main/java/cn/axzo/workflow/client/feign/bpmn/ProcessTaskApi.java +++ b/workflow-engine-api/src/main/java/cn/axzo/workflow/client/feign/bpmn/ProcessTaskApi.java @@ -198,9 +198,20 @@ public interface ProcessTaskApi { * @return */ @Operation(summary = "重置节点审批人(提级审批、指定审批人)") - @PostMapping("/api/process/task/approvers/reset") + @PostMapping("/api/process/task/upgrade") @InvokeMode(ASYNC) - CommonResponse resetTaskApprovers(@Validated @RequestBody BpmnTaskResetApproversDTO dto); + CommonResponse upgradeTask(@Validated @RequestBody BpmnTaskResetApproversDTO dto); + + /** + * 重置节点审批(管理员指定审批人) + * + * @param dto + * @return + */ + @Operation(summary = "重置节点审批(管理员指定审批人)") + @PostMapping("/api/process/task/repoint") + @InvokeMode(ASYNC) + CommonResponse repointTask(@Validated @RequestBody BpmnTaskResetApproversDTO dto); /** * 催办 diff --git a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/enums/ApprovalMethodEnum.java b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/enums/ApprovalMethodEnum.java index d5539405d..f86b261ba 100644 --- a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/enums/ApprovalMethodEnum.java +++ b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/enums/ApprovalMethodEnum.java @@ -23,6 +23,7 @@ public enum ApprovalMethodEnum { nobody("nobody", "不设置审批人", "[仅业务节点可能有该值]"), bizSpecify("bizSpecify", "业务指定审批人", "[仅业务节点可能有该值]"), transferToAdmin("transferToAdmin", "转办给管理员", "该枚举仅日志处理使用"), + transferToAdminSpecify("transferToAdminSpecify", "管理员指定审批人", "该枚举仅日志处理使用"), @JsonEnumDefaultValue unknown("unknown", "未知", "兜底"); diff --git a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/enums/BpmnProcessInstanceResultEnum.java b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/enums/BpmnProcessInstanceResultEnum.java index 0877066a0..0ed6e263b 100644 --- a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/enums/BpmnProcessInstanceResultEnum.java +++ b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/enums/BpmnProcessInstanceResultEnum.java @@ -17,6 +17,7 @@ public enum BpmnProcessInstanceResultEnum { TRANSFER("TRANSFER", "已转交"), COUNTERSIGN("COUNTERSIGN", "已加签"), UPGRADED("UPGRADED", "已提级"), + REPOINT("REPOINT", "已指定"), COMMENTED("COMMENTED", "已评论"), DELETED("DELETED", "已删除"), HIDDEN("HIDDEN", "已隐藏"), diff --git a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/task/BaseBpmnTaskDelegateAssigner.java b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/task/BaseBpmnTaskDelegateAssigner.java index 6ec1117ca..81d98f315 100644 --- a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/task/BaseBpmnTaskDelegateAssigner.java +++ b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/task/BaseBpmnTaskDelegateAssigner.java @@ -39,6 +39,6 @@ public abstract class BaseBpmnTaskDelegateAssigner { /** * 是否是管理员指定审批人 */ - private Boolean isTransferToAdminSpecify; + private Boolean isTransferToAdminSpecify = false; } diff --git a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/task/BpmnTaskResetApproversDTO.java b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/task/BpmnTaskResetApproversDTO.java index ec5bd9237..a63b58186 100644 --- a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/task/BpmnTaskResetApproversDTO.java +++ b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/task/BpmnTaskResetApproversDTO.java @@ -69,7 +69,7 @@ public class BpmnTaskResetApproversDTO implements Serializable { /** * 任务提级给谁审批 */ - @ApiModelProperty(value = "任务提级给谁审批") + @ApiModelProperty(value = "任务给谁审批") @NotEmpty(message = "任务接收人不能为空") private List targetAssignerList; @@ -86,6 +86,7 @@ public class BpmnTaskResetApproversDTO implements Serializable { */ @ApiModelProperty(value = "设置节点审批人操作后的角标") private BpmnProcessInstanceResultEnum statusEnum; + /** * 是否异步执行 */ diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/conf/FlowableConfiguration.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/conf/FlowableConfiguration.java index aadb9aa29..7ad42bdd1 100644 --- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/conf/FlowableConfiguration.java +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/conf/FlowableConfiguration.java @@ -20,8 +20,10 @@ import cn.axzo.workflow.core.engine.job.AsyncCountersignUserTaskJobHandler; import cn.axzo.workflow.core.engine.job.AsyncExtTaskInstJobHandler; import cn.axzo.workflow.core.engine.job.AsyncRejectTaskJobHandler; import cn.axzo.workflow.core.engine.job.AsyncRemindTaskJobHandler; +import cn.axzo.workflow.core.engine.job.AsyncRepointTaskJobHandler; import cn.axzo.workflow.core.engine.job.AsyncResetApproversUserTaskJobHandler; import cn.axzo.workflow.core.engine.job.AsyncTransferUserTaskJobHandler; +import cn.axzo.workflow.core.engine.job.AsyncUpgradeTaskJobHandler; import cn.axzo.workflow.core.engine.job.NextActivityConfigCheckJobHandler; import cn.axzo.workflow.core.engine.job.exception.handle.CustomAsyncJobLogClearTraceExceptionHandler; import cn.axzo.workflow.core.engine.job.exception.handle.CustomAsyncRunnableExceptionExceptionHandler; @@ -121,8 +123,11 @@ public class FlowableConfiguration { configuration.addCustomJobHandler(new AsyncActivityCallbackJobHandler()); configuration.addCustomJobHandler(new AsyncApproveTaskWithFormJobHandler()); configuration.addCustomJobHandler(new AsyncRemindTaskJobHandler(refreshProperties)); + // 这个 jobHandler 后期可以下掉,它已经被 AsyncUpgradeTaskJobHandler()代替,目前为了保证在途审批不出异常,先保留 configuration.addCustomJobHandler(new AsyncResetApproversUserTaskJobHandler(extAxHiTaskInstService)); configuration.addCustomJobHandler(new NextActivityConfigCheckJobHandler(refreshProperties)); + configuration.addCustomJobHandler(new AsyncUpgradeTaskJobHandler()); + configuration.addCustomJobHandler(new AsyncRepointTaskJobHandler()); configurers.forEach(i -> configuration.addCustomJobHandler(i.getJobHandler())); // 异步任务异常重试时间间隔 configuration.setDefaultFailedJobWaitTime(30); diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomRepointTaskAsyncCmd.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomRepointTaskAsyncCmd.java new file mode 100644 index 000000000..56f7ca91e --- /dev/null +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomRepointTaskAsyncCmd.java @@ -0,0 +1,95 @@ +package cn.axzo.workflow.core.engine.cmd; + +import cn.axzo.workflow.common.exception.WorkflowEngineException; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskResetApproversDTO; +import cn.axzo.workflow.core.engine.job.AsyncRepointTaskJobHandler; +import cn.hutool.json.JSONUtil; +import com.alibaba.fastjson.JSON; +import lombok.extern.slf4j.Slf4j; +import org.flowable.bpmn.model.BpmnModel; +import org.flowable.common.engine.impl.interceptor.CommandContext; +import org.flowable.engine.TaskService; +import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.flowable.engine.impl.util.CommandContextUtil; +import org.flowable.engine.impl.util.ProcessDefinitionUtil; +import org.flowable.job.service.JobService; +import org.flowable.job.service.impl.persistence.entity.JobEntity; +import org.flowable.task.api.history.HistoricTaskInstance; +import org.flowable.task.api.history.HistoricTaskInstanceQuery; +import org.flowable.task.service.impl.persistence.entity.TaskEntity; + +import java.io.Serializable; + +import static cn.axzo.workflow.common.code.OtherRespCode.ASSIGNEE_NODE_ID_NOT_EXISTS; +import static cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper.getCategoryVersion; +import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.validTask; + +/** + * 重置节点下的所有审批人 + * + * @author wangli + * @since 2025-06-24 17:17 + */ +@Slf4j +public class CustomRepointTaskAsyncCmd extends CustomResetTaskApproversAsyncCmd implements Serializable { + + private static final long serialVersionUID = 6231755400617981273L; + + public CustomRepointTaskAsyncCmd(BpmnTaskResetApproversDTO dto) { + super(dto); + } + + @Override + public String paramToJsonString() { + return JSON.toJSONString(dto); + } + + @Override + public Void executeInternal(CommandContext commandContext) { + ProcessEngineConfigurationImpl processEngineConfiguration = + CommandContextUtil.getProcessEngineConfiguration(commandContext); + HistoricTaskInstanceQuery taskQuery = + processEngineConfiguration.getHistoryService().createHistoricTaskInstanceQuery(); + HistoricTaskInstance historicTaskInstance = taskQuery.taskId(dto.getTaskId()).singleResult(); + + TaskService taskService = processEngineConfiguration.getTaskService(); + TaskEntity task = (TaskEntity) taskService.createTaskQuery().taskId(dto.getTaskId()).singleResult(); + + validTargetAssigneeNodeId(task.getProcessDefinitionId()); + + validTask(historicTaskInstance, task, dto.getOriginAssigner(), null); + + startAsync(processEngineConfiguration, task); + return null; + } + + private void startAsync(ProcessEngineConfigurationImpl processEngineConfiguration, TaskEntity task) { + JobService jobService = processEngineConfiguration.getJobServiceConfiguration().getJobService(); + + JobEntity job = jobService.createJob(); + // 这里的 executionId 可为 null + job.setExecutionId(task.getExecutionId()); + job.setProcessInstanceId(task.getProcessInstanceId()); + job.setProcessDefinitionId(task.getProcessDefinitionId()); + job.setElementId(task.getTaskDefinitionKey()); + job.setElementName(task.getName()); + job.setJobHandlerType(AsyncRepointTaskJobHandler.TYPE); + job.setTenantId(task.getTenantId()); + + // 携带自定义的数据 + job.setCustomValues(JSONUtil.toJsonStr(dto)); + + // 创建异步任务并调度 + jobService.createAsyncJob(job, false); + jobService.scheduleAsyncJob(job); + } + + private void validTargetAssigneeNodeId(String processDefinitionId) { + BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(processDefinitionId); + boolean present = dto.getTargetAssignerList().stream().anyMatch(assigner -> !org.springframework.util.StringUtils.hasText(assigner.getNodeId())); + Integer categoryVersion = getCategoryVersion(bpmnModel.getMainProcess()).orElse(0); + if (categoryVersion > 0 && present) { + throw new WorkflowEngineException(ASSIGNEE_NODE_ID_NOT_EXISTS, "审批人"); + } + } +} diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomRepointTaskCmd.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomRepointTaskCmd.java new file mode 100644 index 000000000..83d77a517 --- /dev/null +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomRepointTaskCmd.java @@ -0,0 +1,72 @@ +package cn.axzo.workflow.core.engine.cmd; + +import cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum; +import cn.axzo.workflow.common.model.request.bpmn.task.AttachmentDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner; +import lombok.extern.slf4j.Slf4j; +import org.flowable.common.engine.impl.identity.Authentication; +import org.flowable.common.engine.impl.interceptor.CommandContext; +import org.flowable.engine.TaskService; +import org.flowable.task.service.impl.persistence.entity.TaskEntity; + +import java.io.Serializable; +import java.util.List; + +import static cn.axzo.workflow.common.constant.BpmnConstants.COMMENT_TYPE_ADVICE; +import static cn.axzo.workflow.common.constant.BpmnConstants.COMMENT_TYPE_OPERATION_DESC; +import static cn.axzo.workflow.common.constant.BpmnConstants.RESET_TASK_ASSIGNER_SHOW_NUMBER; +import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_ASSIGNEE_SKIP_FLAT; +import static cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner.buildDummyAssigner; +import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.addComment; + +/** + * 重置节点下的所有审批人 + * + * @author wangli + * @since 2025-06-24 17:17 + */ +@Slf4j +public class CustomRepointTaskCmd extends CustomResetTaskApproversCmd implements Serializable { + + + public CustomRepointTaskCmd(String originTaskId, + String advice, + List attachmentList, + BpmnTaskDelegateAssigner originTaskAssignee, + List targetTaskAssigneeList, + BpmnProcessInstanceResultEnum statusEnum) { + super(originTaskId, advice, attachmentList, originTaskAssignee, targetTaskAssigneeList, statusEnum); + } + + @Override + protected void resolveOriginTask(CommandContext commandContext, TaskService taskService, TaskEntity task) { + BpmnTaskDelegateAssigner assigner = buildDummyAssigner("repoint", TASK_ASSIGNEE_SKIP_FLAT, "dummyApprover"); + task.setAssignee(assigner.buildAssigneeId()); + task.setScopeType("REPOINT"); + + Authentication.setAuthenticatedUserId(originTaskAssignee.buildAssigneeId()); + + // 构建评论内容 + StringBuilder message = new StringBuilder("指定"); + int end = Math.min(targetTaskAssigneeList.size(), RESET_TASK_ASSIGNER_SHOW_NUMBER); + //加签人员数量显示指定个数 + for (int i = 0; i < end; i++) { + message.append(targetTaskAssigneeList.get(i).getAssignerName()); + if (i < end - 1) { + message.append("、"); + } + } + if (targetTaskAssigneeList.size() > end) { + message.append("等") + .append(targetTaskAssigneeList.size()) + .append("人"); + } + message.append("为审批人(管理员指定)"); + addComment(commandContext, task, COMMENT_TYPE_OPERATION_DESC, message.toString()); + addComment(commandContext, task, COMMENT_TYPE_ADVICE, advice); + Authentication.setAuthenticatedUserId(null); + + taskService.saveTask(task); + } + +} diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomResetTaskApproversAsyncCmd.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomResetTaskApproversAsyncCmd.java index 3098c7f05..f34681a18 100644 --- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomResetTaskApproversAsyncCmd.java +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomResetTaskApproversAsyncCmd.java @@ -31,10 +31,10 @@ import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.validTask * @since 2025-06-24 17:17 */ @Slf4j -public class CustomResetTaskApproversAsyncCmd extends AbstractCommand implements Serializable { +public abstract class CustomResetTaskApproversAsyncCmd extends AbstractCommand implements Serializable { private static final long serialVersionUID = 6231755400617981273L; - private final BpmnTaskResetApproversDTO dto; + protected final BpmnTaskResetApproversDTO dto; public CustomResetTaskApproversAsyncCmd(BpmnTaskResetApproversDTO dto) { this.dto = dto; diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomResetTaskApproversCmd.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomResetTaskApproversCmd.java index 24223c20f..f82f120d3 100644 --- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomResetTaskApproversCmd.java +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomResetTaskApproversCmd.java @@ -5,12 +5,10 @@ import cn.axzo.workflow.common.exception.WorkflowEngineException; import cn.axzo.workflow.common.model.request.bpmn.task.AttachmentDTO; import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner; import cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper; -import cn.axzo.workflow.core.service.ExtAxHiTaskInstService; import cn.hutool.json.JSONUtil; import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; import org.flowable.bpmn.model.BpmnModel; -import org.flowable.common.engine.impl.identity.Authentication; import org.flowable.common.engine.impl.interceptor.CommandContext; import org.flowable.engine.RuntimeService; import org.flowable.engine.TaskService; @@ -30,17 +28,11 @@ import java.util.Objects; import java.util.stream.Collectors; import static cn.axzo.workflow.common.code.OtherRespCode.ASSIGNEE_NODE_ID_NOT_EXISTS; -import static cn.axzo.workflow.common.constant.BpmnConstants.COMMENT_TYPE_ADVICE; -import static cn.axzo.workflow.common.constant.BpmnConstants.COMMENT_TYPE_OPERATION_DESC; import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_ACTIVITY_RELATION_ASSIGNEE_LIST_INFO_SNAPSHOT; import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_TASK_RELATION_ASSIGNEE_LIST_INFO; -import static cn.axzo.workflow.common.constant.BpmnConstants.RESET_TASK_ASSIGNER_SHOW_NUMBER; -import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_ASSIGNEE_SKIP_FLAT; import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_COMPLETE_OPERATION_TYPE; import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.UPGRADED; -import static cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner.buildDummyAssigner; import static cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper.getCategoryVersion; -import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.addComment; import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.batchAddAttachment; import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.validTask; @@ -51,30 +43,27 @@ import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.validTask * @since 2025-06-24 17:17 */ @Slf4j -public class CustomResetTaskApproversCmd extends AbstractCommand implements Serializable { +public abstract class CustomResetTaskApproversCmd extends AbstractCommand implements Serializable { - private final String originTaskId; - private final String advice; - private final List attachmentList; - private final BpmnTaskDelegateAssigner originTaskAssignee; - private final List targetTaskAssigneeList; - private final BpmnProcessInstanceResultEnum statusEnum; - private final ExtAxHiTaskInstService extAxHiTaskInstService; + protected final String originTaskId; + protected final String advice; + protected final List attachmentList; + protected final BpmnTaskDelegateAssigner originTaskAssignee; + protected final List targetTaskAssigneeList; + protected final BpmnProcessInstanceResultEnum statusEnum; public CustomResetTaskApproversCmd(String originTaskId, String advice, List attachmentList, BpmnTaskDelegateAssigner originTaskAssignee, List targetTaskAssigneeList, - BpmnProcessInstanceResultEnum statusEnum, - ExtAxHiTaskInstService extAxHiTaskInstService) { + BpmnProcessInstanceResultEnum statusEnum) { this.originTaskId = originTaskId; this.advice = advice; this.attachmentList = attachmentList; this.originTaskAssignee = originTaskAssignee; this.targetTaskAssigneeList = targetTaskAssigneeList; this.statusEnum = statusEnum; - this.extAxHiTaskInstService = extAxHiTaskInstService; } @Override @@ -136,35 +125,7 @@ public class CustomResetTaskApproversCmd extends AbstractCommand implement // runtimeService.removeVariables(taskEntity.getProcessInstanceId(), variables.keySet()); } - private void resolveOriginTask(CommandContext commandContext, TaskService taskService, TaskEntity task) { - BpmnTaskDelegateAssigner assigner = buildDummyAssigner("upgrade", TASK_ASSIGNEE_SKIP_FLAT, "dummyApprover"); - task.setAssignee(assigner.buildAssigneeId()); - task.setScopeType("UPGRADE"); - - Authentication.setAuthenticatedUserId(originTaskAssignee.buildAssigneeId()); - - // 构建评论内容 - StringBuilder message = new StringBuilder("提级给"); - int end = Math.min(targetTaskAssigneeList.size(), RESET_TASK_ASSIGNER_SHOW_NUMBER); - //加签人员数量显示指定个数 - for (int i = 0; i < end; i++) { - message.append(targetTaskAssigneeList.get(i).getAssignerName()); - if (i < end - 1) { - message.append("、"); - } - } - if (targetTaskAssigneeList.size() > end) { - message.append("等") - .append(targetTaskAssigneeList.size()) - .append("人"); - } - message.append("审批"); - addComment(commandContext, task, COMMENT_TYPE_OPERATION_DESC, message.toString()); - addComment(commandContext, task, COMMENT_TYPE_ADVICE, advice); - Authentication.setAuthenticatedUserId(null); - - taskService.saveTask(task); - } + protected abstract void resolveOriginTask(CommandContext commandContext, TaskService taskService, TaskEntity task); private void validTargetAssigneeNodeId(String processDefinitionId) { BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(processDefinitionId); diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomUpgradeTaskAsyncCmd.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomUpgradeTaskAsyncCmd.java new file mode 100644 index 000000000..a8105134a --- /dev/null +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomUpgradeTaskAsyncCmd.java @@ -0,0 +1,95 @@ +package cn.axzo.workflow.core.engine.cmd; + +import cn.axzo.workflow.common.exception.WorkflowEngineException; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskResetApproversDTO; +import cn.axzo.workflow.core.engine.job.AsyncUpgradeTaskJobHandler; +import cn.hutool.json.JSONUtil; +import com.alibaba.fastjson.JSON; +import lombok.extern.slf4j.Slf4j; +import org.flowable.bpmn.model.BpmnModel; +import org.flowable.common.engine.impl.interceptor.CommandContext; +import org.flowable.engine.TaskService; +import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.flowable.engine.impl.util.CommandContextUtil; +import org.flowable.engine.impl.util.ProcessDefinitionUtil; +import org.flowable.job.service.JobService; +import org.flowable.job.service.impl.persistence.entity.JobEntity; +import org.flowable.task.api.history.HistoricTaskInstance; +import org.flowable.task.api.history.HistoricTaskInstanceQuery; +import org.flowable.task.service.impl.persistence.entity.TaskEntity; + +import java.io.Serializable; + +import static cn.axzo.workflow.common.code.OtherRespCode.ASSIGNEE_NODE_ID_NOT_EXISTS; +import static cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper.getCategoryVersion; +import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.validTask; + +/** + * 重置节点下的所有审批人 + * + * @author wangli + * @since 2025-06-24 17:17 + */ +@Slf4j +public class CustomUpgradeTaskAsyncCmd extends CustomResetTaskApproversAsyncCmd implements Serializable { + + private static final long serialVersionUID = 6231755400617981273L; + + public CustomUpgradeTaskAsyncCmd(BpmnTaskResetApproversDTO dto) { + super(dto); + } + + @Override + public String paramToJsonString() { + return JSON.toJSONString(dto); + } + + @Override + public Void executeInternal(CommandContext commandContext) { + ProcessEngineConfigurationImpl processEngineConfiguration = + CommandContextUtil.getProcessEngineConfiguration(commandContext); + HistoricTaskInstanceQuery taskQuery = + processEngineConfiguration.getHistoryService().createHistoricTaskInstanceQuery(); + HistoricTaskInstance historicTaskInstance = taskQuery.taskId(dto.getTaskId()).singleResult(); + + TaskService taskService = processEngineConfiguration.getTaskService(); + TaskEntity task = (TaskEntity) taskService.createTaskQuery().taskId(dto.getTaskId()).singleResult(); + + validTargetAssigneeNodeId(task.getProcessDefinitionId()); + + validTask(historicTaskInstance, task, dto.getOriginAssigner(), null); + + startAsync(processEngineConfiguration, task); + return null; + } + + private void startAsync(ProcessEngineConfigurationImpl processEngineConfiguration, TaskEntity task) { + JobService jobService = processEngineConfiguration.getJobServiceConfiguration().getJobService(); + + JobEntity job = jobService.createJob(); + // 这里的 executionId 可为 null + job.setExecutionId(task.getExecutionId()); + job.setProcessInstanceId(task.getProcessInstanceId()); + job.setProcessDefinitionId(task.getProcessDefinitionId()); + job.setElementId(task.getTaskDefinitionKey()); + job.setElementName(task.getName()); + job.setJobHandlerType(AsyncUpgradeTaskJobHandler.TYPE); + job.setTenantId(task.getTenantId()); + + // 携带自定义的数据 + job.setCustomValues(JSONUtil.toJsonStr(dto)); + + // 创建异步任务并调度 + jobService.createAsyncJob(job, false); + jobService.scheduleAsyncJob(job); + } + + private void validTargetAssigneeNodeId(String processDefinitionId) { + BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(processDefinitionId); + boolean present = dto.getTargetAssignerList().stream().anyMatch(assigner -> !org.springframework.util.StringUtils.hasText(assigner.getNodeId())); + Integer categoryVersion = getCategoryVersion(bpmnModel.getMainProcess()).orElse(0); + if (categoryVersion > 0 && present) { + throw new WorkflowEngineException(ASSIGNEE_NODE_ID_NOT_EXISTS, "审批人"); + } + } +} diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomUpgradeTaskCmd.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomUpgradeTaskCmd.java new file mode 100644 index 000000000..1a64b1ffe --- /dev/null +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomUpgradeTaskCmd.java @@ -0,0 +1,71 @@ +package cn.axzo.workflow.core.engine.cmd; + +import cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum; +import cn.axzo.workflow.common.model.request.bpmn.task.AttachmentDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner; +import lombok.extern.slf4j.Slf4j; +import org.flowable.common.engine.impl.identity.Authentication; +import org.flowable.common.engine.impl.interceptor.CommandContext; +import org.flowable.engine.TaskService; +import org.flowable.task.service.impl.persistence.entity.TaskEntity; + +import java.io.Serializable; +import java.util.List; + +import static cn.axzo.workflow.common.constant.BpmnConstants.COMMENT_TYPE_ADVICE; +import static cn.axzo.workflow.common.constant.BpmnConstants.COMMENT_TYPE_OPERATION_DESC; +import static cn.axzo.workflow.common.constant.BpmnConstants.RESET_TASK_ASSIGNER_SHOW_NUMBER; +import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_ASSIGNEE_SKIP_FLAT; +import static cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner.buildDummyAssigner; +import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.addComment; + +/** + * 重置节点下的所有审批人 + * + * @author wangli + * @since 2025-06-24 17:17 + */ +@Slf4j +public class CustomUpgradeTaskCmd extends CustomResetTaskApproversCmd implements Serializable { + + public CustomUpgradeTaskCmd(String originTaskId, + String advice, + List attachmentList, + BpmnTaskDelegateAssigner originTaskAssignee, + List targetTaskAssigneeList, + BpmnProcessInstanceResultEnum statusEnum) { + super(originTaskId, advice, attachmentList, originTaskAssignee, targetTaskAssigneeList, statusEnum); + } + + @Override + protected void resolveOriginTask(CommandContext commandContext, TaskService taskService, TaskEntity task) { + BpmnTaskDelegateAssigner assigner = buildDummyAssigner("upgrade", TASK_ASSIGNEE_SKIP_FLAT, "dummyApprover"); + task.setAssignee(assigner.buildAssigneeId()); + task.setScopeType("UPGRADE"); + + Authentication.setAuthenticatedUserId(originTaskAssignee.buildAssigneeId()); + + // 构建评论内容 + StringBuilder message = new StringBuilder("提级给"); + int end = Math.min(targetTaskAssigneeList.size(), RESET_TASK_ASSIGNER_SHOW_NUMBER); + //加签人员数量显示指定个数 + for (int i = 0; i < end; i++) { + message.append(targetTaskAssigneeList.get(i).getAssignerName()); + if (i < end - 1) { + message.append("、"); + } + } + if (targetTaskAssigneeList.size() > end) { + message.append("等") + .append(targetTaskAssigneeList.size()) + .append("人"); + } + message.append("审批"); + addComment(commandContext, task, COMMENT_TYPE_OPERATION_DESC, message.toString()); + addComment(commandContext, task, COMMENT_TYPE_ADVICE, advice); + Authentication.setAuthenticatedUserId(null); + + taskService.saveTask(task); + } + +} diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/job/AsyncRepointTaskJobHandler.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/job/AsyncRepointTaskJobHandler.java new file mode 100644 index 000000000..e271c27d6 --- /dev/null +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/job/AsyncRepointTaskJobHandler.java @@ -0,0 +1,42 @@ +package cn.axzo.workflow.core.engine.job; + +import cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskResetApproversDTO; +import cn.axzo.workflow.core.engine.cmd.CustomRepointTaskCmd; +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; +import org.flowable.common.engine.impl.interceptor.CommandContext; +import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.flowable.engine.impl.util.CommandContextUtil; +import org.flowable.job.service.JobHandler; +import org.flowable.job.service.impl.persistence.entity.JobEntity; +import org.flowable.variable.api.delegate.VariableScope; + +@Slf4j +public class AsyncRepointTaskJobHandler extends AbstractJobHandler implements JobHandler { + + public static final String TYPE = "async-repoint-task"; + + public AsyncRepointTaskJobHandler() { + } + + @Override + public String getType() { + return TYPE; + } + + @Override + public void execute(JobEntity job, String configuration, VariableScope variableScope, CommandContext commandContext) { + log.info("AsyncCountersignUserTaskJobHandler executing..."); + log(job); + ProcessEngineConfigurationImpl processEngineConfiguration = + CommandContextUtil.getProcessEngineConfiguration(commandContext); + BpmnTaskResetApproversDTO dto = JSONUtil.toBean(job.getCustomValues(), BpmnTaskResetApproversDTO.class); + processEngineConfiguration.getCommandExecutor().execute(new CustomRepointTaskCmd(dto.getTaskId(), + dto.getAdvice(), + dto.getAttachmentList(), + dto.getOriginAssigner(), + dto.getTargetAssignerList(), + BpmnProcessInstanceResultEnum.REPOINT)); + } +} diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/job/AsyncResetApproversUserTaskJobHandler.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/job/AsyncResetApproversUserTaskJobHandler.java index 48dee935e..5584ae4ec 100644 --- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/job/AsyncResetApproversUserTaskJobHandler.java +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/job/AsyncResetApproversUserTaskJobHandler.java @@ -2,7 +2,7 @@ package cn.axzo.workflow.core.engine.job; import cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum; import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskResetApproversDTO; -import cn.axzo.workflow.core.engine.cmd.CustomResetTaskApproversCmd; +import cn.axzo.workflow.core.engine.cmd.CustomUpgradeTaskCmd; import cn.axzo.workflow.core.service.ExtAxHiTaskInstService; import cn.hutool.json.JSONUtil; import lombok.extern.slf4j.Slf4j; @@ -13,7 +13,13 @@ import org.flowable.job.service.JobHandler; import org.flowable.job.service.impl.persistence.entity.JobEntity; import org.flowable.variable.api.delegate.VariableScope; +/** + * 该功能抽象到底层了,上层目前有提级审批、指定审批人两种实现 + *

+ * 为了兼容,先保留该 handler + */ @Slf4j +@Deprecated public class AsyncResetApproversUserTaskJobHandler extends AbstractJobHandler implements JobHandler { public static final String TYPE = "async-reset-approves-task"; @@ -36,12 +42,11 @@ public class AsyncResetApproversUserTaskJobHandler extends AbstractJobHandler im ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext); BpmnTaskResetApproversDTO dto = JSONUtil.toBean(job.getCustomValues(), BpmnTaskResetApproversDTO.class); - processEngineConfiguration.getCommandExecutor().execute(new CustomResetTaskApproversCmd(dto.getTaskId(), + processEngineConfiguration.getCommandExecutor().execute(new CustomUpgradeTaskCmd(dto.getTaskId(), dto.getAdvice(), dto.getAttachmentList(), dto.getOriginAssigner(), dto.getTargetAssignerList(), - BpmnProcessInstanceResultEnum.UPGRADED, - extAxHiTaskInstService)); + BpmnProcessInstanceResultEnum.UPGRADED)); } } diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/job/AsyncUpgradeTaskJobHandler.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/job/AsyncUpgradeTaskJobHandler.java new file mode 100644 index 000000000..406c397e5 --- /dev/null +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/job/AsyncUpgradeTaskJobHandler.java @@ -0,0 +1,42 @@ +package cn.axzo.workflow.core.engine.job; + +import cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskResetApproversDTO; +import cn.axzo.workflow.core.engine.cmd.CustomUpgradeTaskCmd; +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; +import org.flowable.common.engine.impl.interceptor.CommandContext; +import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.flowable.engine.impl.util.CommandContextUtil; +import org.flowable.job.service.JobHandler; +import org.flowable.job.service.impl.persistence.entity.JobEntity; +import org.flowable.variable.api.delegate.VariableScope; + +@Slf4j +public class AsyncUpgradeTaskJobHandler extends AbstractJobHandler implements JobHandler { + + public static final String TYPE = "async-upgrade-task"; + + public AsyncUpgradeTaskJobHandler() { + } + + @Override + public String getType() { + return TYPE; + } + + @Override + public void execute(JobEntity job, String configuration, VariableScope variableScope, CommandContext commandContext) { + log.info("AsyncCountersignUserTaskJobHandler executing..."); + log(job); + ProcessEngineConfigurationImpl processEngineConfiguration = + CommandContextUtil.getProcessEngineConfiguration(commandContext); + BpmnTaskResetApproversDTO dto = JSONUtil.toBean(job.getCustomValues(), BpmnTaskResetApproversDTO.class); + processEngineConfiguration.getCommandExecutor().execute(new CustomUpgradeTaskCmd(dto.getTaskId(), + dto.getAdvice(), + dto.getAttachmentList(), + dto.getOriginAssigner(), + dto.getTargetAssignerList(), + BpmnProcessInstanceResultEnum.UPGRADED)); + } +} diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/BpmnProcessTaskService.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/BpmnProcessTaskService.java index b03b43964..a7d8aaf64 100644 --- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/BpmnProcessTaskService.java +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/BpmnProcessTaskService.java @@ -1,9 +1,26 @@ package cn.axzo.workflow.core.service; -import cn.axzo.workflow.common.model.request.bpmn.task.*; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnNodeBackSystemOperateDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnOptionalNodeDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnRobotTaskCompleteDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnRobotTaskCreateDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAttachmentDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAuditDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAuditWithFormDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskBackAuditDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskCommentDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskCountersignDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskPageSearchDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskRemindDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskResetApproversDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskTransferDTO; import cn.axzo.workflow.common.model.response.BpmPageResult; import cn.axzo.workflow.common.model.response.bpmn.BatchOperationResultVO; -import cn.axzo.workflow.common.model.response.bpmn.task.*; +import cn.axzo.workflow.common.model.response.bpmn.task.BpmnHistoricTaskInstanceGroupVO; +import cn.axzo.workflow.common.model.response.bpmn.task.BpmnHistoricTaskInstanceVO; +import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskDonePageItemVO; +import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskInstanceVO; +import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskTodoPageItemVO; import org.flowable.form.api.FormInfo; import java.util.List; @@ -141,7 +158,9 @@ public interface BpmnProcessTaskService { */ void countersignTask(BpmnTaskCountersignDTO countersignDTO); - void resetTaskApprovers(BpmnTaskResetApproversDTO dto); + void upgradeTask(BpmnTaskResetApproversDTO dto); + + void repointTask(BpmnTaskResetApproversDTO dto); void remindTask(BpmnTaskRemindDTO dto); @@ -152,5 +171,4 @@ public interface BpmnProcessTaskService { String findTaskIdByInstanceIdAndPersonId(String processInstanceId, String personId); Map findTaskIdByInstanceIdsAndPersonId(List processInstanceIds, String personId); - } diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/BpmnProcessInstanceServiceImpl.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/BpmnProcessInstanceServiceImpl.java index 556335036..f16492728 100644 --- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/BpmnProcessInstanceServiceImpl.java +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/BpmnProcessInstanceServiceImpl.java @@ -204,6 +204,7 @@ import static cn.axzo.workflow.common.enums.ApprovalMethodEnum.autoPassed_empty; import static cn.axzo.workflow.common.enums.ApprovalMethodEnum.autoRejection_empty; import static cn.axzo.workflow.common.enums.ApprovalMethodEnum.human; import static cn.axzo.workflow.common.enums.ApprovalMethodEnum.transferToAdmin; +import static cn.axzo.workflow.common.enums.ApprovalMethodEnum.transferToAdminSpecify; import static cn.axzo.workflow.common.enums.BpmnButtonEnum.BPMN_REPOINT; import static cn.axzo.workflow.common.enums.BpmnButtonEnum.BPMN_UPGRADE; import static cn.axzo.workflow.common.enums.BpmnFlowNodeMode.AND; @@ -1201,7 +1202,7 @@ public class BpmnProcessInstanceServiceImpl implements BpmnProcessInstanceServic .execute(new CustomForecastUserTaskAssigneeCmd(processInstanceId, i, engineExecutionStartListener, categoryVersion)); node.setForecastAssigners(forecastAssigners); - if (CollectionUtils.isEmpty(forecastAssigners)) { + if (CollectionUtils.isEmpty(forecastAssigners) || forecastAssigners.stream().anyMatch(j -> Objects.equals(Boolean.TRUE, j.getIsTransferToAdminSpecify()))) { getApproverEmptyHandleType(i).ifPresent(emptyHandleType -> { switch (emptyHandleType) { case autoPassed: @@ -1213,6 +1214,9 @@ public class BpmnProcessInstanceServiceImpl implements BpmnProcessInstanceServic case transferToAdmin: node.setApprovalMethod(transferToAdmin); break; + case transferToAdminSpecify: + node.setApprovalMethod(transferToAdminSpecify); + break; default: node.setNodeMode(EXCEPTIONAL); break; @@ -1744,6 +1748,7 @@ public class BpmnProcessInstanceServiceImpl implements BpmnProcessInstanceServic .forecastAssignees(e.getForecastAssigners()) .build(); if (Objects.nonNull(e.getApprovalMethod())) { + int countApprovers = e.getForecastAssigners().size(); switch (e.getApprovalMethod()) { case bizSpecify: build.setOperationDesc("动态审批人"); @@ -1760,17 +1765,23 @@ public class BpmnProcessInstanceServiceImpl implements BpmnProcessInstanceServic case transferToAdmin: build.setOperationDesc("找不到审批人且转交管理员失败,系统终止"); break; + case transferToAdminSpecify: + if (countApprovers > 1) { + build.setOperationDesc("审批人缺失,需管理员指定,仅一人指定即可"); + } else { + build.setOperationDesc("审批人缺失,需" + e.getForecastAssigners().stream().findFirst().orElse(new BpmnTaskDelegateAssigner()).getAssignerName() + "指定审批人(管理员指定)"); + } + break; case human: if (Objects.equals(e.getNodeMode(), EXCEPTIONAL)) { build.setOperationDesc(""); } else { - int countPerson = e.getForecastAssigners().size(); if (Objects.equals(BpmnFlowNodeMode.AND, e.getNodeMode())) { - build.setOperationDesc(countPerson + "人会签,需要全部同意"); + build.setOperationDesc(countApprovers + "人会签,需要全部同意"); } else if (Objects.equals(BpmnFlowNodeMode.OR, e.getNodeMode())) { - build.setOperationDesc(countPerson + "人或签,仅一人同意即可"); + build.setOperationDesc(countApprovers + "人或签,仅一人同意即可"); } - if (Objects.equals(countPerson, 1)) { + if (Objects.equals(countApprovers, 1)) { // 如果未来节点是单人,则按单人节点展示 build.setAssigneeSnapshot(build.getForecastAssignees().get(0)); build.setOperationDesc(build.getAssigneeSnapshot().getAssignerName()); @@ -1821,6 +1832,10 @@ public class BpmnProcessInstanceServiceImpl implements BpmnProcessInstanceServic // 不修改操作描述 break; } + // 审批人指定特殊文案定制 + if (Objects.nonNull(assigner) && Objects.equals(Boolean.TRUE, assigner.getIsTransferToAdminSpecify())) { + i.setOperationDesc("审批人缺失,待管理员指定,仅一人指定即可"); + } i.setAssigneeSnapshot(null); i.setForecastAssignees(assigners); i.setButtonConf(e.getButtonConf()); @@ -1831,6 +1846,11 @@ public class BpmnProcessInstanceServiceImpl implements BpmnProcessInstanceServic } }); } else { + boolean adminSpecify = false; + BpmnTaskDelegateAssigner adminSpecifyUser = ListUtils.emptyIfNull(e.getAssigneeFull()).stream().filter(i -> Objects.equals(Boolean.TRUE, i.getIsTransferToAdminSpecify())).findFirst().orElse(null); + if (Objects.nonNull(adminSpecifyUser)) { + adminSpecify = true; + } tasks.add(BpmnTaskInstanceLogVO.builder() .taskId(e.getTaskId()) .taskDefinitionKey(e.getActivityId()) @@ -1841,7 +1861,7 @@ public class BpmnProcessInstanceServiceImpl implements BpmnProcessInstanceServic .nodeType(BpmnFlowNodeType.valueOfType(e.getNodeType())) .nodeMode(BpmnFlowNodeMode.valueOfType(e.getNodeMode())) .result(BpmnProcessInstanceResultEnum.valueOfStatus(e.getStatus())) - .operationDesc(e.getOperationDesc()) + .operationDesc(Objects.equals(e.getStatus(), PROCESSING.getStatus()) && adminSpecify ? "审批人缺失,待" + adminSpecifyUser.getAssignerName() + "指定审批人(管理员指定)" : e.getOperationDesc()) .advice(e.getAdvice()) .commentExt("") .buttonConf(e.getButtonConf()) diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/BpmnProcessTaskServiceImpl.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/BpmnProcessTaskServiceImpl.java index 7dd72e807..5e77d4fd6 100644 --- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/BpmnProcessTaskServiceImpl.java +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/BpmnProcessTaskServiceImpl.java @@ -47,10 +47,12 @@ import cn.axzo.workflow.core.engine.cmd.CustomRejectionTaskAsyncCmd; import cn.axzo.workflow.core.engine.cmd.CustomRejectionTaskCmd; import cn.axzo.workflow.core.engine.cmd.CustomRemindTaskAsyncCmd; import cn.axzo.workflow.core.engine.cmd.CustomRemindTaskCmd; -import cn.axzo.workflow.core.engine.cmd.CustomResetTaskApproversAsyncCmd; -import cn.axzo.workflow.core.engine.cmd.CustomResetTaskApproversCmd; +import cn.axzo.workflow.core.engine.cmd.CustomRepointTaskAsyncCmd; +import cn.axzo.workflow.core.engine.cmd.CustomRepointTaskCmd; import cn.axzo.workflow.core.engine.cmd.CustomTransferUserTaskAsyncCmd; import cn.axzo.workflow.core.engine.cmd.CustomTransferUserTaskCmd; +import cn.axzo.workflow.core.engine.cmd.CustomUpgradeTaskAsyncCmd; +import cn.axzo.workflow.core.engine.cmd.CustomUpgradeTaskCmd; import cn.axzo.workflow.core.repository.entity.ExtAxHiTaskInst; import cn.axzo.workflow.core.service.BpmnProcessDefinitionService; import cn.axzo.workflow.core.service.BpmnProcessTaskService; @@ -887,13 +889,25 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService { @Override @Transactional(rollbackFor = Exception.class) - public void resetTaskApprovers(BpmnTaskResetApproversDTO dto) { + public void upgradeTask(BpmnTaskResetApproversDTO dto) { CommandExecutor commandExecutor = processEngineConfiguration.getCommandExecutor(); if (dto.getAsync() != null && dto.getAsync()) { - commandExecutor.execute(new CustomResetTaskApproversAsyncCmd(dto)); + commandExecutor.execute(new CustomUpgradeTaskAsyncCmd(dto)); } else { - commandExecutor.execute(new CustomResetTaskApproversCmd(dto.getTaskId(), dto.getAdvice(), - dto.getAttachmentList(), dto.getOriginAssigner(), dto.getTargetAssignerList(), dto.getStatusEnum(), extAxHiTaskInstService)); + commandExecutor.execute(new CustomUpgradeTaskCmd(dto.getTaskId(), dto.getAdvice(), + dto.getAttachmentList(), dto.getOriginAssigner(), dto.getTargetAssignerList(), dto.getStatusEnum())); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void repointTask(BpmnTaskResetApproversDTO dto) { + CommandExecutor commandExecutor = processEngineConfiguration.getCommandExecutor(); + if (dto.getAsync() != null && dto.getAsync()) { + commandExecutor.execute(new CustomRepointTaskAsyncCmd(dto)); + } else { + commandExecutor.execute(new CustomRepointTaskCmd(dto.getTaskId(), dto.getAdvice(), + dto.getAttachmentList(), dto.getOriginAssigner(), dto.getTargetAssignerList(), dto.getStatusEnum())); } } diff --git a/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/web/bpmn/BpmnProcessTaskController.java b/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/web/bpmn/BpmnProcessTaskController.java index dfb8f363a..740fbc7c4 100644 --- a/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/web/bpmn/BpmnProcessTaskController.java +++ b/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/web/bpmn/BpmnProcessTaskController.java @@ -1,6 +1,7 @@ package cn.axzo.workflow.server.controller.web.bpmn; import cn.axzo.workflow.client.feign.bpmn.ProcessTaskApi; +import cn.axzo.workflow.common.annotation.InvokeMode; import cn.axzo.workflow.common.annotation.Manageable; import cn.axzo.workflow.common.enums.AttachmentTypeEnum; import cn.axzo.workflow.common.exception.WorkflowEngineException; @@ -59,6 +60,7 @@ import java.util.Objects; import java.util.stream.Collectors; import static cn.axzo.workflow.common.code.BpmnTaskRespCode.TASK_OPERATION_PARAM_INVALID; +import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.ASYNC; import static cn.azxo.framework.common.model.CommonResponse.success; /** @@ -331,16 +333,16 @@ public class BpmnProcessTaskController extends BasicPopulateAvatarController imp } /** - * 提级审批 + * 提级审批设置审批人 * * @param dto * @return */ - @Operation(summary = "重置审批人") + @Operation(summary = "提级审批设置审批人") @Override - @PostMapping("/approvers/reset") + @PostMapping("/upgrade") @RepeatSubmit - public CommonResponse resetTaskApprovers(@Validated @RequestBody BpmnTaskResetApproversDTO dto) { + public CommonResponse upgradeTask(@Validated @RequestBody BpmnTaskResetApproversDTO dto) { if (!StringUtils.hasText(dto.getProcessInstanceId()) && !StringUtils.hasText(dto.getTaskId())) { throw new WorkflowEngineException(TASK_OPERATION_PARAM_INVALID); } @@ -349,7 +351,30 @@ public class BpmnProcessTaskController extends BasicPopulateAvatarController imp } populateUsersAvatar(dto.getOriginAssigner()); populateUsersAvatar(dto.getTargetAssignerList()); - bpmnProcessTaskService.resetTaskApprovers(dto); + bpmnProcessTaskService.upgradeTask(dto); + return success(true); + } + + /** + * 重置节点审批(管理员指定审批人) + * + * @param dto + * @return + */ + @Operation(summary = "重置节点审批(管理员指定审批人)") + @PostMapping("/api/process/task/repoint") + @InvokeMode(ASYNC) + @Override + public CommonResponse repointTask(BpmnTaskResetApproversDTO dto) { + if (!StringUtils.hasText(dto.getProcessInstanceId()) && !StringUtils.hasText(dto.getTaskId())) { + throw new WorkflowEngineException(TASK_OPERATION_PARAM_INVALID); + } + if (!StringUtils.hasText(dto.getTaskId())) { + dto.setTaskId(bpmnProcessTaskService.findTaskIdByInstanceIdAndPersonId(dto.getProcessInstanceId(), dto.getOriginAssigner().getPersonId())); + } + populateUsersAvatar(dto.getOriginAssigner()); + populateUsersAvatar(dto.getTargetAssignerList()); + bpmnProcessTaskService.repointTask(dto); return success(true); }