Activiti7 任务办理人、委派、转办、持有人、候选人、候选人组、审批意见【十三】

Activiti 7系列文章目录

文章代码下载

Activiti7 工作流设计器【一】
Activiti7 创建表【二】
Activiti7 表结构介绍 【三】
Activiti7 设计器创建流程 【四】
Activiti7 部署流程【五】
Activiti7 查询流程【六】
Activiti7 删除流程【七】
Activiti7 生成SVG图片【八】
Activiti7 发起任务【九】
Activiti7 查询任务执行流程图【十】
Activiti7 完成任务【十一】
Activiti7 历史数据【十二】
Activiti7 任务办理人、委派、转办、持有人、候选人、候选人组、审批意见【十三】
Activiti7 监听器【十四】
Activiti7 流程变量【十五】
Activiti7 网关Gateway【十六】
Activiti7 整合SpringBoot【十七】
Activiti7 多种任务类型【十八】
Activiti7 子流程【十九】
Activiti7 流程回退、流程拒绝【二十】

设置任务办理人

image.png

说明

Assignee指定办理人模式:即设置办理人,就是设置Assignee。Assignee 受让人; 受托人,代理人; 被指定人;办理人只能指定一个人,不能使用逗号分隔。默认执行签收操作taskService.claim(taskId, currentUserId);在ACT_HI_TASKINST和ACT_RU_TASK会产生数据,这两个表里面的Assignee_字段就是设置的办理人姓名或者对象的ID

涉及API

//根据用户来查询任务(待办任务)
taskService.createTaskQuery().taskAssignee(param);

//设置办理人
TaskService().setAssignee(taskId,userId);

任务委派

任务委派只是任务人将当前的任务交给接收人进行审批,完成任务后又重新回到任务人身上。委派人查询任务与完成任务与正常的有区别。

/**
 * 指定代办人
 */
@Test
public void delegateTask() {
    List<Task> list = taskService.createTaskQuery().list();
    String taskId = list.get(0).getId();
    String loginName = "李四";
    taskService.delegateTask(taskId, loginName);
}

插入数据表

==>  Preparing: insert into ACT_HI_IDENTITYLINK (ID_, TYPE_, USER_ID_, GROUP_ID_, TASK_ID_, PROC_INST_ID_) values (?, ?, ?, ?, ?, ?)
==> Parameters: 2501(String), participant(String), 李四(String), null, null, 4(String)
<==    Updates: 1
==>  Preparing: insert into ACT_RU_IDENTITYLINK (ID_, REV_, TYPE_, USER_ID_, GROUP_ID_, TASK_ID_, PROC_INST_ID_, PROC_DEF_ID_) values (?, 1, ?, ?, ?, ?, ?, ?)
==> Parameters: 2501(String), participant(String), 李四(String), null, null, 4(String), null
<==    Updates: 1

修改的数据表

==>  Preparing: update ACT_RU_TASK SET REV_ = ?, NAME_ = ?, PARENT_TASK_ID_ = ?, PRIORITY_ = ?, CREATE_TIME_ = ?, OWNER_ = ?, ASSIGNEE_ = ?, DELEGATION_ = ?, EXECUTION_ID_ = ?, PROC_DEF_ID_ = ?, DESCRIPTION_ = ?, DUE_DATE_ = ?, CATEGORY_ = ?, SUSPENSION_STATE_ = ?, FORM_KEY_ = ?, CLAIM_TIME_ = ? where ID_= ? and REV_ = ?
==> Parameters: 2(Integer), 经理审批(String), null, 50(Integer), 2023-07-28 11:00:14.096(Timestamp), null, 李四(String), PENDING(String), 5(String), test03:1:3(String), null, null, null, 1(Integer), null, null, 8(String), 1(Integer)
<==    Updates: 1
==>  Preparing: update ACT_HI_TASKINST set PROC_DEF_ID_ = ?, EXECUTION_ID_ = ?, NAME_ = ?, PARENT_TASK_ID_ = ?, DESCRIPTION_ = ?, OWNER_ = ?, ASSIGNEE_ = ?, CLAIM_TIME_ = ?, END_TIME_ = ?, DURATION_ = ?, DELETE_REASON_ = ?, TASK_DEF_KEY_ = ?, FORM_KEY_ = ?, PRIORITY_ = ?, DUE_DATE_ = ?, CATEGORY_ = ? where ID_ = ?
==> Parameters: test03:1:3(String), 5(String), 经理审批(String), null, null, null, 李四(String), null, null, null, null, sid-BD4D49BD-E99D-4D9A-9688-7778F37E3180(String), null, 50(Integer), null, null, 8(String)
<==    Updates: 1
==>  Preparing: update ACT_HI_ACTINST set EXECUTION_ID_ = ?, ASSIGNEE_ = ?, END_TIME_ = ?, DURATION_ = ?, DELETE_REASON_ = ? where ID_ = ?
==> Parameters: 5(String), 李四(String), null, null, null, 7(String)

这里关键是将ACT_RU_TASK的ASSIGNEE_设置为新待办人

被委派人处理任务

/**
 * 正在运行的任务表中被委派人办理任务后任务会回到委派人 ,历史任务表中也一样,只是多了一个人进行审批
 */
@Test
public void resolveTask() {
    List<Task> list = taskService.createTaskQuery().list();
    String taskId = list.get(0).getId();

    taskService.resolveTask(taskId);
}

执行的SQL语句

==>  Preparing: update ACT_RU_TASK SET REV_ = ?, NAME_ = ?, PARENT_TASK_ID_ = ?, PRIORITY_ = ?, CREATE_TIME_ = ?, OWNER_ = ?, ASSIGNEE_ = ?, DELEGATION_ = ?, EXECUTION_ID_ = ?, PROC_DEF_ID_ = ?, DESCRIPTION_ = ?, DUE_DATE_ = ?, CATEGORY_ = ?, SUSPENSION_STATE_ = ?, FORM_KEY_ = ?, CLAIM_TIME_ = ? where ID_= ? and REV_ = ?
==> Parameters: 3(Integer), 经理审批(String), null, 50(Integer), 2023-07-28 11:00:14.096(Timestamp), null, null, RESOLVED(String), 5(String), test03:1:3(String), null, null, null, 1(Integer), null, null, 8(String), 2(Integer)
<==    Updates: 1
==>  Preparing: update ACT_HI_ACTINST set EXECUTION_ID_ = ?, ASSIGNEE_ = ?, END_TIME_ = ?, DURATION_ = ?, DELETE_REASON_ = ? where ID_ = ?
==> Parameters: 5(String), null, null, null, null, 7(String)
<==    Updates: 1
==>  Preparing: update ACT_HI_TASKINST set PROC_DEF_ID_ = ?, EXECUTION_ID_ = ?, NAME_ = ?, PARENT_TASK_ID_ = ?, DESCRIPTION_ = ?, OWNER_ = ?, ASSIGNEE_ = ?, CLAIM_TIME_ = ?, END_TIME_ = ?, DURATION_ = ?, DELETE_REASON_ = ?, TASK_DEF_KEY_ = ?, FORM_KEY_ = ?, PRIORITY_ = ?, DUE_DATE_ = ?, CATEGORY_ = ? where ID_ = ?
==> Parameters: test03:1:3(String), 5(String), 经理审批(String), null, null, null, null, null, null, null, null, sid-BD4D49BD-E99D-4D9A-9688-7778F37E3180(String), null, 50(Integer), null, null, 8(String)
<==    Updates: 1

image.png

/**
 * 任务转办,将任务交给其他人处理
 */
@Test
public void turnTask() {
    String taskId =  "7511";
    String assignee = "李四";
    trunTask(taskId,assignee);
}

public boolean trunTask(String taskId, String assignee) {
    taskService.setAssignee(taskId, assignee);
    return true;
}

任务持有人

持有人:指当前任务的执行人,他此时持有该任务。
设置任务持有人

    @Test
    public void setOwner(){
        List<Task> list = taskService.createTaskQuery().list();
        String taskId = list.get(0).getId();
        String loginName = "王五";
        taskService.setOwner(taskId, loginName);
    }

执行的SQL

==>  Preparing: insert into ACT_HI_IDENTITYLINK (ID_, TYPE_, USER_ID_, GROUP_ID_, TASK_ID_, PROC_INST_ID_) values (?, ?, ?, ?, ?, ?)
==> Parameters: 5001(String), participant(String), 王五(String), null, null, 4(String)
<==    Updates: 1
==>  Preparing: insert into ACT_RU_IDENTITYLINK (ID_, REV_, TYPE_, USER_ID_, GROUP_ID_, TASK_ID_, PROC_INST_ID_, PROC_DEF_ID_) values (?, 1, ?, ?, ?, ?, ?, ?)
==> Parameters: 5001(String), participant(String), 王五(String), null, null, 4(String), null
<==    Updates: 1
==>  Preparing: insert into ACT_HI_COMMENT (ID_, TYPE_, TIME_, USER_ID_, TASK_ID_, PROC_INST_ID_, ACTION_, MESSAGE_, FULL_MSG_) values (?, ?, ?, ?, ?, ?, ?, ?, ?)
==> Parameters: 5002(String), event(String), 2023-07-28 11:27:01.561(Timestamp), null, 8(String), null, AddUserLink(String), 王五_|_owner(String), null
<==    Updates: 1

更新ACT_RU_TASK是关键

==>  Preparing: update ACT_HI_TASKINST set PROC_DEF_ID_ = ?, EXECUTION_ID_ = ?, NAME_ = ?, PARENT_TASK_ID_ = ?, DESCRIPTION_ = ?, OWNER_ = ?, ASSIGNEE_ = ?, CLAIM_TIME_ = ?, END_TIME_ = ?, DURATION_ = ?, DELETE_REASON_ = ?, TASK_DEF_KEY_ = ?, FORM_KEY_ = ?, PRIORITY_ = ?, DUE_DATE_ = ?, CATEGORY_ = ? where ID_ = ?
==> Parameters: test03:1:3(String), 5(String), 经理审批(String), null, null, 王五(String), null, null, null, null, null, sid-BD4D49BD-E99D-4D9A-9688-7778F37E3180(String), null, 50(Integer), null, null, 8(String)
<==    Updates: 1
==>  Preparing: update ACT_RU_TASK SET REV_ = ?, NAME_ = ?, PARENT_TASK_ID_ = ?, PRIORITY_ = ?, CREATE_TIME_ = ?, OWNER_ = ?, ASSIGNEE_ = ?, DELEGATION_ = ?, EXECUTION_ID_ = ?, PROC_DEF_ID_ = ?, DESCRIPTION_ = ?, DUE_DATE_ = ?, CATEGORY_ = ?, SUSPENSION_STATE_ = ?, FORM_KEY_ = ?, CLAIM_TIME_ = ? where ID_= ? and REV_ = ?
==> Parameters: 4(Integer), 经理审批(String), null, 50(Integer), 2023-07-28 11:00:14.096(Timestamp), 王五(String), null, RESOLVED(String), 5(String), test03:1:3(String), null, null, null, 1(Integer), null, null, 8(String), 3(Integer)
<==    Updates: 1

image.png

根据持有人查询任务

//反向查询任务:根据持有人查询任务
@Test
public void queryByOwner(){
    List<Task> list = taskService.createTaskQuery().taskOwner("王五").list();
    for (Task task : list) {
        System.out.println("task.getId() = " + task.getId());
        System.out.println("task.getName() = " + task.getName());
        System.out.println("task.getOwner() = " + task.getOwner());
    }
}

执行的SQL

==>  Preparing: select distinct RES.* from ACT_RU_TASK RES WHERE RES.OWNER_ = ? order by RES.ID_ asc LIMIT ? OFFSET ?
==> Parameters: 王五(String), 2147483647(Integer), 0(Integer)
<==      Total: 1

打印结果

task.getId() = 8
task.getName() = 经理审批
task.getOwner() = 王五

候选人CandidateUsers

当任务可以被多人处理的时候,可能会发生并发,所以添加候选人,让候选人去获取任务,之后就变成这个候选人的任务了。
image.png

//根据候选人查询任务
@Test
public void testQueryTaskByCandidateUser(){
    //返回所有的任务
    List<Task> tasks = taskService.createTaskQuery().taskCandidateUser("lisi").list();
    for (Task task : tasks) {
        System.out.println("task.getId() = " + task.getId());
        System.out.println("task.getName() = " + task.getName());
    }
}

这里需要注意:如果是和springboot整合,那么会走到SpringSecurity登录拦截,要么排除SpringSecurity,要么模拟一个登录
我这里提供模拟账号密码:相当于SpringSecurity登录查询用户,但是我这里给写死了。让他先通过再说。。。。

package com.boot.service;

import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.stereotype.Service;

@Service
public class UserService implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        InMemoryUserDetailsManager userDetailsService = new InMemoryUserDetailsManager();
        //User类用于创建代表用户的对象的构造器实现,该类由SpringSecurity提供,并非我们自己创建
        UserDetails user = User.withUsername(username)
                .password("123456")
                .authorities("admin")
                .build();
        userDetailsService.createUser(user);
        return user;
    }
}

当发起人zs完成自己的审批后到底下一个任务节点经理审批时,此时的ASSIGNEE_字段是空的。

//拾取任务
@Test
public void testClaimTask(){
    //返回所有的任务
    List<Task> tasks = taskService.createTaskQuery().taskCandidateUser("lisi").list();
    for (Task task : tasks) {
        System.out.println("task.getId() = " + task.getId());
        System.out.println("task.getName() = " + task.getName());
        taskService.claim(task.getId(), "lisi");//拾取任务
    }
}

image.png

候选人组:代表有权限对任务进行操作的人。

@Test
public void taskCandidateGroup(){
    List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("admin").list();
    for (Task task : tasks) {
        System.out.println("task.getId() = " + task.getId());
        System.out.println("task.getName() = " + task.getName());
    }
}
==>  Preparing: select distinct RES.* from ACT_RU_TASK RES inner join ACT_RU_IDENTITYLINK I on I.TASK_ID_ = RES.ID_ WHERE RES.ASSIGNEE_ is null and I.TYPE_ = 'candidate' and ( I.GROUP_ID_ IN ( ? ) ) order by RES.ID_ asc LIMIT ? OFFSET ?
==> Parameters: admin(String), 2147483647(Integer), 0(Integer)
<==      Total: 1
task.getId() = 7508
task.getName() = 经理审批

添加审批意见

我们可以通过TaskService的addComment方法来给任务审批意见

Task task = taskService
        .createTaskQuery()
        .singleResult();
//任务ID、流程实例ID、审批意见
taskService.addComment(task.getId(),"232504","同意审批");

审批意见存放的表

上述执行后会插入如下的表中

insert into ACT_HI_COMMENT

查询任务审批意见

//select * from ACT_HI_COMMENT where TASK_ID_ = ? and TYPE_ = 'comment' order by TIME_ desc
List<Comment> taskComments = taskService.getTaskComments(task.getId());
for (Comment taskComment : taskComments) {
    System.out.println("taskComment.getFullMessage() = " + taskComment.getFullMessage());
}
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Activiti中,候选人是用于指定具有某个任务的执行权限的一用户的标识符。任务可以分配给一个或多个候选人,并且只有属于该的用户才能执行该任务。这样可以实现任务的协作和分配。 要创建一个候选人,可以在流程定义文件(BPMN文件)中使用`<candidate-groups>`元素来指定。例如: ```xml <userTask id="task1" name="Task 1" activiti:assignee="${assignee}"> <extensionElements> <activiti:candidateGroups> <activiti:candidateGroup>group1</activiti:candidateGroup> <activiti:candidateGroup>group2</activiti:candidateGroup> </activiti:candidateGroups> </extensionElements> </userTask> ``` 上述示例中,`task1`任务会被分配给`group1`和`group2`这两个候选人。只有属于这两个的用户才能执行该任务。 在运行时,可以使用Activiti的API来查询候选人候选人信息,并将任务分配给具体的候选人。例如,可以使用以下代码将任务分配给具体的用户: ```java TaskService taskService = processEngine.getTaskService(); Task task = taskService.createTaskQuery().taskCandidateGroup("group1").singleResult(); taskService.setAssignee(task.getId(), "user1"); ``` 上述代码中,首先通过`taskCandidateGroup`方法查询属于`group1`候选人任务,然后使用`setAssignee`方法将任务分配给具体的用户`user1`。 希望以上信息对你有所帮助!如果还有其他问题,请继续提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员一灯

请给我打钱!!!谢谢,不客气!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值