标签:return String businessId Flowable processDefinitionKey 流程 案例 null 综合
Flowable综合案例二
需求:支持发起人选择审批人;支持会签。审批人驳回后流程作废(强制结束)。
流程:发起人申请→EPC总承包商+监理单位+业主单位会签
这次我们使用的是比较通用的方案,流程代码基本不用动,只需要在业务代码里边调用流程相关service即可。
思路:
1、为了支持多人会签,这里我们使用了并行网关。根据下面的流程图,当流程启动之后会同时创建出三个用户任务;只有当这三个用户任务同时完成流程才能结束。
2、这个流程设计器是我们封装好的。为了支持用户自己选择审批人这里的所有审批节点全部使用同一个create任务监听器。
3、为了区分不同节点的审批人,我们为每个审批节点增加了用户变量配置;这个配置是单独保存在我们自己的表里面的,主要保存节点ID、流程定义的Key和用户变量(一般是审批角色英文缩写)。
4、我们把用户选择的审批人放进流程全局变量进行保存,然后使用任务监听器根据审批节点定义的ID(节点ID)去数据库找到该节点对应的变量名称,再根据变量名称与全局变量的名称进行匹配获取到审批人id;最终把任务分配给用户。
实现:
1、流程图:
2、流程启动:
controller层:
/**
* 保存并提交
*
* @param entity
* @return
*/
@ApiOperation("保存并提交")
@PostMapping(value = "/saveAndSubmit")
@Transactional(rollbackFor = Exception.class)
public WebRestResponse<String> saveAndSubmit(EquipmentUnpackingApplicationEntity entity,
@ApiParam(value = "EPC总承包商", required = true) @RequestParam Long epc,
@ApiParam(value = "监理单位", required = true) @RequestParam Long pm,
@ApiParam(value = "业主单位", required = true) @RequestParam Long bus) {
try {
Long id = entity.getId();
Map<String, Object> map = new HashMap<>();
map.put("epc", epc);
map.put("pm", pm);
map.put("bus", bus);
//新增并提交
if (id == null) {
WebRestResponse<EquipmentUnpackingApplicationEntity> add = this.add(entity);
EquipmentUnpackingApplicationEntity data = add.getData();
Long bId = data.getId();
return this.startWithMap(bId.toString(), map);
} else {
//修改并提交
this.update(entity);
return this.startWithMap(id.toString(), map);
}
} catch (Exception e) {
e.printStackTrace();
return WebRestResponse.errorWebRestResponse("启动失败!");
}
}
/**
* 启动流程
*
* @param businessId
* @return
*/
@ApiOperation("启动流程")
@PostMapping(value = "/startWithMap")
@Transactional(rollbackFor = Exception.class)
public WebRestResponse<String> startWithMap(@RequestParam String businessId, Map<String, Object> map) {
try {
String processId = processService.startProcessByKey(processDefinitionKey, businessId, map);
if (processId == null) {
return WebRestResponse.errorWebRestResponse("启动失败!");
}
//修改业务状态
EquipmentUnpackingApplicationEntity equipmentUnpackingApplicationEntity = equipmentUnpackingApplicationService.selectById(businessId);
equipmentUnpackingApplicationEntity.setStatus(BusinessStatusConstant.TO_DO);
equipmentUnpackingApplicationService.updateById(equipmentUnpackingApplicationEntity);
return WebRestResponse.successWebRestResponse("启动成功!");
} catch (Exception e) {
e.printStackTrace();
return WebRestResponse.errorWebRestResponse("启动失败!");
}
}
service层:
@Override
@Transactional(rollbackFor = Exception.class)
public String startProcessByKey(String processDefinitionKey, String businessId, Map<String, Object> map) {
try {
String businessKey = businessId;
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(businessKey).processDefinitionKey(processDefinitionKey).singleResult();
//先判读businessKey有没有重复
if (processInstance != null && !processInstance.isEnded()) {
throw new RuntimeException("当前业务id所绑定的流程未结束!");
}
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceBusinessKey(businessKey).processDefinitionKey(processDefinitionKey).finished().singleResult();
//如果存在已结束的流程则判定为重新提交,把原来的历史数据删除
if (historicProcessInstance != null) {
historyService.deleteHistoricProcessInstance(historicProcessInstance.getId());
}
//启动流程获取流程实例Id,流程绑定业务
//获取当前登录用户
User currentUser = organizationStructureService.getCurrentUser();
//设置启动人
identityService.setAuthenticatedUserId(currentUser.getId().toString());
//启动流程
ProcessInstance processInstance1 = runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey, map);
String processInstance1Id = processInstance1.getId();
//保存流程全局变量
runtimeService.setVariables(processInstance1Id, map);
return processInstance1Id;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("流程启动异常,请确认当前业务数据是否已绑定运行中的流程!");
}
}
3、任务监听器:
/**
* 动态分配审批人
*
* @author WangChenYang
*/
@Component("CreateListener")
public class CreateListener implements TaskListener {
public static CreateListener createListener;
@Autowired
private UserVariateConfigMapper userVariateConfigMapper;
@Autowired
private RuntimeService runtimeService;
@Autowired
private ProcessService processService;
@Autowired
private TaskService taskService;
@PostConstruct
public void init() {
createListener = this;
createListener.userVariateConfigMapper = this.userVariateConfigMapper;
createListener.runtimeService = this.runtimeService;
createListener.taskService = this.taskService;
createListener.processService = this.processService;
}
@Override
public void notify(DelegateTask delegateTask) {
//节点Id
String nodeId = delegateTask.getTaskDefinitionKey();
//流程定义的Key
String processDefinitionKey = GetProcessKeyOrIdUtils.getProcessDefinitionKey(delegateTask.getProcessDefinitionId());
//流程实例ID
String processInstanceId = delegateTask.getProcessInstanceId();
//TaskId
String taskId = delegateTask.getId();
//通过用户变量的方式分配审批人
//根据流程实例id获取流程全局变量
Map<String, Object> variables = createListener.runtimeService.getVariables(processInstanceId);
//根据流程定义的Key和节点Id查询审批节点用户变量配置
UserVariateConfigEntity userVariateConfigEntity = createListener.userVariateConfigMapper.getByNodeId(processDefinitionKey, nodeId);
if (!variables.isEmpty() && userVariateConfigEntity != null) {
//获取变量名称
String variateName = userVariateConfigEntity.getVariateName();
//获取变量值(审批人Id)
String userId = String.valueOf(variables.get(variateName));
//设置审批人
createListener.taskService.addCandidateUser(taskId, userId);
}
}
}
4、根据业务ID判断当前登录用户是否可审批:
@Override
public Boolean booleanAudit(String processDefinitionKey, String businessId) {
//查询当前流程所有代办任务id
String businessKey = businessId;
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(businessKey).processDefinitionKey(processDefinitionKey).singleResult();
if (processInstance == null) {
return false;
}
String processInstanceId = processInstance.getId();
List<String> taskIds = this.getTaskId(processInstanceId);
//查询当前用户所有代办任务
User currentUser = organizationStructureService.getCurrentUser();
Long currentUserId = currentUser.getId();
List<Task> list = taskService.createTaskQuery().taskCandidateOrAssigned(currentUserId.toString()).list();
//如果有交集则可以审批
if (list != null && taskIds != null && taskIds.size() > 0 && list.size() > 0) {
for (String taskId : taskIds) {
for (Task task : list) {
if (task.getId().equals(taskId)) {
return true;
}
}
}
}
return false;
}
5、审批:
注:status=1是暂存状态;2是审批中;3是办结;-1是驳回
controller层:
/**
* 流程跳转
*
* @param businessId
* @param outcome
* @param comment
* @return
*/
@ApiOperation("流程跳转")
@PostMapping(value = "/completeTask")
@Transactional(rollbackFor = Exception.class)
public WebRestResponse<Boolean> completeTask(@RequestParam String businessId,
@RequestParam Integer outcome,
@RequestParam(required = false) String comment) {
try {
Boolean res = processService.completeTask(processDefinitionKey, businessId, outcome, comment);
if (res == null || !res) {
return WebRestResponse.errorWebRestResponse("流程跳转异常!");
}
EquipmentUnpackingApplicationEntity equipmentUnpackingApplicationEntity = equipmentUnpackingApplicationService.selectById(businessId);
//通过
if (outcome == 1) {
//判断流程是否结束
Boolean finished= processService.booleanFinished(processDefinitionKey, businessId);
if (finished) {
//完结后修改业务状态
equipmentUnpackingApplicationEntity.setStatus(BusinessStatusConstant.FINISH);
equipmentUnpackingApplicationService.updateById(equipmentUnpackingApplicationEntity);
}
} else {
//驳回后作废
equipmentUnpackingApplicationEntity.setStatus(BusinessStatusConstant.INVALID);
equipmentUnpackingApplicationService.updateById(equipmentUnpackingApplicationEntity);
}
return WebRestResponse.successWebRestResponse(true);
} catch (Exception e) {
e.printStackTrace();
return WebRestResponse.errorWebRestResponse("流程跳转异常!");
}
}
service层:
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean completeTask(String processDefinitionKey, String businessId, Integer outcome, String comment) {
String businessKey = businessId;
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(businessKey).processDefinitionKey(processDefinitionKey).singleResult();
String processInstanceId = processInstance.getId();
//根据流程实例id获取所有待办任务
List<String> taskIds = this.getTaskId(processInstanceId);
if (taskIds == null || taskIds.size() == 0) {
return false;
}
//获取当前用户的所有代办任务
Long userId = organizationStructureService.getCurrentUser().getId();
List<Task> tasks = taskService.createTaskQuery().taskCandidateOrAssigned(userId.toString()).list();
if (tasks == null || tasks.size() == 0) {
return false;
}
//获取当前用户在当前流程下的任务Id
String taskId = null;
for (Task task : tasks) {
for (String tId : taskIds) {
if (task.getId().equals(tId)) {
taskId = tId;
}
}
}
if (taskId == null) {
return false;
}
//当前任务真实办理人
taskService.setAssignee(taskId, userId.toString());
if (StringUtils.isNotBlank(comment)) {
//审批评论
taskService.addComment(taskId, processInstanceId, comment);
}
//审批通过
if (outcome == 1) {
taskService.complete(taskId);
return true;
} else {
try {
//先完成当前任务
taskService.complete(taskId);
//强制终止流程
this.stopProcessInstanceById(processDefinitionKey, businessId);
return true;
} catch (Exception e) {
return false;
}
}
}
//强制终止流程
public void stopProcessInstanceById(String processDefinitionKey, String businessId) {
String businessKey = businessId;
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(businessKey).processDefinitionKey(processDefinitionKey).singleResult();
if (processInstance != null) {
String processInstanceId = processInstance.getId();
//1、获取终止节点
List<EndEvent> endNodes = findEndFlowElement(processInstance.getProcessDefinitionId());
String endId = endNodes.get(0).getId();
//2、执行终止
List<String> taskIds = getTaskId(processInstanceId);
if (taskIds.size() > 0) {
for (String taskId : taskIds) {
User currentUser = organizationStructureService.getCurrentUser();
if (taskId != null) {
taskService.setAssignee(taskId, currentUser.getId().toString());
taskService.addComment(taskId, processInstanceId, "此节点被强制终止!");
}
}
}
List<Execution> executions = runtimeService.createExecutionQuery().parentId(processInstanceId).list();
List<String> executionIds = new ArrayList<>();
executions.forEach(execution -> executionIds.add(execution.getId()));
runtimeService.createChangeActivityStateBuilder().moveExecutionsToSingleActivityId(executionIds, endId).changeState();
}
}
//判断流程是否已经结束
@Override
public Boolean booleanFinished(String processDefinitionKey, String businessId) {
String businessKey = businessId;
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceBusinessKey(businessKey).processDefinitionKey(processDefinitionKey).finished().singleResult();
if (historicProcessInstance != null) {
return true;
}
return false;
}
6、删除:
controller:
/**
* 删除设备开箱申请
*
* @param id
* @return
*/
@RequestMapping(value = "deletedById", method = {RequestMethod.POST})
@ApiOperation("删除开箱申请")
@Transactional(rollbackFor = Exception.class)
public WebRestResponse<EquipmentUnpackingApplicationEntity> deletedById(Long id) {
try {
//删除流程数据
processService.deleteProcess(processDefinitionKey, id.toString());
if (equipmentUnpackingApplicationService.deleteById(id) > 0) {
return WebRestResponse.successWebRestResponse();
}
} catch (Exception e) {
log.error(ExceptionUtils.getStackTrace(e));
}
return WebRestResponse.errorWebRestResponse("系统出错");
}
service:
@Override
public Boolean deleteProcess(String processDefinitionKey, String businessId) {
String businessKey = businessId;
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceBusinessKey(businessKey).processDefinitionKey(processDefinitionKey).singleResult();
if (historicProcessInstance == null) {
return true;
}
String processInstanceId = historicProcessInstance.getId();
Boolean finished = this.booleanFinished(processDefinitionKey, businessId);
if (finished) {
historyService.deleteHistoricProcessInstance(processInstanceId);
} else {
runtimeService.deleteProcessInstance(processInstanceId, "delete");
}
return true;
}
7、 流程跳转日志参考案例一
成品页面展示:
本案例只供参考;如果有做的不好的地方欢迎各位大佬指正。
标签:return,String,businessId,Flowable,processDefinitionKey,流程,案例,null,综合 来源: https://blog.csdn.net/weixin_44150993/article/details/117814896
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。