|
@@ -0,0 +1,1229 @@
|
|
|
+package com.yh.saas.plugin.yiliangyiyun.service.impl;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSONArray;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.alipay.sofa.runtime.api.annotation.SofaReference;
|
|
|
+import com.baomidou.mybatisplus.mapper.BaseMapper;
|
|
|
+import com.baomidou.mybatisplus.plugins.Page;
|
|
|
+import com.google.common.collect.Lists;
|
|
|
+import com.winsea.svc.base.base.entity.*;
|
|
|
+import com.winsea.svc.base.base.service.*;
|
|
|
+import com.winsea.svc.base.base.util.ObjectUtils;
|
|
|
+import com.winsea.svc.base.base.util.provider.BeanWorkFlowProvider;
|
|
|
+import com.winsea.svc.base.security.entity.User;
|
|
|
+import com.winsea.svc.base.security.util.AuthSecurityUtils;
|
|
|
+import com.winsea.svc.base.workflow.configservice.IWorkflowConfigService;
|
|
|
+import com.winsea.svc.base.workflow.entity.Workflow;
|
|
|
+import com.winsea.svc.base.workflow.entity.WorkflowListener;
|
|
|
+import com.winsea.svc.base.workflow.entity.WorkflowStep;
|
|
|
+import com.yh.saas.common.support.util.ContextWrapper;
|
|
|
+import com.yh.saas.common.support.util.IdGenerator;
|
|
|
+import com.yh.saas.common.support.util.StringUtils;
|
|
|
+import com.yh.saas.common.support.workflow.AbstractWorkflowTaskListener;
|
|
|
+import com.yh.saas.common.support.workflow.IWorkflowTaskChecklist;
|
|
|
+import com.yh.saas.plugin.yiliangyiyun.service.INewWorkflowService;
|
|
|
+import com.yh.saas.toolkit.workflow.activiti.ActivitiWorkflowBuilder;
|
|
|
+import com.yh.saas.toolkit.workflow.activiti.cmd.DeleteTaskCmd;
|
|
|
+import com.yh.saas.toolkit.workflow.activiti.util.ActivitiCountersignUtils;
|
|
|
+import com.yh.saas.toolkit.workflow.activiti.util.ActivitiHistoryUtils;
|
|
|
+import com.yh.saas.toolkit.workflow.activiti.util.ActivitiProcessUtils;
|
|
|
+import com.yh.saas.toolkit.workflow.activiti.util.ActivitiTaskUtils;
|
|
|
+import com.yh.saas.toolkit.workflow.config.WorkflowProperties;
|
|
|
+import com.yh.saas.toolkit.workflow.constants.ActivitiVariableNameConstants;
|
|
|
+import com.yh.saas.toolkit.workflow.exception.WorkflowErrorCodeEnums;
|
|
|
+import com.yh.saas.toolkit.workflow.exception.WorkflowException;
|
|
|
+import com.yh.saas.toolkit.workflow.service.IWorkflowHistoryService;
|
|
|
+import com.yh.saas.toolkit.workflow.service.IWorkflowListenerService;
|
|
|
+import com.yh.saas.toolkit.workflow.service.IWorkflowService;
|
|
|
+import com.yh.saas.toolkit.workflow.service.IWorkflowStepService;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.activiti.bpmn.model.FlowElement;
|
|
|
+import org.activiti.bpmn.model.Process;
|
|
|
+import org.activiti.bpmn.model.UserTask;
|
|
|
+import org.activiti.engine.*;
|
|
|
+import org.activiti.engine.history.HistoricProcessInstance;
|
|
|
+import org.activiti.engine.runtime.ProcessInstance;
|
|
|
+import org.activiti.engine.task.Task;
|
|
|
+import org.activiti.engine.task.TaskInfo;
|
|
|
+import org.activiti.engine.task.TaskQuery;
|
|
|
+import org.apache.commons.collections.CollectionUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.data.redis.core.RedisTemplate;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Propagation;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import java.io.InputStream;
|
|
|
+import java.io.Serializable;
|
|
|
+import java.lang.reflect.ParameterizedType;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.Map.Entry;
|
|
|
+import java.util.concurrent.ConcurrentHashMap;
|
|
|
+import java.util.function.Consumer;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 工作流服务实现
|
|
|
+ *
|
|
|
+ * @author gdc
|
|
|
+ */
|
|
|
+@Transactional
|
|
|
+@Service
|
|
|
+@Slf4j
|
|
|
+public class NewWorkflowServiceImpl implements INewWorkflowService {
|
|
|
+
|
|
|
+ private static final String TASK_QUERY_TASK_ID = "taskId";
|
|
|
+
|
|
|
+ private static final String TASK_QUERY_TASK_NAME = "taskName";
|
|
|
+
|
|
|
+ private static final String TASK_QUERY_WORKFLOW_ID = "workflowId";
|
|
|
+
|
|
|
+ private static final String TASK_QUERY_BUSINESS_KEY = "businessKey";
|
|
|
+
|
|
|
+ private static final String WORKFLOW_ID_FIELD = "workflowId";
|
|
|
+
|
|
|
+ private static final String WORK_FLOW_ID_FIELD = "workFlowId";
|
|
|
+
|
|
|
+ public static final String SERVICE_NAME_SPAREPART = "sparepart";
|
|
|
+ public static final String SERVICE_NAME_MATERIEL = "materiel";
|
|
|
+ public static final String SERVICE_NAME_NAVIGATION = "navigation";
|
|
|
+ public static final String SERVICE_NAME_PURCHASE = "purchase";
|
|
|
+
|
|
|
+ private Map<String, BaseMapper<?>> entityClassBaseMapperMap = new ConcurrentHashMap<>();
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private WorkflowProperties workflowProperties;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private RedisTemplate<String, String> redisTemplate;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ProcessEngine processEngine;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ManagementService managementService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private RuntimeService runtimeService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private TaskService taskService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IdentityService identityService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IWorkflowStepService workflowStepService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IWorkflowListenerService workflowListenerService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IWorkflowHistoryService workflowHistoryService;
|
|
|
+
|
|
|
+ @SofaReference
|
|
|
+ private IWorkflowConfigService workflowConfigService;
|
|
|
+
|
|
|
+ @SofaReference
|
|
|
+ private ICommonStaffService staffService;
|
|
|
+
|
|
|
+ @SofaReference
|
|
|
+ private ICommonCompanyService companyService;
|
|
|
+
|
|
|
+ @SofaReference
|
|
|
+ private ILanguageChangeService languageChangeService;
|
|
|
+
|
|
|
+ @SofaReference
|
|
|
+ private IAuditHistoryService auditHistoryService;
|
|
|
+
|
|
|
+ @SofaReference
|
|
|
+ private ICommonFlowBusinessTableService flowBusinessTableService;
|
|
|
+
|
|
|
+ @SofaReference
|
|
|
+ private ICommonStaffVesselService staffVesselService;
|
|
|
+
|
|
|
+ private ThreadLocal<String> localUserId = new ThreadLocal<>();
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String create(Workflow workflow) {
|
|
|
+ workflow.setId(generateFlowId()); // 工作流ID将作为Activiti流程定义ID,必须以字母或下划线开头
|
|
|
+ workflow.setLatest(1); // 最新版
|
|
|
+ insert(workflow);
|
|
|
+
|
|
|
+ // 创建步骤和全局监听器
|
|
|
+ createStepsAndListeners(workflow.getId(), workflow.getSteps(), workflow.getListeners());
|
|
|
+
|
|
|
+ // 将全局监听器绑定到所有步骤
|
|
|
+ workflow.getSteps().stream().forEach(step -> {
|
|
|
+ if (CollectionUtils.isEmpty(step.getListeners())) {
|
|
|
+ step.setListeners(workflow.getListeners());
|
|
|
+ } else {
|
|
|
+ step.getListeners().addAll(workflow.getListeners());
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 如果是租户创建的工作流则部署工作流
|
|
|
+ if (!StringUtils.isEmpty(workflow.getCompId())) {
|
|
|
+ // 设置租户ID
|
|
|
+ workflow.setTenantId(companyService.selectById(workflow.getCompId()).getTenantId());
|
|
|
+
|
|
|
+ buildActivitiWorkflow(workflow);
|
|
|
+ }
|
|
|
+ return workflow.getId();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String changeInfo(Workflow workflow) {
|
|
|
+ Workflow originalWorkflow = this.selectById(workflow.getId());
|
|
|
+
|
|
|
+ // 模板修改
|
|
|
+ if (null == originalWorkflow.getCompId()) {
|
|
|
+ // 删除步骤和全局监听器
|
|
|
+ workflowStepService.removeByWorkflowId(workflow.getId());
|
|
|
+ workflowListenerService.removeByFlowId(workflow.getId());
|
|
|
+
|
|
|
+ // 创建步骤和全局监听器
|
|
|
+ createStepsAndListeners(workflow.getId(), workflow.getSteps(), workflow.getListeners());
|
|
|
+
|
|
|
+ updateById(workflow);
|
|
|
+ return workflow.getId();
|
|
|
+ }
|
|
|
+ // 工作流修改
|
|
|
+ else {
|
|
|
+ // 设置原始工作流为旧版
|
|
|
+ originalWorkflow.setLatest(0);
|
|
|
+ updateById(originalWorkflow);
|
|
|
+
|
|
|
+ // 创建新版工作流
|
|
|
+ return create(workflow);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Workflow getWorkflowDetail(String workflowId) {
|
|
|
+ return workflowConfigService.getWorkflowDetail(workflowId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<Workflow> getWorkflowDefinitions(String businessCode, String compId) {
|
|
|
+ return workflowConfigService.getWorkflowDefinitions(businessCode, compId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Workflow findLatestWorkflowByBusinessCode(String businessCode) {
|
|
|
+ return workflowConfigService.findLatestWorkflowByBusinessCode(businessCode, getCurrentCompId(), getCurrentUserRoles());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Workflow getLatestWorkflowByBusinessCodeAndCompId(String businessCode, String compId) {
|
|
|
+ return workflowConfigService.getLatestWorkflowByBusinessCodeAndCompId(businessCode, compId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<Workflow> findWorkflowsByBusinessCode(String businessCode) {
|
|
|
+ return workflowConfigService.findWorkflowsByBusinessCode(businessCode, getCurrentCompId(),
|
|
|
+ getCurrentUserRoles());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<String> findWorkflowIdsByBusinessCode(String businessCode) {
|
|
|
+ return findWorkflowsByBusinessCode(businessCode).stream().map(Workflow::getId).collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public InputStream getProcessDiagram(String workflowId) {
|
|
|
+ return ActivitiProcessUtils.getProcessDiagram(workflowId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void startInstance(String workflowId, String businessKey) {
|
|
|
+ startInstance(workflowId, businessKey, getCurrentUserId());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void startInstance(String workflowId, String businessKey, String startUserId) {
|
|
|
+ // 设置发起人ID
|
|
|
+ identityService.setAuthenticatedUserId(startUserId);
|
|
|
+
|
|
|
+ // 开始流程
|
|
|
+ Map<String, Object> vars = new HashMap<>();
|
|
|
+ vars.put(ActivitiVariableNameConstants.START_USER_ID, startUserId);
|
|
|
+ vars.put(ActivitiVariableNameConstants.STEP_NUMBER, 1);
|
|
|
+ runtimeService.startProcessInstanceByKey(workflowId, businessKey, vars);
|
|
|
+
|
|
|
+ ProcessInstance processInstance = ActivitiProcessUtils.findInstanceByWorkflowIdAndBusinessKey(workflowId,
|
|
|
+ businessKey);
|
|
|
+
|
|
|
+ if (null == processInstance) {
|
|
|
+ notify(workflowId,
|
|
|
+ taskListener -> taskListener.handleStatusChanged(businessKey, "已完成", "Completed", true));
|
|
|
+ } else {
|
|
|
+ // 跳过占位步骤
|
|
|
+ skipPlaceholder(processInstance.getProcessInstanceId());
|
|
|
+
|
|
|
+ // 设置审批状态
|
|
|
+ setApprovedOnStart(processInstance);
|
|
|
+
|
|
|
+ if ("1".equals(getWorkflowDetail(workflowId).getCreatorQuickAuditFlag())) {
|
|
|
+ // 跳过相邻步骤是同一人
|
|
|
+ skipAdjacentSameApprover(processInstance);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String activateInstance(String workflowId, String businessKey) {
|
|
|
+ ProcessInstance instance = ActivitiProcessUtils.findInstanceByWorkflowIdAndBusinessKey(workflowId, businessKey);
|
|
|
+ String currentWorkflowId = reaunchAudit(instance.getId());
|
|
|
+ if (!workflowId.equals(currentWorkflowId)) {
|
|
|
+ return currentWorkflowId;
|
|
|
+ }
|
|
|
+
|
|
|
+ String processExecutionId = instance.getId();
|
|
|
+
|
|
|
+ // 首先激活流程实例,否则跳转不了
|
|
|
+ runtimeService.activateProcessInstanceById(instance.getId());
|
|
|
+
|
|
|
+ // 设置审核历史用变量
|
|
|
+ String startInfos = ActivitiProcessUtils.getProcessVariable(processExecutionId,
|
|
|
+ ActivitiVariableNameConstants.START_INFOS, String.class);
|
|
|
+ String staffId = null == getCurrentUserId() ? instance.getStartUserId() : getCurrentUserId();
|
|
|
+
|
|
|
+ String startInfo = getStartInfo(staffId, System.currentTimeMillis());
|
|
|
+ if (StringUtils.isEmpty(startInfos)) {
|
|
|
+ startInfos = getStartInfo(staffId, instance.getStartTime().getTime()) + "," + startInfo;
|
|
|
+ } else {
|
|
|
+ startInfos = startInfos + "," + startInfo;
|
|
|
+ }
|
|
|
+ ActivitiProcessUtils.setProcessVariable(processExecutionId, ActivitiVariableNameConstants.START_INFOS,
|
|
|
+ startInfos);
|
|
|
+
|
|
|
+ // 获取跳转用变量
|
|
|
+ String jumpPreTaskId = ActivitiProcessUtils.getProcessVariable(processExecutionId,
|
|
|
+ ActivitiVariableNameConstants.JUMP_PRE_TASK_ID, String.class);
|
|
|
+ String jumpToUserTaskId = ActivitiProcessUtils.getProcessVariable(processExecutionId,
|
|
|
+ ActivitiVariableNameConstants.JUMP_TO_USER_TASK_ID, String.class);
|
|
|
+
|
|
|
+ // 如果有跳转标识则进行流程跳转
|
|
|
+ if (null != jumpPreTaskId && null != jumpToUserTaskId) {
|
|
|
+ ActivitiTaskUtils.jump(jumpPreTaskId, jumpToUserTaskId);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 清理跳转用变量
|
|
|
+ ActivitiProcessUtils.removeProcessVariable(processExecutionId, ActivitiVariableNameConstants.JUMP_PRE_TASK_ID);
|
|
|
+ ActivitiProcessUtils.removeProcessVariable(processExecutionId,
|
|
|
+ ActivitiVariableNameConstants.JUMP_TO_USER_TASK_ID);
|
|
|
+
|
|
|
+ // 设置当前步骤
|
|
|
+ ActivitiProcessUtils.setProcessVariable(processExecutionId, ActivitiVariableNameConstants.STEP_NUMBER, 1);
|
|
|
+
|
|
|
+ // 跳过占位步骤
|
|
|
+ skipPlaceholder(instance.getProcessInstanceId());
|
|
|
+
|
|
|
+ // 设置审批状态
|
|
|
+ setApprovedOnStart(instance);
|
|
|
+
|
|
|
+ return workflowId;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void suspendInstance(String workflowId, String businessKey) {
|
|
|
+ ProcessInstance instance = ActivitiProcessUtils.findInstanceByWorkflowIdAndBusinessKey(workflowId, businessKey);
|
|
|
+ if (null != instance) {
|
|
|
+ runtimeService.suspendProcessInstanceById(instance.getProcessInstanceId());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void stopInstance(String workflowId, String businessKey, String reason) {
|
|
|
+ ProcessInstance instance = ActivitiProcessUtils.findInstanceByWorkflowIdAndBusinessKey(workflowId, businessKey);
|
|
|
+ if (null != instance) {
|
|
|
+ notifyStatusChanged(workflowId, businessKey, reason);
|
|
|
+
|
|
|
+ deleteProcessInstanceWrapper(instance.getProcessInstanceId(), reason);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void claim(String taskId) {
|
|
|
+ claim(taskId, getCurrentUserId());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void claim(String taskId, String userId) {
|
|
|
+ try {
|
|
|
+ taskService.claim(taskId, userId);
|
|
|
+ } catch (ActivitiTaskAlreadyClaimedException ex) {
|
|
|
+ throw new WorkflowException(WorkflowErrorCodeEnums.TASK_REPEATED_CLAIMED);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void handle(String taskId, boolean approved, String auditMind, boolean needReapply) {
|
|
|
+ // 先签收,保证审核历史有数据
|
|
|
+ claim(taskId);
|
|
|
+
|
|
|
+ Task task = ActivitiTaskUtils.getTaskById(taskId);
|
|
|
+ if (null != task) {
|
|
|
+ ProcessInstance instance = ActivitiProcessUtils.getInstanceById(task.getProcessInstanceId());
|
|
|
+ String processExecutionId = instance.getId();
|
|
|
+
|
|
|
+ // 设置任务自己的变量信息
|
|
|
+ ActivitiTaskUtils.setTaskVariableLocal(taskId, ActivitiVariableNameConstants.APPROVAL_FLAG, approved);
|
|
|
+ ActivitiTaskUtils.setTaskVariableLocal(taskId, ActivitiVariableNameConstants.AUDIT_MIND, auditMind);
|
|
|
+ ActivitiTaskUtils.setTaskVariableLocal(taskId, ActivitiVariableNameConstants.OPERATOR_USER_ID,
|
|
|
+ getCurrentUserId());
|
|
|
+
|
|
|
+ // 设置流程id
|
|
|
+ ActivitiProcessUtils.setProcessVariable(processExecutionId,
|
|
|
+ ActivitiVariableNameConstants.TASK_DEFINITION_KEY, task.getTaskDefinitionKey());
|
|
|
+
|
|
|
+ // 如果是会签则增加访问计数
|
|
|
+ if (ActivitiCountersignUtils.isCountersignTask(task)) {
|
|
|
+ ActivitiCountersignUtils.increaseLoopCounter(task.getId());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 通过
|
|
|
+ if (approved) {
|
|
|
+ // 当前状态,如果节点没有走下去(会签),会用作状态恢复
|
|
|
+ String currentStatus = ActivitiProcessUtils.getProcessVariable(instance.getId(),
|
|
|
+ ActivitiVariableNameConstants.APPROVAL_STATUS, String.class);
|
|
|
+
|
|
|
+ // 更新最后审批状态
|
|
|
+ ActivitiProcessUtils.setProcessVariable(processExecutionId, ActivitiVariableNameConstants.APPROVAL_FLAG,
|
|
|
+ approved);
|
|
|
+
|
|
|
+ // 将状态先至诚“已完成”,解决流程结束状态改变不了问题
|
|
|
+ ActivitiProcessUtils.setProcessVariable(instance.getId(), ActivitiVariableNameConstants.APPROVAL_STATUS,
|
|
|
+ "已完成");
|
|
|
+
|
|
|
+ // 设置流程
|
|
|
+ ActivitiProcessUtils.setProcessVariable(processExecutionId,
|
|
|
+ ActivitiVariableNameConstants.TASK_DEFINITION_KEY, task.getTaskDefinitionKey());
|
|
|
+
|
|
|
+ taskService.complete(taskId, getConditionMap(instance.getProcessInstanceId()));
|
|
|
+
|
|
|
+ // 记录当前是哪个步骤
|
|
|
+ Task activeTask = ActivitiTaskUtils.getActiveTask(instance.getProcessInstanceId());
|
|
|
+ if (null != activeTask) {
|
|
|
+ String definitionKey = ActivitiProcessUtils.getProcessVariable(processExecutionId,
|
|
|
+ ActivitiVariableNameConstants.TASK_DEFINITION_KEY, String.class);
|
|
|
+ if (!StringUtils.isEmpty(definitionKey)
|
|
|
+ && !definitionKey.equals(activeTask.getTaskDefinitionKey())) {
|
|
|
+ Integer stepNumber = ActivitiProcessUtils.getProcessVariable(processExecutionId,
|
|
|
+ ActivitiVariableNameConstants.STEP_NUMBER, Integer.class);
|
|
|
+ if (null != stepNumber) {
|
|
|
+ ActivitiProcessUtils.setProcessVariable(processExecutionId,
|
|
|
+ ActivitiVariableNameConstants.STEP_NUMBER, ++stepNumber);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 跳过占位步骤
|
|
|
+ skipPlaceholder(instance.getProcessInstanceId());
|
|
|
+
|
|
|
+ // 设置审批状态
|
|
|
+ setApprovedStatusOnApproved(instance, task, currentStatus);
|
|
|
+
|
|
|
+ if ("1".equals(getWorkflowDetail(instance.getProcessDefinitionKey()).getSkipAdjacentFlag())) {
|
|
|
+ // 跳过相邻步骤是同一人
|
|
|
+ skipAdjacentSameApprover(instance);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ // 拒绝
|
|
|
+ else {
|
|
|
+ if (ActivitiCountersignUtils.isCountersignTask(task)
|
|
|
+ && !ActivitiCountersignUtils.canCompleteCountersign(task)
|
|
|
+ || !ActivitiCountersignUtils.isCountersignTask(task)) {
|
|
|
+
|
|
|
+ // 更新最后审批状态
|
|
|
+ // 必须先执行,否则流程挂起执行不了
|
|
|
+ ActivitiProcessUtils.setProcessVariable(processExecutionId,
|
|
|
+ ActivitiVariableNameConstants.APPROVAL_FLAG, approved);
|
|
|
+
|
|
|
+ // 驳回
|
|
|
+ reject(task, needReapply);
|
|
|
+
|
|
|
+ // 发送申请被拒绝通知,申请被驳回
|
|
|
+ notifyApplicationRejected(instance.getProcessDefinitionKey(), instance.getBusinessKey(), true,
|
|
|
+ needReapply);
|
|
|
+ } else {
|
|
|
+ // 发送申请被拒绝通知,申请还在进行中
|
|
|
+ notifyApplicationRejected(instance.getProcessDefinitionKey(), instance.getBusinessKey(), false,
|
|
|
+ needReapply);
|
|
|
+
|
|
|
+ // 删除任务
|
|
|
+ managementService.executeCommand(new DeleteTaskCmd(taskId));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ String businessId = instance.getBusinessKey();
|
|
|
+ String taskName = task.getName();
|
|
|
+ String staffId = getCurrentUserId();
|
|
|
+ saveHistory(businessId, taskName, staffId, auditMind, approved);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Page<Object> getTaskList(List<String> workflowIds, int current, int size) {
|
|
|
+ TaskQuery taskQuery = ActivitiTaskUtils.getTaskQueryByUserAndRoles(getCurrentUserId(), getCurrentUserRoles(),
|
|
|
+ workflowIds);
|
|
|
+ List<TaskInfo> tasks = taskQuery.listPage((current - 1) * size, size).stream().map(task -> (TaskInfo) task)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ return generateIPage(current, size, taskQuery.count(), getTaskDetailInfos(workflowIds.get(0), tasks));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<String> getTaskBusinessKeysByCode(String businessCode) {
|
|
|
+ List<String> workflowIds = findWorkflowIdsByBusinessCode(businessCode);
|
|
|
+ if (CollectionUtils.isEmpty(workflowIds)) {
|
|
|
+ return new ArrayList<>();
|
|
|
+ }
|
|
|
+ return getTaskBusinessKeys(workflowIds);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<String> getTaskBusinessKeysByFlowId(String workflowId) {
|
|
|
+ return getTaskBusinessKeys(Lists.newArrayList(workflowId));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<String> getDoneTaskBusinessKeysByCode(String businessCode) {
|
|
|
+ List<String> doneTaskBusinessKeys = workflowHistoryService
|
|
|
+ .getCheckerHisInstBusinessKeysByCode(getCurrentUserId(), businessCode);
|
|
|
+
|
|
|
+ // 删除待办任务
|
|
|
+ List<String> currentTaskBusinessKeys = getTaskBusinessKeysByCode(businessCode);
|
|
|
+ doneTaskBusinessKeys.removeAll(currentTaskBusinessKeys);
|
|
|
+
|
|
|
+ return doneTaskBusinessKeys;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<String> getDoneTaskBusinessKeysByFlowId(String workflowId) {
|
|
|
+ List<String> doneTaskBusinessKeys = workflowHistoryService
|
|
|
+ .getCheckerHisInstBusinessKeysByFlowId(getCurrentUserId(), workflowId);
|
|
|
+
|
|
|
+ // 删除待办任务
|
|
|
+ List<String> currentTaskBusinessKeys = getTaskBusinessKeysByFlowId(workflowId);
|
|
|
+ doneTaskBusinessKeys.removeAll(currentTaskBusinessKeys);
|
|
|
+
|
|
|
+ return doneTaskBusinessKeys;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public JSONObject getActiveTask(List<String> workflowIds, String businessKey) {
|
|
|
+ Task activeTask = ActivitiTaskUtils.getActiveTask(getCurrentUserId(), getCurrentUserRoles(), workflowIds,
|
|
|
+ businessKey);
|
|
|
+ JSONObject activeTaskJsonObj = new JSONObject();
|
|
|
+ if (activeTask != null) {
|
|
|
+ activeTaskJsonObj.put(TASK_QUERY_TASK_ID, activeTask.getId());
|
|
|
+ activeTaskJsonObj.put(TASK_QUERY_TASK_NAME, activeTask.getName());
|
|
|
+ activeTaskJsonObj.put(TASK_QUERY_WORKFLOW_ID, getTaskWorkflowId(activeTask));
|
|
|
+ }
|
|
|
+ return activeTaskJsonObj;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public JSONObject getActiveTask(String staffId, List<String> workflowIds, String businessKey) {
|
|
|
+ List<String> roleIds = AuthSecurityUtils.getUserRoles(staffId).stream().map(CommonRole::getRoleId).collect(Collectors.toList());
|
|
|
+ Task activeTask = ActivitiTaskUtils.getActiveTask(staffId, roleIds, workflowIds,
|
|
|
+ businessKey);
|
|
|
+ JSONObject activeTaskJsonObj = new JSONObject();
|
|
|
+ if (activeTask != null) {
|
|
|
+ activeTaskJsonObj.put(TASK_QUERY_TASK_ID, activeTask.getId());
|
|
|
+ activeTaskJsonObj.put(TASK_QUERY_TASK_NAME, activeTask.getName());
|
|
|
+ activeTaskJsonObj.put(TASK_QUERY_WORKFLOW_ID, getTaskWorkflowId(activeTask));
|
|
|
+ }
|
|
|
+ return activeTaskJsonObj;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Workflow selectById(Serializable id) {
|
|
|
+ return workflowConfigService.selectById(id);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Integer findWorkflowStepNumber(String workflowId, String businessKey) {
|
|
|
+ HistoricProcessInstance historicProcessInstance = ActivitiHistoryUtils.findHistoricProcessInstance(workflowId, businessKey);
|
|
|
+ Map<String, Object> map = historicProcessInstance.getProcessVariables();
|
|
|
+ if (null == map.get(ActivitiVariableNameConstants.STEP_NUMBER)) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ return Integer.parseInt(map.get(ActivitiVariableNameConstants.STEP_NUMBER).toString());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean judgeBusinessLastStep(String taskId) {
|
|
|
+ // 当前任务
|
|
|
+ Task currentTask = taskService.createTaskQuery().taskId(taskId).singleResult();
|
|
|
+ String sequenceFlowId = currentTask.getTaskDefinitionKey() + "-" + "endEvent";
|
|
|
+ // 获取流程定义
|
|
|
+ Process process = ActivitiProcessUtils.getMainProcess(currentTask.getProcessDefinitionId());
|
|
|
+ Map<String, FlowElement> map = process.getFlowElementMap();
|
|
|
+ return map.containsKey(sequenceFlowId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void removeLatestWorkflow(String workflowId) {
|
|
|
+ Workflow workflow = this.selectById(workflowId);
|
|
|
+ if (workflow == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ workflow.setLatest(0);
|
|
|
+ this.updateById(workflow);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 审核被驳回
|
|
|
+ *
|
|
|
+ * @param task task
|
|
|
+ * @param needReapply 是否需要重新申请
|
|
|
+ */
|
|
|
+ private void reject(Task task, boolean needReapply) {
|
|
|
+ ProcessInstance instance = ActivitiProcessUtils.getInstanceById(task.getProcessInstanceId());
|
|
|
+ String processExecutionId = instance.getId();
|
|
|
+ String firstUserTaskId = ActivitiTaskUtils.getFirstUserTask(task.getProcessDefinitionId()).getId();
|
|
|
+
|
|
|
+ // 清除会签变量,防止回退不能完整走会签节点
|
|
|
+ ActivitiCountersignUtils.clearCountersignVars(task);
|
|
|
+
|
|
|
+ // 删除未审批的任务
|
|
|
+ deleteUnapprovedTask(instance.getProcessInstanceId());
|
|
|
+
|
|
|
+ if (needReapply) {
|
|
|
+ // 设置用户重新申请要跳转的节点
|
|
|
+ ActivitiProcessUtils.setProcessVariable(processExecutionId, ActivitiVariableNameConstants.JUMP_PRE_TASK_ID,
|
|
|
+ task.getId());
|
|
|
+ ActivitiProcessUtils.setProcessVariable(processExecutionId,
|
|
|
+ ActivitiVariableNameConstants.JUMP_TO_USER_TASK_ID, firstUserTaskId);
|
|
|
+
|
|
|
+ // 设置审批状态
|
|
|
+ setApprovedStatusOnRejected(instance, task, needReapply);
|
|
|
+
|
|
|
+ // 挂起流程
|
|
|
+ runtimeService.suspendProcessInstanceById(instance.getProcessInstanceId());
|
|
|
+ } else {
|
|
|
+ ActivitiTaskUtils.jump(task.getId(), firstUserTaskId);
|
|
|
+
|
|
|
+ // 跳过占位步骤
|
|
|
+ skipPlaceholder(instance.getProcessInstanceId());
|
|
|
+
|
|
|
+ // 设置审批状态
|
|
|
+ setApprovedStatusOnRejected(instance, task, needReapply);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 重新发起审核流
|
|
|
+ *
|
|
|
+ * @param instanceId 流程实例ID
|
|
|
+ * @return 新流程ID
|
|
|
+ */
|
|
|
+ @SuppressWarnings({"rawtypes", "unchecked"})
|
|
|
+ private String reaunchAudit(String instanceId) {
|
|
|
+ ProcessInstance instance = ActivitiProcessUtils.getInstanceById(instanceId);
|
|
|
+ String businessCode = selectById(instance.getProcessDefinitionKey()).getBusinessCode();
|
|
|
+
|
|
|
+ String staffId = null == getCurrentUserId() ? instance.getStartUserId() : getCurrentUserId();
|
|
|
+ CommonStaff staff = staffService.selectById(staffId);
|
|
|
+
|
|
|
+ Workflow workflow = getLatestWorkflowByBusinessCodeAndCompId(businessCode, staff.getCompId());
|
|
|
+
|
|
|
+ // 如果审核流被修改,则废弃旧的审核流并开启新的审核流
|
|
|
+ if (null != workflow && !workflow.getId().equals(instance.getProcessDefinitionKey())) {
|
|
|
+ deleteProcessInstanceWrapper(instance.getId(), "");
|
|
|
+ startInstance(workflow.getId(), instance.getBusinessKey(), instance.getStartUserId());
|
|
|
+
|
|
|
+ CommonFlowBusinessTable flowBusinessTable = flowBusinessTableService.selectById(businessCode);
|
|
|
+ if (null != flowBusinessTable) {
|
|
|
+ BaseMapper baseMapper = getEntityClassBaseMapperMap()
|
|
|
+ .get(flowBusinessTable.getBusinessTableEntityClass());
|
|
|
+ if (null != baseMapper) {
|
|
|
+ Object entity = baseMapper.selectById(instance.getBusinessKey());
|
|
|
+ if (setEntityWorkflowId(entity, instance.getProcessDefinitionKey(), workflow.getId())) {
|
|
|
+ baseMapper.updateById(entity);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return workflow.getId();
|
|
|
+ }
|
|
|
+ return instance.getProcessDefinitionKey();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取实体中的流程ID
|
|
|
+ *
|
|
|
+ * @param entity 实体
|
|
|
+ * @return 流程ID
|
|
|
+ */
|
|
|
+ private String getEntityWorkflowId(Object entity) {
|
|
|
+ Object workflowId = null;
|
|
|
+
|
|
|
+ try {
|
|
|
+ workflowId = ObjectUtils.getFieldValue(entity, WORKFLOW_ID_FIELD);
|
|
|
+ } catch (Exception e) {
|
|
|
+ // ignore
|
|
|
+ }
|
|
|
+
|
|
|
+ if (null == workflowId) {
|
|
|
+ try {
|
|
|
+ workflowId = ObjectUtils.getFieldValue(entity, WORK_FLOW_ID_FIELD);
|
|
|
+ } catch (Exception e) {
|
|
|
+ // ignore
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null != workflowId ? workflowId.toString() : null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置实体流程ID
|
|
|
+ *
|
|
|
+ * @param entity 实体
|
|
|
+ * @param originalWrkflowId 原流程ID
|
|
|
+ * @param currentWorkflowId 新流程ID
|
|
|
+ * @return 是否设置成功
|
|
|
+ */
|
|
|
+ private boolean setEntityWorkflowId(Object entity, String originalWrkflowId, String currentWorkflowId) {
|
|
|
+ if (null == entity) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ String originalWrkflowIds = getEntityWorkflowId(entity);
|
|
|
+ if (null == originalWrkflowIds || originalWrkflowIds.isEmpty()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ String workflowIds = originalWrkflowIds.replace(originalWrkflowId, currentWorkflowId);
|
|
|
+
|
|
|
+ try {
|
|
|
+ ObjectUtils.setFieldValue(entity, WORKFLOW_ID_FIELD, workflowIds);
|
|
|
+ } catch (Exception e) {
|
|
|
+ // ignore
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ ObjectUtils.setFieldValue(entity, WORK_FLOW_ID_FIELD, workflowIds);
|
|
|
+ } catch (Exception e) {
|
|
|
+ // ignore
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 跳过占位步骤
|
|
|
+ *
|
|
|
+ * @param processInstanceId 流程实例ID
|
|
|
+ */
|
|
|
+ private void skipPlaceholder(String processInstanceId) {
|
|
|
+ Task task = ActivitiTaskUtils.getActiveTask(processInstanceId);
|
|
|
+ if (null != task && "_PLACEHOLDER_".equals(task.getName())) {
|
|
|
+ // 完成占位步骤
|
|
|
+ taskService.complete(task.getId(), getConditionMap(processInstanceId));
|
|
|
+
|
|
|
+ // 跳过占位步骤
|
|
|
+ skipPlaceholder(processInstanceId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除未审批的任务
|
|
|
+ *
|
|
|
+ * @param processInstanceId 流程ID
|
|
|
+ */
|
|
|
+ private void deleteUnapprovedTask(String processInstanceId) {
|
|
|
+ ActivitiTaskUtils.getActiveTasks(processInstanceId).stream().filter(activeTask -> !activeTask.isSuspended())
|
|
|
+ .filter(activeTask -> null == ActivitiTaskUtils.getTaskVariableLocal(activeTask.getId(),
|
|
|
+ ActivitiVariableNameConstants.APPROVAL_FLAG))
|
|
|
+ .forEach(activeTask -> managementService.executeCommand(new DeleteTaskCmd(activeTask.getId())));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置审批状态,流程启动场景
|
|
|
+ *
|
|
|
+ * @param instance 流程实例
|
|
|
+ */
|
|
|
+ private void setApprovedOnStart(ProcessInstance instance) {
|
|
|
+ Task nextTask = ActivitiTaskUtils.getActiveTask(instance.getProcessInstanceId());
|
|
|
+ String workflowId = instance.getProcessDefinitionKey();
|
|
|
+ String businessKey = instance.getBusinessKey();
|
|
|
+
|
|
|
+ String status = null;
|
|
|
+ if (null == nextTask) {
|
|
|
+ status = "已完成";
|
|
|
+ } else {
|
|
|
+ status = "待" + nextTask.getName();
|
|
|
+ ActivitiProcessUtils.setProcessVariable(instance.getId(), ActivitiVariableNameConstants.APPROVAL_STATUS,
|
|
|
+ status);
|
|
|
+ }
|
|
|
+ notifyStatusChanged(workflowId, businessKey, status);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置审批状态,审核通过场景
|
|
|
+ *
|
|
|
+ * @param instance 流程实例
|
|
|
+ * @param preTask 上一步
|
|
|
+ * @param currentStatus 当前状态
|
|
|
+ */
|
|
|
+ private void setApprovedStatusOnApproved(ProcessInstance instance, Task preTask, String currentStatus) {
|
|
|
+ Task nextTask = ActivitiTaskUtils.getActiveTask(instance.getProcessInstanceId());
|
|
|
+ String workflowId = instance.getProcessDefinitionKey();
|
|
|
+ String businessKey = instance.getBusinessKey();
|
|
|
+
|
|
|
+ String status = null;
|
|
|
+ if (null != nextTask) {
|
|
|
+ if (!nextTask.getTaskDefinitionKey().equals(preTask.getTaskDefinitionKey())) {
|
|
|
+ status = "待" + nextTask.getName();
|
|
|
+ } else {
|
|
|
+ status = currentStatus;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ notifyStatusChanged(workflowId, businessKey, "已完成");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (null != status) {
|
|
|
+ ActivitiProcessUtils.setProcessVariable(instance.getId(), ActivitiVariableNameConstants.APPROVAL_STATUS,
|
|
|
+ status);
|
|
|
+
|
|
|
+ notifyStatusChanged(workflowId, businessKey, status);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 结束流程
|
|
|
+ *
|
|
|
+ * @param processInstanceId 流程实例ID
|
|
|
+ * @param deleteReason 结束原因
|
|
|
+ */
|
|
|
+ private void deleteProcessInstanceWrapper(String processInstanceId, String deleteReason) {
|
|
|
+ try {
|
|
|
+ ContextWrapper.getApplicationContext().getBean(this.getClass()).deleteProcessInstance(processInstanceId,
|
|
|
+ deleteReason);
|
|
|
+ } catch (ActivitiObjectNotFoundException ex) {
|
|
|
+ // 流程已结束
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 结束流程
|
|
|
+ *
|
|
|
+ * @param processInstanceId 流程实例ID
|
|
|
+ * @param deleteReason 结束原因
|
|
|
+ */
|
|
|
+ @Transactional(propagation = Propagation.NESTED)
|
|
|
+ public void deleteProcessInstance(String processInstanceId, String deleteReason) {
|
|
|
+ runtimeService.deleteProcessInstance(processInstanceId, deleteReason);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置审批状态,审核不通过场景
|
|
|
+ *
|
|
|
+ * @param instance 流程实例
|
|
|
+ * @param preTask 上一步
|
|
|
+ * @param needReapply 是否需要重新申请
|
|
|
+ */
|
|
|
+ private void setApprovedStatusOnRejected(ProcessInstance instance, Task preTask, Boolean needReapply) {
|
|
|
+ Task nextTask = ActivitiTaskUtils.getActiveTask(instance.getProcessInstanceId());
|
|
|
+ String workflowId = instance.getProcessDefinitionKey();
|
|
|
+ String businessKey = instance.getBusinessKey();
|
|
|
+
|
|
|
+ String status = null;
|
|
|
+ if (needReapply) {
|
|
|
+ status = preTask.getName() + "失败";
|
|
|
+ } else {
|
|
|
+ status = "待" + nextTask.getName();
|
|
|
+ }
|
|
|
+
|
|
|
+ ActivitiProcessUtils.setProcessVariable(instance.getId(), ActivitiVariableNameConstants.APPROVAL_STATUS,
|
|
|
+ status);
|
|
|
+
|
|
|
+ notifyStatusChanged(workflowId, businessKey, status);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 通知状态变更
|
|
|
+ *
|
|
|
+ * @param workflowId 工作流ID
|
|
|
+ * @param businessKey 业务ID
|
|
|
+ * @param status 状态
|
|
|
+ */
|
|
|
+ private void notifyStatusChanged(String workflowId, String businessKey, String status) {
|
|
|
+ boolean processIsEnd = "已完成".equals(status);
|
|
|
+ String compId = null;
|
|
|
+ User user = AuthSecurityUtils.getCurrentUserInfo();
|
|
|
+ if (null != user) {
|
|
|
+ compId = user.getCompId();
|
|
|
+ } else {
|
|
|
+ ProcessInstance processInstance = ActivitiProcessUtils.findInstanceByWorkflowIdAndBusinessKey(workflowId,
|
|
|
+ businessKey);
|
|
|
+ compId = staffService.selectById(processInstance.getStartUserId()).getCompId();
|
|
|
+ }
|
|
|
+
|
|
|
+ String statusEn = languageChangeService.findLanguageBySourceType(compId, LanguageChange.LanguageStataus.CHINESE,
|
|
|
+ processIsEnd ? status : status.substring(1), LanguageChange.LanguageStataus.ENGLISH);
|
|
|
+ notify(workflowId, taskListener -> taskListener.handleStatusChanged(businessKey, status,
|
|
|
+ !StringUtils.isEmpty(statusEn) ? "Waiting for the " + statusEn : null, processIsEnd));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 通知申请被拒绝
|
|
|
+ *
|
|
|
+ * @param workflowId 工作流ID
|
|
|
+ * @param businessKey 业务ID
|
|
|
+ * @param applicationRepulsed 申请被打回
|
|
|
+ * @param needReapply 是否需要重新填写
|
|
|
+ */
|
|
|
+ private void notifyApplicationRejected(String workflowId, String businessKey, boolean applicationRepulsed,
|
|
|
+ boolean needReapply) {
|
|
|
+ notify(workflowId, taskListener -> {
|
|
|
+ if (applicationRepulsed) {
|
|
|
+ taskListener.handleRejectApplicationRepulsed(workflowId, businessKey, needReapply);
|
|
|
+ } else {
|
|
|
+ taskListener.handleRejectApplicationProcessing(workflowId, businessKey);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 通知
|
|
|
+ *
|
|
|
+ * @param workflowId 工作流ID
|
|
|
+ * @param consumer 通知业务
|
|
|
+ */
|
|
|
+ private void notify(String workflowId, Consumer<AbstractWorkflowTaskListener> consumer) {
|
|
|
+ List<WorkflowListener> workflowListeners = workflowListenerService.findByFlowId(workflowId);
|
|
|
+
|
|
|
+ // 调用默认任务监听器
|
|
|
+ final String defaultTaskListenerId = "defaultWorkflowTaskListener";
|
|
|
+ WorkflowListener defaultWorkflowTaskListener = workflowListeners.stream()
|
|
|
+ .filter(workflowListener -> defaultTaskListenerId.equals(workflowListener.getListenerId())).findAny()
|
|
|
+ .orElse(null);
|
|
|
+ if (null == defaultWorkflowTaskListener) {
|
|
|
+ AbstractWorkflowTaskListener defaultTaskListener = ContextWrapper.getApplicationContext()
|
|
|
+ .getBean(defaultTaskListenerId, AbstractWorkflowTaskListener.class);
|
|
|
+ consumer.accept(defaultTaskListener);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 通知
|
|
|
+ workflowListeners.stream().forEach(workflowListener -> {
|
|
|
+ AbstractWorkflowTaskListener taskListener = ContextWrapper.getApplicationContext()
|
|
|
+ .getBean(workflowListener.getListenerId(), AbstractWorkflowTaskListener.class);
|
|
|
+ consumer.accept(taskListener);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取流程分支条件
|
|
|
+ *
|
|
|
+ * @param processInstanceId 流程ID
|
|
|
+ * @return 分支条件
|
|
|
+ */
|
|
|
+ private Map<String, Object> getConditionMap(String processInstanceId) {
|
|
|
+ ProcessInstance processInstance = ActivitiProcessUtils.getInstanceById(processInstanceId);
|
|
|
+ Workflow workflow = selectById(processInstance.getProcessDefinitionKey());
|
|
|
+
|
|
|
+ Map<String, Object> conditionValueMap = null;
|
|
|
+ if (null != workflow) {
|
|
|
+ IWorkflowTaskChecklist<?> checklistImpl = getChecklistImpl(workflow.getChecklistId());
|
|
|
+ if (null != checklistImpl) {
|
|
|
+ conditionValueMap = checklistImpl.getCondtionValueMap(processInstance.getBusinessKey());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null != conditionValueMap ? conditionValueMap : new HashMap<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取任务详情
|
|
|
+ *
|
|
|
+ * @param workflowId 工作流ID
|
|
|
+ * @param tasks 任务列表
|
|
|
+ * @return 任务详情列表
|
|
|
+ */
|
|
|
+ private JSONArray getTaskDetailInfos(String workflowId, List<TaskInfo> tasks) {
|
|
|
+ Workflow workflow = selectById(workflowId);
|
|
|
+ IWorkflowTaskChecklist<?> checklistImpl = getChecklistImpl(workflow.getChecklistId());
|
|
|
+ if (null == workflow.getChecklistId() || null == checklistImpl) {
|
|
|
+ JSONArray jsonArray = new JSONArray();
|
|
|
+ tasks.forEach(task -> jsonArray.add(getTaskJsonInfo(task)));
|
|
|
+ return jsonArray;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 通过checklist服务获取具体record对象
|
|
|
+ List<?> results = checklistImpl.getRecords(tasks.stream()
|
|
|
+ .map(task -> ActivitiProcessUtils.getInstanceById(task.getProcessInstanceId()).getBusinessKey())
|
|
|
+ .collect(Collectors.toList()));
|
|
|
+
|
|
|
+ // 为checklist添加任务Id和任务名称
|
|
|
+ JSONArray jsonArray = JSONObject.parseArray(JSONObject.toJSONString(results));
|
|
|
+ for (int i = 0; i < jsonArray.size(); i++) {
|
|
|
+ JSONObject taskJsonObj = jsonArray.getJSONObject(i);
|
|
|
+ taskJsonObj.putAll(getTaskJsonInfo(tasks.get(i)));
|
|
|
+
|
|
|
+ // 设置审核状态
|
|
|
+ String approvalStatus = ActivitiProcessUtils.getProcessVariable(tasks.get(i).getProcessInstanceId(),
|
|
|
+ ActivitiVariableNameConstants.APPROVAL_STATUS, String.class);
|
|
|
+ taskJsonObj.put(ActivitiVariableNameConstants.APPROVAL_STATUS, approvalStatus);
|
|
|
+ }
|
|
|
+ return jsonArray;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取任务JSON信息
|
|
|
+ *
|
|
|
+ * @param task 任务信息
|
|
|
+ * @return 任务JSON信息
|
|
|
+ */
|
|
|
+ private JSONObject getTaskJsonInfo(TaskInfo task) {
|
|
|
+ JSONObject taskJsonObj = new JSONObject();
|
|
|
+ taskJsonObj.put(TASK_QUERY_TASK_ID, task.getId());
|
|
|
+ taskJsonObj.put(TASK_QUERY_TASK_NAME, task.getName());
|
|
|
+ taskJsonObj.put(TASK_QUERY_WORKFLOW_ID, getTaskWorkflowId(task));
|
|
|
+ taskJsonObj.put(TASK_QUERY_BUSINESS_KEY,
|
|
|
+ ActivitiProcessUtils.getInstanceById(task.getProcessInstanceId()).getBusinessKey());
|
|
|
+ return taskJsonObj;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取checklist实现类
|
|
|
+ *
|
|
|
+ * @param checklistId checklist id
|
|
|
+ * @return checklist实现类
|
|
|
+ */
|
|
|
+ private IWorkflowTaskChecklist<?> getChecklistImpl(String checklistId) {
|
|
|
+ if (StringUtils.isEmpty(checklistId)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ return (IWorkflowTaskChecklist<?>) ContextWrapper.getApplicationContext().getBean(checklistId);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成工作流ID
|
|
|
+ *
|
|
|
+ * @return 工作流ID
|
|
|
+ */
|
|
|
+ private String generateFlowId() {
|
|
|
+ return "_" + IdGenerator.generateLongIncrId(); // 工作流ID规则与Activiti流程ID命名规则保持一致
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取当前用户角色列表
|
|
|
+ *
|
|
|
+ * @return 角色列表
|
|
|
+ */
|
|
|
+ private List<String> getCurrentUserRoles() {
|
|
|
+ return getUserRoles(getCurrentUserId());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取用户角色列表
|
|
|
+ *
|
|
|
+ * @param userId 用户ID
|
|
|
+ * @return 角色列表
|
|
|
+ */
|
|
|
+ private List<String> getUserRoles(String userId) {
|
|
|
+ return AuthSecurityUtils.getUserRoles(userId).stream().map(role -> role.getRoleId())
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取当前用户ID
|
|
|
+ *
|
|
|
+ * @return 当前用户ID
|
|
|
+ */
|
|
|
+ private String getCurrentUserId() {
|
|
|
+ if (!StringUtils.isEmpty(localUserId.get())) {
|
|
|
+ return localUserId.get();
|
|
|
+ }
|
|
|
+ return null == AuthSecurityUtils.getCurrentUserInfo() ? null
|
|
|
+ : AuthSecurityUtils.getCurrentUserInfo().getUserId();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取当前用户所属公司ID
|
|
|
+ *
|
|
|
+ * @return 当前用户所属公司ID
|
|
|
+ */
|
|
|
+ private String getCurrentCompId() {
|
|
|
+ return AuthSecurityUtils.getCurrentUserInfo().getCompId();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成page对象
|
|
|
+ *
|
|
|
+ * @param current 页码
|
|
|
+ * @param size 分页大小
|
|
|
+ * @param total 总数
|
|
|
+ * @param records 数据
|
|
|
+ * @return page
|
|
|
+ */
|
|
|
+ private Page<Object> generateIPage(int current, int size, long total, List<Object> records) {
|
|
|
+ Page<Object> page = new Page<>(current, size);
|
|
|
+ page.setTotal(total);
|
|
|
+ page.setRecords(records);
|
|
|
+ return page;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建工作流步骤和全局监听
|
|
|
+ *
|
|
|
+ * @param workflowId 工作流ID
|
|
|
+ * @param steps 工作流步骤
|
|
|
+ * @param listeners 工作流全局监听器
|
|
|
+ */
|
|
|
+ private void createStepsAndListeners(String workflowId, List<WorkflowStep> steps,
|
|
|
+ List<WorkflowListener> listeners) {
|
|
|
+ // 创建工作流步骤
|
|
|
+ if (!CollectionUtils.isEmpty(steps)) {
|
|
|
+ steps.stream().forEach(step -> step.setWorkflowId(workflowId));
|
|
|
+ workflowStepService.createBatch(steps);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 创建工作流全局监听器
|
|
|
+ if (!CollectionUtils.isEmpty(listeners)) {
|
|
|
+ listeners.stream().forEach(listener -> listener.setWorkflowId(workflowId));
|
|
|
+ workflowListenerService.createBatch(listeners);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取任务工作流ID
|
|
|
+ *
|
|
|
+ * @param task 任务
|
|
|
+ * @return 任务所属工作流ID
|
|
|
+ */
|
|
|
+ private String getTaskWorkflowId(TaskInfo task) {
|
|
|
+ return null != task ? task.getProcessDefinitionId().substring(0, task.getProcessDefinitionId().indexOf(':'))
|
|
|
+ : null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取工作流任务业务编码
|
|
|
+ *
|
|
|
+ * @param workflowIds 工作流ID列表
|
|
|
+ * @return 工作流任务业务编码列表
|
|
|
+ */
|
|
|
+ private List<String> getTaskBusinessKeys(List<String> workflowIds) {
|
|
|
+ return ActivitiTaskUtils.getTaskQueryByUserAndRoles(getCurrentUserId(), getCurrentUserRoles(), workflowIds)
|
|
|
+ .list().stream()
|
|
|
+ .map(task -> ActivitiProcessUtils.getInstanceById(task.getProcessInstanceId()).getBusinessKey())
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
+ private void saveHistory(String businessId, String taskName, String staffId, String auditMind, boolean approved) {
|
|
|
+ AuditHistory auditHistory = new AuditHistory();
|
|
|
+ auditHistory.setBusinessId(businessId);
|
|
|
+ auditHistory.setStaffId(staffId);
|
|
|
+ auditHistory.setTaskName(taskName);
|
|
|
+ auditHistory.setAuditOpinion(auditMind);
|
|
|
+ auditHistory.setAdoptFlag(approved ? "1" : "0");
|
|
|
+ auditHistoryService.create(auditHistory);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 跳过相邻审核人
|
|
|
+ */
|
|
|
+ private void skipAdjacentSameApprover(ProcessInstance instance) {
|
|
|
+ if (null == getCurrentUserId()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 获取服务code
|
|
|
+ String businessCode = selectById(instance.getProcessDefinitionKey()).getBusinessCode();
|
|
|
+
|
|
|
+ String vesselId = null;
|
|
|
+ Map<String, BeanWorkFlowProvider> beanMap = ContextWrapper.getApplicationContext()
|
|
|
+ .getBeansOfType(BeanWorkFlowProvider.class);
|
|
|
+ if (null != beanMap) {
|
|
|
+ BeanWorkFlowProvider service = beanMap
|
|
|
+ .get(StringUtils.underlineToCamel(businessCode.toLowerCase().replace("-", "_")));
|
|
|
+ if (null != service) {
|
|
|
+ vesselId = service.getVesselId(instance.getBusinessKey());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Task task = ActivitiTaskUtils.getActiveTask(getCurrentUserId(), getCurrentUserRoles(),
|
|
|
+ Lists.newArrayList(instance.getProcessDefinitionKey()), instance.getBusinessKey());
|
|
|
+ // 如果业务关联要求过滤船舶
|
|
|
+ if (!StringUtils.isEmpty(vesselId)) {
|
|
|
+ // 1.先获取船舶关联人员
|
|
|
+ List<String> staffIds = staffVesselService.findStaffIdsWithVesselAndRoles(vesselId, getCurrentUserRoles());
|
|
|
+ if (!staffIds.contains(getCurrentUserId())) {
|
|
|
+ return;
|
|
|
+ } else {
|
|
|
+ // 2.查看是否是会签
|
|
|
+ if (task != null && ActivitiCountersignUtils.isCountersignTask(task)) {
|
|
|
+ UserTask userTask = ActivitiTaskUtils.getFirstUserTask(task.getProcessDefinitionId());
|
|
|
+ if (null != userTask) {
|
|
|
+ if (ActivitiCountersignUtils.isCountersignatureTask(userTask)) {
|
|
|
+ handle(task.getId(), true, "_PLACEHOLDER_", false);
|
|
|
+ return;
|
|
|
+ } else {
|
|
|
+ handle(task.getId(), false, "_PLACEHOLDER_", false);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (null != task) {
|
|
|
+ handle(task.getId(), true, "_PLACEHOLDER_", false);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建工作流<br>
|
|
|
+ * 自动判断创建远程的还是本地的
|
|
|
+ */
|
|
|
+ private void buildActivitiWorkflow(Workflow workflow) {
|
|
|
+ String businessCode = workflow.getBusinessCode();
|
|
|
+ String moduleName = businessCode.substring(0, businessCode.indexOf('-')).toLowerCase();
|
|
|
+ String serviceName = moduleName;
|
|
|
+ if (null != workflowProperties.getConsumerModules()) {
|
|
|
+ Entry<String, List<String>> targetEntry = workflowProperties.getConsumerModules().entrySet().stream()
|
|
|
+ .filter(entry -> entry.getValue().contains(moduleName)).findAny().orElse(null);
|
|
|
+ if (null != targetEntry) {
|
|
|
+ serviceName = targetEntry.getKey();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((null != workflowProperties.getConsumers() && workflowProperties.getConsumers().contains(serviceName))) {
|
|
|
+ redisTemplate.opsForList().leftPush("/topic/" + serviceName + "/workflow/build",
|
|
|
+ JSONObject.toJSONString(workflow));
|
|
|
+ } else {
|
|
|
+ new ActivitiWorkflowBuilder(workflow).addFlowElement().addFlowLine().build(processEngine);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private boolean insert(Workflow entity) {
|
|
|
+ return workflowConfigService.insert(entity);
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean updateById(Workflow entity) {
|
|
|
+ return workflowConfigService.updateById(entity);
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getStartInfo(String startUserId, Object startTime) {
|
|
|
+ return (null != startUserId ? startUserId : "") + "|" + (null != startTime ? String.valueOf(startTime) : "");
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, BaseMapper<?>> getEntityClassBaseMapperMap() {
|
|
|
+ if (entityClassBaseMapperMap.isEmpty()) {
|
|
|
+ ContextWrapper.getApplicationContext().getBeansOfType(BaseMapper.class).values().forEach(baseMapper -> {
|
|
|
+ try {
|
|
|
+ Class<?> entityClass = (Class<?>) ((ParameterizedType) (((Class<?>) baseMapper.getClass()
|
|
|
+ .getGenericInterfaces()[0]).getGenericInterfaces()[0])).getActualTypeArguments()[0];
|
|
|
+ entityClassBaseMapperMap.put(entityClass.getName(), baseMapper);
|
|
|
+ } catch (ClassCastException ex) {
|
|
|
+ // ignore
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ return entityClassBaseMapperMap;
|
|
|
+ }
|
|
|
+}
|