1. 程式人生 > >專案整合Activiti關聯業務(二)

專案整合Activiti關聯業務(二)

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;

import javax.annotation.Resource;

import org.activiti.engine.FormService;
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.history.HistoricVariableInstance;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;


/**
 * Activiti工作流引擎  核心 service
 * @author nuohy  
 * @Description: TODO   
 * @date 2017年7月21日
 */
@Service(value="actworkflowservice")
@Transactional
public class ActWorkFlowCommServiceImpl implements IActWorkFlowCommService{

	@Resource(name="repositoryService")
	private RepositoryService repositoryService;
	
	@Resource(name="runtimeService")
	private RuntimeService runtimeService;
	
	@Resource(name="taskService")
	private TaskService taskService;
	
	@Resource(name="formService")
	private FormService formService;
	
	@Resource(name="historyService")
	private HistoryService historyService;
	
	@Resource(name="leavebilldao")
	private ILeaveBillDao leavebilldao;

	@Resource(name="rebMoneyDao")
	private IRebMoneyDao rebMoneyDao;
	
	@Resource(name="approvalBeanConfDao")
	private IApprovalBeanConfDao approvalBeanConfDao;
	
	/**
	 * 部署流程定義
	 */
	@Override
	public boolean saveNewDeploy(String filepath,String filename) {
		boolean returnflag  = true;
		ZipInputStream zipInputStream;
		try {
			
			System.out.println(filepath);
			
			zipInputStream = new ZipInputStream(new FileInputStream(new File(filepath)));
			repositoryService.createDeployment()
				.name(filename)
				.addZipInputStream(zipInputStream)
				.deploy();
			System.out.println("部署完成!");
			return returnflag;
		} catch (FileNotFoundException e) {
			returnflag = false;
			e.printStackTrace();
		}
		return returnflag;
	}

	/**
	 * 查詢部署物件資訊
	 */
	@Override
	public List<FDeployment> findDeployList() {
		List<FDeployment> relist = null;
		List<Deployment> list = repositoryService.createDeploymentQuery().orderByDeploymenTime().desc().list();
		if(list!=null&&list.size()>0){
			relist = new ArrayList<FDeployment>();
			for (Deployment dm : list) {
				FDeployment fDeployment = new FDeployment(dm.getId(), dm.getName(), dm.getDeploymentTime(), dm.getCategory(), dm.getTenantId());
				relist.add(fDeployment);
				System.err.println(fDeployment.toString());
			}
		}
		return relist;
	}
	
	
	/**
	 * 刪除部署資訊 
	 */
	@Override
	public boolean deldeployment(String deploymentid) {
		try{
			repositoryService.deleteDeployment(deploymentid, true);
		}catch(Exception e){
			return false;
		}
		return true;
	}
	
	
	
	/**
	 * 啟動流程例項
	 */
	@Override
	public boolean startProcess(String formKey,String userid,String formid) {
		
		//查詢資料庫來確定需要執行哪個
		String customBeanName = approvalBeanConfDao.getApprovalSerBeanById(formKey).getBeanName();
		IActWorkFlowCustomService customService = null;
		if(customBeanName!=null){
			WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
			customService = (IActWorkFlowCustomService)wac.getBean(customBeanName);
			customService.startRunTask(formid);
		}
		
		
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("userid", userid);
		
		//使用流程變數設定字串(格式 : LeaveBill.Id 的形式)
		//使用正在執行物件表中的一個欄位BUSINESS_KEY(Activiti提供的一個欄位),讓啟動的流程(流程例項)關聯業務
		String objId = formKey + "." +formid;
		map.put("objId", objId);
		
		runtimeService.startProcessInstanceByKey(formKey, objId, map);
		return true;
	}
	
	
	
	/**
	 * 查詢流程定義資訊
	 */
	@Override
	public List<FProcessDefinition> findProcessDefinitionList(){
		List<FProcessDefinition> relist = null;
		List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().orderByProcessDefinitionVersion().desc().list();
		if(list!=null&&list.size()>0){
			relist = new ArrayList<FProcessDefinition>();
			for (ProcessDefinition pd : list) {
				FProcessDefinition fProcessDefinition = new FProcessDefinition(pd.getId(), pd.getCategory(), pd.getName(), pd.getKey(), pd.getDescription(), pd.getVersion(), pd.getResourceName(), pd.getDeploymentId(),pd.getDiagramResourceName(), pd.hasStartFormKey(), pd.isSuspended(), pd.getTenantId());
				relist.add(fProcessDefinition);
				System.out.println(fProcessDefinition.toString());
			}
		}
		return relist;
	}
	

	
	/**
	 * 檢視總體流程圖
	 */
	@Override
	public InputStream lookProcessImage(String deploymentid, String imagename) {
		InputStream in = repositoryService.getResourceAsStream(deploymentid, imagename);
		return in;
	}

	
	/**
	 * 檢視當前流程圖(1)
	 * @param taskid
	 */
	@Override
	public ProcessDefinition lookCurrentProcessImage(String taskId) {
		//任務ID
		//1:獲取任務ID,獲取任務物件,使用任務物件獲取流程定義ID,查詢流程定義物件
		//使用任務ID,查詢任務物件
		Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
		//獲取流程定義ID
		String processDefinitionId = task.getProcessDefinitionId();
		//查詢流程定義的物件
		ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()//建立流程定義查詢物件,對應表act_re_procdef 
							.processDefinitionId(processDefinitionId)//使用流程定義ID查詢
							.singleResult();
		return pd;
	}
	
	
	
	/**  檢視當前流程圖(2)	--	公用
	 *   檢視當前活動,獲取當期活動對應的座標x,y,width,height,將4個值存放到Map<String,Object>中
	 * 	 map集合的key:表示座標x,y,width,height
	 * 	 map集合的value:表示座標對應的值
	 */
	@Override
	public Map<String, Object> findCoordingByTask(String taskId) {
		//存放座標
		Map<String, Object> map = new HashMap<String,Object>();
		//使用任務ID,查詢任務物件
		Task task = taskService.createTaskQuery()//
					.taskId(taskId)//使用任務ID查詢
					.singleResult();
		//獲取流程定義的ID
		String processDefinitionId = task.getProcessDefinitionId();
		//獲取流程定義的實體物件(對應.bpmn檔案中的資料)
		ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity)repositoryService.getProcessDefinition(processDefinitionId);
		//流程例項ID
		String processInstanceId = task.getProcessInstanceId();
		//使用流程例項ID,查詢正在執行的執行物件表,獲取當前活動對應的流程例項物件
		ProcessInstance pi = runtimeService.createProcessInstanceQuery()//建立流程例項查詢
					.processInstanceId(processInstanceId)//使用流程例項ID查詢
					.singleResult();
		//獲取當前活動的ID
		String activityId = pi.getActivityId();
		//獲取當前活動物件
		ActivityImpl activityImpl = processDefinitionEntity.findActivity(activityId);//活動ID
		//獲取座標
		map.put("x", activityImpl.getX());
		map.put("y", activityImpl.getY());
		map.put("width", activityImpl.getWidth());
		map.put("height", activityImpl.getHeight());
		
		return map;
	}
	
	
	
	
	@Override
	public ProcessDefinition lookCurrentProcessImgByFormId(String formid, String formKey) {
		Task task = taskService.createTaskQuery().processInstanceBusinessKey(formKey+"."+formid).singleResult();
		String processDefinitionId = task.getProcessDefinitionId();
		ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()//建立流程定義查詢物件,對應表act_re_procdef 
				.processDefinitionId(processDefinitionId)//使用流程定義ID查詢
				.singleResult();
		return pd;
	}
	
	
	
	@Override
	public Map<String, Object> findCoordingByTaskByFormId(String formid, String formKey) {
		
		//存放座標
		Map<String, Object> map = new HashMap<String,Object>();
		
		Task task = taskService.createTaskQuery().processInstanceBusinessKey(formKey+"."+formid).singleResult();
		
		//獲取流程定義的ID
		String processDefinitionId = task.getProcessDefinitionId();
		//獲取流程定義的實體物件(對應.bpmn檔案中的資料)
		ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity)repositoryService.getProcessDefinition(processDefinitionId);
		//流程例項ID
		String processInstanceId = task.getProcessInstanceId();
		//使用流程例項ID,查詢正在執行的執行物件表,獲取當前活動對應的流程例項物件
		ProcessInstance pi = runtimeService.createProcessInstanceQuery()//建立流程例項查詢
					.processInstanceId(processInstanceId)//使用流程例項ID查詢
					.singleResult();
		//獲取當前活動的ID
		String activityId = pi.getActivityId();
		//獲取當前活動物件
		ActivityImpl activityImpl = processDefinitionEntity.findActivity(activityId);//活動ID
		//獲取座標
		map.put("x", activityImpl.getX());
		map.put("y", activityImpl.getY());
		map.put("width", activityImpl.getWidth());
		map.put("height", activityImpl.getHeight());
		
		return map;
	}
	
	
	
	
	
	

	/**
	 * 檢視個人任務列表
	 */
	@Override
	public DataGrid<Map<String, Object>> mytasklist(String userid,PageInfo page) {
		DataGrid<Map<String, Object>> dataGrid = new DataGrid<Map<String, Object>>();
		
		int pagenum = page.getPage();
		int rowsnum = page.getRows();
		
		int firstResult = (pagenum-1)*rowsnum;
		int maxResults = firstResult+rowsnum;
		
		TaskQuery taskQuery = taskService.createTaskQuery().taskAssignee(userid);
		long allcount = taskQuery.count();
		dataGrid.setTotal(allcount);
		
		List<Task> list = taskQuery.orderByTaskCreateTime().desc().listPage(firstResult, maxResults);
		
		List<Map<String, Object>> listmap = new ArrayList<Map<String, Object>>();
		for (Task task : list) {
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("id", task.getId());
			map.put("name", task.getName());
			map.put("description", task.getDescription());
			map.put("priority", task.getPriority());
			map.put("owner", task.getOwner());
			map.put("assignee", task.getAssignee());
			map.put("delegationState", task.getDelegationState());
			map.put("processInstanceId", task.getProcessInstanceId());
			map.put("executionId", task.getExecutionId());
			map.put("processDefinitionId", task.getProcessDefinitionId());
			map.put("createTime", task.getCreateTime());
			map.put("taskDefinitionKey", task.getTaskDefinitionKey());
			map.put("dueDate", task.getDueDate());
			map.put("category", task.getCategory());
			map.put("parentTaskId", task.getParentTaskId());
			map.put("tenantId", task.getTenantId());
			
			Map<String, Object> FormModel_map = findFormModelByTaskId(task.getId());
			//表單中避免使用 hfmx_actWorkFlow_formType 關鍵字
			/*map.put("hfmx_actWorkFlow_formType", FormModel_map.get("hfmx_actWorkFlow_formType"));
			map.put("formid", FormModel_map.get("id"));*/
			
			map.putAll(FormModel_map);
			
			List<Map<String,Object>> searchForMap = leavebilldao.searchForMap("select * from sysuser where id="+task.getAssignee());
			map.put("processUser", searchForMap.get(0).get("name"));
			
			listmap.add(map);
		}
		dataGrid.setRows(listmap);
		
		return dataGrid;
	}

	
	
	
	@Override
	public Map<String, Object> findFormModelByTaskId(String taskId) {
		//任務Id 查詢任務物件
		Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
		
		//任務物件  獲取流程例項Id
		String processInstanceId = task.getProcessInstanceId();

		//流程例項Id 查詢正在執行的執行物件表  返回流程例項物件
		ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
		
		//流程例項物件 獲取 BUSINESS_KEY ,從而獲取表單物件
		String businessKey = processInstance.getBusinessKey();
		String[] split = businessKey.split("\\.");
		
		
		Map<String, Object> map = new HashMap<String,Object>();

		ApprovalBeanConf approvalBeanConf = approvalBeanConfDao.getApprovalSerBeanById(split[0]);
		map.put("hfmx_actWorkFlow_formType", split[0]);
		map.put("showFormUrl", approvalBeanConf.getShowFormUrl());
		map.put("formid", split[1]);
		
		return map;
	}
	
	

	/**
	 * 完成提交任務
	 */
	@Override
	public int completeProcess(String formtype,String remark, String taskId,String userId,String formid,String outcome) {
		
		//任務Id 查詢任務物件
		Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
		
		//任務物件  獲取流程例項Id
		String processInstanceId = task.getProcessInstanceId();
		
		//設定審批人的userId
		Authentication.setAuthenticatedUserId(userId);
		
		//新增記錄
		taskService.addComment(taskId, processInstanceId, remark);
		
		/**
		 * 如果連線的名稱是'預設提交',那麼就不需要設定,如果不是,就需要設定流程變數
		 * 在完成任務之前,設定流程變數,按照連線的名稱,去完成任務
				 流程變數的名稱:outcome
				 流程變數的值:連線的名稱
		 */
		Map<String, Object> variables = new HashMap<String,Object>();
		if(outcome!=null && !outcome.equals("預設提交")){
			variables.put("outcome", outcome);
		}
		
		
		//設定流程變數  條件控制
		String customBean = null;
		
		//查詢資料庫來確定需要執行哪個
		customBean = approvalBeanConfDao.getApprovalSerBeanById(formtype).getBeanName();
		IActWorkFlowCustomService customService = null;
		if(customBean!=null){
			WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
			customService = (IActWorkFlowCustomService)wac.getBean(customBean);
		    if(customService!=null){
		    	Map<String, Object> map = customService.setvariables(formid);
		    	variables.putAll(map);
		    }
		}
		
	    //完成辦理
	    taskService.complete(taskId,variables);
	    
	    
	    //執行結束  更改狀態
		ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
		if(processInstance==null&&customService!=null){
			if(customService!=null){
				customService.endRunTask(formid);
		    }
			return 2;
		}else{
			return 1;
		}
	}

	
	/**
	 * 通過當前任務Id 獲取 批註時的備註資訊
	 */
	@Override
	public List<FComment> getComment(String currenttaskId) {
		List<FComment> relist = new ArrayList<FComment>();
		List<Comment> list = new ArrayList<Comment>();
		Task task = taskService.createTaskQuery().taskId(currenttaskId).singleResult();
		
		String processInstanceId = task.getProcessInstanceId();
		
		List<HistoricTaskInstance> htilist = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).list();
		if(htilist!=null&&htilist.size()>0){
			for (HistoricTaskInstance hti : htilist) {
				String htaskid = hti.getId();
				List<Comment> tasklist = taskService.getTaskComments(htaskid);
				list.addAll(tasklist);
			}
		}
		
		for (Comment com : list) {
			FComment fc = new FComment();
			fc.setId(com.getId());
			fc.setUserid(com.getUserId());
			List<Map<String,Object>> searchForMap = leavebilldao.searchForMap("select * from sysuser where id="+com.getUserId());
			fc.setUserName(searchForMap.get(0).get("name").toString());
			fc.setTime(com.getTime());
			fc.setTaskId(com.getTaskId());
			fc.setProcessInstanceId(com.getProcessInstanceId());
			fc.setType(com.getType());
			fc.setFullMessage(com.getFullMessage());
			relist.add(fc);
		}
		
		System.out.println(relist.toString());
		
		return relist;
	}

	
	
	
	
	/**
	 * 通過請假單id查詢 批註資訊
	 */
	@Override
	public List<FComment> getCommentByLeavebillId(String leaveBillId) {
		List<FComment> relist = new ArrayList<FComment>();
		LeaveBill leaveBill = new LeaveBill();
		String simpleName = leaveBill.getClass().getSimpleName();
		String objId = simpleName+"."+leaveBillId;
		HistoricVariableInstance hvi = historyService.createHistoricVariableInstanceQuery().variableValueEquals("objId", objId).orderByProcessInstanceId().asc().singleResult();
		String processInstanceId = hvi.getProcessInstanceId();
		List<Comment> list = taskService.getProcessInstanceComments(processInstanceId);
		
		for (Comment com : list) {
			FComment fc = new FComment();
			fc.setId(com.getId());
			fc.setUserid(com.getUserId());
			List<Map<String,Object>> searchForMap = leavebilldao.searchForMap("select * from sysuser where id="+com.getUserId());
			fc.setUserName(searchForMap.get(0).get("name").toString());
			fc.setTime(com.getTime());
			fc.setTaskId(com.getTaskId());
			fc.setProcessInstanceId(com.getProcessInstanceId());
			fc.setType(com.getType());
			fc.setFullMessage(com.getFullMessage());
			relist.add(fc);
		}
		Collections.reverse(relist);
		return relist;
	}

	
	/**
	 * 已知任務ID,查詢ProcessDefinitionEntiy物件,從而獲取當前任務完成之後的連線名稱,並放置到List<String>集合中
	 */
	@Override
	public List<String> findOutComeListByTaskId(String taskId) {
		//返回存放連線的名稱集合
		List<String> list = new ArrayList<String>();
		//1:使用任務ID,查詢任務物件
		Task task = taskService.createTaskQuery()//
					.taskId(taskId)//使用任務ID查詢
					.singleResult();
		//2:獲取流程定義ID
		String processDefinitionId = task.getProcessDefinitionId();
		//3:查詢ProcessDefinitionEntiy物件
		ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(processDefinitionId);
		//使用任務物件Task獲取流程例項ID
		String processInstanceId = task.getProcessInstanceId();
		//使用流程例項ID,查詢正在執行的執行物件表,返回流程例項物件
		ProcessInstance pi = runtimeService.createProcessInstanceQuery()//
					.processInstanceId(processInstanceId)//使用流程例項ID查詢
					.singleResult();
		//獲取當前活動的id
		String activityId = pi.getActivityId();
		//4:獲取當前的活動
		ActivityImpl activityImpl = processDefinitionEntity.findActivity(activityId);
		//5:獲取當前活動完成之後連線的名稱
		List<PvmTransition> pvmList = activityImpl.getOutgoingTransitions();
		if(pvmList!=null && pvmList.size()>0){
			for(PvmTransition pvm:pvmList){
				String name = (String) pvm.getProperty("name");
				if(StringUtils.isNotBlank(name)){
					list.add(name);
				}else{
					list.add("預設提交");
				}
			}
		}
		return list;
	}

}