activity 撤回工單

package com.dawnpro.wcp.process.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

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.HistoricTaskInstance;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.pvm.process.ProcessDefinitionImpl;
import org.activiti.engine.impl.pvm.process.TransitionImpl;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.dawnpro.dpframework.component.common.BaseService;
import com.dawnpro.dpframework.component.security.pojo.Staff;
import com.dawnpro.dpframework.component.workflow.exception.WorkFlowException;
import com.dawnpro.wcp.process.service.WcpProcessService;

/**
 * @author zhang.wensen1.outs
 * @version 2020-9-22
 */
@Service("wcpProcessService")
@Transactional
public class WcpProcessServiceImpl extends BaseService implements WcpProcessService {

    private static final Logger log = LoggerFactory.getLogger(WcpProcessServiceImpl.class);
    @Autowired
    private TaskService taskService;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private RuntimeService runtimeService;

    /**
     * 撤回工單
     *
     * @param proInsId
     */
    @Override
    public void withdrawTask(String proInsId,String taskKey) {
        try {
            // 根據流程id查詢代辦任務中流程信息
            List<Task> taskList = taskService.createTaskQuery().processInstanceId(proInsId).list();
            if (taskList == null || taskList.size()<=0) {
                log.error("流程未啓動或已執行完成,無法撤回");
                throw new WorkFlowException("流程未啓動或已執行完成,無法撤回", "WorkFlowImpl.startFlow.empty");
            }
            Task task = null;
            for(Task item : taskList) {
                if (item.getTaskDefinitionKey().equals(taskKey)) {
                    task = item;
                }
            }
            if (task == null) {
                log.error("流程未啓動或已執行完成,無法撤回");
                throw new WorkFlowException("流程未啓動或已執行完成,無法撤回", "WorkFlowImpl.startFlow.empty");
            }
            Staff staff = super.getOperatorStaff();
            String userId = staff.getStaffId()+"";
            List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery().processInstanceId(proInsId)
                    .finished()
                    .orderByTaskCreateTime()
                    .desc()
                    .list();
            //判斷上一節點處理人是否爲當前用戶
            HistoricTaskInstance hisTask = null;
            if(htiList != null && htiList.size()>0) {
                HistoricTaskInstance hisTaskObj = htiList.get(0);
                if(userId.equals(hisTaskObj.getAssignee())) {
                    hisTask = hisTaskObj;
                }
            }
            if(null==hisTask || !userId.equals(hisTask.getAssignee())) {
                throw new WorkFlowException("該任務非當前用戶提交,無法撤回","WorkFlowImpl.startFlow.empty");
            }
            // 取回流程接點 當前任務id 取回任務id
            callBackProcess(task.getId(), hisTask.getId());
            // 刪除歷史流程走向記錄
            historyService.deleteHistoricTaskInstance(hisTask.getId());
            historyService.deleteHistoricTaskInstance(task.getId());
        } catch (Exception e) {
            log.error(e + "");
            e.printStackTrace();
            throw new WorkFlowException("內部服務報錯,請聯繫管理員", "WorkFlowImpl.startFlow.empty");
        }
    }

    /**
     * 取回流程
     *
     * @param taskId     當前任務ID
     * @param activityId 取回節點ID
     * @throws Exception
     */
    public void callBackProcess(String taskId, String activityId) throws Exception {
        if (StringUtils.isEmpty(activityId)) {
            throw new Exception("目標節點ID爲空!");
        }

        // 查找所有並行任務節點,同時取回
        List<Task> taskList = findTaskListByKey(findProcessInstanceByTaskId(taskId).getId(),
                findTaskById(taskId).getTaskDefinitionKey());
        for (Task task : taskList) {
            commitProcess(task.getId(), null, activityId);
        }
    }
    
    /**  
     * 根據任務ID獲取對應的流程實例  
     *   
     * @param taskId  
     *            任務ID  
     * @return  
     * @throws Exception  
     */    
    public ProcessInstance findProcessInstanceByTaskId(String taskId)    
            throws Exception {    
        // 找到流程實例    
        ProcessInstance processInstance = runtimeService    
                .createProcessInstanceQuery().processInstanceId(    
                        findTaskById(taskId).getProcessInstanceId())    
                .singleResult();    
        if (processInstance == null) {     
            throw new Exception("流程實例未找到!");    
        }    
        return processInstance;    
    }    
    
    /**  
     * 根據任務ID獲得任務實例  
     *   
     * @param taskId  
     *            任務ID  
     * @return  
     * @throws Exception  
     */    
    private TaskEntity findTaskById(String taskId) throws Exception {    
        TaskEntity task = (TaskEntity) taskService.createTaskQuery().taskId(    
                taskId).singleResult();    
        if (task == null) {    
            throw new Exception("任務實例未找到!");    
        }    
        return task;    
    }
    
    /**  
     * 根據流程實例ID和任務key值查詢所有同級任務集合  
     *   
     * @param processInstanceId  
     * @param key  
     * @return  
     */    
    private List<Task> findTaskListByKey(String processInstanceId, String key) {    
        return taskService.createTaskQuery().processInstanceId(    
                processInstanceId).taskDefinitionKey(key).list();    
    }
    
    /**  
     * 提交流程/流程轉向
     * @param taskId  
     *            當前任務ID  
     * @param variables  
     *            流程變量  
     * @param activityId  
     *            流程轉向執行任務節點ID<br>  
     *            此參數爲空,默認爲提交操作  
     * @throws Exception  
     */    
    private void commitProcess(String taskId, Map<String, Object> variables,    
            String activityId) throws Exception {    
        if (variables == null) {    
            variables = new HashMap<String, Object>();    
        }    
        // 跳轉節點爲空,默認提交操作    
        if (StringUtils.isEmpty(activityId)) {    
            taskService.complete(taskId, variables);    
        } else {// 流程轉向操作    
            turnTransition(taskId, activityId, variables);    
        }    
    }
    
    /**  
     * 流程轉向操作  
     *   
     * @param taskId  
     *            當前任務ID  
     * @param activityId  
     *            目標節點任務ID  
     * @param variables  
     *            流程變量  
     * @throws Exception  
     */    
    private void turnTransition(String taskId, String activityId,    
            Map<String, Object> variables) throws Exception {    
        // 當前節點    
        ActivityImpl currActivity = findActivitiImpl(taskId, null);    
        // 清空當前流向    
        List<PvmTransition> oriPvmTransitionList = clearTransition(currActivity);    
    
        // 創建新流向    
        TransitionImpl newTransition = currActivity.createOutgoingTransition();    
        // 目標節點    
        ActivityImpl pointActivity = findActivitiImpl(taskId, activityId);    
        // 設置新流向的目標節點    
        newTransition.setDestination(pointActivity);    
    
        // 執行轉向任務    
        taskService.complete(taskId, variables);    
        // 刪除目標節點新流入    
        pointActivity.getIncomingTransitions().remove(newTransition);    
    
        // 還原以前流向    
        restoreTransition(currActivity, oriPvmTransitionList);    
    }
    
    /**  
     * 根據任務ID和節點ID獲取活動節點 <br>  
     *   
     * @param taskId  
     *            任務ID  
     * @param activityId  
     *            活動節點ID <br>  
     *            如果爲null或"",則默認查詢當前活動節點 <br>  
     *            如果爲"end",則查詢結束節點 <br>  
     *   
     * @return  
     * @throws Exception  
     */    
    private ActivityImpl findActivitiImpl(String taskId, String activityId)    
            throws Exception {    
        // 取得流程定義    
        ProcessDefinitionEntity processDefinition = findProcessDefinitionEntityByTaskId(taskId);    
    
        // 獲取當前活動節點ID    
        if (StringUtils.isEmpty(activityId)) {    
            activityId = findTaskById(taskId).getTaskDefinitionKey();    
        }else{
        HistoricTaskInstance currTask = historyService
                    .createHistoricTaskInstanceQuery().taskId(activityId)
                    .singleResult();
        activityId = currTask.getTaskDefinitionKey();
        }    
    
        // 根據流程定義,獲取該流程實例的結束節點    
        if (activityId.toUpperCase().equals("END")) {    
            for (ActivityImpl activityImpl : processDefinition.getActivities()) {    
                List<PvmTransition> pvmTransitionList = activityImpl    
                        .getOutgoingTransitions();    
                if (pvmTransitionList.isEmpty()) {    
                    return activityImpl;    
                }    
            }    
        }    
    
        // 根據節點ID,獲取對應的活動節點    
        ActivityImpl activityImpl = ((ProcessDefinitionImpl) processDefinition)    
                .findActivity(activityId);    
    
        return activityImpl;    
    }
    
    
    /**  
     * 根據任務ID獲取流程定義  
     *   
     * @param taskId  
     *            任務ID  
     * @return  
     * @throws Exception  
     */    
    public ProcessDefinitionEntity findProcessDefinitionEntityByTaskId(    
            String taskId) throws Exception {    
        // 取得流程定義    
        ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)    
                .getDeployedProcessDefinition(findTaskById(taskId)    
                        .getProcessDefinitionId());    
    
        if (processDefinition == null) {    
            throw new Exception("流程定義未找到!");    
        }    
    
        return processDefinition;    
    }
    
    /**  
     * 清空指定活動節點流向  
     *   
     * @param activityImpl  
     *            活動節點  
     * @return 節點流向集合  
     */    
    private List<PvmTransition> clearTransition(ActivityImpl activityImpl) {    
        // 存儲當前節點所有流向臨時變量    
        List<PvmTransition> oriPvmTransitionList = new ArrayList<PvmTransition>();    
        // 獲取當前節點所有流向,存儲到臨時變量,然後清空    
        List<PvmTransition> pvmTransitionList = activityImpl    
                .getOutgoingTransitions();    
        for (PvmTransition pvmTransition : pvmTransitionList) {    
            oriPvmTransitionList.add(pvmTransition);    
        }    
        pvmTransitionList.clear();    
    
        return oriPvmTransitionList;    
    }
    
    /**  
     * 還原指定活動節點流向  
     *   
     * @param activityImpl  
     *            活動節點  
     * @param oriPvmTransitionList  
     *            原有節點流向集合  
     */    
    private void restoreTransition(ActivityImpl activityImpl,    
            List<PvmTransition> oriPvmTransitionList) {    
        // 清空現有流向    
        List<PvmTransition> pvmTransitionList = activityImpl    
                .getOutgoingTransitions();    
        pvmTransitionList.clear();    
        // 還原以前流向    
        for (PvmTransition pvmTransition : oriPvmTransitionList) {    
            pvmTransitionList.add(pvmTransition);    
        }    
    }    

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章