Flowable之任务撤回(支持主流程、子流程相互撤回)

news2024/12/29 9:43:41

撤回任务:主流程 > 主流程

处室主管【送科长审核】

处室主管【撤回科长审核】

流程日志

撤回任务:子流程 > 子流程

会办接收岗【送处室主管】

会办接收岗【撤回处室主管】

会办接收岗【同意】

撤回任务:子流程 > 主流程

处室主管【送会办】

处室主管【撤回送会办】

处室主管【再次送会办】【接收员同意】

撤回任务:主流程 > 子流程

会办主管【送经办人】

会办主管【撤回经办人】

会办主管【同意】

撤回任务:主流程 > 并行子流程

同时送2个会办,A接收员同意,B主管送经办人

B主管【撤回送经办人】

B主管【同意】

核心代码实现


        List<FlowNode> doingNodes = findFlowNodesInMainProcess(taskItem.getProcDefId(), doingTaskKey);
        List<FlowNode> targetNodes = findFlowNodesInMainProcess(taskItem.getProcDefId(), taskKey);

        //撤回到子流程内部: 恢复子流程数据AddChildExecutionCmd
        if(doingNodes.size()>0 && targetNodes.size()==0){
            log.info(">>>> 主流程撤回到子流程 {} > {}", doingTaskKey, taskKey);
            revokeExecutions(bo.getProcInstId(), taskKey);
            //还原子流程subProcess边界
            ExecutionEntityImpl root = (ExecutionEntityImpl)runtimeService.createExecutionQuery().executionId(bo.getProcInstId()).singleResult();
            ExecutionEntityImpl child = (ExecutionEntityImpl)runtimeService.createExecutionQuery().parentId(bo.getProcInstId()).singleResult();
            Map<String, Object> varMap = this.getInstancesVariables(bo.getProcInstId());
            managementService.executeCommand(new AddChildExecutionCmd(root, child, varMap));
        }else if(doingNodes.size()==0 && targetNodes.size()==0){
            log.info(">>>> 子流程内任务撤回 {} > {}", doingTaskKey, taskKey);
            revokeActivityIds(bo.getProcInstId(), taskKey, doingTaskKeys);
        }else if(doingNodes.size()>0 && targetNodes.size()>0){
            log.info(">>>> 主流程内任务撤回 {} > {}", doingTaskKey, taskKey);
            revokeExecutions(bo.getProcInstId(), taskKey);
        }else if(doingNodes.size()==0 && targetNodes.size()>0){
            log.info(">>>> 子流程撤回到主流程 {} > {}", doingTaskKey, taskKey);
            revokeActivityIds(bo.getProcInstId(), taskKey, doingTaskKeys);
        }else {
            log.error(">>>> 未知撤回流程 {} > {}", doingTaskKey, taskKey);
        }

        //6.退回到指定节点(撤销所有子流程)
        Date endTime = taskItem.getEndTime();
        //撤回当前用户上一次已办理任务
        Integer taskNum = processCmdMapper.updateRevokeTask(procInstIdsStr, endTime);
        Integer actNum = processCmdMapper.updateRevokeAct(procInstIdsStr, endTime);
        log.info("success revokeTask  = {}, revokeAct = {}", taskNum, actNum);

        //更新待办任务并发通知
        handleDoingTask(taskItem.getBusinessKey(), false);
    }

    //撤回已经办理的任务
    private void revokeActivityIds(String procInstId, String taskKey, List<String> doingTaskKeys){
        if(doingTaskKeys.size()>0){
            runtimeService.createChangeActivityStateBuilder().processInstanceId(procInstId)
                    .moveActivityIdsToSingleActivityId(doingTaskKeys, taskKey).changeState();
        }
    }

    //撤回已经办理的任务
    private void revokeExecutions(String procInstId, String taskKey){
        List<String> executionIds = new ArrayList<>();
        List<Execution> executions = runtimeService.createExecutionQuery().parentId(procInstId).list();
        executions.forEach(execution -> executionIds.add(execution.getId()));
        if(executionIds.size()>0){
            runtimeService.createChangeActivityStateBuilder().moveExecutionsToSingleActivityId(executionIds, taskKey).changeState();
        }
    }


    //在主流程中查询节点
    private List<FlowNode> findFlowNodesInMainProcess(String processDefId, String activityId) {
        List<FlowNode> activities = new ArrayList<>();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefId);
        List<Process> processes = bpmnModel.getProcesses();
        for (Process process : processes) {
            FlowElement flowElement = process.getFlowElement(activityId);
            if (flowElement != null) {
                FlowNode flowNode = (FlowNode) flowElement;
                activities.add(flowNode);
            }
        }
        return activities;
    }

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

秋招内推--招联金融2025

【投递方式】 直接扫下方二维码&#xff0c;或点击内推官网https://wecruit.hotjob.cn/SU61025e262f9d247b98e0a2c2/mc/position/campus&#xff0c;使用内推码 igcefb 投递&#xff09; 【招聘岗位】 后台开发 前端开发 数据开发 数据运营 算法开发 技术运维 软件测试 产品策…

每日读则推(一)

v.避免,回避,撤销 n.黑花园蚁 Several animals are known to alter their behavior to avoid infections. But black garden v.改变,改动 n.传染病,感染,污染ants are th…

低空经济时代来临,挑战和机遇详细分析

低空经济作为一种新兴的经济形态&#xff0c;正逐步成为推动国民经济发展的新增长点。它依托于低空空域&#xff0c;涵盖通用航空、无人机应用、航空运动、低空旅游等多个领域&#xff0c;展现了广阔的发展前景和巨大的发展潜力。本文旨在详细分析低空经济时代来临所带来的挑战…

C语言数组和指针笔试题(三)

目录 字符数组四例题1例题2例题3例题4例题5例题6例题7 结果字符数组五例题1例题2例题3例题4例题5例题6例题7结果字符数组六例题1例题2例题3例题4例题5例题6例题7 结果 感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接 &#x1f412;&#x1f412;&#x1f412;个…

C语言、Eazy_x——井字棋

#include<graphics.h>char board_data[3][3] { { -,-,-},{ -,-,-},{ -,-,-}, };char current_piece o;//检测指定棋子玩家是否获胜 bool CheckWin(char c) {if (board_data[0][0] c && board_data[0][1] c && board_data[0][2] c)return true;if (…

html+css+js实现step进度条效果

实现效果 代码实现 HTML部分 <div class"box"><ul class"step"><li class"circle actives ">1</li><li class"circle">2</li><li class"circle">3</li><li class&quo…

Sui Bridge今日正式上线Sui主网

等待结束&#xff01;Sui Bridge现已上线Sui主网。 Sui Bridge是一种原生解决方案&#xff0c;用于在外部生态&#xff08;如以太坊&#xff09;之间转移资产。随着Web3的扩展和成熟&#xff0c;打破主要生态之间的壁垒&#xff0c;允许资产和数据自由流动变得尤为重要。 在W…

十大排序算法集锦

前言 众所周知&#xff0c;程序数据结构算法&#xff0c;由此可见算法的重要性。 为了了解算法&#xff0c;可以从排序算法入手&#xff0c;如下是十大排序算法的介绍(简介&#xff0c;原理&#xff0c;动图&#xff0c;代码&#xff0c;复杂性分析等)&#xff0c;希望可以带你…

代码随想录算法训练营Day18 | 530.二叉搜索树的最小绝对差、501.二叉搜索树中的众数、236. 二叉树的最近公共祖先

目录 530.二叉搜索树的最小绝对差 501.二叉搜索树中的众数 236. 二叉树的最近公共祖先 530.二叉搜索树的最小绝对差 题目 530. 二叉搜索树的最小绝对差 - 力扣&#xff08;LeetCode&#xff09; 给你一个二叉搜索树的根节点 root &#xff0c;返回 树中任意两不同节点值…

✨机器学习笔记(六)—— ReLU、多分类问题、Softmax、Adam、反向传播

Course2-Week2: https://github.com/kaieye/2022-Machine-Learning-Specialization/tree/main/Advanced%20Learning%20Algorithms/week2机器学习笔记&#xff08;六&#xff09; 1️⃣ReLU&#xff08;Rectified Linear Unit&#xff09;2️⃣多分类问题3️⃣Softmax4️⃣Adam5…

【Linux】进程+权限管理+软硬链接+其他命令

目录 1. man手册 2. find按文件名称 3. find按文件类型 4. date显示时间 5. cal显示日历 6. du文件大小 7. ln链接 8. 软连接&#xff0c;硬链接区别 9. 文本查找 10. wc统计文本(计算文件的Bytes数、字数或列数) 11. 查看文本内容&#xff1a; 1…

深度学习---------------------------深度循环神经网络

目录 回顾&#xff1a;循环神经网络总结深度循环神经网络代码 回顾&#xff1a;循环神经网络 RNN就一个隐藏的层&#xff0c;无法做的很宽&#xff0c;所以一般的做法是做的更深。&#xff08;更深的时候是说每一层做一点点的非线性。&#xff09; 怎么样把循环网络变深&#…

新版IDEA中Git的使用(四)——解决冲突

说明&#xff1a;之前介绍过新版IDEA中Git的基础操作、分支操作和回滚代码&#xff0c;本文介绍基于新版IDEA&#xff0c;如何解决代码冲突。 避免冲突 解决冲突的最好方法就是不要发生冲突&#xff0c;这里我介绍下面几点&#xff0c;可以避免代码冲突&#xff1b; 时常做pu…

[Unity Demo]从零开始制作空洞骑士Hollow Knight第十三集:制作小骑士的接触地刺复活机制以及完善地图的可交互对象

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、制作小骑士的接触地刺复活机制 1.制作动画以及使用UNITY编辑器编辑2.实现有攻击的地刺行为3.使用代码实现小骑士接触复活功能二、完善地图的可交互对象 1.制…

ThreadLocal原理解析及面试

基本使用 讲原理之前&#xff0c;我简单写个demo小程序 public class TestThreadLocal {public static void main(String[] args) throws InterruptedException {ThreadLocal<String> tl new ThreadLocal();/**主线程设置了一个值*/tl.set("SSSSSs");//tl.…

黑马头条day10 热点文章定时文章

day8-9是项目实战没有新东西 暂时跳过 进度到这里 但是后边的东西一直跑不通 调度一直失败 我也不知道哪里出了问题 整tm一天了也没搞出来 心态炸了 主要是xxl调度算是新内容 但是一直跑不出来就很烦 所谓的热点也就是计算权值然后存储到redis就行了 未解决&#xff1a; we…

【源码部署】springboot部署服务器之宝塔安装数据库远程无法链接问题

最近新搞了一个阿里云服务器&#xff0c;使用docker安装东西感觉太麻烦&#xff0c;于是用了宝塔。按了宝塔之后麻烦接连不断啊&#xff0c;最让人头疼的就是这个mysql无法远程链接问题&#xff0c;因此整理一下防止忘记在踩坑&#xff1a; 1、首先就是在宝塔面板中放行端口&a…

深度学习--------------------长短期记忆网络(LSTM)

目录 长短期记忆网络候选记忆单元记忆单元隐状态 长短期记忆网络代码从零实现初始化模型参数初始化实际模型训练 简洁实现 长短期记忆网络 忘记门&#xff1a;将值朝0减少 输入门&#xff1a;决定要不要忽略掉输入数据 输出门&#xff1a;决定要不要使用隐状态。 候选记忆单元…

这4款专业的Windows录屏工具,帮你解决多样的录屏的问题。

像Xbox 录制&#xff0c;步骤记录器等工具都是Windows系统里面自带的录屏工具&#xff0c;如果时想要更多功能的录屏工具&#xff0c;可以下载一些专业录屏软件&#xff0c;我可以给大家推荐几款&#xff0c;实用稳定&#xff0c;专业高效的录屏软件。 1、福昕多效录屏 直达&a…

【Java基础】Java面试基础知识QA(上)

Java面试基础知识Q&A&#xff08;上&#xff09; 面向对象编程&#xff08; OOP&#xff09; Java 是一个支持并发、基于类和面向对象的计算机编程语言。面向对象软件开发的优点&#xff1a; 代码开发模块化&#xff0c;更易维护和修改。代码复用。增强代码的可靠性和灵活性…