Avtiviti(七)之组任务

1、Candidate-users候选人

1.1 需求

       在流程定义中,在任务结点的assignee固定设置任务负责人,在流程定义时将参与者固定设置在.bpmn文件中,如果临时任务负责人变更则需要修改流程定义,系统可扩展性差。
       针对这种情况可以给任务设置多个候选人,可以从候选人中选择参与者来完成任务。

1.2 设置任务候选人

在流程图中任务节点的配置中设置candidate-users(候选人),多个候选人之间用逗号分开。

Avtiviti(七)之组任务

查看bpmn文件:

Avtiviti(七)之组任务

我们可以看到部门经理的审核人已经设置为tom,jack这样的一组候选人,可以使用activiti:candiateUsers=”用户1,用户2,用户3”的这种方式来实现设置一组候选人。

2、办理组任务

2.1 部署上面的流程定义

package com.zdw.activiti04;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;

/**
 * Create By zdw on 2019/8/6
 */
public class GroupTest {

    //部署流程定义,可以不部署png文件
    public static void main(String[] args) {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        RepositoryService repositoryService = processEngine.getRepositoryService();
        Deployment deployment = repositoryService.createDeployment().addClasspathResource("bpmn/holiday4.bpmn")
                .name("测试组任务的请假流程").deploy();
        System.out.println("流程定义的ID:"+deployment.getId());
        System.out.println("流程定义的名称:"+deployment.getName());
    }
}

上面部署流程定义的时候,我们没有部署png的图片文件,这样也是可以成功的。

2.2 启动流程实例

//启动流程实例
    public static void main(String[] args) {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        RuntimeService runtimeService = processEngine.getRuntimeService();
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myholiday4");
        System.out.println("流程实例的id:"+processInstance.getId());//2501
    }

2.3 办理组任务的流程

第一步:查询组任务
       指定候选人,查询该候选人当前的待办任务。
       候选人不能办理任务。
第二步:拾取(claim)任务
       该组任务的所有候选人都能拾取。
       将候选人的组任务,变成个人任务。原来候选人就变成了该任务的负责人。
       ***如果拾取后不想办理该任务?
           需要将已经拾取的个人任务归还到组里边,将个人任务变成了组任务。
第三步:查询个人任务
       查询方式同个人任务部分,根据assignee查询用户负责的个人任务。
第四步:办理个人任务

2.3.1 执行任务

因为我们是在第二个节点设置了组任务,所以要看到效果,我们需要先执行第一个节点的任务:

//用户完成任务
    public static void main(String[] args) {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        TaskQuery taskQuery = taskService.createTaskQuery();
        List<Task> taskList = taskQuery.processDefinitionKey("myholiday4").taskAssignee("zhangsan").list();
        for (Task task : taskList) {
            if(task!=null){
                taskService.complete(task.getId());
                System.out.println("用户执行了任务:"+task.getName());
            }
        }
    }

此时,我们查看表:act_ru_task,发现 TSSIGNEE列为null,也就是说,avtiviti不知道接下来要执行任务的是谁:

Avtiviti(七)之组任务

查看表 act_ru_identitylink ,信息如下:

Avtiviti(七)之组任务

可以看到,tom和jack都是下一个任务id为5002的候选人,也就是说他们两个都能去执行这个任务,但是具体由谁去执行,还要通过先拾取任务才行。 

2.3.2 查询组任务

//用户查询组任务
    public static void main(String[] args) {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        TaskQuery taskQuery = taskService.createTaskQuery();
        List<Task> taskList = taskQuery.processDefinitionKey("myholiday4").taskCandidateUser("tom").list();
        for (Task task : taskList) {
            if(task!=null){
                System.out.println("任务ID:"+task.getId());
                System.out.println("任务名称:"+task.getName());
                System.out.println("任务的执行人:"+task.getAssignee());
            }
        }
    }

我们通过候选人的名称tom去查询,可以查询到他有组任务。

2.3.3 用户拾取组任务

//用户拾取组任务,查询到的组任务,不能立马去执行,
    // 如果用户要执行组任务,需要先拾取组任务,让组任务变成个人任务
    public static void main(String[] args) {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        TaskQuery taskQuery = taskService.createTaskQuery();
        List<Task> taskList = taskQuery.processDefinitionKey("myholiday4").taskCandidateUser("tom").list();
        for (Task task : taskList) {
            if(task!=null){
                //拾取任务,第一个参数是任务ID,第二个任务是执行人的ID
                taskService.claim(task.getId(),"tom");
                System.out.println("任务拾取成功");
            }
        }
    }

执行完成上面的程序,tom已经拾取成功了任务了,我们再次查询表act_ru_task

Avtiviti(七)之组任务

发现,此时任务的执行人就有值了,所以tom接下来也就可以完成任务了。

注意:即使该用户不是候选人也能拾取,建议拾取时校验是否有资格。组任务拾取后,该任务已有负责人,通过候选人将查询不到该任务

2.3.4 归还组任务

当tom已经拾取了组任务,但是他又发现这个任务不知道如何处理的时候,可以选择归还组任务。也就是把个人任务再次变成组任务,那么组任务的其他候选人,比如jack就可以去拾取组任务了。

//归还组任务
    public static void main(String[] args) {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        TaskQuery taskQuery = taskService.createTaskQuery();
        String taskId = "5002";
        //通过流程定义key和个人id还要任务id来查询任务
        //校验tom是否是taskId的负责人,如果是负责人才可以归还组任务
        List<Task> taskList = taskQuery.processDefinitionKey("myholiday4").taskAssignee("tom").taskId(taskId).list();
        for (Task task : taskList) {
            if(task!=null){
                //只要把任务的执行人设置为null,就相当于归还了
                taskService.setAssignee(taskId,null);
                System.out.println("归还了组任务");
            }
        }
    }

说明:建议归还任务前校验该用户是否是该任务的负责人
也可以通过setAssignee方法将任务委托给其它用户负责,注意被委托的用户可以不是候选人(建议不要这样使用)

2.3.5 任务交接(委托)

任务交接,任务负责人将任务交给其它候选人办理该任务。上面我们已经归还了组任务,所以候选人jack就能去拾取任务了。我们可以让jack先拾取任务,然后再把任务交接给tom,这样最终执行任务的还是tom。

//候选人jack执行拾取组任务操作
    public static void main(String[] args) {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        TaskQuery taskQuery = taskService.createTaskQuery();
        //根据key和userID,任务ID来拾取任务
        Task task = taskQuery.processDefinitionKey("myholiday4").taskCandidateUser("jack").taskId("5002").singleResult();
        if(task!=null){
            //拾取任务,第一个参数是任务ID,第二个任务是执行人的ID
            taskService.claim(task.getId(),"jack");
            System.out.println("任务拾取成功");
        }
    }
//执行人jack把任务交接给tom
//任务交接,前提要保证当前用户是这个任务的负责人,这时候他才可以有权限去将任务交接给其他候选人
    public static void main(String[] args) {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        TaskQuery taskQuery = taskService.createTaskQuery();
        //校验jack是否是taskId的负责人,如果是负责人才可以归还组任务
        String taskId = "5002";
        Task task = taskQuery.taskId(taskId).taskAssignee("jack").singleResult();
        if(task!=null){
            //把任务交接给tom。交接任务就是一个候选人拾取用户的过程
            taskService.setAssignee(taskId,"tom");
            System.out.println("交接任务成功");
        }
    }

上面的操作就是jack先拾取了组任务,然后把组任务交接给了tom去执行,所以最终的执行人是tom,接下来我们可以查询tom的可执行任务,然后去完成该任务即可,这操作和之前的完成任务是一样的,这里就不重复写了。

 

2.3.6 数据库表操作

        SELECT * FROM act_ru_task #任务执行表,记录当前执行的任务,由于该任务当前是组任务,所有assignee为空,当拾取任务后该字段就是拾取用户的id

       SELECT * FROM act_ru_identitylink #任务参与者,记录当前参考任务用户或组,当前任务如果设置了候选人,会向该表插入候选人记录,有几个候选就插入几个

与act_ru_identitylink对应的还有一张历史表act_hi_identitylink,向act_ru_identitylink插入记录的同时也会向历史表插入记录。任务完成。

上一篇:流程引擎activiti入门级使用


下一篇:[NgRx] Sort Entity with ngrx