Flowable自动审核、相邻节点审核、已存在审核人审核

news/2024/11/17 11:38:56/文章来源:https://www.cnblogs.com/zgf123/p/18350897

Flowable 监听器的使用

需求背景:
1、发起人发起流程,可以实现发起人自动审核
2、上一节点的审核人,与当前节点审核人相同时,自动审核
3、整个流程实例中,存在已审核的审核人,当前节点自动审核

流程图如下所示:
image
针对于自动审核设置,其实是由前端内置bpnm.xml 去设置的,与前端达成协议,例如不启用时,就不要置入监听器,启用时,就植入监听器,在配置不同的字段,表示不同的审核方式。

发起人自动审核

自定义监听器,实现TaskListener,并配置需要的字段,该字段与前端的需要达成一致
image

bpmn.xml 如下:
image

这样在监听器下就可以接受到这两个字段的值,根据这两个字段的值,去完成自动审核功能。
值得注意的是,在监听器中,spring的自动注入并不能通过注解 @Autowired 去实现,而且通过构造函数加spring的上下文去实现注入。
例如:
image

重写TaskListener 的 notify 方法,该方法的形参是DelegateTask,这个参数可以获取到bpnm.xml 中 任务节点的属性,例如监听器的字段,任务id,流程实例id,流程定义等等。基于这个现有条件,我们即可完成发起人自动审核。

   @Overridepublic void notify(DelegateTask delegateTask) {// 从 FixedValue 中获取值String autoApprovalEnabledStr = (String) autoApprovalEnabled.getValue(delegateTask);String autoApprovalRuleStr = (String) autoApprovalRule.getValue(delegateTask);String processDefinitionId = delegateTask.getProcessDefinitionId();String taskDefinitionKey = delegateTask.getTaskDefinitionKey();BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);String eventName = delegateTask.getEventName();logger.info("触发监听器,当前监听器级别:{}",eventName);logger.info("触发监听器,当前任务:{}",delegateTask.getName());UserTask userTask = (UserTask) bpmnModel.getFlowElement(taskDefinitionKey);createLevelAutoTask(userTask,delegateTask,autoApprovalRuleStr,autoApprovalEnabledStr);}

在 createLevelAutoTask 方法中,需要完成以下步骤,判断当前的任务节点是不是会签节点,针对与会签节点,我们不去实现自动审核,直接停止当前监听器即可,还需要考虑,发起人如果是角色,或者是部门的情况下,我们应该怎么去实现,同样的,发起人是单个用户的话怎么实现,针对单个用户非常简单。

 private void createLevelAutoTask(UserTask userTask, DelegateTask delegateTask, String autoApprovalRuleStr,  String autoApprovalEnabledStr) {// 检查会签任务Integer nrOfInstances = (Integer) delegateTask.getVariable("nrOfInstances");Integer nrOfCompletedInstances = (Integer) delegateTask.getVariable("nrOfCompletedInstances");if (nrOfInstances != null && nrOfCompletedInstances != null) {// 这是一个多实例任务return;}if (userTask !=null){// 获取 当前任务节点的 类型,部门 DEPTS 、角色 ROLESString dataType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_DATA_TYPE);// 获取组的ID,角色ID集合或部门ID集合List<Long> groups = userTask.getCandidateGroups().stream().map(item -> Long.parseLong(item.substring(4))).collect(Collectors.toList());List<Long> userIds = new ArrayList<>();// 分别处理发起人是角色,部门,和user的场景if ("ROLES".equals(dataType) && !groups.isEmpty()){UserGroupRoleBO userGroupRoleBO = new UserGroupRoleBO();userGroupRoleBO.setRoleIdList(groups);userGroupRoleBO.setOrgIdList(null);userIds = userRemote.findUserByOrgIdsOrByRoleIds(userGroupRoleBO);// 表示启用自动审核if (AutoProcessType.AUTO_RULE_ENABLE.getCode().equals(autoApprovalEnabledStr)) {handleAutoApproval1(delegateTask, autoApprovalRuleStr,userIds);}}else if("DEPTS".equals(dataType) && !groups.isEmpty()){UserGroupRoleBO userGroupRoleBO = new UserGroupRoleBO();userGroupRoleBO.setRoleIdList(null);userGroupRoleBO.setOrgIdList(groups);userIds = userRemote.findUserByOrgIdsOrByRoleIds(userGroupRoleBO);// 表示启用自动审核if (AutoProcessType.AUTO_RULE_ENABLE.getCode().equals(autoApprovalEnabledStr)) {handleAutoApproval1(delegateTask, autoApprovalRuleStr,userIds);}}else {if (AutoProcessType.AUTO_RULE_ENABLE.getCode().equals(autoApprovalEnabledStr)){handleAutoApproval(delegateTask, autoApprovalRuleStr);}}}}

直接从单个用户来说吧,对于部门和角色相差不差,只需要获取到部门的id或者角色id,通过服务调用的方式去拿到用户的id,判断当前的登录用户是否在这个用户id集合中,存在即自动审核就好。

以下是针对单个用户的实现代码

    @Transactionalpublic void handleAutoApproval(DelegateTask delegateTask, String autoApprovalRule) {String processInstanceId = delegateTask.getProcessInstanceId();Map<String, Object> variables = delegateTask.getVariables();String taskId = delegateTask.getId();String assignee = delegateTask.getAssignee();String currentAssignee = (String) variables.get(ProcessConstants.CURRENT_ASSIGNEE);// 每一次任务审核,存储审核人的idList<String> assigneeList = (ArrayList) variables.get(ProcessConstants.ASSIGNEE_LIST) == null?new ArrayList<>():(ArrayList) variables.get("assigneeList") ;String userIdStr = (String) variables.get(ProcessConstants.PROCESS_INITIATOR);UserToken userToken = AuthorizationContext.getAdminUser();String userId = userToken.getUserId().toString();NodeUserVO uservo = userRemote.findUserById(Long.parseLong(assignee));String nickname = uservo.getNickname();String msg = AutoProcessType.AUTO_INITIATOR_ENABLE.getCode().equals(autoApprovalRule)?nickname + "发起流程申请":nickname+"通过";// 发起人自动审核if (AutoProcessType.AUTO_INITIATOR_ENABLE.getCode().equals(autoApprovalRule)) {if (userId.equals(userIdStr)) {assigneeList.add(userIdStr);variables.put(ProcessConstants.CURRENT_ASSIGNEE,userId);variables.put(ProcessConstants.ASSIGNEE_LIST,assigneeList);commentTask(userId, taskId, processInstanceId, FlowComment.NORMAL.getType(), msg, variables, delegateTask);}}   else if (AutoProcessType.AUTO_ADJACENT_ENABLE.getCode().equals(autoApprovalRule)) {
//            if (checkPreviousAssignee(assignee, delegateTask)) {
//                variables.put("currentAssignee",String.valueOf(userId));
//                variables.put(ProcessConstants.FLOWABLE_SKIP_EXPRESSION_ENABLED, true);
//                commentTask(userId, taskId, processInstanceId, FlowComment.SKIP.getType(), msg, variables, delegateTask);
//            }// 判断 上一节点 审批人 与当前节点审批人是否一致if (StringUtils.isNotBlank(currentAssignee) && currentAssignee.equals(assignee)) {variables.put(ProcessConstants.CURRENT_ASSIGNEE,userId);assigneeList.add(userIdStr);variables.put(ProcessConstants.ASSIGNEE_LIST,assigneeList);variables.put(ProcessConstants.FLOWABLE_SKIP_EXPRESSION_ENABLED, true);commentTask(userId, taskId, processInstanceId, FlowComment.SKIP.getType(), msg, variables, delegateTask);}} // 表示 当前流程实例中,存在已审核过的审核人,自动审核else if (AutoProcessType.AUTO_APPROVED.getCode().equals(autoApprovalRule)){// 相同表示 已存在审核人了if (assigneeList.contains(userId)){msg = nickname + "通过";variables.put(ProcessConstants.CURRENT_ASSIGNEE,userId);assigneeList.add(userIdStr);variables.put(ProcessConstants.ASSIGNEE_LIST,assigneeList);variables.put(ProcessConstants.FLOWABLE_SKIP_EXPRESSION_ENABLED, true);commentTask(userId, taskId, processInstanceId, FlowComment.SKIP.getType(), msg, variables, delegateTask);}}}private void commentTask(String userId,String taskId,String processInId,String commentType,String message,  Map<String, Object> variables ,DelegateTask delegateTask){identityService.setAuthenticatedUserId(userId);taskService.addComment(taskId, processInId, commentType, message);logger.info("已完成任务:{}",delegateTask.getName());taskService.complete(taskId, variables);}

主要的实现方式,通过设置流程变量的方式,在流程发起的时候,去判断当前登录用户与任务节点受理用户的id是否一致,如果一致就自动审核即可,对于上一节点和当前节点审核人相同自动审核的,在用户审核时,添加流程变量,那么这个流程实例就存储了当前的审核人信息,在下一个任务时,判断以下是否一致即可。就不写那么详细了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/780342.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ALLEGRO软件打开提示说没有内存

打开云雾管理器,确认下是不是没有内存,如果是内存没问题就重启下电脑

大数据框架之一——Hadoop学习第四天

1、MapReduce序列化(接着昨天的知识继续学习)序列化 (Serialization)将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。 当两个进程在进行远…

div-固定在页面中间,不被其他元素覆盖

最开始设置的子元素D 是text-align:center,子元素C的内容过长的时候,会发现子元素D不在页面正中了 所以需要把子元素D设置成固定中间,把子元素D设置成固定中间后,发现元素B把子元素D给覆盖了一部分, 所以需要在父元素A和元素B之间加一个空的div,给div设置高度后,父元素A…

div-实现靠左和靠右

display:block; display:inline-table;<div style="margin-bottom: 8px;display:block;"><div style="float:left;color:#ABABAB;font-size:12px;">实际工时</div><div style="float:right;font-size:12px;">{{ item.ac…

pyinstaller 打包uvicorn的坑

0.1 你使用fastapi搭建服务,并使用uvicorn来启动。 0.2 你使用pyinstaller打包成exe文件,并且需要隐藏控制台窗口。 0.3 执行exe文件时,程序报错了(模块相关错误和日志相关错误),网上找的资料都无法解决你的问题。 如果满足这些条件,可以继续往下看,我的方法主要参考ch…

JAVA线程资源共享问题

JAVA多线程共享资源问题 场景引入 这个场景是一个典型的多线程共享资源的场景,主要目的是测试和观察多个线程对共享变量 sum 进行并发操作时是否会出现线程安全问题 场景描述 共享资源:共享变量 sum,初始值为 0。 多个线程同时对 sum 进行操作,一个线程负责自增操作,另一个…

透过vivo的鞋子和亚马逊的椅子:探究新商业文明

有一种领先,叫微微领先。在亚马逊的会议室中,有一把永远为用户准备的椅子;在vivo,则要求不能只坐在会议室看PPT上的用户需求,而是要穿着用户的鞋子在企业奔跑。殊途同归,将“以用户导向”作为企业长期发展的基石,亚马逊和vivo真正将“让用户Happy”通过道、法、术落到了…

Neo4j 实现一个简单的CMDB管理平台

简介Neo4j是一个高性能的图形数据库管理系统,它使用图形模型来存储和查询数据。图形数据库与传统的关系型数据库不同,它们使用节点和边来表示数据实体和它们之间的关系,而不是使用表格和行,可以使用neo4j实现权限系统,知识图谱,cmdb等部署 docker run -d --name=neo4j \--…

10V45-ASEMI超低Low VF值肖特基二极管10V45

10V45-ASEMI超低Low VF值肖特基二极管10V45编辑:ll 10V45-ASEMI超低Low VF值肖特基二极管10V45 型号:10V45 品牌:ASEMI 封装:TO-277 批号:最新 恢复时间:35ns 最大平均正向电流(IF):10A 最大循环峰值反向电压(VRRM):45V 最大正向电压(VF):0.28V~0.42V 工作温度:…

方法的作用及定义

5.1 方法的作用及定义目录5.1 方法的作用及定义5.1.1 方法的作用5.1.2 方法的定义5.1.3 方法调用5.1.4 静态方法5.1.1 方法的作用 一、什么是方法呢? Java方法是语句的集合,它们在一起执行一个功能。方法是解决一类问题的步骤的有序组合 方法包含于类或对象中 方法在程序中被…

零基础学习人工智能—Python—Pytorch学习(三)

前言 这篇文章主要两个内容。 一,把上一篇关于requires_grad的内容补充一下。 二,介绍一下线性回归。 关闭张量计算 关闭张量计算。这个相对简单,阅读下面代码即可。 print("============关闭require_grad==============") x = torch.randn(3, requires_grad=True…