fourcal/src/main/java/cn/palmte/work/service/ActProcInsService.java

358 lines
18 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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;
}
}