358 lines
18 KiB
Java
358 lines
18 KiB
Java
package cn.palmte.work.service;
|
||
|
||
|
||
import cn.palmte.work.bean.ApproveStatusEnum;
|
||
import cn.palmte.work.config.activiti.ActConstant;
|
||
import cn.palmte.work.config.activiti.ActTaskIndexEnum;
|
||
import cn.palmte.work.model.ActTaskDefRepository;
|
||
import cn.palmte.work.model.ProjectTaskRecord;
|
||
import cn.palmte.work.pojo.ActProcIns;
|
||
import cn.palmte.work.utils.ActUtil;
|
||
import cn.palmte.work.utils.InterfaceUtil;
|
||
import cn.palmte.work.utils.StrKit;
|
||
import com.alibaba.fastjson.JSON;
|
||
import org.activiti.bpmn.model.BpmnModel;
|
||
import org.activiti.bpmn.model.FlowNode;
|
||
import org.activiti.bpmn.model.SequenceFlow;
|
||
import org.activiti.engine.HistoryService;
|
||
import org.activiti.engine.RepositoryService;
|
||
import org.activiti.engine.RuntimeService;
|
||
import org.activiti.engine.TaskService;
|
||
import org.activiti.engine.history.HistoricActivityInstance;
|
||
import org.activiti.engine.history.HistoricProcessInstance;
|
||
import org.activiti.engine.impl.identity.Authentication;
|
||
import org.activiti.engine.repository.ProcessDefinition;
|
||
import org.activiti.engine.runtime.ProcessInstance;
|
||
import org.activiti.engine.task.Task;
|
||
import org.apache.commons.lang.StringUtils;
|
||
import org.slf4j.Logger;
|
||
import org.slf4j.LoggerFactory;
|
||
import org.springframework.beans.factory.annotation.Autowired;
|
||
import org.springframework.stereotype.Service;
|
||
import top.jfunc.common.db.QueryHelper;
|
||
import top.jfunc.common.db.bean.Page;
|
||
import top.jfunc.common.db.utils.Pagination;
|
||
|
||
import javax.servlet.http.HttpServletResponse;
|
||
import java.io.IOException;
|
||
import java.util.*;
|
||
import java.util.concurrent.ConcurrentHashMap;
|
||
import java.util.stream.Collectors;
|
||
|
||
|
||
@Service
|
||
public class ActProcInsService {
|
||
private static final Logger logger = LoggerFactory.getLogger(ActProcInsService.class);
|
||
@Autowired
|
||
private RepositoryService repositoryService; //管理流程定义 与流程定义和部署对象相关的Service
|
||
@Autowired
|
||
private TaskService taskService; //任务管理 与正在执行的任务管理相关的Service
|
||
|
||
@Autowired
|
||
private AccountService accountService;
|
||
|
||
@Autowired
|
||
private RuntimeService runtimeService; //与正在执行的流程实例和执行对象相关的Service(执行管理,包括启动、推进、删除流程实例等操作)
|
||
|
||
@Autowired
|
||
Pagination pagination;
|
||
|
||
@Autowired
|
||
private ProjectTaskRecordService projectTaskRecordService;
|
||
|
||
@Autowired
|
||
private HistoryService historyService; //历史管理(执行完的数据的管理)
|
||
|
||
@Autowired
|
||
private ActTaskDefRepository actTaskDefRepository;
|
||
|
||
@Autowired
|
||
private ActUtil actUtil;
|
||
|
||
|
||
/**
|
||
* 正常启动流程实列
|
||
*
|
||
* @param procDefKey
|
||
* @param variables
|
||
* @return
|
||
*/
|
||
public String startProcessInstance(String procDefKey, String businessKey, Map<String, Object> variables) throws Exception {
|
||
List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().processDefinitionKey(procDefKey).active().orderByProcessDefinitionVersion().desc().list();
|
||
if (list == null || list.isEmpty()) {
|
||
throw new Exception("procDefKey(" + procDefKey + ")未定义");
|
||
}
|
||
|
||
//取最新版本的流程定义进行启动流程实列
|
||
ProcessDefinition processDefinition = list.get(0);
|
||
|
||
String adminId = InterfaceUtil.getAdminId() + "";
|
||
variables.put(ActConstant.START_PROCESS_USERID, adminId);
|
||
//启动流程
|
||
ProcessInstance instance = runtimeService.startProcessInstanceById(processDefinition.getId(), businessKey, variables);
|
||
logger.info("startProcessInstanceSuccess procInsId:{}, procDefKey:{}, procDefName:{}, variables:{}",
|
||
instance.getId(), instance.getProcessDefinitionKey(), instance.getProcessDefinitionName(), JSON.toJSONString(variables));
|
||
|
||
String procInsId = instance.getProcessInstanceId();
|
||
Task task = taskService.createTaskQuery().processInstanceId(procInsId).singleResult();
|
||
if (task == null) {
|
||
throw new Exception("procDefKey(" + procDefKey + ")启动异常");
|
||
}
|
||
|
||
String taskId = task.getId();
|
||
String comment = "提交" + processDefinition.getName();
|
||
Authentication.setAuthenticatedUserId(adminId);
|
||
taskService.addComment(taskId, procInsId, comment);
|
||
|
||
//设置发起人为办理人 然后完成任务 任务转入下一个审批节点
|
||
taskService.setAssignee(taskId, adminId);
|
||
taskService.complete(taskId);
|
||
|
||
projectTaskRecordService.saveTaskRecord(Integer.parseInt(instance.getBusinessKey()),
|
||
task, ApproveStatusEnum.APPROVAL_PENDING.getApproveStatus(), ActTaskIndexEnum.FIRST_USER_TASK.getIndex(), comment);
|
||
|
||
return instance.getId();
|
||
}
|
||
|
||
|
||
/**
|
||
* 系统启动流程实列
|
||
*
|
||
* @param procDefKey
|
||
* @param businessKey
|
||
* @param variables
|
||
* @return
|
||
* @throws Exception
|
||
*/
|
||
public String startProcessInstanceBySystem(String procDefKey, String businessKey, Map<String, Object> variables,
|
||
ProjectTaskRecord taskRecord) throws Exception {
|
||
List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().processDefinitionKey(procDefKey).active().orderByProcessDefinitionVersion().desc().list();
|
||
if (list == null || list.isEmpty()) {
|
||
throw new Exception("procDefKey(" + procDefKey + ")未定义");
|
||
}
|
||
|
||
//取最新版本的流程定义进行启动流程实列
|
||
ProcessDefinition processDefinition = list.get(0);
|
||
|
||
String adminId = "-1";
|
||
variables.put(ActConstant.START_PROCESS_USERID, adminId);
|
||
//启动流程
|
||
ProcessInstance instance = runtimeService.startProcessInstanceById(processDefinition.getId(), businessKey, variables);
|
||
logger.info("startProcessInstanceSuccess procInsId:{}, procDefKey:{}, procDefName:{}", instance.getId(), instance.getProcessDefinitionKey(), instance.getProcessDefinitionName());
|
||
|
||
String procInsId = instance.getProcessInstanceId();
|
||
Task task = taskService.createTaskQuery().processInstanceId(procInsId).singleResult();
|
||
if (task == null) {
|
||
throw new Exception("procDefKey(" + procDefKey + ")启动异常");
|
||
}
|
||
|
||
String taskId = task.getId();
|
||
String comment = "系统提交" + processDefinition.getName();
|
||
Authentication.setAuthenticatedUserId(adminId);
|
||
taskService.addComment(taskId, procInsId, comment);
|
||
|
||
taskService.setAssignee(taskId, taskRecord.getAssigneeId() + "");
|
||
|
||
return instance.getId();
|
||
}
|
||
|
||
/**
|
||
* 流程实列列表
|
||
*
|
||
* @param searchInfo
|
||
* @param pageNumber
|
||
* @param pageSize
|
||
* @return
|
||
*/
|
||
public Page<ActProcIns> list(ConcurrentHashMap<String, String> searchInfo, int pageNumber, int pageSize) {
|
||
String select = "select h.proc_inst_id_ as procInsId,h.proc_def_id_ as procDefId," +
|
||
"h.start_time_ as startTime,h.end_time_ as endTime,p.key_ as procKey," +
|
||
"p.name_ as procName,p.NAME_ as dgrmResourceName,p.version_ as version," +
|
||
" GROUP_CONCAT(t.NAME_) as currentTask, GROUP_CONCAT(t.ID_) as currentTaskId," +
|
||
" pjct.name as projectName,pp.project_title AS projectTitle";
|
||
QueryHelper queryHelper = new QueryHelper(select, " act_hi_procinst h " +
|
||
"left join ACT_RE_PROCDEF p on h.PROC_DEF_ID_ =p.ID_ " +
|
||
"LEFT JOIN act_ru_task t on t.PROC_INST_ID_=h.proc_inst_id_ " +
|
||
"LEFT JOIN project pjct on pjct.id=h.BUSINESS_KEY_ " +
|
||
"LEFT JOIN project_process pp on pp.id=h.BUSINESS_KEY_ ");
|
||
|
||
String procDefKey = searchInfo.get("procDefKey");
|
||
queryHelper.addCondition(StrKit.notBlank(procDefKey), "p.key_=?", procDefKey);
|
||
|
||
String projectName = searchInfo.get("projectName");
|
||
String projectNameLike = "%" + projectName + "%";
|
||
queryHelper.addCondition(StrKit.notBlank(projectName), " (pjct.name like ? or pp.project_title like ?) ", projectNameLike, projectNameLike);
|
||
|
||
String projectId = searchInfo.get("projectId");
|
||
queryHelper.addCondition(StrKit.notBlank(projectId), "h.BUSINESS_KEY_ =? ", projectId);
|
||
|
||
String procInsId = searchInfo.get("procInsId");
|
||
queryHelper.addCondition(StrKit.notBlank(procInsId), "h.proc_inst_id_ =? ", procInsId);
|
||
|
||
queryHelper.addGroupProperty("h.PROC_INST_ID_");
|
||
queryHelper.addOrderProperty("h.start_time_", false);
|
||
Page<ActProcIns> paginate = pagination.paginate(queryHelper.getSql(), ActProcIns.class, pageNumber, pageSize);
|
||
List<ActProcIns> list = paginate.getList();
|
||
|
||
for (ActProcIns ins : list) {
|
||
//查询流程发起人
|
||
String userId = actUtil.getStartUserId(ins.getProcInsId());
|
||
ins.setUser(accountService.getNameById(Integer.parseInt(userId)));
|
||
|
||
//查询当前任务审批人
|
||
String currentTaskId = ins.getCurrentTaskId();
|
||
if (StringUtils.isNotBlank(currentTaskId)) {
|
||
String[] split = currentTaskId.split(",");
|
||
String candidateUsers = "";
|
||
for (String taskId : split) {
|
||
candidateUsers += actUtil.getAssigneeByIdentityLink(taskId) + ",";
|
||
}
|
||
if (candidateUsers.endsWith(",")) {
|
||
candidateUsers = candidateUsers.substring(0, candidateUsers.length() - 1);
|
||
}
|
||
ins.setCandidateUsers(candidateUsers);
|
||
}
|
||
}
|
||
|
||
return paginate;
|
||
}
|
||
|
||
|
||
public void deleteProcessInstance(String procInsId, String reason) {
|
||
runtimeService.deleteProcessInstance(procInsId, reason);
|
||
}
|
||
|
||
|
||
public void createProcInsPng(HttpServletResponse response, String procInsId) throws IOException {
|
||
try {
|
||
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(procInsId).singleResult(); //获取历史流程实例
|
||
//获取流程中已经执行的节点,按照执行先后顺序排序
|
||
List<HistoricActivityInstance> hai = historyService.createHistoricActivityInstanceQuery().processInstanceId(procInsId).orderByHistoricActivityInstanceStartTime().asc().list();
|
||
// 历史流程节点中
|
||
List<HistoricActivityInstance> newHisActInstanceList = new ArrayList<HistoricActivityInstance>();
|
||
List<HistoricActivityInstance> newHisTaskInstanceList = new ArrayList<HistoricActivityInstance>();
|
||
if (hai != null && hai.size() > 0) {
|
||
for (int i = 0; i < hai.size(); i++) {
|
||
HistoricActivityInstance historicActivityInstance = hai.get(i);
|
||
String activityType = historicActivityInstance.getActivityType();
|
||
if (activityType.equals("startEvent") || activityType.equals("endEvent")) {
|
||
newHisActInstanceList.add(historicActivityInstance);
|
||
} else if (activityType.equals("serviceTask") || activityType.equals("userTask") || activityType.equals("exclusiveGateway") || activityType.equals("parallelGateway")) {
|
||
if (newHisTaskInstanceList.size() > 0) {
|
||
for (int j = 0; j < newHisTaskInstanceList.size(); j++) {
|
||
HistoricActivityInstance historicTaskInstance = newHisTaskInstanceList.get(j);
|
||
if (historicTaskInstance.getActivityId().equals(historicActivityInstance.getActivityId())) { //如果列表中已包括
|
||
newHisTaskInstanceList.clear();
|
||
newHisTaskInstanceList.add(historicActivityInstance);
|
||
break;
|
||
} else {
|
||
newHisTaskInstanceList.add(historicActivityInstance);
|
||
break;
|
||
}
|
||
}
|
||
} else {
|
||
newHisTaskInstanceList.add(historicActivityInstance);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
for (int i = 0; i < newHisActInstanceList.size(); i++) {
|
||
HistoricActivityInstance historicActivityInstance = newHisActInstanceList.get(i);
|
||
newHisTaskInstanceList.add(historicActivityInstance);
|
||
}
|
||
|
||
List<String> executedActivityIdList = new ArrayList<String>(); // 构造已执行的节点ID集合
|
||
for (HistoricActivityInstance activityInstance : newHisTaskInstanceList) {
|
||
executedActivityIdList.add(activityInstance.getActivityId());
|
||
}
|
||
BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId()); // 获取bpmnModel
|
||
List<String> flowIds = this.getExecutedFlows(bpmnModel, newHisTaskInstanceList); // 获取流程已发生流转的线ID集合
|
||
actUtil.responsePng(response, bpmnModel, executedActivityIdList, flowIds);
|
||
} catch (Exception e) {
|
||
logger.error("an exception happens in try catch statement", e);
|
||
}
|
||
|
||
}
|
||
|
||
public List<String> getExecutedFlows(BpmnModel bpmnModel, List<HistoricActivityInstance> historicActivityInstances) {
|
||
List<String> flowIdList = new ArrayList<String>(); //流转线ID集合
|
||
List<FlowNode> historicFlowNodeList = new LinkedList<FlowNode>(); //全部活动实例
|
||
List<HistoricActivityInstance> finishedActivityInstanceList = new LinkedList<HistoricActivityInstance>(); //已完成的历史活动节点
|
||
List list = new ArrayList();
|
||
|
||
for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
|
||
historicFlowNodeList.add((FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstance.getActivityId(), true));
|
||
if (historicActivityInstance.getEndTime() != null) {
|
||
finishedActivityInstanceList.add(historicActivityInstance);
|
||
}
|
||
|
||
}
|
||
for (int x = 0; x < historicActivityInstances.size(); x++) {
|
||
HistoricActivityInstance historicActivityInstance = historicActivityInstances.get(x);
|
||
String activityType = historicActivityInstance.getActivityType();
|
||
String activityId = historicActivityInstance.getActivityId();
|
||
if (!list.contains(activityId) && ("userTask".equals(activityType)
|
||
|| "serviceTask".equals(activityType)
|
||
|| "endEvent".equals(activityType)
|
||
|| "exclusiveGateway".equals(activityType)
|
||
|| "parallelGateway".equals(activityType))) {
|
||
list.add(activityId);
|
||
}
|
||
}
|
||
/**遍历已完成的活动实例,从每个实例的outgoingFlows中找到已执行的*/
|
||
FlowNode currentFlowNode = null;
|
||
for (HistoricActivityInstance currentActivityInstance : finishedActivityInstanceList) {
|
||
/**获得当前活动对应的节点信息及outgoingFlows信息*/
|
||
currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currentActivityInstance.getActivityId(), true);
|
||
List<SequenceFlow> sequenceFlowList = currentFlowNode.getOutgoingFlows();
|
||
/**
|
||
* 遍历outgoingFlows并找到已流转的
|
||
* 满足如下条件任务已流转:
|
||
* 1.当前节点是并行网关或包含网关,则通过outgoingFlows能够在历史活动中找到的全部节点均为已流转
|
||
* 2.当前节点是以上两种类型之外的,通过outgoingFlows查找到的时间最近的流转节点视为有效流转
|
||
*/
|
||
FlowNode targetFlowNode = null;
|
||
if ("parallelGateway".equals(currentActivityInstance.getActivityType())
|
||
|| "inclusiveGateway".equals(currentActivityInstance.getActivityType())) {
|
||
for (SequenceFlow sequenceFlow : sequenceFlowList) { //遍历历史活动节点,找到匹配Flow目标节点的
|
||
targetFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(sequenceFlow.getTargetRef(), true);
|
||
if (historicFlowNodeList.contains(targetFlowNode)) {
|
||
flowIdList.add(sequenceFlow.getId());
|
||
}
|
||
}
|
||
} else {
|
||
List<Map<String, String>> tempMapList = new LinkedList<Map<String, String>>();
|
||
// for(SequenceFlow sequenceFlow : sequenceFlowList) { //遍历历史活动节点,找到匹配Flow目标节点的
|
||
for (int i = 0; i < sequenceFlowList.size(); i++) { //遍历历史活动节点,找到匹配Flow目标节点的
|
||
SequenceFlow sequenceFlow = sequenceFlowList.get(i);
|
||
int taskSeq = list.indexOf(sequenceFlow.getSourceRef()); // 获取当前flow目标节点key在审批顺序
|
||
String nextTaskKey = ""; // 下一个任务节点
|
||
String beforeTaskKey = sequenceFlow.getSourceRef(); //上一个任务节点
|
||
|
||
if ((taskSeq + 1) < list.size()) { // 判断下一个任务节点是否存在
|
||
nextTaskKey = String.valueOf(list.get((taskSeq + 1)));
|
||
}
|
||
if (taskSeq == list.size() - 1) {
|
||
nextTaskKey = String.valueOf(list.get((taskSeq)));
|
||
}
|
||
for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
|
||
if (historicActivityInstance.getActivityId().equals(sequenceFlow.getTargetRef()) && sequenceFlow.getSourceRef().equals(beforeTaskKey) && sequenceFlow.getTargetRef().equals(nextTaskKey)) {
|
||
Map<String, String> map = new HashMap<>();
|
||
map.put("flowId", sequenceFlow.getId());
|
||
map.put("activityStartTime", String.valueOf(historicActivityInstance.getStartTime().getTime()));
|
||
tempMapList.add(map);
|
||
}
|
||
}
|
||
}
|
||
String flowId = null;
|
||
for (Map<String, String> map : tempMapList) {
|
||
flowId = map.get("flowId");
|
||
flowIdList.add(flowId);
|
||
}
|
||
|
||
}
|
||
}
|
||
return flowIdList;
|
||
}
|
||
}
|