Merge branch 'release/20241028' into 'master'
Release/20241028 See merge request universal/infrastructure/backend/workflow-engine!9
This commit is contained in:
commit
2a339ead96
2
.gitignore
vendored
2
.gitignore
vendored
@ -18,6 +18,8 @@ target/
|
|||||||
*.iws
|
*.iws
|
||||||
*.iml
|
*.iml
|
||||||
*.ipr
|
*.ipr
|
||||||
|
WorkflowCoreService.java
|
||||||
|
WorkflowManageService.java
|
||||||
|
|
||||||
### NetBeans ###
|
### NetBeans ###
|
||||||
/nbproject/private/
|
/nbproject/private/
|
||||||
|
|||||||
2
pom.xml
2
pom.xml
@ -16,7 +16,7 @@
|
|||||||
<name>workflow-engine</name>
|
<name>workflow-engine</name>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<revision>1.4.1-SNAPSHOT</revision>
|
<revision>1.4.2-SNAPSHOT</revision>
|
||||||
<axzo-bom.version>2.0.0-SNAPSHOT</axzo-bom.version>
|
<axzo-bom.version>2.0.0-SNAPSHOT</axzo-bom.version>
|
||||||
<axzo-dependencies.version>2.0.0-SNAPSHOT</axzo-dependencies.version>
|
<axzo-dependencies.version>2.0.0-SNAPSHOT</axzo-dependencies.version>
|
||||||
<feign-httpclient.version>11.8</feign-httpclient.version>
|
<feign-httpclient.version>11.8</feign-httpclient.version>
|
||||||
|
|||||||
@ -0,0 +1,22 @@
|
|||||||
|
package cn.axzo.workflow.client.annotation;
|
||||||
|
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Inherited;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于开启原生 FeignClient
|
||||||
|
*
|
||||||
|
* @author wangli
|
||||||
|
* @since 2024-09-10 11:30
|
||||||
|
*/
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Inherited
|
||||||
|
public @interface WorkflowEngineFeignClient {
|
||||||
|
}
|
||||||
@ -1,9 +1,11 @@
|
|||||||
package cn.axzo.workflow.client.feign.bpmn;
|
package cn.axzo.workflow.client.feign.bpmn;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.client.annotation.WorkflowEngineFeignClient;
|
||||||
import cn.axzo.workflow.common.annotation.Manageable;
|
import cn.axzo.workflow.common.annotation.Manageable;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.activity.BpmnActivityTimeoutCallbackDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.activity.BpmnActivityTimeoutCallbackDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.activity.BpmnActivityTimeoutTriggerDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.activity.BpmnActivityTimeoutTriggerDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivitySetAssigneeDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivitySetAssigneeDTO;
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivityTriggerDTO;
|
||||||
import cn.azxo.framework.common.model.CommonResponse;
|
import cn.azxo.framework.common.model.CommonResponse;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
@ -21,16 +23,27 @@ import javax.validation.constraints.NotBlank;
|
|||||||
* @since 2023/11/17 16:28
|
* @since 2023/11/17 16:28
|
||||||
*/
|
*/
|
||||||
//@FeignClient(name = "workflow-engine", url = "${axzo.service.workflow-engine:http://workflow-engine:8080}", configuration = CommonFeignConfiguration.class)
|
//@FeignClient(name = "workflow-engine", url = "${axzo.service.workflow-engine:http://workflow-engine:8080}", configuration = CommonFeignConfiguration.class)
|
||||||
|
@WorkflowEngineFeignClient
|
||||||
public interface ProcessActivityApi {
|
public interface ProcessActivityApi {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 业务节点唤醒
|
* 业务节点唤醒, 该节点废弃,请换成 {@link ProcessActivityApi#trigger(cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivityTriggerDTO)} 接口
|
||||||
* <p>
|
* <p>
|
||||||
* 当模型中使用了“业务节点”,且设置了“不设置审批人”模式,则当业务监听到 PROCESS_ACTIVITY_START 事件时,可通过该接口推动流程继续运行
|
* 当模型中使用了“业务节点”,且设置了“不设置审批人”模式,则当业务监听到 PROCESS_ACTIVITY_START 事件时,可通过该接口推动流程继续运行
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
@GetMapping("/api/process/activity/trigger")
|
@GetMapping("/api/process/activity/trigger")
|
||||||
CommonResponse<Boolean> trigger(@NotBlank(message = "触发 ID 不能为空") @RequestParam String triggerId);
|
CommonResponse<Boolean> trigger(@NotBlank(message = "触发 ID 不能为空") @RequestParam String triggerId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务节点唤醒
|
||||||
|
*
|
||||||
|
* @param dto
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@PostMapping("/api/process/activity/trigger")
|
||||||
|
CommonResponse<Boolean> trigger(@Validated @RequestBody BpmnActivityTriggerDTO dto);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 业务节点设置审批人, 不支持重复设置
|
* 业务节点设置审批人, 不支持重复设置
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package cn.axzo.workflow.client.feign.bpmn;
|
package cn.axzo.workflow.client.feign.bpmn;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.client.annotation.WorkflowEngineFeignClient;
|
||||||
import cn.axzo.workflow.client.config.CommonFeignConfiguration;
|
import cn.axzo.workflow.client.config.CommonFeignConfiguration;
|
||||||
import cn.axzo.workflow.common.annotation.InvokeMode;
|
import cn.axzo.workflow.common.annotation.InvokeMode;
|
||||||
import cn.axzo.workflow.common.annotation.Manageable;
|
import cn.axzo.workflow.common.annotation.Manageable;
|
||||||
@ -28,6 +29,7 @@ import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.SYNC;
|
|||||||
* @since 2023/9/21 16:25
|
* @since 2023/9/21 16:25
|
||||||
*/
|
*/
|
||||||
//@FeignClient(name = "workflow-engine", url = "${axzo.service.workflow-engine:http://workflow-engine:8080}", configuration = CommonFeignConfiguration.class)
|
//@FeignClient(name = "workflow-engine", url = "${axzo.service.workflow-engine:http://workflow-engine:8080}", configuration = CommonFeignConfiguration.class)
|
||||||
|
@WorkflowEngineFeignClient
|
||||||
@Manageable
|
@Manageable
|
||||||
public interface ProcessDefinitionApi {
|
public interface ProcessDefinitionApi {
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
package cn.axzo.workflow.client.feign.bpmn;
|
package cn.axzo.workflow.client.feign.bpmn;
|
||||||
|
|
||||||
import cn.axzo.workflow.client.config.CommonFeignConfiguration;
|
import cn.axzo.workflow.client.annotation.WorkflowEngineFeignClient;
|
||||||
import cn.axzo.workflow.common.annotation.InvokeMode;
|
import cn.axzo.workflow.common.annotation.InvokeMode;
|
||||||
import cn.axzo.workflow.common.annotation.Manageable;
|
import cn.axzo.workflow.common.annotation.Manageable;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceAbortDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceAbortDTO;
|
||||||
@ -10,18 +10,19 @@ import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCar
|
|||||||
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCheckApproverDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCheckApproverDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCreateDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCreateDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCreateWithFormDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCreateWithFormDTO;
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceLogQueryDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceMyPageReqVO;
|
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceMyPageReqVO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceQueryDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceQueryDTO;
|
||||||
import cn.axzo.workflow.common.model.response.BpmPageResult;
|
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.BatchOperationResultVO;
|
||||||
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceAdminPageItemVO;
|
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceAdminPageItemVO;
|
||||||
|
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceLogVO;
|
||||||
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstancePageItemVO;
|
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstancePageItemVO;
|
||||||
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceVO;
|
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceVO;
|
||||||
import cn.axzo.workflow.common.model.response.bpmn.process.ProcessNodeDetailVO;
|
import cn.axzo.workflow.common.model.response.bpmn.process.ProcessNodeDetailVO;
|
||||||
import cn.azxo.framework.common.model.CommonResponse;
|
import cn.azxo.framework.common.model.CommonResponse;
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@ -45,6 +46,7 @@ import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.SYNC;
|
|||||||
* @since 2023/9/21 16:26
|
* @since 2023/9/21 16:26
|
||||||
*/
|
*/
|
||||||
//@FeignClient(name = "workflow-engine", url = "${axzo.service.workflow-engine:http://workflow-engine:8080}", configuration = CommonFeignConfiguration.class)
|
//@FeignClient(name = "workflow-engine", url = "${axzo.service.workflow-engine:http://workflow-engine:8080}", configuration = CommonFeignConfiguration.class)
|
||||||
|
@WorkflowEngineFeignClient
|
||||||
public interface ProcessInstanceApi {
|
public interface ProcessInstanceApi {
|
||||||
/**
|
/**
|
||||||
* 创建审批流程
|
* 创建审批流程
|
||||||
@ -241,4 +243,15 @@ public interface ProcessInstanceApi {
|
|||||||
@Manageable
|
@Manageable
|
||||||
@InvokeMode(SYNC)
|
@InvokeMode(SYNC)
|
||||||
CommonResponse<Boolean> checkInstanceApprover(@Validated @RequestBody BpmnProcessInstanceCheckApproverDTO dto);
|
CommonResponse<Boolean> checkInstanceApprover(@Validated @RequestBody BpmnProcessInstanceCheckApproverDTO dto);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定流程的日志
|
||||||
|
*
|
||||||
|
* @param dto
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Operation(summary = "获取指定流程的日志")
|
||||||
|
@PostMapping("/api/process/instance/logs")
|
||||||
|
@InvokeMode(SYNC)
|
||||||
|
CommonResponse<BpmnProcessInstanceLogVO> getProcessInstanceLogs(@Validated @RequestBody BpmnProcessInstanceLogQueryDTO dto);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,13 @@
|
|||||||
package cn.axzo.workflow.client.feign.bpmn;
|
package cn.axzo.workflow.client.feign.bpmn;
|
||||||
|
|
||||||
import cn.axzo.workflow.client.config.CommonFeignConfiguration;
|
import cn.axzo.workflow.client.annotation.WorkflowEngineFeignClient;
|
||||||
import cn.axzo.workflow.common.annotation.InvokeMode;
|
|
||||||
import cn.axzo.workflow.common.annotation.Manageable;
|
import cn.axzo.workflow.common.annotation.Manageable;
|
||||||
import cn.azxo.framework.common.model.CommonResponse;
|
import cn.azxo.framework.common.model.CommonResponse;
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
|
||||||
import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.SYNC;
|
|
||||||
|
|
||||||
//@FeignClient(name = "workflow-engine", url = "${axzo.service.workflow-engine:http://workflow-engine:8080}", configuration = CommonFeignConfiguration.class)
|
//@FeignClient(name = "workflow-engine", url = "${axzo.service.workflow-engine:http://workflow-engine:8080}", configuration = CommonFeignConfiguration.class)
|
||||||
|
@WorkflowEngineFeignClient
|
||||||
public interface ProcessJobApi {
|
public interface ProcessJobApi {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -27,4 +24,22 @@ public interface ProcessJobApi {
|
|||||||
@Manageable
|
@Manageable
|
||||||
CommonResponse<Void> executeDeadLetterJobAction(@RequestParam(required = false) String jobId,
|
CommonResponse<Void> executeDeadLetterJobAction(@RequestParam(required = false) String jobId,
|
||||||
@RequestParam(required = false) String procInstId);
|
@RequestParam(required = false) String procInstId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询死信消息数据
|
||||||
|
* @param procInstId 流程实例id
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@GetMapping("/dead-letter/exception/stacktrace")
|
||||||
|
@Manageable
|
||||||
|
String getDeadLetterJobExceptionStacktrace(@RequestParam String procInstId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询死信消息数据
|
||||||
|
* @param jobId 死信job的id
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@GetMapping("/dead-letter/exception/stacktrace/byId")
|
||||||
|
@Manageable
|
||||||
|
String getDeadLetterJobExceptionStacktraceByJobId(@RequestParam String jobId);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package cn.axzo.workflow.client.feign.bpmn;
|
package cn.axzo.workflow.client.feign.bpmn;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.client.annotation.WorkflowEngineFeignClient;
|
||||||
import cn.axzo.workflow.client.config.CommonFeignConfiguration;
|
import cn.axzo.workflow.client.config.CommonFeignConfiguration;
|
||||||
import cn.axzo.workflow.common.annotation.InvokeMode;
|
import cn.axzo.workflow.common.annotation.InvokeMode;
|
||||||
import cn.axzo.workflow.common.annotation.Manageable;
|
import cn.axzo.workflow.common.annotation.Manageable;
|
||||||
@ -33,6 +34,7 @@ import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.SYNC;
|
|||||||
* @since 2023/9/21 15:47
|
* @since 2023/9/21 15:47
|
||||||
*/
|
*/
|
||||||
//@FeignClient(name = "workflow-engine", url = "${axzo.service.workflow-engine:http://workflow-engine:8080}", configuration = CommonFeignConfiguration.class)
|
//@FeignClient(name = "workflow-engine", url = "${axzo.service.workflow-engine:http://workflow-engine:8080}", configuration = CommonFeignConfiguration.class)
|
||||||
|
@WorkflowEngineFeignClient
|
||||||
@Manageable
|
@Manageable
|
||||||
public interface ProcessModelApi {
|
public interface ProcessModelApi {
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +1,14 @@
|
|||||||
package cn.axzo.workflow.client.feign.bpmn;
|
package cn.axzo.workflow.client.feign.bpmn;
|
||||||
|
|
||||||
import cn.axzo.workflow.client.config.CommonFeignConfiguration;
|
import cn.axzo.workflow.client.annotation.WorkflowEngineFeignClient;
|
||||||
import cn.axzo.workflow.common.annotation.InvokeMode;
|
import cn.axzo.workflow.common.annotation.InvokeMode;
|
||||||
import cn.axzo.workflow.common.annotation.Manageable;
|
import cn.axzo.workflow.common.annotation.Manageable;
|
||||||
|
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.BpmnRobotTaskCompleteDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnRobotTaskCreateDTO;
|
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.BpmnTaskAttachmentDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAuditDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAuditDTO;
|
||||||
|
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.BpmnTaskCommentDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskCountersignDTO;
|
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.BpmnTaskPageSearchDTO;
|
||||||
@ -21,7 +23,6 @@ import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskInstanceVO;
|
|||||||
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskTodoPageItemVO;
|
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskTodoPageItemVO;
|
||||||
import cn.azxo.framework.common.model.CommonResponse;
|
import cn.azxo.framework.common.model.CommonResponse;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
@ -44,6 +45,7 @@ import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.SYNC;
|
|||||||
* @since 2023/9/21 16:26
|
* @since 2023/9/21 16:26
|
||||||
*/
|
*/
|
||||||
//@FeignClient(name = "workflow-engine", url = "${axzo.service.workflow-engine:http://workflow-engine:8080}", configuration = CommonFeignConfiguration.class)
|
//@FeignClient(name = "workflow-engine", url = "${axzo.service.workflow-engine:http://workflow-engine:8080}", configuration = CommonFeignConfiguration.class)
|
||||||
|
@WorkflowEngineFeignClient
|
||||||
public interface ProcessTaskApi {
|
public interface ProcessTaskApi {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -71,6 +73,24 @@ public interface ProcessTaskApi {
|
|||||||
@PostMapping("/api/process/task/batch/approve")
|
@PostMapping("/api/process/task/batch/approve")
|
||||||
CommonResponse<BatchOperationResultVO> batchApproveTask(@Validated @RequestBody List<BpmnTaskAuditDTO> dtos);
|
CommonResponse<BatchOperationResultVO> batchApproveTask(@Validated @RequestBody List<BpmnTaskAuditDTO> dtos);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前节点可回退节点选项列表
|
||||||
|
* @param taskId 当前任务id
|
||||||
|
* @return 可以回退节点列表
|
||||||
|
*/
|
||||||
|
@Operation(summary = "获取当前节点可回退节点选项列表")
|
||||||
|
@GetMapping("/api/process/task/back/optional/nodes")
|
||||||
|
CommonResponse<List<BpmnOptionalNodeDTO>> getBackOptionalNodes(@RequestParam @NotBlank(message = "任务id不能为空") String taskId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回退到指定节点
|
||||||
|
* @param dto
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Operation(summary = "回退")
|
||||||
|
@PostMapping("/api/process/task/back")
|
||||||
|
CommonResponse<Boolean> backTask(@Validated @RequestBody BpmnTaskBackAuditDTO dto);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 驳回
|
* 驳回
|
||||||
*
|
*
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package cn.axzo.workflow.client.feign.bpmn;
|
package cn.axzo.workflow.client.feign.bpmn;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.client.annotation.WorkflowEngineFeignClient;
|
||||||
import cn.axzo.workflow.client.config.CommonFeignConfiguration;
|
import cn.axzo.workflow.client.config.CommonFeignConfiguration;
|
||||||
import cn.axzo.workflow.common.annotation.InvokeMode;
|
import cn.axzo.workflow.common.annotation.InvokeMode;
|
||||||
import cn.axzo.workflow.common.annotation.Manageable;
|
import cn.axzo.workflow.common.annotation.Manageable;
|
||||||
@ -21,6 +22,7 @@ import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.SYNC;
|
|||||||
* 流程变量api
|
* 流程变量api
|
||||||
*/
|
*/
|
||||||
//@FeignClient(name = "workflow-engine", url = "${axzo.service.workflow-engine:http://workflow-engine:8080}", configuration = CommonFeignConfiguration.class)
|
//@FeignClient(name = "workflow-engine", url = "${axzo.service.workflow-engine:http://workflow-engine:8080}", configuration = CommonFeignConfiguration.class)
|
||||||
|
@WorkflowEngineFeignClient
|
||||||
@Manageable
|
@Manageable
|
||||||
public interface ProcessVariableApi {
|
public interface ProcessVariableApi {
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package cn.axzo.workflow.client.feign.manage;
|
package cn.axzo.workflow.client.feign.manage;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.client.annotation.WorkflowEngineFeignClient;
|
||||||
import cn.axzo.workflow.client.config.CommonFeignConfiguration;
|
import cn.axzo.workflow.client.config.CommonFeignConfiguration;
|
||||||
import cn.axzo.workflow.common.annotation.InvokeMode;
|
import cn.axzo.workflow.common.annotation.InvokeMode;
|
||||||
import cn.axzo.workflow.common.annotation.Manageable;
|
import cn.axzo.workflow.common.annotation.Manageable;
|
||||||
@ -36,6 +37,7 @@ import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.SYNC;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
//@FeignClient(name = "workflow-engine", url = "${axzo.service.workflow-engine:http://workflow-engine:8080}", configuration = CommonFeignConfiguration.class)
|
//@FeignClient(name = "workflow-engine", url = "${axzo.service.workflow-engine:http://workflow-engine:8080}", configuration = CommonFeignConfiguration.class)
|
||||||
|
@WorkflowEngineFeignClient
|
||||||
@Manageable
|
@Manageable
|
||||||
public interface ProcessCategoryApi {
|
public interface ProcessCategoryApi {
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package cn.axzo.workflow.client.feign.manage;
|
package cn.axzo.workflow.client.feign.manage;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.client.annotation.WorkflowEngineFeignClient;
|
||||||
import cn.axzo.workflow.client.config.CommonFeignConfiguration;
|
import cn.axzo.workflow.client.config.CommonFeignConfiguration;
|
||||||
import cn.axzo.workflow.common.annotation.InvokeMode;
|
import cn.axzo.workflow.common.annotation.InvokeMode;
|
||||||
import cn.axzo.workflow.common.annotation.Manageable;
|
import cn.axzo.workflow.common.annotation.Manageable;
|
||||||
@ -22,6 +23,7 @@ import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.SYNC;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
//@FeignClient(name = "workflow-engine", url = "${axzo.service.workflow-engine:http://workflow-engine:8080}", configuration = CommonFeignConfiguration.class)
|
//@FeignClient(name = "workflow-engine", url = "${axzo.service.workflow-engine:http://workflow-engine:8080}", configuration = CommonFeignConfiguration.class)
|
||||||
|
@WorkflowEngineFeignClient
|
||||||
@Manageable
|
@Manageable
|
||||||
public interface ProcessConfigApi {
|
public interface ProcessConfigApi {
|
||||||
|
|
||||||
|
|||||||
@ -40,6 +40,7 @@ public interface BpmnConstants {
|
|||||||
@Deprecated
|
@Deprecated
|
||||||
String OLD_INTERNAL_TASK_RELATION_ASSIGNEE_INFO_SNAPSHOT = "[_ASSIGNEE_INFO_SNAPSHOT_]";
|
String OLD_INTERNAL_TASK_RELATION_ASSIGNEE_INFO_SNAPSHOT = "[_ASSIGNEE_INFO_SNAPSHOT_]";
|
||||||
String INTERNAL_ACTIVITY_RELATION_ASSIGNEE_LIST_INFO_SNAPSHOT = "[_ACTIVITY_INFO_SNAPSHOT_]";
|
String INTERNAL_ACTIVITY_RELATION_ASSIGNEE_LIST_INFO_SNAPSHOT = "[_ACTIVITY_INFO_SNAPSHOT_]";
|
||||||
|
String BIZ_NODE_ALTER = "[_BIZ_NODE_ALTER_]";
|
||||||
String PROCESS_PREFIX = "Flowable";
|
String PROCESS_PREFIX = "Flowable";
|
||||||
@Deprecated
|
@Deprecated
|
||||||
String OLD_TASK_ASSIGNEE_SKIP_FLAT = "taskSkip";
|
String OLD_TASK_ASSIGNEE_SKIP_FLAT = "taskSkip";
|
||||||
@ -108,6 +109,7 @@ public interface BpmnConstants {
|
|||||||
String BPM_MODEL_CATEGORY = "bpm_model_category";
|
String BPM_MODEL_CATEGORY = "bpm_model_category";
|
||||||
String BPM_ALLOW_SKIP_USER_TASK = "_INTERNAL_SKIP_USER_TASK_";
|
String BPM_ALLOW_SKIP_USER_TASK = "_INTERNAL_SKIP_USER_TASK_";
|
||||||
String AUTO_APPROVAL_TYPE = "autoApprovalType";
|
String AUTO_APPROVAL_TYPE = "autoApprovalType";
|
||||||
|
String PROCESS_CLOSING_TYPE = "[_PROCESS_CLOSING_TYPE]";
|
||||||
/**
|
/**
|
||||||
* 用于国内审批节点填写审批建议
|
* 用于国内审批节点填写审批建议
|
||||||
* <p>
|
* <p>
|
||||||
@ -120,6 +122,8 @@ public interface BpmnConstants {
|
|||||||
String NUMBER_OF_INSTANCES = "nrOfInstances";
|
String NUMBER_OF_INSTANCES = "nrOfInstances";
|
||||||
String MULTI_INSTANCE_LOOP_COUNTER = "loopCounter";
|
String MULTI_INSTANCE_LOOP_COUNTER = "loopCounter";
|
||||||
String TASK_COMPLETE_OPERATION_TYPE = "_TASK_COMPLETE_TYPE";
|
String TASK_COMPLETE_OPERATION_TYPE = "_TASK_COMPLETE_TYPE";
|
||||||
|
String TASK_ATTACHMENTS_VAR_NAME = "TASK_ATTACHMENTS";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 会签表达式
|
* 会签表达式
|
||||||
*/
|
*/
|
||||||
@ -178,4 +182,9 @@ public interface BpmnConstants {
|
|||||||
* 加签显示人员数量
|
* 加签显示人员数量
|
||||||
*/
|
*/
|
||||||
Integer COUNTERSIGN_ASSIGNER_SHOW_NUMBER = 2;
|
Integer COUNTERSIGN_ASSIGNER_SHOW_NUMBER = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回退操作次数上限
|
||||||
|
*/
|
||||||
|
Integer MAX_BACKED_OPERATE_COUNT = 20;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
package cn.axzo.workflow.common.enums;
|
package cn.axzo.workflow.common.enums;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 审批方式枚举
|
* 审批方式枚举
|
||||||
*
|
*
|
||||||
@ -48,4 +51,11 @@ public enum ApprovalMethodEnum {
|
|||||||
public void setRemark(String remark) {
|
public void setRemark(String remark) {
|
||||||
this.remark = remark;
|
this.remark = remark;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ApprovalMethodEnum valueOfType(String type) {
|
||||||
|
return Arrays.stream(ApprovalMethodEnum.values())
|
||||||
|
.filter(i -> Objects.equals(i.getType(), type))
|
||||||
|
.findAny()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
package cn.axzo.workflow.common.enums;
|
package cn.axzo.workflow.common.enums;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public enum BpmnFlowNodeMode {
|
public enum BpmnFlowNodeMode {
|
||||||
GENERAL("GENERAL", "普通节点"),
|
GENERAL("GENERAL", "普通节点"),
|
||||||
OR("OR", "或签节点"),
|
OR("OR", "或签节点"),
|
||||||
@ -35,4 +38,11 @@ public enum BpmnFlowNodeMode {
|
|||||||
public void setDesc(String desc) {
|
public void setDesc(String desc) {
|
||||||
this.desc = desc;
|
this.desc = desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static BpmnFlowNodeMode valueOfType(String type) {
|
||||||
|
return Arrays.stream(BpmnFlowNodeMode.values())
|
||||||
|
.filter(i -> Objects.equals(i.getType(), type))
|
||||||
|
.findAny()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
package cn.axzo.workflow.common.enums;
|
package cn.axzo.workflow.common.enums;
|
||||||
|
|
||||||
|
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@ -51,6 +53,19 @@ public enum BpmnFlowNodeType {
|
|||||||
this.desc = desc;
|
this.desc = desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static BpmnFlowNodeType getByType(String type) {
|
||||||
|
if (!StringUtils.hasText(type)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
BpmnFlowNodeType[] values = BpmnFlowNodeType.values();
|
||||||
|
for (BpmnFlowNodeType value : values) {
|
||||||
|
if (value.getType().equals(type)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public static BpmnFlowNodeType valueOfType(String type) {
|
public static BpmnFlowNodeType valueOfType(String type) {
|
||||||
return Arrays.stream(BpmnFlowNodeType.values())
|
return Arrays.stream(BpmnFlowNodeType.values())
|
||||||
.filter(i -> Objects.equals(i.getType(), type))
|
.filter(i -> Objects.equals(i.getType(), type))
|
||||||
|
|||||||
@ -6,6 +6,7 @@ public enum BpmnProcessInstanceResultEnum {
|
|||||||
PROCESSING("PROCESSING", "审批中"),
|
PROCESSING("PROCESSING", "审批中"),
|
||||||
APPROVED("APPROVED", "已通过"),
|
APPROVED("APPROVED", "已通过"),
|
||||||
REJECTED("REJECTED", "已驳回"),
|
REJECTED("REJECTED", "已驳回"),
|
||||||
|
BACKED("BACKED", "已回退"),
|
||||||
CANCELLED("CANCELLED", "已撤回"),
|
CANCELLED("CANCELLED", "已撤回"),
|
||||||
ABORTED("ABORTED", "已中止"),
|
ABORTED("ABORTED", "已中止"),
|
||||||
TRANSFER("TRANSFER", "已转交"),
|
TRANSFER("TRANSFER", "已转交"),
|
||||||
|
|||||||
@ -10,8 +10,8 @@ import cn.axzo.framework.rocketmq.Event;
|
|||||||
*/
|
*/
|
||||||
public enum ProcessTaskEventEnum {
|
public enum ProcessTaskEventEnum {
|
||||||
|
|
||||||
PROCESS_TASK_CREATED("process-task", "process-task-created", "流程任务已创建"),
|
|
||||||
PROCESS_TASK_ASSIGNED("process-task", "process-task-assigned", "流程任务已分配"),
|
PROCESS_TASK_ASSIGNED("process-task", "process-task-assigned", "流程任务已分配"),
|
||||||
|
PROCESS_TASK_CREATED("process-task", "process-task-created", "流程任务已创建"),
|
||||||
PROCESS_TASK_COMPLETED("process-task", "process-task-completed", "流程任务已结束"),
|
PROCESS_TASK_COMPLETED("process-task", "process-task-completed", "流程任务已结束"),
|
||||||
PROCESS_TASK_DELETED("process-task", "process-task-deleted", "流程任务已删除"),
|
PROCESS_TASK_DELETED("process-task", "process-task-deleted", "流程任务已删除"),
|
||||||
;
|
;
|
||||||
|
|||||||
@ -0,0 +1,25 @@
|
|||||||
|
package cn.axzo.workflow.common.model.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 告警对象
|
||||||
|
*
|
||||||
|
* @author wangli
|
||||||
|
* @since 2024-09-13 11:37
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class AlterDTO {
|
||||||
|
private String processInstanceId;
|
||||||
|
|
||||||
|
private String activityId;
|
||||||
|
|
||||||
|
private String taskId;
|
||||||
|
|
||||||
|
private Date startTime;
|
||||||
|
|
||||||
|
private String prettyStartTime;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
package cn.axzo.workflow.common.model.dto;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 卡住节点的查询条件模型
|
||||||
|
*
|
||||||
|
* @author wangli
|
||||||
|
* @since 2024-09-11 13:57
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public class TermNodePausingDTO implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -1L;
|
||||||
|
private String processInstanceId;
|
||||||
|
|
||||||
|
private String activityId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重试次数
|
||||||
|
*/
|
||||||
|
private Integer retries;
|
||||||
|
|
||||||
|
}
|
||||||
@ -3,18 +3,23 @@ package cn.axzo.workflow.common.model.request;
|
|||||||
import cn.axzo.workflow.common.enums.AutoApprovalTypeEnum;
|
import cn.axzo.workflow.common.enums.AutoApprovalTypeEnum;
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
|
||||||
@ApiModel("JSON 版本的 BPMN 协议模型中流程配置管理")
|
@ApiModel("JSON 版本的 BPMN 协议模型中流程配置管理")
|
||||||
@Data
|
@Data
|
||||||
@NoArgsConstructor
|
@AllArgsConstructor
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
public class BpmnApproveConf {
|
public class BpmnApproveConf {
|
||||||
|
|
||||||
|
public BpmnApproveConf() {
|
||||||
|
this.supportBatchOperation = false;
|
||||||
|
this.userAgreeSignature = false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否支持批量审批
|
* 是否支持批量审批
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import lombok.NoArgsConstructor;
|
|||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,25 +26,25 @@ public class BpmnButtonConf implements Serializable {
|
|||||||
* 发起人的按钮配置信息, 需要给全量按钮的配置
|
* 发起人的按钮配置信息, 需要给全量按钮的配置
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "发起人的按钮配置信息")
|
@ApiModelProperty(value = "发起人的按钮配置信息")
|
||||||
private List<BpmnButtonMetaInfo> initiator;
|
private List<BpmnButtonMetaInfo> initiator = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当前审批人的按钮配置信息, JSON 格式
|
* 当前审批人的按钮配置信息, JSON 格式
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "当前审批人的按钮配置信息")
|
@ApiModelProperty(value = "当前审批人的按钮配置信息")
|
||||||
private List<BpmnButtonMetaInfo> current;
|
private List<BpmnButtonMetaInfo> current = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 历史审批人的按钮配置信息, JSON 格式
|
* 历史审批人的按钮配置信息, JSON 格式
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "历史审批人的按钮配置信息")
|
@ApiModelProperty(value = "历史审批人的按钮配置信息")
|
||||||
private List<BpmnButtonMetaInfo> history;
|
private List<BpmnButtonMetaInfo> history = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 抄送人的按钮配置信息, JSON 格式
|
* 抄送人的按钮配置信息, JSON 格式
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "抄送人的按钮配置信息")
|
@ApiModelProperty(value = "抄送人的按钮配置信息")
|
||||||
private List<BpmnButtonMetaInfo> carbonCopy;
|
private List<BpmnButtonMetaInfo> carbonCopy = new ArrayList<>();
|
||||||
|
|
||||||
public List<BpmnButtonMetaInfo> getInitiator() {
|
public List<BpmnButtonMetaInfo> getInitiator() {
|
||||||
return initiator;
|
return initiator;
|
||||||
|
|||||||
@ -36,6 +36,7 @@ public class BpmnProcessInstanceCancelDTO {
|
|||||||
* 工作台 ID
|
* 工作台 ID
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "工作台 ID")
|
@ApiModelProperty(value = "工作台 ID")
|
||||||
|
@NotBlank(message = "工作台不能为空")
|
||||||
private String tenantId;
|
private String tenantId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -43,9 +43,9 @@ public class BpmnProcessInstanceCreateDTO {
|
|||||||
* 发起流程实例归属租户 ID
|
* 发起流程实例归属租户 ID
|
||||||
* <p>
|
* <p>
|
||||||
* 为空时,默认是编辑公共流程模型, 如果是代运营创建,则必填
|
* 为空时,默认是编辑公共流程模型, 如果是代运营创建,则必填
|
||||||
|
* <h1 color=red>建议都传值,在安心筑中对应工作台 ID</h1>
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "发起的审批是属于哪个租户")
|
@ApiModelProperty(value = "发起的审批是属于哪个租户")
|
||||||
// @NotBlank(message = "审批实例归属租户 ID 不能为空")
|
|
||||||
private String tenantId;
|
private String tenantId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -0,0 +1,54 @@
|
|||||||
|
package cn.axzo.workflow.common.model.request.bpmn.process;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询流程实例日志
|
||||||
|
*
|
||||||
|
* @author wangli
|
||||||
|
* @since 2024-09-07 17:32
|
||||||
|
*/
|
||||||
|
@ApiModel("查询流程实例日志")
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public class BpmnProcessInstanceLogQueryDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程实例 ID
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "流程实例 ID")
|
||||||
|
@NotBlank(message = "流程实例 ID 不能为空")
|
||||||
|
private String processInstanceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 谁来访问该实例日志,如果为空,则始终不就返回按钮信息
|
||||||
|
* <p>
|
||||||
|
* 注意,为了确保历史审批数据的查询,需要将除 avatar 外的其他所有属性补全
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "访问者信息", notes = "如果为空,则始终不就返回按钮信息")
|
||||||
|
private BpmnTaskDelegateAssigner visitor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回结果中是否包含按钮
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "返回结果中是否包含按钮", notes = "如果访问者为空,该属性为 true 时,同样也不会返回按钮")
|
||||||
|
private Boolean hasButton = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否需要加密(同一个实例的日志,在不同端[cms/oms]下,审批人的信息需要按一定规则进行隐藏控制)
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "是否需要加密", notes = "同一个实例的日志,在不同端[cms/oms]下,审批人的信息需要按一定规则进行隐藏控制")
|
||||||
|
private Boolean encrypt;
|
||||||
|
}
|
||||||
@ -3,10 +3,14 @@ package cn.axzo.workflow.common.model.request.bpmn.task;
|
|||||||
import cn.axzo.workflow.common.enums.AttachmentTypeEnum;
|
import cn.axzo.workflow.common.enums.AttachmentTypeEnum;
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
import javax.validation.constraints.NotBlank;
|
import javax.validation.constraints.NotBlank;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 附件模型
|
* 附件模型
|
||||||
@ -16,8 +20,12 @@ import javax.validation.constraints.NotNull;
|
|||||||
*/
|
*/
|
||||||
@ApiModel("附件模型")
|
@ApiModel("附件模型")
|
||||||
@Data
|
@Data
|
||||||
public class AttachmentDTO {
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class AttachmentDTO implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 6954179791395744269L;
|
||||||
/**
|
/**
|
||||||
* 附件 ID
|
* 附件 ID
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -53,7 +53,6 @@ public class BpmnActivitySetAssigneeDTO {
|
|||||||
* 业务如果传入的 assigners 集合为空, 引擎则会对该流程进行自动驳回处理,且驳回意见为“业务未指定审批人”
|
* 业务如果传入的 assigners 集合为空, 引擎则会对该流程进行自动驳回处理,且驳回意见为“业务未指定审批人”
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "审批人集合信息", notes = "业务传参时,需要注意去重")
|
@ApiModelProperty(value = "审批人集合信息", notes = "业务传参时,需要注意去重")
|
||||||
@Valid
|
|
||||||
@Size(max = 60, message = "指定审批人数量限制为60")
|
@Size(max = 60, message = "指定审批人数量限制为60")
|
||||||
private List<BpmnTaskDelegateAssigner> assigners;
|
private List<BpmnTaskDelegateAssigner> assigners;
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,37 @@
|
|||||||
|
package cn.axzo.workflow.common.model.request.bpmn.task;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推动业务节点继续执行
|
||||||
|
*
|
||||||
|
* @author wangli
|
||||||
|
* @since 2024-09-09 13:46
|
||||||
|
*/
|
||||||
|
@ApiModel("业务节点设置审批人")
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public class BpmnActivityTriggerDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务节点的触发 ID
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "触发 ID 不能为空")
|
||||||
|
@ApiModelProperty(value = "触发 ID", notes = "数据来源于事件")
|
||||||
|
private String triggerId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否异步执行
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "是否异步", notes = "异步时,只接收请求便返回数据")
|
||||||
|
private Boolean async = true;
|
||||||
|
}
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
package cn.axzo.workflow.common.model.request.bpmn.task;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.common.enums.BpmnFlowNodeType;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回退到指定节点,可选节点模型
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
public class BpmnOptionalNodeDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对应流程实例id
|
||||||
|
*/
|
||||||
|
private String processInstanceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对应流程定义id
|
||||||
|
*/
|
||||||
|
private String processDefinitionId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点id
|
||||||
|
*/
|
||||||
|
private String processActivityId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点名称
|
||||||
|
*/
|
||||||
|
private String processActivityName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点描述,用于页面展示
|
||||||
|
*/
|
||||||
|
private String processNodeDesc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点类型
|
||||||
|
*/
|
||||||
|
private BpmnFlowNodeType nodeType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 序号,越小越靠近发起节点
|
||||||
|
*/
|
||||||
|
private Integer ordinal;
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
package cn.axzo.workflow.common.model.request.bpmn.task;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ApiModel("回退到指定节点入参模型")
|
||||||
|
@Data
|
||||||
|
@Validated
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class BpmnTaskBackAuditDTO extends BpmnTaskAuditDTO implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -4160538355403179298L;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "目标流程节点id", required = true)
|
||||||
|
@NotBlank(message = "目标流程节点id不能为空")
|
||||||
|
private String toActivityId;
|
||||||
|
}
|
||||||
@ -0,0 +1,159 @@
|
|||||||
|
package cn.axzo.workflow.common.model.response.bpmn.process;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum;
|
||||||
|
import cn.axzo.workflow.common.enums.WorkspaceType;
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.BpmnButtonConf;
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.BpmnButtonMetaInfo;
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||||
|
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskInstanceLogVO;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程实例日志模型
|
||||||
|
*
|
||||||
|
* @author wangli
|
||||||
|
* @since 2024-09-07 17:07
|
||||||
|
*/
|
||||||
|
@ApiModel("流程实例日志模型")
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class BpmnProcessInstanceLogVO {
|
||||||
|
/**
|
||||||
|
* 流程实例的编号
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "流程实例的编号", example = "1024")
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程名称
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "流程名称", example = "权限点申请")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程分类
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "流程分类", notes = "关联的业务分类", example = "1")
|
||||||
|
private String category;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审核状态
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "审核状态(PROCESSING:审核中,APPROVED:已通过,REJECTED:已拒绝,CANCELLED:已取消)", example = "APPROVED")
|
||||||
|
private BpmnProcessInstanceResultEnum result;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发起时间
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("发起时间")
|
||||||
|
private Date startTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结束时间
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("结束时间")
|
||||||
|
private Date endTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程定义 KEY
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("流程定义 KEY")
|
||||||
|
private String processDefinitionKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程定义 ID
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("流程定义 ID")
|
||||||
|
private String processDefinitionId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务的唯一标识
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "业务的唯一标识", example = "1", notes = "例如说,请假申请的编号")
|
||||||
|
private String businessKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程最终状态
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("流程最终状态")
|
||||||
|
private String businessStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发起人
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("发起人")
|
||||||
|
private BpmnTaskDelegateAssigner initiator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前流程发起租户
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("当前流程发起租户")
|
||||||
|
private String tenantId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是代运营的流程
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("是代运营的流程")
|
||||||
|
private Boolean agented;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务信息集合
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("任务信息集合")
|
||||||
|
private List<BpmnTaskInstanceLogVO> taskDetails;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前实例对应模型的全局兜底按钮配置
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "当前实例对应模型的全局兜底按钮配置")
|
||||||
|
private BpmnButtonConf defaultButtonConf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指定人访问实例日志时,计算其流程应该有权限操作的按钮
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "指定人访问实例日志时,计算其流程应该有权限操作的按钮", notes = "流程有权限,不代表待办消息中一定能看到按钮")
|
||||||
|
private List<BpmnButtonMetaInfo> currentUserButtons;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 需要隐藏的自定义按钮集合
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "需要隐藏的自定义按钮集合")
|
||||||
|
private List<BpmnButtonMetaInfo> customHiddenButtons;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否支持批量审批
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "是否支持批量审批")
|
||||||
|
private Boolean supportBatchOperation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审批同意录入手写签名
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "审批同意录入手写签名")
|
||||||
|
private Boolean userAgreeSignature;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据产生版本
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "数据产生版本")
|
||||||
|
private String workflowEngineVersion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前流程对应工作台类型
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "工作台类型")
|
||||||
|
private WorkspaceType workspaceType;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "程序计算按钮使用,非对外使用", hidden = true)
|
||||||
|
private transient BpmnButtonConf calculatingButtonConf;
|
||||||
|
}
|
||||||
@ -0,0 +1,127 @@
|
|||||||
|
package cn.axzo.workflow.common.model.response.bpmn.task;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.common.enums.ApprovalMethodEnum;
|
||||||
|
import cn.axzo.workflow.common.enums.BpmnFlowNodeMode;
|
||||||
|
import cn.axzo.workflow.common.enums.BpmnFlowNodeType;
|
||||||
|
import cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum;
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.BpmnButtonConf;
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.task.AttachmentDTO;
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程任务日志模型
|
||||||
|
*
|
||||||
|
* @author wangli
|
||||||
|
* @since 2024-09-07 17:08
|
||||||
|
*/
|
||||||
|
@ApiModel("流程任务日志模型")
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class BpmnTaskInstanceLogVO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审批任务 ID
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "审批任务 ID")
|
||||||
|
private String taskId;
|
||||||
|
/**
|
||||||
|
* 审批任务节点定义KEY
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "审批任务节点定义KEY")
|
||||||
|
private String taskDefinitionKey;
|
||||||
|
/**
|
||||||
|
* 审批任务节点名称
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "审批任务节点名称")
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 任务创建时间
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "任务创建时间")
|
||||||
|
private Date createTime;
|
||||||
|
/**
|
||||||
|
* 任务结束时间
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "任务结束时间")
|
||||||
|
private Date endTime;
|
||||||
|
/**
|
||||||
|
* 审批方式
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "审批方式")
|
||||||
|
private ApprovalMethodEnum approvalMethod;
|
||||||
|
/**
|
||||||
|
* 节点类型
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "节点类型")
|
||||||
|
private BpmnFlowNodeType nodeType;
|
||||||
|
/**
|
||||||
|
* 审批任务节点的类型
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "审批任务节点的类型")
|
||||||
|
private BpmnFlowNodeMode nodeMode;
|
||||||
|
/**
|
||||||
|
* 任务状态
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "任务状态")
|
||||||
|
private BpmnProcessInstanceResultEnum result;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作描述
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "操作描述")
|
||||||
|
private String operationDesc;
|
||||||
|
/**
|
||||||
|
* 审批建议
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "审批建议")
|
||||||
|
private String advice;
|
||||||
|
/**
|
||||||
|
* 一些扩展信息
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "一些扩展信息")
|
||||||
|
private String commentExt;
|
||||||
|
/**
|
||||||
|
* 图片列表
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "图片列表")
|
||||||
|
private List<AttachmentDTO> imageList;
|
||||||
|
/**
|
||||||
|
* 附件列表
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "附件列表")
|
||||||
|
private List<AttachmentDTO> fileList;
|
||||||
|
/**
|
||||||
|
* 手写签名地址
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "手写签名地址")
|
||||||
|
private String signatureUrl;
|
||||||
|
/**
|
||||||
|
* 审批人快照信息
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "审批人快照信息")
|
||||||
|
private BpmnTaskDelegateAssigner assigneeSnapshot;
|
||||||
|
/**
|
||||||
|
* 未完成节点多实例模式的审批人信息
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "未完成节点多实例模式的审批人信息")
|
||||||
|
private List<BpmnTaskDelegateAssigner> forecastAssignees;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "程序计算按钮使用,非对外使用", hidden = true)
|
||||||
|
private transient BpmnButtonConf buttonConf;
|
||||||
|
|
||||||
|
public boolean isVirtual() {
|
||||||
|
return StringUtils.isBlank(this.taskId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,6 +3,7 @@ package cn.axzo.workflow.common.model.response.mq;
|
|||||||
import cn.axzo.workflow.common.enums.BpmnNoticeEnum;
|
import cn.axzo.workflow.common.enums.BpmnNoticeEnum;
|
||||||
import cn.axzo.workflow.common.enums.ProcessTaskEventEnum;
|
import cn.axzo.workflow.common.enums.ProcessTaskEventEnum;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.BpmnNoticeConf;
|
import cn.axzo.workflow.common.model.request.bpmn.BpmnNoticeConf;
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.task.AttachmentDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
@ -44,6 +45,10 @@ public class ProcessTaskDTO implements Serializable {
|
|||||||
* 流程实例 ID
|
* 流程实例 ID
|
||||||
*/
|
*/
|
||||||
private String processInstanceId;
|
private String processInstanceId;
|
||||||
|
/**
|
||||||
|
* 流程实例的businessKey
|
||||||
|
*/
|
||||||
|
private String businessKey;
|
||||||
/**
|
/**
|
||||||
* 流程实例所属业务分类,同时也等于流程模型对应的业务分类 ID
|
* 流程实例所属业务分类,同时也等于流程模型对应的业务分类 ID
|
||||||
*/
|
*/
|
||||||
@ -103,4 +108,13 @@ public class ProcessTaskDTO implements Serializable {
|
|||||||
* 当前数据的流程引擎版本
|
* 当前数据的流程引擎版本
|
||||||
*/
|
*/
|
||||||
private String workflowEngineVersion;
|
private String workflowEngineVersion;
|
||||||
|
/**
|
||||||
|
* 任务关联的附件
|
||||||
|
*/
|
||||||
|
private List<AttachmentDTO> attachments;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审批意见
|
||||||
|
*/
|
||||||
|
private String advice;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -89,17 +89,25 @@
|
|||||||
<groupId>cn.axzo.workflow</groupId>
|
<groupId>cn.axzo.workflow</groupId>
|
||||||
<artifactId>workflow-engine-api</artifactId>
|
<artifactId>workflow-engine-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.axzo.workflow</groupId>
|
<groupId>cn.axzo.workflow</groupId>
|
||||||
<artifactId>workflow-engine-common</artifactId>
|
<artifactId>workflow-engine-common</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.maven</groupId>
|
<groupId>org.apache.maven</groupId>
|
||||||
<artifactId>maven-artifact</artifactId>
|
<artifactId>maven-artifact</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>jakarta.servlet</groupId>
|
<groupId>jakarta.servlet</groupId>
|
||||||
<artifactId>jakarta.servlet-api</artifactId>
|
<artifactId>jakarta.servlet-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aliyun</groupId>
|
||||||
|
<artifactId>alibaba-dingtalk-service-sdk</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@ -27,6 +27,7 @@ public enum BpmnInstanceRespCode implements IModuleRespCode {
|
|||||||
TASK_CANT_COMMENT_INSTANCE_NOT_EXISTS("012", "流程实例【{}】不存在, 不能评论"),
|
TASK_CANT_COMMENT_INSTANCE_NOT_EXISTS("012", "流程实例【{}】不存在, 不能评论"),
|
||||||
RUNNING_INSTANCE_ONLY_FORECAST("013", "仅运行中的实例可以推测"),
|
RUNNING_INSTANCE_ONLY_FORECAST("013", "仅运行中的实例可以推测"),
|
||||||
ENGINE_EXEC_EXCEPTION("014", "引擎内部异常"),
|
ENGINE_EXEC_EXCEPTION("014", "引擎内部异常"),
|
||||||
|
PROCESS_TASK_NOT_EXISTS("015", "流程任务不存在或已处理"),
|
||||||
;
|
;
|
||||||
private final String code;
|
private final String code;
|
||||||
private final String message;
|
private final String message;
|
||||||
|
|||||||
@ -37,6 +37,9 @@ public enum BpmnTaskRespCode implements IModuleRespCode {
|
|||||||
TASK_TYPE_MISMATCH("020", "节点类型不匹配,当前节点类型:【{}】,指定节点类型:【{}】!"),
|
TASK_TYPE_MISMATCH("020", "节点类型不匹配,当前节点类型:【{}】,指定节点类型:【{}】!"),
|
||||||
PROCESS_CANT_SET_ASSIGNEE("021", "当前审批状态不允许设置审批人"),
|
PROCESS_CANT_SET_ASSIGNEE("021", "当前审批状态不允许设置审批人"),
|
||||||
ASSIGNER_NUMBER_EXCEEDS_NUMBER_LIMIT("022", String.format("人员数量超过限制,节点审批人限制数量为: %d!", APPROVAL_ASSIGNER_LIMIT_NUMBER)),
|
ASSIGNER_NUMBER_EXCEEDS_NUMBER_LIMIT("022", String.format("人员数量超过限制,节点审批人限制数量为: %d!", APPROVAL_ASSIGNER_LIMIT_NUMBER)),
|
||||||
|
BACK_TARGET_ACTIVITY_NOT_EXISTS("023", "回退到指定节点【{}】失败!"),
|
||||||
|
BACK_NODE_CANNOT_REACHABLE("024", "退回节点【{}】不可达,不允许退回"),
|
||||||
|
REACHED_BACKED_MAXIMUM_NUM("025", "达到回退操作次数上限【{}】次"),
|
||||||
;
|
;
|
||||||
|
|
||||||
private final String code;
|
private final String code;
|
||||||
|
|||||||
@ -19,7 +19,7 @@ public enum FlowableEngineRespCode implements IModuleRespCode {
|
|||||||
ENGINE_USER_TASK_PARAM_ERROR("004", "构建后的查询审批人入参为空. 任务节点【nodeId:{}】, 该节点选择的\"审批人所在范围\"是:【{}】,请检查 cooperationOrg 参数"),
|
ENGINE_USER_TASK_PARAM_ERROR("004", "构建后的查询审批人入参为空. 任务节点【nodeId:{}】, 该节点选择的\"审批人所在范围\"是:【{}】,请检查 cooperationOrg 参数"),
|
||||||
ENGINE_NOTICE_CUSTOM_FLOW_ELEMENT_ERROR("005", "查询通知目标用户前参数发生异常,未获取到 WorkspaceType"),
|
ENGINE_NOTICE_CUSTOM_FLOW_ELEMENT_ERROR("005", "查询通知目标用户前参数发生异常,未获取到 WorkspaceType"),
|
||||||
ENGINE_ASYNC_COMMAND_EXECUTION_ERROR("006", "引擎出现 SQL 相关异常, 异常信息:【{}】"),
|
ENGINE_ASYNC_COMMAND_EXECUTION_ERROR("006", "引擎出现 SQL 相关异常, 异常信息:【{}】"),
|
||||||
ENGINE_ASYNC_COMMAND_EXECUTION_RETRY_GIVE_UP("007", "命令重试尝试【{}】次仍然失败,并出现异常, 将放弃"),
|
ENGINE_ASYNC_COMMAND_EXECUTION_RETRY_GIVE_UP("007", "命令重试尝试【{}】次仍然失败,并出现异常, 将放弃, 错误信息:{}"),
|
||||||
;
|
;
|
||||||
|
|
||||||
private final String code;
|
private final String code;
|
||||||
|
|||||||
@ -9,7 +9,8 @@ import java.util.Arrays;
|
|||||||
* @since 2023/9/18 17:11
|
* @since 2023/9/18 17:11
|
||||||
*/
|
*/
|
||||||
public enum BpmnProcessTaskResultEnum {
|
public enum BpmnProcessTaskResultEnum {
|
||||||
|
PENDING("PENDING", "待处理"),
|
||||||
|
PROCESSED("PROCESSED", "已处理"),
|
||||||
AUTO_SKIP("AUTO_SKIP", "任务自动跳过"),
|
AUTO_SKIP("AUTO_SKIP", "任务自动跳过"),
|
||||||
// 引擎默认的标识,不允许修改
|
// 引擎默认的标识,不允许修改
|
||||||
MI_END("MI_END", "多实例任务运行结束"),
|
MI_END("MI_END", "多实例任务运行结束"),
|
||||||
@ -17,8 +18,7 @@ public enum BpmnProcessTaskResultEnum {
|
|||||||
DELETE_MI_EXECUTION("Delete MI execution", "多实例任务被删除"),
|
DELETE_MI_EXECUTION("Delete MI execution", "多实例任务被删除"),
|
||||||
INITIATOR_REVOCATION("INITIATOR_REVOCATION", "发起者主动撤回"),
|
INITIATOR_REVOCATION("INITIATOR_REVOCATION", "发起者主动撤回"),
|
||||||
REJECTION_AUTO_COMPLETED("REJECTION_AUTO_COMPLETED", "审批驳回自动结束"),
|
REJECTION_AUTO_COMPLETED("REJECTION_AUTO_COMPLETED", "审批驳回自动结束"),
|
||||||
BACKED("BACKED", "退回");
|
;
|
||||||
|
|
||||||
private final String status;
|
private final String status;
|
||||||
/**
|
/**
|
||||||
* 描述
|
* 描述
|
||||||
|
|||||||
@ -0,0 +1,91 @@
|
|||||||
|
package cn.axzo.workflow.core.common.utils;
|
||||||
|
|
||||||
|
import org.flowable.bpmn.model.EventSubProcess;
|
||||||
|
import org.flowable.bpmn.model.FlowElement;
|
||||||
|
import org.flowable.bpmn.model.FlowElementsContainer;
|
||||||
|
import org.flowable.bpmn.model.FlowNode;
|
||||||
|
import org.flowable.bpmn.model.SequenceFlow;
|
||||||
|
import org.flowable.bpmn.model.StartEvent;
|
||||||
|
import org.flowable.bpmn.model.SubProcess;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class BpmnModelUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点是否可达
|
||||||
|
* @param process
|
||||||
|
* @param sourceElement
|
||||||
|
* @param targetElement
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean isReachable(org.flowable.bpmn.model.Process process, FlowNode sourceElement, FlowNode targetElement) {
|
||||||
|
return isReachable(process, sourceElement, targetElement, new HashSet<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isReachable(org.flowable.bpmn.model.Process process, FlowNode sourceElement, FlowNode targetElement, Set<String> visitedElements) {
|
||||||
|
// Special case: start events in an event subprocess might exist as an execution and are most likely be able to
|
||||||
|
// reach the target
|
||||||
|
// when the target is in the event subprocess, but should be ignored as they are not 'real' runtime executions
|
||||||
|
// (but rather waiting for trigger)
|
||||||
|
if (sourceElement instanceof StartEvent && isInEventSubprocess(sourceElement)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// No outgoing seq flow: could be the end of eg . the process or an embedded subprocess
|
||||||
|
if (sourceElement.getOutgoingFlows().isEmpty()) {
|
||||||
|
visitedElements.add(sourceElement.getId());
|
||||||
|
FlowElementsContainer parentElement = process.findParent(sourceElement);
|
||||||
|
if (parentElement instanceof SubProcess) {
|
||||||
|
sourceElement = (SubProcess) parentElement;
|
||||||
|
// 子流程的结束节点,若目标节点在该子流程中,说明无法到达,返回false
|
||||||
|
if (((SubProcess) sourceElement).getFlowElement(targetElement.getId()) != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sourceElement.getId().equals(targetElement.getId())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// To avoid infinite looping, we must capture every node we visit
|
||||||
|
// and check before going further in the graph if we have already
|
||||||
|
// visited the node.
|
||||||
|
visitedElements.add(sourceElement.getId());
|
||||||
|
// 当前节点能够到达子流程,且目标节点在子流程中,说明可以到达,返回true
|
||||||
|
if (sourceElement instanceof SubProcess && ((SubProcess) sourceElement).getFlowElement(targetElement.getId()) != null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
List<SequenceFlow> sequenceFlows = sourceElement.getOutgoingFlows();
|
||||||
|
if (sequenceFlows != null && !sequenceFlows.isEmpty()) {
|
||||||
|
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||||
|
String targetRef = sequenceFlow.getTargetRef();
|
||||||
|
FlowNode sequenceFlowTarget = (FlowNode) process.getFlowElement(targetRef, true);
|
||||||
|
if (sequenceFlowTarget != null && !visitedElements.contains(sequenceFlowTarget.getId())) {
|
||||||
|
boolean reachable = isReachable(process, sequenceFlowTarget, targetElement, visitedElements);
|
||||||
|
if (reachable) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static boolean isInEventSubprocess(FlowNode flowNode) {
|
||||||
|
FlowElementsContainer flowElementsContainer = flowNode.getParentContainer();
|
||||||
|
while (flowElementsContainer != null) {
|
||||||
|
if (flowElementsContainer instanceof EventSubProcess) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (flowElementsContainer instanceof FlowElement) {
|
||||||
|
flowElementsContainer = ((FlowElement) flowElementsContainer).getParentContainer();
|
||||||
|
} else {
|
||||||
|
flowElementsContainer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,15 +5,18 @@ import cn.axzo.workflow.core.engine.behavior.CustomActivityBehaviorFactory;
|
|||||||
import cn.axzo.workflow.core.engine.cmd.CustomCommandContextFactory;
|
import cn.axzo.workflow.core.engine.cmd.CustomCommandContextFactory;
|
||||||
import cn.axzo.workflow.core.engine.id.BasedNacosSnowflakeIdGenerator;
|
import cn.axzo.workflow.core.engine.id.BasedNacosSnowflakeIdGenerator;
|
||||||
import cn.axzo.workflow.core.engine.interceptor.CustomRetryInterceptor;
|
import cn.axzo.workflow.core.engine.interceptor.CustomRetryInterceptor;
|
||||||
import cn.axzo.workflow.core.engine.job.AsyncAbortProcessInstanceHandler;
|
|
||||||
import cn.axzo.workflow.core.engine.job.AsyncActivityCallbackJobHandler;
|
import cn.axzo.workflow.core.engine.job.AsyncActivityCallbackJobHandler;
|
||||||
import cn.axzo.workflow.core.engine.job.AsyncActivityLeaveJobHandler;
|
import cn.axzo.workflow.core.engine.job.AsyncActivityLeaveJobHandler;
|
||||||
|
import cn.axzo.workflow.core.engine.job.AsyncAbortProcessInstanceJobHandler;
|
||||||
|
import cn.axzo.workflow.core.engine.job.AsyncActivitySetAssigneeJobHandler;
|
||||||
|
import cn.axzo.workflow.core.engine.job.AsyncActivityTriggerJobHandler;
|
||||||
import cn.axzo.workflow.core.engine.job.AsyncApproveTaskJobHandler;
|
import cn.axzo.workflow.core.engine.job.AsyncApproveTaskJobHandler;
|
||||||
import cn.axzo.workflow.core.engine.job.AsyncBpmnProcessActivityJobHandler;
|
import cn.axzo.workflow.core.engine.job.AsyncBackTaskJobHandler;
|
||||||
import cn.axzo.workflow.core.engine.job.AsyncCancelProcessInstanceHandler;
|
import cn.axzo.workflow.core.engine.job.AsyncCancelProcessInstanceJobHandler;
|
||||||
import cn.axzo.workflow.core.engine.job.AsyncCountersignUserTaskJobHandler;
|
import cn.axzo.workflow.core.engine.job.AsyncCountersignUserTaskJobHandler;
|
||||||
import cn.axzo.workflow.core.engine.job.AsyncExtTaskInstJobHandler;
|
import cn.axzo.workflow.core.engine.job.AsyncExtTaskInstJobHandler;
|
||||||
import cn.axzo.workflow.core.engine.job.AsyncRejectTaskJobHandler;
|
import cn.axzo.workflow.core.engine.job.AsyncRejectTaskJobHandler;
|
||||||
|
import cn.axzo.workflow.core.engine.job.AsyncTermNodeAlterJobHandler;
|
||||||
import cn.axzo.workflow.core.engine.job.AsyncTransferUserTaskJobHandler;
|
import cn.axzo.workflow.core.engine.job.AsyncTransferUserTaskJobHandler;
|
||||||
import cn.axzo.workflow.core.engine.job.exception.handle.CustomAsyncJobLogClearTraceExceptionHandler;
|
import cn.axzo.workflow.core.engine.job.exception.handle.CustomAsyncJobLogClearTraceExceptionHandler;
|
||||||
import cn.axzo.workflow.core.engine.job.exception.handle.CustomAsyncRunnableExceptionExceptionHandler;
|
import cn.axzo.workflow.core.engine.job.exception.handle.CustomAsyncRunnableExceptionExceptionHandler;
|
||||||
@ -67,7 +70,7 @@ public class FlowableConfiguration {
|
|||||||
List<JobProcessor> jobProcessors,
|
List<JobProcessor> jobProcessors,
|
||||||
NacosServiceManager nacosServiceManager,
|
NacosServiceManager nacosServiceManager,
|
||||||
NacosDiscoveryProperties nacosDiscoveryProperties,
|
NacosDiscoveryProperties nacosDiscoveryProperties,
|
||||||
StringRedisTemplate redisTemplate) {
|
SupportRefreshProperties refreshProperties) {
|
||||||
return configuration -> {
|
return configuration -> {
|
||||||
configuration.setEnableHistoricTaskLogging(true);
|
configuration.setEnableHistoricTaskLogging(true);
|
||||||
configuration.setHistoryLevel(HistoryLevel.AUDIT);
|
configuration.setHistoryLevel(HistoryLevel.AUDIT);
|
||||||
@ -83,14 +86,18 @@ public class FlowableConfiguration {
|
|||||||
configuration.setIdGenerator(new BasedNacosSnowflakeIdGenerator(nacosServiceManager, nacosDiscoveryProperties));
|
configuration.setIdGenerator(new BasedNacosSnowflakeIdGenerator(nacosServiceManager, nacosDiscoveryProperties));
|
||||||
configuration.setHistoricProcessInstanceDataManager(new CustomMybatisHistoricProcessInstanceDataManager(configuration));
|
configuration.setHistoricProcessInstanceDataManager(new CustomMybatisHistoricProcessInstanceDataManager(configuration));
|
||||||
// 自定义的异步任务处理器
|
// 自定义的异步任务处理器
|
||||||
|
configuration.addCustomJobHandler(new AsyncAbortProcessInstanceJobHandler(extAxHiTaskInstService));
|
||||||
|
configuration.addCustomJobHandler(new AsyncActivitySetAssigneeJobHandler());
|
||||||
|
configuration.addCustomJobHandler(new AsyncActivityTriggerJobHandler());
|
||||||
configuration.addCustomJobHandler(new AsyncApproveTaskJobHandler());
|
configuration.addCustomJobHandler(new AsyncApproveTaskJobHandler());
|
||||||
configuration.addCustomJobHandler(new AsyncRejectTaskJobHandler(extAxHiTaskInstService));
|
configuration.addCustomJobHandler(new AsyncBackTaskJobHandler());
|
||||||
configuration.addCustomJobHandler(new AsyncExtTaskInstJobHandler(extAxHiTaskInstService));
|
configuration.addCustomJobHandler(new AsyncCancelProcessInstanceJobHandler(extAxHiTaskInstService));
|
||||||
configuration.addCustomJobHandler(new AsyncTransferUserTaskJobHandler());
|
configuration.addCustomJobHandler(new AsyncCountersignUserTaskJobHandler(extAxHiTaskInstService));
|
||||||
|
configuration.addCustomJobHandler(new AsyncExtTaskInstJobHandler(extAxHiTaskInstService));
|
||||||
|
configuration.addCustomJobHandler(new AsyncRejectTaskJobHandler(extAxHiTaskInstService));
|
||||||
|
configuration.addCustomJobHandler(new AsyncTransferUserTaskJobHandler());
|
||||||
|
configuration.addCustomJobHandler(new AsyncTermNodeAlterJobHandler(refreshProperties));
|
||||||
configuration.addCustomJobHandler(new AsyncCountersignUserTaskJobHandler(extAxHiTaskInstService));
|
configuration.addCustomJobHandler(new AsyncCountersignUserTaskJobHandler(extAxHiTaskInstService));
|
||||||
configuration.addCustomJobHandler(new AsyncCancelProcessInstanceHandler(extAxHiTaskInstService));
|
|
||||||
configuration.addCustomJobHandler(new AsyncAbortProcessInstanceHandler(extAxHiTaskInstService));
|
|
||||||
configuration.addCustomJobHandler(new AsyncBpmnProcessActivityJobHandler(bpmnProcessActivityService));
|
|
||||||
configuration.addCustomJobHandler(new AsyncActivityLeaveJobHandler(bpmnProcessActivityService));
|
configuration.addCustomJobHandler(new AsyncActivityLeaveJobHandler(bpmnProcessActivityService));
|
||||||
configuration.addCustomJobHandler(new AsyncActivityCallbackJobHandler());
|
configuration.addCustomJobHandler(new AsyncActivityCallbackJobHandler());
|
||||||
// 异步任务异常重试时间间隔
|
// 异步任务异常重试时间间隔
|
||||||
|
|||||||
@ -1,13 +1,14 @@
|
|||||||
package cn.axzo.workflow.core.conf;
|
package cn.axzo.workflow.core.conf;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.alibaba.nacos.api.config.annotation.NacosValue;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支持动态刷新配置属性
|
* 支持动态刷新配置属性
|
||||||
@ -28,4 +29,49 @@ public class SupportRefreshProperties {
|
|||||||
|
|
||||||
@Value("${workflow.apiLog.filterApiType:}")
|
@Value("${workflow.apiLog.filterApiType:}")
|
||||||
private String filterApiType;
|
private String filterApiType;
|
||||||
|
|
||||||
|
@Value("${workflow.api.timeout:10}")
|
||||||
|
private Long apiTimeout;
|
||||||
|
@Value("${workflow.mock:false}")
|
||||||
|
private Boolean mock;
|
||||||
|
@Value("${workflow.assignee.global:true}")
|
||||||
|
private Boolean global;
|
||||||
|
@Value("${workflow.assignee.category:''}")
|
||||||
|
private String category;
|
||||||
|
@Value("#{${workflow.assignee.map:{}}}")
|
||||||
|
private Map<String, String> assigneeMap;
|
||||||
|
|
||||||
|
@Value(value = "${workflow.alter.enable:false}")
|
||||||
|
private Boolean alterEnable;
|
||||||
|
/**
|
||||||
|
* 节点卡住多久才告警
|
||||||
|
*/
|
||||||
|
@Value("${workflow.alter.delay:10}")
|
||||||
|
private Integer pauseDelay;
|
||||||
|
/**
|
||||||
|
* 业务节点暂停告警的次数,该值不建议改小
|
||||||
|
*/
|
||||||
|
@Value(value = "${workflow.alter.retries:1000}")
|
||||||
|
private Integer alterRetries;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务节点暂停告警次数间的间隔
|
||||||
|
*/
|
||||||
|
@Value(value = "${workflow.alter.interval:10}")
|
||||||
|
private Integer alterInterval;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务节点暂停告警次数间隔的时间单位
|
||||||
|
*/
|
||||||
|
@Value(value = "${workflow.alter.intervalUnit:minutes}")
|
||||||
|
private TimeUnit alterIntervalUnit;
|
||||||
|
|
||||||
|
@Value(value = "${workflow.alter.mobiles:}")
|
||||||
|
private List<String> alterMobiles;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于控制转交管理员的 API
|
||||||
|
*/
|
||||||
|
@Value("${workflow.useNewToAdminApi:true}")
|
||||||
|
private Boolean useNewToAdminApi;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,57 @@
|
|||||||
|
package cn.axzo.workflow.core.conf.handler;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.BpmnButtonConf;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Assert;
|
||||||
|
import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler;
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.ibatis.type.JdbcType;
|
||||||
|
import org.apache.ibatis.type.MappedJdbcTypes;
|
||||||
|
import org.apache.ibatis.type.MappedTypes;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BpmnButtonConf 数据映射转换
|
||||||
|
*
|
||||||
|
* @author wangli
|
||||||
|
* @since 2024-09-07 22:40
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@MappedTypes({List.class})
|
||||||
|
@MappedJdbcTypes({JdbcType.VARCHAR})
|
||||||
|
public class ButtonConfTypeHandler extends AbstractJsonTypeHandler<BpmnButtonConf> {
|
||||||
|
private static ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
|
public ButtonConfTypeHandler(Class<?> type) {
|
||||||
|
if (log.isTraceEnabled()) {
|
||||||
|
log.trace("JacksonTypeHandler(" + type + ")");
|
||||||
|
}
|
||||||
|
Assert.notNull(type, "Type argument cannot be null", new Object[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BpmnButtonConf parse(String json) {
|
||||||
|
try {
|
||||||
|
// 这里进行了json解析,同样在这里也可以进行字段查询后的处理,如对象内部的手机号字段的加密展示等
|
||||||
|
return objectMapper.readValue(json, new TypeReference<BpmnButtonConf>() {
|
||||||
|
});
|
||||||
|
} catch (IOException var3) {
|
||||||
|
throw new RuntimeException(var3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String toJson(BpmnButtonConf obj) {
|
||||||
|
try {
|
||||||
|
return objectMapper.writeValueAsString(obj);
|
||||||
|
} catch (JsonProcessingException var3) {
|
||||||
|
throw new RuntimeException(var3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setObjectMapper(ObjectMapper om) {
|
||||||
|
objectMapper = om;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
package cn.axzo.workflow.core.conf.handler;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Assert;
|
||||||
|
import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler;
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.ibatis.type.JdbcType;
|
||||||
|
import org.apache.ibatis.type.MappedJdbcTypes;
|
||||||
|
import org.apache.ibatis.type.MappedTypes;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BpmnTaskDelegateAssigner 数据映射转换
|
||||||
|
*
|
||||||
|
* @author wangli
|
||||||
|
* @since 2024-09-07 22:40
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@MappedTypes({List.class})
|
||||||
|
@MappedJdbcTypes({JdbcType.VARCHAR})
|
||||||
|
public class ListAssigneeTypeHandler extends AbstractJsonTypeHandler<List<BpmnTaskDelegateAssigner>> {
|
||||||
|
private static ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
|
public ListAssigneeTypeHandler(Class<?> type) {
|
||||||
|
if (log.isTraceEnabled()) {
|
||||||
|
log.trace("JacksonTypeHandler(" + type + ")");
|
||||||
|
}
|
||||||
|
Assert.notNull(type, "Type argument cannot be null", new Object[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<BpmnTaskDelegateAssigner> parse(String json) {
|
||||||
|
try {
|
||||||
|
// 这里进行了json解析,同样在这里也可以进行字段查询后的处理,如对象内部的手机号字段的加密展示等
|
||||||
|
return objectMapper.readValue(json, new TypeReference<List<BpmnTaskDelegateAssigner>>() {
|
||||||
|
});
|
||||||
|
} catch (IOException var3) {
|
||||||
|
throw new RuntimeException(var3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String toJson(List<BpmnTaskDelegateAssigner> obj) {
|
||||||
|
try {
|
||||||
|
return objectMapper.writeValueAsString(obj);
|
||||||
|
} catch (JsonProcessingException var3) {
|
||||||
|
throw new RuntimeException(var3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setObjectMapper(ObjectMapper om) {
|
||||||
|
objectMapper = om;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -12,12 +12,12 @@ import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
|
|||||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
|
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
|
||||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||||
import org.flowable.engine.impl.util.TaskHelper;
|
import org.flowable.engine.impl.util.TaskHelper;
|
||||||
import org.flowable.task.api.Task;
|
|
||||||
import org.flowable.task.service.TaskService;
|
import org.flowable.task.service.TaskService;
|
||||||
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_COMPLETE_OPERATION_TYPE;
|
||||||
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.APPROVED;
|
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.APPROVED;
|
||||||
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.PROCESSING;
|
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.PROCESSING;
|
||||||
|
|
||||||
@ -48,7 +48,8 @@ public class CustomReceiveTaskActivityBehavior extends ReceiveTaskActivityBehavi
|
|||||||
task.setTaskDefinitionKey(receiveTask.getId());
|
task.setTaskDefinitionKey(receiveTask.getId());
|
||||||
task.setPropagatedStageInstanceId(execution.getPropagatedStageInstanceId());
|
task.setPropagatedStageInstanceId(execution.getPropagatedStageInstanceId());
|
||||||
task.setName(receiveTask.getName());
|
task.setName(receiveTask.getName());
|
||||||
TaskHelper.insertTask(task, (ExecutionEntity) execution, false, false);
|
TaskHelper.insertTask(task, (ExecutionEntity) execution, true, false);
|
||||||
|
|
||||||
|
|
||||||
// 添加 taskInst 扩展表数据
|
// 添加 taskInst 扩展表数据
|
||||||
FlowableEventDispatcher eventDispatcher = processEngineConfiguration.getEventDispatcher();
|
FlowableEventDispatcher eventDispatcher = processEngineConfiguration.getEventDispatcher();
|
||||||
@ -65,14 +66,17 @@ public class CustomReceiveTaskActivityBehavior extends ReceiveTaskActivityBehavi
|
|||||||
FlowableEventDispatcher eventDispatcher = processEngineConfiguration.getEventDispatcher();
|
FlowableEventDispatcher eventDispatcher = processEngineConfiguration.getEventDispatcher();
|
||||||
|
|
||||||
org.flowable.engine.TaskService taskService = processEngineConfiguration.getTaskService();
|
org.flowable.engine.TaskService taskService = processEngineConfiguration.getTaskService();
|
||||||
Task task = taskService.createTaskQuery().executionId(execution.getId())
|
TaskEntity task = (TaskEntity) taskService.createTaskQuery().executionId(execution.getId())
|
||||||
.taskDefinitionKey(execution.getCurrentActivityId()).singleResult();
|
.taskDefinitionKey(execution.getCurrentActivityId()).singleResult();
|
||||||
if (Objects.nonNull(task)) {
|
if (Objects.nonNull(task)) {
|
||||||
|
// 用于新版日志
|
||||||
|
task.setTransientVariable(TASK_COMPLETE_OPERATION_TYPE + task.getId(), APPROVED.getStatus());
|
||||||
|
|
||||||
eventDispatcher.dispatchEvent(new ExtTaskInstUpdateEvent(execution.getProcessInstanceId(),
|
eventDispatcher.dispatchEvent(new ExtTaskInstUpdateEvent(execution.getProcessInstanceId(),
|
||||||
receiveTask.getId(), task.getId(), APPROVED),
|
receiveTask.getId(), task.getId(), APPROVED),
|
||||||
processEngineConfiguration.getEngineCfgKey());
|
processEngineConfiguration.getEngineCfgKey());
|
||||||
} else {
|
} else {
|
||||||
log.warn("task is null, executionId: {}, activityId: {}", execution.getId(),
|
log.warn("ReceiveTask is null, executionId: {}, activityId: {}", execution.getId(),
|
||||||
execution.getCurrentActivityId());
|
execution.getCurrentActivityId());
|
||||||
}
|
}
|
||||||
super.leave(execution);
|
super.leave(execution);
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package cn.axzo.workflow.core.engine.behavior;
|
|||||||
|
|
||||||
import cn.axzo.workflow.core.engine.event.ExtTaskInstCreateEvent;
|
import cn.axzo.workflow.core.engine.event.ExtTaskInstCreateEvent;
|
||||||
import cn.axzo.workflow.core.engine.event.ExtTaskInstUpdateEvent;
|
import cn.axzo.workflow.core.engine.event.ExtTaskInstUpdateEvent;
|
||||||
|
import cn.axzo.workflow.core.engine.listener.EngineCarbonCopyEventListener;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.flowable.bpmn.model.MapExceptionEntry;
|
import org.flowable.bpmn.model.MapExceptionEntry;
|
||||||
import org.flowable.bpmn.model.ServiceTask;
|
import org.flowable.bpmn.model.ServiceTask;
|
||||||
@ -19,14 +20,16 @@ import org.flowable.task.service.TaskService;
|
|||||||
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_COMPLETE_OPERATION_TYPE;
|
||||||
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.APPROVED;
|
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.APPROVED;
|
||||||
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.PROCESSING;
|
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.PROCESSING;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自定义的服务任务活动行为处理器
|
* 自定义的服务任务活动行为处理器
|
||||||
* <p>
|
* <p>
|
||||||
* 主要用来创建审批日志
|
* 主要用来创建抄送节点审批日志,真实计算抄送人的集合是由 {@link EngineCarbonCopyEventListener} 来完成的
|
||||||
*
|
*
|
||||||
* @author wangli
|
* @author wangli
|
||||||
* @since 13/03/2024 14:17
|
* @since 13/03/2024 14:17
|
||||||
@ -35,6 +38,7 @@ import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.PROCES
|
|||||||
public class CustomServiceTaskDelegateExpressionActivityBehavior extends ServiceTaskDelegateExpressionActivityBehavior {
|
public class CustomServiceTaskDelegateExpressionActivityBehavior extends ServiceTaskDelegateExpressionActivityBehavior {
|
||||||
|
|
||||||
protected final ServiceTask serviceTask;
|
protected final ServiceTask serviceTask;
|
||||||
|
// thread safe
|
||||||
private TaskEntity task;
|
private TaskEntity task;
|
||||||
|
|
||||||
public CustomServiceTaskDelegateExpressionActivityBehavior(String serviceTaskId, Expression expression,
|
public CustomServiceTaskDelegateExpressionActivityBehavior(String serviceTaskId, Expression expression,
|
||||||
@ -57,7 +61,7 @@ public class CustomServiceTaskDelegateExpressionActivityBehavior extends Service
|
|||||||
task.setTaskDefinitionKey(serviceTask.getId());
|
task.setTaskDefinitionKey(serviceTask.getId());
|
||||||
task.setPropagatedStageInstanceId(execution.getPropagatedStageInstanceId());
|
task.setPropagatedStageInstanceId(execution.getPropagatedStageInstanceId());
|
||||||
task.setName(serviceTask.getName());
|
task.setName(serviceTask.getName());
|
||||||
TaskHelper.insertTask(task, (ExecutionEntity) execution, false, false);
|
TaskHelper.insertTask(task, (ExecutionEntity) execution, true, false);
|
||||||
|
|
||||||
// 添加 taskInst 扩展表数据
|
// 添加 taskInst 扩展表数据
|
||||||
FlowableEventDispatcher eventDispatcher = processEngineConfiguration.getEventDispatcher();
|
FlowableEventDispatcher eventDispatcher = processEngineConfiguration.getEventDispatcher();
|
||||||
@ -72,11 +76,24 @@ public class CustomServiceTaskDelegateExpressionActivityBehavior extends Service
|
|||||||
CommandContext commandContext = CommandContextUtil.getCommandContext();
|
CommandContext commandContext = CommandContextUtil.getCommandContext();
|
||||||
ProcessEngineConfigurationImpl processEngineConfiguration =
|
ProcessEngineConfigurationImpl processEngineConfiguration =
|
||||||
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||||
|
|
||||||
FlowableEventDispatcher eventDispatcher = processEngineConfiguration.getEventDispatcher();
|
FlowableEventDispatcher eventDispatcher = processEngineConfiguration.getEventDispatcher();
|
||||||
eventDispatcher.dispatchEvent(new ExtTaskInstUpdateEvent(execution.getProcessInstanceId(),
|
|
||||||
execution.getCurrentActivityId(), task.getId(), APPROVED),
|
org.flowable.engine.TaskService taskService = processEngineConfiguration.getTaskService();
|
||||||
|
TaskEntity serviceTask = (TaskEntity) taskService.createTaskQuery().taskId(task.getId())
|
||||||
|
.taskDefinitionKey(execution.getCurrentActivityId()).singleResult();
|
||||||
|
if (Objects.nonNull(serviceTask)) {
|
||||||
|
// 用于新版日志
|
||||||
|
serviceTask.setTransientVariable(TASK_COMPLETE_OPERATION_TYPE + serviceTask.getId(), APPROVED.getStatus());
|
||||||
|
|
||||||
|
eventDispatcher.dispatchEvent(new ExtTaskInstUpdateEvent(execution.getProcessInstanceId(),
|
||||||
|
execution.getCurrentActivityId(), serviceTask.getId(), APPROVED),
|
||||||
processEngineConfiguration.getEngineCfgKey());
|
processEngineConfiguration.getEngineCfgKey());
|
||||||
|
TaskHelper.deleteTask(serviceTask, "complete carbon", false, true, true);
|
||||||
|
} else {
|
||||||
|
log.warn("ServiceTask is null, executionId: {}, activityId: {}", execution.getId(),
|
||||||
|
execution.getCurrentActivityId());
|
||||||
|
}
|
||||||
|
|
||||||
super.leave(execution);
|
super.leave(execution);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import org.flowable.common.engine.impl.interceptor.CommandContext;
|
|||||||
import static cn.axzo.workflow.core.common.code.BpmnInstanceRespCode.ENGINE_EXEC_EXCEPTION;
|
import static cn.axzo.workflow.core.common.code.BpmnInstanceRespCode.ENGINE_EXEC_EXCEPTION;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* 抽象的命令,用于将在 Command 中执行的逻辑所抛出的非 WorkflowEngineException 的异常都包装为 WorkflowEngineException
|
||||||
*
|
*
|
||||||
* @author wangli
|
* @author wangli
|
||||||
* @since 2024/7/1 13:59
|
* @since 2024/7/1 13:59
|
||||||
|
|||||||
@ -2,7 +2,7 @@ package cn.axzo.workflow.core.engine.cmd;
|
|||||||
|
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceAbortDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceAbortDTO;
|
||||||
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
||||||
import cn.axzo.workflow.core.engine.job.AsyncAbortProcessInstanceHandler;
|
import cn.axzo.workflow.core.engine.job.AsyncAbortProcessInstanceJobHandler;
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||||
@ -73,9 +73,9 @@ public class CustomAbortProcessInstanceAsyncCmd extends AbstractCommand<Void> im
|
|||||||
job.setExecutionId(instance.getId());
|
job.setExecutionId(instance.getId());
|
||||||
job.setProcessInstanceId(instance.getId());
|
job.setProcessInstanceId(instance.getId());
|
||||||
job.setProcessDefinitionId(instance.getProcessDefinitionId());
|
job.setProcessDefinitionId(instance.getProcessDefinitionId());
|
||||||
job.setElementId(AsyncAbortProcessInstanceHandler.TYPE);
|
job.setElementId(AsyncAbortProcessInstanceJobHandler.TYPE);
|
||||||
job.setElementName(instance.getName());
|
job.setElementName(instance.getName());
|
||||||
job.setJobHandlerType(AsyncAbortProcessInstanceHandler.TYPE);
|
job.setJobHandlerType(AsyncAbortProcessInstanceJobHandler.TYPE);
|
||||||
job.setTenantId(instance.getTenantId());
|
job.setTenantId(instance.getTenantId());
|
||||||
|
|
||||||
// 携带自定义的数据
|
// 携带自定义的数据
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package cn.axzo.workflow.core.engine.cmd;
|
|||||||
|
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||||
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
||||||
|
import cn.axzo.workflow.core.engine.model.AddComment;
|
||||||
import cn.axzo.workflow.core.engine.operation.DeleteProcessInstanceOperation;
|
import cn.axzo.workflow.core.engine.operation.DeleteProcessInstanceOperation;
|
||||||
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
|
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
@ -20,7 +21,6 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.COMMENT_TYPE_OPERATION_DESC;
|
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_DELETE_PROCESS_FLAG;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_DELETE_PROCESS_FLAG;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_END_TENANT_ID;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_END_TENANT_ID;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_END_USER_ID;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_END_USER_ID;
|
||||||
@ -35,7 +35,7 @@ import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.CANCEL
|
|||||||
import static cn.axzo.workflow.core.common.code.BpmnInstanceRespCode.PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS;
|
import static cn.axzo.workflow.core.common.code.BpmnInstanceRespCode.PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS;
|
||||||
import static cn.axzo.workflow.core.common.code.BpmnInstanceRespCode.PROCESS_INSTANCE_CANT_ABORT;
|
import static cn.axzo.workflow.core.common.code.BpmnInstanceRespCode.PROCESS_INSTANCE_CANT_ABORT;
|
||||||
import static cn.axzo.workflow.core.common.code.BpmnInstanceRespCode.PROCESS_INSTANCE_NOT_EXISTS;
|
import static cn.axzo.workflow.core.common.code.BpmnInstanceRespCode.PROCESS_INSTANCE_NOT_EXISTS;
|
||||||
import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.addComment;
|
import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.completeVirtualTask;
|
||||||
import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.createVirtualTask;
|
import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.createVirtualTask;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -101,14 +101,15 @@ public class CustomAbortProcessInstanceCmd extends AbstractCommand<Void> impleme
|
|||||||
runtimeService.setVariables(instance.getId(), variables);
|
runtimeService.setVariables(instance.getId(), variables);
|
||||||
|
|
||||||
CommandContextUtil.getAgenda(commandContext).planOperation(new DeleteProcessInstanceOperation(commandContext,
|
CommandContextUtil.getAgenda(commandContext).planOperation(new DeleteProcessInstanceOperation(commandContext,
|
||||||
processInstanceId, extAxHiTaskInstService));
|
processInstanceId, extAxHiTaskInstService, ABORTED));
|
||||||
|
|
||||||
// 添加自定义的节点,用于展示最后的操作
|
// 添加自定义的节点,用于展示最后的操作
|
||||||
Task task = createVirtualTask(commandContext, extAxHiTaskInstService, processInstanceId,
|
Task task = createVirtualTask(commandContext, extAxHiTaskInstService, processInstanceId,
|
||||||
"系统中止", NODE_ABORT.getType(), null, BpmnTaskDelegateAssigner.buildDummyAssigner("system",
|
"系统中止", NODE_ABORT.getType(), null, BpmnTaskDelegateAssigner.buildDummyAssigner("system",
|
||||||
TASK_ASSIGNEE_SKIP_FLAT, "系统"), ABORTED.getStatus());
|
TASK_ASSIGNEE_SKIP_FLAT, "系统"), ABORTED.getStatus(), new AddComment(reason));
|
||||||
addComment(commandContext, task, COMMENT_TYPE_OPERATION_DESC, reason);
|
|
||||||
runtimeService.setVariable(task.getProcessInstanceId(), TASK_COMPLETE_OPERATION_TYPE + task.getId(), ABORTED);
|
runtimeService.setVariable(task.getProcessInstanceId(), TASK_COMPLETE_OPERATION_TYPE + task.getId(), ABORTED);
|
||||||
|
|
||||||
|
completeVirtualTask(commandContext, task);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,85 @@
|
|||||||
|
package cn.axzo.workflow.core.engine.cmd;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivityTriggerDTO;
|
||||||
|
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
||||||
|
import cn.axzo.workflow.core.engine.job.AsyncActivityTriggerJobHandler;
|
||||||
|
import cn.axzo.workflow.core.engine.job.AsyncApproveTaskJobHandler;
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||||
|
import org.flowable.engine.RuntimeService;
|
||||||
|
import org.flowable.engine.TaskService;
|
||||||
|
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
|
||||||
|
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||||
|
import org.flowable.engine.runtime.Execution;
|
||||||
|
import org.flowable.job.service.JobService;
|
||||||
|
import org.flowable.job.service.impl.persistence.entity.JobEntity;
|
||||||
|
import org.flowable.task.api.Task;
|
||||||
|
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static cn.axzo.workflow.core.common.code.BpmnTaskRespCode.ACTIVITY_TRIGGER_NOT_EXISTS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义(异步)流转业务姐弟那的命令器实现
|
||||||
|
*
|
||||||
|
* @author wangli
|
||||||
|
* @since 2024-09-09 13:58
|
||||||
|
*/
|
||||||
|
public class CustomActivityTriggerAsyncCmd extends AbstractCommand<String> implements Serializable {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(CustomActivityTriggerAsyncCmd.class);
|
||||||
|
private final BpmnActivityTriggerDTO dto;
|
||||||
|
|
||||||
|
public CustomActivityTriggerAsyncCmd(BpmnActivityTriggerDTO dto) {
|
||||||
|
this.dto = dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String paramToJsonString() {
|
||||||
|
return JSON.toJSONString(dto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String execute(CommandContext commandContext) {
|
||||||
|
ProcessEngineConfigurationImpl processEngineConfiguration =
|
||||||
|
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||||
|
RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
|
||||||
|
Execution execution = runtimeService.createExecutionQuery().executionId(dto.getTriggerId()).singleResult();
|
||||||
|
if (Objects.isNull(execution)) {
|
||||||
|
throw new WorkflowEngineException(ACTIVITY_TRIGGER_NOT_EXISTS, dto.getTriggerId());
|
||||||
|
}
|
||||||
|
|
||||||
|
return startAsync(commandContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String startAsync(CommandContext commandContext) {
|
||||||
|
ProcessEngineConfigurationImpl processEngineConfiguration =
|
||||||
|
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||||
|
TaskService taskService = processEngineConfiguration.getTaskService();
|
||||||
|
TaskEntity task = (TaskEntity) taskService.createTaskQuery().executionId(dto.getTriggerId()).singleResult();
|
||||||
|
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(AsyncActivityTriggerJobHandler.TYPE);
|
||||||
|
job.setTenantId(task.getTenantId());
|
||||||
|
|
||||||
|
// 携带自定义的数据
|
||||||
|
job.setCustomValues(JSONUtil.toJsonStr(dto));
|
||||||
|
|
||||||
|
// 创建异步任务并调度
|
||||||
|
jobService.createAsyncJob(job, false);
|
||||||
|
jobService.scheduleAsyncJob(job);
|
||||||
|
return job.getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
package cn.axzo.workflow.core.engine.cmd;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivityTriggerDTO;
|
||||||
|
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
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.util.CommandContextUtil;
|
||||||
|
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.COMMENT_TYPE_OPERATION_DESC;
|
||||||
|
import static cn.axzo.workflow.core.common.code.BpmnTaskRespCode.ACTIVITY_TRIGGER_NOT_EXISTS;
|
||||||
|
import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.addComment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义(同步)流转业务姐弟那的命令器实现
|
||||||
|
*
|
||||||
|
* @author wangli
|
||||||
|
* @since 2024-09-09 13:58
|
||||||
|
*/
|
||||||
|
public class CustomActivityTriggerCmd extends AbstractCommand<Void> implements Serializable {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(CustomActivityTriggerCmd.class);
|
||||||
|
private final BpmnActivityTriggerDTO dto;
|
||||||
|
|
||||||
|
public CustomActivityTriggerCmd(BpmnActivityTriggerDTO dto) {
|
||||||
|
this.dto = dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String paramToJsonString() {
|
||||||
|
return JSON.toJSONString(dto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void execute(CommandContext commandContext) {
|
||||||
|
ProcessEngineConfigurationImpl processEngineConfiguration =
|
||||||
|
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||||
|
|
||||||
|
TaskEntity task = (TaskEntity) processEngineConfiguration.getTaskService()
|
||||||
|
.createTaskQuery().executionId(dto.getTriggerId()).singleResult();
|
||||||
|
if (Objects.isNull(task)) {
|
||||||
|
throw new WorkflowEngineException(ACTIVITY_TRIGGER_NOT_EXISTS, dto.getTriggerId());
|
||||||
|
}
|
||||||
|
addComment(commandContext, task, COMMENT_TYPE_OPERATION_DESC, "已处理");
|
||||||
|
RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
|
||||||
|
runtimeService.trigger(dto.getTriggerId());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -29,8 +29,10 @@ import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.validTask
|
|||||||
* @since 2024/1/4 15:50
|
* @since 2024/1/4 15:50
|
||||||
*/
|
*/
|
||||||
public class CustomApproveTaskAsyncCmd extends AbstractCommand<String> implements Serializable {
|
public class CustomApproveTaskAsyncCmd extends AbstractCommand<String> implements Serializable {
|
||||||
|
private static final long serialVersionUID = -4706627700694867170L;
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(CustomApproveTaskAsyncCmd.class);
|
private static final Logger log = LoggerFactory.getLogger(CustomApproveTaskAsyncCmd.class);
|
||||||
|
|
||||||
private final BpmnTaskAuditDTO dto;
|
private final BpmnTaskAuditDTO dto;
|
||||||
|
|
||||||
public CustomApproveTaskAsyncCmd(BpmnTaskAuditDTO dto) {
|
public CustomApproveTaskAsyncCmd(BpmnTaskAuditDTO dto) {
|
||||||
|
|||||||
@ -101,7 +101,7 @@ public class CustomApproveTaskCmd extends AbstractCommand<Void> implements Seria
|
|||||||
if (Objects.nonNull(operationDesc)) {
|
if (Objects.nonNull(operationDesc)) {
|
||||||
this.operationDesc = operationDesc;
|
this.operationDesc = operationDesc;
|
||||||
} else {
|
} else {
|
||||||
this.operationDesc = "已通过";
|
this.operationDesc = "(已通过)";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,8 +115,8 @@ public class CustomApproveTaskCmd extends AbstractCommand<Void> implements Seria
|
|||||||
|
|
||||||
HistoricTaskInstance historicTaskInstance = taskQuery.taskId(taskId).singleResult();
|
HistoricTaskInstance historicTaskInstance = taskQuery.taskId(taskId).singleResult();
|
||||||
|
|
||||||
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
|
TaskEntity task = (TaskEntity) taskService.createTaskQuery().taskId(taskId).singleResult();
|
||||||
validTask(historicTaskInstance, (TaskEntity) task, approver, nodeTypes);
|
validTask(historicTaskInstance, task, approver, nodeTypes);
|
||||||
|
|
||||||
// TODO 所有的跟 Task 相关的动作都可以在这里进行扩展,用于扩展八大按钮标准动作以外的一些逻辑,但这里需要结合 Spring 能力,需设计好扩展点,否则无法进行扩展
|
// TODO 所有的跟 Task 相关的动作都可以在这里进行扩展,用于扩展八大按钮标准动作以外的一些逻辑,但这里需要结合 Spring 能力,需设计好扩展点,否则无法进行扩展
|
||||||
// 其他动态也应该在类似的地方预留扩展点
|
// 其他动态也应该在类似的地方预留扩展点
|
||||||
@ -127,7 +127,7 @@ public class CustomApproveTaskCmd extends AbstractCommand<Void> implements Seria
|
|||||||
Authentication.setAuthenticatedUserId(null);
|
Authentication.setAuthenticatedUserId(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
batchAddAttachment(commandContext, task.getProcessInstanceId(), taskId, attachmentList, approver);
|
batchAddAttachment(commandContext, task.getProcessInstanceId(), task, attachmentList, approver);
|
||||||
|
|
||||||
Authentication.setAuthenticatedUserId(Objects.nonNull(approver) ? approver.buildAssigneeId() : null);
|
Authentication.setAuthenticatedUserId(Objects.nonNull(approver) ? approver.buildAssigneeId() : null);
|
||||||
addComment(commandContext, task, COMMENT_TYPE_OPERATION_DESC, operationDesc);
|
addComment(commandContext, task, COMMENT_TYPE_OPERATION_DESC, operationDesc);
|
||||||
@ -139,8 +139,7 @@ public class CustomApproveTaskCmd extends AbstractCommand<Void> implements Seria
|
|||||||
runtimeService.setVariable(task.getProcessInstanceId(), INTERNAL_SPECIFY_NEXT_APPROVER,
|
runtimeService.setVariable(task.getProcessInstanceId(), INTERNAL_SPECIFY_NEXT_APPROVER,
|
||||||
nextApprover);
|
nextApprover);
|
||||||
}
|
}
|
||||||
((TaskEntity) task).setTransientVariable(TASK_COMPLETE_OPERATION_TYPE + taskId, APPROVED.getStatus());
|
task.setTransientVariable(TASK_COMPLETE_OPERATION_TYPE + taskId, APPROVED.getStatus());
|
||||||
|
|
||||||
executeSynchronous(task, taskService, runtimeService);
|
executeSynchronous(task, taskService, runtimeService);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,95 @@
|
|||||||
|
package cn.axzo.workflow.core.engine.cmd;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskBackAuditDTO;
|
||||||
|
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
||||||
|
import cn.axzo.workflow.core.common.utils.BpmnModelUtils;
|
||||||
|
import cn.axzo.workflow.core.engine.job.AsyncBackTaskJobHandler;
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.flowable.bpmn.model.FlowElement;
|
||||||
|
import org.flowable.bpmn.model.FlowNode;
|
||||||
|
import org.flowable.bpmn.model.Process;
|
||||||
|
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.engine.impl.util.ProcessDefinitionUtil;
|
||||||
|
import org.flowable.job.service.JobService;
|
||||||
|
import org.flowable.job.service.impl.persistence.entity.JobEntity;
|
||||||
|
import org.flowable.task.api.Task;
|
||||||
|
import org.flowable.task.api.history.HistoricTaskInstance;
|
||||||
|
import org.flowable.task.api.history.HistoricTaskInstanceQuery;
|
||||||
|
import org.flowable.task.service.TaskService;
|
||||||
|
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static cn.axzo.workflow.core.common.code.BpmnTaskRespCode.BACK_NODE_CANNOT_REACHABLE;
|
||||||
|
import static cn.axzo.workflow.core.common.code.BpmnTaskRespCode.BACK_TARGET_ACTIVITY_NOT_EXISTS;
|
||||||
|
import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.validTask;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class CustomBackTaskAsyncCmd extends AbstractCommand<String> implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1773108485033787095L;
|
||||||
|
|
||||||
|
private final BpmnTaskBackAuditDTO dto;
|
||||||
|
|
||||||
|
public CustomBackTaskAsyncCmd(BpmnTaskBackAuditDTO dto) {
|
||||||
|
this.dto = dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String executeInternal(CommandContext commandContext) {
|
||||||
|
ProcessEngineConfigurationImpl processEngineConfiguration =
|
||||||
|
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||||
|
HistoricTaskInstanceQuery taskQuery =
|
||||||
|
processEngineConfiguration.getHistoryService().createHistoricTaskInstanceQuery();
|
||||||
|
TaskService taskService = processEngineConfiguration.getTaskServiceConfiguration().getTaskService();
|
||||||
|
HistoricTaskInstance historicTaskInstance = taskQuery.taskId(dto.getTaskId()).singleResult();
|
||||||
|
|
||||||
|
TaskEntity taskEntity = taskService.getTask(dto.getTaskId());
|
||||||
|
validTask(historicTaskInstance, taskEntity, dto.getApprover(), dto.getNodeTypes());
|
||||||
|
|
||||||
|
Process process = ProcessDefinitionUtil.getProcess(taskEntity.getProcessDefinitionId());
|
||||||
|
FlowElement targetFlowElement = process.getFlowElement(dto.getToActivityId(), true);
|
||||||
|
if (Objects.isNull(targetFlowElement)) {
|
||||||
|
throw new WorkflowEngineException(BACK_TARGET_ACTIVITY_NOT_EXISTS, dto.getToActivityId());
|
||||||
|
}
|
||||||
|
FlowElement sourceFlowElement = process.getFlowElement(taskEntity.getTaskDefinitionKey(), true);
|
||||||
|
// 退回节点到当前节点不可达到,不允许退回
|
||||||
|
if (!BpmnModelUtils.isReachable(process, (FlowNode) targetFlowElement, (FlowNode) sourceFlowElement)) {
|
||||||
|
throw new WorkflowEngineException(BACK_NODE_CANNOT_REACHABLE, dto.getToActivityId());
|
||||||
|
}
|
||||||
|
|
||||||
|
return startAsync(processEngineConfiguration, taskEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String startAsync(ProcessEngineConfigurationImpl processEngineConfiguration, Task 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(AsyncBackTaskJobHandler.TYPE);
|
||||||
|
job.setTenantId(task.getTenantId());
|
||||||
|
|
||||||
|
// 携带自定义的数据
|
||||||
|
job.setCustomValues(JSONUtil.toJsonStr(dto));
|
||||||
|
|
||||||
|
// 创建异步任务并调度
|
||||||
|
jobService.createAsyncJob(job, false);
|
||||||
|
jobService.scheduleAsyncJob(job);
|
||||||
|
return job.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String paramToJsonString() {
|
||||||
|
return JSON.toJSONString(dto);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,108 @@
|
|||||||
|
package cn.axzo.workflow.core.engine.cmd;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskBackAuditDTO;
|
||||||
|
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
||||||
|
import cn.axzo.workflow.core.common.utils.BpmnModelUtils;
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.flowable.bpmn.model.FlowElement;
|
||||||
|
import org.flowable.bpmn.model.FlowNode;
|
||||||
|
import org.flowable.bpmn.model.Process;
|
||||||
|
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.impl.cfg.ProcessEngineConfigurationImpl;
|
||||||
|
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||||
|
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
|
||||||
|
import org.flowable.task.api.history.HistoricTaskInstance;
|
||||||
|
import org.flowable.task.api.history.HistoricTaskInstanceQuery;
|
||||||
|
import org.flowable.task.service.TaskService;
|
||||||
|
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
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_TASK_RELATION_ASSIGNEE_LIST_INFO;
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_COMPLETE_OPERATION_TYPE;
|
||||||
|
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.BACKED;
|
||||||
|
import static cn.axzo.workflow.core.common.code.BpmnTaskRespCode.BACK_NODE_CANNOT_REACHABLE;
|
||||||
|
import static cn.axzo.workflow.core.common.code.BpmnTaskRespCode.BACK_TARGET_ACTIVITY_NOT_EXISTS;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回退命令
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class CustomBackTaskCmd extends AbstractCommand<Void> implements Serializable {
|
||||||
|
private static final long serialVersionUID = -1241290344311892346L;
|
||||||
|
|
||||||
|
private final BpmnTaskBackAuditDTO dto;
|
||||||
|
|
||||||
|
private static final String OPERATION_DESC = "回退至";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String paramToJsonString() {
|
||||||
|
Map<String, Object> params = new HashMap<>();
|
||||||
|
params.put("taskId", dto.getTaskId());
|
||||||
|
params.put("advice", dto.getAdvice());
|
||||||
|
params.put("operationDesc", OPERATION_DESC);
|
||||||
|
params.put("attachmentList", JSON.toJSONString(dto.getAttachmentList()));
|
||||||
|
params.put("approver", JSON.toJSONString(dto.getApprover()));
|
||||||
|
params.put("nodeTypes", JSON.toJSONString(dto.getNodeTypes()));
|
||||||
|
return JSON.toJSONString(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomBackTaskCmd(BpmnTaskBackAuditDTO dto) {
|
||||||
|
this.dto = dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void execute(CommandContext commandContext) {
|
||||||
|
ProcessEngineConfigurationImpl processEngineConfiguration =
|
||||||
|
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||||
|
HistoricTaskInstanceQuery taskQuery =
|
||||||
|
processEngineConfiguration.getHistoryService().createHistoricTaskInstanceQuery();
|
||||||
|
TaskService taskService = processEngineConfiguration.getTaskServiceConfiguration().getTaskService();
|
||||||
|
|
||||||
|
HistoricTaskInstance historicTaskInstance = taskQuery.taskId(dto.getTaskId()).singleResult();
|
||||||
|
|
||||||
|
TaskEntity task = taskService.getTask(dto.getTaskId());
|
||||||
|
validTask(historicTaskInstance, task, dto.getApprover(), dto.getNodeTypes());
|
||||||
|
|
||||||
|
Process process = ProcessDefinitionUtil.getProcess(task.getProcessDefinitionId());
|
||||||
|
FlowElement targetFlowElement = process.getFlowElement(dto.getToActivityId(), true);
|
||||||
|
if (Objects.isNull(targetFlowElement)) {
|
||||||
|
throw new WorkflowEngineException(BACK_TARGET_ACTIVITY_NOT_EXISTS, dto.getToActivityId());
|
||||||
|
}
|
||||||
|
FlowElement sourceFlowElement = process.getFlowElement(task.getTaskDefinitionKey(), true);
|
||||||
|
// 退回节点到当前节点不可达到,不允许退回
|
||||||
|
if (!BpmnModelUtils.isReachable(process, (FlowNode) targetFlowElement, (FlowNode) sourceFlowElement)) {
|
||||||
|
throw new WorkflowEngineException(BACK_NODE_CANNOT_REACHABLE, dto.getToActivityId());
|
||||||
|
}
|
||||||
|
batchAddAttachment(commandContext, task.getProcessInstanceId(), task, dto.getAttachmentList(), dto.getApprover());
|
||||||
|
|
||||||
|
Authentication.setAuthenticatedUserId(dto.getApprover().buildAssigneeId());
|
||||||
|
addComment(commandContext, task, COMMENT_TYPE_ADVICE, dto.getAdvice());
|
||||||
|
addComment(commandContext, task, COMMENT_TYPE_OPERATION_DESC, OPERATION_DESC + targetFlowElement.getName());
|
||||||
|
Authentication.setAuthenticatedUserId(null);
|
||||||
|
|
||||||
|
RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
|
||||||
|
task.setTransientVariable(TASK_COMPLETE_OPERATION_TYPE + dto.getTaskId(), BACKED.getStatus());
|
||||||
|
|
||||||
|
// 移除回退到的指定节点的变量,让 EngineExecutionStartListener 重新计算该节点的人
|
||||||
|
runtimeService.removeVariable(task.getProcessInstanceId(), INTERNAL_TASK_RELATION_ASSIGNEE_LIST_INFO + dto.getToActivityId());
|
||||||
|
runtimeService.createChangeActivityStateBuilder()
|
||||||
|
.processInstanceId(task.getProcessInstanceId())
|
||||||
|
.moveActivityIdsToSingleActivityId(Collections.singletonList(task.getTaskDefinitionKey()), dto.getToActivityId())
|
||||||
|
.changeState();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,102 @@
|
|||||||
|
package cn.axzo.workflow.core.engine.cmd;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivitySetAssigneeDTO;
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||||
|
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
||||||
|
import cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper;
|
||||||
|
import cn.axzo.workflow.core.engine.job.AsyncActivitySetAssigneeJobHandler;
|
||||||
|
import cn.axzo.workflow.core.engine.job.AsyncApproveTaskJobHandler;
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||||
|
import org.flowable.engine.HistoryService;
|
||||||
|
import org.flowable.engine.ProcessEngineConfiguration;
|
||||||
|
import org.flowable.engine.RuntimeService;
|
||||||
|
import org.flowable.engine.TaskService;
|
||||||
|
import org.flowable.engine.history.HistoricProcessInstance;
|
||||||
|
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
|
||||||
|
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||||
|
import org.flowable.job.service.JobService;
|
||||||
|
import org.flowable.job.service.impl.persistence.entity.JobEntity;
|
||||||
|
import org.flowable.task.api.Task;
|
||||||
|
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.HIDDEN_ASSIGNEE_ID;
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_ACTIVITY_RELATION_ASSIGNEE_LIST_INFO_SNAPSHOT;
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.NO_ASSIGNEE;
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_COMPLETE_OPERATION_TYPE;
|
||||||
|
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.DELETED;
|
||||||
|
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.PROCESSING;
|
||||||
|
import static cn.axzo.workflow.core.common.code.BpmnInstanceRespCode.PROCESS_INSTANCE_ID_NOT_EXISTS;
|
||||||
|
import static cn.axzo.workflow.core.common.code.BpmnTaskRespCode.ACTIVITY_BIZ_SET_ASSIGNEE_ERROR;
|
||||||
|
import static cn.axzo.workflow.core.common.code.BpmnTaskRespCode.ACTIVITY_CANT_SET_ASSIGNEE;
|
||||||
|
import static cn.axzo.workflow.core.common.code.BpmnTaskRespCode.PROCESS_CANT_SET_ASSIGNEE;
|
||||||
|
import static cn.axzo.workflow.core.engine.cmd.CustomBizSpecifyAssigneeToTaskCmd.getOperateTask;
|
||||||
|
import static cn.axzo.workflow.core.engine.cmd.CustomBizSpecifyAssigneeToTaskCmd.validProcessInstance;
|
||||||
|
import static cn.axzo.workflow.core.engine.cmd.CustomBizSpecifyAssigneeToTaskCmd.validate;
|
||||||
|
import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.validTaskAssignerCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定的业务指定审批人命令实现
|
||||||
|
*
|
||||||
|
* @author wangli
|
||||||
|
* @since 2023/12/22 13:51
|
||||||
|
*/
|
||||||
|
public class CustomBizSpecifyAssigneeToTaskAsyncCmd extends AbstractCommand<String> implements Serializable {
|
||||||
|
|
||||||
|
private final BpmnActivitySetAssigneeDTO dto;
|
||||||
|
|
||||||
|
public CustomBizSpecifyAssigneeToTaskAsyncCmd(BpmnActivitySetAssigneeDTO dto) {
|
||||||
|
this.dto = dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String paramToJsonString() {
|
||||||
|
return JSON.toJSONString(dto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String execute(CommandContext commandContext) {
|
||||||
|
ProcessEngineConfigurationImpl processEngineConfiguration =
|
||||||
|
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||||
|
TaskService taskService = processEngineConfiguration.getTaskService();
|
||||||
|
TaskEntity task = (TaskEntity) getOperateTask(taskService, dto.getTriggerId());
|
||||||
|
//校验
|
||||||
|
validate(processEngineConfiguration.getRuntimeService(), dto.getTriggerId(), task, dto.getAssigners());
|
||||||
|
|
||||||
|
validProcessInstance(commandContext, task);
|
||||||
|
|
||||||
|
return startAsync(processEngineConfiguration, task);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String 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(AsyncActivitySetAssigneeJobHandler.TYPE);
|
||||||
|
job.setTenantId(task.getTenantId());
|
||||||
|
|
||||||
|
// 携带自定义的数据
|
||||||
|
job.setCustomValues(JSONUtil.toJsonStr(dto));
|
||||||
|
|
||||||
|
// 创建异步任务并调度
|
||||||
|
jobService.createAsyncJob(job, false);
|
||||||
|
jobService.scheduleAsyncJob(job);
|
||||||
|
return job.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -6,11 +6,14 @@ import cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper;
|
|||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||||
import org.flowable.engine.HistoryService;
|
import org.flowable.engine.HistoryService;
|
||||||
|
import org.flowable.engine.ManagementService;
|
||||||
import org.flowable.engine.RuntimeService;
|
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.impl.cfg.ProcessEngineConfigurationImpl;
|
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
|
||||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||||
|
import org.flowable.job.api.Job;
|
||||||
|
import org.flowable.job.service.impl.persistence.entity.TimerJobEntity;
|
||||||
import org.flowable.task.api.Task;
|
import org.flowable.task.api.Task;
|
||||||
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
@ -59,8 +62,8 @@ public class CustomBizSpecifyAssigneeToTaskCmd extends AbstractCommand<Boolean>
|
|||||||
|
|
||||||
public static Task getOperateTask(TaskService taskService, String executionId) {
|
public static Task getOperateTask(TaskService taskService, String executionId) {
|
||||||
return taskService.createTaskQuery().executionId(executionId)
|
return taskService.createTaskQuery().executionId(executionId)
|
||||||
.taskAssignee(NO_ASSIGNEE)
|
.taskAssignee(NO_ASSIGNEE)
|
||||||
.singleResult();
|
.singleResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -79,9 +82,9 @@ public class CustomBizSpecifyAssigneeToTaskCmd extends AbstractCommand<Boolean>
|
|||||||
@Override
|
@Override
|
||||||
public Boolean execute(CommandContext commandContext) {
|
public Boolean execute(CommandContext commandContext) {
|
||||||
ProcessEngineConfigurationImpl processEngineConfiguration =
|
ProcessEngineConfigurationImpl processEngineConfiguration =
|
||||||
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||||
TaskService taskService = processEngineConfiguration.getTaskService();
|
TaskService taskService = processEngineConfiguration.getTaskService();
|
||||||
Task task = getOperateTask(taskService, executionId);
|
TaskEntity task = (TaskEntity) getOperateTask(taskService, executionId);
|
||||||
//校验
|
//校验
|
||||||
validate(processEngineConfiguration.getRuntimeService(), executionId, task, addedAssigners);
|
validate(processEngineConfiguration.getRuntimeService(), executionId, task, addedAssigners);
|
||||||
|
|
||||||
@ -91,12 +94,29 @@ public class CustomBizSpecifyAssigneeToTaskCmd extends AbstractCommand<Boolean>
|
|||||||
|
|
||||||
addAssignee(commandContext, taskService, task);
|
addAssignee(commandContext, taskService, task);
|
||||||
|
|
||||||
|
clearAlterTimeJob(commandContext, task);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validProcessInstance(CommandContext commandContext, Task task) {
|
/**
|
||||||
|
* 清空告警的任务
|
||||||
|
*
|
||||||
|
* @param commandContext
|
||||||
|
* @param task
|
||||||
|
*/
|
||||||
|
private void clearAlterTimeJob(CommandContext commandContext, TaskEntity task) {
|
||||||
|
ManagementService managementService = CommandContextUtil.getProcessEngineConfiguration(commandContext).getManagementService();
|
||||||
|
Job timerJob = managementService.createTimerJobQuery().elementId(task.getTaskDefinitionKey()).processInstanceId(task.getProcessInstanceId()).singleResult();
|
||||||
|
if (Objects.nonNull(timerJob)) {
|
||||||
|
CommandContextUtil.getTimerJobService().deleteTimerJob((TimerJobEntity) timerJob);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void validProcessInstance(CommandContext commandContext, Task task) {
|
||||||
ProcessEngineConfigurationImpl processEngineConfiguration =
|
ProcessEngineConfigurationImpl processEngineConfiguration =
|
||||||
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||||
HistoryService historyService = processEngineConfiguration.getHistoryService();
|
HistoryService historyService = processEngineConfiguration.getHistoryService();
|
||||||
HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
|
HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
|
||||||
if (Objects.isNull(processInstance)) {
|
if (Objects.isNull(processInstance)) {
|
||||||
@ -110,11 +130,11 @@ public class CustomBizSpecifyAssigneeToTaskCmd extends AbstractCommand<Boolean>
|
|||||||
|
|
||||||
private void changeAssigneeSnapshot(CommandContext commandContext, Task task) {
|
private void changeAssigneeSnapshot(CommandContext commandContext, Task task) {
|
||||||
ProcessEngineConfigurationImpl processEngineConfiguration =
|
ProcessEngineConfigurationImpl processEngineConfiguration =
|
||||||
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||||
RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
|
RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
|
||||||
|
|
||||||
List<BpmnTaskDelegateAssigner> originAssingeeList = runtimeService.getVariable(task.getProcessInstanceId(),
|
List<BpmnTaskDelegateAssigner> originAssingeeList = runtimeService.getVariable(task.getProcessInstanceId(),
|
||||||
INTERNAL_ACTIVITY_RELATION_ASSIGNEE_LIST_INFO_SNAPSHOT + task.getTaskDefinitionKey(), List.class);
|
INTERNAL_ACTIVITY_RELATION_ASSIGNEE_LIST_INFO_SNAPSHOT + task.getTaskDefinitionKey(), List.class);
|
||||||
|
|
||||||
for (BpmnTaskDelegateAssigner assigner : originAssingeeList) {
|
for (BpmnTaskDelegateAssigner assigner : originAssingeeList) {
|
||||||
if (Objects.equals(assigner.buildAssigneeId(), NO_ASSIGNEE)) {
|
if (Objects.equals(assigner.buildAssigneeId(), NO_ASSIGNEE)) {
|
||||||
@ -124,8 +144,8 @@ public class CustomBizSpecifyAssigneeToTaskCmd extends AbstractCommand<Boolean>
|
|||||||
}
|
}
|
||||||
originAssingeeList.addAll(addedAssigners);
|
originAssingeeList.addAll(addedAssigners);
|
||||||
runtimeService.setVariable(task.getProcessInstanceId(),
|
runtimeService.setVariable(task.getProcessInstanceId(),
|
||||||
INTERNAL_ACTIVITY_RELATION_ASSIGNEE_LIST_INFO_SNAPSHOT + task.getTaskDefinitionKey(),
|
INTERNAL_ACTIVITY_RELATION_ASSIGNEE_LIST_INFO_SNAPSHOT + task.getTaskDefinitionKey(),
|
||||||
originAssingeeList);
|
originAssingeeList);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addAssignee(CommandContext commandContext, TaskService taskService, Task task) {
|
private void addAssignee(CommandContext commandContext, TaskService taskService, Task task) {
|
||||||
|
|||||||
@ -3,7 +3,7 @@ package cn.axzo.workflow.core.engine.cmd;
|
|||||||
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCancelDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCancelDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||||
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
||||||
import cn.axzo.workflow.core.engine.job.AsyncCancelProcessInstanceHandler;
|
import cn.axzo.workflow.core.engine.job.AsyncCancelProcessInstanceJobHandler;
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||||
@ -74,9 +74,9 @@ public class CustomCancelProcessInstanceAsyncCmd extends AbstractCommand<Void> i
|
|||||||
job.setExecutionId(instance.getId());
|
job.setExecutionId(instance.getId());
|
||||||
job.setProcessInstanceId(instance.getId());
|
job.setProcessInstanceId(instance.getId());
|
||||||
job.setProcessDefinitionId(instance.getProcessDefinitionId());
|
job.setProcessDefinitionId(instance.getProcessDefinitionId());
|
||||||
job.setElementId(AsyncCancelProcessInstanceHandler.TYPE);
|
job.setElementId(AsyncCancelProcessInstanceJobHandler.TYPE);
|
||||||
job.setElementName(instance.getName());
|
job.setElementName(instance.getName());
|
||||||
job.setJobHandlerType(AsyncCancelProcessInstanceHandler.TYPE);
|
job.setJobHandlerType(AsyncCancelProcessInstanceJobHandler.TYPE);
|
||||||
job.setTenantId(instance.getTenantId());
|
job.setTenantId(instance.getTenantId());
|
||||||
|
|
||||||
// 携带自定义的数据
|
// 携带自定义的数据
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package cn.axzo.workflow.core.engine.cmd;
|
|||||||
|
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||||
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
||||||
|
import cn.axzo.workflow.core.engine.model.AddComment;
|
||||||
import cn.axzo.workflow.core.engine.operation.DeleteProcessInstanceOperation;
|
import cn.axzo.workflow.core.engine.operation.DeleteProcessInstanceOperation;
|
||||||
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
|
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
@ -18,7 +19,6 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.COMMENT_TYPE_OPERATION_DESC;
|
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_DELETE_PROCESS_FLAG;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_DELETE_PROCESS_FLAG;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_END_TENANT_ID;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_END_TENANT_ID;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_END_USER_ID;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_END_USER_ID;
|
||||||
@ -32,7 +32,7 @@ import static cn.axzo.workflow.core.common.code.BpmnInstanceRespCode.PROCESS_INS
|
|||||||
import static cn.axzo.workflow.core.common.code.BpmnInstanceRespCode.PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF;
|
import static cn.axzo.workflow.core.common.code.BpmnInstanceRespCode.PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF;
|
||||||
import static cn.axzo.workflow.core.common.code.BpmnInstanceRespCode.PROCESS_INSTANCE_CANT_CANCEL;
|
import static cn.axzo.workflow.core.common.code.BpmnInstanceRespCode.PROCESS_INSTANCE_CANT_CANCEL;
|
||||||
import static cn.axzo.workflow.core.common.code.BpmnInstanceRespCode.PROCESS_INSTANCE_NOT_EXISTS;
|
import static cn.axzo.workflow.core.common.code.BpmnInstanceRespCode.PROCESS_INSTANCE_NOT_EXISTS;
|
||||||
import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.addComment;
|
import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.completeVirtualTask;
|
||||||
import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.createVirtualTask;
|
import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.createVirtualTask;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -104,12 +104,12 @@ public class CustomCancelProcessInstanceCmd extends AbstractCommand<Void> implem
|
|||||||
runtimeService.setVariables(instance.getId(), variables);
|
runtimeService.setVariables(instance.getId(), variables);
|
||||||
|
|
||||||
CommandContextUtil.getAgenda(commandContext).planOperation(new DeleteProcessInstanceOperation(commandContext,
|
CommandContextUtil.getAgenda(commandContext).planOperation(new DeleteProcessInstanceOperation(commandContext,
|
||||||
processInstanceId, extAxHiTaskInstService));
|
processInstanceId, extAxHiTaskInstService, CANCELLED));
|
||||||
|
|
||||||
// 添加自定义的节点,用于展示最后的操作
|
// 添加自定义的节点,用于展示最后的操作
|
||||||
Task task = createVirtualTask(commandContext, extAxHiTaskInstService, processInstanceId,
|
Task task = createVirtualTask(commandContext, extAxHiTaskInstService, processInstanceId,
|
||||||
"发起人撤回", NODE_CANCEL.getType(), reason, initiator, CANCELLED.getStatus());
|
"发起人撤回", NODE_CANCEL.getType(), reason, initiator, CANCELLED.getStatus(), new AddComment(CANCELLED.getDesc()));
|
||||||
addComment(commandContext, task, COMMENT_TYPE_OPERATION_DESC, "已撤回");
|
completeVirtualTask(commandContext, task);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +1,16 @@
|
|||||||
package cn.axzo.workflow.core.engine.cmd;
|
package cn.axzo.workflow.core.engine.cmd;
|
||||||
|
|
||||||
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
||||||
|
import org.apache.ibatis.exceptions.PersistenceException;
|
||||||
import org.flowable.common.engine.api.FlowableException;
|
import org.flowable.common.engine.api.FlowableException;
|
||||||
import org.flowable.common.engine.api.FlowableOptimisticLockingException;
|
import org.flowable.common.engine.api.FlowableOptimisticLockingException;
|
||||||
import org.flowable.common.engine.impl.interceptor.Command;
|
import org.flowable.common.engine.impl.interceptor.Command;
|
||||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对 CommandContext 中的 WorkflowEngineException 进行日志降级
|
* 对 CommandContext 中的 WorkflowEngineException 进行日志降级
|
||||||
@ -15,7 +19,9 @@ import org.slf4j.LoggerFactory;
|
|||||||
* @since 2024/5/21 09:46
|
* @since 2024/5/21 09:46
|
||||||
*/
|
*/
|
||||||
public class CustomCommandContext extends CommandContext {
|
public class CustomCommandContext extends CommandContext {
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(CommandContext.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(CustomCommandContext.class);
|
||||||
|
|
||||||
|
private static final String[] PERSISTENCE_EXCEPTION_WARN_MESSAGE = new String[]{"act_ru_job"};
|
||||||
|
|
||||||
public CustomCommandContext(Command<?> command) {
|
public CustomCommandContext(Command<?> command) {
|
||||||
super(command);
|
super(command);
|
||||||
@ -36,6 +42,10 @@ public class CustomCommandContext extends CommandContext {
|
|||||||
LOGGER.info("Error while closing command context", exception);
|
LOGGER.info("Error while closing command context", exception);
|
||||||
} else if (exception instanceof WorkflowEngineException) {
|
} else if (exception instanceof WorkflowEngineException) {
|
||||||
LOGGER.warn("Workflow error while closing command context", exception);
|
LOGGER.warn("Workflow error while closing command context", exception);
|
||||||
|
} else if (exception instanceof PersistenceException &&
|
||||||
|
StringUtils.hasText(exception.getMessage()) &&
|
||||||
|
Arrays.stream(PERSISTENCE_EXCEPTION_WARN_MESSAGE).anyMatch(m -> exception.getMessage().contains(m))) {
|
||||||
|
LOGGER.warn("persistence error while closing command context", exception);
|
||||||
} else {
|
} else {
|
||||||
LOGGER.error("Error while closing command context", exception);
|
LOGGER.error("Error while closing command context", exception);
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import org.flowable.common.engine.impl.interceptor.CommandContext;
|
|||||||
import org.flowable.common.engine.impl.interceptor.CommandContextFactory;
|
import org.flowable.common.engine.impl.interceptor.CommandContextFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* CommandContextFactory
|
||||||
*
|
*
|
||||||
* @author wangli
|
* @author wangli
|
||||||
* @since 2024/5/21 09:45
|
* @since 2024/5/21 09:45
|
||||||
|
|||||||
@ -4,13 +4,11 @@ import cn.axzo.workflow.common.model.request.bpmn.task.AttachmentDTO;
|
|||||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskCommentExtDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskCommentExtDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||||
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
||||||
import cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper;
|
|
||||||
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
|
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import org.flowable.common.engine.impl.cfg.IdGenerator;
|
import org.flowable.common.engine.impl.cfg.IdGenerator;
|
||||||
import org.flowable.common.engine.impl.identity.Authentication;
|
import org.flowable.common.engine.impl.identity.Authentication;
|
||||||
import org.flowable.common.engine.impl.interceptor.Command;
|
|
||||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||||
import org.flowable.engine.HistoryService;
|
import org.flowable.engine.HistoryService;
|
||||||
import org.flowable.engine.TaskService;
|
import org.flowable.engine.TaskService;
|
||||||
@ -22,7 +20,6 @@ import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
|||||||
import org.flowable.variable.service.HistoricVariableService;
|
import org.flowable.variable.service.HistoricVariableService;
|
||||||
import org.flowable.variable.service.impl.persistence.entity.HistoricVariableInstanceEntity;
|
import org.flowable.variable.service.impl.persistence.entity.HistoricVariableInstanceEntity;
|
||||||
import org.flowable.variable.service.impl.types.StringType;
|
import org.flowable.variable.service.impl.types.StringType;
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
@ -36,9 +33,13 @@ import java.util.Objects;
|
|||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.COMMENT_TYPE_ADVICE;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.COMMENT_TYPE_ADVICE;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.COMMENT_TYPE_COMMENT_EXT;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.COMMENT_TYPE_COMMENT_EXT;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_TASK_RELATION_ASSIGNEE_INFO;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_TASK_RELATION_ASSIGNEE_INFO;
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_COMPLETE_OPERATION_TYPE;
|
||||||
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_COMMENT;
|
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_COMMENT;
|
||||||
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.COMMENTED;
|
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.COMMENTED;
|
||||||
import static cn.axzo.workflow.core.common.code.BpmnInstanceRespCode.TASK_CANT_COMMENT_INSTANCE_NOT_EXISTS;
|
import static cn.axzo.workflow.core.common.code.BpmnInstanceRespCode.TASK_CANT_COMMENT_INSTANCE_NOT_EXISTS;
|
||||||
|
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.createExtTaskInst;
|
||||||
import static org.flowable.task.api.Task.DEFAULT_PRIORITY;
|
import static org.flowable.task.api.Task.DEFAULT_PRIORITY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -80,11 +81,11 @@ public class CustomCommentTaskCmd extends AbstractCommand<Void> implements Seria
|
|||||||
@Override
|
@Override
|
||||||
public Void execute(CommandContext commandContext) {
|
public Void execute(CommandContext commandContext) {
|
||||||
ProcessEngineConfigurationImpl processEngineConfiguration =
|
ProcessEngineConfigurationImpl processEngineConfiguration =
|
||||||
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||||
HistoryService historyService = processEngineConfiguration.getHistoryService();
|
HistoryService historyService = processEngineConfiguration.getHistoryService();
|
||||||
|
|
||||||
HistoricProcessInstance processInstance =
|
HistoricProcessInstance processInstance =
|
||||||
historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
|
historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
|
||||||
if (Objects.isNull(processInstance)) {
|
if (Objects.isNull(processInstance)) {
|
||||||
throw new WorkflowEngineException(TASK_CANT_COMMENT_INSTANCE_NOT_EXISTS, processInstanceId);
|
throw new WorkflowEngineException(TASK_CANT_COMMENT_INSTANCE_NOT_EXISTS, processInstanceId);
|
||||||
}
|
}
|
||||||
@ -103,32 +104,34 @@ public class CustomCommentTaskCmd extends AbstractCommand<Void> implements Seria
|
|||||||
task.setTaskDefinitionKey(NODE_COMMENT.getType());
|
task.setTaskDefinitionKey(NODE_COMMENT.getType());
|
||||||
task.setPriority(DEFAULT_PRIORITY);
|
task.setPriority(DEFAULT_PRIORITY);
|
||||||
task.setCreateTime(new Date());
|
task.setCreateTime(new Date());
|
||||||
// 创建临时节点
|
|
||||||
taskService.saveTask(task);
|
|
||||||
// 处理该评论节点的评论人
|
// 处理该评论节点的评论人
|
||||||
buildAndInsertHistoryVariable(task, processInstance, processEngineConfiguration);
|
buildAndInsertHistoryVariable(task, processInstance, processEngineConfiguration);
|
||||||
|
|
||||||
CommandContextUtil.getEntityCache().findInCache(HistoricTaskInstanceEntity.class).stream()
|
CommandContextUtil.getEntityCache().findInCache(HistoricTaskInstanceEntity.class).stream()
|
||||||
.filter(i -> Objects.equals(i.getId(), task.getId())).findAny()
|
.filter(i -> Objects.equals(i.getId(), task.getId())).findAny()
|
||||||
.ifPresent(i -> i.setAssignee(operator.buildAssigneeId()));
|
.ifPresent(i -> i.setAssignee(operator.buildAssigneeId()));
|
||||||
// 完成临时节点
|
|
||||||
taskService.complete(task.getId());
|
createExtTaskInst(extAxHiTaskInstService, processInstanceId,
|
||||||
|
task.getId(), task.getTaskDefinitionKey(), operator, COMMENTED.getStatus());
|
||||||
|
task.setTransientVariable(TASK_COMPLETE_OPERATION_TYPE + task.getId(), COMMENTED.getStatus());
|
||||||
|
|
||||||
|
// 保存临时节点
|
||||||
|
taskService.saveTask(task);
|
||||||
|
|
||||||
// 新增评论
|
// 新增评论
|
||||||
Authentication.setAuthenticatedUserId(operator.buildAssigneeId());
|
Authentication.setAuthenticatedUserId(operator.buildAssigneeId());
|
||||||
if (StringUtils.hasText(comment)) {
|
addComment(commandContext, task, COMMENT_TYPE_ADVICE, comment);
|
||||||
CustomTaskHelper.addComment(commandContext, task, COMMENT_TYPE_ADVICE, comment);
|
addComment(commandContext, task, COMMENT_TYPE_COMMENT_EXT, JSONUtil.toJsonStr(commentExt));
|
||||||
}
|
|
||||||
if (Objects.nonNull(commentExt)) {
|
|
||||||
CustomTaskHelper.addComment(commandContext, task, COMMENT_TYPE_COMMENT_EXT, JSONUtil.toJsonStr(commentExt));
|
|
||||||
}
|
|
||||||
Authentication.setAuthenticatedUserId(null);
|
Authentication.setAuthenticatedUserId(null);
|
||||||
|
|
||||||
// 处理附件
|
// 处理附件
|
||||||
CustomTaskHelper.batchAddAttachment(commandContext, processInstanceId, task.getId(), attachmentList, operator);
|
batchAddAttachment(commandContext, processInstanceId, task, attachmentList, operator);
|
||||||
|
|
||||||
CustomTaskHelper.createExtTaskInst(extAxHiTaskInstService, processInstanceId,
|
// 设置快照信息
|
||||||
task.getId(), task.getTaskDefinitionKey(), operator, COMMENTED.getStatus());
|
task.setTransientVariable(INTERNAL_TASK_RELATION_ASSIGNEE_INFO + task.getId(), operator.toJson());
|
||||||
|
|
||||||
|
// 完成临时节点
|
||||||
|
taskService.complete(task.getId());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,9 +139,9 @@ public class CustomCommentTaskCmd extends AbstractCommand<Void> implements Seria
|
|||||||
HistoricProcessInstance processInstance,
|
HistoricProcessInstance processInstance,
|
||||||
ProcessEngineConfigurationImpl processEngineConfiguration) {
|
ProcessEngineConfigurationImpl processEngineConfiguration) {
|
||||||
HistoricVariableService historicVariableService =
|
HistoricVariableService historicVariableService =
|
||||||
processEngineConfiguration.getVariableServiceConfiguration().getHistoricVariableService();
|
processEngineConfiguration.getVariableServiceConfiguration().getHistoricVariableService();
|
||||||
HistoricVariableInstanceEntity historicVariableInstance =
|
HistoricVariableInstanceEntity historicVariableInstance =
|
||||||
historicVariableService.createHistoricVariableInstance();
|
historicVariableService.createHistoricVariableInstance();
|
||||||
historicVariableInstance.setTaskId(task.getId());
|
historicVariableInstance.setTaskId(task.getId());
|
||||||
historicVariableInstance.setExecutionId(task.getExecutionId());
|
historicVariableInstance.setExecutionId(task.getExecutionId());
|
||||||
historicVariableInstance.setProcessInstanceId(processInstance.getId());
|
historicVariableInstance.setProcessInstanceId(processInstance.getId());
|
||||||
|
|||||||
@ -7,12 +7,12 @@ import cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper;
|
|||||||
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
|
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import org.flowable.common.engine.impl.identity.Authentication;
|
import org.flowable.common.engine.impl.identity.Authentication;
|
||||||
import org.flowable.common.engine.impl.interceptor.Command;
|
|
||||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||||
import org.flowable.engine.TaskService;
|
import org.flowable.engine.TaskService;
|
||||||
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
|
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
|
||||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||||
import org.flowable.task.api.Task;
|
import org.flowable.task.api.Task;
|
||||||
|
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ public class CustomCompleteDummyTaskCmd extends AbstractCommand<Void> implements
|
|||||||
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||||
|
|
||||||
TaskService taskService = processEngineConfiguration.getTaskService();
|
TaskService taskService = processEngineConfiguration.getTaskService();
|
||||||
Task task = taskService.createTaskQuery().processInstanceId(processInstanceId)
|
TaskEntity task = (TaskEntity) taskService.createTaskQuery().processInstanceId(processInstanceId)
|
||||||
.taskId(taskId).singleResult();
|
.taskId(taskId).singleResult();
|
||||||
if (Objects.isNull(task)) {
|
if (Objects.isNull(task)) {
|
||||||
throw new WorkflowEngineException(DUMMY_TASK_NOT_EXISTS, processInstanceId, taskId);
|
throw new WorkflowEngineException(DUMMY_TASK_NOT_EXISTS, processInstanceId, taskId);
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import cn.axzo.workflow.common.enums.BpmnCountersignTypeEnum;
|
|||||||
import cn.axzo.workflow.common.model.request.bpmn.task.AttachmentDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.task.AttachmentDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||||
import cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper;
|
import cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper;
|
||||||
|
import cn.axzo.workflow.core.engine.model.AddComment;
|
||||||
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
|
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
@ -23,12 +24,11 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.COMMENT_TYPE_OPERATION_DESC;
|
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.COUNTERSIGN_ASSIGNER_SHOW_NUMBER;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.COUNTERSIGN_ASSIGNER_SHOW_NUMBER;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_ACTIVITY_RELATION_ASSIGNEE_LIST_INFO_SNAPSHOT;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_ACTIVITY_RELATION_ASSIGNEE_LIST_INFO_SNAPSHOT;
|
||||||
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.COUNTERSIGN;
|
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.COUNTERSIGN;
|
||||||
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.batchAddAttachment;
|
||||||
|
import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.completeVirtualTask;
|
||||||
import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.createVirtualTask;
|
import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.createVirtualTask;
|
||||||
import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.validTask;
|
import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.validTask;
|
||||||
import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.validTaskAssignerCount;
|
import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.validTaskAssignerCount;
|
||||||
@ -81,24 +81,24 @@ public class CustomCountersignUserTaskCmd extends AbstractCommand<Void> implemen
|
|||||||
@Override
|
@Override
|
||||||
public Void execute(CommandContext commandContext) {
|
public Void execute(CommandContext commandContext) {
|
||||||
ProcessEngineConfigurationImpl processEngineConfiguration =
|
ProcessEngineConfigurationImpl processEngineConfiguration =
|
||||||
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||||
HistoricTaskInstanceQuery taskQuery =
|
HistoricTaskInstanceQuery taskQuery =
|
||||||
processEngineConfiguration.getHistoryService().createHistoricTaskInstanceQuery();
|
processEngineConfiguration.getHistoryService().createHistoricTaskInstanceQuery();
|
||||||
HistoricTaskInstance historicTaskInstance = taskQuery.taskId(originTaskId).singleResult();
|
HistoricTaskInstance historicTaskInstance = taskQuery.taskId(originTaskId).singleResult();
|
||||||
|
|
||||||
TaskService taskService = processEngineConfiguration.getTaskService();
|
TaskService taskService = processEngineConfiguration.getTaskService();
|
||||||
Task task = taskService.createTaskQuery().taskId(originTaskId).singleResult();
|
TaskEntity task = (TaskEntity) taskService.createTaskQuery().taskId(originTaskId).singleResult();
|
||||||
|
|
||||||
validTask(historicTaskInstance, (TaskEntity) task, originTaskAssignee, null);
|
validTask(historicTaskInstance, task, originTaskAssignee, null);
|
||||||
|
|
||||||
validTaskAssignerCount(processEngineConfiguration.getRuntimeService(), (TaskEntity) task, targetTaskAssigneeList);
|
validTaskAssignerCount(processEngineConfiguration.getRuntimeService(), task, targetTaskAssigneeList);
|
||||||
|
|
||||||
List<BpmnTaskDelegateAssigner> taskDelegateAssigners =
|
List<BpmnTaskDelegateAssigner> taskDelegateAssigners =
|
||||||
validTaskAssignerDuplicated(commandContext, (TaskEntity) task, targetTaskAssigneeList);
|
validTaskAssignerDuplicated(commandContext, task, targetTaskAssigneeList);
|
||||||
|
|
||||||
resolveOriginTask(commandContext, extAxHiTaskInstService, taskService, task);
|
resolveOriginTask(commandContext, extAxHiTaskInstService, taskService, task);
|
||||||
|
|
||||||
batchAddAttachment(commandContext, task.getProcessInstanceId(), task.getId(), attachmentList,
|
batchAddAttachment(commandContext, task.getProcessInstanceId(), task, attachmentList,
|
||||||
originTaskAssignee);
|
originTaskAssignee);
|
||||||
|
|
||||||
switch (countersignType) {
|
switch (countersignType) {
|
||||||
@ -110,7 +110,7 @@ public class CustomCountersignUserTaskCmd extends AbstractCommand<Void> implemen
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// share_counterSign
|
// share_counterSign
|
||||||
shareCountSign(commandContext, (TaskEntity) task, taskDelegateAssigners);
|
shareCountSign(commandContext, task, taskDelegateAssigners);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,11 +127,11 @@ public class CustomCountersignUserTaskCmd extends AbstractCommand<Void> implemen
|
|||||||
private void shareCountSign(CommandContext commandContext, TaskEntity taskEntity,
|
private void shareCountSign(CommandContext commandContext, TaskEntity taskEntity,
|
||||||
List<BpmnTaskDelegateAssigner> taskDelegateAssigners) {
|
List<BpmnTaskDelegateAssigner> taskDelegateAssigners) {
|
||||||
ProcessEngineConfigurationImpl processEngineConfiguration =
|
ProcessEngineConfigurationImpl processEngineConfiguration =
|
||||||
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||||
RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
|
RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
|
||||||
// 这个节点下所有审批人快照
|
// 这个节点下所有审批人快照
|
||||||
String activityListSnapshot =
|
String activityListSnapshot =
|
||||||
INTERNAL_ACTIVITY_RELATION_ASSIGNEE_LIST_INFO_SNAPSHOT + taskEntity.getTaskDefinitionKey();
|
INTERNAL_ACTIVITY_RELATION_ASSIGNEE_LIST_INFO_SNAPSHOT + taskEntity.getTaskDefinitionKey();
|
||||||
taskDelegateAssigners.addAll(targetTaskAssigneeList);
|
taskDelegateAssigners.addAll(targetTaskAssigneeList);
|
||||||
runtimeService.setVariable(taskEntity.getProcessInstanceId(), activityListSnapshot, taskDelegateAssigners);
|
runtimeService.setVariable(taskEntity.getProcessInstanceId(), activityListSnapshot, taskDelegateAssigners);
|
||||||
log.info("正在进行加签任务:{},待加签人合并列表:{}", taskEntity.getId(), JSONUtil.toJsonStr(taskDelegateAssigners));
|
log.info("正在进行加签任务:{},待加签人合并列表:{}", taskEntity.getId(), JSONUtil.toJsonStr(taskDelegateAssigners));
|
||||||
@ -142,22 +142,22 @@ public class CustomCountersignUserTaskCmd extends AbstractCommand<Void> implemen
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void resolveOriginTask(CommandContext commandContext, ExtAxHiTaskInstService extAxHiTaskInstService,
|
private void resolveOriginTask(CommandContext commandContext, ExtAxHiTaskInstService extAxHiTaskInstService,
|
||||||
TaskService taskService, Task task) {
|
TaskService taskService, TaskEntity task) {
|
||||||
// 构建评论内容
|
// 构建评论内容
|
||||||
StringBuilder message = new StringBuilder("添加");
|
StringBuilder message = new StringBuilder("添加");
|
||||||
int end = Math.min(targetTaskAssigneeList.size(), COUNTERSIGN_ASSIGNER_SHOW_NUMBER);
|
int end = Math.min(targetTaskAssigneeList.size(), COUNTERSIGN_ASSIGNER_SHOW_NUMBER);
|
||||||
//加签人员数量显示指定个数
|
//加签人员数量显示指定个数
|
||||||
for (int i = 0; i < end; i++) {
|
for (int i = 0; i < end; i++) {
|
||||||
message.append(targetTaskAssigneeList.get(i).getAssignerName());
|
message.append(targetTaskAssigneeList.get(i).getAssignerName());
|
||||||
if (i < targetTaskAssigneeList.size() - 1) {
|
if (i < end - 1) {
|
||||||
message.append("、");
|
message.append("、");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
message.append("等").append(targetTaskAssigneeList.size()).append("人进行审批");
|
message.append("等").append(targetTaskAssigneeList.size()).append("人进行审批");
|
||||||
Task virtualTask = createVirtualTask(commandContext, extAxHiTaskInstService, task.getProcessInstanceId(), task.getName(),
|
Task virtualTask = createVirtualTask(commandContext, extAxHiTaskInstService, task.getProcessInstanceId(), task.getName(),
|
||||||
task.getTaskDefinitionKey(), advice, originTaskAssignee, COUNTERSIGN.getStatus());
|
task.getTaskDefinitionKey(), advice, originTaskAssignee, COUNTERSIGN.getStatus(), new AddComment(message.toString()));
|
||||||
addComment(commandContext, virtualTask, COMMENT_TYPE_OPERATION_DESC, message.toString());
|
batchAddAttachment(commandContext, task.getProcessInstanceId(), task, attachmentList, originTaskAssignee);
|
||||||
batchAddAttachment(commandContext, task.getProcessInstanceId(), task.getId(), attachmentList, originTaskAssignee);
|
completeVirtualTask(commandContext, virtualTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import cn.axzo.workflow.common.enums.BpmnFlowNodeType;
|
|||||||
import cn.axzo.workflow.common.model.request.bpmn.task.AttachmentDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.task.AttachmentDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAuditDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAuditDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||||
|
import cn.axzo.workflow.core.engine.model.AddComment;
|
||||||
import cn.axzo.workflow.core.engine.operation.DeleteProcessInstanceOperation;
|
import cn.axzo.workflow.core.engine.operation.DeleteProcessInstanceOperation;
|
||||||
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
|
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
@ -23,7 +24,6 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.COMMENT_TYPE_OPERATION_DESC;
|
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_DELETE_PROCESS_FLAG;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_DELETE_PROCESS_FLAG;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_END_TENANT_ID;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_END_TENANT_ID;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_END_USER_ID;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_END_USER_ID;
|
||||||
@ -31,9 +31,10 @@ import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_END_USER_N
|
|||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_PROCESS_DELETE_REASON;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_PROCESS_DELETE_REASON;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_PROCESS_TYPE_REJECT;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_PROCESS_TYPE_REJECT;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_COMPLETE_OPERATION_TYPE;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_COMPLETE_OPERATION_TYPE;
|
||||||
|
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.DELETED;
|
||||||
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.REJECTED;
|
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.REJECTED;
|
||||||
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.batchAddAttachment;
|
||||||
|
import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.completeVirtualTask;
|
||||||
import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.createVirtualTask;
|
import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.createVirtualTask;
|
||||||
import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.validTask;
|
import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.validTask;
|
||||||
|
|
||||||
@ -69,7 +70,7 @@ public class CustomRejectionTaskCmd extends AbstractCommand<Void> implements Ser
|
|||||||
if (Objects.nonNull(operationDesc)) {
|
if (Objects.nonNull(operationDesc)) {
|
||||||
this.operationDesc = operationDesc;
|
this.operationDesc = operationDesc;
|
||||||
} else {
|
} else {
|
||||||
this.operationDesc = "已驳回";
|
this.operationDesc = "(已驳回)";
|
||||||
}
|
}
|
||||||
this.attachmentList = dto.getAttachmentList();
|
this.attachmentList = dto.getAttachmentList();
|
||||||
this.approver = dto.getApprover();
|
this.approver = dto.getApprover();
|
||||||
@ -97,17 +98,18 @@ public class CustomRejectionTaskCmd extends AbstractCommand<Void> implements Ser
|
|||||||
HistoricTaskInstance historicTaskInstance = taskQuery.taskId(taskId).singleResult();
|
HistoricTaskInstance historicTaskInstance = taskQuery.taskId(taskId).singleResult();
|
||||||
|
|
||||||
TaskService taskService = processEngineConfiguration.getTaskService();
|
TaskService taskService = processEngineConfiguration.getTaskService();
|
||||||
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
|
TaskEntity task = (TaskEntity) taskService.createTaskQuery().taskId(taskId).singleResult();
|
||||||
|
|
||||||
validTask(historicTaskInstance, (TaskEntity) task, approver, nodeTypes);
|
validTask(historicTaskInstance, task, approver, nodeTypes);
|
||||||
|
|
||||||
((TaskEntity) task).setTransientVariable(TASK_COMPLETE_OPERATION_TYPE + task.getId(), REJECTED.getStatus());
|
task.setTransientVariable(TASK_COMPLETE_OPERATION_TYPE + task.getId(), DELETED.getStatus());
|
||||||
Task virtualTask = createVirtualTask(commandContext, extAxHiTaskInstService, task.getProcessInstanceId(), task.getName(),
|
TaskEntity virtualTask = createVirtualTask(commandContext, extAxHiTaskInstService, task.getProcessInstanceId(), task.getName(),
|
||||||
task.getTaskDefinitionKey(), advice, Objects.equals(operationDesc, "自动驳回") ? null : approver, REJECTED.getStatus());
|
task.getTaskDefinitionKey(), advice,
|
||||||
|
Objects.equals(operationDesc, "自动驳回") ? null : approver, REJECTED.getStatus(),
|
||||||
|
new AddComment(operationDesc));
|
||||||
|
|
||||||
addComment(commandContext, virtualTask, COMMENT_TYPE_OPERATION_DESC, operationDesc);
|
batchAddAttachment(commandContext, task.getProcessInstanceId(), virtualTask, attachmentList, approver);
|
||||||
|
completeVirtualTask(commandContext, virtualTask);
|
||||||
batchAddAttachment(commandContext, task.getProcessInstanceId(), virtualTask.getId(), attachmentList, approver);
|
|
||||||
|
|
||||||
RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
|
RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
|
||||||
finishProcessInstance(commandContext, runtimeService, task, advice);
|
finishProcessInstance(commandContext, runtimeService, task, advice);
|
||||||
@ -125,7 +127,7 @@ public class CustomRejectionTaskCmd extends AbstractCommand<Void> implements Ser
|
|||||||
runtimeService.setVariables(task.getProcessInstanceId(), variables);
|
runtimeService.setVariables(task.getProcessInstanceId(), variables);
|
||||||
CommandContextUtil.getAgenda(commandContext)
|
CommandContextUtil.getAgenda(commandContext)
|
||||||
.planOperation(new DeleteProcessInstanceOperation(commandContext, task.getProcessInstanceId(),
|
.planOperation(new DeleteProcessInstanceOperation(commandContext, task.getProcessInstanceId(),
|
||||||
extAxHiTaskInstService));
|
extAxHiTaskInstService, REJECTED));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,28 @@
|
|||||||
|
package cn.axzo.workflow.core.engine.cmd;
|
||||||
|
|
||||||
|
import org.flowable.bpmn.model.TimerEventDefinition;
|
||||||
|
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||||
|
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
|
||||||
|
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义的节点长时间卡住的告警
|
||||||
|
*
|
||||||
|
* @author wangli
|
||||||
|
* @since 2024-09-11 13:44
|
||||||
|
*/
|
||||||
|
public class CustomTermNodePausingAlertCmd extends AbstractCommand<Void> implements Serializable {
|
||||||
|
@Override
|
||||||
|
public String paramToJsonString() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void executeInternal(CommandContext commandContext) {
|
||||||
|
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -6,7 +6,6 @@ import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
|||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import org.flowable.common.engine.impl.identity.Authentication;
|
import org.flowable.common.engine.impl.identity.Authentication;
|
||||||
import org.flowable.common.engine.impl.interceptor.Command;
|
|
||||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||||
import org.flowable.engine.RuntimeService;
|
import org.flowable.engine.RuntimeService;
|
||||||
import org.flowable.engine.TaskService;
|
import org.flowable.engine.TaskService;
|
||||||
@ -16,7 +15,6 @@ import org.flowable.task.api.Task;
|
|||||||
import org.flowable.task.api.history.HistoricTaskInstance;
|
import org.flowable.task.api.history.HistoricTaskInstance;
|
||||||
import org.flowable.task.api.history.HistoricTaskInstanceQuery;
|
import org.flowable.task.api.history.HistoricTaskInstanceQuery;
|
||||||
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -77,52 +75,54 @@ public class CustomTransferUserTaskCmd extends AbstractCommand<Void> implements
|
|||||||
@Override
|
@Override
|
||||||
public Void execute(CommandContext commandContext) {
|
public Void execute(CommandContext commandContext) {
|
||||||
ProcessEngineConfigurationImpl processEngineConfiguration =
|
ProcessEngineConfigurationImpl processEngineConfiguration =
|
||||||
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||||
HistoricTaskInstanceQuery taskQuery =
|
HistoricTaskInstanceQuery taskQuery =
|
||||||
processEngineConfiguration.getHistoryService().createHistoricTaskInstanceQuery();
|
processEngineConfiguration.getHistoryService().createHistoricTaskInstanceQuery();
|
||||||
HistoricTaskInstance historicTaskInstance = taskQuery.taskId(originTaskId).singleResult();
|
HistoricTaskInstance historicTaskInstance = taskQuery.taskId(originTaskId).singleResult();
|
||||||
|
|
||||||
TaskService taskService = processEngineConfiguration.getTaskService();
|
TaskService taskService = processEngineConfiguration.getTaskService();
|
||||||
Task task = taskService.createTaskQuery().taskId(originTaskId).singleResult();
|
TaskEntity task = (TaskEntity) taskService.createTaskQuery().taskId(originTaskId).singleResult();
|
||||||
|
|
||||||
validTask(historicTaskInstance, (TaskEntity) task, originTaskAssignee, null);
|
validTask(historicTaskInstance, task, originTaskAssignee, null);
|
||||||
|
|
||||||
validTaskAssignerDuplicated(commandContext, (TaskEntity) task, Lists.newArrayList(targetTaskAssignee));
|
validTaskAssignerDuplicated(commandContext, task, Lists.newArrayList(targetTaskAssignee));
|
||||||
|
|
||||||
|
// 修改节点对应的审批人集合快照信息
|
||||||
processAssignee(processEngineConfiguration, task);
|
processAssignee(processEngineConfiguration, task);
|
||||||
|
|
||||||
|
// 对被转交的任务进行建议和附件的处理
|
||||||
resolveOriginTask(commandContext, taskService, task);
|
resolveOriginTask(commandContext, taskService, task);
|
||||||
|
batchAddAttachment(commandContext, task.getProcessInstanceId(), task, attachmentList,
|
||||||
|
originTaskAssignee);
|
||||||
|
|
||||||
batchAddAttachment(commandContext, task.getProcessInstanceId(), task.getId(), attachmentList,
|
// 生成转交任务
|
||||||
originTaskAssignee);
|
addMultiTask(commandContext, task, targetTaskAssignee);
|
||||||
|
task.setTransientVariable(TASK_COMPLETE_OPERATION_TYPE + task.getId(), TRANSFER.getStatus());
|
||||||
addMultiTask(commandContext, (TaskEntity) task, targetTaskAssignee);
|
// 结束被转交任务
|
||||||
((TaskEntity) task).setTransientVariable(TASK_COMPLETE_OPERATION_TYPE + task.getId(), TRANSFER.getStatus());
|
deleteMultiTask(commandContext, task);
|
||||||
deleteMultiTask(commandContext, (TaskEntity) task);
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resolveOriginTask(CommandContext commandContext, TaskService taskService, Task task) {
|
private void resolveOriginTask(CommandContext commandContext, TaskService taskService, TaskEntity task) {
|
||||||
BpmnTaskDelegateAssigner assigner = buildDummyAssigner("transfer", TASK_ASSIGNEE_SKIP_FLAT, "dummyApprover");
|
BpmnTaskDelegateAssigner assigner = buildDummyAssigner("transfer", TASK_ASSIGNEE_SKIP_FLAT, "dummyApprover");
|
||||||
task.setAssignee(assigner.buildAssigneeId());
|
task.setAssignee(assigner.buildAssigneeId());
|
||||||
((TaskEntity) task).setScopeType("TRANSFER");
|
task.setScopeType("TRANSFER");
|
||||||
taskService.saveTask(task);
|
|
||||||
|
|
||||||
Authentication.setAuthenticatedUserId(originTaskAssignee.buildAssigneeId());
|
Authentication.setAuthenticatedUserId(originTaskAssignee.buildAssigneeId());
|
||||||
addComment(commandContext, task, COMMENT_TYPE_OPERATION_DESC, "转交给" + targetTaskAssignee.getAssignerName());
|
addComment(commandContext, task, COMMENT_TYPE_OPERATION_DESC, "转交给" + targetTaskAssignee.getAssignerName());
|
||||||
if (StringUtils.hasLength(advice)) {
|
addComment(commandContext, task, COMMENT_TYPE_ADVICE, advice);
|
||||||
addComment(commandContext, task, COMMENT_TYPE_ADVICE, advice);
|
|
||||||
}
|
|
||||||
Authentication.setAuthenticatedUserId(null);
|
Authentication.setAuthenticatedUserId(null);
|
||||||
|
|
||||||
|
taskService.saveTask(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processAssignee(ProcessEngineConfigurationImpl processEngineConfiguration, Task task) {
|
public void processAssignee(ProcessEngineConfigurationImpl processEngineConfiguration, Task task) {
|
||||||
RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
|
RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
|
||||||
List<BpmnTaskDelegateAssigner> originAssingeeList = runtimeService.getVariable(task.getProcessInstanceId(),
|
List<BpmnTaskDelegateAssigner> originAssingeeList = runtimeService.getVariable(task.getProcessInstanceId(),
|
||||||
INTERNAL_ACTIVITY_RELATION_ASSIGNEE_LIST_INFO_SNAPSHOT + task.getTaskDefinitionKey(), List.class);
|
INTERNAL_ACTIVITY_RELATION_ASSIGNEE_LIST_INFO_SNAPSHOT + task.getTaskDefinitionKey(), List.class);
|
||||||
Optional<BpmnTaskDelegateAssigner> exists = originAssingeeList.stream()
|
Optional<BpmnTaskDelegateAssigner> exists = originAssingeeList.stream()
|
||||||
.filter(i -> Objects.equals(i.buildAssigneeId(), targetTaskAssignee.buildAssigneeId())).findAny();
|
.filter(i -> Objects.equals(i.buildAssigneeId(), targetTaskAssignee.buildAssigneeId())).findAny();
|
||||||
if (exists.isPresent()) {
|
if (exists.isPresent()) {
|
||||||
throw new WorkflowEngineException(ASSIGNEE_HAS_BEEN_EXISTS);
|
throw new WorkflowEngineException(ASSIGNEE_HAS_BEEN_EXISTS);
|
||||||
}
|
}
|
||||||
@ -135,8 +135,8 @@ public class CustomTransferUserTaskCmd extends AbstractCommand<Void> implements
|
|||||||
}
|
}
|
||||||
originAssingeeList.add(targetTaskAssignee);
|
originAssingeeList.add(targetTaskAssignee);
|
||||||
runtimeService.setVariable(task.getProcessInstanceId(),
|
runtimeService.setVariable(task.getProcessInstanceId(),
|
||||||
INTERNAL_ACTIVITY_RELATION_ASSIGNEE_LIST_INFO_SNAPSHOT + task.getTaskDefinitionKey(),
|
INTERNAL_ACTIVITY_RELATION_ASSIGNEE_LIST_INFO_SNAPSHOT + task.getTaskDefinitionKey(),
|
||||||
originAssingeeList);
|
originAssingeeList);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
|||||||
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnHistoricTaskInstanceVO;
|
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnHistoricTaskInstanceVO;
|
||||||
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
||||||
import cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper;
|
import cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper;
|
||||||
|
import cn.axzo.workflow.core.engine.model.AddComment;
|
||||||
import cn.axzo.workflow.core.repository.entity.ExtAxHiTaskInst;
|
import cn.axzo.workflow.core.repository.entity.ExtAxHiTaskInst;
|
||||||
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
|
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
|
||||||
import cn.axzo.workflow.core.service.converter.BpmnHistoricTaskInstanceConverter;
|
import cn.axzo.workflow.core.service.converter.BpmnHistoricTaskInstanceConverter;
|
||||||
@ -27,7 +28,6 @@ import org.flowable.engine.impl.util.CommandContextUtil;
|
|||||||
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
|
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
|
||||||
import org.flowable.engine.runtime.Execution;
|
import org.flowable.engine.runtime.Execution;
|
||||||
import org.flowable.engine.task.Attachment;
|
import org.flowable.engine.task.Attachment;
|
||||||
import org.flowable.engine.task.Comment;
|
|
||||||
import org.flowable.engine.task.Event;
|
import org.flowable.engine.task.Event;
|
||||||
import org.flowable.task.api.Task;
|
import org.flowable.task.api.Task;
|
||||||
import org.flowable.task.api.history.HistoricTaskInstance;
|
import org.flowable.task.api.history.HistoricTaskInstance;
|
||||||
@ -55,6 +55,7 @@ import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_ACTIVITY_R
|
|||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_TASK_RELATION_ASSIGNEE_INFO;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_TASK_RELATION_ASSIGNEE_INFO;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.NO_ASSIGNEE;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.NO_ASSIGNEE;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.OLD_INTERNAL_TASK_RELATION_ASSIGNEE_INFO_SNAPSHOT;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.OLD_INTERNAL_TASK_RELATION_ASSIGNEE_INFO_SNAPSHOT;
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_ATTACHMENTS_VAR_NAME;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_COMPLETE_OPERATION_TYPE;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_COMPLETE_OPERATION_TYPE;
|
||||||
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_EMPTY;
|
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_EMPTY;
|
||||||
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.PROCESSING;
|
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.PROCESSING;
|
||||||
@ -63,6 +64,7 @@ import static cn.axzo.workflow.core.common.code.BpmnTaskRespCode.ASSIGNER_NUMBER
|
|||||||
import static cn.axzo.workflow.core.common.code.BpmnTaskRespCode.TASK_COMPLETE_FAIL_ASSIGN_NOT_SELF;
|
import static cn.axzo.workflow.core.common.code.BpmnTaskRespCode.TASK_COMPLETE_FAIL_ASSIGN_NOT_SELF;
|
||||||
import static cn.axzo.workflow.core.common.code.BpmnTaskRespCode.TASK_COMPLETE_FAIL_NOT_EXISTS;
|
import static cn.axzo.workflow.core.common.code.BpmnTaskRespCode.TASK_COMPLETE_FAIL_NOT_EXISTS;
|
||||||
import static cn.axzo.workflow.core.common.code.BpmnTaskRespCode.TASK_HAS_BEEN_COMPLETE;
|
import static cn.axzo.workflow.core.common.code.BpmnTaskRespCode.TASK_HAS_BEEN_COMPLETE;
|
||||||
|
import static cn.axzo.workflow.core.common.code.BpmnTaskRespCode.TASK_TYPE_MISMATCH;
|
||||||
import static org.flowable.task.api.Task.DEFAULT_PRIORITY;
|
import static org.flowable.task.api.Task.DEFAULT_PRIORITY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -154,7 +156,7 @@ public class CustomTaskHelper {
|
|||||||
//不包含对应的任务
|
//不包含对应的任务
|
||||||
if (!nodeTypes.contains(nodeType)) {
|
if (!nodeTypes.contains(nodeType)) {
|
||||||
// log.warn(TASK_TYPE_MISMATCH.getMessage(), nodeType.getDesc(), nodeTypes.stream().map(BpmnFlowNodeType::getDesc).collect(Collectors.joining(",")));
|
// log.warn(TASK_TYPE_MISMATCH.getMessage(), nodeType.getDesc(), nodeTypes.stream().map(BpmnFlowNodeType::getDesc).collect(Collectors.joining(",")));
|
||||||
throw new WorkflowEngineException(ASSIGNER_NUMBER_EXCEEDS_NUMBER_LIMIT, nodeType.getDesc(), nodeTypes.stream().map(BpmnFlowNodeType::getDesc).collect(Collectors.joining(",")));
|
throw new WorkflowEngineException(TASK_TYPE_MISMATCH, nodeType.getDesc(), nodeTypes.stream().map(BpmnFlowNodeType::getDesc).collect(Collectors.joining(",")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -219,10 +221,10 @@ public class CustomTaskHelper {
|
|||||||
*
|
*
|
||||||
* @param commandContext
|
* @param commandContext
|
||||||
* @param processInstanceId
|
* @param processInstanceId
|
||||||
* @param taskId
|
* @param task
|
||||||
* @param attachmentList
|
* @param attachmentList
|
||||||
*/
|
*/
|
||||||
public static void batchAddAttachment(CommandContext commandContext, String processInstanceId, String taskId,
|
public static void batchAddAttachment(CommandContext commandContext, String processInstanceId, TaskEntity task,
|
||||||
List<AttachmentDTO> attachmentList, BpmnTaskDelegateAssigner assigner) {
|
List<AttachmentDTO> attachmentList, BpmnTaskDelegateAssigner assigner) {
|
||||||
if (CollectionUtils.isEmpty(attachmentList)) {
|
if (CollectionUtils.isEmpty(attachmentList)) {
|
||||||
return;
|
return;
|
||||||
@ -232,22 +234,30 @@ public class CustomTaskHelper {
|
|||||||
TaskService taskService = processEngineConfiguration.getTaskService();
|
TaskService taskService = processEngineConfiguration.getTaskService();
|
||||||
Authentication.setAuthenticatedUserId(assigner.buildAssigneeId());
|
Authentication.setAuthenticatedUserId(assigner.buildAssigneeId());
|
||||||
attachmentList.forEach(dto -> {
|
attachmentList.forEach(dto -> {
|
||||||
Attachment attachment = taskService.createAttachment(dto.getType().getType(), taskId, processInstanceId,
|
Attachment attachment = taskService.createAttachment(dto.getType().getType(), task.getId(), processInstanceId,
|
||||||
dto.getName(), dto.getDescription(), dto.getUrl());
|
dto.getName(), dto.getDescription(), dto.getUrl());
|
||||||
taskService.saveAttachment(attachment);
|
taskService.saveAttachment(attachment);
|
||||||
});
|
});
|
||||||
|
task.setTransientVariableLocal(TASK_ATTACHMENTS_VAR_NAME, attachmentList);
|
||||||
Authentication.setAuthenticatedUserId(null);
|
Authentication.setAuthenticatedUserId(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Comment addComment(CommandContext commandContext, String taskId, String processInstanceId,
|
public static void addComment(CommandContext commandContext, String taskId, String processInstanceId,
|
||||||
String type, String message) {
|
String type, String message) {
|
||||||
TaskEntity task = new TaskEntityImpl();
|
TaskEntity task = new TaskEntityImpl();
|
||||||
task.setId(taskId);
|
task.setId(taskId);
|
||||||
task.setProcessInstanceId(processInstanceId);
|
task.setProcessInstanceId(processInstanceId);
|
||||||
return addComment(commandContext, task, type, message);
|
addComment(commandContext, task, type, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Comment addComment(CommandContext commandContext, Task task, String type, String message) {
|
public static void addComment(CommandContext commandContext, TaskEntity task, AddComment addComment) {
|
||||||
|
addComment(commandContext, task, addComment.getCommentType(), addComment.getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addComment(CommandContext commandContext, TaskEntity task, String type, String message) {
|
||||||
|
if (!StringUtils.hasText(type) || !StringUtils.hasText(message)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
ProcessEngineConfigurationImpl processEngineConfiguration =
|
ProcessEngineConfigurationImpl processEngineConfiguration =
|
||||||
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||||
|
|
||||||
@ -269,8 +279,7 @@ public class CustomTaskHelper {
|
|||||||
comment.setFullMessage(message);
|
comment.setFullMessage(message);
|
||||||
|
|
||||||
processEngineConfiguration.getCommentEntityManager().insert(comment);
|
processEngineConfiguration.getCommentEntityManager().insert(comment);
|
||||||
|
task.setTransientVariableLocal(type, message);
|
||||||
return comment;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Attachment addAttachment(CommandContext commandContext, Task task, AttachmentDTO attachmentDto) {
|
public static Attachment addAttachment(CommandContext commandContext, Task task, AttachmentDTO attachmentDto) {
|
||||||
@ -313,10 +322,10 @@ public class CustomTaskHelper {
|
|||||||
* @param extTaskInstStatus 节点状态
|
* @param extTaskInstStatus 节点状态
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static Task createVirtualTask(CommandContext commandContext, ExtAxHiTaskInstService extAxHiTaskInstService
|
public static TaskEntity createVirtualTask(CommandContext commandContext, ExtAxHiTaskInstService extAxHiTaskInstService
|
||||||
, String processInstanceId, String nodeName, String taskDefinitionKey, String advice,
|
, String processInstanceId, String nodeName, String taskDefinitionKey, String advice,
|
||||||
BpmnTaskDelegateAssigner assigner,
|
BpmnTaskDelegateAssigner assigner,
|
||||||
String extTaskInstStatus) {
|
String extTaskInstStatus, AddComment addComment) {
|
||||||
ProcessEngineConfigurationImpl processEngineConfiguration =
|
ProcessEngineConfigurationImpl processEngineConfiguration =
|
||||||
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||||
HistoryService historyService = processEngineConfiguration.getHistoryService();
|
HistoryService historyService = processEngineConfiguration.getHistoryService();
|
||||||
@ -336,8 +345,6 @@ public class CustomTaskHelper {
|
|||||||
task.setTaskDefinitionKey(taskDefinitionKey);
|
task.setTaskDefinitionKey(taskDefinitionKey);
|
||||||
task.setPriority(DEFAULT_PRIORITY);
|
task.setPriority(DEFAULT_PRIORITY);
|
||||||
task.setCreateTime(new Date());
|
task.setCreateTime(new Date());
|
||||||
// 创建临时节点
|
|
||||||
taskService.saveTask(task);
|
|
||||||
|
|
||||||
if (Objects.nonNull(assigner)) {
|
if (Objects.nonNull(assigner)) {
|
||||||
CommandContextUtil.getEntityCache().findInCache(TaskEntity.class).stream()
|
CommandContextUtil.getEntityCache().findInCache(TaskEntity.class).stream()
|
||||||
@ -351,23 +358,36 @@ public class CustomTaskHelper {
|
|||||||
|
|
||||||
// 添加审批意见
|
// 添加审批意见
|
||||||
addAdvice(commandContext, task, advice, Objects.nonNull(assigner) ? assigner.buildAssigneeId() : null);
|
addAdvice(commandContext, task, advice, Objects.nonNull(assigner) ? assigner.buildAssigneeId() : null);
|
||||||
|
// 添加操作描述
|
||||||
|
addComment(commandContext, task, addComment);
|
||||||
|
|
||||||
CustomTaskHelper.createExtTaskInst(extAxHiTaskInstService, task.getProcessInstanceId(), task.getId(),
|
CustomTaskHelper.createExtTaskInst(extAxHiTaskInstService, task.getProcessInstanceId(), task.getId(),
|
||||||
task.getTaskDefinitionKey(), assigner, extTaskInstStatus);
|
task.getTaskDefinitionKey(), assigner, extTaskInstStatus);
|
||||||
task.setTransientVariable(TASK_COMPLETE_OPERATION_TYPE + task.getId(), extTaskInstStatus);
|
task.setTransientVariable(TASK_COMPLETE_OPERATION_TYPE + task.getId(), extTaskInstStatus);
|
||||||
|
|
||||||
|
// 保存任务
|
||||||
|
taskService.saveTask(task);
|
||||||
|
|
||||||
if (Objects.nonNull(assigner)) {
|
if (Objects.nonNull(assigner)) {
|
||||||
// 设置快照信息
|
// 设置快照信息
|
||||||
task.setVariable(INTERNAL_TASK_RELATION_ASSIGNEE_INFO + task.getId(), assigner.toJson());
|
task.setVariable(INTERNAL_TASK_RELATION_ASSIGNEE_INFO + task.getId(), assigner.toJson());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 完成临时节点
|
// 完成临时节点, 1.4.2虚拟节点创建方法不再默认完成,需主动调用 completeVirtualTask 完成
|
||||||
taskService.complete(task.getId());
|
// taskService.complete(task.getId());
|
||||||
|
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addAdvice(CommandContext commandContext, Task task, String comment, String userId) {
|
public static Task completeVirtualTask(CommandContext commandContext, Task task) {
|
||||||
|
ProcessEngineConfigurationImpl processEngineConfiguration =
|
||||||
|
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||||
|
TaskService taskService = processEngineConfiguration.getTaskService();
|
||||||
|
taskService.complete(task.getId());
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addAdvice(CommandContext commandContext, TaskEntity task, String comment, String userId) {
|
||||||
if (StringUtils.hasLength(comment)) {
|
if (StringUtils.hasLength(comment)) {
|
||||||
Authentication.setAuthenticatedUserId(userId);
|
Authentication.setAuthenticatedUserId(userId);
|
||||||
addComment(commandContext, task, COMMENT_TYPE_ADVICE, comment);
|
addComment(commandContext, task, COMMENT_TYPE_ADVICE, comment);
|
||||||
|
|||||||
@ -10,6 +10,8 @@ import org.flowable.common.engine.impl.interceptor.Command;
|
|||||||
import org.flowable.common.engine.impl.interceptor.CommandConfig;
|
import org.flowable.common.engine.impl.interceptor.CommandConfig;
|
||||||
import org.flowable.common.engine.impl.interceptor.CommandExecutor;
|
import org.flowable.common.engine.impl.interceptor.CommandExecutor;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import static cn.axzo.workflow.core.common.code.FlowableEngineRespCode.ENGINE_ASYNC_COMMAND_EXECUTION_RETRY_GIVE_UP;
|
import static cn.axzo.workflow.core.common.code.FlowableEngineRespCode.ENGINE_ASYNC_COMMAND_EXECUTION_RETRY_GIVE_UP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -29,6 +31,7 @@ public class CustomRetryInterceptor extends AbstractCommandInterceptor {
|
|||||||
public <T> T execute(CommandConfig config, Command<T> command, CommandExecutor commandExecutor) {
|
public <T> T execute(CommandConfig config, Command<T> command, CommandExecutor commandExecutor) {
|
||||||
long waitTime = waitTimeInMs;
|
long waitTime = waitTimeInMs;
|
||||||
int failedAttempts = 0;
|
int failedAttempts = 0;
|
||||||
|
Throwable lastException = null;
|
||||||
do {
|
do {
|
||||||
if (failedAttempts > 0) {
|
if (failedAttempts > 0) {
|
||||||
log.warn("Waiting for {}ms before retrying the command.", waitTime);
|
log.warn("Waiting for {}ms before retrying the command.", waitTime);
|
||||||
@ -38,9 +41,6 @@ public class CustomRetryInterceptor extends AbstractCommandInterceptor {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// try to execute the command
|
// try to execute the command
|
||||||
if (log.isDebugEnabled()) {
|
|
||||||
log.debug("assignableFrom result: {}", AbstractCommand.class.isAssignableFrom(command.getClass()));
|
|
||||||
}
|
|
||||||
if (AbstractCommand.class.isAssignableFrom(command.getClass())) {
|
if (AbstractCommand.class.isAssignableFrom(command.getClass())) {
|
||||||
// 如果在以后,重试三次也不能解决的话, 可以利用这里的拿到的参数,重新自动构造CMD,并执行.
|
// 如果在以后,重试三次也不能解决的话, 可以利用这里的拿到的参数,重新自动构造CMD,并执行.
|
||||||
log.info("Executing command params: {} traceId:{} ", TraceUtil.traceId(),
|
log.info("Executing command params: {} traceId:{} ", TraceUtil.traceId(),
|
||||||
@ -50,12 +50,13 @@ public class CustomRetryInterceptor extends AbstractCommandInterceptor {
|
|||||||
|
|
||||||
} catch (PersistenceException e) {
|
} catch (PersistenceException e) {
|
||||||
log.warn("Caught persistence exception: {}", e.getMessage(), e);
|
log.warn("Caught persistence exception: {}", e.getMessage(), e);
|
||||||
|
lastException = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
failedAttempts++;
|
failedAttempts++;
|
||||||
} while (failedAttempts <= numOfRetries);
|
} while (failedAttempts <= numOfRetries);
|
||||||
|
|
||||||
throw new WorkflowEngineException(ENGINE_ASYNC_COMMAND_EXECUTION_RETRY_GIVE_UP, String.valueOf(numOfRetries));
|
throw new WorkflowEngineException(ENGINE_ASYNC_COMMAND_EXECUTION_RETRY_GIVE_UP, String.valueOf(numOfRetries), lastException.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void waitBeforeRetry(long waitTime) {
|
protected void waitBeforeRetry(long waitTime) {
|
||||||
|
|||||||
@ -13,11 +13,11 @@ import org.flowable.job.service.impl.persistence.entity.JobEntity;
|
|||||||
import org.flowable.variable.api.delegate.VariableScope;
|
import org.flowable.variable.api.delegate.VariableScope;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class AsyncAbortProcessInstanceHandler extends AbstractExecuteWithLockJobHandler implements JobHandler {
|
public class AsyncAbortProcessInstanceJobHandler extends AbstractExecuteWithLockJobHandler implements JobHandler {
|
||||||
public static final String TYPE = "async-abort-instance";
|
public static final String TYPE = "async-abort-instance";
|
||||||
private final ExtAxHiTaskInstService extAxHiTaskInstService;
|
private final ExtAxHiTaskInstService extAxHiTaskInstService;
|
||||||
|
|
||||||
public AsyncAbortProcessInstanceHandler(ExtAxHiTaskInstService extAxHiTaskInstService) {
|
public AsyncAbortProcessInstanceJobHandler(ExtAxHiTaskInstService extAxHiTaskInstService) {
|
||||||
this.extAxHiTaskInstService = extAxHiTaskInstService;
|
this.extAxHiTaskInstService = extAxHiTaskInstService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1,6 +1,7 @@
|
|||||||
package cn.axzo.workflow.core.engine.job;
|
package cn.axzo.workflow.core.engine.job;
|
||||||
|
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.activity.BpmnActivityTimeoutTriggerDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.activity.BpmnActivityTimeoutTriggerDTO;
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivityTriggerDTO;
|
||||||
import cn.axzo.workflow.core.service.BpmnProcessActivityService;
|
import cn.axzo.workflow.core.service.BpmnProcessActivityService;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -33,6 +34,6 @@ public class AsyncActivityLeaveJobHandler extends AbstractJobHandler implements
|
|||||||
public void execute(JobEntity job, String configuration, VariableScope variableScope, CommandContext commandContext) {
|
public void execute(JobEntity job, String configuration, VariableScope variableScope, CommandContext commandContext) {
|
||||||
log.warn("AsyncActivityLeaveJobHandler exec start...");
|
log.warn("AsyncActivityLeaveJobHandler exec start...");
|
||||||
BpmnActivityTimeoutTriggerDTO dto = JSON.parseObject(job.getCustomValues(), BpmnActivityTimeoutTriggerDTO.class);
|
BpmnActivityTimeoutTriggerDTO dto = JSON.parseObject(job.getCustomValues(), BpmnActivityTimeoutTriggerDTO.class);
|
||||||
bpmnProcessActivityService.trigger(dto.getTriggerId());
|
bpmnProcessActivityService.trigger(BpmnActivityTriggerDTO.builder().async(false).triggerId(dto.getTriggerId()).build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,37 @@
|
|||||||
|
package cn.axzo.workflow.core.engine.job;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivitySetAssigneeDTO;
|
||||||
|
import cn.axzo.workflow.core.engine.cmd.CustomBizSpecifyAssigneeToTaskCmd;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步处理业务节点设置审批人的处理器
|
||||||
|
*
|
||||||
|
* @author wangli
|
||||||
|
* @since 2024-09-09 14:54
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class AsyncActivitySetAssigneeJobHandler extends AbstractJobHandler implements JobHandler {
|
||||||
|
public static String TYPE = "async-activity-set-assignee";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(JobEntity job, String configuration, VariableScope variableScope, CommandContext commandContext) {
|
||||||
|
log.info("AsyncActivitySetAssigneeJobHandler executing...");
|
||||||
|
ProcessEngineConfigurationImpl processEngineConfiguration =
|
||||||
|
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||||
|
BpmnActivitySetAssigneeDTO dto = JSONUtil.toBean(job.getCustomValues(), BpmnActivitySetAssigneeDTO.class);
|
||||||
|
processEngineConfiguration.getCommandExecutor().execute(new CustomBizSpecifyAssigneeToTaskCmd(dto.getTriggerId(), dto.getAssigners()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
package cn.axzo.workflow.core.engine.job;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivityTriggerDTO;
|
||||||
|
import cn.axzo.workflow.core.engine.cmd.CustomActivityTriggerCmd;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步处理业务节点触发的处理器
|
||||||
|
*
|
||||||
|
* @author wangli
|
||||||
|
* @since 2024-09-09 14:36
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class AsyncActivityTriggerJobHandler extends AbstractJobHandler implements JobHandler {
|
||||||
|
public static final String TYPE = "async-activity-trigger";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(JobEntity job, String configuration, VariableScope variableScope, CommandContext commandContext) {
|
||||||
|
log.info("AsyncActivityTriggerJobHandler executing...");
|
||||||
|
ProcessEngineConfigurationImpl processEngineConfiguration =
|
||||||
|
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||||
|
BpmnActivityTriggerDTO dto = JSONUtil.toBean(job.getCustomValues(), BpmnActivityTriggerDTO.class);
|
||||||
|
processEngineConfiguration.getCommandExecutor().execute(new CustomActivityTriggerCmd(dto));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
package cn.axzo.workflow.core.engine.job;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskBackAuditDTO;
|
||||||
|
import cn.axzo.workflow.core.engine.cmd.CustomBackTaskCmd;
|
||||||
|
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.task.api.Task;
|
||||||
|
import org.flowable.variable.api.delegate.VariableScope;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class AsyncBackTaskJobHandler extends AbstractExecuteWithLockJobHandler implements JobHandler {
|
||||||
|
|
||||||
|
public static final String TYPE = "async-back-task";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void executeInternal(JobEntity job, String configuration, VariableScope variableScope, CommandContext commandContext) {
|
||||||
|
log.info("AsyncBackTaskJobHandler executing...");
|
||||||
|
log(job);
|
||||||
|
ProcessEngineConfigurationImpl processEngineConfiguration =
|
||||||
|
CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||||
|
BpmnTaskBackAuditDTO dto = JSONUtil.toBean(job.getCustomValues(), BpmnTaskBackAuditDTO.class);
|
||||||
|
Task task = processEngineConfiguration.getTaskService().createTaskQuery().taskId(dto.getTaskId()).singleResult();
|
||||||
|
if (Objects.isNull(task)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
processEngineConfiguration.getCommandExecutor().execute(new CustomBackTaskCmd(dto));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,31 +0,0 @@
|
|||||||
package cn.axzo.workflow.core.engine.job;
|
|
||||||
|
|
||||||
import cn.axzo.workflow.core.service.BpmnProcessActivityService;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
|
||||||
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 AsyncBpmnProcessActivityJobHandler extends AbstractJobHandler implements JobHandler {
|
|
||||||
|
|
||||||
public static final String TYPE = "async-bpmn-process-activity";
|
|
||||||
|
|
||||||
private final BpmnProcessActivityService activityService;
|
|
||||||
|
|
||||||
public AsyncBpmnProcessActivityJobHandler(BpmnProcessActivityService activityService) {
|
|
||||||
this.activityService = activityService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getType() {
|
|
||||||
return TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(JobEntity job, String configuration, VariableScope variableScope, CommandContext commandContext) {
|
|
||||||
log(job);
|
|
||||||
activityService.executeAsyncJob(job);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -13,13 +13,13 @@ import org.flowable.job.service.impl.persistence.entity.JobEntity;
|
|||||||
import org.flowable.variable.api.delegate.VariableScope;
|
import org.flowable.variable.api.delegate.VariableScope;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class AsyncCancelProcessInstanceHandler extends AbstractJobHandler implements JobHandler {
|
public class AsyncCancelProcessInstanceJobHandler extends AbstractJobHandler implements JobHandler {
|
||||||
|
|
||||||
public static final String TYPE = "async-cancel-process";
|
public static final String TYPE = "async-cancel-process";
|
||||||
|
|
||||||
private final ExtAxHiTaskInstService extAxHiTaskInstService;
|
private final ExtAxHiTaskInstService extAxHiTaskInstService;
|
||||||
|
|
||||||
public AsyncCancelProcessInstanceHandler(ExtAxHiTaskInstService extAxHiTaskInstService) {
|
public AsyncCancelProcessInstanceJobHandler(ExtAxHiTaskInstService extAxHiTaskInstService) {
|
||||||
this.extAxHiTaskInstService = extAxHiTaskInstService;
|
this.extAxHiTaskInstService = extAxHiTaskInstService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -0,0 +1,77 @@
|
|||||||
|
package cn.axzo.workflow.core.engine.job;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.common.model.dto.AlterDTO;
|
||||||
|
import cn.axzo.workflow.common.model.dto.TermNodePausingDTO;
|
||||||
|
import cn.axzo.workflow.core.common.utils.SpringContextUtils;
|
||||||
|
import cn.axzo.workflow.core.conf.SupportRefreshProperties;
|
||||||
|
import cn.axzo.workflow.core.listener.Alter;
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||||
|
import org.flowable.engine.RuntimeService;
|
||||||
|
import org.flowable.engine.TaskService;
|
||||||
|
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.task.api.Task;
|
||||||
|
import org.flowable.variable.api.delegate.VariableScope;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.BIZ_NODE_ALTER;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查指定节点是否长时间卡住,如果卡住则进行钉钉告警
|
||||||
|
*
|
||||||
|
* @author wangli
|
||||||
|
* @since 2024-09-11 13:50
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class AsyncTermNodeAlterJobHandler extends AbstractJobHandler implements JobHandler {
|
||||||
|
public static final String TYPE = "term-node-alter-cycle";
|
||||||
|
private final SupportRefreshProperties refreshProperties;
|
||||||
|
|
||||||
|
public AsyncTermNodeAlterJobHandler(SupportRefreshProperties refreshProperties) {
|
||||||
|
this.refreshProperties = refreshProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(JobEntity job, String configuration, VariableScope variableScope, CommandContext commandContext) {
|
||||||
|
log.warn("AsyncActivityLeaveJobHandler exec start...");
|
||||||
|
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
|
||||||
|
JSONObject jsonObject = JSON.parseObject(job.getJobHandlerConfiguration());
|
||||||
|
if (!jsonObject.containsKey("activityId")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String activityId = jsonObject.getString("activityId");
|
||||||
|
RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
|
||||||
|
TermNodePausingDTO dto = runtimeService.getVariable(job.getProcessInstanceId(), BIZ_NODE_ALTER + activityId, TermNodePausingDTO.class);
|
||||||
|
TaskService taskService = processEngineConfiguration.getTaskService();
|
||||||
|
Task task = taskService.createTaskQuery()
|
||||||
|
.processInstanceId(dto.getProcessInstanceId())
|
||||||
|
.taskDefinitionKey(dto.getActivityId())
|
||||||
|
.singleResult();
|
||||||
|
if (Objects.isNull(task)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (DateUtil.compare(DateUtil.date(), DateUtil.offsetMinute(task.getCreateTime(), refreshProperties.getPauseDelay())) > 0) {
|
||||||
|
// 发送告警对象
|
||||||
|
Alter alter = SpringContextUtils.getBean(Alter.class);
|
||||||
|
AlterDTO alterDTO = new AlterDTO();
|
||||||
|
alterDTO.setProcessInstanceId(dto.getProcessInstanceId());
|
||||||
|
alterDTO.setActivityId(dto.getActivityId());
|
||||||
|
alterDTO.setTaskId(task.getId());
|
||||||
|
alterDTO.setStartTime(task.getCreateTime());
|
||||||
|
alterDTO.setPrettyStartTime(DateUtil.formatDateTime(task.getCreateTime()));
|
||||||
|
alter.invoke(alterDTO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,12 +4,18 @@ import cn.axzo.workflow.common.constant.BpmnConstants;
|
|||||||
import cn.axzo.workflow.common.enums.ApproverEmptyHandleTypeEnum;
|
import cn.axzo.workflow.common.enums.ApproverEmptyHandleTypeEnum;
|
||||||
import cn.axzo.workflow.common.enums.ApproverSpecifyEnum;
|
import cn.axzo.workflow.common.enums.ApproverSpecifyEnum;
|
||||||
import cn.axzo.workflow.common.enums.BpmnFlowNodeType;
|
import cn.axzo.workflow.common.enums.BpmnFlowNodeType;
|
||||||
|
import cn.axzo.workflow.common.model.dto.CooperationOrgDTO;
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceAbortDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||||
import cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper;
|
import cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper;
|
||||||
|
import cn.axzo.workflow.core.conf.SupportRefreshProperties;
|
||||||
import cn.axzo.workflow.core.deletage.BpmnTaskAssigneeSelector;
|
import cn.axzo.workflow.core.deletage.BpmnTaskAssigneeSelector;
|
||||||
import cn.axzo.workflow.core.deletage.BpmnTaskCalculateDTO;
|
import cn.axzo.workflow.core.deletage.BpmnTaskCalculateDTO;
|
||||||
import cn.axzo.workflow.core.deletage.BpmnTaskDelegate;
|
import cn.axzo.workflow.core.deletage.BpmnTaskDelegate;
|
||||||
import cn.axzo.workflow.core.deletage.MockTaskAssigneeSelector;
|
import cn.axzo.workflow.core.deletage.MockTaskAssigneeSelector;
|
||||||
|
import cn.axzo.workflow.core.engine.cmd.CustomAbortProcessInstanceAsyncCmd;
|
||||||
|
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
|
||||||
|
import cn.axzo.workflow.core.util.DingTalkUtils;
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
@ -20,6 +26,7 @@ import org.flowable.bpmn.model.Process;
|
|||||||
import org.flowable.bpmn.model.UserTask;
|
import org.flowable.bpmn.model.UserTask;
|
||||||
import org.flowable.engine.delegate.DelegateExecution;
|
import org.flowable.engine.delegate.DelegateExecution;
|
||||||
import org.flowable.engine.delegate.ExecutionListener;
|
import org.flowable.engine.delegate.ExecutionListener;
|
||||||
|
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||||
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
|
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
|
||||||
import org.springframework.beans.factory.ObjectProvider;
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
@ -38,6 +45,7 @@ import java.util.Objects;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.APPROVAL_ASSIGNER_LIMIT_NUMBER;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.APPROVAL_ASSIGNER_LIMIT_NUMBER;
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.BIZ_ORG_RELATION;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.BPM_ALLOW_SKIP_USER_TASK;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.BPM_ALLOW_SKIP_USER_TASK;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.DUMMY_ASSIGNEE;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.DUMMY_ASSIGNEE;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.DUMMY_ASSIGNEE_TYPE;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.DUMMY_ASSIGNEE_TYPE;
|
||||||
@ -68,22 +76,17 @@ import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.removeDup
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class EngineExecutionStartListener implements ExecutionListener {
|
public class EngineExecutionStartListener implements ExecutionListener {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
@Value("${spring.profiles.active}")
|
||||||
|
private String profile;
|
||||||
@Resource
|
@Resource
|
||||||
@Deprecated
|
@Deprecated
|
||||||
private ObjectProvider<BpmnTaskDelegate> bpmTaskDelegate;
|
private ObjectProvider<BpmnTaskDelegate> bpmTaskDelegate;
|
||||||
@Resource
|
@Resource
|
||||||
@Lazy
|
@Lazy
|
||||||
private List<BpmnTaskAssigneeSelector> selectors;
|
private List<BpmnTaskAssigneeSelector> selectors;
|
||||||
@Value("${workflow.api.timeout:10}")
|
@Resource
|
||||||
private Long apiTimeout;
|
private SupportRefreshProperties refreshProperties;
|
||||||
@Value("${workflow.mock:false}")
|
|
||||||
private Boolean mock;
|
|
||||||
@Value("${workflow.assignee.global:true}")
|
|
||||||
private Boolean global;
|
|
||||||
@Value("${workflow.assignee.category:''}")
|
|
||||||
private String category;
|
|
||||||
@Value("#{${workflow.assignee.map:{}}}")
|
|
||||||
private Map<String, String> assigneeMap;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notify(DelegateExecution execution) {
|
public void notify(DelegateExecution execution) {
|
||||||
@ -180,6 +183,7 @@ public class EngineExecutionStartListener implements ExecutionListener {
|
|||||||
}
|
}
|
||||||
log.info("当前节点id: [{}], name: [{}] 审批人为空, 将执行审批人为空的兜底配置!", userTask.getId(), userTask.getName());
|
log.info("当前节点id: [{}], name: [{}] 审批人为空, 将执行审批人为空的兜底配置!", userTask.getId(), userTask.getName());
|
||||||
getApproverEmptyHandleType(userTask).ifPresent(type -> {
|
getApproverEmptyHandleType(userTask).ifPresent(type -> {
|
||||||
|
log.info("节点兜底的配置模式:[{}]", type.getType());
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case autoPassed:
|
case autoPassed:
|
||||||
case autoRejection:
|
case autoRejection:
|
||||||
@ -189,19 +193,32 @@ public class EngineExecutionStartListener implements ExecutionListener {
|
|||||||
case transferToAdmin:
|
case transferToAdmin:
|
||||||
assigners.addAll(approverSelect(ApproverEmptyHandleTypeEnum.transferToAdmin.getType(), userTask,
|
assigners.addAll(approverSelect(ApproverEmptyHandleTypeEnum.transferToAdmin.getType(), userTask,
|
||||||
execution, true));
|
execution, true));
|
||||||
|
finalEmptyAssigneeHandle(assigners, userTask, execution, "转交管理员失败,系统中止");
|
||||||
break;
|
break;
|
||||||
case specifyAssignee:
|
case specifyAssignee:
|
||||||
List<BpmnTaskDelegateAssigner> emptyAssignees =
|
assigners.addAll(approverSelect(ApproverEmptyHandleTypeEnum.specifyAssignee.getType(), userTask,
|
||||||
BpmnMetaParserHelper.getEmptyApproverSpecify(userTask)
|
execution, true));
|
||||||
.map(listStr -> JSON.parseArray(listStr, BpmnTaskDelegateAssigner.class))
|
finalEmptyAssigneeHandle(assigners, userTask, execution, "转交指定人员失败,系统自动中止");
|
||||||
.orElse(Collections.emptyList());
|
|
||||||
assigners.addAll(emptyAssignees);
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void finalEmptyAssigneeHandle(List<BpmnTaskDelegateAssigner> assigners, UserTask userTask, DelegateExecution execution, String operationDesc) {
|
||||||
|
if (CollectionUtils.isEmpty(assigners)) {
|
||||||
|
CooperationOrgDTO orgScopes = execution.getVariable(BIZ_ORG_RELATION, CooperationOrgDTO.class);
|
||||||
|
DingTalkUtils.sendDingTalkForTransferToAdminError(profile, execution.getProcessInstanceId(), userTask.getId(), orgScopes);
|
||||||
|
BpmnProcessInstanceAbortDTO abortDTO = new BpmnProcessInstanceAbortDTO();
|
||||||
|
abortDTO.setProcessInstanceId(execution.getProcessInstanceId());
|
||||||
|
abortDTO.setReason("转交管理员失败,系统中止");
|
||||||
|
CommandContextUtil.getProcessEngineConfiguration().getCommandExecutor()
|
||||||
|
.execute(new CustomAbortProcessInstanceAsyncCmd(abortDTO));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据审批人指定类型查询审批人
|
* 根据审批人指定类型查询审批人
|
||||||
*
|
*
|
||||||
@ -235,6 +252,10 @@ public class EngineExecutionStartListener implements ExecutionListener {
|
|||||||
* \"personId\":\"89508\",\"assignee\":\"2000560\",\"assigneeType\":\"3\"}]'
|
* \"personId\":\"89508\",\"assignee\":\"2000560\",\"assigneeType\":\"3\"}]'
|
||||||
* }"
|
* }"
|
||||||
*/
|
*/
|
||||||
|
Boolean mock = refreshProperties.getMock();
|
||||||
|
Boolean global = refreshProperties.getGlobal();
|
||||||
|
String category = refreshProperties.getCategory();
|
||||||
|
Map<String, String> assigneeMap = refreshProperties.getAssigneeMap();
|
||||||
if ((mock && global) ||
|
if ((mock && global) ||
|
||||||
(mock && !global && Objects.equals(category, execution.getProcessDefinitionId().split(":")[0]))) {
|
(mock && !global && Objects.equals(category, execution.getProcessDefinitionId().split(":")[0]))) {
|
||||||
log.info("当前系统 Nacos 配置中开启了 mock: {}, 将使用 mock 方式查找审批人", mock);
|
log.info("当前系统 Nacos 配置中开启了 mock: {}, 将使用 mock 方式查找审批人", mock);
|
||||||
@ -308,7 +329,4 @@ public class EngineExecutionStartListener implements ExecutionListener {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getApiTimeout() {
|
|
||||||
return apiTimeout;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,115 @@
|
|||||||
|
package cn.axzo.workflow.core.engine.listener.entity;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.flowable.common.engine.api.delegate.event.AbstractFlowableEventListener;
|
||||||
|
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
|
||||||
|
import org.flowable.common.engine.api.delegate.event.FlowableEntityEvent;
|
||||||
|
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static org.flowable.common.engine.api.delegate.event.FlowableEngineEventType.ENTITY_ACTIVATED;
|
||||||
|
import static org.flowable.common.engine.api.delegate.event.FlowableEngineEventType.ENTITY_CREATED;
|
||||||
|
import static org.flowable.common.engine.api.delegate.event.FlowableEngineEventType.ENTITY_DELETED;
|
||||||
|
import static org.flowable.common.engine.api.delegate.event.FlowableEngineEventType.ENTITY_INITIALIZED;
|
||||||
|
import static org.flowable.common.engine.api.delegate.event.FlowableEngineEventType.ENTITY_SUSPENDED;
|
||||||
|
import static org.flowable.common.engine.api.delegate.event.FlowableEngineEventType.ENTITY_UPDATED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* @author wangli
|
||||||
|
* @since 2024-09-02 15:34
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class EngineEntityEventListener extends AbstractFlowableEventListener {
|
||||||
|
|
||||||
|
private final List<EntityEventHandle> handles;
|
||||||
|
public static final Set<FlowableEngineEventType> SUPPORTED =
|
||||||
|
ImmutableSet.<FlowableEngineEventType>builder()
|
||||||
|
.add(ENTITY_CREATED)
|
||||||
|
.add(ENTITY_INITIALIZED)
|
||||||
|
.add(ENTITY_UPDATED)
|
||||||
|
.add(ENTITY_DELETED)
|
||||||
|
.add(ENTITY_SUSPENDED)
|
||||||
|
.add(ENTITY_ACTIVATED)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEvent(FlowableEvent event) {
|
||||||
|
if (event instanceof FlowableEntityEvent && SUPPORTED.contains(event.getType())) {
|
||||||
|
FlowableEntityEvent entityEvent = (FlowableEntityEvent) event;
|
||||||
|
// log.warn("entity event type: {}, class: {}",entityEvent.getType(), entityEvent.getEntity().getClass());
|
||||||
|
handles.forEach(handle -> {
|
||||||
|
Object entity = entityEvent.getEntity();
|
||||||
|
if (handle.support(entity)) {
|
||||||
|
Object convert = handle.convert(entity);
|
||||||
|
if (Objects.equals(event.getType(), ENTITY_CREATED)) {
|
||||||
|
handle.onCreate(convert);
|
||||||
|
} else if (Objects.equals(event.getType(), ENTITY_INITIALIZED)) {
|
||||||
|
handle.onInitialized(convert);
|
||||||
|
} else if (Objects.equals(event.getType(), ENTITY_UPDATED)) {
|
||||||
|
handle.onUpdated(convert);
|
||||||
|
} else if (Objects.equals(event.getType(), ENTITY_DELETED)) {
|
||||||
|
handle.onDeleted(convert);
|
||||||
|
} else if (Objects.equals(event.getType(), ENTITY_SUSPENDED)) {
|
||||||
|
handle.onSuspended(convert);
|
||||||
|
} else if (Objects.equals(event.getType(), ENTITY_ACTIVATED)) {
|
||||||
|
handle.onActivated(convert);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// if (entityEvent.getEntity() instanceof TaskEntity) {
|
||||||
|
// TaskEntity taskEntity = (TaskEntity) entityEvent.getEntity();
|
||||||
|
// log.error("event taskId :{}, taskDefKey: {}", taskEntity.getId(), taskEntity.getTaskDefinitionKey());
|
||||||
|
//
|
||||||
|
// if (Objects.equals(event.getType(), ENTITY_CREATED)) {
|
||||||
|
// onCreate(taskEntity);
|
||||||
|
// } else if (Objects.equals(event.getType(), ENTITY_INITIALIZED)) {
|
||||||
|
// onInitialized(taskEntity);
|
||||||
|
// } else if (Objects.equals(event.getType(), ENTITY_UPDATED)) {
|
||||||
|
// onUpdated(taskEntity);
|
||||||
|
// } else if (Objects.equals(event.getType(), ENTITY_DELETED)) {
|
||||||
|
// onDeleted(taskEntity);
|
||||||
|
// } else if (Objects.equals(event.getType(), ENTITY_SUSPENDED)) {
|
||||||
|
// onSuspended(taskEntity);
|
||||||
|
// } else if (Objects.equals(event.getType(), ENTITY_ACTIVATED)) {
|
||||||
|
// onActivated(taskEntity);
|
||||||
|
// }
|
||||||
|
// } else if(entityEvent.getEntity() instanceof CommentEntity) {
|
||||||
|
// CommentEntity commentEntity = (CommentEntity) entityEvent.getEntity();
|
||||||
|
// log.error("event taskId :{}", commentEntity.getId());
|
||||||
|
//
|
||||||
|
// if (Objects.equals(event.getType(), ENTITY_CREATED)) {
|
||||||
|
// onCreate(commentEntity);
|
||||||
|
// } else if (Objects.equals(event.getType(), ENTITY_INITIALIZED)) {
|
||||||
|
// onInitialized(commentEntity);
|
||||||
|
// } else if (Objects.equals(event.getType(), ENTITY_UPDATED)) {
|
||||||
|
// onUpdated(commentEntity);
|
||||||
|
// } else if (Objects.equals(event.getType(), ENTITY_DELETED)) {
|
||||||
|
// onDeleted(commentEntity);
|
||||||
|
// } else if (Objects.equals(event.getType(), ENTITY_SUSPENDED)) {
|
||||||
|
// onSuspended(commentEntity);
|
||||||
|
// } else if (Objects.equals(event.getType(), ENTITY_ACTIVATED)) {
|
||||||
|
// onActivated(commentEntity);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFailOnException() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
package cn.axzo.workflow.core.engine.listener.entity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* @author wangli
|
||||||
|
* @since 2024-09-06 00:03
|
||||||
|
*/
|
||||||
|
public interface EntityEventHandle<T> {
|
||||||
|
|
||||||
|
boolean support(Object entity);
|
||||||
|
|
||||||
|
T convert(Object entity);
|
||||||
|
|
||||||
|
void onCreate(T entity);
|
||||||
|
|
||||||
|
void onInitialized(T entity);
|
||||||
|
|
||||||
|
void onUpdated(T entity);
|
||||||
|
|
||||||
|
void onDeleted(T entity);
|
||||||
|
|
||||||
|
void onSuspended(T entity);
|
||||||
|
|
||||||
|
void onActivated(T entity);
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,81 @@
|
|||||||
|
package cn.axzo.workflow.core.engine.listener.entity.type;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.core.engine.listener.entity.EntityEventHandle;
|
||||||
|
import cn.axzo.workflow.core.repository.entity.ExtAxProcessLog;
|
||||||
|
import cn.axzo.workflow.core.service.ExtAxProcessLogService;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.flowable.engine.impl.persistence.entity.CommentEntity;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.COMMENT_TYPE_ADVICE;
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.COMMENT_TYPE_OPERATION_DESC;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* @author wangli
|
||||||
|
* @since 2024-09-06 00:14
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
//@Component
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class CommentEntityEventHandle implements EntityEventHandle<CommentEntity> {
|
||||||
|
private final ExtAxProcessLogService processLogService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean support(Object entity) {
|
||||||
|
return entity instanceof CommentEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommentEntity convert(Object entity) {
|
||||||
|
return (CommentEntity) entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(CommentEntity entity) {
|
||||||
|
log.info("comment event onCreate: {}", entity.getId());
|
||||||
|
ExtAxProcessLog queryLog = new ExtAxProcessLog();
|
||||||
|
queryLog.setProcessInstanceId(entity.getProcessInstanceId());
|
||||||
|
queryLog.setTaskId(entity.getId());
|
||||||
|
ExtAxProcessLog update = new ExtAxProcessLog();
|
||||||
|
if (Objects.equals(COMMENT_TYPE_ADVICE, entity.getType())) {
|
||||||
|
update.setAdvice(entity.getFullMessage());
|
||||||
|
} else if (Objects.equals(COMMENT_TYPE_OPERATION_DESC, entity.getType())) {
|
||||||
|
update.setOperationDesc(entity.getFullMessage());
|
||||||
|
}
|
||||||
|
processLogService.update(queryLog, update);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInitialized(CommentEntity entity) {
|
||||||
|
log.info("comment event onInitialized: {}", entity.getId());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpdated(CommentEntity entity) {
|
||||||
|
log.info("comment event onUpdated: {}", entity.getId());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDeleted(CommentEntity entity) {
|
||||||
|
log.info("comment event onDeleted: {}", entity.getId());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuspended(CommentEntity entity) {
|
||||||
|
log.info("comment event onSuspended: {}", entity.getId());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivated(CommentEntity entity) {
|
||||||
|
log.info("comment event onSuspended: {}", entity.getId());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,241 @@
|
|||||||
|
package cn.axzo.workflow.core.engine.listener.entity.type;
|
||||||
|
|
||||||
|
import cn.axzo.framework.jackson.utility.JSON;
|
||||||
|
import cn.axzo.workflow.common.enums.BpmnFlowNodeMode;
|
||||||
|
import cn.axzo.workflow.common.enums.BpmnFlowNodeType;
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||||
|
import cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper;
|
||||||
|
import cn.axzo.workflow.core.engine.listener.entity.EntityEventHandle;
|
||||||
|
import cn.axzo.workflow.core.repository.entity.ExtAxProcessLog;
|
||||||
|
import cn.axzo.workflow.core.service.ExtAxProcessLogService;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.collections4.ListUtils;
|
||||||
|
import org.flowable.bpmn.model.BpmnModel;
|
||||||
|
import org.flowable.bpmn.model.FlowElement;
|
||||||
|
import org.flowable.bpmn.model.UserTask;
|
||||||
|
import org.flowable.engine.RepositoryService;
|
||||||
|
import org.flowable.engine.RuntimeService;
|
||||||
|
import org.flowable.engine.impl.bpmn.behavior.MultiInstanceActivityBehavior;
|
||||||
|
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
|
||||||
|
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||||
|
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
|
||||||
|
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.AND_SIGN_EXPRESSION;
|
||||||
|
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.HIDDEN_ASSIGNEE_ID;
|
||||||
|
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_INFO;
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.NO_ASSIGNEE;
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_COMPLETE_OPERATION_TYPE;
|
||||||
|
import static cn.axzo.workflow.common.enums.ApprovalMethodEnum.nobody;
|
||||||
|
import static cn.axzo.workflow.common.enums.BpmnFlowNodeMode.AND;
|
||||||
|
import static cn.axzo.workflow.common.enums.BpmnFlowNodeMode.GENERAL;
|
||||||
|
import static cn.axzo.workflow.common.enums.BpmnFlowNodeMode.OR;
|
||||||
|
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_STARTER;
|
||||||
|
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.APPROVED;
|
||||||
|
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.DELETED;
|
||||||
|
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.PROCESSING;
|
||||||
|
import static cn.axzo.workflow.core.common.enums.BpmnProcessTaskResultEnum.PENDING;
|
||||||
|
import static cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper.getApprovalMethod;
|
||||||
|
import static cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper.getNodeType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同意、评论、加签、转交、驳回、撤回、中止、抄送
|
||||||
|
* <p>
|
||||||
|
* 回退
|
||||||
|
*
|
||||||
|
* @author wangli
|
||||||
|
* @since 2024-09-06 00:02
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class TaskEntityEventHandle implements EntityEventHandle<TaskEntity> {
|
||||||
|
private final ExtAxProcessLogService processLogService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean support(Object entity) {
|
||||||
|
return entity instanceof TaskEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TaskEntity convert(Object entity) {
|
||||||
|
return (TaskEntity) entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivated(TaskEntity taskEntity) {
|
||||||
|
log.debug("onActivated");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onSuspended(TaskEntity taskEntity) {
|
||||||
|
log.debug("onSuspended");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onDeleted(TaskEntity taskEntity) {
|
||||||
|
log.debug("onDeleted");
|
||||||
|
ExtAxProcessLog queryLog = new ExtAxProcessLog();
|
||||||
|
queryLog.setProcessInstanceId(taskEntity.getProcessInstanceId());
|
||||||
|
queryLog.setTaskId(taskEntity.getId());
|
||||||
|
queryLog.setOperationDesc(PENDING.getDesc());
|
||||||
|
ExtAxProcessLog update = new ExtAxProcessLog();
|
||||||
|
|
||||||
|
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();
|
||||||
|
RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
|
||||||
|
BpmnTaskDelegateAssigner assignee = BpmnTaskDelegateAssigner.toObjectCompatible(taskEntity.getVariable(INTERNAL_TASK_RELATION_ASSIGNEE_INFO + taskEntity.getId()));
|
||||||
|
if (Objects.nonNull(assignee) && !Objects.equals(NO_ASSIGNEE, assignee.buildAssigneeId())) {
|
||||||
|
update.setAssigneeFull(Lists.newArrayList(assignee));
|
||||||
|
update.setAssigneeId(Long.valueOf(assignee.getPersonId()));
|
||||||
|
update.setAssigneeTenantId(assignee.getTenantId());
|
||||||
|
update.setAssigneeName(assignee.getAssignerName());
|
||||||
|
update.setAssigneeOuId(assignee.getOuId());
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean needDelete = false;
|
||||||
|
if (Objects.equals(taskEntity.getTaskDefinitionKey(), NODE_STARTER.getType())) {
|
||||||
|
update.setStatus(APPROVED.getStatus());
|
||||||
|
} else {
|
||||||
|
|
||||||
|
Object advice = taskEntity.getTransientVariableLocal(COMMENT_TYPE_ADVICE);
|
||||||
|
if (Objects.nonNull(advice) && StringUtils.hasText(advice.toString())) {
|
||||||
|
log.info("COMMENT_TYPE_ADVICE: {}", advice);
|
||||||
|
update.setAdvice(advice.toString());
|
||||||
|
}
|
||||||
|
Object operationDesc = taskEntity.getTransientVariableLocal(COMMENT_TYPE_OPERATION_DESC);
|
||||||
|
if (Objects.nonNull(operationDesc) && StringUtils.hasText(operationDesc.toString())) {
|
||||||
|
log.info("COMMENT_TYPE_OPERATION_DESC: {}", operationDesc);
|
||||||
|
update.setOperationDesc(Objects.nonNull(assignee) ? assignee.getAssignerName() + operationDesc : operationDesc.toString());
|
||||||
|
} else {
|
||||||
|
update.setOperationDesc(Objects.nonNull(assignee) ? assignee.getAssignerName() : "");
|
||||||
|
// 评论节点会给 operationDesc 赋 COMMENTED 的值,所以注释
|
||||||
|
// update.setOperationDesc(BpmnProcessInstanceResultEnum.valueOfStatus(completionType).getDesc());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String completionType = taskEntity.getVariable(TASK_COMPLETE_OPERATION_TYPE + taskEntity.getId(), String.class);
|
||||||
|
if (StringUtils.hasText(completionType) && !Objects.equals(DELETED.getStatus(), completionType)) {
|
||||||
|
log.info("TASK_COMPLETE_OPERATION_TYPE: {}", completionType);
|
||||||
|
update.setStatus(completionType);
|
||||||
|
} else {
|
||||||
|
// 多实例除操作人以外的任务,直接删除日志, 例如一个节点有两个人或签,A 人驳回了,那么 B 人不再需要操作,任务自动删除。而会签也同理
|
||||||
|
update.setStatus(DELETED.getStatus());// delete标志着是多实例删除
|
||||||
|
needDelete = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update.setEndTime(new Date());
|
||||||
|
|
||||||
|
// 判断是否抄送节点,如果是的话,需要将抄送人集合放入对应字段
|
||||||
|
if (isCarbonCopyNode(queryLog)) {
|
||||||
|
// 抄送人集合
|
||||||
|
List<BpmnTaskDelegateAssigner> carbonCopies = runtimeService.getVariable(taskEntity.getProcessInstanceId(), INTERNAL_ACTIVITY_RELATION_ASSIGNEE_LIST_INFO_SNAPSHOT + taskEntity.getTaskDefinitionKey(), List.class);
|
||||||
|
update.setAssigneeFull(carbonCopies);
|
||||||
|
update.setOperationDesc("抄送" + carbonCopies.size() + "人");
|
||||||
|
}
|
||||||
|
|
||||||
|
processLogService.update(queryLog, update);
|
||||||
|
|
||||||
|
if (needDelete) {
|
||||||
|
// 再逻辑删除该记录
|
||||||
|
ExtAxProcessLog deleteLog = new ExtAxProcessLog();
|
||||||
|
deleteLog.setProcessInstanceId(taskEntity.getProcessInstanceId());
|
||||||
|
deleteLog.setTaskId(taskEntity.getId());
|
||||||
|
processLogService.delete(deleteLog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isCarbonCopyNode(ExtAxProcessLog queryLog) {
|
||||||
|
List<ExtAxProcessLog> logs = processLogService.genericQuery(queryLog);
|
||||||
|
if (CollectionUtils.isEmpty(logs) || logs.size() != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Objects.equals(logs.get(0).getNodeType(), BpmnFlowNodeType.NODE_CARBON_COPY.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onUpdated(TaskEntity taskEntity) {
|
||||||
|
log.debug("onUpdated");
|
||||||
|
if (Objects.equals(HIDDEN_ASSIGNEE_ID, taskEntity.getAssignee())) {
|
||||||
|
ExtAxProcessLog queryLog = new ExtAxProcessLog();
|
||||||
|
queryLog.setProcessInstanceId(taskEntity.getProcessInstanceId());
|
||||||
|
queryLog.setTaskId(taskEntity.getId());
|
||||||
|
processLogService.delete(queryLog);
|
||||||
|
} else {
|
||||||
|
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();
|
||||||
|
RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
|
||||||
|
List<BpmnTaskDelegateAssigner> assigneeList = runtimeService.getVariable(taskEntity.getProcessInstanceId(),
|
||||||
|
INTERNAL_ACTIVITY_RELATION_ASSIGNEE_LIST_INFO_SNAPSHOT + taskEntity.getTaskDefinitionKey(), List.class);
|
||||||
|
ListUtils.emptyIfNull(assigneeList).stream().filter(e -> Objects.equals(e.buildAssigneeId(), taskEntity.getAssignee())).findAny()
|
||||||
|
.ifPresent(assignee -> {
|
||||||
|
log.debug("审批人: {}", JSON.toJSONString(assignee));
|
||||||
|
ExtAxProcessLog queryLog = new ExtAxProcessLog();
|
||||||
|
queryLog.setProcessInstanceId(taskEntity.getProcessInstanceId());
|
||||||
|
queryLog.setTaskId(taskEntity.getId());
|
||||||
|
processLogService.updateAssignee(queryLog, assignee);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onInitialized(TaskEntity taskEntity) {
|
||||||
|
log.debug("onInitialized");
|
||||||
|
BpmnMetaParserHelper.getButtonConfig(ProcessDefinitionUtil.getProcess(taskEntity.getProcessDefinitionId()), taskEntity.getTaskDefinitionKey())
|
||||||
|
.ifPresent(buttons -> {
|
||||||
|
ExtAxProcessLog queryLog = new ExtAxProcessLog();
|
||||||
|
queryLog.setProcessInstanceId(taskEntity.getProcessInstanceId());
|
||||||
|
queryLog.setTaskId(taskEntity.getId());
|
||||||
|
|
||||||
|
ExtAxProcessLog updateLog = new ExtAxProcessLog();
|
||||||
|
updateLog.setButtonConf(buttons);
|
||||||
|
processLogService.update(queryLog, updateLog);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onCreate(TaskEntity taskEntity) {
|
||||||
|
log.debug("onCreate");
|
||||||
|
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();
|
||||||
|
// 记录发起人
|
||||||
|
boolean isNodeStarter = Objects.equals(taskEntity.getTaskDefinitionKey(), NODE_STARTER.getType());
|
||||||
|
|
||||||
|
RepositoryService repositoryService = processEngineConfiguration.getRepositoryService();
|
||||||
|
BpmnModel bpmnModel = repositoryService.getBpmnModel(taskEntity.getProcessDefinitionId());
|
||||||
|
FlowElement flowElement = bpmnModel.getFlowElement(taskEntity.getTaskDefinitionKey());
|
||||||
|
|
||||||
|
ExtAxProcessLog log = new ExtAxProcessLog();
|
||||||
|
log.setProcessInstanceId(taskEntity.getProcessInstanceId());
|
||||||
|
log.setTenantId(taskEntity.getTenantId());
|
||||||
|
log.setActivityId(taskEntity.getTaskDefinitionKey());
|
||||||
|
log.setActivityName(taskEntity.getName());
|
||||||
|
log.setApprovalMethod((isNodeStarter ? nobody : getApprovalMethod(flowElement).orElse(nobody)).getType());
|
||||||
|
log.setNodeType((getNodeType(flowElement).orElse(BpmnFlowNodeType.NODE_EMPTY)).getType());
|
||||||
|
log.setNodeMode((isNodeStarter ? BpmnFlowNodeMode.GENERAL : getNodeMode(flowElement)).getType());
|
||||||
|
log.setTaskId(taskEntity.getId());
|
||||||
|
log.setOperationDesc(PENDING.getDesc());
|
||||||
|
log.setStartTime(taskEntity.getCreateTime());
|
||||||
|
log.setStatus(PROCESSING.getStatus());
|
||||||
|
|
||||||
|
processLogService.insert(log);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BpmnFlowNodeMode getNodeMode(FlowElement flowElement) {
|
||||||
|
BpmnFlowNodeMode node = GENERAL;
|
||||||
|
if (flowElement instanceof UserTask) {
|
||||||
|
UserTask userTask = (UserTask) flowElement;
|
||||||
|
if (userTask.getBehavior() instanceof MultiInstanceActivityBehavior) {
|
||||||
|
MultiInstanceActivityBehavior behavior =
|
||||||
|
(MultiInstanceActivityBehavior) userTask.getBehavior();
|
||||||
|
node = Objects.equals(AND_SIGN_EXPRESSION, behavior.getCompletionCondition()) ? AND : OR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
package cn.axzo.workflow.core.engine.model;
|
||||||
|
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.COMMENT_TYPE_OPERATION_DESC;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 评论模型
|
||||||
|
*
|
||||||
|
* @author wangli
|
||||||
|
* @since 2024-09-05 23:18
|
||||||
|
*/
|
||||||
|
public class AddComment {
|
||||||
|
private String commentType;
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
public AddComment(String commentType, String content) {
|
||||||
|
this.commentType = commentType;
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AddComment(String content) {
|
||||||
|
this.commentType = COMMENT_TYPE_OPERATION_DESC;
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCommentType() {
|
||||||
|
return commentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCommentType(String commentType) {
|
||||||
|
this.commentType = commentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContent(String content) {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
package cn.axzo.workflow.core.engine.operation;
|
package cn.axzo.workflow.core.engine.operation;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum;
|
||||||
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
|
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
|
||||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||||
import org.flowable.engine.HistoryService;
|
import org.flowable.engine.HistoryService;
|
||||||
@ -16,6 +17,7 @@ import java.util.List;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.HIDDEN_ASSIGNEE_ID;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.HIDDEN_ASSIGNEE_ID;
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.PROCESS_CLOSING_TYPE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通用的在 Command 内执行删除流程实例时的额外操作
|
* 通用的在 Command 内执行删除流程实例时的额外操作
|
||||||
@ -27,21 +29,25 @@ public class DeleteProcessInstanceOperation extends AbstractOperation {
|
|||||||
private final String processInstanceId;
|
private final String processInstanceId;
|
||||||
private final ExtAxHiTaskInstService extAxHiTaskInstService;
|
private final ExtAxHiTaskInstService extAxHiTaskInstService;
|
||||||
private String customDeleteReason;
|
private String customDeleteReason;
|
||||||
|
private final BpmnProcessInstanceResultEnum closingType;
|
||||||
|
|
||||||
public DeleteProcessInstanceOperation(CommandContext commandContext, String processInstanceId,
|
public DeleteProcessInstanceOperation(CommandContext commandContext, String processInstanceId,
|
||||||
ExtAxHiTaskInstService extAxHiTaskInstService) {
|
ExtAxHiTaskInstService extAxHiTaskInstService,
|
||||||
|
BpmnProcessInstanceResultEnum closingType) {
|
||||||
super(commandContext, null);
|
super(commandContext, null);
|
||||||
this.processInstanceId = processInstanceId;
|
this.processInstanceId = processInstanceId;
|
||||||
this.extAxHiTaskInstService = extAxHiTaskInstService;
|
this.extAxHiTaskInstService = extAxHiTaskInstService;
|
||||||
|
this.closingType = closingType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeleteProcessInstanceOperation(CommandContext commandContext, String processInstanceId,
|
public DeleteProcessInstanceOperation(CommandContext commandContext, String processInstanceId,
|
||||||
ExtAxHiTaskInstService extAxHiTaskInstService,
|
ExtAxHiTaskInstService extAxHiTaskInstService,
|
||||||
String customDeleteReason) {
|
String customDeleteReason, BpmnProcessInstanceResultEnum closingType) {
|
||||||
super(commandContext, null);
|
super(commandContext, null);
|
||||||
this.processInstanceId = processInstanceId;
|
this.processInstanceId = processInstanceId;
|
||||||
this.extAxHiTaskInstService = extAxHiTaskInstService;
|
this.extAxHiTaskInstService = extAxHiTaskInstService;
|
||||||
this.customDeleteReason = customDeleteReason;
|
this.customDeleteReason = customDeleteReason;
|
||||||
|
this.closingType = closingType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -65,6 +71,7 @@ public class DeleteProcessInstanceOperation extends AbstractOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
|
RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
|
||||||
|
runtimeService.setVariableLocal(processInstanceId, PROCESS_CLOSING_TYPE, closingType);
|
||||||
runtimeService.deleteProcessInstance(processInstanceId, StringUtils.hasText(customDeleteReason) ? customDeleteReason : HIDDEN_ASSIGNEE_ID);
|
runtimeService.deleteProcessInstance(processInstanceId, StringUtils.hasText(customDeleteReason) ? customDeleteReason : HIDDEN_ASSIGNEE_ID);
|
||||||
// 将结束流程实例的原因记录下来
|
// 将结束流程实例的原因记录下来
|
||||||
// runtimeService.deleteProcessInstance(processInstanceId, reason);
|
// runtimeService.deleteProcessInstance(processInstanceId, reason);
|
||||||
|
|||||||
@ -59,7 +59,7 @@ public class AutoPassTransactionListener implements TransactionListener {
|
|||||||
pass.setTaskId(delegateTask.getId());
|
pass.setTaskId(delegateTask.getId());
|
||||||
pass.setAdvice(advice);
|
pass.setAdvice(advice);
|
||||||
pass.setApprover(assigner);
|
pass.setApprover(assigner);
|
||||||
pass.setOperationDesc("自动通过");
|
pass.setOperationDesc("(自动通过)");
|
||||||
String jobId = commandExecutor.execute(commandConfig, new CustomApproveTaskAsyncCmd(pass));
|
String jobId = commandExecutor.execute(commandConfig, new CustomApproveTaskAsyncCmd(pass));
|
||||||
|
|
||||||
// 重置任务,因为上面的 cmd 和这个 cmd 的 lock 对象不一致
|
// 重置任务,因为上面的 cmd 和这个 cmd 的 lock 对象不一致
|
||||||
|
|||||||
@ -0,0 +1,14 @@
|
|||||||
|
package cn.axzo.workflow.core.listener;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.common.model.dto.AlterDTO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Core 往外转发的钩子
|
||||||
|
*
|
||||||
|
* @author wangli
|
||||||
|
* @since 2024-09-13 11:33
|
||||||
|
*/
|
||||||
|
public interface Alter {
|
||||||
|
|
||||||
|
void invoke(AlterDTO alterDTO);
|
||||||
|
}
|
||||||
@ -0,0 +1,131 @@
|
|||||||
|
package cn.axzo.workflow.core.listener.impl;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.common.enums.BpmnFlowNodeType;
|
||||||
|
import cn.axzo.workflow.common.model.dto.TermNodePausingDTO;
|
||||||
|
import cn.axzo.workflow.core.common.context.ActivityOperationContext;
|
||||||
|
import cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper;
|
||||||
|
import cn.axzo.workflow.core.conf.SupportRefreshProperties;
|
||||||
|
import cn.axzo.workflow.core.engine.job.AsyncTermNodeAlterJobHandler;
|
||||||
|
import cn.axzo.workflow.core.listener.AbstractBpmnEventListener;
|
||||||
|
import cn.axzo.workflow.core.listener.BpmnActivityEventListener;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.flowable.bpmn.model.BpmnModel;
|
||||||
|
import org.flowable.bpmn.model.FlowElement;
|
||||||
|
import org.flowable.bpmn.model.TimerEventDefinition;
|
||||||
|
import org.flowable.engine.ManagementService;
|
||||||
|
import org.flowable.engine.RuntimeService;
|
||||||
|
import org.flowable.engine.delegate.DelegateExecution;
|
||||||
|
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
|
||||||
|
import org.flowable.engine.impl.jobexecutor.TimerEventHandler;
|
||||||
|
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
|
||||||
|
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||||
|
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
|
||||||
|
import org.flowable.engine.impl.util.TimerUtil;
|
||||||
|
import org.flowable.job.api.Job;
|
||||||
|
import org.flowable.job.service.impl.persistence.entity.TimerJobEntity;
|
||||||
|
import org.springframework.context.annotation.Scope;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.BIZ_NODE_ALTER;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Core 包内置的活动事件处理,可共用与 Jar 包集成和微服务集成
|
||||||
|
* <p>
|
||||||
|
* 该监听主要是监听启动“无人”的业务节点超时告警功能
|
||||||
|
*
|
||||||
|
* @author wangli
|
||||||
|
* @since 2024-09-11 11:44
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@Scope("prototype")
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class InternalBpmnActivityEventListener_lo_Listener extends AbstractBpmnEventListener<ActivityOperationContext> implements BpmnActivityEventListener, Ordered {
|
||||||
|
private final SupportRefreshProperties refreshProperties;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOrder() {
|
||||||
|
return Integer.MIN_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点已启动
|
||||||
|
* <p>
|
||||||
|
* 创建一个周期性监控业务节点执行状态的任务
|
||||||
|
*
|
||||||
|
* @param execution
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onStart(DelegateExecution execution) {
|
||||||
|
if (!Boolean.TRUE.equals(refreshProperties.getAlterEnable())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();
|
||||||
|
RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
|
||||||
|
TermNodePausingDTO dto = new TermNodePausingDTO(execution.getProcessInstanceId(), execution.getCurrentActivityId(), refreshProperties.getAlterRetries());
|
||||||
|
runtimeService.setVariable(execution.getProcessInstanceId(), BIZ_NODE_ALTER + execution.getCurrentActivityId(), dto);
|
||||||
|
BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(execution.getProcessDefinitionId());
|
||||||
|
FlowElement flowElement = bpmnModel.getFlowElement(execution.getCurrentActivityId());
|
||||||
|
BpmnMetaParserHelper.getNodeType(flowElement).ifPresent(e -> {
|
||||||
|
if (Objects.equals(BpmnFlowNodeType.NODE_BUSINESS, e)) {
|
||||||
|
BpmnMetaParserHelper.getApprovalMethod(flowElement).ifPresent(method -> {
|
||||||
|
switch (method) {
|
||||||
|
case nobody:
|
||||||
|
case bizSpecify:
|
||||||
|
// FIXME 业务指定审批人,需要在业务设置了人后,清除定时
|
||||||
|
TimerEventDefinition timerEventDefinition = new TimerEventDefinition();
|
||||||
|
String timeUnit;
|
||||||
|
switch (refreshProperties.getAlterIntervalUnit()) {
|
||||||
|
case SECONDS:
|
||||||
|
timeUnit = "S";
|
||||||
|
break;
|
||||||
|
case HOURS:
|
||||||
|
timeUnit = "H";
|
||||||
|
break;
|
||||||
|
case DAYS:
|
||||||
|
timeUnit = "D";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// MINUTES
|
||||||
|
timeUnit = "M";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
timerEventDefinition.setTimeCycle("R" + refreshProperties.getAlterRetries() + "/PT" + refreshProperties.getAlterInterval() + timeUnit);
|
||||||
|
|
||||||
|
TimerJobEntity timerJob = TimerUtil.createTimerEntityForTimerEventDefinition(timerEventDefinition, execution.getCurrentFlowElement(),
|
||||||
|
false, (ExecutionEntity) execution, AsyncTermNodeAlterJobHandler.TYPE,
|
||||||
|
TimerEventHandler.createConfiguration(execution.getCurrentActivityId(), null, timerEventDefinition.getCalendarName()));
|
||||||
|
if (timerJob != null) {
|
||||||
|
CommandContextUtil.getTimerJobService().scheduleTimerJob(timerJob);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点已取消
|
||||||
|
*
|
||||||
|
* @param execution
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onEnd(DelegateExecution execution) {
|
||||||
|
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();
|
||||||
|
ManagementService managementService = processEngineConfiguration.getManagementService();
|
||||||
|
Job timerJob = managementService.createTimerJobQuery()
|
||||||
|
.elementId(execution.getCurrentActivityId())
|
||||||
|
.processInstanceId(execution.getProcessInstanceId())
|
||||||
|
.singleResult();
|
||||||
|
if (Objects.nonNull(timerJob)) {
|
||||||
|
CommandContextUtil.getTimerJobService().deleteTimerJob((TimerJobEntity) timerJob);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,114 @@
|
|||||||
|
package cn.axzo.workflow.core.repository.entity;
|
||||||
|
|
||||||
|
import cn.axzo.framework.data.mybatisplus.model.BaseEntity;
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.BpmnButtonConf;
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||||
|
import cn.axzo.workflow.core.conf.handler.ButtonConfTypeHandler;
|
||||||
|
import cn.axzo.workflow.core.conf.handler.ListAssigneeTypeHandler;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审批日志
|
||||||
|
*
|
||||||
|
* @author wangli
|
||||||
|
* @since 2024-08-30 15:29
|
||||||
|
*/
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@TableName(value = "ext_ax_process_log", autoResultMap = true)
|
||||||
|
@Data
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
public class ExtAxProcessLog extends BaseEntity<ExtAxProcessLog> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程实例 ID
|
||||||
|
*/
|
||||||
|
private String processInstanceId;
|
||||||
|
/**
|
||||||
|
* 实例归属租户
|
||||||
|
*/
|
||||||
|
private String tenantId;
|
||||||
|
/**
|
||||||
|
* 活动节点 ID
|
||||||
|
*/
|
||||||
|
private String activityId;
|
||||||
|
/**
|
||||||
|
* 活动节点名称
|
||||||
|
*/
|
||||||
|
private String activityName;
|
||||||
|
/**
|
||||||
|
* 审批方式:配置审批人/业务指定/业务触发(不含人)
|
||||||
|
*/
|
||||||
|
private String approvalMethod;
|
||||||
|
/**
|
||||||
|
* 节点类型:审批节点/业务节点/评论节点/抄送节点
|
||||||
|
*/
|
||||||
|
private String nodeType;
|
||||||
|
/**
|
||||||
|
* 节点模式:会签/或签
|
||||||
|
*/
|
||||||
|
private String nodeMode;
|
||||||
|
/**
|
||||||
|
* 任务 ID
|
||||||
|
*/
|
||||||
|
private String taskId;
|
||||||
|
/**
|
||||||
|
* 操作建议
|
||||||
|
*/
|
||||||
|
private String advice;
|
||||||
|
/**
|
||||||
|
* 操作描述
|
||||||
|
*/
|
||||||
|
private String operationDesc;
|
||||||
|
/**
|
||||||
|
* 审批人对象信息
|
||||||
|
*/
|
||||||
|
@TableField(typeHandler = ListAssigneeTypeHandler.class)
|
||||||
|
private List<BpmnTaskDelegateAssigner> assigneeFull;
|
||||||
|
/**
|
||||||
|
* 审批人标识
|
||||||
|
*/
|
||||||
|
private Long assigneeId;
|
||||||
|
/**
|
||||||
|
* 审批人归属租户
|
||||||
|
*/
|
||||||
|
private String assigneeTenantId;
|
||||||
|
/**
|
||||||
|
* 审批人姓名
|
||||||
|
*/
|
||||||
|
private String assigneeName;
|
||||||
|
/**
|
||||||
|
* 审批人归属单位
|
||||||
|
*/
|
||||||
|
private String assigneeOuId;
|
||||||
|
/**
|
||||||
|
* 任务开始时间
|
||||||
|
*/
|
||||||
|
private Date startTime;
|
||||||
|
/**
|
||||||
|
* 任务结束时间
|
||||||
|
*/
|
||||||
|
private Date endTime;
|
||||||
|
/**
|
||||||
|
* 节点按钮的全量配置
|
||||||
|
*/
|
||||||
|
@TableField(typeHandler = ButtonConfTypeHandler.class)
|
||||||
|
private BpmnButtonConf buttonConf;
|
||||||
|
/**
|
||||||
|
* 任务状态:审批中/通过/驳回/转交/加签/回退
|
||||||
|
*/
|
||||||
|
private String status;
|
||||||
|
/**
|
||||||
|
* 扩展字段
|
||||||
|
*/
|
||||||
|
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||||
|
private JSONObject extra;
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
package cn.axzo.workflow.core.repository.mapper;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.core.repository.entity.ExtAxProcessLog;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface ExtAxProcessLogMapper extends BaseMapperX<ExtAxProcessLog> {
|
||||||
|
}
|
||||||
@ -3,6 +3,7 @@ package cn.axzo.workflow.core.service;
|
|||||||
import cn.axzo.workflow.common.model.request.bpmn.activity.BpmnActivityTimeoutCallbackDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.activity.BpmnActivityTimeoutCallbackDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.activity.BpmnActivityTimeoutTriggerDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.activity.BpmnActivityTimeoutTriggerDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivitySetAssigneeDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivitySetAssigneeDTO;
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivityTriggerDTO;
|
||||||
import org.flowable.job.service.impl.persistence.entity.JobEntity;
|
import org.flowable.job.service.impl.persistence.entity.JobEntity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -13,26 +14,14 @@ import org.flowable.job.service.impl.persistence.entity.JobEntity;
|
|||||||
*/
|
*/
|
||||||
public interface BpmnProcessActivityService {
|
public interface BpmnProcessActivityService {
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行异步任务
|
|
||||||
*
|
|
||||||
* @param job 需要执行的任务
|
|
||||||
*/
|
|
||||||
void executeAsyncJob(JobEntity job);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 唤醒业务节点
|
* 唤醒业务节点
|
||||||
*
|
*
|
||||||
* @param executionId 活动 ID
|
* @param dto
|
||||||
*/
|
*/
|
||||||
void trigger(String executionId);
|
void trigger(BpmnActivityTriggerDTO dto);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 唤醒业务节点-异步
|
|
||||||
*
|
|
||||||
* @param executionId 活动 ID
|
|
||||||
*/
|
|
||||||
void triggerAsync(String executionId);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 给指定实例的指定节点重设审批人
|
* 给指定实例的指定节点重设审批人
|
||||||
@ -41,13 +30,6 @@ public interface BpmnProcessActivityService {
|
|||||||
*/
|
*/
|
||||||
void setAssignee(BpmnActivitySetAssigneeDTO dto);
|
void setAssignee(BpmnActivitySetAssigneeDTO dto);
|
||||||
|
|
||||||
/**
|
|
||||||
* 给指定实例的指定节点重设审批人
|
|
||||||
*
|
|
||||||
* @param dto
|
|
||||||
*/
|
|
||||||
void setAssigneeAsync(BpmnActivitySetAssigneeDTO dto);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置指定业务接口继续往下流转的触发时间
|
* 设置指定业务接口继续往下流转的触发时间
|
||||||
*
|
*
|
||||||
|
|||||||
@ -4,6 +4,9 @@ import cn.axzo.workflow.common.model.request.bpmn.definition.BpmnProcessDefiniti
|
|||||||
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessDefinitionPageDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessDefinitionPageDTO;
|
||||||
import cn.axzo.workflow.common.model.response.BpmPageResult;
|
import cn.axzo.workflow.common.model.response.BpmPageResult;
|
||||||
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessDefinitionVO;
|
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessDefinitionVO;
|
||||||
|
import org.flowable.bpmn.model.EndEvent;
|
||||||
|
import org.flowable.bpmn.model.FlowElement;
|
||||||
|
import org.flowable.bpmn.model.FlowNode;
|
||||||
import org.flowable.common.engine.impl.db.SuspensionState;
|
import org.flowable.common.engine.impl.db.SuspensionState;
|
||||||
import org.flowable.engine.repository.Model;
|
import org.flowable.engine.repository.Model;
|
||||||
import org.flowable.engine.repository.ProcessDefinition;
|
import org.flowable.engine.repository.ProcessDefinition;
|
||||||
@ -82,4 +85,12 @@ public interface BpmnProcessDefinitionService {
|
|||||||
List<ProcessDefinition> getProcessDefinitionListByDeploymentIds(Set<String> deploymentIds);
|
List<ProcessDefinition> getProcessDefinitionListByDeploymentIds(Set<String> deploymentIds);
|
||||||
|
|
||||||
void delete(String deploymentId, Boolean cascade);
|
void delete(String deploymentId, Boolean cascade);
|
||||||
|
|
||||||
|
List<EndEvent> findEndFlowElement(String processDefinitionId);
|
||||||
|
|
||||||
|
List<FlowNode> findFlowNodes(String processDefinitionId);
|
||||||
|
|
||||||
|
List<FlowElement> findFlowElements(String processDefinitionId);
|
||||||
|
|
||||||
|
List<FlowElement> findFlowElementsByIds(String processDefinitionId, List<String> flowElementIds);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,18 +7,21 @@ import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCar
|
|||||||
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCheckApproverDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCheckApproverDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCreateDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCreateDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCreateWithFormDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCreateWithFormDTO;
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceLogQueryDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceMyPageReqVO;
|
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceMyPageReqVO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceQueryDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceQueryDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.process.HistoricProcessInstanceSearchDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.process.HistoricProcessInstanceSearchDTO;
|
||||||
import cn.axzo.workflow.common.model.response.BpmPageResult;
|
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.BatchOperationResultVO;
|
||||||
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceAdminPageItemVO;
|
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceAdminPageItemVO;
|
||||||
|
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceLogVO;
|
||||||
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstancePageItemVO;
|
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstancePageItemVO;
|
||||||
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceVO;
|
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceVO;
|
||||||
import cn.axzo.workflow.common.model.response.bpmn.process.HistoricProcessInstanceVO;
|
import cn.axzo.workflow.common.model.response.bpmn.process.HistoricProcessInstanceVO;
|
||||||
import cn.axzo.workflow.common.model.response.bpmn.process.ProcessNodeDetailVO;
|
import cn.axzo.workflow.common.model.response.bpmn.process.ProcessNodeDetailVO;
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import org.flowable.engine.history.HistoricProcessInstance;
|
import org.flowable.engine.history.HistoricProcessInstance;
|
||||||
|
import org.flowable.engine.runtime.ProcessInstance;
|
||||||
import org.flowable.form.api.FormInfo;
|
import org.flowable.form.api.FormInfo;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -107,7 +110,7 @@ public interface BpmnProcessInstanceService {
|
|||||||
* 获得流程实例
|
* 获得流程实例
|
||||||
*
|
*
|
||||||
* @param processDefinitionId 流程实例的编号
|
* @param processDefinitionId 流程实例的编号
|
||||||
* @param status 状态
|
* @param status 状态
|
||||||
* @link SuspensionState.ACTIVE.getStateCode()
|
* @link SuspensionState.ACTIVE.getStateCode()
|
||||||
*/
|
*/
|
||||||
Boolean updateProcessStatus(String processDefinitionId, Integer status);
|
Boolean updateProcessStatus(String processDefinitionId, Integer status);
|
||||||
@ -143,9 +146,28 @@ public interface BpmnProcessInstanceService {
|
|||||||
*/
|
*/
|
||||||
List<ProcessNodeDetailVO> getProcessInstanceNodeForecast(String processInstanceId, String tenantId);
|
List<ProcessNodeDetailVO> getProcessInstanceNodeForecast(String processInstanceId, String tenantId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对指定流程的指定节点开始推送未来的结点,并结合变量计算正确的分支
|
||||||
|
*
|
||||||
|
* @param processInstanceId 实例编号
|
||||||
|
* @param startNodeDefinitionKey 从该节点开始推断后续的节点
|
||||||
|
* @param containSelf 是否包含起始节点
|
||||||
|
* @param checkAliveThrowException 如果给的实例编号已到终态,不会执行推测,用该参数为 true 时,抛出实例完结的异常信息,如果为 false时,直接返回空集合
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
List<ProcessNodeDetailVO> getProcessInstanceNodeForecastWithSpecifyTaskDefinitionKey(String processInstanceId, ProcessInstance instance, String startNodeDefinitionKey, Boolean containSelf, Boolean checkAliveThrowException);
|
||||||
|
|
||||||
List<ProcessNodeDetailVO> getProcessInstanceNodeFilterForecast(String processInstanceId, String tenantId, List<String> nodeDefinitionKeys);
|
List<ProcessNodeDetailVO> getProcessInstanceNodeFilterForecast(String processInstanceId, String tenantId, List<String> nodeDefinitionKeys);
|
||||||
|
|
||||||
List<String> getTenantIds();
|
List<String> getTenantIds();
|
||||||
|
|
||||||
Boolean checkInstanceApprover(BpmnProcessInstanceCheckApproverDTO dto);
|
Boolean checkInstanceApprover(BpmnProcessInstanceCheckApproverDTO dto);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定流程实例的日志
|
||||||
|
*
|
||||||
|
* @param dto
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
BpmnProcessInstanceLogVO getProcessInstanceLog(BpmnProcessInstanceLogQueryDTO dto);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,4 +5,8 @@ public interface BpmnProcessJobService {
|
|||||||
void executeDeadLetterJobActionByJobId(String jobId);
|
void executeDeadLetterJobActionByJobId(String jobId);
|
||||||
|
|
||||||
void executeDeadLetterJobActionByProcInstId(String processInstanceId);
|
void executeDeadLetterJobActionByProcInstId(String processInstanceId);
|
||||||
|
|
||||||
|
String getDeadLetterJobExceptionStacktrace(String processInstId);
|
||||||
|
|
||||||
|
String getDeadLetterJobExceptionStacktraceByJobId(String jobId);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
package cn.axzo.workflow.core.service;
|
package cn.axzo.workflow.core.service;
|
||||||
|
|
||||||
import cn.axzo.workflow.common.enums.BpmnFlowNodeType;
|
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.BpmnRobotTaskCompleteDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnRobotTaskCreateDTO;
|
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.BpmnTaskAttachmentDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAuditDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAuditDTO;
|
||||||
|
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.BpmnTaskCommentDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskCountersignDTO;
|
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.BpmnTaskPageSearchDTO;
|
||||||
@ -41,6 +42,11 @@ public interface BpmnProcessTaskService {
|
|||||||
*/
|
*/
|
||||||
void approveTask(BpmnTaskAuditDTO taskAuditDTO);
|
void approveTask(BpmnTaskAuditDTO taskAuditDTO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回退
|
||||||
|
*/
|
||||||
|
void backTask(BpmnTaskBackAuditDTO taskAuditDTO);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量同意
|
* 批量同意
|
||||||
*
|
*
|
||||||
@ -48,6 +54,12 @@ public interface BpmnProcessTaskService {
|
|||||||
*/
|
*/
|
||||||
BatchOperationResultVO batchApproveTask(List<BpmnTaskAuditDTO> taskAuditDTOS);
|
BatchOperationResultVO batchApproveTask(List<BpmnTaskAuditDTO> taskAuditDTOS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回退到指定节点,可以回退节点选项
|
||||||
|
* @param taskId 任务id
|
||||||
|
*/
|
||||||
|
List<BpmnOptionalNodeDTO> getBackOptionalNodes(String taskId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 驳回
|
* 驳回
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -0,0 +1,56 @@
|
|||||||
|
package cn.axzo.workflow.core.service;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||||
|
import cn.axzo.workflow.core.repository.entity.ExtAxProcessLog;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Api Log 表操作服务
|
||||||
|
*
|
||||||
|
* @author wangli
|
||||||
|
* @since 2024/4/3 10:40
|
||||||
|
*/
|
||||||
|
public interface ExtAxProcessLogService {
|
||||||
|
/**
|
||||||
|
* 新增审批流程日志
|
||||||
|
*
|
||||||
|
* @param log
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Long insert(ExtAxProcessLog log);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据参数删除指定任务
|
||||||
|
*
|
||||||
|
* @param deleteLog 查询条件
|
||||||
|
*/
|
||||||
|
void delete(ExtAxProcessLog deleteLog);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据有 ID 的实体直接更新
|
||||||
|
*
|
||||||
|
* @param updateLog
|
||||||
|
*/
|
||||||
|
void updateById(ExtAxProcessLog updateLog);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据条件更新指定对象的列
|
||||||
|
*
|
||||||
|
* @param query
|
||||||
|
* @param update
|
||||||
|
*/
|
||||||
|
void update(ExtAxProcessLog query, ExtAxProcessLog update);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新指定任务的审批人
|
||||||
|
*
|
||||||
|
* @param updateLog
|
||||||
|
* @param assignee
|
||||||
|
*/
|
||||||
|
void updateAssignee(ExtAxProcessLog updateLog, BpmnTaskDelegateAssigner assignee);
|
||||||
|
|
||||||
|
void updateAssignee(ExtAxProcessLog updateLog, BpmnTaskDelegateAssigner assignee, String operationDesc);
|
||||||
|
|
||||||
|
List<ExtAxProcessLog> genericQuery(ExtAxProcessLog query);
|
||||||
|
}
|
||||||
@ -30,12 +30,12 @@ import static org.mapstruct.NullValueCheckStrategy.ALWAYS;
|
|||||||
* @since 2024/1/25 16:31
|
* @since 2024/1/25 16:31
|
||||||
*/
|
*/
|
||||||
@Mapper(
|
@Mapper(
|
||||||
componentModel = "spring",
|
componentModel = "spring",
|
||||||
nullValueCheckStrategy = ALWAYS,
|
nullValueCheckStrategy = ALWAYS,
|
||||||
imports = Arrays.class
|
imports = Arrays.class
|
||||||
)
|
)
|
||||||
public interface BpmnProcessInstanceAdminPageItemConverter extends EntityConverter<BpmnProcessInstanceAdminPageItemVO,
|
public interface BpmnProcessInstanceAdminPageItemConverter extends EntityConverter<BpmnProcessInstanceAdminPageItemVO,
|
||||||
HistoricProcessInstance> {
|
HistoricProcessInstance> {
|
||||||
|
|
||||||
@Mapping(target = "processInstanceId", source = "id")
|
@Mapping(target = "processInstanceId", source = "id")
|
||||||
@Mapping(target = "processInstanceName", source = "name")
|
@Mapping(target = "processInstanceName", source = "name")
|
||||||
@ -58,8 +58,8 @@ public interface BpmnProcessInstanceAdminPageItemConverter extends EntityConvert
|
|||||||
|
|
||||||
if (Objects.equals(PROCESSING.getStatus(), i.getBusinessStatus())) {
|
if (Objects.equals(PROCESSING.getStatus(), i.getBusinessStatus())) {
|
||||||
List<FlowElement> flowElements = instanceFlowElementMap.get(i.getId()).stream()
|
List<FlowElement> flowElements = instanceFlowElementMap.get(i.getId()).stream()
|
||||||
.filter(j -> j instanceof UserTask || j instanceof ReceiveTask || j instanceof ServiceTask)
|
.filter(j -> j instanceof UserTask || j instanceof ReceiveTask || j instanceof ServiceTask)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
vo.setTotalNodeCount(flowElements.size());
|
vo.setTotalNodeCount(flowElements.size());
|
||||||
|
|
||||||
// 进行中的节点
|
// 进行中的节点
|
||||||
@ -85,7 +85,7 @@ public interface BpmnProcessInstanceAdminPageItemConverter extends EntityConvert
|
|||||||
vo.setCategoryDesc(category.getLabel());
|
vo.setCategoryDesc(category.getLabel());
|
||||||
vo.setWorkspaceTypeCode(category.getWorkspaceTypeCode());
|
vo.setWorkspaceTypeCode(category.getWorkspaceTypeCode());
|
||||||
vo.setBusinessStatusDesc(BpmnProcessInstanceResultEnum.valueOfStatus(vo.getBusinessStatus()).getDesc());
|
vo.setBusinessStatusDesc(BpmnProcessInstanceResultEnum.valueOfStatus(vo.getBusinessStatus()).getDesc());
|
||||||
vo.setWorkspaceType(WorkspaceType.getType(Integer.valueOf(vo.getWorkspaceTypeCode())));
|
vo.setWorkspaceType(WorkspaceType.getType(Integer.valueOf(Objects.nonNull(vo.getWorkspaceTypeCode()) ? vo.getWorkspaceTypeCode() : "0")));
|
||||||
result.add(vo);
|
result.add(vo);
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@ -3,34 +3,31 @@ package cn.axzo.workflow.core.service.impl;
|
|||||||
import cn.axzo.workflow.common.model.request.bpmn.activity.BpmnActivityTimeoutCallbackDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.activity.BpmnActivityTimeoutCallbackDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.activity.BpmnActivityTimeoutTriggerDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.activity.BpmnActivityTimeoutTriggerDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivitySetAssigneeDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivitySetAssigneeDTO;
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivityTriggerDTO;
|
||||||
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
||||||
import cn.axzo.workflow.core.engine.cmd.CustomAbortProcessInstanceCmd;
|
import cn.axzo.workflow.core.engine.cmd.CustomAbortProcessInstanceCmd;
|
||||||
|
import cn.axzo.workflow.core.engine.cmd.CustomActivityTriggerAsyncCmd;
|
||||||
|
import cn.axzo.workflow.core.engine.cmd.CustomActivityTriggerCmd;
|
||||||
|
import cn.axzo.workflow.core.engine.cmd.CustomBizSpecifyAssigneeToTaskAsyncCmd;
|
||||||
import cn.axzo.workflow.core.engine.cmd.CustomBizSpecifyAssigneeToTaskCmd;
|
import cn.axzo.workflow.core.engine.cmd.CustomBizSpecifyAssigneeToTaskCmd;
|
||||||
import cn.axzo.workflow.core.engine.cmd.CustomBusinessNodeTimeoutCallbackCmd;
|
import cn.axzo.workflow.core.engine.cmd.CustomBusinessNodeTimeoutCallbackCmd;
|
||||||
import cn.axzo.workflow.core.engine.cmd.CustomBusinessNodeTimeoutTriggerCmd;
|
import cn.axzo.workflow.core.engine.cmd.CustomBusinessNodeTimeoutTriggerCmd;
|
||||||
import cn.axzo.workflow.core.engine.job.AsyncBpmnProcessActivityJobHandler;
|
|
||||||
import cn.axzo.workflow.core.service.BpmnProcessActivityService;
|
import cn.axzo.workflow.core.service.BpmnProcessActivityService;
|
||||||
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
|
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
|
||||||
import cn.hutool.json.JSONUtil;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.flowable.common.engine.impl.interceptor.Command;
|
|
||||||
import org.flowable.common.engine.impl.interceptor.CommandExecutor;
|
import org.flowable.common.engine.impl.interceptor.CommandExecutor;
|
||||||
import org.flowable.engine.RuntimeService;
|
import org.flowable.engine.RuntimeService;
|
||||||
import org.flowable.engine.runtime.Execution;
|
import org.flowable.engine.runtime.Execution;
|
||||||
import org.flowable.engine.runtime.ProcessInstance;
|
|
||||||
import org.flowable.job.service.JobService;
|
|
||||||
import org.flowable.job.service.impl.persistence.entity.JobEntity;
|
|
||||||
import org.flowable.spring.SpringProcessEngineConfiguration;
|
import org.flowable.spring.SpringProcessEngineConfiguration;
|
||||||
import org.flowable.task.api.Task;
|
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import static cn.axzo.workflow.core.common.code.BpmnTaskRespCode.ACTIVITY_TRIGGER_NOT_EXISTS;
|
import static cn.axzo.workflow.core.common.code.BpmnTaskRespCode.ACTIVITY_TRIGGER_NOT_EXISTS;
|
||||||
import static cn.axzo.workflow.core.common.code.BpmnTaskRespCode.PROCESS_INSTANCE_IS_NOT_EXIST;
|
|
||||||
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@ -46,42 +43,15 @@ public class BpmnProcessActivityServiceImpl implements BpmnProcessActivityServic
|
|||||||
@Lazy
|
@Lazy
|
||||||
private SpringProcessEngineConfiguration processEngineConfiguration;
|
private SpringProcessEngineConfiguration processEngineConfiguration;
|
||||||
|
|
||||||
private static final String JOB_TRIGGER_ASYNC_NAME = "asyncTrigger";
|
|
||||||
private static final String JOB_ASSIGNEE_ASYNC_NAME = "asyncSetAssignee";
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void executeAsyncJob(JobEntity job) {
|
@Transactional(rollbackFor = Exception.class)
|
||||||
if (job == null) {
|
public void trigger(BpmnActivityTriggerDTO dto) {
|
||||||
log.warn("job is null");
|
CommandExecutor commandExecutor = processEngineConfiguration.getCommandExecutor();
|
||||||
throw new NullPointerException("job is null");
|
if (Boolean.TRUE.equals(dto.getAsync())) {
|
||||||
|
commandExecutor.execute(new CustomActivityTriggerAsyncCmd(dto));
|
||||||
|
} else {
|
||||||
|
commandExecutor.execute(new CustomActivityTriggerCmd(dto));
|
||||||
}
|
}
|
||||||
String type = job.getElementName();
|
|
||||||
String customValues = job.getCustomValues();
|
|
||||||
switch (type) {
|
|
||||||
case JOB_TRIGGER_ASYNC_NAME:
|
|
||||||
trigger(customValues);
|
|
||||||
break;
|
|
||||||
case JOB_ASSIGNEE_ASYNC_NAME:
|
|
||||||
BpmnActivitySetAssigneeDTO dto = JSONUtil.toBean(customValues, BpmnActivitySetAssigneeDTO.class);
|
|
||||||
setAssignee(dto);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new UnsupportedOperationException(String.format("不支持'%s'类型操作", type));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void trigger(String executionId) {
|
|
||||||
Execution execution = runtimeService.createExecutionQuery().executionId(executionId).singleResult();
|
|
||||||
if (Objects.isNull(execution)) {
|
|
||||||
throw new WorkflowEngineException(ACTIVITY_TRIGGER_NOT_EXISTS, executionId);
|
|
||||||
}
|
|
||||||
runtimeService.trigger(executionId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void triggerAsync(String executionId) {
|
|
||||||
validateAndStartAsyncJob(executionId, executionId, JOB_TRIGGER_ASYNC_NAME);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -95,43 +65,12 @@ public class BpmnProcessActivityServiceImpl implements BpmnProcessActivityServic
|
|||||||
commandExecutor.execute(new CustomAbortProcessInstanceCmd(execution.getProcessInstanceId(), null, "业务未指定审批人", extAxHiTaskInstService));
|
commandExecutor.execute(new CustomAbortProcessInstanceCmd(execution.getProcessInstanceId(), null, "业务未指定审批人", extAxHiTaskInstService));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
commandExecutor.execute(new CustomBizSpecifyAssigneeToTaskCmd(dto.getTriggerId(), dto.getAssigners()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
if(Boolean.TRUE.equals(dto.getAsync())) {
|
||||||
public void setAssigneeAsync(BpmnActivitySetAssigneeDTO dto) {
|
commandExecutor.execute(new CustomBizSpecifyAssigneeToTaskAsyncCmd(dto));
|
||||||
//查询任务
|
} else {
|
||||||
Task task = CustomBizSpecifyAssigneeToTaskCmd.getOperateTask(processEngineConfiguration.getTaskService(), dto.getTriggerId());
|
commandExecutor.execute(new CustomBizSpecifyAssigneeToTaskCmd(dto.getTriggerId(), dto.getAssigners()));
|
||||||
//先校验
|
}
|
||||||
CustomBizSpecifyAssigneeToTaskCmd.validate(processEngineConfiguration.getRuntimeService(), dto.getTriggerId(), task, dto.getAssigners());
|
|
||||||
validateAndStartAsyncJob(dto.getTriggerId(), dto, JOB_ASSIGNEE_ASYNC_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void validateAndStartAsyncJob(String executionId, Object customValue, String actionName) {
|
|
||||||
processEngineConfiguration.getCommandExecutor().execute((Command<Void>) commandContext -> {
|
|
||||||
Execution execution = runtimeService.createExecutionQuery().executionId(executionId).singleResult();
|
|
||||||
if (Objects.isNull(execution)) {
|
|
||||||
throw new WorkflowEngineException(ACTIVITY_TRIGGER_NOT_EXISTS, executionId);
|
|
||||||
}
|
|
||||||
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(execution.getProcessInstanceId()).singleResult();
|
|
||||||
if (Objects.isNull(processInstance)) {
|
|
||||||
throw new WorkflowEngineException(PROCESS_INSTANCE_IS_NOT_EXIST, execution.getId());
|
|
||||||
}
|
|
||||||
JobService jobService = processEngineConfiguration.getJobServiceConfiguration().getJobService();
|
|
||||||
JobEntity job = jobService.createJob();
|
|
||||||
// 这里的 executionId 可为 null
|
|
||||||
job.setExecutionId(executionId);
|
|
||||||
job.setProcessInstanceId(execution.getProcessInstanceId());
|
|
||||||
job.setProcessDefinitionId(processInstance.getProcessDefinitionId());
|
|
||||||
job.setElementId(AsyncBpmnProcessActivityJobHandler.TYPE);
|
|
||||||
job.setElementName(actionName);
|
|
||||||
job.setJobHandlerType(AsyncBpmnProcessActivityJobHandler.TYPE);
|
|
||||||
job.setTenantId(execution.getTenantId());
|
|
||||||
job.setCustomValues(JSONUtil.toJsonStr(customValue));
|
|
||||||
jobService.createAsyncJob(job, false);
|
|
||||||
jobService.scheduleAsyncJob(job);
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -14,6 +14,9 @@ import cn.hutool.core.collection.CollUtil;
|
|||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.flowable.bpmn.model.BpmnModel;
|
import org.flowable.bpmn.model.BpmnModel;
|
||||||
|
import org.flowable.bpmn.model.EndEvent;
|
||||||
|
import org.flowable.bpmn.model.FlowElement;
|
||||||
|
import org.flowable.bpmn.model.FlowNode;
|
||||||
import org.flowable.common.engine.impl.db.SuspensionState;
|
import org.flowable.common.engine.impl.db.SuspensionState;
|
||||||
import org.flowable.engine.RepositoryService;
|
import org.flowable.engine.RepositoryService;
|
||||||
import org.flowable.engine.repository.Deployment;
|
import org.flowable.engine.repository.Deployment;
|
||||||
@ -27,6 +30,7 @@ import org.springframework.util.StringUtils;
|
|||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@ -282,4 +286,50 @@ public class BpmnProcessDefinitionServiceImpl implements BpmnProcessDefinitionSe
|
|||||||
}
|
}
|
||||||
return repositoryService.createDeploymentQuery().deploymentId(id).singleResult();
|
return repositoryService.createDeploymentQuery().deploymentId(id).singleResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<EndEvent> findEndFlowElement(String processDefinitionId) {
|
||||||
|
return getNodesByType(processDefinitionId, EndEvent.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<FlowNode> findFlowNodes(String processDefinitionId) {
|
||||||
|
return getNodesByType(processDefinitionId, FlowNode.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<FlowElement> findFlowElements(String processDefinitionId) {
|
||||||
|
return getNodesByType(processDefinitionId, FlowElement.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<FlowElement> findFlowElementsByIds(String processDefinitionId, List<String> flowElementIds) {
|
||||||
|
if (CollectionUtils.isEmpty(flowElementIds)) {
|
||||||
|
return emptyList();
|
||||||
|
}
|
||||||
|
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
|
||||||
|
.processDefinitionId(processDefinitionId)
|
||||||
|
.singleResult();
|
||||||
|
if (processDefinition == null) {
|
||||||
|
return emptyList();
|
||||||
|
}
|
||||||
|
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
|
||||||
|
return flowElementIds.stream().map(bpmnModel::getFlowElement).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T extends FlowElement> List<T> getNodesByType(String processDefinitionId, Class<T> clazz) {
|
||||||
|
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
|
||||||
|
.processDefinitionId(processDefinitionId)
|
||||||
|
.singleResult();
|
||||||
|
if (processDefinition == null) {
|
||||||
|
return emptyList();
|
||||||
|
}
|
||||||
|
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
|
||||||
|
Collection<T> flowNodes = bpmnModel.getMainProcess().findFlowElementsOfType(clazz);
|
||||||
|
if (CollectionUtils.isEmpty(flowNodes)) {
|
||||||
|
return emptyList();
|
||||||
|
}
|
||||||
|
return new ArrayList<>(flowNodes);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,15 @@
|
|||||||
package cn.axzo.workflow.core.service.impl;
|
package cn.axzo.workflow.core.service.impl;
|
||||||
|
|
||||||
import cn.axzo.workflow.common.constant.BpmnConstants;
|
import cn.axzo.workflow.common.constant.BpmnConstants;
|
||||||
|
import cn.axzo.workflow.common.enums.ApprovalMethodEnum;
|
||||||
|
import cn.axzo.workflow.common.enums.AttachmentTypeEnum;
|
||||||
import cn.axzo.workflow.common.enums.BpmnFlowNodeMode;
|
import cn.axzo.workflow.common.enums.BpmnFlowNodeMode;
|
||||||
|
import cn.axzo.workflow.common.enums.BpmnFlowNodeType;
|
||||||
|
import cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum;
|
||||||
import cn.axzo.workflow.common.enums.WorkspaceType;
|
import cn.axzo.workflow.common.enums.WorkspaceType;
|
||||||
|
import cn.axzo.workflow.common.model.request.BpmnApproveConf;
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.BpmnButtonConf;
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.BpmnButtonMetaInfo;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceAbortDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceAbortDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceAdminPageReqVO;
|
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceAdminPageReqVO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCancelDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCancelDTO;
|
||||||
@ -10,9 +17,11 @@ import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCar
|
|||||||
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCheckApproverDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCheckApproverDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCreateDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCreateDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCreateWithFormDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCreateWithFormDTO;
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceLogQueryDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceMyPageReqVO;
|
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceMyPageReqVO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceQueryDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceQueryDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.process.HistoricProcessInstanceSearchDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.process.HistoricProcessInstanceSearchDTO;
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.task.AttachmentDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||||
import cn.axzo.workflow.common.model.request.category.CategorySearchDTO;
|
import cn.axzo.workflow.common.model.request.category.CategorySearchDTO;
|
||||||
import cn.axzo.workflow.common.model.response.BpmPageResult;
|
import cn.axzo.workflow.common.model.response.BpmPageResult;
|
||||||
@ -20,10 +29,12 @@ import cn.axzo.workflow.common.model.response.bpmn.BatchOperationItemResultVO;
|
|||||||
import cn.axzo.workflow.common.model.response.bpmn.BatchOperationResultVO;
|
import cn.axzo.workflow.common.model.response.bpmn.BatchOperationResultVO;
|
||||||
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessDefinitionVO;
|
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessDefinitionVO;
|
||||||
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceAdminPageItemVO;
|
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceAdminPageItemVO;
|
||||||
|
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceLogVO;
|
||||||
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstancePageItemVO;
|
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstancePageItemVO;
|
||||||
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceVO;
|
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceVO;
|
||||||
import cn.axzo.workflow.common.model.response.bpmn.process.HistoricProcessInstanceVO;
|
import cn.axzo.workflow.common.model.response.bpmn.process.HistoricProcessInstanceVO;
|
||||||
import cn.axzo.workflow.common.model.response.bpmn.process.ProcessNodeDetailVO;
|
import cn.axzo.workflow.common.model.response.bpmn.process.ProcessNodeDetailVO;
|
||||||
|
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskInstanceLogVO;
|
||||||
import cn.axzo.workflow.common.model.response.category.CategoryItemVO;
|
import cn.axzo.workflow.common.model.response.category.CategoryItemVO;
|
||||||
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
||||||
import cn.axzo.workflow.core.common.utils.BpmnCollectionUtils;
|
import cn.axzo.workflow.core.common.utils.BpmnCollectionUtils;
|
||||||
@ -34,10 +45,12 @@ import cn.axzo.workflow.core.engine.cmd.CustomCancelProcessInstanceCmd;
|
|||||||
import cn.axzo.workflow.core.engine.cmd.CustomCarbonCopyUserSelectorCmd;
|
import cn.axzo.workflow.core.engine.cmd.CustomCarbonCopyUserSelectorCmd;
|
||||||
import cn.axzo.workflow.core.engine.cmd.CustomForecastUserTaskAssigneeCmd;
|
import cn.axzo.workflow.core.engine.cmd.CustomForecastUserTaskAssigneeCmd;
|
||||||
import cn.axzo.workflow.core.engine.listener.EngineExecutionStartListener;
|
import cn.axzo.workflow.core.engine.listener.EngineExecutionStartListener;
|
||||||
|
import cn.axzo.workflow.core.repository.entity.ExtAxProcessLog;
|
||||||
import cn.axzo.workflow.core.service.BpmnProcessDefinitionService;
|
import cn.axzo.workflow.core.service.BpmnProcessDefinitionService;
|
||||||
import cn.axzo.workflow.core.service.BpmnProcessInstanceService;
|
import cn.axzo.workflow.core.service.BpmnProcessInstanceService;
|
||||||
import cn.axzo.workflow.core.service.CategoryService;
|
import cn.axzo.workflow.core.service.CategoryService;
|
||||||
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
|
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
|
||||||
|
import cn.axzo.workflow.core.service.ExtAxProcessLogService;
|
||||||
import cn.axzo.workflow.core.service.converter.BpmnHistoricProcessInstanceConverter;
|
import cn.axzo.workflow.core.service.converter.BpmnHistoricProcessInstanceConverter;
|
||||||
import cn.axzo.workflow.core.service.converter.BpmnHistoricTaskInstanceConverter;
|
import cn.axzo.workflow.core.service.converter.BpmnHistoricTaskInstanceConverter;
|
||||||
import cn.axzo.workflow.core.service.converter.BpmnProcessInstanceAdminPageItemConverter;
|
import cn.axzo.workflow.core.service.converter.BpmnProcessInstanceAdminPageItemConverter;
|
||||||
@ -77,6 +90,7 @@ import org.flowable.engine.runtime.NativeActivityInstanceQuery;
|
|||||||
import org.flowable.engine.runtime.ProcessInstance;
|
import org.flowable.engine.runtime.ProcessInstance;
|
||||||
import org.flowable.engine.runtime.ProcessInstanceBuilder;
|
import org.flowable.engine.runtime.ProcessInstanceBuilder;
|
||||||
import org.flowable.engine.runtime.ProcessInstanceQuery;
|
import org.flowable.engine.runtime.ProcessInstanceQuery;
|
||||||
|
import org.flowable.engine.task.Attachment;
|
||||||
import org.flowable.form.api.FormInfo;
|
import org.flowable.form.api.FormInfo;
|
||||||
import org.flowable.spring.SpringProcessEngineConfiguration;
|
import org.flowable.spring.SpringProcessEngineConfiguration;
|
||||||
import org.flowable.task.api.Task;
|
import org.flowable.task.api.Task;
|
||||||
@ -95,6 +109,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -109,6 +124,10 @@ import static cn.axzo.workflow.client.config.WorkflowRequestInterceptor.HEADER_S
|
|||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.AND_SIGN_EXPRESSION;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.AND_SIGN_EXPRESSION;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.BIZ_ORG_RELATION;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.BIZ_ORG_RELATION;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.BPM_MODEL_CATEGORY;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.BPM_MODEL_CATEGORY;
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_BUTTON_TYPE_CARBON_COPY;
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_BUTTON_TYPE_CURRENT;
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_BUTTON_TYPE_HISTORY;
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_BUTTON_TYPE_INITIATOR;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.CREATE_INSTANCE_PARAMS;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.CREATE_INSTANCE_PARAMS;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.FLOW_SERVER_VERSION_121;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.FLOW_SERVER_VERSION_121;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_INITIATOR;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_INITIATOR;
|
||||||
@ -125,8 +144,14 @@ import static cn.axzo.workflow.common.enums.BpmnFlowNodeMode.AND;
|
|||||||
import static cn.axzo.workflow.common.enums.BpmnFlowNodeMode.EXCEPTIONAL;
|
import static cn.axzo.workflow.common.enums.BpmnFlowNodeMode.EXCEPTIONAL;
|
||||||
import static cn.axzo.workflow.common.enums.BpmnFlowNodeMode.GENERAL;
|
import static cn.axzo.workflow.common.enums.BpmnFlowNodeMode.GENERAL;
|
||||||
import static cn.axzo.workflow.common.enums.BpmnFlowNodeMode.OR;
|
import static cn.axzo.workflow.common.enums.BpmnFlowNodeMode.OR;
|
||||||
|
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_BUSINESS;
|
||||||
|
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_CARBON_COPY;
|
||||||
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_STARTER;
|
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_STARTER;
|
||||||
|
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_TASK;
|
||||||
|
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.APPROVED;
|
||||||
|
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.DELETED;
|
||||||
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.PROCESSING;
|
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.PROCESSING;
|
||||||
|
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.REJECTED;
|
||||||
import static cn.axzo.workflow.common.enums.WorkspaceType.GOVERNMENT;
|
import static cn.axzo.workflow.common.enums.WorkspaceType.GOVERNMENT;
|
||||||
import static cn.axzo.workflow.core.common.code.BpmnInstanceRespCode.PROCESS_INSTANCE_ID_NOT_EXISTS;
|
import static cn.axzo.workflow.core.common.code.BpmnInstanceRespCode.PROCESS_INSTANCE_ID_NOT_EXISTS;
|
||||||
import static cn.axzo.workflow.core.common.code.BpmnInstanceRespCode.PROCESS_INSTANCE_NOT_EXISTS;
|
import static cn.axzo.workflow.core.common.code.BpmnInstanceRespCode.PROCESS_INSTANCE_NOT_EXISTS;
|
||||||
@ -187,6 +212,8 @@ public class BpmnProcessInstanceServiceImpl implements BpmnProcessInstanceServic
|
|||||||
@Resource
|
@Resource
|
||||||
@Lazy
|
@Lazy
|
||||||
private BpmnProcessInstanceService bpmnProcessInstanceService;
|
private BpmnProcessInstanceService bpmnProcessInstanceService;
|
||||||
|
@Resource
|
||||||
|
private ExtAxProcessLogService processLogService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HistoricProcessInstance getProcessInstanceByBusinessKey(String businessKey, @Nullable String tenantId,
|
public HistoricProcessInstance getProcessInstanceByBusinessKey(String businessKey, @Nullable String tenantId,
|
||||||
@ -844,6 +871,30 @@ public class BpmnProcessInstanceServiceImpl implements BpmnProcessInstanceServic
|
|||||||
return getProcessInstanceNodeFilterForecast(processInstanceId, tenantId, Collections.emptyList());
|
return getProcessInstanceNodeFilterForecast(processInstanceId, tenantId, Collections.emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ProcessNodeDetailVO> getProcessInstanceNodeForecastWithSpecifyTaskDefinitionKey(String processInstanceId,
|
||||||
|
ProcessInstance instance,
|
||||||
|
String startNodeDefinitionKey,
|
||||||
|
Boolean containSelf,
|
||||||
|
Boolean checkAliveThrowException) {
|
||||||
|
if (Objects.isNull(instance)) {
|
||||||
|
instance = runtimeService.createProcessInstanceQuery()
|
||||||
|
.processInstanceId(processInstanceId).singleResult();
|
||||||
|
if (Objects.isNull(instance)) {
|
||||||
|
if (checkAliveThrowException) {
|
||||||
|
throw new WorkflowEngineException(RUNNING_INSTANCE_ONLY_FORECAST);
|
||||||
|
} else {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<FlowElement> flowElements = forecastService.performProcessForecasting(instance.getProcessInstanceId(), instance, startNodeDefinitionKey, containSelf);
|
||||||
|
|
||||||
|
return buildNodeDetailVos(processInstanceId, Collections.emptyList(), instance, flowElements);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ProcessNodeDetailVO> getProcessInstanceNodeFilterForecast(String processInstanceId, String tenantId, List<String> nodeDefinitionKeys) {
|
public List<ProcessNodeDetailVO> getProcessInstanceNodeFilterForecast(String processInstanceId, String tenantId, List<String> nodeDefinitionKeys) {
|
||||||
ProcessInstanceQuery query = runtimeService.createProcessInstanceQuery()
|
ProcessInstanceQuery query = runtimeService.createProcessInstanceQuery()
|
||||||
@ -857,6 +908,10 @@ public class BpmnProcessInstanceServiceImpl implements BpmnProcessInstanceServic
|
|||||||
}
|
}
|
||||||
List<FlowElement> flowElements = forecastService.performProcessForecasting(processInstanceId, instance);
|
List<FlowElement> flowElements = forecastService.performProcessForecasting(processInstanceId, instance);
|
||||||
|
|
||||||
|
return buildNodeDetailVos(processInstanceId, nodeDefinitionKeys, instance, flowElements);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ProcessNodeDetailVO> buildNodeDetailVos(String processInstanceId, List<String> nodeDefinitionKeys, ProcessInstance instance, List<FlowElement> flowElements) {
|
||||||
BpmnModel bpmnModel = repositoryService.getBpmnModel(instance.getProcessDefinitionId());
|
BpmnModel bpmnModel = repositoryService.getBpmnModel(instance.getProcessDefinitionId());
|
||||||
List<ProcessNodeDetailVO> resultList = new ArrayList<>(flowElements.size());
|
List<ProcessNodeDetailVO> resultList = new ArrayList<>(flowElements.size());
|
||||||
// 发起人节点,也是一个 UserTask 节点, 所以这里默认就包含了发起人节点
|
// 发起人节点,也是一个 UserTask 节点, 所以这里默认就包含了发起人节点
|
||||||
@ -961,4 +1016,361 @@ public class BpmnProcessInstanceServiceImpl implements BpmnProcessInstanceServic
|
|||||||
.list();
|
.list();
|
||||||
return !CollectionUtils.isEmpty(list);
|
return !CollectionUtils.isEmpty(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BpmnProcessInstanceLogVO getProcessInstanceLog(BpmnProcessInstanceLogQueryDTO dto) {
|
||||||
|
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
|
||||||
|
.processInstanceId(dto.getProcessInstanceId())
|
||||||
|
.includeProcessVariables().singleResult();
|
||||||
|
if (Objects.isNull(historicProcessInstance)) {
|
||||||
|
throw new WorkflowEngineException(PROCESS_INSTANCE_ID_NOT_EXISTS, dto.getProcessInstanceId());
|
||||||
|
}
|
||||||
|
|
||||||
|
ExtAxProcessLog query = new ExtAxProcessLog();
|
||||||
|
query.setProcessInstanceId(dto.getProcessInstanceId());
|
||||||
|
List<ExtAxProcessLog> logs = processLogService.genericQuery(query).stream()
|
||||||
|
.sorted(Comparator.comparing(ExtAxProcessLog::getEndTime, Comparator.nullsLast(Comparator.naturalOrder())))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
List<ProcessNodeDetailVO> forecasting = new ArrayList<>();
|
||||||
|
// 只有还在运行中的实例才需要推测后续节点
|
||||||
|
if (Objects.equals(historicProcessInstance.getBusinessStatus(), PROCESSING.getStatus())) {
|
||||||
|
ProcessInstance instance = runtimeService.createProcessInstanceQuery()
|
||||||
|
.processInstanceId(dto.getProcessInstanceId())
|
||||||
|
.includeProcessVariables()
|
||||||
|
.singleResult();
|
||||||
|
logs.stream().reduce((f, s) -> s).ifPresent(e -> forecasting.addAll(
|
||||||
|
getProcessInstanceNodeForecastWithSpecifyTaskDefinitionKey(dto.getProcessInstanceId(), instance, e.getActivityId(), false, false))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId());
|
||||||
|
|
||||||
|
Map<String, Object> variables = historicProcessInstance.getProcessVariables();
|
||||||
|
BpmnProcessInstanceLogVO logVO = BpmnProcessInstanceLogVO.builder()
|
||||||
|
.id(historicProcessInstance.getId())
|
||||||
|
.name(historicProcessInstance.getName())
|
||||||
|
.result(BpmnProcessInstanceResultEnum.valueOfStatus(historicProcessInstance.getBusinessStatus()))
|
||||||
|
.startTime(historicProcessInstance.getStartTime())
|
||||||
|
.endTime(historicProcessInstance.getEndTime())
|
||||||
|
.processDefinitionKey(historicProcessInstance.getProcessDefinitionKey())
|
||||||
|
.processDefinitionId(historicProcessInstance.getProcessDefinitionId())
|
||||||
|
.businessKey(historicProcessInstance.getBusinessKey())
|
||||||
|
.businessStatus(historicProcessInstance.getBusinessStatus())
|
||||||
|
.initiator(BpmnTaskDelegateAssigner.toObjectCompatible(Optional.ofNullable(variables.getOrDefault(INTERNAL_INITIATOR, null))
|
||||||
|
.orElse(variables.getOrDefault(OLD_INTERNAL_INITIATOR, null))))
|
||||||
|
.tenantId(historicProcessInstance.getTenantId())
|
||||||
|
.agented((Boolean) Optional.ofNullable(variables.get(INTERNAL_PROCESS_AGENT)).orElse(false))
|
||||||
|
.taskDetails(genericTaskLogVos(historicProcessInstance.getId(), logs, forecasting, dto))
|
||||||
|
.defaultButtonConf(getButtonConfig(bpmnModel.getMainProcess()).orElse(new BpmnButtonConf()))
|
||||||
|
.supportBatchOperation(getProcessApproveConf(bpmnModel.getMainProcess()).orElse(new BpmnApproveConf()).getSupportBatchOperation())
|
||||||
|
.userAgreeSignature(getProcessApproveConf(bpmnModel.getMainProcess()).orElse(new BpmnApproveConf()).getUserAgreeSignature())
|
||||||
|
.workflowEngineVersion((String) variables.getOrDefault(WORKFLOW_ENGINE_VERSION, FLOW_SERVER_VERSION_121))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
|
categoryService.get(BPM_MODEL_CATEGORY, historicProcessInstance.getProcessDefinitionKey()).ifPresent(category -> {
|
||||||
|
logVO.setWorkspaceType(WorkspaceType.getType(Integer.valueOf(category.getWorkspaceTypeCode())));
|
||||||
|
logVO.setCategory(category.getValue());
|
||||||
|
});
|
||||||
|
|
||||||
|
// 根据传入的访问人计算有权限的按钮
|
||||||
|
calcAuthorizedButtons(logVO, dto.getVisitor());
|
||||||
|
return logVO;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void calcAuthorizedButtons(BpmnProcessInstanceLogVO logVO, BpmnTaskDelegateAssigner visitor) {
|
||||||
|
List<BpmnButtonMetaInfo> authorizedButtons = new ArrayList<>();
|
||||||
|
if (Objects.nonNull(logVO.getDefaultButtonConf())
|
||||||
|
&& !CollectionUtils.isEmpty(logVO.getDefaultButtonConf().getCarbonCopy())) {
|
||||||
|
authorizedButtons.addAll(logVO.getDefaultButtonConf().getCarbonCopy());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Objects.equals(PROCESSING, logVO.getResult()) && Objects.nonNull(visitor)) {
|
||||||
|
String ge130Assignee = getGe130Assignee(visitor);
|
||||||
|
String le130Assignee = getLe130Assignee(visitor);
|
||||||
|
|
||||||
|
// 运行到的当前节点的按钮配置
|
||||||
|
logVO.getTaskDetails().stream()
|
||||||
|
.filter(i -> Objects.equals(PROCESSING, i.getResult()))
|
||||||
|
.findFirst()
|
||||||
|
.ifPresent(i -> logVO.setCalculatingButtonConf(i.getButtonConf()));
|
||||||
|
|
||||||
|
|
||||||
|
// 比对发起人
|
||||||
|
if (Objects.nonNull(logVO.getInitiator()) &&
|
||||||
|
(Objects.equals(logVO.getInitiator().buildAssigneeId_1_2_1(), le130Assignee)
|
||||||
|
|| logVO.getInitiator().buildAssigneeId().contains(ge130Assignee))) {
|
||||||
|
authorizedButtons.addAll(chooseButtons(logVO, CONFIG_BUTTON_TYPE_INITIATOR));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 比对当前审批人
|
||||||
|
logVO.getTaskDetails().stream().filter(i -> Objects.equals(PROCESSING, i.getResult())
|
||||||
|
|| (Objects.equals(DELETED, i.getResult()) && Objects.isNull(i.getEndTime())))
|
||||||
|
.findFirst()
|
||||||
|
.map(i -> {
|
||||||
|
List<BpmnTaskDelegateAssigner> list = new ArrayList<>();
|
||||||
|
if (Objects.nonNull(i.getAssigneeSnapshot())) {
|
||||||
|
list.add(i.getAssigneeSnapshot());
|
||||||
|
}
|
||||||
|
if (!CollectionUtils.isEmpty(i.getForecastAssignees())) {
|
||||||
|
list.addAll(i.getForecastAssignees());
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
})
|
||||||
|
.orElse(Collections.emptyList())
|
||||||
|
.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.filter(i -> i.buildAssigneeId().contains(ge130Assignee) || Objects.equals(i.buildAssigneeId_1_2_1(), le130Assignee))
|
||||||
|
.findAny()
|
||||||
|
.ifPresent(i -> authorizedButtons.addAll(chooseButtons(logVO, CONFIG_BUTTON_TYPE_CURRENT)));
|
||||||
|
|
||||||
|
|
||||||
|
// 比对历史审批人
|
||||||
|
logVO.getTaskDetails().stream()
|
||||||
|
.filter(i -> Objects.equals(i.getNodeType(), NODE_TASK) || Objects.equals(i.getNodeType(), NODE_BUSINESS))
|
||||||
|
.filter(i -> !Objects.equals(PROCESSING, i.getResult()))
|
||||||
|
.map(BpmnTaskInstanceLogVO::getAssigneeSnapshot)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.filter(i -> i.buildAssigneeId().contains(ge130Assignee) || Objects.equals(i.buildAssigneeId_1_2_1(), le130Assignee))
|
||||||
|
.findAny()
|
||||||
|
.ifPresent(i -> authorizedButtons.addAll(chooseButtons(logVO, CONFIG_BUTTON_TYPE_HISTORY)));
|
||||||
|
|
||||||
|
// 比对抄送人
|
||||||
|
logVO.getTaskDetails().stream()
|
||||||
|
.filter(i -> Objects.equals(i.getNodeType(), NODE_CARBON_COPY))
|
||||||
|
.flatMap(i -> ListUtils.emptyIfNull(i.getForecastAssignees()).stream())
|
||||||
|
.filter(i -> i.buildAssigneeId().contains(ge130Assignee) || Objects.equals(i.buildAssigneeId_1_2_1(), le130Assignee))
|
||||||
|
.findAny()
|
||||||
|
.ifPresent(i -> authorizedButtons.addAll(chooseButtons(logVO, CONFIG_BUTTON_TYPE_CARBON_COPY)));
|
||||||
|
}
|
||||||
|
|
||||||
|
logVO.setCurrentUserButtons(authorizedButtons);
|
||||||
|
// 有权限访问的自定义按钮
|
||||||
|
List<String> customButtonKeys = authorizedButtons.stream()
|
||||||
|
.filter(i -> Objects.equals(i.getType(), "CUSTOM"))
|
||||||
|
.map(BpmnButtonMetaInfo::getBtnKey)
|
||||||
|
.distinct().collect(Collectors.toList());
|
||||||
|
List<BpmnButtonMetaInfo> customButtons = logVO.getDefaultButtonConf().getInitiator().stream()
|
||||||
|
.filter(i -> Objects.equals(i.getType(), "CUSTOM"))
|
||||||
|
.filter(i -> !customButtonKeys.contains(i.getBtnKey()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
logVO.setCustomHiddenButtons(customButtons);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按钮的通用处理, 有限使用节点的按钮配置,如果没有则按兜底按钮配置
|
||||||
|
*
|
||||||
|
* @param logVO 该对象中的 calcButtonConf 字段为当前节点的按钮配置
|
||||||
|
* @param buttonConfigName String CONFIG_BUTTON_TYPE_INITIATOR = "initiator";
|
||||||
|
* String CONFIG_BUTTON_TYPE_CURRENT = "current";
|
||||||
|
* String CONFIG_BUTTON_TYPE_HISTORY = "history";
|
||||||
|
* String CONFIG_BUTTON_TYPE_CARBON_COPY = "carbonCopy";
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private List<BpmnButtonMetaInfo> chooseButtons(BpmnProcessInstanceLogVO logVO, String buttonConfigName) {
|
||||||
|
List<BpmnButtonMetaInfo> mergeButtons = new ArrayList<>();
|
||||||
|
if (Objects.isNull(logVO.getCalculatingButtonConf())) {
|
||||||
|
BpmnButtonConf defaultButtonConf = logVO.getDefaultButtonConf();
|
||||||
|
if (Objects.isNull(defaultButtonConf)) {
|
||||||
|
return mergeButtons;
|
||||||
|
}
|
||||||
|
logVO.setCalculatingButtonConf(defaultButtonConf);
|
||||||
|
}
|
||||||
|
switch (buttonConfigName) {
|
||||||
|
case CONFIG_BUTTON_TYPE_INITIATOR:
|
||||||
|
mergeButtons.addAll(logVO.getCalculatingButtonConf().getInitiator());
|
||||||
|
break;
|
||||||
|
case CONFIG_BUTTON_TYPE_CURRENT:
|
||||||
|
mergeButtons.addAll(logVO.getCalculatingButtonConf().getCurrent());
|
||||||
|
break;
|
||||||
|
case CONFIG_BUTTON_TYPE_HISTORY:
|
||||||
|
mergeButtons.addAll(logVO.getCalculatingButtonConf().getHistory());
|
||||||
|
break;
|
||||||
|
case CONFIG_BUTTON_TYPE_CARBON_COPY:
|
||||||
|
mergeButtons.addAll(logVO.getCalculatingButtonConf().getCarbonCopy());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return mergeButtons;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getLe130Assignee(BpmnTaskDelegateAssigner visitor) {
|
||||||
|
return visitor.getTenantId() + "|" + visitor.getAssignee() + "|" + visitor.getAssigneeType();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getGe130Assignee(BpmnTaskDelegateAssigner visitor) {
|
||||||
|
// String ge130Assignee = contextInfo.getOuId() + "|" + contextInfo.getUserInfo().getPersonId();
|
||||||
|
// 130版本以上,产品要求仅校验 personId
|
||||||
|
return "|" + visitor.getPersonId();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<BpmnTaskInstanceLogVO> genericTaskLogVos(String processInstanceId,
|
||||||
|
List<ExtAxProcessLog> logs,
|
||||||
|
List<ProcessNodeDetailVO> forecasting,
|
||||||
|
BpmnProcessInstanceLogQueryDTO dto) {
|
||||||
|
List<BpmnTaskInstanceLogVO> tasks = new ArrayList<>();
|
||||||
|
Map<String, List<Attachment>> attachmentByTaskMap =
|
||||||
|
taskService.getProcessInstanceAttachments(processInstanceId).stream()
|
||||||
|
.collect(Collectors.groupingBy(Attachment::getTaskId));
|
||||||
|
// 已完成的和进行中的
|
||||||
|
getHistoricTasks(logs, tasks, attachmentByTaskMap, dto.getVisitor());
|
||||||
|
// 未来节点
|
||||||
|
getFutureTasks(forecasting, tasks);
|
||||||
|
// 处理是否加密
|
||||||
|
handleEncrypt(dto.getEncrypt(), tasks);
|
||||||
|
// reset field forecastAssignees Empty to null;
|
||||||
|
resetCollectionToNull(tasks);
|
||||||
|
return tasks;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetCollectionToNull(List<BpmnTaskInstanceLogVO> tasks) {
|
||||||
|
tasks.forEach(i -> {
|
||||||
|
if (ListUtils.emptyIfNull(i.getForecastAssignees()).isEmpty()) {
|
||||||
|
i.setForecastAssignees(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void handleEncrypt(Boolean encrypt, List<BpmnTaskInstanceLogVO> tasks) {
|
||||||
|
if (Boolean.FALSE.equals(encrypt)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tasks.forEach(i -> {
|
||||||
|
if (Objects.equals(NODE_STARTER.getType(), i.getTaskDefinitionKey())) {
|
||||||
|
i.setOperationDesc(i.getAssigneeSnapshot().getAssignerName());
|
||||||
|
} else if (Objects.equals(i.getResult(), APPROVED)) {
|
||||||
|
i.setOperationDesc(APPROVED.getDesc());
|
||||||
|
} else if (Objects.equals(i.getResult(), REJECTED)) {
|
||||||
|
i.setOperationDesc(REJECTED.getDesc());
|
||||||
|
} else if (Objects.equals(i.getResult(), PROCESSING) || Objects.isNull(i.getTaskId())) {
|
||||||
|
i.setOperationDesc("待处理");
|
||||||
|
} else {
|
||||||
|
i.setOperationDesc("已处理");
|
||||||
|
}
|
||||||
|
// 统一将多人节点数据全部置空
|
||||||
|
i.setForecastAssignees(null);
|
||||||
|
// 统一将签名数据置空
|
||||||
|
i.setSignatureUrl(null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void getFutureTasks(List<ProcessNodeDetailVO> forecasting, List<BpmnTaskInstanceLogVO> tasks) {
|
||||||
|
ListUtils.emptyIfNull(forecasting).forEach(e -> {
|
||||||
|
BpmnTaskInstanceLogVO build = BpmnTaskInstanceLogVO.builder()
|
||||||
|
.taskDefinitionKey(e.getId())
|
||||||
|
.name(e.getName())
|
||||||
|
.approvalMethod(e.getApprovalMethod())
|
||||||
|
.nodeType(e.getNodeType())
|
||||||
|
.nodeMode(e.getNodeMode())
|
||||||
|
.forecastAssignees(e.getForecastAssigners())
|
||||||
|
.build();
|
||||||
|
if (Objects.nonNull(e.getApprovalMethod())) {
|
||||||
|
switch (e.getApprovalMethod()) {
|
||||||
|
case bizSpecify:
|
||||||
|
case nobody:
|
||||||
|
build.setOperationDesc("待处理");
|
||||||
|
break;
|
||||||
|
case autoPassed:
|
||||||
|
case autoRejection:
|
||||||
|
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 + "人会签,需要全部同意");
|
||||||
|
} else if (Objects.equals(BpmnFlowNodeMode.OR, e.getNodeMode())) {
|
||||||
|
build.setOperationDesc(countPerson + "人或签,仅一人同意即可");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Objects.equals(e.getNodeType(), NODE_CARBON_COPY)) {
|
||||||
|
build.setOperationDesc("抄送" + e.getForecastAssigners().size() + "人");
|
||||||
|
}
|
||||||
|
tasks.add(build);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getHistoricTasks(List<ExtAxProcessLog> logs,
|
||||||
|
List<BpmnTaskInstanceLogVO> tasks,
|
||||||
|
Map<String, List<Attachment>> attachmentByTaskMap,
|
||||||
|
BpmnTaskDelegateAssigner visitor) {
|
||||||
|
ListUtils.emptyIfNull(logs).forEach(e -> {
|
||||||
|
Optional<BpmnTaskInstanceLogVO> processingTask = tasks.stream().filter(i -> Objects.equals(PROCESSING, i.getResult()))
|
||||||
|
.filter(i -> Objects.equals(i.getTaskDefinitionKey(), e.getActivityId())).findAny();
|
||||||
|
|
||||||
|
if (processingTask.isPresent()) {
|
||||||
|
// 多实例的情况,需要合并节点
|
||||||
|
processingTask.ifPresent(i -> {
|
||||||
|
List<BpmnTaskDelegateAssigner> assigners = new ArrayList<>(ListUtils.emptyIfNull(i.getForecastAssignees()));
|
||||||
|
if (CollectionUtils.isEmpty(assigners)) {
|
||||||
|
if (Objects.nonNull(i.getAssigneeSnapshot())) {
|
||||||
|
assigners.add(i.getAssigneeSnapshot());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assigners.add(BpmnTaskDelegateAssigner.toObjectCompatible(CollectionUtils.isEmpty(ListUtils.emptyIfNull(e.getAssigneeFull())) ? null : e.getAssigneeFull().get(0)));
|
||||||
|
switch (i.getNodeMode()) {
|
||||||
|
case AND:
|
||||||
|
i.setOperationDesc(assigners.size() + "人会签,需要全部同意");
|
||||||
|
break;
|
||||||
|
case OR:
|
||||||
|
i.setOperationDesc(assigners.size() + "人或签,仅一人同意即可");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// 不修改操作描述
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i.setAssigneeSnapshot(null);
|
||||||
|
i.setForecastAssignees(assigners);
|
||||||
|
i.setButtonConf(e.getButtonConf());
|
||||||
|
// 根据当前登录人重设聚合后的节点 taskId
|
||||||
|
assigners.stream().filter(user -> Objects.equals(user.getPersonId(), visitor.getPersonId())).findFirst()
|
||||||
|
.ifPresent(user -> i.setTaskId(e.getTaskId()));
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
tasks.add(BpmnTaskInstanceLogVO.builder()
|
||||||
|
.taskId(e.getTaskId())
|
||||||
|
.taskDefinitionKey(e.getActivityId())
|
||||||
|
.name(e.getActivityName())
|
||||||
|
.createTime(e.getStartTime())
|
||||||
|
.endTime(e.getEndTime())
|
||||||
|
.approvalMethod(ApprovalMethodEnum.valueOfType(e.getApprovalMethod()))
|
||||||
|
.nodeType(BpmnFlowNodeType.valueOfType(e.getNodeType()))
|
||||||
|
.nodeMode(BpmnFlowNodeMode.valueOfType(e.getNodeMode()))
|
||||||
|
.result(BpmnProcessInstanceResultEnum.valueOfStatus(e.getStatus()))
|
||||||
|
.operationDesc(e.getOperationDesc())
|
||||||
|
.advice(e.getAdvice())
|
||||||
|
.commentExt("")
|
||||||
|
.buttonConf(e.getButtonConf())
|
||||||
|
.imageList(getAttachmentByType(attachmentByTaskMap, e.getTaskId(), AttachmentTypeEnum.image))
|
||||||
|
.fileList(getAttachmentByType(attachmentByTaskMap, e.getTaskId(), AttachmentTypeEnum.file))
|
||||||
|
.signatureUrl(getAttachmentByType(attachmentByTaskMap, e.getTaskId(), AttachmentTypeEnum.signature).stream().findFirst().orElse(new AttachmentDTO()).getUrl())
|
||||||
|
.assigneeSnapshot(Objects.equals(e.getNodeType(), BpmnFlowNodeType.NODE_CARBON_COPY.getType()) ? null :
|
||||||
|
BpmnTaskDelegateAssigner.toObjectCompatible(CollectionUtils.isEmpty(ListUtils.emptyIfNull(e.getAssigneeFull())) ? null : e.getAssigneeFull().get(0)))
|
||||||
|
.forecastAssignees(Objects.equals(e.getNodeType(), BpmnFlowNodeType.NODE_CARBON_COPY.getType()) ? ListUtils.emptyIfNull(e.getAssigneeFull()) : Collections.emptyList())
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AttachmentDTO> getAttachmentByType(Map<String, List<Attachment>> attachmentByTaskMap, String taskId, AttachmentTypeEnum type) {
|
||||||
|
return ListUtils.emptyIfNull(attachmentByTaskMap.get(taskId)).stream()
|
||||||
|
.filter(attachment -> Objects.equals(type.getType(), attachment.getType()))
|
||||||
|
.map(e -> AttachmentDTO.builder()
|
||||||
|
.id(e.getId())
|
||||||
|
.type(type)
|
||||||
|
.name(e.getName())
|
||||||
|
.description(e.getDescription())
|
||||||
|
.url(e.getUrl())
|
||||||
|
.build())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import org.flowable.engine.ManagementService;
|
|||||||
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
|
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
|
||||||
import org.flowable.job.api.Job;
|
import org.flowable.job.api.Job;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -39,6 +40,31 @@ public class BpmnProcessJobServiceImp implements BpmnProcessJobService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDeadLetterJobExceptionStacktrace(String processInstId) {
|
||||||
|
List<Job> jobs = managementService.createDeadLetterJobQuery().processInstanceId(processInstId).list();
|
||||||
|
if (CollectionUtils.isEmpty(jobs)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
jobs.forEach(job -> {
|
||||||
|
String deadLetterJobExceptionStacktrace = managementService.getDeadLetterJobExceptionStacktrace(job.getId());
|
||||||
|
if (StringUtils.hasText(deadLetterJobExceptionStacktrace)) {
|
||||||
|
builder.append(deadLetterJobExceptionStacktrace);
|
||||||
|
builder.append("\n");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDeadLetterJobExceptionStacktraceByJobId(String jobId) {
|
||||||
|
if (!StringUtils.hasText(jobId)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return managementService.getDeadLetterJobExceptionStacktrace(jobId);
|
||||||
|
}
|
||||||
|
|
||||||
protected Job getDeadLetterJobById(String jobId) {
|
protected Job getDeadLetterJobById(String jobId) {
|
||||||
Job job = managementService.createDeadLetterJobQuery().jobId(jobId).singleResult();
|
Job job = managementService.createDeadLetterJobQuery().jobId(jobId).singleResult();
|
||||||
if (job == null) {
|
if (job == null) {
|
||||||
|
|||||||
@ -1,11 +1,16 @@
|
|||||||
package cn.axzo.workflow.core.service.impl;
|
package cn.axzo.workflow.core.service.impl;
|
||||||
|
|
||||||
|
import cn.axzo.framework.domain.ServiceException;
|
||||||
import cn.axzo.workflow.common.enums.BpmnCountersignTypeEnum;
|
import cn.axzo.workflow.common.enums.BpmnCountersignTypeEnum;
|
||||||
|
import cn.axzo.workflow.common.enums.BpmnFlowNodeType;
|
||||||
|
import cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.BpmnNoticeConf;
|
import cn.axzo.workflow.common.model.request.bpmn.BpmnNoticeConf;
|
||||||
|
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.BpmnRobotTaskCompleteDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnRobotTaskCreateDTO;
|
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.BpmnTaskAttachmentDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAuditDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAuditDTO;
|
||||||
|
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.BpmnTaskCommentDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskCountersignDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskCountersignDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||||
@ -25,6 +30,8 @@ import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
|||||||
import cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper;
|
import cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper;
|
||||||
import cn.axzo.workflow.core.engine.cmd.CustomApproveTaskAsyncCmd;
|
import cn.axzo.workflow.core.engine.cmd.CustomApproveTaskAsyncCmd;
|
||||||
import cn.axzo.workflow.core.engine.cmd.CustomApproveTaskCmd;
|
import cn.axzo.workflow.core.engine.cmd.CustomApproveTaskCmd;
|
||||||
|
import cn.axzo.workflow.core.engine.cmd.CustomBackTaskAsyncCmd;
|
||||||
|
import cn.axzo.workflow.core.engine.cmd.CustomBackTaskCmd;
|
||||||
import cn.axzo.workflow.core.engine.cmd.CustomCommentTaskCmd;
|
import cn.axzo.workflow.core.engine.cmd.CustomCommentTaskCmd;
|
||||||
import cn.axzo.workflow.core.engine.cmd.CustomCompleteDummyTaskCmd;
|
import cn.axzo.workflow.core.engine.cmd.CustomCompleteDummyTaskCmd;
|
||||||
import cn.axzo.workflow.core.engine.cmd.CustomCountersignUserTaskAsyncCmd;
|
import cn.axzo.workflow.core.engine.cmd.CustomCountersignUserTaskAsyncCmd;
|
||||||
@ -38,6 +45,7 @@ import cn.axzo.workflow.core.engine.event.MessagePushEventBuilder;
|
|||||||
import cn.axzo.workflow.core.engine.event.MessagePushEventImpl;
|
import cn.axzo.workflow.core.engine.event.MessagePushEventImpl;
|
||||||
import cn.axzo.workflow.core.engine.event.MessagePushEventType;
|
import cn.axzo.workflow.core.engine.event.MessagePushEventType;
|
||||||
import cn.axzo.workflow.core.repository.entity.ExtAxHiTaskInst;
|
import cn.axzo.workflow.core.repository.entity.ExtAxHiTaskInst;
|
||||||
|
import cn.axzo.workflow.core.service.BpmnProcessDefinitionService;
|
||||||
import cn.axzo.workflow.core.service.BpmnProcessTaskService;
|
import cn.axzo.workflow.core.service.BpmnProcessTaskService;
|
||||||
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
|
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
|
||||||
import cn.axzo.workflow.core.service.converter.BpmnHistoricAttachmentConverter;
|
import cn.axzo.workflow.core.service.converter.BpmnHistoricAttachmentConverter;
|
||||||
@ -48,7 +56,11 @@ import cn.axzo.workflow.core.service.converter.BpmnTaskTodoPageItemConverter;
|
|||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
import org.flowable.bpmn.model.BaseElement;
|
||||||
import org.flowable.bpmn.model.BpmnModel;
|
import org.flowable.bpmn.model.BpmnModel;
|
||||||
|
import org.flowable.bpmn.model.FlowElement;
|
||||||
import org.flowable.common.engine.api.delegate.event.FlowableEventDispatcher;
|
import org.flowable.common.engine.api.delegate.event.FlowableEventDispatcher;
|
||||||
import org.flowable.common.engine.impl.identity.Authentication;
|
import org.flowable.common.engine.impl.identity.Authentication;
|
||||||
import org.flowable.common.engine.impl.interceptor.CommandExecutor;
|
import org.flowable.common.engine.impl.interceptor.CommandExecutor;
|
||||||
@ -80,7 +92,6 @@ import org.flowable.variable.service.impl.persistence.entity.HistoricVariableIns
|
|||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.util.CollectionUtils;
|
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
@ -89,11 +100,13 @@ import java.util.Arrays;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@ -103,16 +116,27 @@ import static cn.axzo.workflow.common.constant.BpmnConstants.COMMENT_TYPE_COMMEN
|
|||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.COMMENT_TYPE_OPERATION_DESC;
|
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_ACTIVITY_RELATION_ASSIGNEE_LIST_INFO_SNAPSHOT;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_TASK_RELATION_ASSIGNEE_INFO;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_TASK_RELATION_ASSIGNEE_INFO;
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.MAX_BACKED_OPERATE_COUNT;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.NO_ASSIGNEE;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.NO_ASSIGNEE;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.OLD_INTERNAL_TASK_RELATION_ASSIGNEE_INFO_SNAPSHOT;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.OLD_INTERNAL_TASK_RELATION_ASSIGNEE_INFO_SNAPSHOT;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.WORKFLOW_ENGINE_VERSION;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.WORKFLOW_ENGINE_VERSION;
|
||||||
|
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_BUSINESS;
|
||||||
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_CARBON_COPY;
|
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_CARBON_COPY;
|
||||||
|
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_EMPTY;
|
||||||
|
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_STARTER;
|
||||||
|
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_TASK;
|
||||||
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.APPROVED;
|
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.APPROVED;
|
||||||
|
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.BACKED;
|
||||||
|
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.DELETED;
|
||||||
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.PROCESSING;
|
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.PROCESSING;
|
||||||
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.REJECTED;
|
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.REJECTED;
|
||||||
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.valueOfStatus;
|
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.valueOfStatus;
|
||||||
import static cn.axzo.workflow.core.common.code.BpmnInstanceRespCode.PROCESS_INSTANCE_ID_NOT_EXISTS;
|
import static cn.axzo.workflow.core.common.code.BpmnInstanceRespCode.PROCESS_INSTANCE_ID_NOT_EXISTS;
|
||||||
|
import static cn.axzo.workflow.core.common.code.BpmnInstanceRespCode.PROCESS_INSTANCE_NOT_EXISTS;
|
||||||
|
import static cn.axzo.workflow.core.common.code.BpmnInstanceRespCode.PROCESS_TASK_NOT_EXISTS;
|
||||||
|
import static cn.axzo.workflow.core.common.code.BpmnTaskRespCode.BACK_NODE_CANNOT_REACHABLE;
|
||||||
import static cn.axzo.workflow.core.common.code.BpmnTaskRespCode.FIND_TASK_BY_PERSON_ID_ERROR;
|
import static cn.axzo.workflow.core.common.code.BpmnTaskRespCode.FIND_TASK_BY_PERSON_ID_ERROR;
|
||||||
|
import static cn.axzo.workflow.core.common.code.BpmnTaskRespCode.REACHED_BACKED_MAXIMUM_NUM;
|
||||||
import static cn.axzo.workflow.core.common.code.BpmnTaskRespCode.TASK_REMIND_ERROR_NOT_EXISTS;
|
import static cn.axzo.workflow.core.common.code.BpmnTaskRespCode.TASK_REMIND_ERROR_NOT_EXISTS;
|
||||||
import static cn.axzo.workflow.core.common.utils.BpmnCollectionUtils.convertSet;
|
import static cn.axzo.workflow.core.common.utils.BpmnCollectionUtils.convertSet;
|
||||||
import static cn.axzo.workflow.core.common.utils.BpmnNativeQueryUtil.countSql;
|
import static cn.axzo.workflow.core.common.utils.BpmnNativeQueryUtil.countSql;
|
||||||
@ -151,6 +175,8 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService {
|
|||||||
@Resource
|
@Resource
|
||||||
@Lazy
|
@Lazy
|
||||||
private BpmnProcessTaskService bpmnProcessTaskService;
|
private BpmnProcessTaskService bpmnProcessTaskService;
|
||||||
|
@Resource
|
||||||
|
private BpmnProcessDefinitionService bpmnProcessModelService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BpmPageResult<BpmnTaskTodoPageItemVO> getTodoTaskPage(BpmnTaskPageSearchDTO dto) {
|
public BpmPageResult<BpmnTaskTodoPageItemVO> getTodoTaskPage(BpmnTaskPageSearchDTO dto) {
|
||||||
@ -158,8 +184,8 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService {
|
|||||||
Long resultTotalCount;
|
Long resultTotalCount;
|
||||||
if (CollectionUtils.isEmpty(dto.getResults())) {
|
if (CollectionUtils.isEmpty(dto.getResults())) {
|
||||||
HistoricTaskInstanceQuery query =
|
HistoricTaskInstanceQuery query =
|
||||||
historyService.createHistoricTaskInstanceQuery().unfinished().taskAssignee(dto.getUserId()) // 分配给自己
|
historyService.createHistoricTaskInstanceQuery().unfinished().taskAssignee(dto.getUserId()) // 分配给自己
|
||||||
.orderByTaskCreateTime().desc();
|
.orderByTaskCreateTime().desc();
|
||||||
populateQuery(dto, query);
|
populateQuery(dto, query);
|
||||||
tasks = query.listPage((dto.getPageNo() - 1) * dto.getPageSize(), dto.getPageSize());
|
tasks = query.listPage((dto.getPageNo() - 1) * dto.getPageSize(), dto.getPageSize());
|
||||||
resultTotalCount = query.count();
|
resultTotalCount = query.count();
|
||||||
@ -178,7 +204,7 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService {
|
|||||||
|
|
||||||
// 获得 ProcessInstance Map
|
// 获得 ProcessInstance Map
|
||||||
Map<String, ProcessInstance> processInstanceMap =
|
Map<String, ProcessInstance> processInstanceMap =
|
||||||
processInstanceService.getProcessInstanceMap(processInstanceIds);
|
processInstanceService.getProcessInstanceMap(processInstanceIds);
|
||||||
|
|
||||||
List<BpmnTaskTodoPageItemVO> vos = todoPageItemConverter.toVos(tasks, processInstanceMap);
|
List<BpmnTaskTodoPageItemVO> vos = todoPageItemConverter.toVos(tasks, processInstanceMap);
|
||||||
return new BpmPageResult<>(vos, resultTotalCount);
|
return new BpmPageResult<>(vos, resultTotalCount);
|
||||||
@ -192,8 +218,8 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService {
|
|||||||
if (CollectionUtils.isEmpty(dto.getResults())) {
|
if (CollectionUtils.isEmpty(dto.getResults())) {
|
||||||
// 查询已办任务
|
// 查询已办任务
|
||||||
HistoricTaskInstanceQuery query = historyService.createHistoricTaskInstanceQuery().finished() // 已完成
|
HistoricTaskInstanceQuery query = historyService.createHistoricTaskInstanceQuery().finished() // 已完成
|
||||||
.taskAssignee(dto.getUserId()) // 分配给自己
|
.taskAssignee(dto.getUserId()) // 分配给自己
|
||||||
.orderByHistoricTaskInstanceEndTime().desc(); // 审批时间倒序
|
.orderByHistoricTaskInstanceEndTime().desc(); // 审批时间倒序
|
||||||
populateQuery(dto, query);
|
populateQuery(dto, query);
|
||||||
// 执行查询
|
// 执行查询
|
||||||
tasks = query.listPage((dto.getPageNo() - 1) * dto.getPageSize(), dto.getPageSize());
|
tasks = query.listPage((dto.getPageNo() - 1) * dto.getPageSize(), dto.getPageSize());
|
||||||
@ -210,7 +236,7 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService {
|
|||||||
}
|
}
|
||||||
Set<String> processInstanceIds = convertSet(tasks, HistoricTaskInstance::getProcessInstanceId);
|
Set<String> processInstanceIds = convertSet(tasks, HistoricTaskInstance::getProcessInstanceId);
|
||||||
Map<String, HistoricProcessInstance> historicProcessInstanceMap =
|
Map<String, HistoricProcessInstance> historicProcessInstanceMap =
|
||||||
processInstanceService.getHistoricProcessInstanceMap(processInstanceIds);
|
processInstanceService.getHistoricProcessInstanceMap(processInstanceIds);
|
||||||
List<BpmnTaskDonePageItemVO> vos = donePageItemConverter.toVos(tasks, historicProcessInstanceMap);
|
List<BpmnTaskDonePageItemVO> vos = donePageItemConverter.toVos(tasks, historicProcessInstanceMap);
|
||||||
return new BpmPageResult<>(vos, resultTotalCount);
|
return new BpmPageResult<>(vos, resultTotalCount);
|
||||||
}
|
}
|
||||||
@ -234,7 +260,7 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService {
|
|||||||
NativeHistoricTaskInstanceQuery nativeQuery = historyService.createNativeHistoricTaskInstanceQuery();
|
NativeHistoricTaskInstanceQuery nativeQuery = historyService.createNativeHistoricTaskInstanceQuery();
|
||||||
String tableName = managementService.getTableName(HistoricTaskInstance.class);
|
String tableName = managementService.getTableName(HistoricTaskInstance.class);
|
||||||
baseQuerySql.append("SELECT a.* FROM ").append(tableName).append(" a JOIN " + "ACT_HI_PROCINST b").append(" " +
|
baseQuerySql.append("SELECT a.* FROM ").append(tableName).append(" a JOIN " + "ACT_HI_PROCINST b").append(" " +
|
||||||
"ON b.PROC_INST_ID_ = a.PROC_INST_ID_");
|
"ON b.PROC_INST_ID_ = a.PROC_INST_ID_");
|
||||||
|
|
||||||
if (Objects.nonNull(dto.getTenantId())) {
|
if (Objects.nonNull(dto.getTenantId())) {
|
||||||
baseQuerySql.append(sqlConnectors(baseQuerySql)).append(" b.TENANT_ID_ = #{tenantId}").append(sqlConnectors(baseQuerySql)).append(" a.TENANT_ID_ = #{tenantId}");
|
baseQuerySql.append(sqlConnectors(baseQuerySql)).append(" b.TENANT_ID_ = #{tenantId}").append(sqlConnectors(baseQuerySql)).append(" a.TENANT_ID_ = #{tenantId}");
|
||||||
@ -253,7 +279,7 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService {
|
|||||||
}
|
}
|
||||||
if (StringUtils.hasLength(dto.getCategories())) {
|
if (StringUtils.hasLength(dto.getCategories())) {
|
||||||
List<String> categories =
|
List<String> categories =
|
||||||
Arrays.stream(dto.getCategories().split(",")).map(String::trim).collect(Collectors.toList());
|
Arrays.stream(dto.getCategories().split(",")).map(String::trim).collect(Collectors.toList());
|
||||||
baseQuerySql.append(sqlConnectors(baseQuerySql)).append(" a.CATEGORY_ in (");
|
baseQuerySql.append(sqlConnectors(baseQuerySql)).append(" a.CATEGORY_ in (");
|
||||||
for (int i = 0; i < categories.size(); i++) {
|
for (int i = 0; i < categories.size(); i++) {
|
||||||
baseQuerySql.append("#{category").append(i).append("}");
|
baseQuerySql.append("#{category").append(i).append("}");
|
||||||
@ -294,7 +320,7 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService {
|
|||||||
}
|
}
|
||||||
if (StringUtils.hasLength(dto.getCategories())) {
|
if (StringUtils.hasLength(dto.getCategories())) {
|
||||||
List<String> categories =
|
List<String> categories =
|
||||||
Arrays.stream(dto.getCategories().split(",")).map(String::trim).collect(Collectors.toList());
|
Arrays.stream(dto.getCategories().split(",")).map(String::trim).collect(Collectors.toList());
|
||||||
query.processCategoryIn(categories);
|
query.processCategoryIn(categories);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -303,13 +329,140 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService {
|
|||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void approveTask(BpmnTaskAuditDTO dto) {
|
public void approveTask(BpmnTaskAuditDTO dto) {
|
||||||
CommandExecutor commandExecutor = processEngineConfiguration.getCommandExecutor();
|
CommandExecutor commandExecutor = processEngineConfiguration.getCommandExecutor();
|
||||||
if (dto.getAsync()) {
|
if (Boolean.TRUE.equals(dto.getAsync())) {
|
||||||
commandExecutor.execute(new CustomApproveTaskAsyncCmd(dto));
|
commandExecutor.execute(new CustomApproveTaskAsyncCmd(dto));
|
||||||
} else {
|
} else {
|
||||||
commandExecutor.execute(new CustomApproveTaskCmd(dto));
|
commandExecutor.execute(new CustomApproveTaskCmd(dto));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void backTask(BpmnTaskBackAuditDTO dto) {
|
||||||
|
List<BpmnOptionalNodeDTO> backOptionalNodes = getBackOptionalNodes(dto.getTaskId());
|
||||||
|
if (CollectionUtils.isEmpty(backOptionalNodes)) {
|
||||||
|
throw new WorkflowEngineException(BACK_NODE_CANNOT_REACHABLE, dto.getToActivityId());
|
||||||
|
}
|
||||||
|
List<String> activityList = backOptionalNodes.stream().map(BpmnOptionalNodeDTO::getProcessActivityId).collect(Collectors.toList());
|
||||||
|
if (!activityList.contains(dto.getToActivityId())) {
|
||||||
|
throw new WorkflowEngineException(BACK_NODE_CANNOT_REACHABLE, dto.getToActivityId());
|
||||||
|
}
|
||||||
|
Optional<String> instOpt = backOptionalNodes.stream()
|
||||||
|
.map(BpmnOptionalNodeDTO::getProcessInstanceId)
|
||||||
|
.filter(StringUtils::hasText)
|
||||||
|
.findAny();
|
||||||
|
if (instOpt.isPresent()) {
|
||||||
|
ExtHiTaskSearchDTO searchDTO = new ExtHiTaskSearchDTO();
|
||||||
|
searchDTO.setProcessInstanceId(instOpt.get());
|
||||||
|
List<ExtAxHiTaskInst> extAxHiTaskInsts = extAxHiTaskInstService.queryList(searchDTO);
|
||||||
|
if (CollectionUtils.isNotEmpty(extAxHiTaskInsts)) {
|
||||||
|
long backOpeCount = extAxHiTaskInsts.stream()
|
||||||
|
.filter(ext -> BACKED.getStatus().equals(ext.getStatus()))
|
||||||
|
.count();
|
||||||
|
if (backOpeCount > MAX_BACKED_OPERATE_COUNT) {
|
||||||
|
throw new WorkflowEngineException(REACHED_BACKED_MAXIMUM_NUM, String.valueOf(MAX_BACKED_OPERATE_COUNT));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CommandExecutor commandExecutor = processEngineConfiguration.getCommandExecutor();
|
||||||
|
if (Boolean.TRUE.equals(dto.getAsync())) {
|
||||||
|
commandExecutor.execute(new CustomBackTaskAsyncCmd(dto));
|
||||||
|
} else {
|
||||||
|
commandExecutor.execute(new CustomBackTaskCmd(dto));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<BpmnOptionalNodeDTO> getBackOptionalNodes(String taskId) {
|
||||||
|
Task task = processEngineConfiguration.getTaskService().createTaskQuery().taskId(taskId).singleResult();
|
||||||
|
if (task == null) {
|
||||||
|
throw new WorkflowEngineException(PROCESS_TASK_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
String processInstanceId = task.getProcessInstanceId();
|
||||||
|
//1.获取当前的流程实例
|
||||||
|
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
|
||||||
|
if (processInstance == null) {
|
||||||
|
//流程为空,已经结束,返回空
|
||||||
|
throw new WorkflowEngineException(PROCESS_INSTANCE_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
List<BpmnHistoricTaskInstanceVO> tasks = this.getHistoricTaskListByProcessInstanceId(processInstanceId, null);
|
||||||
|
tasks = tasks.stream()
|
||||||
|
.filter(t -> t.getNodeType() == NODE_STARTER || t.getNodeType() == NODE_TASK || t.getNodeType() == NODE_BUSINESS)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (CollectionUtils.isEmpty(tasks)) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
tasks.sort(Comparator.comparing(BpmnHistoricTaskInstanceVO::getCreateTime));
|
||||||
|
LinkedList<Pair<String, List<BpmnHistoricTaskInstanceVO>>> executedList = new LinkedList<>();
|
||||||
|
for (BpmnHistoricTaskInstanceVO vo : tasks) {
|
||||||
|
Pair<String, List<BpmnHistoricTaskInstanceVO>> last = org.springframework.util.CollectionUtils.isEmpty(executedList) ? null : executedList.getLast();
|
||||||
|
if (last != null && last.getLeft().equals(vo.getTaskDefinitionKey())) {
|
||||||
|
last.getRight().add(vo);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ArrayList<BpmnHistoricTaskInstanceVO> objects = new ArrayList<>();
|
||||||
|
objects.add(vo);
|
||||||
|
executedList.addLast(Pair.of(vo.getTaskDefinitionKey(), objects));
|
||||||
|
}
|
||||||
|
List<Pair<String, List<BpmnHistoricTaskInstanceVO>>> valuableList = new LinkedList<>();
|
||||||
|
for (Pair<String, List<BpmnHistoricTaskInstanceVO>> pair : executedList) {
|
||||||
|
List<BpmnHistoricTaskInstanceVO> taskInstanceVOList = pair.getRight();
|
||||||
|
Optional<BpmnHistoricTaskInstanceVO> backTaskOpt = taskInstanceVOList
|
||||||
|
.stream()
|
||||||
|
.filter(t -> t.getResult() != null)
|
||||||
|
.filter(t -> t.getResult() == BpmnProcessInstanceResultEnum.BACKED)
|
||||||
|
.findFirst();
|
||||||
|
if (backTaskOpt.isPresent()) {
|
||||||
|
String deleteReason = backTaskOpt.get().getDeleteReason();
|
||||||
|
String changeParentActivityTo = deleteReason
|
||||||
|
.replace("Change parent activity to ", "")
|
||||||
|
.replace("Change activity to ", "");
|
||||||
|
if (org.springframework.util.CollectionUtils.isEmpty(valuableList)) {
|
||||||
|
throw new ServiceException("状态异常,首个节点进行了退回操作");
|
||||||
|
}
|
||||||
|
int j = valuableList.size() - 1;
|
||||||
|
for (; j >= 0; j--) {
|
||||||
|
Pair<String, List<BpmnHistoricTaskInstanceVO>> vPair = valuableList.get(j);
|
||||||
|
if (vPair.getLeft().equals(changeParentActivityTo)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
valuableList = valuableList.subList(0, j);
|
||||||
|
} else {
|
||||||
|
valuableList.add(pair);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<FlowElement> flowElements = bpmnProcessModelService.findFlowElements(processInstance.getProcessDefinitionId());
|
||||||
|
Map<String, FlowElement> flowElementMap = flowElements.stream().collect(Collectors.toMap(BaseElement::getId, f -> f));
|
||||||
|
AtomicInteger index = new AtomicInteger(0);
|
||||||
|
List<BpmnOptionalNodeDTO> resultList = valuableList
|
||||||
|
.stream()
|
||||||
|
.filter(pair -> !task.getTaskDefinitionKey().equals(pair.getLeft())) //排除当前节点
|
||||||
|
.map(pair -> flowElementMap.get(pair.getLeft()))
|
||||||
|
.filter(flowElement -> {
|
||||||
|
BpmnFlowNodeType currentNodeType = BpmnMetaParserHelper.getNodeType(flowElement).orElse(NODE_EMPTY);
|
||||||
|
return currentNodeType == NODE_TASK || currentNodeType == NODE_BUSINESS;
|
||||||
|
})
|
||||||
|
.filter(flowElement -> !NODE_STARTER.getType().equals(flowElement.getId()))
|
||||||
|
.map(flowElement -> BpmnOptionalNodeDTO
|
||||||
|
.builder()
|
||||||
|
.processInstanceId(task.getProcessInstanceId())
|
||||||
|
.processDefinitionId(task.getProcessDefinitionId())
|
||||||
|
.processActivityId(flowElement.getId())
|
||||||
|
.processActivityName(flowElement.getName())
|
||||||
|
.processNodeDesc(flowElement.getName())
|
||||||
|
.nodeType(BpmnMetaParserHelper.getNodeType(flowElement).orElse(NODE_EMPTY))
|
||||||
|
.ordinal(index.incrementAndGet())
|
||||||
|
.build())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (CollectionUtils.isNotEmpty(resultList)) {
|
||||||
|
BpmnOptionalNodeDTO bpmnOptionalNodeDTO = resultList.get(resultList.size() - 1);
|
||||||
|
bpmnOptionalNodeDTO.setProcessNodeDesc(bpmnOptionalNodeDTO.getProcessActivityName() + "(上一步)");
|
||||||
|
}
|
||||||
|
resultList.sort((o1, o2) -> o2.getOrdinal() - o1.getOrdinal());
|
||||||
|
return resultList;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BatchOperationResultVO batchApproveTask(List<BpmnTaskAuditDTO> dtos) {
|
public BatchOperationResultVO batchApproveTask(List<BpmnTaskAuditDTO> dtos) {
|
||||||
return batchOperation(dtos, bpmnProcessTaskService::approveTask);
|
return batchOperation(dtos, bpmnProcessTaskService::approveTask);
|
||||||
@ -335,13 +488,13 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService {
|
|||||||
public List<BpmnHistoricTaskInstanceVO> getHistoricTaskListByProcessInstanceId(String processInstanceId,
|
public List<BpmnHistoricTaskInstanceVO> getHistoricTaskListByProcessInstanceId(String processInstanceId,
|
||||||
String tenantId) {
|
String tenantId) {
|
||||||
HistoricTaskInstanceQuery query =
|
HistoricTaskInstanceQuery query =
|
||||||
historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId);
|
historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId);
|
||||||
if (StringUtils.hasLength(tenantId)) {
|
if (StringUtils.hasLength(tenantId)) {
|
||||||
query.taskTenantId(tenantId);
|
query.taskTenantId(tenantId);
|
||||||
}
|
}
|
||||||
HistoricProcessInstanceQuery instanceQuery =
|
HistoricProcessInstanceQuery instanceQuery =
|
||||||
historyService.createHistoricProcessInstanceQuery()
|
historyService.createHistoricProcessInstanceQuery()
|
||||||
.processInstanceId(processInstanceId);
|
.processInstanceId(processInstanceId);
|
||||||
// .includeProcessVariables();
|
// .includeProcessVariables();
|
||||||
if (StringUtils.hasLength(tenantId)) {
|
if (StringUtils.hasLength(tenantId)) {
|
||||||
instanceQuery.processInstanceTenantId(tenantId);
|
instanceQuery.processInstanceTenantId(tenantId);
|
||||||
@ -352,67 +505,72 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<HistoricTaskInstance> taskInstances = query.orderByHistoricTaskInstanceStartTime().desc() // 创建时间倒序
|
List<HistoricTaskInstance> taskInstances = query.orderByHistoricTaskInstanceStartTime().desc() // 创建时间倒序
|
||||||
.list();
|
.list();
|
||||||
taskInstances.forEach(task -> ((HistoricTaskInstanceEntity) task).setCreateTime(((HistoricTaskInstanceEntity) task).getLastUpdateTime()));
|
taskInstances.forEach(task -> ((HistoricTaskInstanceEntity) task).setCreateTime(((HistoricTaskInstanceEntity) task).getLastUpdateTime()));
|
||||||
taskInstances.sort(Comparator.comparing(p -> ((HistoricTaskInstanceEntity) p).getLastUpdateTime()));
|
taskInstances.sort(Comparator.comparing(p -> ((HistoricTaskInstanceEntity) p).getLastUpdateTime()));
|
||||||
|
|
||||||
Map<String, HistoricVariableInstance> variableInstanceMap =
|
Map<String, HistoricVariableInstance> variableInstanceMap =
|
||||||
// 不能使用框架提供的历史变量 API 查询,有 BUG
|
// 不能使用框架提供的历史变量 API 查询,有 BUG
|
||||||
historyService.createNativeHistoricVariableInstanceQuery()
|
historyService.createNativeHistoricVariableInstanceQuery()
|
||||||
.sql("select * from ACT_HI_VARINST t where t.proc_inst_id_= #{processInstanceId}")
|
.sql("select * from ACT_HI_VARINST t where t.proc_inst_id_= #{processInstanceId}")
|
||||||
.parameter("processInstanceId", processInstanceId)
|
.parameter("processInstanceId", processInstanceId)
|
||||||
.list().stream()
|
.list().stream()
|
||||||
.collect(Collectors.toMap(HistoricVariableInstance::getVariableName, Function.identity(),
|
.collect(Collectors.toMap(HistoricVariableInstance::getVariableName, Function.identity(),
|
||||||
(s, t) -> s));
|
(s, t) -> s));
|
||||||
HistoricVariableInstance instanceVersion = variableInstanceMap.getOrDefault(WORKFLOW_ENGINE_VERSION, null);
|
HistoricVariableInstance instanceVersion = variableInstanceMap.getOrDefault(WORKFLOW_ENGINE_VERSION, null);
|
||||||
// 过滤了多实例或签自动完成的任务
|
// 过滤了多实例或签自动完成的任务
|
||||||
List<BpmnHistoricTaskInstanceVO> vos = historicTaskInstanceConverter.toVosSkipSystemOperation(taskInstances,
|
List<BpmnHistoricTaskInstanceVO> vos = historicTaskInstanceConverter.toVosSkipSystemOperation(taskInstances,
|
||||||
Objects.isNull(instanceVersion) ? null :
|
Objects.isNull(instanceVersion) ? null :
|
||||||
((HistoricVariableInstanceEntityImpl) instanceVersion).getTextValue());
|
((HistoricVariableInstanceEntityImpl) instanceVersion).getTextValue());
|
||||||
Map<String, List<Comment>> commentByTaskIdMap =
|
Map<String, List<Comment>> commentByTaskIdMap =
|
||||||
taskService.getProcessInstanceComments(processInstanceId).stream()
|
taskService.getProcessInstanceComments(processInstanceId).stream()
|
||||||
.collect(Collectors.groupingBy(Comment::getTaskId));
|
.collect(Collectors.groupingBy(Comment::getTaskId));
|
||||||
|
|
||||||
Map<String, List<Attachment>> attachmentByTaskIdMap =
|
Map<String, List<Attachment>> attachmentByTaskIdMap =
|
||||||
taskService.getProcessInstanceAttachments(processInstanceId).stream()
|
taskService.getProcessInstanceAttachments(processInstanceId).stream()
|
||||||
.collect(Collectors.groupingBy(Attachment::getTaskId));
|
.collect(Collectors.groupingBy(Attachment::getTaskId));
|
||||||
|
|
||||||
ExtHiTaskSearchDTO searchDTO = new ExtHiTaskSearchDTO();
|
ExtHiTaskSearchDTO searchDTO = new ExtHiTaskSearchDTO();
|
||||||
searchDTO.setProcessInstanceId(processInstanceId);
|
searchDTO.setProcessInstanceId(processInstanceId);
|
||||||
Map<String, ExtAxHiTaskInst> extTaskInstMap = extAxHiTaskInstService.queryList(searchDTO).stream()
|
Map<String, ExtAxHiTaskInst> extTaskInstMap = extAxHiTaskInstService.queryList(searchDTO).stream()
|
||||||
.collect(Collectors.toMap(ExtAxHiTaskInst::getTaskId, Function.identity(), (s, t) -> s));
|
.collect(Collectors.toMap(ExtAxHiTaskInst::getTaskId, Function.identity(), (s, t) -> s));
|
||||||
|
|
||||||
BpmnModel bpmnModel = repositoryService.getBpmnModel(instance.getProcessDefinitionId());
|
BpmnModel bpmnModel = repositoryService.getBpmnModel(instance.getProcessDefinitionId());
|
||||||
|
List<BpmnHistoricTaskInstanceVO> resultList = new ArrayList<>();
|
||||||
for (BpmnHistoricTaskInstanceVO vo : vos) {
|
for (BpmnHistoricTaskInstanceVO vo : vos) {
|
||||||
ExtAxHiTaskInst taskInst = extTaskInstMap.getOrDefault(vo.getTaskId(), new ExtAxHiTaskInst());
|
ExtAxHiTaskInst taskInst = extTaskInstMap.getOrDefault(vo.getTaskId(), new ExtAxHiTaskInst());
|
||||||
|
if (Objects.equals(taskInst.getStatus(), DELETED.getStatus())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
resultList.add(vo);
|
||||||
vo.setResult(valueOfStatus(taskInst.getStatus()));
|
vo.setResult(valueOfStatus(taskInst.getStatus()));
|
||||||
List<Comment> taskComments = commentByTaskIdMap.getOrDefault(vo.getTaskId(), Collections.emptyList());
|
List<Comment> taskComments = commentByTaskIdMap.getOrDefault(vo.getTaskId(), Collections.emptyList());
|
||||||
|
|
||||||
// 处理 advice
|
// 处理 advice
|
||||||
taskComments.stream().filter(i -> Objects.equals(i.getTaskId(), vo.getTaskId()))
|
taskComments.stream().filter(i -> Objects.equals(i.getTaskId(), vo.getTaskId()))
|
||||||
.filter(i -> Objects.equals(i.getType(), COMMENT_TYPE_ADVICE)).findFirst()
|
.filter(i -> Objects.equals(i.getType(), COMMENT_TYPE_ADVICE)).findFirst()
|
||||||
.ifPresent(i -> vo.setAdvice(i.getFullMessage()));
|
.ifPresent(i -> vo.setAdvice(i.getFullMessage()));
|
||||||
|
|
||||||
// 处理 operationDesc
|
// 处理 operationDesc
|
||||||
taskComments.stream().filter(i -> Objects.equals(i.getTaskId(), vo.getTaskId()))
|
taskComments.stream().filter(i -> Objects.equals(i.getTaskId(), vo.getTaskId()))
|
||||||
.filter(i -> Objects.equals(COMMENT_TYPE_OPERATION_DESC, i.getType()))
|
.filter(i -> Objects.equals(COMMENT_TYPE_OPERATION_DESC, i.getType()))
|
||||||
.max(Comparator.comparing(Comment::getTime))
|
.max(Comparator.comparing(Comment::getTime))
|
||||||
.ifPresent(i -> vo.setOperationDesc(i.getFullMessage()));
|
.ifPresent(i -> vo.setOperationDesc(i.getFullMessage()));
|
||||||
|
|
||||||
// 处理 CommentExt
|
// 处理 CommentExt
|
||||||
taskComments.stream().filter(i -> Objects.equals(i.getTaskId(), vo.getTaskId()))
|
taskComments.stream().filter(i -> Objects.equals(i.getTaskId(), vo.getTaskId()))
|
||||||
.filter(i -> Objects.equals(i.getType(), COMMENT_TYPE_COMMENT_EXT)).findFirst()
|
.filter(i -> Objects.equals(i.getType(), COMMENT_TYPE_COMMENT_EXT)).findFirst()
|
||||||
.ifPresent(i -> vo.setCommentExt(i.getFullMessage()));
|
.ifPresent(i -> vo.setCommentExt(i.getFullMessage()));
|
||||||
|
|
||||||
List<Attachment> attachments = attachmentByTaskIdMap.getOrDefault(vo.getTaskId(), Collections.emptyList());
|
List<Attachment> attachments = attachmentByTaskIdMap.getOrDefault(vo.getTaskId(), Collections.emptyList());
|
||||||
vo.setAttachments(attachmentConverter.toVos(attachments));
|
vo.setAttachments(attachmentConverter.toVos(attachments));
|
||||||
|
|
||||||
HistoricVariableInstance assginerSnapshot =
|
HistoricVariableInstance assginerSnapshot =
|
||||||
variableInstanceMap.getOrDefault(INTERNAL_TASK_RELATION_ASSIGNEE_INFO + vo.getTaskId(),
|
variableInstanceMap.getOrDefault(INTERNAL_TASK_RELATION_ASSIGNEE_INFO + vo.getTaskId(),
|
||||||
null);
|
null);
|
||||||
if (Objects.isNull(assginerSnapshot)) {
|
if (Objects.isNull(assginerSnapshot)) {
|
||||||
assginerSnapshot =
|
assginerSnapshot =
|
||||||
variableInstanceMap.getOrDefault(OLD_INTERNAL_TASK_RELATION_ASSIGNEE_INFO_SNAPSHOT + vo.getTaskId(), null);
|
variableInstanceMap.getOrDefault(OLD_INTERNAL_TASK_RELATION_ASSIGNEE_INFO_SNAPSHOT + vo.getTaskId(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
BpmnTaskDelegateAssigner assigner = null;
|
BpmnTaskDelegateAssigner assigner = null;
|
||||||
@ -426,17 +584,17 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService {
|
|||||||
vo.setNodeType(nodeType);
|
vo.setNodeType(nodeType);
|
||||||
if (Objects.equals(NODE_CARBON_COPY, nodeType)) {
|
if (Objects.equals(NODE_CARBON_COPY, nodeType)) {
|
||||||
HistoricVariableInstance carbonUsers =
|
HistoricVariableInstance carbonUsers =
|
||||||
variableInstanceMap.getOrDefault(INTERNAL_ACTIVITY_RELATION_ASSIGNEE_LIST_INFO_SNAPSHOT + vo.getTaskDefinitionKey(), null);
|
variableInstanceMap.getOrDefault(INTERNAL_ACTIVITY_RELATION_ASSIGNEE_LIST_INFO_SNAPSHOT + vo.getTaskDefinitionKey(), null);
|
||||||
vo.setForecastAssignees(Objects.isNull(carbonUsers) ? Collections.emptyList() :
|
vo.setForecastAssignees(Objects.isNull(carbonUsers) ? Collections.emptyList() :
|
||||||
(List<BpmnTaskDelegateAssigner>) carbonUsers.getValue());
|
(List<BpmnTaskDelegateAssigner>) carbonUsers.getValue());
|
||||||
} else {
|
} else {
|
||||||
vo.setForecastAssignees(Collections.emptyList());
|
vo.setForecastAssignees(Collections.emptyList());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
BpmnMetaParserHelper.getApprovalMethod(bpmnModel.getFlowElement(vo.getTaskDefinitionKey()))
|
BpmnMetaParserHelper.getApprovalMethod(bpmnModel.getFlowElement(vo.getTaskDefinitionKey()))
|
||||||
.ifPresent(vo::setApprovalMethod);
|
.ifPresent(vo::setApprovalMethod);
|
||||||
}
|
}
|
||||||
return vos;
|
return resultList;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -448,11 +606,11 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<BpmnHistoricTaskInstanceGroupVO> getHistoricTaskListGroupByProcessInstanceId(String processInstanceId
|
public List<BpmnHistoricTaskInstanceGroupVO> getHistoricTaskListGroupByProcessInstanceId(String processInstanceId
|
||||||
, String tenantId) {
|
, String tenantId) {
|
||||||
List<BpmnHistoricTaskInstanceVO> vos = getHistoricTaskListByProcessInstanceId(processInstanceId, tenantId);
|
List<BpmnHistoricTaskInstanceVO> vos = getHistoricTaskListByProcessInstanceId(processInstanceId, tenantId);
|
||||||
|
|
||||||
Map<String, List<BpmnHistoricTaskInstanceVO>> voMapByTaskDefKey =
|
Map<String, List<BpmnHistoricTaskInstanceVO>> voMapByTaskDefKey =
|
||||||
vos.stream().collect(Collectors.groupingBy(BpmnHistoricTaskInstanceVO::getTaskDefinitionKey));
|
vos.stream().collect(Collectors.groupingBy(BpmnHistoricTaskInstanceVO::getTaskDefinitionKey));
|
||||||
|
|
||||||
List<BpmnHistoricTaskInstanceGroupVO> groupVos = new ArrayList<>();
|
List<BpmnHistoricTaskInstanceGroupVO> groupVos = new ArrayList<>();
|
||||||
for (Map.Entry<String, List<BpmnHistoricTaskInstanceVO>> entry : voMapByTaskDefKey.entrySet()) {
|
for (Map.Entry<String, List<BpmnHistoricTaskInstanceVO>> entry : voMapByTaskDefKey.entrySet()) {
|
||||||
@ -490,9 +648,9 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService {
|
|||||||
}
|
}
|
||||||
List<BpmnTaskInstanceVO> vos = bpmnTaskConverter.toVos(query.list());
|
List<BpmnTaskInstanceVO> vos = bpmnTaskConverter.toVos(query.list());
|
||||||
List<String> snapshotTaskIds =
|
List<String> snapshotTaskIds =
|
||||||
vos.stream().map(i -> INTERNAL_TASK_RELATION_ASSIGNEE_INFO + i.getTaskId()).collect(Collectors.toList());
|
vos.stream().map(i -> INTERNAL_TASK_RELATION_ASSIGNEE_INFO + i.getTaskId()).collect(Collectors.toList());
|
||||||
Map<String, VariableInstance> instanceMap = runtimeService.getVariableInstances(processInstanceId,
|
Map<String, VariableInstance> instanceMap = runtimeService.getVariableInstances(processInstanceId,
|
||||||
snapshotTaskIds);
|
snapshotTaskIds);
|
||||||
vos.forEach(i -> i.setAssigner(BpmnTaskDelegateAssigner.toObjectCompatible(instanceMap.get(INTERNAL_TASK_RELATION_ASSIGNEE_INFO + i.getTaskId()).getValue())));
|
vos.forEach(i -> i.setAssigner(BpmnTaskDelegateAssigner.toObjectCompatible(instanceMap.get(INTERNAL_TASK_RELATION_ASSIGNEE_INFO + i.getTaskId()).getValue())));
|
||||||
return vos;
|
return vos;
|
||||||
}
|
}
|
||||||
@ -526,7 +684,7 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService {
|
|||||||
commandExecutor.execute(new CustomTransferUserTaskAsyncCmd(dto));
|
commandExecutor.execute(new CustomTransferUserTaskAsyncCmd(dto));
|
||||||
} else {
|
} else {
|
||||||
commandExecutor.execute(new CustomTransferUserTaskCmd(dto.getTaskId(),
|
commandExecutor.execute(new CustomTransferUserTaskCmd(dto.getTaskId(),
|
||||||
dto.getOriginAssigner(), dto.getAdvice(), dto.getAttachmentList(), dto.getTargetAssigner()));
|
dto.getOriginAssigner(), dto.getAdvice(), dto.getAttachmentList(), dto.getTargetAssigner()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -568,8 +726,8 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService {
|
|||||||
public void commentTask(BpmnTaskCommentDTO dto) {
|
public void commentTask(BpmnTaskCommentDTO dto) {
|
||||||
CommandExecutor commandExecutor = processEngineConfiguration.getCommandExecutor();
|
CommandExecutor commandExecutor = processEngineConfiguration.getCommandExecutor();
|
||||||
commandExecutor.execute(new CustomCommentTaskCmd(dto.getProcessInstanceId(),
|
commandExecutor.execute(new CustomCommentTaskCmd(dto.getProcessInstanceId(),
|
||||||
dto.getOperator(), dto.getComment(), dto.getCommentExt(), dto.getAttachmentList(),
|
dto.getOperator(), dto.getComment(), dto.getCommentExt(), dto.getAttachmentList(),
|
||||||
extAxHiTaskInstService));
|
extAxHiTaskInstService));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -577,8 +735,8 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService {
|
|||||||
public void attachmentTask(BpmnTaskAttachmentDTO dto, String assignee) {
|
public void attachmentTask(BpmnTaskAttachmentDTO dto, String assignee) {
|
||||||
Authentication.setAuthenticatedUserId(assignee);
|
Authentication.setAuthenticatedUserId(assignee);
|
||||||
Attachment attachment = taskService.createAttachment(dto.getType(), dto.getTaskId(),
|
Attachment attachment = taskService.createAttachment(dto.getType(), dto.getTaskId(),
|
||||||
dto.getProcessInstanceId(), dto.getName(), dto.getDescription(),
|
dto.getProcessInstanceId(), dto.getName(), dto.getDescription(),
|
||||||
dto.getUrl());
|
dto.getUrl());
|
||||||
taskService.saveAttachment(attachment);
|
taskService.saveAttachment(attachment);
|
||||||
Authentication.setAuthenticatedUserId(null);
|
Authentication.setAuthenticatedUserId(null);
|
||||||
}
|
}
|
||||||
@ -592,8 +750,8 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService {
|
|||||||
commandExecutor.execute(new CustomCountersignUserTaskAsyncCmd(dto));
|
commandExecutor.execute(new CustomCountersignUserTaskAsyncCmd(dto));
|
||||||
} else {
|
} else {
|
||||||
commandExecutor.execute(new CustomCountersignUserTaskCmd(BpmnCountersignTypeEnum.valueOfType(dto.getCountersignType()), dto.getTaskId(),
|
commandExecutor.execute(new CustomCountersignUserTaskCmd(BpmnCountersignTypeEnum.valueOfType(dto.getCountersignType()), dto.getTaskId(),
|
||||||
dto.getOriginAssigner(), dto.getAdvice(), dto.getAttachmentList(), dto.getTargetAssignerList(),
|
dto.getOriginAssigner(), dto.getAdvice(), dto.getAttachmentList(), dto.getTargetAssignerList(),
|
||||||
extAxHiTaskInstService));
|
extAxHiTaskInstService));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -614,22 +772,22 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService {
|
|||||||
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();
|
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();
|
||||||
FlowableEventDispatcher eventDispatcher = processEngineConfiguration.getEventDispatcher();
|
FlowableEventDispatcher eventDispatcher = processEngineConfiguration.getEventDispatcher();
|
||||||
ProcessInstance processInstance =
|
ProcessInstance processInstance =
|
||||||
runtimeService.createProcessInstanceQuery().processInstanceId(dto.getProcessInstanceId()).singleResult();
|
runtimeService.createProcessInstanceQuery().processInstanceId(dto.getProcessInstanceId()).singleResult();
|
||||||
Optional<BpmnNoticeConf> noticeConfig =
|
Optional<BpmnNoticeConf> noticeConfig =
|
||||||
BpmnMetaParserHelper.getNoticeConfig(ProcessDefinitionUtil.getProcess(processInstance.getProcessDefinitionId()));
|
BpmnMetaParserHelper.getNoticeConfig(ProcessDefinitionUtil.getProcess(processInstance.getProcessDefinitionId()));
|
||||||
List<BpmnTaskDelegateAssigner> assigners =
|
List<BpmnTaskDelegateAssigner> assigners =
|
||||||
(List<BpmnTaskDelegateAssigner>) runtimeService.getVariable(dto.getProcessInstanceId(),
|
(List<BpmnTaskDelegateAssigner>) runtimeService.getVariable(dto.getProcessInstanceId(),
|
||||||
INTERNAL_ACTIVITY_RELATION_ASSIGNEE_LIST_INFO_SNAPSHOT + dto.getTaskDefinitionKey());
|
INTERNAL_ACTIVITY_RELATION_ASSIGNEE_LIST_INFO_SNAPSHOT + dto.getTaskDefinitionKey());
|
||||||
|
|
||||||
// 过滤出未审批的任何,用选择的方式去发送消息
|
// 过滤出未审批的任何,用选择的方式去发送消息
|
||||||
dto.getRemindTypes().forEach(type -> {
|
dto.getRemindTypes().forEach(type -> {
|
||||||
list.forEach(task -> {
|
list.forEach(task -> {
|
||||||
assigners.stream().filter(i -> Objects.equals(task.getAssignee(), i.buildAssigneeId())).findAny().ifPresent(assigner -> {
|
assigners.stream().filter(i -> Objects.equals(task.getAssignee(), i.buildAssigneeId())).findAny().ifPresent(assigner -> {
|
||||||
MessagePushEventImpl event = MessagePushEventBuilder.createEvent(MessagePushEventType.valueOf(type),
|
MessagePushEventImpl event = MessagePushEventBuilder.createEvent(MessagePushEventType.valueOf(type),
|
||||||
Lists.newArrayList(assigner), noticeConfig.orElse(null),
|
Lists.newArrayList(assigner), noticeConfig.orElse(null),
|
||||||
processInstance.getProcessInstanceId(),
|
processInstance.getProcessInstanceId(),
|
||||||
processInstance.getProcessDefinitionKey(),
|
processInstance.getProcessDefinitionKey(),
|
||||||
processInstance.getTenantId(), task.getId());
|
processInstance.getTenantId(), task.getId());
|
||||||
event.setProcessInstanceId(processInstance.getProcessInstanceId());
|
event.setProcessInstanceId(processInstance.getProcessInstanceId());
|
||||||
event.setTenantId(processInstance.getTenantId());
|
event.setTenantId(processInstance.getTenantId());
|
||||||
event.setTaskId(task.getId());
|
event.setTaskId(task.getId());
|
||||||
@ -644,8 +802,8 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService {
|
|||||||
public String createRobotTask(BpmnRobotTaskCreateDTO dto) {
|
public String createRobotTask(BpmnRobotTaskCreateDTO dto) {
|
||||||
CommandExecutor commandExecutor = processEngineConfiguration.getCommandExecutor();
|
CommandExecutor commandExecutor = processEngineConfiguration.getCommandExecutor();
|
||||||
return commandExecutor.execute(new CustomCreateDummyTaskCmd(dto.getProcessInstanceId(),
|
return commandExecutor.execute(new CustomCreateDummyTaskCmd(dto.getProcessInstanceId(),
|
||||||
dto.getRobotNode().getFlowNodeName(), dto.getRobotNode().getOperationDesc(), dto.getApprover(),
|
dto.getRobotNode().getFlowNodeName(), dto.getRobotNode().getOperationDesc(), dto.getApprover(),
|
||||||
extAxHiTaskInstService));
|
extAxHiTaskInstService));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -653,17 +811,17 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService {
|
|||||||
public void completeRobotTask(BpmnRobotTaskCompleteDTO dto) {
|
public void completeRobotTask(BpmnRobotTaskCompleteDTO dto) {
|
||||||
CommandExecutor commandExecutor = processEngineConfiguration.getCommandExecutor();
|
CommandExecutor commandExecutor = processEngineConfiguration.getCommandExecutor();
|
||||||
commandExecutor.execute(new CustomCompleteDummyTaskCmd(dto.getProcessInstanceId(), dto.getTaskId(),
|
commandExecutor.execute(new CustomCompleteDummyTaskCmd(dto.getProcessInstanceId(), dto.getTaskId(),
|
||||||
Objects.isNull(dto.getRobotNode()) ? null : dto.getRobotNode().getFlowNodeName(),
|
Objects.isNull(dto.getRobotNode()) ? null : dto.getRobotNode().getFlowNodeName(),
|
||||||
Objects.isNull(dto.getRobotNode()) ? null : dto.getRobotNode().getOperationDesc(),
|
Objects.isNull(dto.getRobotNode()) ? null : dto.getRobotNode().getOperationDesc(),
|
||||||
extAxHiTaskInstService));
|
extAxHiTaskInstService));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String findTaskIdByInstanceIdAndPersonId(String processInstanceId, String personId) {
|
public String findTaskIdByInstanceIdAndPersonId(String processInstanceId, String personId) {
|
||||||
List<Task> list = taskService.createTaskQuery().processInstanceId(processInstanceId)
|
List<Task> list = taskService.createTaskQuery().processInstanceId(processInstanceId)
|
||||||
.taskAssigneeLike("%" + personId)
|
.taskAssigneeLike("%" + personId)
|
||||||
.active()
|
.active()
|
||||||
.list();
|
.list();
|
||||||
if (CollectionUtils.isEmpty(list) || list.size() > 1) {
|
if (CollectionUtils.isEmpty(list) || list.size() > 1) {
|
||||||
throw new WorkflowEngineException(FIND_TASK_BY_PERSON_ID_ERROR, processInstanceId, personId);
|
throw new WorkflowEngineException(FIND_TASK_BY_PERSON_ID_ERROR, processInstanceId, personId);
|
||||||
}
|
}
|
||||||
@ -673,9 +831,9 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService {
|
|||||||
@Override
|
@Override
|
||||||
public Map<String, String> findTaskIdByInstanceIdsAndPersonId(List<String> processInstanceIds, String personId) {
|
public Map<String, String> findTaskIdByInstanceIdsAndPersonId(List<String> processInstanceIds, String personId) {
|
||||||
List<Task> tasks = taskService.createTaskQuery().processInstanceIdIn(processInstanceIds)
|
List<Task> tasks = taskService.createTaskQuery().processInstanceIdIn(processInstanceIds)
|
||||||
.taskAssigneeLike("%" + personId)
|
.taskAssigneeLike("%" + personId)
|
||||||
.active()
|
.active()
|
||||||
.list();
|
.list();
|
||||||
if (CollectionUtils.isEmpty(tasks)) {
|
if (CollectionUtils.isEmpty(tasks)) {
|
||||||
return new HashMap<>();
|
return new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user