springboot使用flowable(2)

22 篇文章 3 订阅

创建历史审批表

CREATE TABLE `tb_his_approval` (
  `id` varchar(50) NOT NULL COMMENT '主键',
  `business_id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '业务表主键',
  `approval_name` varchar(50) DEFAULT NULL COMMENT '审批人姓名',
  `approval_time` datetime DEFAULT NULL COMMENT '审批时间',
  `approval_comments` text COMMENT '审批意见',
  `approval_attachment_url` varchar(255) DEFAULT NULL COMMENT '审批附件的地址,可以看到当时上传的文件,这是属于你的扩展功能,可以在这里自己扩展',
  `task_name` varchar(50) DEFAULT NULL COMMENT '任务节点',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='历史审批表';

创建实体类

package com.dmg.entity;

import java.util.Date;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

/**
    * 历史审批表
    */
@Data
@TableName("tb_his_approval")
public class HisApproval {
    /**
    * 主键
    */
    private String id;

    /**
    * 业务表主键
    */
    private String businessId;

    /**
    * 审批人姓名
    */
    private String approvalName;

    /**
    * 审批时间
    */
    private Date approvalTime;

    /**
    * 审批意见
    */
    private String approvalComments;

    /**
    * 审批附件的地址,可以看到当时上传的文件,这是属于你的扩展功能,可以在这里自己扩展
    */
    private String approvalAttachmentUrl;

    /**
     * 任务节点
     */
    private String taskName;
}

创建mapper

package com.dmg.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dmg.entity.HisApproval;

public interface HisApprovalMapper extends BaseMapper<HisApproval> {

}

先在请假表造一条数据

INSERT INTO `flowable`.`tb_qj` (`id`, `name`, `day`, `create_by`, `create_by_name`, `instance_id`, `approval_status`, `create_time`) VALUES ('001', '张三-请假单', 1, 'zhangsan', '张三', NULL, '1', '2022-11-25 17:26:52');
 

 创建请求类

package com.dmg.vo.req;

import lombok.Data;


@Data
public class Req {


    /**
     * 主键
     */
    private String id;


    /**
     * 审批意见
     */
    private String approvalComments;


    /**
     * 通过:true  驳回false
     */
    private String flag;


    /**
     * 审批人
     */
    private String approver;

}

创建请假service

package com.dmg.service;

import com.dmg.vo.req.QjReq;

public interface QjService {

    public boolean submitApplication(Req req);

}

创建请假实现类

package com.dmg.service.impl;

import com.dmg.entity.Qj;
import com.dmg.mapper.QjMapper;
import com.dmg.service.FlowService;
import com.dmg.service.QjService;
import com.dmg.vo.req.QjReq;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Map;

@Service
public class QjServiceImpl implements QjService {


    @Autowired
    private QjMapper qjMapper;

    @Autowired
    private FlowService flowService;


/**
     * 提交请假单
     * @param req
     */
    @Transactional
    @Override
    public boolean submitApplication(Req req) {
        //从数据库查询当前信息
        Qj qj=qjMapper.selectById(req.getId());
        if(qj==null){
            throw new RuntimeException("请假单不存在");
        }
        if("3".equals(qj.getApprovalStatus())){
            throw new RuntimeException("已审批通过,不能提交");
        }

        //业务key 用于待办已办 扩展字段 展示使用
        //我这里以 流程定义key + 主键 + 申请单名称 的方式命名
        String businessKey="qj."+qj.getId()+"."+qj.getName();
        //参数 分支条件
        Map<String, Object> map=new HashMap<>();
        // >=3走一级审批  <3走 三级审批
        map.put("num",qj.getDay());
        //如果流程实例为空 启动一个新的流程实例
        String instanceId = flowService.startProcessInstance(businessKey, map,qj.getInstanceId());
        //保存instanceId到数据库
        qj.setInstanceId(instanceId);
        //审批状态改为 2:审批中
        qj.setApprovalStatus("2");
        qjMapper.updateById(qj);
        return true;
    }



}

然后在流程服务和流程服务实现类加入对应的方法 

public interface FlowService {

   
 public String startProcessInstance(String businessKey, Map<String, Object> map,String instanceId);

}
package com.dmg.service.impl;



/**
 * 流程定义服务实现类
 */
@Service
public class FlowServiceImpl extends FlowServiceFactory implements FlowService {

    @Autowired
    private HisApprovalMapper hisApprovalMapper;

  /**
     * 启动流程实例,返回流程实例id 完成第一个任务
     * @param map 分支条件参数
     * @param businessKey   业务表拼接内容  流程定义key+业务表主键+申请单名称
     * @param instanceId 流程实例id 如果不为空表示还没有走完这个流程 不需要发起
     */
    @Override
    public String startProcessInstance(String businessKey, Map<String, Object> map,
                                       String instanceId){
        //截取业务key
        String []res=businessKey.split("\\.");
        //流程定义key
        String processDefinitionKey=res[0];
        //业务表主键
        String businessId=res[1];
        //我这里写死 你要改成 申请单传入过来的账号
        String userId="zhangsan";

        if(StringUtils.isEmpty(instanceId)){
            ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey,businessKey, map);
            if(processInstance==null){
                throw new RuntimeException("启动流程实例失败");
            }
            instanceId=processInstance.getId();
        }
        //启动流程实例之后 完成第一个任务 就是提交申请单这一个节点  这样才能走到领导审批的节点
        //根据流程实例id 获取任务
        Task task = taskService.createTaskQuery()
                .processInstanceId(instanceId)
                .singleResult();
        //先认领任务
        taskService.claim(task.getId(),userId);
        //在完成任务
        taskService.complete(task.getId(),map);
        //添加历史审批
        insertHisApproval( "", userId, businessId, task.getName());
        //返回流程实例id
        return instanceId;
    }



    /**
     * 添加历史审批
     * @param approvalComments 审批意见
     * @param assignee 审批人
     * @param businessId 业务表主键
     * @param taskName 节点名称
     */
    public void insertHisApproval(String approvalComments,String assignee,String businessId,String taskName){
        HisApproval hisApproval=new HisApproval();
        hisApproval.setId(UUID.randomUUID().toString().replaceAll("-",""));
        hisApproval.setApprovalComments(approvalComments);
        hisApproval.setApprovalName(assignee);
        hisApproval.setBusinessId(businessId);
        //任务节点
        hisApproval.setTaskName(taskName);
        hisApproval.setApprovalTime(new Date());
        hisApprovalMapper.insert(hisApproval);
    }


}

然后在请假控制层加入

package com.dmg.controller;



@RestController
@RequestMapping("/qj")
public class QjController {


    @Autowired
    private QjService qjService;


    /***
     * 提交请假单
     * @param req
     * @return
     */
    @PostMapping("submitApplication")
    public Result submitApplication(@RequestBody Req req){
        return Result.success(qjService.submitApplication(req));
    }

}

http://localhost:8080/qj/submitApplication

{

    "id":"001"

}

从数据库找一个id, 提交请假单

 可以看到数据库已经发生了变化

 接下来 我们看下所有任务信息

先创建分页vo

package com.dmg.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dmg.entity.Qj;
import com.dmg.vo.TaskVo;

public interface QjMapper extends BaseMapper<Qj> {

    /**
     * 分页查询任务
     * @param page
     * @return
     */
    IPage<TaskVo>getTaskPage(Page<?>page);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dmg.mapper.QjMapper">

    <select id="getTaskPage" resultType="com.dmg.vo.TaskVo">
        SELECT
            ID_ taskId,
            PROC_INST_ID_ procInsId,
            PROC_DEF_ID_ procDefId,
            NAME_ taskName,
            CREATE_TIME_ createTime,
            SUSPENSION_STATE_ suspensionState,
            EXECUTION_ID_ executionId,
            ASSIGNEE_ assigneeName
        FROM
            act_ru_task
            order by CREATE_TIME_ desc
    </select>

</mapper>
package com.dmg.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.dmg.vo.TaskVo;
import com.dmg.vo.req.QjReq;

public interface QjService {

    public IPage<TaskVo> getTaskPage(int current,int size);
}
package com.dmg.service.impl;


@Service
public class QjServiceImpl implements QjService {


    @Autowired
    private QjMapper qjMapper;


    /**
     * 查询任务信息
     * @param current
     * @param size
     * @return
     */
    @Override
    public IPage<TaskVo> getTaskPage(int current, int size) {
        Page<?>page=new Page<>();
        page.setCurrent(current);
        page.setSize(size);
        IPage<TaskVo> taskPage = qjMapper.getTaskPage(page);
        return taskPage;
    }
}
package com.dmg.controller;


/**
 * 任务控制层
 */
@RestController
public class TaskController {


    @Autowired
    private QjService qjService;


    /**
     *  分页查询任务信息
     */
    @PostMapping("getTaskPage")
    public Result getTaskPage(@RequestBody PageReq req){
        IPage<TaskVo> page = qjService.getTaskPage(req.getCurrent()
                , req.getSize());
        return Result.success(page);
    }


}
package com.dmg.vo;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;


/**
 * 任务
 */
@Data
public class TaskVo {


    // 任务编号
    private String taskId;

    //任务执行编号
    private String executionId;

    // 任务名称
    private String taskName;

    //任务执行人名称
    private String assigneeName;

    //流程定义ID
    private String procDefId;

    //流程定义key
    private String procDefKey;

    //流程实例ID
    private String procInsId;

    //任务创建时间
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;

    /**
     * 是否激活 1正常  2挂起
     */
    private String suspensionState;

}

接下来我们看下结果

http://localhost:8080/getTaskPage

{

    "current":"1",

    "size": 2

}

我们可以看到assigneeName还没有人认领,那么我们先找一个人去认领这个任务

package com.dmg.service;
public interface FlowService {
    public void claim(String taskId,String account);
}
package com.dmg.service.impl;
/**
 * 流程定义服务实现类
 */
@Service
public class FlowServiceImpl extends FlowServiceFactory implements FlowService {
    /**
     * 认领 审批单
     * @param taskId
     * @param account
     */
    @Override
    public void claim(String taskId, String account) {
        //吧act_ru_task表的ASSIGNEE_ 设置为account 来审批
        taskService.claim(taskId,account);
    }
}
package com.dmg.controller;

/**
 * 流程定义控制层
 */
@RestController
public class ProcessDefinitionController {

    @Autowired
    private FlowService flowService;


    /**
     *  认领
     */
    @PostMapping("claim")
    public Result claim(@RequestBody FlowReq req){
        flowService.claim(req.getTaskId(),req.getAccount());
        return Result.success();
    }

}

我们来看下效果

http://localhost:8080/claim

{

    "taskId":"5da9023a-6cb9-11ed-b720-005056c00008",

    "account":"lisi"

}

 可以看到act_ru_task运行时任务表的ASSIGNEE_字段已经有值了,说明认领了,可以审批了

 接下来,我们使用lisi来进行审批驳回,看看是什么效果

package com.dmg.controller;



@RestController
@RequestMapping("/qj")
public class QjController {


    @Autowired
    private QjService qjService;



    /***
     * 审批请假单
     * @param req
     * @return
     */
    @PostMapping("approval")
    public Result approval(@RequestBody Req req){
        return Result.success(qjService.approval(req));
    }
}
package com.dmg.service;

public interface QjService {
    public boolean approval(Req req);
}
package com.dmg.service.impl;

@Service
public class QjServiceImpl implements QjService {


    @Autowired
    private QjMapper qjMapper;

    @Autowired
    private FlowService flowService;


 /**
     * 审批请假单
     * @param req
     */
    @Transactional
    @Override
    public boolean approval(Req req) {
        //从数据库查询当前信息
        Qj qj=qjMapper.selectById(req.getId());
        if(qj==null){
            throw new RuntimeException("请假单不存在");
        }
        //2:审批中
        if(!"2".equals(qj.getApprovalStatus())){
            throw new RuntimeException("状态不是审批中,不能审批");
        }
        //参数 分支条件
        Map<String, Object> map=new HashMap<>();
        //通过:true  驳回false
        map.put("flag",req.getFlag());
        String res = flowService.complete(qj.getInstanceId(), map, qj.getId(), req.getApprovalComments(), req.getApprover());
        if("end".equals(res)){
            //如果流程已经走完了 那么吧审批状态修改为 3:审批通过
            qj.setApprovalStatus("3");
            qjMapper.updateById(qj);
        }
        if("false".equals(req.getFlag())){
            //如果是驳回 那么修改状态为 未提交
            qj.setApprovalStatus("1");
            qjMapper.updateById(qj);
        }
        return true;
    }
   
}
package com.dmg.service;



public interface FlowService {


    public String complete(String instanceId,Map<String,Object>map,String businessKey,String approvalComments,String assignee);


}
package com.dmg.service.impl;



/**
 * 流程定义服务实现类
 */
@Service
public class FlowServiceImpl extends FlowServiceFactory implements FlowService {

    @Autowired
    private HisApprovalMapper hisApprovalMapper;
    @Autowired
    private QjMapper qjMapper;

 


    /**
     * 审批
     * @param businessId 业务表主键
     * @param map 分支条件
     * @param approvalComments 审批意见
     * @param instanceId 流程实例id
     * @param assignee 审批人
     */
    @Override
    public String complete(String instanceId,Map<String,Object>map,
                         String businessId,String approvalComments,
                         String assignee){
        //根据流程实例id 获取任务
        Task task = taskService.createTaskQuery()
                .processInstanceId(instanceId)
                .taskAssignee(assignee)
                .singleResult();
        if(task==null){
            throw new RuntimeException("任务不存在,或者不是当前任务的审批人");
        }
        //完成任务
        taskService.complete(task.getId(),map);
        //审批完成后 再次查询任务是否还有数据
        long count = taskService.createTaskQuery()
                .processInstanceId(instanceId)
                .count();
        //添加历史审批
        insertHisApproval( approvalComments, assignee, businessId, task.getName());
        if(count==0){
            //返回结束 修改表单的状态
            return "end";
        }
        return "ok";
    }

 
 
    

    /**
     * 添加历史审批
     * @param approvalComments 审批意见
     * @param assignee 审批人
     * @param businessId 业务表主键
     * @param taskName 节点名称
     */
    public void insertHisApproval(String approvalComments,String assignee,String businessId,String taskName){
        HisApproval hisApproval=new HisApproval();
        hisApproval.setId(UUID.randomUUID().toString().replaceAll("-",""));
        hisApproval.setApprovalComments(approvalComments);
        hisApproval.setApprovalName(assignee);
        hisApproval.setBusinessId(businessId);
        //任务节点
        hisApproval.setTaskName(taskName);
        hisApproval.setApprovalTime(new Date());
        hisApprovalMapper.insert(hisApproval);
    }




}

我们来看下结果

http://localhost:8080/qj/approval

{

    "id":"001",

    "approvalComments":"我不同意",

    "flag":"false",

    "approver":"lisi"

}

我们可以看到状态回到了未提交,任务也回到了提交的节点 

然后我们一路审批通过,flag设置为true,走完这个流程

 

这个时候我们可以看到,请假表已经更改了状态为审批通过,运行时任务表也走完了整个流程 

springboot使用flowable(3)_我是一只代码狗的博客-CSDN博客

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值