撤回-撤销、驳回-退回、作废-终止、挂起-中止

  • 流程撤回-撤销
    • 1、流程定义
    • 2、部署流程,开启流程,完成第一个节点"审批1"审批
    • 3、撤回案例
  • 流程驳回-退回-退回到历史节点的任何节点
  • 流程挂起、作废

流程撤回-撤销

1、流程定义

<process id="test2" isClosed="false" isExecutable="true" processType="None"><startEvent id="_2" name="StartEvent"/><userTask activiti:assignee="sp1" activiti:exclusive="true" id="_3" name="审批1"/><userTask activiti:assignee="sp2" activiti:exclusive="true" id="_4" name="审批2"/><endEvent id="_5" name="EndEvent"/><sequenceFlow id="_6" sourceRef="_2" targetRef="_3"/><sequenceFlow id="_7" sourceRef="_3" targetRef="_4"/><sequenceFlow id="_8" sourceRef="_4" targetRef="_5"/></process>

2、部署流程,开启流程,完成第一个节点"审批1"审批

/*** 部署流程,开启流程,完成第一个节点“审批1”审核*/@Testpublic void shenpi1(){Deployment deploy = repositoryService.createDeployment().addClasspathResource("bpmn/test2.bpmn").deploy();log.info("流程部署成功:{}",deploy.getId());//设置开启人Authentication.setAuthenticatedUserId("sp1");ProcessInstance instance = runtimeService.startProcessInstanceByKey("test2");log.info("流程已开启:id:{},key:{},startUser:{}",instance.getId(),instance.getBusinessKey(),instance.getStartUserId());String instanceId=instance.getId();//        String instanceId="2ac7e417-e2f5-11eb-9ffb-34f39ab07ea4";//完成第一个节点审批Task task = taskService.createTaskQuery().processInstanceId(instanceId).taskAssignee("sp1").singleResult();taskService.complete(task.getId());log.info("任务已完成:id:{}",task.getId());}/*** 获取流程审批历史记录*/@Testpublic void history(){String instanceId="2ac7e417-e2f5-11eb-9ffb-34f39ab07ea4";HistoricProcessInstance instance = historyService.createHistoricProcessInstanceQuery().processInstanceId(instanceId).singleResult();String startUserId = instance.getStartUserId();Date startTime = instance.getStartTime();String startActivityId = instance.getStartActivityId();Task startTask = taskService.createTaskQuery().taskId(startActivityId).singleResult();List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery().processInstanceId(instanceId).orderByHistoricTaskInstanceStartTime().asc().list();for(HistoricTaskInstance task:list){List<Comment> comments = taskService.getTaskComments(task.getId());for(Comment c:comments){log.info("任务备注:id:{},userid:{},message:{}",c.getTaskId(),c.getUserId(),c.getFullMessage());}List<Attachment> attachments = taskService.getTaskAttachments(task.getId());log.info("任务id:{},name:{},assignee:{}",task.getId(),task.getName(),task.getAssignee());}}

3、撤回案例

撤回实现逻辑:

  1. 根据业务逻辑判断,当前任务是否可以撤回;这里只是简单判断,当前任务是当前用户审批的,并且流程下一个节点任务人还未处理任务时,此时任务是可以撤回的。比如流程开启人sp1,开启任务后,提交审批“审批1”,流程走到“审批2”节点。审核人sp1 还未审批任务,此时sp1想撤回刚才的提交,此时是可以的。如果“审批2”处理了审核,此时流程走过当前“审批2”节点了(对于这个流程案例是流程结束),sp1就不能撤回之前的提交了。
  2. 如何实现撤回功能?当前流程审核节点在“审批2”节点,可以手动修改“审批2”节点的输出流,既把“审批2”-“EndEvent”输出流删除,添加1条新输出流 “审批2”-“审批1”,这样“审批2”节点任务complete 流程自动就走到“审批1”了;
  3. “审批2”提交任务后,由于是撤回操作,流程到达“审批1”,历史任务记录中存在“审批2”提交到“审批1”历史记录。但对于业务上来说,可能这个历史记录不是必须要存在的(审批备注里面已经添加“撤回”备注信息),此时就可以把这个历史任务记录删除;当然如果需求要求也可以不删除。
  4. “审批2”提交任务后,流程走到“审批1”节点后,此时需要恢复原来的流程走向“审批2”-“EndEvent”输出流;
  5. 对于流程实现撤回功能,实现方式有很多种,比如也可以修改历史记录信息,同时在历史任务表添加新的任务记录等操作都是可以实现撤回功能。这里只是以修改输出流的方式作为说明,也是工作中用的比较多的一种实现方式。
/*** 流程撤回:* 当前用户审批通过后(流程到下一节点后),又想撤回时。撤回到上一节点;*/@Testpublic void proBack(){//1、判断是否可撤回? 上一个节点是当前用户审核的,并且下一节点审批人还未处理时,可撤回到上一节点;//2、如何撤回?动态修改BpmnModel当前流程节点输出流。//把当前流程节点输出流方向改成上一个节点,原有输出流删除;//审批通过后,再次恢复当前节点的原有输出流;//根据业务需求,判断是否删除上次审批的历史记录,不需删除时,不用处理;要求删除时,需删除撤回前的历史记录;String instanceId="2ac7e417-e2f5-11eb-9ffb-34f39ab07ea4";String canBackTaskId="2acc29dc-e2f5-11eb-9ffb-34f39ab07ea4";String userId="sp1";Tuple result = canBack(instanceId, canBackTaskId, userId);boolean canBack=result.get(0);HistoricTaskInstance currentTask=result.get(1);if(!canBack){log.debug("流程:{}-任务:{},已经处理,不可撤回",instanceId,canBackTaskId);return;}//流程撤回HistoricProcessInstance instance = historyService.createHistoricProcessInstanceQuery().processInstanceId(instanceId).singleResult();BpmnModel bpmnModel = repositoryService.getBpmnModel(instance.getProcessDefinitionId());HistoricTaskInstance canBackTask = historyService.createHistoricTaskInstanceQuery().taskId(canBackTaskId).taskAssignee(userId).singleResult();if(ObjectUtil.isEmpty(canBack)){log.debug("未找到要回退的任务");return;}FlowNode canBackNode = (FlowNode)bpmnModel.getFlowElement(canBackTask.getTaskDefinitionKey());FlowNode currentNode=(FlowNode)bpmnModel.getFlowElement(currentTask.getTaskDefinitionKey());//记录原始输出流程List<SequenceFlow> sourceOuts =new ArrayList<>();sourceOuts.addAll(currentNode.getOutgoingFlows());//清理活动方向currentNode.getOutgoingFlows().clear();//创建新流List<SequenceFlow> newFlows=new ArrayList<>();SequenceFlow newSequenceFlow = new SequenceFlow();newSequenceFlow.setId("newSequenceFlowId");newSequenceFlow.setSourceFlowElement(currentNode);newSequenceFlow.setTargetFlowElement(canBackNode);newFlows.add(newSequenceFlow);currentNode.setOutgoingFlows(newFlows);//记录备注信息Authentication.setAuthenticatedUserId(userId);taskService.addComment(currentTask.getId(), currentTask.getProcessInstanceId(), "撤回");//完成任务taskService.complete(currentTask.getId());//恢复原方向currentNode.setOutgoingFlows(sourceOuts);//删除当前任务历史记录historyService.deleteHistoricTaskInstance(currentTask.getId());}/*** 判断流程是否能够撤回* 上一个节点是当前用户审核的,并且下一节点审批人还未处理时,可撤回到上一节点;* @return*/
//    @Testpublic Tuple canBack(String instanceId,String canBackTaskId,String userId){//        String instanceId="2ac7e417-e2f5-11eb-9ffb-34f39ab07ea4";
//        String canBackTaskId="2acc29dc-e2f5-11eb-9ffb-34f39ab07ea4";
//        String userId="sp1";boolean canBack=false;//查看流程历史节点List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery().processInstanceId(instanceId).orderByHistoricTaskInstanceStartTime().asc().list();boolean hasUserTask=false;HistoricTaskInstance currentTask=null;for(HistoricTaskInstance task:list) {if(task.getId().equalsIgnoreCase(canBackTaskId)&&task.getAssignee().equalsIgnoreCase(userId)){//找到了处理人处理的任务,查看下一个任务是否已经处理hasUserTask=true;continue;}if(hasUserTask){//上一个任务是当前人处理的,查看当前任务是否已经被处理hasUserTask=false;if(ObjectUtil.isEmpty(task.getEndTime())){canBack=true;currentTask=task;break;}}}if(canBack){log.debug("未处理的流程可撤回,任务ID:{},任务接收人:{}",currentTask.getId(),currentTask.getAssignee());}//方法返回多个值,是否可回退,当前任务return new Tuple(canBack,currentTask);}

流程驳回-退回-退回到历史节点的任何节点

流程驳回,和流程撤回功能实现逻辑基本相同。
撤回功能是上一个节点审批人发起撤回;而驳回功能是当前审批节点人审核处理的,都可以通过修改当前审批节点的输出流进行处理,一般驳回功能需要记录历史记录,不会删除当前任务的历史记录。
具体驳回实现代码,这里不再记录,可借助撤回功能完成。

通过修改节点输出流向的操作,会发现,其实退回可以指定到任何节点上。
比如审批页面列出所有审核历史节点,可以选择历史任务节点,退回到选择的历史节点重新审批操作等功能。

流程挂起、作废

/*** 流程-作废(终止)、挂起(中止)*/@Testpublic void deleteProcess(){String instanceId="2ac7e417-e2f5-11eb-9ffb-34f39ab07ea4";//流程挂起、激活runtimeService.suspendProcessInstanceById(instanceId);runtimeService.activateProcessInstanceById(instanceId);//作废-删除流程,删除流程历史记录runtimeService.deleteProcessInstance(instanceId,"删除流程实例");historyService.deleteHistoricProcessInstance(instanceId);}

13、撤回(撤销)、驳回(退回)、作废(终止)、挂起(中止)相关推荐

  1. 对方服务器已读的邮件无法撤回,撤销已发送的邮件 时遇到的问题.

    楼上的朋友给的信息,非常感谢呀! 谢谢楼上的朋友! 这个答案很完美. 撤回邮件的工作机制 帮助 协助 > Outlook 2003 > 电子邮件 此功能要求使用 Microsoft Exc ...

  2. Linux查看进程和终止进程的技巧

    1. 在LINUX命令平台输入1-2个字符后按Tab键会自动补全后面的部分(前提是要有这个东西,例如在装了tomcat的前提下,输入tomcat的to按tab). 2. ps 命令用于查看当前正在运行 ...

  3. linux查看进程和终止进程

    1. 在LINUX命令平台输入1-2个字符后按Tab键会自动补全后面的部分(前提是要有这个东西,例如在装了tomcat的前提下,输入tomcat的to按tab). 2. ps 命令用于查看当前正在运行 ...

  4. git 撤销单个文件到某个提交

    开发过程中发现某个文件修改错误,需要回退到前一个版本. 用git status查看状态,并复制需要撤销(退回到某个版本)的单个文件 然后查看提交日志,确定要回到的提交为 591d0 执行 git ch ...

  5. 支持自动打怪(内挂)的网游,更新日期15.3.2

    更新日期:15.3.2 持续更新中,希望大家多多支持,未涉及到的内容可通过留言或其他方式联系我,我会及时添加的. 极乐空间-----------------15.3.2,3D画面不错,Ctrl+Z开启 ...

  6. 全球与中国无线颈挂式耳机市场深度研究分析报告

    [报告篇幅]:97 [报告图表数]:136 [报告出版时间]:2022年3月 2021年全球无线颈挂式耳机市场销售额达到了 亿美元,预计2028年将达到 亿美元,年复合增长率(CAGR)为 %(202 ...

  7. 快手小店保证金在哪里退?退回有啥条件?

    在快手开小店需要交保证金才能开店成功,大家如果不想做了的话,也可以将这个小店的保证金退回来,那么如何去申请退回快手小店保证金呢?下面的内容中一起了解一下. 在哪里退? 1.打开快手app,在侧边栏点击 ...

  8. linux 查看进程和终止进程

    1. 在LINUX命令平台输入1-2个字符后按Tab键会自动补全后面的部分(前提是要有这个东西,例如在装了tomcat的前提下,输入tomcat的to按tab). 2. ps 命令用于查看当前正在运行 ...

  9. Flowable 快速入门教程:任务驳回与回退

    Flowable 快速入门教程:任务驳回与回退 前言 BUG 修复记录 支持场景 功能描述 驳回 退回 脏数据 什么是脏数据 串行样例 并行样例 会签样例 脏数据清洗效果图 完整代码 效果图 前言 本 ...

最新文章

  1. linux修改mac ethtool,ethtool命令
  2. ASP.NET MVC下使用SWFUpload完成剪切头像功能
  3. 小试---EF5.0入门实例1
  4. undefined reference to `pthread_create‘(linux下Clion使用thread报错)
  5. python 读中文乱码_python字符乱码的解决小结
  6. 没有bug队——加贝——Python 练习实例 19,20
  7. 满汉全席(洛谷-P4171)
  8. 可作为GC Roots的对象
  9. eclipse导入外部项目引发的错误以及解决方案
  10. Android入门学习2
  11. Linux命令(压缩,解压rar)
  12. soem主站移植到rt thread smart操作系统
  13. DataPipeline王睿:业务异常实时自动化检测 — 基于人工智能的系统实战
  14. 使用spark-md5获取文件md5值
  15. scrapy--Rule()与LinkExtractor()函数理解
  16. python成语接龙到为所欲为_python成语接龙
  17. 动态规划-剪绳子问题
  18. 二维dct变换例题_图象题处理习题
  19. 一万小时定律的数学解释-可怕的复利
  20. MATLAB - 三维图绘制

热门文章

  1. 理论+实验·MySQL数据库管理
  2. Python 还原控制SCI论文算法系列1: 基于策略迭代的自适应最优控制器设计
  3. 最经典的android塔防,安卓TOP10:经典塔防《王国保卫战:起源》上架
  4. 信息学奥赛一本通 1255:迷宫问题 | OpenJudge NOI 2.5 7084:迷宫问题
  5. MobaXterm Professional v11.1 Build 3860 注册版-全功能SSH/X远程客户端-Xmanager最佳替代品
  6. Mac忘记登录密码解决方案
  7. Redis基础-下载安装、配置、数据类型、指令、Jedis、持久化
  8. 为什么码农要了解业务?
  9. CVE-2017-8464(震网三代)漏洞分析与复现
  10. 神都夜行录无法显示服务器,神都夜行录提示无响应怎么办