Activiti(二)简单请假流程实现

在SpringBoot2集成Activiti6的环境中,实现简单的请假流程。编写请假业务流程。流程业务为:

1,员工请假,先创建请假流程

2,员工填写请假申请,也可以不填写,直接结束流程

3,提交给直接主管审批,如果直接主管拒绝,则重新填写,如果直接主管同意,再到部门主管审批,

4,部门主管审批部门主管同意,则请假流程结束,请假成功,如果部门主管不同意,返回员工重新提交申请。

创建流程文件

 

流程定义代码如下

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:tns="http://www.activiti.org/testm1539766523202" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1539766523202" name="" targetNamespace="http://www.activiti.org/testm1539766523202" typeLanguage="http://www.w3.org/2001/XMLSchema">
  <process id="leave1" isClosed="false" isExecutable="true" processType="None">
    <startEvent id="_2" name="start"/>
    <userTask activiti:assignee="${leave.userId}" activiti:exclusive="true" id="_3" name="submit"/>
    <exclusiveGateway gatewayDirection="Unspecified" id="_4" name="result"/>
    <userTask activiti:assignee="${leave.approver1}" activiti:exclusive="true" id="_5" name="approve1"/>
    <exclusiveGateway gatewayDirection="Unspecified" id="_6" name="result"/>
    <userTask activiti:assignee="${leave.approver2}" activiti:exclusive="true" id="_7" name="approve2"/>
    <exclusiveGateway gatewayDirection="Unspecified" id="_8" name="result"/>
    <endEvent id="_9" name="end"/>
    <sequenceFlow id="_10" sourceRef="_2" targetRef="_3"/>
    <sequenceFlow id="_11" sourceRef="_3" targetRef="_4"/>
    <sequenceFlow id="_12" name="y" sourceRef="_4" targetRef="_5">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${leave.submit==true}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="_13" name="n" sourceRef="_4" targetRef="_9">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${leave.submit==false}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="_14" sourceRef="_5" targetRef="_6"/>
    <sequenceFlow id="_15" name="n" sourceRef="_6" targetRef="_7">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${leave.agree1==true}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="_16" sourceRef="_7" targetRef="_8"/>
    <sequenceFlow id="_17" name="y" sourceRef="_6" targetRef="_3">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${leave.agree1==false}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="_18" name="n" sourceRef="_8" targetRef="_3">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${leave.agree2==false}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="_19" name="y" sourceRef="_8" targetRef="_9">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${leave.agree2==true}]]></conditionExpression>
    </sequenceFlow>
  </process>
</definitions>

请注意流程图中userTask的assignee属性表示任务的所有者,userTask需要指定任务的所有者变量,如:

 

sequenceFlow中的condition描述流程的走向,当满足条件是,流程自动走该sequenceFlow

 

编写用户接口

@RestController
@RequestMapping("/leave/v1")
public class LeaveController {

    public static final Logger log = LoggerFactory.getLogger(LeaveController.class);

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private ProcessEngine processEngine;

    /**
     * 启动流程
     * @param userId
     * @return
     */
    @RequestMapping(value = "/start", method = RequestMethod.GET)
    public Map<String, Object> start(@RequestParam String userId){
        Map<String, Object> vars = new HashMap<>();
        Leave leave = new Leave();
        leave.setUserId(userId);
        vars.put("leave",leave);
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("leave1",vars);
        Map<String, Object> resultMap = new HashMap<>();
        return resultMap;
    }

    /**
     * 填写请假单
     * @param leave
     * @return
     */
    @RequestMapping(value="/apply", method = RequestMethod.POST)
    public Map<String, Object> apply(@RequestBody Leave leave){
        Task task = taskService.createTaskQuery().taskId(leave.getTaskId()).singleResult();
        Map<String, Object> vars = new HashMap<>();
        Leave origin = (Leave) taskService.getVariable(leave.getTaskId(), "leave");
        origin.setDesc(leave.getDesc());
        origin.setStartDate(leave.getStartDate());
        origin.setEndDate(leave.getEndDate());
        origin.setTotalDay(leave.getTotalDay());
        origin.setApprover1(leave.getApprover1());
        origin.setApprover2(leave.getApprover2());
        origin.setSubmit(leave.getSubmit());
        vars.put("leave", origin);
        taskService.complete(leave.getTaskId(), vars);
        Map<String, Object> resultMap = ResultMapHelper.getSuccessMap();
        return resultMap;
    }

    /**
     * 查询用户流程
     * @param userId
     * @return
     */
    @RequestMapping(value = "/find", method = RequestMethod.GET)
    public Map<String, Object> find(@RequestParam("userId")String userId){
        List<Task> taskList = taskService.createTaskQuery().taskAssignee(userId).list();
        List<Leave> resultList = new ArrayList<>();
        if(!CollectionUtils.isEmpty(taskList)){
            for(Task task : taskList){
                Leave leave = (Leave) taskService.getVariable(task.getId(),"leave");
                leave.setTaskId(task.getId());
                leave.setTaskName(task.getName());
                resultList.add(leave);
            }
        }
        Map<String, Object> resultMap = ResultMapHelper.getSuccessMap();
        resultMap.put("datas", resultList);
        return resultMap;
    }

    /**
     * 直接主管审批
     * @param leave
     * @return
     */
    @RequestMapping(value = "/approve1", method = RequestMethod.POST)
    public Map<String, Object> approve1(@RequestBody Leave leave){
        Task task = taskService.createTaskQuery().taskId(leave.getTaskId()).singleResult();
        Map<String, Object> vars = new HashMap<>();
        Leave origin = (Leave) taskService.getVariable(leave.getTaskId(), "leave");
        origin.setApproveDesc1(leave.getApproveDesc1());
        origin.setAgree1(leave.getAgree1());
        vars.put("leave", origin);
        taskService.complete(leave.getTaskId(),vars);
        Map<String, Object> resultMap = ResultMapHelper.getSuccessMap();
        return resultMap;
    }

    /**
     * 部门主管审批
     * @param leave
     * @return
     */
    @RequestMapping(value = "/approve2", method = RequestMethod.POST)
    public Map<String, Object> approve2(@RequestBody Leave leave){
        Task task = taskService.createTaskQuery().taskId(leave.getTaskId()).singleResult();
        Map<String, Object> vars = new HashMap<>();
        Leave origin = (Leave) taskService.getVariable(leave.getTaskId(), "leave");
        origin.setApproveDesc2(leave.getApproveDesc2());
        origin.setAgree2(leave.getAgree2());
        vars.put("leave", origin);
        taskService.complete(leave.getTaskId(),vars);
        Map<String, Object> resultMap = ResultMapHelper.getSuccessMap();
        return resultMap;
    }

    /**
     * 查看历史记录
     * @param userId
     * @return
     */
    @RequestMapping(value="/findClosed", method = RequestMethod.GET)
    public Map<String, Object> findClosed(String userId){
        HistoryService historyService = processEngine.getHistoryService();

        List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery().processDefinitionKey("leave1").variableValueEquals("leave.userId",userId).list();
        List<Leave> leaves = new ArrayList<>();
        for(HistoricProcessInstance pi : list){
            leaves.add((Leave) pi.getProcessVariables().get("leave"));
        }
        Map<String, Object> resultMap = ResultMapHelper.getSuccessMap();
        resultMap.put("datas", leaves);
        return resultMap;
    }

}

请假相关Java Model

public class Leave implements Serializable {
    private static final long serialVersionUID = 2248469053125414262L;

    private String userId;

    private Boolean submit;

    private Date startDate;

    private Date endDate;

    private float totalDay;

    private String desc;

    private String taskId;

    private String taskName;

    private String approver1;

    private Boolean agree1;

    private String approveDesc1;

    private String approver2;

    private Boolean agree2;

    private String approveDesc2;
}

测试

1,启动流程

访问GET请求http://192.168.104.24:8092/level/v1/start?userId=3000,用户3000启动请求流程

curl -X GET --header 'Accept: application/json' 'http://192.168.104.24:8092/level/v1/start?userId=3000'

2,查看用户的3000的任务

访问GET请求http://192.168.104.24:8092/level/v1/find?userId=3000

curl -X GET --header 'Accept: application/json' 'http://192.168.104.24:8092/leave/v1/find?userId=3000'

返回:

{
  "msg": "ok",
  "code": "0",
  "datas": [
    {
      "userId": "3000",
      "submit": null,
      "startDate": null,
      "endDate": null,
      "totalDay": 0,
      "desc": null,
      "taskId": "15021",
      "taskName": "submit",
      "approver1": null,
      "agree1": null,
      "approveDesc1": null,
      "approver2": null,
      "agree2": null,
      "approveDesc2": null
    }
  ]
}

表示用户3000已经有请假单待提交

3,用户提交请假单

curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{ \ 
   "desc": "没有理由", \ 
   "endDate": "2018-10-24 18:00:00", \ 
   "startDate": "2018-10-21 09:00:00", \ 
   "submit": true, \ 
   "taskId": "15021", \ 
   "totalDay": 3, \ 
   "approver1": "3001", \ 
   "approver2": "3002" \ 
}' 'http://192.168.104.24:8092/leave/v1/apply'

4,查看直接主管任务提交请假理由,直接主管3001,部门主管3002,开始时间,结束时间,提交状态(提交,或者关闭),任务ID,请假天数,请假事由等。

curl -X GET --header 'Accept: application/json' 'http://192.168.104.24:8092/leave/v1/find?userId=3001'

返回直接主管审批任务信息

{
  "msg": "ok",
  "code": "0",
  "datas": [
    {
      "userId": "3000",
      "submit": true,
      "startDate": "2018-10-21 09:00:00",
      "endDate": "2018-10-24 18:00:00",
      "totalDay": 3,
      "desc": "没有理由",
      "taskId": "15025",
      "taskName": "approve1",
      "approver1": "3001",
      "agree1": null,
      "approveDesc1": null,
      "approver2": "3002",
      "agree2": null,
      "approveDesc2": null
    }
  ]
}

5,直接主管审批

curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{ \ 
   "agree1": true, \ 
   "approveDesc1": "同意", \ 
   "taskId": "15025" \ 
  \ 
 }' 'http://192.168.104.24:8092/leave/v1/approve1'

提交审批结果agree1,审批意见,任务id


6,查看部门主管任务提交审批结果agree1,审批意见,任务id

curl -X GET --header 'Accept: application/json' 'http://192.168.104.24:8092/leave/v1/find?userId=3002'

返回部门主管审批任务信息

{
  "msg": "ok",
  "code": "0",
  "datas": [
    {
      "userId": "3000",
      "submit": true,
      "startDate": "2018-10-21 09:00:00",
      "endDate": "2018-10-24 18:00:00",
      "totalDay": 3,
      "desc": "没有理由",
      "taskId": "15029",
      "taskName": "approve2",
      "approver1": "3001",
      "agree1": true,
      "approveDesc1": "同意",
      "approver2": "3002",
      "agree2": null,
      "approveDesc2": null
    }
  ]
}

7,部门主管审批 

curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{ \ 
   "agree2": true, \ 
   "approveDesc2": "string", \ 
   "taskId": "15029" \ 
 }' 'http://192.168.104.24:8092/leave/v1/approve2'

执行成功后请假流程执行成功。

8,查看历史任务


curl -X GET --header 'Accept: application/json' 'http://192.168.104.24:8092/leave/v1/findClosed?userId=3000'

 

返回任务的历史记录信息

{
  "msg": "ok",
  "code": "0",
  "datas": [
    {
      "userId": "3000",
      "submit": true,
      "startDate": "2018-10-21 09:00:00",
      "endDate": "2018-10-24 18:00:00",
      "totalDay": 3,
      "desc": "没有理由",
      "taskId": null,
      "taskName": null,
      "approver1": "3001",
      "agree1": true,
      "approveDesc1": "同意",
      "approver2": "3002",
      "agree2": true,
      "approveDesc2": "string"
    }
  ]
}

篇幅有限,就不一一罗列其他测试用例了。

(完)

补充,查询不到历史记录的问题已修复,代码已经上传码云。传送门

  • 7
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值