审核功能开发
This commit is contained in:
parent
7c3d2eb7f6
commit
908b420246
@ -31,12 +31,18 @@
|
||||
<artifactId>axzo-mybatisplus-spring-boot-starter</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.flowable</groupId>
|
||||
<artifactId>flowable-bpmn-model</artifactId>
|
||||
<version>${flowable.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.flowable</groupId>
|
||||
<artifactId>flowable-json-converter</artifactId>
|
||||
@ -64,5 +70,6 @@
|
||||
<artifactId>flowable-engine</artifactId>
|
||||
<version>6.7.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package cn.axzo.workflow.core.common;
|
||||
|
||||
public interface WorkflowConstants {
|
||||
public interface BpmConstants {
|
||||
String SERVER_APP_ID = "server-app-id";
|
||||
/**
|
||||
* 引擎自己隐藏指令
|
||||
@ -0,0 +1,58 @@
|
||||
package cn.axzo.workflow.core.common.enums;
|
||||
|
||||
import cn.azxo.framework.common.utils.StringUtils;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 流程实例的删除原因
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum BpmProcessInstanceDeleteReasonEnum {
|
||||
REJECT_TASK("不通过任务,原因:{}"), // 修改文案时,需要注意 isRejectReason 方法
|
||||
CANCEL_TASK("主动取消任务,原因:{}"),
|
||||
|
||||
// ========== 流程任务的独有原因 ==========
|
||||
MULTI_TASK_END(
|
||||
"该任务审核已被处理,无需审核"); // 多实例满足 condition 而结束时,其它任务实例任务会被取消,对应的删除原因是 MI_END
|
||||
|
||||
private final String reason;
|
||||
|
||||
/**
|
||||
* 格式化理由
|
||||
*
|
||||
* @param args 参数
|
||||
* @return 理由
|
||||
*/
|
||||
public String format(Object... args) {
|
||||
return StrUtil.format(reason, args);
|
||||
}
|
||||
|
||||
// ========== 逻辑 ==========
|
||||
|
||||
public static boolean isRejectReason(String reason) {
|
||||
return StrUtil.startWith(reason, "不通过任务,原因:");
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 Flowable 的删除原因,翻译成对应的中文原因
|
||||
*
|
||||
* @param reason 原始原因
|
||||
* @return 原因
|
||||
*/
|
||||
public static String translateReason(String reason) {
|
||||
if (StrUtil.isEmpty(reason)) {
|
||||
return reason;
|
||||
}
|
||||
switch (reason) {
|
||||
case "MI_END":
|
||||
return MULTI_TASK_END.getReason();
|
||||
default:
|
||||
return reason;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package cn.axzo.workflow.core.common.exception;
|
||||
|
||||
import cn.axzo.framework.domain.ServiceException;
|
||||
import cn.axzo.framework.domain.web.code.BaseCode;
|
||||
import cn.axzo.framework.domain.web.code.IRespCode;
|
||||
|
||||
public class WorkflowEngineException extends ServiceException {
|
||||
private String code;
|
||||
|
||||
public WorkflowEngineException() {
|
||||
this((IRespCode)BaseCode.SERVICE_UNAVAILABLE);
|
||||
}
|
||||
|
||||
public WorkflowEngineException(IRespCode code) {
|
||||
super(code.getMessage());
|
||||
this.code = code.getRespCode();
|
||||
}
|
||||
|
||||
public WorkflowEngineException(IRespCode code, String message) {
|
||||
super(message);
|
||||
this.code = code.getRespCode();
|
||||
}
|
||||
|
||||
public WorkflowEngineException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public WorkflowEngineException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public WorkflowEngineException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,6 @@
|
||||
package cn.axzo.workflow.core.common.utils;
|
||||
|
||||
import cn.axzo.workflow.core.common.WorkflowConstants;
|
||||
import cn.axzo.framework.domain.ServiceException;
|
||||
import cn.axzo.workflow.core.common.BpmConstants;
|
||||
import cn.axzo.workflow.core.common.enums.BpmFlowNodeType;
|
||||
import cn.axzo.workflow.core.service.dto.BpmJsonNode;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
@ -16,8 +15,6 @@ import org.flowable.bpmn.model.Process;
|
||||
import org.flowable.engine.delegate.TaskListener;
|
||||
import org.flowable.engine.repository.Model;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.*;
|
||||
|
||||
import static cn.axzo.workflow.core.common.enums.BpmErrorCode.BPM_META_DATA_FORMAT_ERROR;
|
||||
@ -50,7 +47,7 @@ public class BpmTransformUtil {
|
||||
lastNode = create(startEvent.getId(), jsonObject, bpmnModel,process,sequenceFlows);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new ServiceException(BPM_META_DATA_FORMAT_ERROR);
|
||||
throw new WorkflowEngineException(BPM_META_DATA_FORMAT_ERROR);
|
||||
}
|
||||
EndEvent endEvent = createEndEvent();
|
||||
process.addFlowElement(endEvent);
|
||||
@ -184,7 +181,7 @@ public class BpmTransformUtil {
|
||||
userTask.setId(id);
|
||||
process.addFlowElement(userTask);
|
||||
if(BpmFlowNodeType.NODE_STARTER.name().equals(flowNode.getString("type"))){
|
||||
id = WorkflowConstants.START_EVENT_ID;
|
||||
id = BpmConstants.START_EVENT_ID;
|
||||
}
|
||||
else{
|
||||
|
||||
|
||||
@ -1,35 +0,0 @@
|
||||
package cn.axzo.workflow.core.exception;
|
||||
|
||||
public class WorkflowEngineException extends RuntimeException {
|
||||
// private String code;
|
||||
//
|
||||
// public WorkflowEngineException() {
|
||||
// this((IRespCode)BaseCode.SERVICE_UNAVAILABLE);
|
||||
// }
|
||||
//
|
||||
// public WorkflowEngineException(IRespCode code) {
|
||||
// super(code.getMessage());
|
||||
// this.code = code.getRespCode();
|
||||
// }
|
||||
//
|
||||
// public WorkflowEngineException(IRespCode code, String message) {
|
||||
// super(message);
|
||||
// this.code = code.getRespCode();
|
||||
// }
|
||||
//
|
||||
// public WorkflowEngineException(String message) {
|
||||
// super(message);
|
||||
// }
|
||||
//
|
||||
// public WorkflowEngineException(String message, Throwable cause) {
|
||||
// super(message, cause);
|
||||
// }
|
||||
//
|
||||
// public WorkflowEngineException(Throwable cause) {
|
||||
// super(cause);
|
||||
// }
|
||||
//
|
||||
// public String getCode() {
|
||||
// return this.code;
|
||||
// }
|
||||
}
|
||||
@ -48,13 +48,13 @@ public class BpmProcessInstanceExtDO {
|
||||
/**
|
||||
* 流程实例的状态
|
||||
* <p>
|
||||
* 枚举 {@link cn.axzo.server.common.enums.BpmProcessInstanceStatusEnum}
|
||||
* 枚举 {@link cn.axzo.workflow.core.common.enums.BpmProcessInstanceStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 流程实例的结果
|
||||
* <p>
|
||||
* 枚举 {@link cn.axzo.server.common.enums.BpmProcessInstanceResultEnum}
|
||||
* 枚举 {@link cn.axzo.workflow.core.common.enums.BpmProcessInstanceResultEnum}
|
||||
*/
|
||||
private Integer result;
|
||||
/**
|
||||
|
||||
@ -1,11 +1,14 @@
|
||||
package cn.axzo.workflow.core.repository.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
@TableName(value = "bpm_task_ext", autoResultMap = true)
|
||||
@Data
|
||||
@ -92,5 +95,9 @@ public class BpmTaskExtDO {
|
||||
*/
|
||||
private String organizationalStructureInfo;
|
||||
|
||||
private Object ext;
|
||||
/**
|
||||
* 拓展字段:业务自定义数据
|
||||
* */
|
||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
private Map ext;
|
||||
}
|
||||
|
||||
@ -1,9 +1,29 @@
|
||||
package cn.axzo.workflow.core.repository.mapper;
|
||||
|
||||
import cn.axzo.workflow.core.repository.entity.BpmTaskExtDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface BpmTaskExtMapper extends BaseMapper<BpmTaskExtDO> {
|
||||
default void updateByTaskId(BpmTaskExtDO entity) {
|
||||
update(entity,
|
||||
new LambdaQueryWrapper<BpmTaskExtDO>().eq(BpmTaskExtDO::getTaskId, entity.getTaskId()));
|
||||
}
|
||||
|
||||
// default List<BpmTaskExtDO> selectListByTaskIds(Collection<String> taskIds) {
|
||||
// return selectList(BpmTaskExtDO::getTaskId, taskIds);
|
||||
// }
|
||||
//
|
||||
// default List<BpmTaskExtDO> selectListByProcessInstanceId(String processInstanceId) {
|
||||
// return selectList("process_instance_id", processInstanceId);
|
||||
// }
|
||||
//
|
||||
// default BpmTaskExtDO selectByTaskId(String taskId) {
|
||||
// return selectOne(BpmTaskExtDO::getTaskId, taskId);
|
||||
// }
|
||||
}
|
||||
|
||||
@ -38,6 +38,14 @@ public interface BpmProcessDefinitionService {
|
||||
*/
|
||||
ProcessDefinition getProcessDefinitionByDeploymentId(String deploymentId);
|
||||
|
||||
/**
|
||||
* 获得流程定义标识对应的激活的流程定义
|
||||
*
|
||||
* @param key 流程定义的标识
|
||||
* @return 流程定义
|
||||
*/
|
||||
ProcessDefinition getActiveProcessDefinitionByKey(String key);
|
||||
|
||||
/**
|
||||
* 挂起/激活流程,
|
||||
* 激活:SuspensionState.ACTIVE.getStateCode()
|
||||
@ -45,4 +53,11 @@ public interface BpmProcessDefinitionService {
|
||||
* {@link SuspensionState}
|
||||
* */
|
||||
void updateProcessDefinitionSuspendedState(String processDefinitionId, Integer state);
|
||||
|
||||
/**
|
||||
* 获取指定模型激活的定义 ID
|
||||
* @return 流程定义ID
|
||||
*/
|
||||
String getActiveProcessDefinitionId(String tenantId, String category);
|
||||
|
||||
}
|
||||
|
||||
@ -21,14 +21,23 @@ public interface BpmProcessInstanceService {
|
||||
*/
|
||||
ProcessInstance getProcessInstance(String id, String tenantId);
|
||||
|
||||
Boolean updateProcessStatus(String processInstanceId, String status);
|
||||
|
||||
|
||||
/**
|
||||
* 获得流程实例
|
||||
*
|
||||
* @param id 流程实例的编号
|
||||
* @param tenantId 租户Id
|
||||
* @param hasVariable 查询结果是否包含流程参数,
|
||||
* @return 流程实例, 租户Id不必传
|
||||
*/
|
||||
ProcessInstance getProcessInstance(String id, String tenantId, boolean hasVariable);
|
||||
|
||||
/**
|
||||
* 获取活跃的流程定义
|
||||
* */
|
||||
ProcessDefinition getActiveProcessDefinitionByKey(String key);
|
||||
* 获得流程实例
|
||||
*
|
||||
* @param processInstanceId 流程实例的编号
|
||||
* @param status 租户Id
|
||||
*/
|
||||
Boolean updateProcessStatus(String processInstanceId, String status);
|
||||
|
||||
/**
|
||||
* 获得历史的流程实例
|
||||
|
||||
@ -1,10 +1,17 @@
|
||||
package cn.axzo.workflow.core.service.dto.request.task;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import org.flowable.engine.task.Comment;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
@Data
|
||||
public class BpmTaskAuditDTO {
|
||||
|
||||
private String taskId;
|
||||
@ApiModelProperty(value = "任务编号", required = true, example = "1024")
|
||||
@NotEmpty(message = "任务编号不能为空")
|
||||
private String id;
|
||||
/**
|
||||
* 审核人Id
|
||||
* */
|
||||
@ -23,5 +30,5 @@ public class BpmTaskAuditDTO {
|
||||
/**
|
||||
* 评论信息
|
||||
* */
|
||||
private Comment comment;
|
||||
private String comment;
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
package cn.axzo.workflow.core.service.impl;
|
||||
|
||||
import cn.axzo.framework.domain.ServiceException;
|
||||
import cn.axzo.workflow.core.common.enums.BpmErrorCode;
|
||||
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
||||
import cn.axzo.workflow.core.service.BpmModelService;
|
||||
import cn.axzo.workflow.core.service.BpmProcessDefinitionService;
|
||||
import cn.axzo.workflow.core.service.converter.BpmModelConverter;
|
||||
@ -25,6 +25,8 @@ import org.springframework.stereotype.Service;
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import static cn.axzo.workflow.core.common.enums.BpmErrorCode.MODEL_NOT_EXISTS;
|
||||
|
||||
@Service
|
||||
public class BpmModelServiceImpl implements BpmModelService {
|
||||
|
||||
@ -44,7 +46,7 @@ public class BpmModelServiceImpl implements BpmModelService {
|
||||
|
||||
Model existModel = repositoryService.createModelQuery().modelKey(createDTO.getKey()).singleResult();
|
||||
if (!ObjectUtils.isEmpty(existModel)) {
|
||||
throw new RuntimeException("模型已存在");
|
||||
throw new WorkflowEngineException("模型已存在");
|
||||
}
|
||||
|
||||
Model model = repositoryService.newModel();
|
||||
@ -99,12 +101,12 @@ public class BpmModelServiceImpl implements BpmModelService {
|
||||
public String deployBpmModelById(String modelId) {
|
||||
Model model = this.repositoryService.getModel(modelId);
|
||||
if (org.springframework.util.ObjectUtils.isEmpty(model)) {
|
||||
throw new ServiceException(BpmErrorCode.MODEL_NOT_EXISTS);
|
||||
throw new WorkflowEngineException(MODEL_NOT_EXISTS);
|
||||
}
|
||||
|
||||
byte[] bpmnBytes = this.repositoryService.getModelEditorSource(model.getId());
|
||||
if (bpmnBytes == null) {
|
||||
throw new ServiceException(BpmErrorCode.MODEL_NOT_EXISTS);
|
||||
throw new WorkflowEngineException(MODEL_NOT_EXISTS);
|
||||
}
|
||||
|
||||
processDefinitionService.createProcessDeinition(model, bpmnBytes);
|
||||
@ -127,6 +129,12 @@ public class BpmModelServiceImpl implements BpmModelService {
|
||||
|
||||
@Override
|
||||
public void deleteBpmModel(String id) {
|
||||
// 校验流程模型存在
|
||||
Model model = repositoryService.getModel(id);
|
||||
if (model == null) {
|
||||
throw new WorkflowEngineException(MODEL_NOT_EXISTS);
|
||||
}
|
||||
// 执行删除
|
||||
repositoryService.deleteModel(id);
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
package cn.axzo.workflow.core.service.impl;
|
||||
|
||||
import cn.axzo.framework.domain.ServiceException;
|
||||
import cn.axzo.workflow.core.repository.entity.BpmProcessDefinitionExtDO;
|
||||
import cn.axzo.workflow.core.repository.mapper.BpmProcessDefinitionExtMapper;
|
||||
import cn.axzo.workflow.core.service.dto.request.process.BpmProcessDefinitionPageDTO;
|
||||
@ -15,12 +14,14 @@ import org.flowable.engine.repository.Deployment;
|
||||
import org.flowable.engine.repository.Model;
|
||||
import org.flowable.engine.repository.ProcessDefinition;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static cn.axzo.workflow.core.common.enums.BpmErrorCode.PROCESS_DEFINITION_KEY_NOT_MATCH;
|
||||
import static cn.axzo.workflow.core.common.enums.BpmErrorCode.PROCESS_DEFINITION_NAME_NOT_MATCH;
|
||||
import static cn.axzo.workflow.core.common.enums.BpmErrorCode.*;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
@ -57,10 +58,10 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
|
||||
// 注意 2,目前该项目的设计上,需要保证 Model、Deployment、ProcessDefinition 使用相同的 key,保证关联性。
|
||||
// 否则,会导致 ProcessDefinition 的分页无法查询到。
|
||||
if (!Objects.equals(model.getKey(), definition.getKey())) {
|
||||
throw new ServiceException(PROCESS_DEFINITION_KEY_NOT_MATCH);
|
||||
throw new WorkflowEngineException(PROCESS_DEFINITION_KEY_NOT_MATCH);
|
||||
}
|
||||
if (!Objects.equals(model.getName(), definition.getName())) {
|
||||
throw new ServiceException(PROCESS_DEFINITION_NAME_NOT_MATCH);
|
||||
throw new WorkflowEngineException(PROCESS_DEFINITION_NAME_NOT_MATCH);
|
||||
}
|
||||
|
||||
// 插入拓展表
|
||||
@ -94,7 +95,10 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
|
||||
|
||||
@Override
|
||||
public ProcessDefinition getProcessDefinition(String id) {
|
||||
return null;
|
||||
if (StringUtils.isBlank(id)) {
|
||||
return null;
|
||||
}
|
||||
return repositoryService.getProcessDefinition(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -105,4 +109,25 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
|
||||
return repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId)
|
||||
.singleResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcessDefinition getActiveProcessDefinitionByKey(String key) {
|
||||
return repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).active()
|
||||
.singleResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getActiveProcessDefinitionId(String tenantId, String category) {
|
||||
List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery()
|
||||
.processDefinitionTenantId(String.valueOf(tenantId))
|
||||
.processDefinitionCategory(category)
|
||||
.active()
|
||||
.latestVersion()
|
||||
.list();
|
||||
if (!CollectionUtils.isEmpty(list) && list.size() != 1) {
|
||||
throw new WorkflowEngineException(BPM_PROCESS_DEFINITION_RESULT_TOO_MANY);
|
||||
} else {
|
||||
return list.get(0).getId();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package cn.axzo.workflow.core.service.impl;
|
||||
|
||||
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
||||
import cn.axzo.workflow.core.repository.entity.BpmProcessInstanceExtDO;
|
||||
import cn.axzo.workflow.core.repository.mapper.BpmProcessInstanceExtMapper;
|
||||
import cn.axzo.workflow.core.service.dto.response.process.BpmProcessInstanceVO;
|
||||
@ -9,6 +10,7 @@ import cn.axzo.workflow.core.service.BpmTaskService;
|
||||
import cn.axzo.workflow.core.service.dto.request.process.BpmProcessInstanceCreateDTO;
|
||||
import cn.axzo.framework.domain.web.BizException;
|
||||
import cn.azxo.framework.common.utils.StringUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.common.engine.impl.identity.Authentication;
|
||||
import org.flowable.engine.*;
|
||||
import org.flowable.engine.history.HistoricProcessInstance;
|
||||
@ -18,15 +20,18 @@ import org.flowable.engine.runtime.ProcessInstanceQuery;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static cn.axzo.workflow.core.common.WorkflowConstants.INTERNAL_START_USER_NAME;
|
||||
import static cn.axzo.workflow.core.common.BpmConstants.INTERNAL_START_USER_NAME;
|
||||
import static cn.axzo.workflow.core.common.enums.BpmErrorCode.PROCESS_DEFINITION_IS_SUSPENDED;
|
||||
import static cn.axzo.workflow.core.common.enums.BpmErrorCode.PROCESS_DEFINITION_NOT_EXISTS;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService {
|
||||
|
||||
@Autowired
|
||||
@ -35,7 +40,6 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
||||
private RepositoryService repositoryService;
|
||||
@Autowired
|
||||
private ManagementService managementService;
|
||||
|
||||
@Autowired
|
||||
private RuntimeService runtimeService;
|
||||
@Autowired
|
||||
@ -58,7 +62,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
||||
return instanceQuery.singleResult();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ProcessInstance getProcessInstance(String id, String tenantId, boolean hasVariable) {
|
||||
ProcessInstanceQuery instanceQuery = runtimeService.createProcessInstanceQuery();
|
||||
instanceQuery.processInstanceId(id);
|
||||
@ -82,15 +86,16 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String createProcessInstance(BpmProcessInstanceCreateDTO processInstanceCreateDTO) {
|
||||
ProcessDefinition definition = getActiveProcessDefinitionByKey(processInstanceCreateDTO.getProcessDefinitionKey());
|
||||
ProcessDefinition definition = processDefinitionService.getActiveProcessDefinitionByKey(processInstanceCreateDTO.getProcessDefinitionKey());
|
||||
// 校验流程定义
|
||||
if (definition == null) {
|
||||
throw new BizException(PROCESS_DEFINITION_NOT_EXISTS);
|
||||
throw new WorkflowEngineException(PROCESS_DEFINITION_NOT_EXISTS);
|
||||
}
|
||||
if (definition.isSuspended()) {
|
||||
throw new BizException(PROCESS_DEFINITION_IS_SUSPENDED);
|
||||
throw new WorkflowEngineException(PROCESS_DEFINITION_IS_SUSPENDED);
|
||||
}
|
||||
processInstanceCreateDTO.getVariables().put(INTERNAL_START_USER_NAME, processInstanceCreateDTO.getUserName());
|
||||
|
||||
@ -117,18 +122,13 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
||||
extDO.setStartIdentityId(processInstanceCreateDTO.getIdentityId());
|
||||
extDO.setStartUserName(processInstanceCreateDTO.getUserName());
|
||||
extDO.setFormVariables(processInstanceCreateDTO.getVariables());
|
||||
extDO.setExt(processInstanceCreateDTO.getExt());
|
||||
// 补全流程实例的拓展表
|
||||
processInstanceExtMapper.updateByProcessInstanceId(extDO);
|
||||
|
||||
return instance.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcessDefinition getActiveProcessDefinitionByKey(String key) {
|
||||
return repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).active()
|
||||
.singleResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HistoricProcessInstance getHistoricProcessInstance(String id, String tenantId) {
|
||||
return null;
|
||||
@ -138,4 +138,27 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
||||
public BpmProcessInstanceVO getProcessInstanceVO(String id, String tenantId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateProcessInstanceExtReject(String id, String comment, String tenantId) {
|
||||
// 需要主动查询,因为 instance 只有 id 属性
|
||||
ProcessInstance processInstance = getProcessInstance(id, tenantId);
|
||||
|
||||
// 删除流程实例,以实现驳回任务时,取消整个审批流程
|
||||
// deleteProcessInstance(id,
|
||||
// StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(comment)));
|
||||
// // 更新 status + result
|
||||
// // 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法,
|
||||
// // 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL,显然和 result 不一定是一致的
|
||||
// BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id)
|
||||
// .setEndTime(new Date())
|
||||
// .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
|
||||
// .setResult(BpmProcessInstanceResultEnum.REJECT.getResult());
|
||||
// processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
|
||||
}
|
||||
|
||||
private void deleteProcessInstance(String id, String reason) {
|
||||
log.info("当前线程: {}", Thread.currentThread().getName());
|
||||
runtimeService.deleteProcessInstance(id, reason);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,21 +1,50 @@
|
||||
package cn.axzo.workflow.core.service.impl;
|
||||
|
||||
import cn.axzo.workflow.core.common.BpmConstants;
|
||||
import cn.axzo.workflow.core.common.enums.BpmProcessInstanceResultEnum;
|
||||
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
|
||||
import cn.axzo.workflow.core.repository.entity.BpmTaskExtDO;
|
||||
import cn.axzo.workflow.core.repository.mapper.BpmTaskExtMapper;
|
||||
import cn.axzo.workflow.core.service.BpmProcessInstanceService;
|
||||
import cn.axzo.workflow.core.service.BpmTaskService;
|
||||
import cn.axzo.workflow.core.service.dto.request.task.BpmTaskAuditDTO;
|
||||
import cn.axzo.workflow.core.service.dto.request.task.BpmTaskTodoBpmPageDTO;
|
||||
import cn.axzo.workflow.core.service.dto.response.BpmPageResult;
|
||||
import cn.axzo.workflow.core.service.dto.response.task.BpmTaskDonePageItemVO;
|
||||
import cn.axzo.workflow.core.service.dto.response.task.BpmTaskTodoPageItemVO;
|
||||
import cn.azxo.framework.common.utils.StringUtils;
|
||||
import org.flowable.engine.HistoryService;
|
||||
import org.flowable.engine.RepositoryService;
|
||||
import org.flowable.engine.RuntimeService;
|
||||
import org.flowable.engine.TaskService;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.flowable.task.api.Task;
|
||||
import org.flowable.task.api.TaskQuery;
|
||||
import org.flowable.task.api.history.HistoricTaskInstance;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
|
||||
import static cn.axzo.workflow.core.common.BpmConstants.*;
|
||||
import static cn.axzo.workflow.core.common.enums.BpmErrorCode.*;
|
||||
|
||||
@Service
|
||||
public class BpmTaskServiceImpl implements BpmTaskService {
|
||||
|
||||
|
||||
@Autowired
|
||||
private TaskService taskService;
|
||||
@Autowired
|
||||
private RuntimeService runtimeService;
|
||||
@Autowired
|
||||
private HistoryService historyService;
|
||||
@Autowired
|
||||
private RepositoryService repositoryService;
|
||||
@Resource
|
||||
private BpmProcessInstanceService processInstanceService;
|
||||
@Resource
|
||||
private BpmTaskExtMapper taskExtMapper;
|
||||
|
||||
@Override
|
||||
public BpmPageResult<BpmTaskTodoPageItemVO> getTodoTaskPage(BpmTaskTodoBpmPageDTO taskTodoPageDTO) {
|
||||
@ -35,55 +64,81 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
||||
@Override
|
||||
public void approveTask(BpmTaskAuditDTO taskAuditDTO) {
|
||||
// 校验任务存在
|
||||
// Task task = checkTask(reqVO.getWorkspaceId(), reqVO.getIdentityId(), reqVO.getId());
|
||||
// // 校验流程实例存在
|
||||
// ProcessInstance instance = processInstanceService.getProcessInstance(
|
||||
// task.getProcessInstanceId(), null, true);
|
||||
// if (instance == null) {
|
||||
// throw exception(PROCESS_INSTANCE_NOT_EXISTS);
|
||||
// }
|
||||
//
|
||||
// bpmAddTask(task, reqVO.getAddAssignees());
|
||||
//
|
||||
// // 根据流程实例ID和任务定义key查询运行中的任务,并记录taskId列表
|
||||
// TaskQuery taskQuery = taskService.createTaskQuery()
|
||||
// .processInstanceId(instance.getId())
|
||||
// .taskTenantId(String.valueOf(reqVO.getWorkspaceId()))
|
||||
// .taskDefinitionKey(task.getTaskDefinitionKey());
|
||||
// List<Task> taskRunningListBefore = taskQuery.list();//eg:1、2、3
|
||||
//
|
||||
// if (taskRunningListBefore.size() > 1 && taskQuery.list().isEmpty()) {
|
||||
// // 满足条件1:当前任务是多实例任务节点的子任务,
|
||||
// // 满足条件2:该子任务完成时,将所在多实例任务节点中的其他子任务也一并删除,说明此时已经满足了多实例的完成条件
|
||||
// // 此时需要将该任务所在多实例任务节点中的其他子任务,更新任务拓展表为已完成
|
||||
// for (Task taskRunningBefore : taskRunningListBefore) {
|
||||
// if (!task.getId().equals(taskRunningBefore.getId())) {
|
||||
// taskExtMapper.updateByTaskId(new BpmTaskExtDO()
|
||||
// .setTaskId(taskRunningBefore.getId())
|
||||
// .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult())
|
||||
// .setComment("自动完成")
|
||||
// .setEndTime(new Date()));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// // 更新任务拓展表为通过
|
||||
// taskExtMapper.updateByTaskId(new BpmTaskExtDO().setTaskId(task.getId())
|
||||
// .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult())
|
||||
// .setComment(reqVO.getComment()));
|
||||
//
|
||||
// // 开启自动跳过功能
|
||||
// Map<String, Object> transientMap = new HashMap<>();
|
||||
// transientMap.put(WorkflowConstants.FLOWABLE_SKIP_EXPRESSION_ENABLE, true);
|
||||
// transientMap.put(WorkflowConstants.INTERNAL_TASK_COMMENT, reqVO.getComment());
|
||||
// // 完成任务,审批通过
|
||||
// taskService.complete(task.getId(), instance.getProcessVariables(), transientMap);
|
||||
// return true;
|
||||
Task task = getTask(taskAuditDTO.getId(), taskAuditDTO.getTenantId());
|
||||
// 校验流程实例存在
|
||||
ProcessInstance instance = processInstanceService.getProcessInstance(
|
||||
task.getProcessInstanceId(), null, true);
|
||||
if (instance == null) {
|
||||
throw new WorkflowEngineException(PROCESS_INSTANCE_NOT_EXISTS);
|
||||
}
|
||||
|
||||
// 根据流程实例ID和任务定义key查询运行中的任务,并记录taskId列表
|
||||
TaskQuery taskQuery = taskService.createTaskQuery()
|
||||
.processInstanceId(instance.getId())
|
||||
.taskTenantId(taskAuditDTO.getTenantId())
|
||||
.taskDefinitionKey(task.getTaskDefinitionKey());
|
||||
List<Task> taskRunningListBefore = taskQuery.list();//eg:1、2、3
|
||||
|
||||
if (taskRunningListBefore.size() > 1 && taskQuery.list().isEmpty()) {
|
||||
// 满足条件1:当前任务是多实例任务节点的子任务,
|
||||
// 满足条件2:该子任务完成时,将所在多实例任务节点中的其他子任务也一并删除,说明此时已经满足了多实例的完成条件
|
||||
// 此时需要将该任务所在多实例任务节点中的其他子任务,更新任务拓展表为已完成
|
||||
for (Task taskRunningBefore : taskRunningListBefore) {
|
||||
if (!task.getId().equals(taskRunningBefore.getId())) {
|
||||
BpmTaskExtDO taskExtDO = new BpmTaskExtDO();
|
||||
taskExtDO.setTaskId(taskRunningBefore.getId());
|
||||
taskExtDO.setResult(BpmProcessInstanceResultEnum.APPROVE.getResult());
|
||||
taskExtDO.setComment("自动完成");
|
||||
taskExtDO.setEndTime(new Date());
|
||||
taskExtMapper.updateByTaskId(taskExtDO);
|
||||
}
|
||||
}
|
||||
}
|
||||
BpmTaskExtDO taskExtDO = new BpmTaskExtDO();
|
||||
taskExtDO.setTaskId(task.getId());
|
||||
taskExtDO.setResult(BpmProcessInstanceResultEnum.APPROVE.getResult());
|
||||
taskExtDO.setComment(taskAuditDTO.getComment());
|
||||
taskExtDO.setEndTime(new Date());
|
||||
// 更新任务拓展表为通过
|
||||
taskExtMapper.updateByTaskId(taskExtDO);
|
||||
|
||||
// 开启自动跳过功能
|
||||
Map<String, Object> transientMap = new HashMap<>();
|
||||
transientMap.put(BpmConstants.FLOWABLE_SKIP_EXPRESSION_ENABLE, true);
|
||||
transientMap.put(BpmConstants.INTERNAL_TASK_COMMENT, taskAuditDTO.getComment());
|
||||
// 完成任务,审批通过
|
||||
taskService.complete(task.getId(), instance.getProcessVariables(), transientMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rejectTask(BpmTaskAuditDTO taskAuditDTO) {
|
||||
// 校验任务存在
|
||||
Task task = checkTask(taskAuditDTO.getTenantId(),
|
||||
taskAuditDTO.getAssigneeId(), taskAuditDTO.getId());
|
||||
|
||||
// 校验流程实例存在
|
||||
ProcessInstance instance = processInstanceService.getProcessInstance(
|
||||
task.getProcessInstanceId(), null);
|
||||
|
||||
if (instance == null) {
|
||||
throw new WorkflowEngineException(PROCESS_INSTANCE_NOT_EXISTS);
|
||||
}
|
||||
Map<String, Object> variables = new HashMap<>();
|
||||
variables.put(INTERNAL_END_USER_WORKSPACE_ID, taskAuditDTO.getTenantId());
|
||||
variables.put(INTERNAL_END_USER_NAME, taskAuditDTO.getAssigneeName());
|
||||
variables.put(INTERNAL_END_USER_IDENTITY_ID, taskAuditDTO.getAssigneeId());
|
||||
runtimeService.setVariables(instance.getProcessInstanceId(), variables);
|
||||
|
||||
// 更新任务拓展表为不通过
|
||||
BpmTaskExtDO taskExtDO = new BpmTaskExtDO();
|
||||
taskExtDO.setTaskId(task.getId());
|
||||
taskExtDO.setResult(BpmProcessInstanceResultEnum.REJECT.getResult());
|
||||
taskExtDO.setComment(taskAuditDTO.getComment());
|
||||
taskExtDO.setEndTime(new Date());
|
||||
taskExtMapper.updateByTaskId(taskExtDO);
|
||||
// 更新流程实例为不通过
|
||||
// processInstanceService.updateProcessInstanceExtReject(instance.getProcessInstanceId(),
|
||||
// reqVO.getComment(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -100,4 +155,32 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
||||
public List<Task> getActiveTasksByProcessInstanceId(String processInstanceId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验任务是否存在, 并且是否是分配给自己的任务
|
||||
*
|
||||
* @param tenantId 租户ID
|
||||
* @param identityId 身份ID
|
||||
* @param taskId task id
|
||||
*/
|
||||
private Task checkTask(String tenantId, String identityId,
|
||||
String taskId) {
|
||||
|
||||
Task task = getTask(taskId, String.valueOf(tenantId));
|
||||
if (task == null) {
|
||||
throw new WorkflowEngineException(TASK_COMPLETE_FAIL_NOT_EXISTS);
|
||||
}
|
||||
if (!Objects.equals(identityId, task.getAssignee())) {
|
||||
throw new WorkflowEngineException(TASK_COMPLETE_FAIL_ASSIGN_NOT_SELF);
|
||||
}
|
||||
return task;
|
||||
}
|
||||
|
||||
private Task getTask(String id, String tenantId) {
|
||||
TaskQuery taskQuery = taskService.createTaskQuery().taskId(id);
|
||||
if (StringUtils.isNotBlank(tenantId)) {
|
||||
taskQuery.taskTenantId(tenantId);
|
||||
}
|
||||
return taskQuery.singleResult();
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user