Commit 3a4b0f4f75eb4c760df56f56414a9eed8bd20848

Authored by cuicui
1 parent 40157244

合并bpm-base和bpm-flowable 为bpm-biz

Showing 153 changed files with 7922 additions and 4 deletions
yudao-module-bpm/pom.xml
... ... @@ -10,9 +10,10 @@
10 10 <modelVersion>4.0.0</modelVersion>
11 11 <modules>
12 12 <module>yudao-module-bpm-api</module>
13   - <module>yudao-module-bpm-base</module>
14   - <module>yudao-module-bpm-biz-flowable</module>
15   - <module>yudao-module-bpm-biz-activiti</module>
  13 + <module>yudao-module-bpm-biz</module>
  14 +<!-- <module>yudao-module-bpm-base</module>-->
  15 +<!-- <module>yudao-module-bpm-biz-flowable</module>-->
  16 +<!-- <module>yudao-module-bpm-biz-activiti</module>-->
16 17 </modules>
17 18 <artifactId>yudao-module-bpm</artifactId>
18 19 <packaging>pom</packaging>
... ...
yudao-module-bpm/yudao-module-bpm-biz/pom.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <parent>
  6 + <groupId>cn.iocoder.boot</groupId>
  7 + <artifactId>yudao-module-bpm</artifactId>
  8 + <version>${revision}</version>
  9 + </parent>
  10 + <modelVersion>4.0.0</modelVersion>
  11 + <artifactId>yudao-module-bpm-biz</artifactId>
  12 +
  13 + <name>${project.artifactId}</name>
  14 + <description>
  15 + bpm-base 模块,实现公用的工作流的逻辑,提供给 bpm-activiti 和 bpm-flowable 复用
  16 + </description>
  17 +
  18 + <dependencies>
  19 + <dependency>
  20 + <groupId>cn.iocoder.boot</groupId>
  21 + <artifactId>yudao-module-bpm-api</artifactId>
  22 + <version>${revision}</version>
  23 + </dependency>
  24 + <dependency>
  25 + <groupId>cn.iocoder.boot</groupId>
  26 + <artifactId>yudao-module-system-api</artifactId>
  27 + <version>${revision}</version>
  28 + </dependency>
  29 +
  30 + <!-- 业务组件 -->
  31 + <dependency>
  32 + <groupId>cn.iocoder.boot</groupId>
  33 + <artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId>
  34 + </dependency>
  35 + <dependency>
  36 + <groupId>cn.iocoder.boot</groupId>
  37 + <artifactId>yudao-spring-boot-starter-biz-data-permission</artifactId>
  38 + </dependency>
  39 +
  40 + <!-- Web 相关 -->
  41 + <dependency>
  42 + <groupId>cn.iocoder.boot</groupId>
  43 + <artifactId>yudao-spring-boot-starter-web</artifactId>
  44 + </dependency>
  45 +
  46 + <dependency>
  47 + <groupId>cn.iocoder.boot</groupId>
  48 + <artifactId>yudao-spring-boot-starter-security</artifactId>
  49 + </dependency>
  50 +
  51 + <!-- DB 相关 -->
  52 + <dependency>
  53 + <groupId>cn.iocoder.boot</groupId>
  54 + <artifactId>yudao-spring-boot-starter-mybatis</artifactId>
  55 + </dependency>
  56 +
  57 + <!-- Test 测试相关 -->
  58 + <dependency>
  59 + <groupId>cn.iocoder.boot</groupId>
  60 + <artifactId>yudao-spring-boot-starter-test</artifactId>
  61 + </dependency>
  62 + <!-- 工作流相关 -->
  63 + <dependency>
  64 + <groupId>cn.iocoder.boot</groupId>
  65 + <artifactId>yudao-spring-boot-starter-flowable</artifactId>
  66 + </dependency>
  67 + </dependencies>
  68 +</project>
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/api/package-info.java 0 → 100644
  1 +/**
  2 + * bpm API 实现类,定义暴露给其它模块的 API
  3 + */
  4 +package cn.iocoder.yudao.module.bpm.api;
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.api.task;
  2 +
  3 +import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
  4 +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
  5 +import org.springframework.stereotype.Service;
  6 +import org.springframework.validation.annotation.Validated;
  7 +
  8 +import javax.annotation.Resource;
  9 +import javax.validation.Valid;
  10 +
  11 +/**
  12 + * Flowable 流程实例 Api 实现类
  13 + *
  14 + * @author 芋道源码
  15 + * @author jason
  16 + */
  17 +@Service
  18 +@Validated
  19 +public class BpmProcessInstanceApiImpl implements BpmProcessInstanceApi {
  20 +
  21 + @Resource
  22 + private BpmProcessInstanceService processInstanceService;
  23 +
  24 + @Override
  25 + public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO reqDTO) {
  26 + return processInstanceService.createProcessInstance(userId, reqDTO);
  27 + }
  28 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmFormController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition;
  2 +
  3 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.*;
  4 +import cn.iocoder.yudao.module.bpm.convert.definition.BpmFormConvert;
  5 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
  6 +import cn.iocoder.yudao.module.bpm.service.definition.BpmFormService;
  7 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  8 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  9 +import io.swagger.annotations.Api;
  10 +import io.swagger.annotations.ApiImplicitParam;
  11 +import io.swagger.annotations.ApiOperation;
  12 +import org.springframework.security.access.prepost.PreAuthorize;
  13 +import org.springframework.validation.annotation.Validated;
  14 +import org.springframework.web.bind.annotation.*;
  15 +
  16 +import javax.annotation.Resource;
  17 +import javax.validation.Valid;
  18 +import java.util.List;
  19 +
  20 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  21 +
  22 +@Api(tags = "管理后台 - 动态表单")
  23 +@RestController
  24 +@RequestMapping("/bpm/form")
  25 +@Validated
  26 +public class BpmFormController {
  27 +
  28 + @Resource
  29 + private BpmFormService formService;
  30 +
  31 + @PostMapping("/create")
  32 + @ApiOperation("创建动态表单")
  33 + @PreAuthorize("@ss.hasPermission('bpm:form:create')")
  34 + public CommonResult<Long> createForm(@Valid @RequestBody BpmFormCreateReqVO createReqVO) {
  35 + return success(formService.createForm(createReqVO));
  36 + }
  37 +
  38 + @PutMapping("/update")
  39 + @ApiOperation("更新动态表单")
  40 + @PreAuthorize("@ss.hasPermission('bpm:form:update')")
  41 + public CommonResult<Boolean> updateForm(@Valid @RequestBody BpmFormUpdateReqVO updateReqVO) {
  42 + formService.updateForm(updateReqVO);
  43 + return success(true);
  44 + }
  45 +
  46 + @DeleteMapping("/delete")
  47 + @ApiOperation("删除动态表单")
  48 + @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
  49 + @PreAuthorize("@ss.hasPermission('bpm:form:delete')")
  50 + public CommonResult<Boolean> deleteForm(@RequestParam("id") Long id) {
  51 + formService.deleteForm(id);
  52 + return success(true);
  53 + }
  54 +
  55 + @GetMapping("/get")
  56 + @ApiOperation("获得动态表单")
  57 + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
  58 + @PreAuthorize("@ss.hasPermission('bpm:form:query')")
  59 + public CommonResult<BpmFormRespVO> getForm(@RequestParam("id") Long id) {
  60 + BpmFormDO form = formService.getForm(id);
  61 + return success(BpmFormConvert.INSTANCE.convert(form));
  62 + }
  63 +
  64 + @GetMapping("/list-all-simple")
  65 + @ApiOperation(value = "获得动态表单的精简列表", notes = "用于表单下拉框")
  66 + public CommonResult<List<BpmFormSimpleRespVO>> getSimpleForms() {
  67 + List<BpmFormDO> list = formService.getFormList();
  68 + return success(BpmFormConvert.INSTANCE.convertList2(list));
  69 + }
  70 +
  71 + @GetMapping("/page")
  72 + @ApiOperation("获得动态表单分页")
  73 + @PreAuthorize("@ss.hasPermission('bpm:form:query')")
  74 + public CommonResult<PageResult<BpmFormRespVO>> getFormPage(@Valid BpmFormPageReqVO pageVO) {
  75 + PageResult<BpmFormDO> pageResult = formService.getFormPage(pageVO);
  76 + return success(BpmFormConvert.INSTANCE.convertPage(pageResult));
  77 + }
  78 +
  79 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.framework.common.util.io.IoUtils;
  6 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*;
  7 +import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert;
  8 +import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService;
  9 +import io.swagger.annotations.Api;
  10 +import io.swagger.annotations.ApiImplicitParam;
  11 +import io.swagger.annotations.ApiOperation;
  12 +import org.springframework.security.access.prepost.PreAuthorize;
  13 +import org.springframework.validation.annotation.Validated;
  14 +import org.springframework.web.bind.annotation.*;
  15 +
  16 +import javax.annotation.Resource;
  17 +import javax.validation.Valid;
  18 +
  19 +import java.io.IOException;
  20 +
  21 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  22 +
  23 +@Api(tags = "管理后台 - 流程模型")
  24 +@RestController
  25 +@RequestMapping("/bpm/model")
  26 +@Validated
  27 +public class BpmModelController {
  28 +
  29 + @Resource
  30 + private BpmModelService modelService;
  31 +
  32 + @GetMapping("/page")
  33 + @ApiOperation(value = "获得模型分页")
  34 + public CommonResult<PageResult<BpmModelPageItemRespVO>> getModelPage(BpmModelPageReqVO pageVO) {
  35 + return success(modelService.getModelPage(pageVO));
  36 + }
  37 +
  38 + @GetMapping("/get")
  39 + @ApiOperation("获得模型")
  40 + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = String.class)
  41 + @PreAuthorize("@ss.hasPermission('bpm:model:query')")
  42 + public CommonResult<BpmModelRespVO> getModel(@RequestParam("id") String id) {
  43 + BpmModelRespVO model = modelService.getModel(id);
  44 + return success(model);
  45 + }
  46 +
  47 + @PostMapping("/create")
  48 + @ApiOperation(value = "新建模型")
  49 + @PreAuthorize("@ss.hasPermission('bpm:model:create')")
  50 + public CommonResult<String> createModel(@Valid @RequestBody BpmModelCreateReqVO createRetVO) {
  51 + return success(modelService.createModel(createRetVO, null));
  52 + }
  53 +
  54 + @PutMapping("/update")
  55 + @ApiOperation(value = "修改模型")
  56 + @PreAuthorize("@ss.hasPermission('bpm:model:update')")
  57 + public CommonResult<Boolean> updateModel(@Valid @RequestBody BpmModelUpdateReqVO modelVO) {
  58 + modelService.updateModel(modelVO);
  59 + return success(true);
  60 + }
  61 +
  62 + @PostMapping("/import")
  63 + @ApiOperation(value = "导入模型")
  64 + @PreAuthorize("@ss.hasPermission('bpm:model:import')")
  65 + public CommonResult<String> importModel(@Valid BpmModeImportReqVO importReqVO) throws IOException {
  66 + BpmModelCreateReqVO createReqVO = BpmModelConvert.INSTANCE.convert(importReqVO);
  67 + // 读取文件
  68 + String bpmnXml = IoUtils.readUtf8(importReqVO.getBpmnFile().getInputStream(), false);
  69 + return success(modelService.createModel(createReqVO, bpmnXml));
  70 + }
  71 +
  72 + @PostMapping("/deploy")
  73 + @ApiOperation(value = "部署模型")
  74 + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = String.class)
  75 + @PreAuthorize("@ss.hasPermission('bpm:model:deploy')")
  76 + public CommonResult<Boolean> deployModel(@RequestParam("id") String id) {
  77 + modelService.deployModel(id);
  78 + return success(true);
  79 + }
  80 +
  81 + @PutMapping("/update-state")
  82 + @ApiOperation(value = "修改模型的状态", notes = "实际更新的部署的流程定义的状态")
  83 + @PreAuthorize("@ss.hasPermission('bpm:model:update')")
  84 + public CommonResult<Boolean> updateModelState(@Valid @RequestBody BpmModelUpdateStateReqVO reqVO) {
  85 + modelService.updateModelState(reqVO.getId(), reqVO.getState());
  86 + return success(true);
  87 + }
  88 +
  89 + @DeleteMapping("/delete")
  90 + @ApiOperation("删除模型")
  91 + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = String.class)
  92 + @PreAuthorize("@ss.hasPermission('bpm:model:delete')")
  93 + public CommonResult<Boolean> deleteModel(@RequestParam("id") String id) {
  94 + modelService.deleteModel(id);
  95 + return success(true);
  96 + }
  97 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO;
  6 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
  7 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO;
  8 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
  9 +import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
  10 +import io.swagger.annotations.Api;
  11 +import io.swagger.annotations.ApiImplicitParam;
  12 +import io.swagger.annotations.ApiOperation;
  13 +import org.springframework.security.access.prepost.PreAuthorize;
  14 +import org.springframework.validation.annotation.Validated;
  15 +import org.springframework.web.bind.annotation.GetMapping;
  16 +import org.springframework.web.bind.annotation.RequestMapping;
  17 +import org.springframework.web.bind.annotation.RequestParam;
  18 +import org.springframework.web.bind.annotation.RestController;
  19 +
  20 +import javax.annotation.Resource;
  21 +
  22 +import java.util.List;
  23 +
  24 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  25 +
  26 +@Api(tags = "管理后台 - 流程定义")
  27 +@RestController
  28 +@RequestMapping("/bpm/process-definition")
  29 +@Validated
  30 +public class BpmProcessDefinitionController {
  31 +
  32 + @Resource
  33 + private BpmProcessDefinitionService bpmDefinitionService;
  34 +
  35 + @GetMapping("/page")
  36 + @ApiOperation(value = "获得流程定义分页")
  37 + @PreAuthorize("@ss.hasPermission('bpm:process-definition:query')")
  38 + public CommonResult<PageResult<BpmProcessDefinitionPageItemRespVO>> getProcessDefinitionPage(
  39 + BpmProcessDefinitionPageReqVO pageReqVO) {
  40 + return success(bpmDefinitionService.getProcessDefinitionPage(pageReqVO));
  41 + }
  42 +
  43 + @GetMapping ("/list")
  44 + @ApiOperation(value = "获得流程定义列表")
  45 + @PreAuthorize("@ss.hasPermission('bpm:process-definition:query')")
  46 + public CommonResult<List<BpmProcessDefinitionRespVO>> getProcessDefinitionList(
  47 + BpmProcessDefinitionListReqVO listReqVO) {
  48 + return success(bpmDefinitionService.getProcessDefinitionList(listReqVO));
  49 + }
  50 +
  51 + @GetMapping ("/get-bpmn-xml")
  52 + @ApiOperation(value = "获得流程定义的 BPMN XML")
  53 + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = String.class)
  54 + @PreAuthorize("@ss.hasPermission('bpm:process-definition:query')")
  55 + public CommonResult<String> getProcessDefinitionBpmnXML(@RequestParam("id") String id) {
  56 + String bpmnXML = bpmDefinitionService.getProcessDefinitionBpmnXML(id);
  57 + return success(bpmnXML);
  58 + }
  59 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmTaskAssignRuleController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  4 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleCreateReqVO;
  5 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO;
  6 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO;
  7 +import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
  8 +import io.swagger.annotations.Api;
  9 +import io.swagger.annotations.ApiImplicitParam;
  10 +import io.swagger.annotations.ApiImplicitParams;
  11 +import io.swagger.annotations.ApiOperation;
  12 +import org.springframework.security.access.prepost.PreAuthorize;
  13 +import org.springframework.validation.annotation.Validated;
  14 +import org.springframework.web.bind.annotation.*;
  15 +
  16 +import javax.annotation.Resource;
  17 +import javax.validation.Valid;
  18 +import java.util.List;
  19 +
  20 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  21 +
  22 +@Api(tags = "管理后台 - 任务分配规则")
  23 +@RestController
  24 +@RequestMapping("/bpm/task-assign-rule")
  25 +@Validated
  26 +public class BpmTaskAssignRuleController {
  27 +
  28 + @Resource
  29 + private BpmTaskAssignRuleService taskAssignRuleService;
  30 +
  31 + @GetMapping("/list")
  32 + @ApiOperation(value = "获得任务分配规则列表")
  33 + @ApiImplicitParams({
  34 + @ApiImplicitParam(name = "modelId", value = "模型编号", example = "1024", dataTypeClass = String.class),
  35 + @ApiImplicitParam(name = "processDefinitionId", value = "流程定义的编号", example = "2048", dataTypeClass = String.class)
  36 + })
  37 + @PreAuthorize("@ss.hasPermission('bpm:task-assign-rule:query')")
  38 + public CommonResult<List<BpmTaskAssignRuleRespVO>> getTaskAssignRuleList(
  39 + @RequestParam(value = "modelId", required = false) String modelId,
  40 + @RequestParam(value = "processDefinitionId", required = false) String processDefinitionId) {
  41 + return success(taskAssignRuleService.getTaskAssignRuleList(modelId, processDefinitionId));
  42 + }
  43 +
  44 + @PostMapping("/create")
  45 + @ApiOperation(value = "创建任务分配规则")
  46 + @PreAuthorize("@ss.hasPermission('bpm:task-assign-rule:create')")
  47 + public CommonResult<Long> createTaskAssignRule(@Valid @RequestBody BpmTaskAssignRuleCreateReqVO reqVO) {
  48 + return success(taskAssignRuleService.createTaskAssignRule(reqVO));
  49 + }
  50 +
  51 + @PutMapping("/update")
  52 + @ApiOperation(value = "更新任务分配规则")
  53 + @PreAuthorize("@ss.hasPermission('bpm:task-assign-rule:update')")
  54 + public CommonResult<Boolean> updateTaskAssignRule(@Valid @RequestBody BpmTaskAssignRuleUpdateReqVO reqVO) {
  55 + taskAssignRuleService.updateTaskAssignRule(reqVO);
  56 + return success(true);
  57 + }
  58 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmUserGroupController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition;
  2 +
  3 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupCreateReqVO;
  4 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupPageReqVO;
  5 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupRespVO;
  6 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupUpdateReqVO;
  7 +import cn.iocoder.yudao.module.bpm.convert.definition.BpmUserGroupConvert;
  8 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
  9 +import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
  10 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  11 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  12 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  13 +import io.swagger.annotations.Api;
  14 +import io.swagger.annotations.ApiImplicitParam;
  15 +import io.swagger.annotations.ApiOperation;
  16 +import org.springframework.security.access.prepost.PreAuthorize;
  17 +import org.springframework.validation.annotation.Validated;
  18 +import org.springframework.web.bind.annotation.*;
  19 +
  20 +import javax.annotation.Resource;
  21 +import javax.validation.Valid;
  22 +import java.util.List;
  23 +
  24 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  25 +
  26 +@Api(tags = "管理后台 - 用户组")
  27 +@RestController
  28 +@RequestMapping("/bpm/user-group")
  29 +@Validated
  30 +public class BpmUserGroupController {
  31 +
  32 + @Resource
  33 + private BpmUserGroupService userGroupService;
  34 +
  35 + @PostMapping("/create")
  36 + @ApiOperation("创建用户组")
  37 + @PreAuthorize("@ss.hasPermission('bpm:user-group:create')")
  38 + public CommonResult<Long> createUserGroup(@Valid @RequestBody BpmUserGroupCreateReqVO createReqVO) {
  39 + return success(userGroupService.createUserGroup(createReqVO));
  40 + }
  41 +
  42 + @PutMapping("/update")
  43 + @ApiOperation("更新用户组")
  44 + @PreAuthorize("@ss.hasPermission('bpm:user-group:update')")
  45 + public CommonResult<Boolean> updateUserGroup(@Valid @RequestBody BpmUserGroupUpdateReqVO updateReqVO) {
  46 + userGroupService.updateUserGroup(updateReqVO);
  47 + return success(true);
  48 + }
  49 +
  50 + @DeleteMapping("/delete")
  51 + @ApiOperation("删除用户组")
  52 + @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
  53 + @PreAuthorize("@ss.hasPermission('bpm:user-group:delete')")
  54 + public CommonResult<Boolean> deleteUserGroup(@RequestParam("id") Long id) {
  55 + userGroupService.deleteUserGroup(id);
  56 + return success(true);
  57 + }
  58 +
  59 + @GetMapping("/get")
  60 + @ApiOperation("获得用户组")
  61 + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
  62 + @PreAuthorize("@ss.hasPermission('bpm:user-group:query')")
  63 + public CommonResult<BpmUserGroupRespVO> getUserGroup(@RequestParam("id") Long id) {
  64 + BpmUserGroupDO userGroup = userGroupService.getUserGroup(id);
  65 + return success(BpmUserGroupConvert.INSTANCE.convert(userGroup));
  66 + }
  67 +
  68 + @GetMapping("/page")
  69 + @ApiOperation("获得用户组分页")
  70 + @PreAuthorize("@ss.hasPermission('bpm:user-group:query')")
  71 + public CommonResult<PageResult<BpmUserGroupRespVO>> getUserGroupPage(@Valid BpmUserGroupPageReqVO pageVO) {
  72 + PageResult<BpmUserGroupDO> pageResult = userGroupService.getUserGroupPage(pageVO);
  73 + return success(BpmUserGroupConvert.INSTANCE.convertPage(pageResult));
  74 + }
  75 +
  76 + @GetMapping("/list-all-simple")
  77 + @ApiOperation(value = "获取用户组精简信息列表", notes = "只包含被开启的用户组,主要用于前端的下拉选项")
  78 + public CommonResult<List<BpmUserGroupRespVO>> getSimpleUserGroups() {
  79 + // 获用户门列表,只要开启状态的
  80 + List<BpmUserGroupDO> list = userGroupService.getUserGroupListByStatus(CommonStatusEnum.ENABLE.getStatus());
  81 + // 排序后,返回给前端
  82 + return success(BpmUserGroupConvert.INSTANCE.convertList2(list));
  83 + }
  84 +
  85 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormBaseVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form;
  2 +
  3 +import lombok.*;
  4 +import io.swagger.annotations.*;
  5 +import javax.validation.constraints.*;
  6 +
  7 +/**
  8 +* 动态表单 Base VO,提供给添加、修改、详细的子 VO 使用
  9 +* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
  10 +*/
  11 +@Data
  12 +public class BpmFormBaseVO {
  13 +
  14 + @ApiModelProperty(value = "表单名称", required = true, example = "芋道")
  15 + @NotNull(message = "表单名称不能为空")
  16 + private String name;
  17 +
  18 + @ApiModelProperty(value = "表单状态", required = true, notes = "参见 CommonStatusEnum 枚举", example = "1")
  19 + @NotNull(message = "表单状态不能为空")
  20 + private Integer status;
  21 +
  22 + @ApiModelProperty(value = "备注", example = "我是备注")
  23 + private String remark;
  24 +
  25 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormCreateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form;
  2 +
  3 +import lombok.*;
  4 +import io.swagger.annotations.*;
  5 +
  6 +import javax.validation.constraints.NotNull;
  7 +import java.util.List;
  8 +
  9 +@ApiModel("管理后台 - 动态表单创建 Request VO")
  10 +@Data
  11 +@EqualsAndHashCode(callSuper = true)
  12 +@ToString(callSuper = true)
  13 +public class BpmFormCreateReqVO extends BpmFormBaseVO {
  14 +
  15 + @ApiModelProperty(value = "表单的配置", required = true, notes = "JSON 字符串")
  16 + @NotNull(message = "表单的配置不能为空")
  17 + private String conf;
  18 +
  19 + @ApiModelProperty(value = "表单项的数组", required = true, notes = "JSON 字符串的数组")
  20 + @NotNull(message = "表单项的数组不能为空")
  21 + private List<String> fields;
  22 +
  23 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormPageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import io.swagger.annotations.ApiModel;
  5 +import io.swagger.annotations.ApiModelProperty;
  6 +import lombok.Data;
  7 +import lombok.EqualsAndHashCode;
  8 +import lombok.ToString;
  9 +
  10 +@ApiModel("管理后台 - 动态表单分页 Request VO")
  11 +@Data
  12 +@EqualsAndHashCode(callSuper = true)
  13 +@ToString(callSuper = true)
  14 +public class BpmFormPageReqVO extends PageParam {
  15 +
  16 + @ApiModelProperty(value = "表单名称", example = "芋道")
  17 + private String name;
  18 +
  19 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +
  9 +import javax.validation.constraints.NotNull;
  10 +import java.util.Date;
  11 +import java.util.List;
  12 +
  13 +@ApiModel("管理后台 - 动态表单 Response VO")
  14 +@Data
  15 +@EqualsAndHashCode(callSuper = true)
  16 +@ToString(callSuper = true)
  17 +public class BpmFormRespVO extends BpmFormBaseVO {
  18 +
  19 + @ApiModelProperty(value = "表单编号", required = true, example = "1024")
  20 + private Long id;
  21 +
  22 + @ApiModelProperty(value = "表单的配置", required = true, notes = "JSON 字符串")
  23 + @NotNull(message = "表单的配置不能为空")
  24 + private String conf;
  25 +
  26 + @ApiModelProperty(value = "表单项的数组", required = true, notes = "JSON 字符串的数组")
  27 + @NotNull(message = "表单项的数组不能为空")
  28 + private List<String> fields;
  29 +
  30 + @ApiModelProperty(value = "创建时间", required = true)
  31 + private Date createTime;
  32 +
  33 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormSimpleRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +
  7 +@ApiModel("管理后台 - 流程表单精简 Response VO")
  8 +@Data
  9 +public class BpmFormSimpleRespVO {
  10 +
  11 + @ApiModelProperty(value = "表单编号", required = true, example = "1024")
  12 + private Long id;
  13 +
  14 + @ApiModelProperty(value = "表单名称", required = true, example = "芋道")
  15 + private String name;
  16 +
  17 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormUpdateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form;
  2 +
  3 +import lombok.*;
  4 +import io.swagger.annotations.*;
  5 +import javax.validation.constraints.*;
  6 +import java.util.List;
  7 +
  8 +@ApiModel("管理后台 - 动态表单更新 Request VO")
  9 +@Data
  10 +@EqualsAndHashCode(callSuper = true)
  11 +@ToString(callSuper = true)
  12 +public class BpmFormUpdateReqVO extends BpmFormBaseVO {
  13 +
  14 + @ApiModelProperty(value = "表单编号", required = true, example = "1024")
  15 + @NotNull(message = "表单编号不能为空")
  16 + private Long id;
  17 +
  18 + @ApiModelProperty(value = "表单的配置", required = true, notes = "JSON 字符串")
  19 + @NotNull(message = "表单的配置不能为空")
  20 + private String conf;
  21 +
  22 + @ApiModelProperty(value = "表单项的数组", required = true, notes = "JSON 字符串的数组")
  23 + @NotNull(message = "表单项的数组不能为空")
  24 + private List<String> fields;
  25 +
  26 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupBaseVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import io.swagger.annotations.*;
  6 +import javax.validation.constraints.*;
  7 +
  8 +/**
  9 +* 用户组 Base VO,提供给添加、修改、详细的子 VO 使用
  10 +* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
  11 +*/
  12 +@Data
  13 +public class BpmUserGroupBaseVO {
  14 +
  15 + @ApiModelProperty(value = "组名", required = true, example = "芋道")
  16 + @NotNull(message = "组名不能为空")
  17 + private String name;
  18 +
  19 + @ApiModelProperty(value = "描述", required = true, example = "芋道源码")
  20 + @NotNull(message = "描述不能为空")
  21 + private String description;
  22 +
  23 + @ApiModelProperty(value = "成员编号数组", required = true, example = "1,2,3")
  24 + @NotNull(message = "成员编号数组不能为空")
  25 + private Set<Long> memberUserIds;
  26 +
  27 + @ApiModelProperty(value = "状态", required = true, example = "1")
  28 + @NotNull(message = "状态不能为空")
  29 + private Integer status;
  30 +
  31 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupCreateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group;
  2 +
  3 +import lombok.*;
  4 +import io.swagger.annotations.*;
  5 +
  6 +@ApiModel("管理后台 - 用户组创建 Request VO")
  7 +@Data
  8 +@EqualsAndHashCode(callSuper = true)
  9 +@ToString(callSuper = true)
  10 +public class BpmUserGroupCreateReqVO extends BpmUserGroupBaseVO {
  11 +
  12 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupPageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import cn.iocoder.yudao.framework.common.util.date.DateUtils;
  5 +import io.swagger.annotations.ApiModel;
  6 +import io.swagger.annotations.ApiModelProperty;
  7 +import lombok.Data;
  8 +import lombok.EqualsAndHashCode;
  9 +import lombok.ToString;
  10 +import org.springframework.format.annotation.DateTimeFormat;
  11 +
  12 +import java.util.Date;
  13 +
  14 +@ApiModel("管理后台 - 用户组分页 Request VO")
  15 +@Data
  16 +@EqualsAndHashCode(callSuper = true)
  17 +@ToString(callSuper = true)
  18 +public class BpmUserGroupPageReqVO extends PageParam {
  19 +
  20 + @ApiModelProperty(value = "组名", example = "芋道")
  21 + private String name;
  22 +
  23 + @ApiModelProperty(value = "状态", example = "1")
  24 + private Integer status;
  25 +
  26 + @DateTimeFormat(pattern = DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  27 + @ApiModelProperty(value = "开始创建时间")
  28 + private Date beginCreateTime;
  29 +
  30 + @DateTimeFormat(pattern = DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  31 + @ApiModelProperty(value = "结束创建时间")
  32 + private Date endCreateTime;
  33 +
  34 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import io.swagger.annotations.*;
  6 +
  7 +@ApiModel("管理后台 - 用户组 Response VO")
  8 +@Data
  9 +@EqualsAndHashCode(callSuper = true)
  10 +@ToString(callSuper = true)
  11 +public class BpmUserGroupRespVO extends BpmUserGroupBaseVO {
  12 +
  13 + @ApiModelProperty(value = "编号", required = true, example = "1024")
  14 + private Long id;
  15 +
  16 + @ApiModelProperty(value = "创建时间", required = true)
  17 + private Date createTime;
  18 +
  19 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupSimpleRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.AllArgsConstructor;
  6 +import lombok.Data;
  7 +import lombok.NoArgsConstructor;
  8 +
  9 +@ApiModel("管理后台 - 用户组精简信息 Response VO")
  10 +@Data
  11 +@NoArgsConstructor
  12 +@AllArgsConstructor
  13 +public class BpmUserGroupSimpleRespVO {
  14 +
  15 + @ApiModelProperty(value = "用户组编号", required = true, example = "1024")
  16 + private Long id;
  17 +
  18 + @ApiModelProperty(value = "用户组名字", required = true, example = "芋道")
  19 + private String name;
  20 +
  21 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupUpdateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group;
  2 +
  3 +import lombok.*;
  4 +import io.swagger.annotations.*;
  5 +import javax.validation.constraints.*;
  6 +
  7 +@ApiModel("管理后台 - 用户组更新 Request VO")
  8 +@Data
  9 +@EqualsAndHashCode(callSuper = true)
  10 +@ToString(callSuper = true)
  11 +public class BpmUserGroupUpdateReqVO extends BpmUserGroupBaseVO {
  12 +
  13 + @ApiModelProperty(value = "编号", required = true, example = "1024")
  14 + @NotNull(message = "编号不能为空")
  15 + private Long id;
  16 +
  17 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModeImportReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +import org.springframework.web.multipart.MultipartFile;
  9 +
  10 +import javax.validation.constraints.NotNull;
  11 +
  12 +@ApiModel(value = "管理后台 - 流程模型的导入 Request VO", description = "相比流程模型的新建来说,只是多了一个 bpmnFile 文件")
  13 +@Data
  14 +@EqualsAndHashCode(callSuper = true)
  15 +@ToString(callSuper = true)
  16 +public class BpmModeImportReqVO extends BpmModelCreateReqVO {
  17 +
  18 + @ApiModelProperty(value = "BPMN 文件", required = true)
  19 + @NotNull(message = "BPMN 文件不能为空")
  20 + private MultipartFile bpmnFile;
  21 +
  22 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelBaseVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model;
  2 +
  3 +import io.swagger.annotations.ApiModelProperty;
  4 +import lombok.Data;
  5 +
  6 +import javax.validation.constraints.NotEmpty;
  7 +
  8 +/**
  9 +* 流程模型 Base VO,提供给添加、修改、详细的子 VO 使用
  10 +* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
  11 +*/
  12 +@Data
  13 +public class BpmModelBaseVO {
  14 +
  15 + @ApiModelProperty(value = "流程标识", required = true, example = "process_yudao")
  16 + @NotEmpty(message = "流程标识不能为空")
  17 + private String key;
  18 +
  19 + @ApiModelProperty(value = "流程名称", required = true, example = "芋道")
  20 + @NotEmpty(message = "流程名称不能为空")
  21 + private String name;
  22 +
  23 + @ApiModelProperty(value = "流程描述", example = "我是描述")
  24 + private String description;
  25 +
  26 + @ApiModelProperty(value = "流程分类", notes = "参见 bpm_model_category 数据字典", example = "1")
  27 + @NotEmpty(message = "流程分类不能为空")
  28 + private String category;
  29 +
  30 + @ApiModelProperty(value = "表单类型", notes = "参见 bpm_model_form_type 数据字典", example = "1")
  31 + private Integer formType;
  32 + @ApiModelProperty(value = "表单编号", example = "1024", notes = "在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时,必须非空")
  33 + private Long formId;
  34 + @ApiModelProperty(value = "自定义表单的提交路径,使用 Vue 的路由地址", example = "/bpm/oa/leave/create",
  35 + notes = "在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时,必须非空")
  36 + private String formCustomCreatePath;
  37 + @ApiModelProperty(value = "自定义表单的查看路径,使用 Vue 的路由地址", example = "/bpm/oa/leave/view",
  38 + notes = "在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时,必须非空")
  39 + private String formCustomViewPath;
  40 +
  41 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelCreateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +
  9 +import javax.validation.constraints.NotEmpty;
  10 +
  11 +@ApiModel("管理后台 - 流程模型的创建 Request VO")
  12 +@Data
  13 +public class BpmModelCreateReqVO {
  14 +
  15 + @ApiModelProperty(value = "流程标识", required = true, example = "process_yudao")
  16 + @NotEmpty(message = "流程标识不能为空")
  17 + private String key;
  18 +
  19 + @ApiModelProperty(value = "流程名称", required = true, example = "芋道")
  20 + @NotEmpty(message = "流程名称不能为空")
  21 + private String name;
  22 +
  23 + @ApiModelProperty(value = "流程描述", example = "我是描述")
  24 + private String description;
  25 +
  26 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelPageItemRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +
  9 +import java.util.Date;
  10 +
  11 +@ApiModel("管理后台 - 流程模型的分页的每一项 Response VO")
  12 +@Data
  13 +@EqualsAndHashCode(callSuper = true)
  14 +@ToString(callSuper = true)
  15 +public class BpmModelPageItemRespVO extends BpmModelBaseVO {
  16 +
  17 + @ApiModelProperty(value = "编号", required = true, example = "1024")
  18 + private String id;
  19 +
  20 + @ApiModelProperty(value = "表单名字", example = "请假表单")
  21 + private String formName;
  22 +
  23 + @ApiModelProperty(value = "创建时间", required = true)
  24 + private Date createTime;
  25 +
  26 + /**
  27 + * 最新部署的流程定义
  28 + */
  29 + private ProcessDefinition processDefinition;
  30 +
  31 + @ApiModel("流程定义")
  32 + @Data
  33 + public static class ProcessDefinition {
  34 +
  35 + @ApiModelProperty(value = "编号", required = true, example = "1024")
  36 + private String id;
  37 +
  38 + @ApiModelProperty(value = "版本", required = true, example = "1")
  39 + private Integer version;
  40 +
  41 + @ApiModelProperty(value = "部署时间", required = true)
  42 + private Date deploymentTime;
  43 +
  44 + @ApiModelProperty(value = "中断状态", required = true, example = "1", notes = "参见 SuspensionState 枚举")
  45 + private Integer suspensionState;
  46 +
  47 + }
  48 +
  49 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelPageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import io.swagger.annotations.ApiModel;
  5 +import io.swagger.annotations.ApiModelProperty;
  6 +import lombok.Data;
  7 +import lombok.EqualsAndHashCode;
  8 +import lombok.ToString;
  9 +
  10 +
  11 +@ApiModel("管理后台 - 流程模型分页 Request VO")
  12 +@Data
  13 +@EqualsAndHashCode(callSuper = true)
  14 +@ToString(callSuper = true)
  15 +public class BpmModelPageReqVO extends PageParam {
  16 +
  17 + @ApiModelProperty(value = "标识", example = "process1641042089407", notes = "精准匹配")
  18 + private String key;
  19 +
  20 + @ApiModelProperty(value = "名字", example = "芋道", notes = "模糊匹配")
  21 + private String name;
  22 +
  23 + @ApiModelProperty(value = "流程分类", notes = "参见 bpm_model_category 数据字典", example = "1")
  24 + private String category;
  25 +
  26 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +
  9 +import java.util.Date;
  10 +
  11 +@ApiModel("管理后台 - 流程模型的创建 Request VO")
  12 +@Data
  13 +@EqualsAndHashCode(callSuper = true)
  14 +@ToString(callSuper = true)
  15 +public class BpmModelRespVO extends BpmModelBaseVO {
  16 +
  17 + @ApiModelProperty(value = "编号", required = true, example = "1024")
  18 + private String id;
  19 +
  20 + @ApiModelProperty(value = "BPMN XML", required = true)
  21 + private String bpmnXml;
  22 +
  23 + @ApiModelProperty(value = "创建时间", required = true)
  24 + private Date createTime;
  25 +
  26 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelUpdateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +
  7 +import javax.validation.constraints.NotEmpty;
  8 +
  9 +@ApiModel("管理后台 - 流程模型的更新 Request VO")
  10 +@Data
  11 +public class BpmModelUpdateReqVO {
  12 +
  13 + @ApiModelProperty(value = "编号", required = true, example = "1024")
  14 + @NotEmpty(message = "编号不能为空")
  15 + private String id;
  16 +
  17 + @ApiModelProperty(value = "流程名称", example = "芋道")
  18 + private String name;
  19 +
  20 + @ApiModelProperty(value = "流程描述", example = "我是描述")
  21 + private String description;
  22 +
  23 + @ApiModelProperty(value = "流程分类", notes = "参见 bpm_model_category 数据字典", example = "1")
  24 + private String category;
  25 +
  26 + @ApiModelProperty(value = "BPMN XML", required = true)
  27 + private String bpmnXml;
  28 +
  29 + @ApiModelProperty(value = "表单类型", notes = "参见 bpm_model_form_type 数据字典", example = "1")
  30 + private Integer formType;
  31 + @ApiModelProperty(value = "表单编号", example = "1024", notes = "在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时,必须非空")
  32 + private Long formId;
  33 + @ApiModelProperty(value = "自定义表单的提交路径,使用 Vue 的路由地址", example = "/bpm/oa/leave/create",
  34 + notes = "在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时,必须非空")
  35 + private String formCustomCreatePath;
  36 + @ApiModelProperty(value = "自定义表单的查看路径,使用 Vue 的路由地址", example = "/bpm/oa/leave/view",
  37 + notes = "在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时,必须非空")
  38 + private String formCustomViewPath;
  39 +
  40 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelUpdateStateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +
  7 +import javax.validation.constraints.NotNull;
  8 +
  9 +@ApiModel("管理后台 - 流程模型更新状态 Request VO")
  10 +@Data
  11 +public class BpmModelUpdateStateReqVO {
  12 +
  13 + @ApiModelProperty(value = "编号", required = true, example = "1024")
  14 + @NotNull(message = "编号不能为空")
  15 + private String id;
  16 +
  17 + @ApiModelProperty(value = "状态", required = true, example = "1", notes = "见 SuspensionState 枚举")
  18 + @NotNull(message = "状态不能为空")
  19 + private Integer state;
  20 +
  21 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionListReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import io.swagger.annotations.ApiModel;
  5 +import io.swagger.annotations.ApiModelProperty;
  6 +import lombok.Data;
  7 +import lombok.EqualsAndHashCode;
  8 +import lombok.ToString;
  9 +
  10 +@ApiModel("管理后台 - 流程定义列表 Request VO")
  11 +@Data
  12 +@ToString(callSuper = true)
  13 +@EqualsAndHashCode(callSuper = true)
  14 +public class BpmProcessDefinitionListReqVO extends PageParam {
  15 +
  16 + @ApiModelProperty(value = "中断状态", example = "1", notes = "参见 SuspensionState 枚举")
  17 + private Integer suspensionState;
  18 +
  19 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionPageItemRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +
  9 +import java.util.Date;
  10 +
  11 +@ApiModel("管理后台 - 流程定义的分页的每一项 Response VO")
  12 +@Data
  13 +@EqualsAndHashCode(callSuper = true)
  14 +@ToString(callSuper = true)
  15 +public class BpmProcessDefinitionPageItemRespVO extends BpmProcessDefinitionRespVO {
  16 +
  17 + @ApiModelProperty(value = "表单名字", example = "请假表单")
  18 + private String formName;
  19 +
  20 + @ApiModelProperty(value = "部署时间", required = true)
  21 + private Date deploymentTime;
  22 +
  23 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionPageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import io.swagger.annotations.ApiModel;
  5 +import io.swagger.annotations.ApiModelProperty;
  6 +import lombok.Data;
  7 +import lombok.EqualsAndHashCode;
  8 +import lombok.ToString;
  9 +
  10 +@ApiModel("管理后台 - 流程定义分页 Request VO")
  11 +@Data
  12 +@ToString(callSuper = true)
  13 +@EqualsAndHashCode(callSuper = true)
  14 +public class BpmProcessDefinitionPageReqVO extends PageParam {
  15 +
  16 + @ApiModelProperty(value = "标识", example = "process1641042089407", notes = "精准匹配")
  17 + private String key;
  18 +
  19 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +
  7 +import javax.validation.constraints.NotEmpty;
  8 +import javax.validation.constraints.NotNull;
  9 +import java.util.List;
  10 +
  11 +@ApiModel("管理后台 - 流程定义 Response VO")
  12 +@Data
  13 +public class BpmProcessDefinitionRespVO {
  14 +
  15 + @ApiModelProperty(value = "编号", required = true, example = "1024")
  16 + private String id;
  17 +
  18 + @ApiModelProperty(value = "版本", required = true, example = "1")
  19 + private Integer version;
  20 +
  21 + @ApiModelProperty(value = "流程名称", required = true, example = "芋道")
  22 + @NotEmpty(message = "流程名称不能为空")
  23 + private String name;
  24 +
  25 + @ApiModelProperty(value = "流程描述", example = "我是描述")
  26 + private String description;
  27 +
  28 + @ApiModelProperty(value = "流程分类", notes = "参见 bpm_model_category 数据字典", example = "1")
  29 + @NotEmpty(message = "流程分类不能为空")
  30 + private String category;
  31 +
  32 + @ApiModelProperty(value = "表单类型", notes = "参见 bpm_model_form_type 数据字典", example = "1")
  33 + private Integer formType;
  34 + @ApiModelProperty(value = "表单编号", example = "1024", notes = "在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时,必须非空")
  35 + private Long formId;
  36 + @ApiModelProperty(value = "表单的配置", required = true,
  37 + notes = "JSON 字符串。在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时,必须非空")
  38 + private String formConf;
  39 + @ApiModelProperty(value = "表单项的数组", required = true,
  40 + notes = "JSON 字符串的数组。在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时,必须非空")
  41 + private List<String> formFields;
  42 + @ApiModelProperty(value = "自定义表单的提交路径,使用 Vue 的路由地址", example = "/bpm/oa/leave/create",
  43 + notes = "在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时,必须非空")
  44 + private String formCustomCreatePath;
  45 + @ApiModelProperty(value = "自定义表单的查看路径,使用 Vue 的路由地址", example = "/bpm/oa/leave/view",
  46 + notes = "在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时,必须非空")
  47 + private String formCustomViewPath;
  48 +
  49 + @ApiModelProperty(value = "中断状态", required = true, example = "1", notes = "参见 SuspensionState 枚举")
  50 + private Integer suspensionState;
  51 +
  52 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/rule/BpmTaskAssignRuleBaseVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule;
  2 +
  3 +import io.swagger.annotations.ApiModelProperty;
  4 +import lombok.Data;
  5 +
  6 +import javax.validation.constraints.NotEmpty;
  7 +import javax.validation.constraints.NotNull;
  8 +import java.util.Set;
  9 +
  10 +/**
  11 + * 流程任务分配规则 Base VO,提供给添加、修改、详细的子 VO 使用
  12 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
  13 + */
  14 +@Data
  15 +public class BpmTaskAssignRuleBaseVO {
  16 +
  17 + @ApiModelProperty(value = "规则类型", required = true, example = "bpm_task_assign_rule_type")
  18 + @NotNull(message = "规则类型不能为空")
  19 + private Integer type;
  20 +
  21 + @ApiModelProperty(value = "规则值数组", required = true, example = "1,2,3")
  22 + @NotNull(message = "规则值数组不能为空")
  23 + private Set<Long> options;
  24 +
  25 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/rule/BpmTaskAssignRuleCreateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +
  9 +import javax.validation.constraints.NotEmpty;
  10 +
  11 +@ApiModel("管理后台 - 流程任务分配规则的创建 Request VO")
  12 +@Data
  13 +@EqualsAndHashCode(callSuper = true)
  14 +@ToString(callSuper = true)
  15 +public class BpmTaskAssignRuleCreateReqVO extends BpmTaskAssignRuleBaseVO {
  16 +
  17 + @ApiModelProperty(value = "流程模型的编号", required = true, example = "1024")
  18 + @NotEmpty(message = "流程模型的编号不能为空")
  19 + private String modelId;
  20 +
  21 + @ApiModelProperty(value = "流程任务定义的编号", required = true, example = "2048")
  22 + @NotEmpty(message = "流程任务定义的编号不能为空")
  23 + private String taskDefinitionKey;
  24 +
  25 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/rule/BpmTaskAssignRuleRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +
  9 +@ApiModel("管理后台 - 流程任务分配规则的 Response VO")
  10 +@Data
  11 +@EqualsAndHashCode(callSuper = true)
  12 +@ToString(callSuper = true)
  13 +public class BpmTaskAssignRuleRespVO extends BpmTaskAssignRuleBaseVO {
  14 +
  15 + @ApiModelProperty(value = "任务分配规则的编号", required = true, example = "1024")
  16 + private Long id;
  17 +
  18 + @ApiModelProperty(value = "流程模型的编号", required = true, example = "2048")
  19 + private String modelId;
  20 +
  21 + @ApiModelProperty(value = "流程定义的编号", required = true, example = "4096")
  22 + private String processDefinitionId;
  23 +
  24 + @ApiModelProperty(value = "流程任务定义的编号", required = true, example = "2048")
  25 + private String taskDefinitionKey;
  26 + @ApiModelProperty(value = "流程任务定义的名字", required = true, example = "关注芋道")
  27 + private String taskDefinitionName;
  28 +
  29 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/rule/BpmTaskAssignRuleUpdateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +
  9 +import javax.validation.constraints.NotNull;
  10 +
  11 +@ApiModel("管理后台 - 流程任务分配规则的更新 Request VO")
  12 +@Data
  13 +@EqualsAndHashCode(callSuper = true)
  14 +@ToString(callSuper = true)
  15 +public class BpmTaskAssignRuleUpdateReqVO extends BpmTaskAssignRuleBaseVO {
  16 +
  17 + @ApiModelProperty(value = "任务分配规则的编号", required = true, example = "1024")
  18 + @NotNull(message = "任务分配规则的编号不能为空")
  19 + private Long id;
  20 +
  21 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOALeaveController.http 0 → 100644
  1 +### 请求 /bpm/oa/leave/create 接口 => 成功
  2 +POST {{baseUrl}}/bpm/oa/leave/create
  3 +Content-Type: application/json
  4 +tenant-id: 1
  5 +Authorization: Bearer {{token}}
  6 +
  7 +{
  8 + "startTime": "2022-03-01",
  9 + "endTime": "2022-03-05",
  10 + "type": 1,
  11 + "reason": "我要请假啦啦啦!"
  12 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOALeaveController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.oa;
  2 +
  3 +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOALeaveCreateReqVO;
  4 +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOALeavePageReqVO;
  5 +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOALeaveRespVO;
  6 +import cn.iocoder.yudao.module.bpm.convert.oa.BpmOALeaveConvert;
  7 +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALeaveDO;
  8 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  9 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  10 +import cn.iocoder.yudao.module.bpm.service.oa.BpmOALeaveService;
  11 +import io.swagger.annotations.Api;
  12 +import io.swagger.annotations.ApiImplicitParam;
  13 +import io.swagger.annotations.ApiOperation;
  14 +import org.springframework.security.access.prepost.PreAuthorize;
  15 +import org.springframework.validation.annotation.Validated;
  16 +import org.springframework.web.bind.annotation.*;
  17 +
  18 +import javax.annotation.Resource;
  19 +import javax.validation.Valid;
  20 +
  21 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  22 +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
  23 +
  24 +/**
  25 + * OA 请假申请 Controller,用于演示自己存储数据,接入工作流的例子
  26 + *
  27 + * @author jason
  28 + * @author 芋道源码
  29 + */
  30 +@Api(tags = "管理后台 - OA 请假申请")
  31 +@RestController
  32 +@RequestMapping("/bpm/oa/leave")
  33 +@Validated
  34 +public class BpmOALeaveController {
  35 +
  36 + @Resource
  37 + private BpmOALeaveService leaveService;
  38 +
  39 + @PostMapping("/create")
  40 + @PreAuthorize("@ss.hasPermission('bpm:oa-leave:create')")
  41 + @ApiOperation("创建请求申请")
  42 + public CommonResult<Long> createLeave(@Valid @RequestBody BpmOALeaveCreateReqVO createReqVO) {
  43 + return success(leaveService.createLeave(getLoginUserId(), createReqVO));
  44 + }
  45 +
  46 + @GetMapping("/get")
  47 + @PreAuthorize("@ss.hasPermission('bpm:oa-leave:query')")
  48 + @ApiOperation("获得请假申请")
  49 + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
  50 + public CommonResult<BpmOALeaveRespVO> getLeave(@RequestParam("id") Long id) {
  51 + BpmOALeaveDO leave = leaveService.getLeave(id);
  52 + return success(BpmOALeaveConvert.INSTANCE.convert(leave));
  53 + }
  54 +
  55 + @GetMapping("/page")
  56 + @PreAuthorize("@ss.hasPermission('bpm:oa-leave:query')")
  57 + @ApiOperation("获得请假申请分页")
  58 + public CommonResult<PageResult<BpmOALeaveRespVO>> getLeavePage(@Valid BpmOALeavePageReqVO pageVO) {
  59 + PageResult<BpmOALeaveDO> pageResult = leaveService.getLeavePage(getLoginUserId(), pageVO);
  60 + return success(BpmOALeaveConvert.INSTANCE.convertPage(pageResult));
  61 + }
  62 +
  63 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/package-info.java 0 → 100644
  1 +/**
  2 + * OA 示例,用于演示外部业务接入 BPM 工作流的示例
  3 + * 一般的接入方式,只需要调用 接口,后续 Admin 用户在管理后台的【待办事务】进行审批
  4 + */
  5 +package cn.iocoder.yudao.module.bpm.controller.admin.oa;
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveBaseVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import io.swagger.annotations.*;
  6 +import javax.validation.constraints.*;
  7 +import org.springframework.format.annotation.DateTimeFormat;
  8 +
  9 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  10 +
  11 +/**
  12 +* 请假申请 Base VO,提供给添加、修改、详细的子 VO 使用
  13 +* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
  14 +*/
  15 +@Data
  16 +public class BpmOALeaveBaseVO {
  17 +
  18 + @ApiModelProperty(value = "请假的开始时间", required = true)
  19 + @NotNull(message = "开始时间不能为空")
  20 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  21 + private Date startTime;
  22 + @ApiModelProperty(value = "请假的结束时间", required = true)
  23 + @NotNull(message = "结束时间不能为空")
  24 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  25 + private Date endTime;
  26 +
  27 + @ApiModelProperty(value = "请假类型", required = true, example = "1", notes = "参见 bpm_oa_type 枚举")
  28 + private Integer type;
  29 +
  30 + @ApiModelProperty(value = "原因", required = true, example = "阅读芋道源码")
  31 + private String reason;
  32 +
  33 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveCreateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
  6 +import lombok.ToString;
  7 +
  8 +import javax.validation.constraints.AssertTrue;
  9 +
  10 +@ApiModel("管理后台 - 请假申请创建 Request VO")
  11 +@Data
  12 +@EqualsAndHashCode(callSuper = true)
  13 +@ToString(callSuper = true)
  14 +public class BpmOALeaveCreateReqVO extends BpmOALeaveBaseVO {
  15 +
  16 + @AssertTrue(message = "结束时间,需要在开始时间之后")
  17 + public boolean isEndTimeValid() {
  18 + return !getEndTime().before(getStartTime());
  19 + }
  20 +
  21 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeavePageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import io.swagger.annotations.*;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  7 +import org.springframework.format.annotation.DateTimeFormat;
  8 +
  9 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  10 +
  11 +@ApiModel("管理后台 - 请假申请分页 Request VO")
  12 +@Data
  13 +@EqualsAndHashCode(callSuper = true)
  14 +@ToString(callSuper = true)
  15 +public class BpmOALeavePageReqVO extends PageParam {
  16 +
  17 + @ApiModelProperty(value = "状态", example = "1", notes = "参见 bpm_process_instance_result 枚举")
  18 + private Integer result;
  19 +
  20 + @ApiModelProperty(value = "请假类型", example = "1", notes = "参见 bpm_oa_type")
  21 + private Integer type;
  22 +
  23 + @ApiModelProperty(value = "原因", example = "阅读芋道源码", notes = "模糊匹配")
  24 + private String reason;
  25 +
  26 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  27 + @ApiModelProperty(value = "开始申请时间")
  28 + private Date beginCreateTime;
  29 +
  30 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  31 + @ApiModelProperty(value = "结束申请时间")
  32 + private Date endCreateTime;
  33 +
  34 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo;
  2 +
  3 +import lombok.*;
  4 +import io.swagger.annotations.*;
  5 +import org.springframework.format.annotation.DateTimeFormat;
  6 +
  7 +import javax.validation.constraints.NotNull;
  8 +import java.util.Date;
  9 +
  10 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  11 +
  12 +@ApiModel("管理后台 - 请假申请 Response VO")
  13 +@Data
  14 +@EqualsAndHashCode(callSuper = true)
  15 +@ToString(callSuper = true)
  16 +public class BpmOALeaveRespVO extends BpmOALeaveBaseVO {
  17 +
  18 + @ApiModelProperty(value = "请假表单主键", required = true, example = "1024")
  19 + private Long id;
  20 +
  21 + @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 bpm_process_instance_result 枚举")
  22 + private Integer result;
  23 +
  24 + @ApiModelProperty(value = "申请时间", required = true)
  25 + @NotNull(message = "申请时间不能为空")
  26 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  27 + private Date createTime;
  28 +
  29 + @ApiModelProperty(value = "流程id")
  30 + private String processInstanceId;
  31 +
  32 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmActivityController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.task;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  4 +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity.BpmActivityRespVO;
  5 +import cn.iocoder.yudao.module.bpm.service.task.BpmActivityService;
  6 +import io.swagger.annotations.Api;
  7 +import io.swagger.annotations.ApiImplicitParam;
  8 +import io.swagger.annotations.ApiOperation;
  9 +import org.springframework.security.access.prepost.PreAuthorize;
  10 +import org.springframework.validation.annotation.Validated;
  11 +import org.springframework.web.bind.annotation.GetMapping;
  12 +import org.springframework.web.bind.annotation.RequestMapping;
  13 +import org.springframework.web.bind.annotation.RequestParam;
  14 +import org.springframework.web.bind.annotation.RestController;
  15 +
  16 +import javax.annotation.Resource;
  17 +import java.util.List;
  18 +
  19 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  20 +
  21 +@Api(tags = "管理后台 - 流程活动实例")
  22 +@RestController
  23 +@RequestMapping("/bpm/activity")
  24 +@Validated
  25 +public class BpmActivityController {
  26 +
  27 + @Resource
  28 + private BpmActivityService activityService;
  29 +
  30 + @GetMapping("/list")
  31 + @ApiOperation(value = "生成指定流程实例的高亮流程图",
  32 + notes = "只高亮进行中的任务。不过要注意,该接口暂时没用,通过前端的 ProcessViewer.vue 界面的 highlightDiagram 方法生成")
  33 + @ApiImplicitParam(name = "processInstanceId", value = "流程实例的编号", required = true, dataTypeClass = String.class)
  34 + @PreAuthorize("@ss.hasPermission('bpm:task:query')")
  35 + public CommonResult<List<BpmActivityRespVO>> getActivityList(
  36 + @RequestParam("processInstanceId") String processInstanceId) {
  37 + return success(activityService.getActivityListByProcessInstanceId(processInstanceId));
  38 + }
  39 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.task;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*;
  6 +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
  7 +import io.swagger.annotations.Api;
  8 +import io.swagger.annotations.ApiImplicitParam;
  9 +import io.swagger.annotations.ApiOperation;
  10 +import org.springframework.security.access.prepost.PreAuthorize;
  11 +import org.springframework.validation.annotation.Validated;
  12 +import org.springframework.web.bind.annotation.*;
  13 +
  14 +import javax.annotation.Resource;
  15 +import javax.validation.Valid;
  16 +
  17 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  18 +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
  19 +
  20 +@Api(tags = "管理后台 - 流程实例") // 流程实例,通过流程定义创建的一次“申请”
  21 +@RestController
  22 +@RequestMapping("/bpm/process-instance")
  23 +@Validated
  24 +public class BpmProcessInstanceController {
  25 + @Resource
  26 + private BpmProcessInstanceService processInstanceService;
  27 +
  28 + @GetMapping("/my-page")
  29 + @ApiOperation(value = "获得我的实例分页列表", notes = "在【我的流程】菜单中,进行调用")
  30 + @PreAuthorize("@ss.hasPermission('bpm:process-instance:query')")
  31 + public CommonResult<PageResult<BpmProcessInstancePageItemRespVO>> getMyProcessInstancePage(
  32 + @Valid BpmProcessInstanceMyPageReqVO pageReqVO) {
  33 + return success(processInstanceService.getMyProcessInstancePage(getLoginUserId(), pageReqVO));
  34 + }
  35 +
  36 + @PostMapping("/create")
  37 + @ApiOperation("新建流程实例")
  38 + @PreAuthorize("@ss.hasPermission('bpm:process-instance:query')")
  39 + public CommonResult<String> createProcessInstance(@Valid @RequestBody BpmProcessInstanceCreateReqVO createReqVO) {
  40 + return success(processInstanceService.createProcessInstance(getLoginUserId(), createReqVO));
  41 + }
  42 +
  43 + @GetMapping("/get")
  44 + @ApiOperation(value = "获得指定流程实例", notes = "在【流程详细】界面中,进行调用")
  45 + @ApiImplicitParam(name = "id", value = "流程实例的编号", required = true, dataTypeClass = String.class)
  46 + @PreAuthorize("@ss.hasPermission('bpm:process-instance:query')")
  47 + public CommonResult<BpmProcessInstanceRespVO> getProcessInstance(@RequestParam("id") String id) {
  48 + return success(processInstanceService.getProcessInstanceVO(id));
  49 + }
  50 +
  51 + @DeleteMapping("/cancel")
  52 + @ApiOperation(value = "取消流程实例", notes = "撤回发起的流程")
  53 + @PreAuthorize("@ss.hasPermission('bpm:process-instance:cancel')")
  54 + public CommonResult<Boolean> cancelProcessInstance(@Valid @RequestBody BpmProcessInstanceCancelReqVO cancelReqVO) {
  55 + processInstanceService.cancelProcessInstance(getLoginUserId(), cancelReqVO);
  56 + return success(true);
  57 + }
  58 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.task;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
  6 +import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService;
  7 +import io.swagger.annotations.Api;
  8 +import io.swagger.annotations.ApiImplicitParam;
  9 +import io.swagger.annotations.ApiOperation;
  10 +import org.flowable.bpmn.model.BpmnModel;
  11 +import org.flowable.engine.TaskService;
  12 +import org.springframework.security.access.prepost.PreAuthorize;
  13 +import org.springframework.validation.annotation.Validated;
  14 +import org.springframework.web.bind.annotation.*;
  15 +
  16 +import javax.annotation.Resource;
  17 +import javax.validation.Valid;
  18 +
  19 +import java.util.List;
  20 +
  21 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  22 +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
  23 +
  24 +@Api(tags = "管理后台 - 流程任务实例")
  25 +@RestController
  26 +@RequestMapping("/bpm/task")
  27 +@Validated
  28 +public class BpmTaskController {
  29 +
  30 + @Resource
  31 + private BpmTaskService taskService;
  32 +
  33 + @GetMapping("todo-page")
  34 + @ApiOperation("获取 Todo 待办任务分页")
  35 + @PreAuthorize("@ss.hasPermission('bpm:task:query')")
  36 + public CommonResult<PageResult<BpmTaskTodoPageItemRespVO>> getTodoTaskPage(@Valid BpmTaskTodoPageReqVO pageVO) {
  37 + return success(taskService.getTodoTaskPage(getLoginUserId(), pageVO));
  38 + }
  39 +
  40 + @GetMapping("done-page")
  41 + @ApiOperation("获取 Done 已办任务分页")
  42 + @PreAuthorize("@ss.hasPermission('bpm:task:query')")
  43 + public CommonResult<PageResult<BpmTaskDonePageItemRespVO>> getDoneTaskPage(@Valid BpmTaskDonePageReqVO pageVO) {
  44 + return success(taskService.getDoneTaskPage(getLoginUserId(), pageVO));
  45 + }
  46 +
  47 + @GetMapping("/list-by-process-instance-id")
  48 + @ApiOperation(value = "获得指定流程实例的任务列表", notes = "包括完成的、未完成的")
  49 + @ApiImplicitParam(name = "processInstanceId", value = "流程实例的编号", required = true, dataTypeClass = String.class)
  50 + @PreAuthorize("@ss.hasPermission('bpm:task:query')")
  51 + public CommonResult<List<BpmTaskRespVO>> getTaskListByProcessInstanceId(
  52 + @RequestParam("processInstanceId") String processInstanceId) {
  53 + return success(taskService.getTaskListByProcessInstanceId(processInstanceId));
  54 + }
  55 +
  56 + @PutMapping("/approve")
  57 + @ApiOperation("通过任务")
  58 + @PreAuthorize("@ss.hasPermission('bpm:task:update')")
  59 + public CommonResult<Boolean> approveTask(@Valid @RequestBody BpmTaskApproveReqVO reqVO) {
  60 + taskService.approveTask(getLoginUserId(), reqVO);
  61 + return success(true);
  62 + }
  63 +
  64 + @PutMapping("/reject")
  65 + @ApiOperation("不通过任务")
  66 + @PreAuthorize("@ss.hasPermission('bpm:task:update')")
  67 + public CommonResult<Boolean> rejectTask(@Valid @RequestBody BpmTaskRejectReqVO reqVO) {
  68 + taskService.rejectTask(getLoginUserId(), reqVO);
  69 + return success(true);
  70 + }
  71 +
  72 + @PutMapping("/update-assignee")
  73 + @ApiOperation(value = "更新任务的负责人", notes = "用于【流程详情】的【转派】按钮")
  74 + @PreAuthorize("@ss.hasPermission('bpm:task:update')")
  75 + public CommonResult<Boolean> updateTaskAssignee(@Valid @RequestBody BpmTaskUpdateAssigneeReqVO reqVO) {
  76 + taskService.updateTaskAssignee(getLoginUserId(), reqVO);
  77 + return success(true);
  78 + }
  79 + @PutMapping("/back")
  80 + @ApiOperation(value = "回退")
  81 +// @PreAuthorize("@ss.hasPermission('bpm:task:back')")
  82 + public CommonResult<Boolean> backTask(@Valid @RequestBody BpmTaskUpdateAssigneeReqVO reqVO) {
  83 + //先硬编码到 回退到第一个审批节点
  84 + String destinationTaskDefKey = "task01";
  85 + taskService.backTask(reqVO.getId(),destinationTaskDefKey);
  86 + return success(true);
  87 + }
  88 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/package-info.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.task;
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/activity/BpmActivityRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +
  7 +import java.util.Date;
  8 +
  9 +@ApiModel("管理后台 - 流程活动的 Response VO")
  10 +@Data
  11 +public class BpmActivityRespVO {
  12 +
  13 + @ApiModelProperty(value = "流程活动的标识", required = true, example = "1024")
  14 + private String key;
  15 + @ApiModelProperty(value = "流程活动的类型", required = true, example = "StartEvent")
  16 + private String type;
  17 +
  18 + @ApiModelProperty(value = "流程活动的开始时间", required = true)
  19 + private Date startTime;
  20 + @ApiModelProperty(value = "流程活动的结束时间", required = true)
  21 + private Date endTime;
  22 +
  23 + @ApiModelProperty(value = "关联的流程任务的编号", example = "2048", notes = "关联的流程任务,只有 UserTask 等类型才有")
  24 + private String taskId;
  25 +
  26 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCancelReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +
  7 +import javax.validation.constraints.NotEmpty;
  8 +import javax.validation.constraints.NotNull;
  9 +import java.util.Map;
  10 +
  11 +@ApiModel("管理后台 - 流程实例的取消 Request VO")
  12 +@Data
  13 +public class BpmProcessInstanceCancelReqVO {
  14 +
  15 + @ApiModelProperty(value = "流程实例的编号", required = true, example = "1024")
  16 + @NotEmpty(message = "流程实例的编号不能为空")
  17 + private String id;
  18 +
  19 + @ApiModelProperty(value = "取消原因", required = true, example = "不请假了!")
  20 + @NotEmpty(message = "取消原因不能为空")
  21 + private String reason;
  22 +
  23 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCreateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +
  7 +import javax.validation.constraints.NotEmpty;
  8 +import java.util.Map;
  9 +
  10 +@ApiModel("管理后台 - 流程实例的创建 Request VO")
  11 +@Data
  12 +public class BpmProcessInstanceCreateReqVO {
  13 +
  14 + @ApiModelProperty(value = "流程定义的编号", required = true, example = "1024")
  15 + @NotEmpty(message = "流程定义编号不能为空")
  16 + private String processDefinitionId;
  17 +
  18 + @ApiModelProperty(value = "变量实例")
  19 + private Map<String, Object> variables;
  20 +
  21 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceMyPageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import io.swagger.annotations.ApiModel;
  5 +import io.swagger.annotations.ApiModelProperty;
  6 +import lombok.Data;
  7 +import lombok.EqualsAndHashCode;
  8 +import lombok.ToString;
  9 +import org.springframework.format.annotation.DateTimeFormat;
  10 +
  11 +import java.util.Date;
  12 +
  13 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  14 +
  15 +@ApiModel("管理后台 - 流程实例的分页 Item Response VO")
  16 +@Data
  17 +@EqualsAndHashCode(callSuper = true)
  18 +@ToString(callSuper = true)
  19 +public class BpmProcessInstanceMyPageReqVO extends PageParam {
  20 +
  21 + @ApiModelProperty(value = "流程名称", example = "芋道")
  22 + private String name;
  23 +
  24 + @ApiModelProperty(value = "流程定义的编号", example = "2048")
  25 + private String processDefinitionId;
  26 +
  27 + @ApiModelProperty(value = "流程实例的状态", notes = "参见 bpm_process_instance_status", example = "1")
  28 + private Integer status;
  29 +
  30 + @ApiModelProperty(value = "流程实例的结果", notes = "参见 bpm_process_instance_result", example = "2")
  31 + private Integer result;
  32 +
  33 + @ApiModelProperty(value = "流程分类", notes = "参见 bpm_model_category 数据字典", example = "1")
  34 + private String category;
  35 +
  36 + @ApiModelProperty(value = "开始的创建时间")
  37 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  38 + private Date beginCreateTime;
  39 +
  40 + @ApiModelProperty(value = "结束的创建时间")
  41 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  42 + private Date endCreateTime;
  43 +
  44 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstancePageItemRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +
  7 +import java.util.Date;
  8 +import java.util.List;
  9 +
  10 +@ApiModel("管理后台 - 流程实例的分页 Item Response VO")
  11 +@Data
  12 +public class BpmProcessInstancePageItemRespVO {
  13 +
  14 + @ApiModelProperty(value = "流程实例的编号", required = true, example = "1024")
  15 + private String id;
  16 +
  17 + @ApiModelProperty(value = "流程名称", required = true, example = "芋道")
  18 + private String name;
  19 +
  20 + @ApiModelProperty(value = "流程定义的编号", required = true, example = "2048")
  21 + private String processDefinitionId;
  22 +
  23 + @ApiModelProperty(value = "流程分类", required = true, notes = "参见 bpm_model_category 数据字典", example = "1")
  24 + private String category;
  25 +
  26 + @ApiModelProperty(value = "流程实例的状态", required = true, notes = "参见 bpm_process_instance_status", example = "1")
  27 + private Integer status;
  28 +
  29 + @ApiModelProperty(value = "流程实例的结果", required = true, notes = "参见 bpm_process_instance_result", example = "2")
  30 + private Integer result;
  31 +
  32 + @ApiModelProperty(value = "提交时间", required = true)
  33 + private Date createTime;
  34 +
  35 + @ApiModelProperty(value = "结束时间", required = true)
  36 + private Date endTime;
  37 +
  38 + /**
  39 + * 当前任务
  40 + */
  41 + private List<Task> tasks;
  42 +
  43 + @ApiModel("流程任务")
  44 + @Data
  45 + public static class Task {
  46 +
  47 + @ApiModelProperty(value = "流程任务的编号", required = true, example = "1024")
  48 + private String id;
  49 +
  50 + @ApiModelProperty(value = "任务名称", required = true, example = "芋道")
  51 + private String name;
  52 +
  53 + }
  54 +
  55 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +
  7 +import java.util.Date;
  8 +import java.util.List;
  9 +import java.util.Map;
  10 +
  11 +@ApiModel("管理后台 - 流程实例的 Response VO")
  12 +@Data
  13 +public class BpmProcessInstanceRespVO {
  14 +
  15 + @ApiModelProperty(value = "流程实例的编号", required = true, example = "1024")
  16 + private String id;
  17 +
  18 + @ApiModelProperty(value = "流程名称", required = true, example = "芋道")
  19 + private String name;
  20 +
  21 + @ApiModelProperty(value = "流程分类", required = true, notes = "参见 bpm_model_category 数据字典", example = "1")
  22 + private String category;
  23 +
  24 + @ApiModelProperty(value = "流程实例的状态", required = true, notes = "参见 bpm_process_instance_status", example = "1")
  25 + private Integer status;
  26 +
  27 + @ApiModelProperty(value = "流程实例的结果", required = true, notes = "参见 bpm_process_instance_result", example = "2")
  28 + private Integer result;
  29 +
  30 + @ApiModelProperty(value = "提交时间", required = true)
  31 + private Date createTime;
  32 +
  33 + @ApiModelProperty(value = "结束时间", required = true)
  34 + private Date endTime;
  35 +
  36 + @ApiModelProperty(value = "提交的表单值", required = true)
  37 + private Map<String, Object> formVariables;
  38 +
  39 + @ApiModelProperty(value = "业务的唯一标识", example = "1", notes = "例如说,请假申请的编号")
  40 + private String businessKey;
  41 +
  42 + /**
  43 + * 发起流程的用户
  44 + */
  45 + private User startUser;
  46 +
  47 + /**
  48 + * 流程定义
  49 + */
  50 + private ProcessDefinition processDefinition;
  51 +
  52 + @ApiModel("用户信息")
  53 + @Data
  54 + public static class User {
  55 +
  56 + @ApiModelProperty(value = "用户编号", required = true, example = "1")
  57 + private Long id;
  58 + @ApiModelProperty(value = "用户昵称", required = true, example = "芋艿")
  59 + private String nickname;
  60 +
  61 + @ApiModelProperty(value = "部门编号", required = true, example = "1")
  62 + private Long deptId;
  63 + @ApiModelProperty(value = "部门名称", required = true, example = "研发部")
  64 + private String deptName;
  65 +
  66 + }
  67 +
  68 + @ApiModel("流程定义信息")
  69 + @Data
  70 + public static class ProcessDefinition {
  71 +
  72 + @ApiModelProperty(value = "编号", required = true, example = "1024")
  73 + private String id;
  74 +
  75 + @ApiModelProperty(value = "表单类型", notes = "参见 bpm_model_form_type 数据字典", example = "1")
  76 + private Integer formType;
  77 + @ApiModelProperty(value = "表单编号", example = "1024", notes = "在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时,必须非空")
  78 + private Long formId;
  79 + @ApiModelProperty(value = "表单的配置", required = true,
  80 + notes = "JSON 字符串。在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时,必须非空")
  81 + private String formConf;
  82 + @ApiModelProperty(value = "表单项的数组", required = true,
  83 + notes = "JSON 字符串的数组。在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时,必须非空")
  84 + private List<String> formFields;
  85 + @ApiModelProperty(value = "自定义表单的提交路径,使用 Vue 的路由地址", example = "/bpm/oa/leave/create",
  86 + notes = "在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时,必须非空")
  87 + private String formCustomCreatePath;
  88 + @ApiModelProperty(value = "自定义表单的查看路径,使用 Vue 的路由地址", example = "/bpm/oa/leave/view",
  89 + notes = "在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时,必须非空")
  90 + private String formCustomViewPath;
  91 +
  92 + @ApiModelProperty(value = "BPMN XML", required = true)
  93 + private String bpmnXml;
  94 +
  95 + }
  96 +
  97 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskApproveReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +
  9 +import javax.validation.constraints.NotEmpty;
  10 +import javax.validation.constraints.NotNull;
  11 +import java.util.Map;
  12 +
  13 +@ApiModel("管理后台 - 通过流程任务的 Request VO")
  14 +@Data
  15 +public class BpmTaskApproveReqVO {
  16 +
  17 + @ApiModelProperty(value = "任务编号", required = true, example = "1024")
  18 + @NotEmpty(message = "任务编号不能为空")
  19 + private String id;
  20 +
  21 + @ApiModelProperty(value = "审批意见", required = true, example = "不错不错!")
  22 + @NotEmpty(message = "审批意见不能为空")
  23 + private String comment;
  24 +
  25 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskDonePageItemRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +
  9 +import java.util.Date;
  10 +
  11 +@ApiModel("管理后台 - 流程任务的 Done 已完成的分页项 Response VO")
  12 +@Data
  13 +@EqualsAndHashCode(callSuper = true)
  14 +@ToString(callSuper = true)
  15 +public class BpmTaskDonePageItemRespVO extends BpmTaskTodoPageItemRespVO {
  16 +
  17 + @ApiModelProperty(value = "结束时间", required = true)
  18 + private Date endTime;
  19 + @ApiModelProperty(value = "持续时间", required = true, example = "1000")
  20 + private Long durationInMillis;
  21 +
  22 + @ApiModelProperty(value = "任务结果", required = true, notes = "参见 bpm_process_instance_result", example = "2")
  23 + private Integer result;
  24 + @ApiModelProperty(value = "审批建议", required = true, example = "不请假了!")
  25 + private String comment;
  26 +
  27 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskDonePageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import io.swagger.annotations.ApiModel;
  5 +import io.swagger.annotations.ApiModelProperty;
  6 +import lombok.Data;
  7 +import lombok.EqualsAndHashCode;
  8 +import lombok.ToString;
  9 +import org.springframework.format.annotation.DateTimeFormat;
  10 +
  11 +import java.util.Date;
  12 +
  13 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  14 +
  15 +@ApiModel("管理后台 - 流程任务的 Done 已办的分页 Request VO")
  16 +@Data
  17 +@EqualsAndHashCode(callSuper = true)
  18 +@ToString(callSuper = true)
  19 +public class BpmTaskDonePageReqVO extends PageParam {
  20 +
  21 + @ApiModelProperty(value = "流程任务名", example = "芋道")
  22 + private String name;
  23 +
  24 + @ApiModelProperty(value = "开始的创建收间")
  25 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  26 + private Date beginCreateTime;
  27 +
  28 + @ApiModelProperty(value = "结束的创建时间")
  29 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  30 + private Date endCreateTime;
  31 +
  32 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskRejectReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +
  7 +import javax.validation.constraints.NotEmpty;
  8 +
  9 +@ApiModel("管理后台 - 不通过流程任务的 Request VO")
  10 +@Data
  11 +public class BpmTaskRejectReqVO {
  12 +
  13 + @ApiModelProperty(value = "任务编号", required = true, example = "1024")
  14 + @NotEmpty(message = "任务编号不能为空")
  15 + private String id;
  16 +
  17 + @ApiModelProperty(value = "审批意见", required = true, example = "不错不错!")
  18 + @NotEmpty(message = "审批意见不能为空")
  19 + private String comment;
  20 +
  21 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +
  9 +@ApiModel("管理后台 - 流程任务的 Response VO")
  10 +@Data
  11 +@EqualsAndHashCode(callSuper = true)
  12 +@ToString(callSuper = true)
  13 +public class BpmTaskRespVO extends BpmTaskDonePageItemRespVO {
  14 +
  15 + @ApiModelProperty(value = "任务定义的标识", required = true, example = "user-001")
  16 + private String definitionKey;
  17 +
  18 + /**
  19 + * 审核的用户信息
  20 + */
  21 + private User assigneeUser;
  22 +
  23 + @ApiModel("用户信息")
  24 + @Data
  25 + public static class User {
  26 +
  27 + @ApiModelProperty(value = "用户编号", required = true, example = "1")
  28 + private Long id;
  29 + @ApiModelProperty(value = "用户昵称", required = true, example = "芋艿")
  30 + private String nickname;
  31 +
  32 + @ApiModelProperty(value = "部门编号", required = true, example = "1")
  33 + private Long deptId;
  34 + @ApiModelProperty(value = "部门名称", required = true, example = "研发部")
  35 + private String deptName;
  36 +
  37 + }
  38 +
  39 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskTodoPageItemRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +
  7 +import java.util.Date;
  8 +
  9 +@ApiModel("管理后台 - 流程任务的 Running 进行中的分页项 Response VO")
  10 +@Data
  11 +public class BpmTaskTodoPageItemRespVO {
  12 +
  13 + @ApiModelProperty(value = "任务编号", required = true, example = "1024")
  14 + private String id;
  15 +
  16 + @ApiModelProperty(value = "任务名字", required = true, example = "芋道")
  17 + private String name;
  18 +
  19 + @ApiModelProperty(value = "接收时间", required = true)
  20 + private Date claimTime;
  21 +
  22 + @ApiModelProperty(value = "创建时间", required = true)
  23 + private Date createTime;
  24 +
  25 + @ApiModelProperty(value = "激活状态", required = true, example = "1", notes = "参见 SuspensionState 枚举")
  26 + private Integer suspensionState;
  27 +
  28 + /**
  29 + * 所属流程实例
  30 + */
  31 + private ProcessInstance processInstance;
  32 +
  33 + @Data
  34 + @ApiModel("流程实例")
  35 + public static class ProcessInstance {
  36 +
  37 + @ApiModelProperty(value = "流程实例编号", required = true, example = "1024")
  38 + private String id;
  39 +
  40 + @ApiModelProperty(value = "流程实例名称", required = true, example = "芋道")
  41 + private String name;
  42 +
  43 + @ApiModelProperty(value = "发起人的用户编号", required = true, example = "1024")
  44 + private Long startUserId;
  45 +
  46 + @ApiModelProperty(value = "发起人的用户昵称", required = true, example = "芋艿")
  47 + private String startUserNickname;
  48 +
  49 + @ApiModelProperty(value = "流程定义的编号", required = true, example = "2048")
  50 + private String processDefinitionId;
  51 +
  52 + }
  53 +
  54 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskTodoPageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import io.swagger.annotations.ApiModel;
  5 +import io.swagger.annotations.ApiModelProperty;
  6 +import lombok.Data;
  7 +import lombok.EqualsAndHashCode;
  8 +import lombok.ToString;
  9 +import org.springframework.format.annotation.DateTimeFormat;
  10 +
  11 +import java.util.Date;
  12 +
  13 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  14 +
  15 +@ApiModel("管理后台 - 流程任务的 TODO 待办的分页 Request VO")
  16 +@Data
  17 +@EqualsAndHashCode(callSuper = true)
  18 +@ToString(callSuper = true)
  19 +public class BpmTaskTodoPageReqVO extends PageParam {
  20 +
  21 + @ApiModelProperty(value = "流程任务名", example = "芋道")
  22 + private String name;
  23 +
  24 + @ApiModelProperty(value = "开始的创建收间")
  25 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  26 + private Date beginCreateTime;
  27 +
  28 + @ApiModelProperty(value = "结束的创建时间")
  29 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  30 + private Date endCreateTime;
  31 +
  32 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskUpdateAssigneeReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +import net.bytebuddy.implementation.bind.annotation.Empty;
  9 +
  10 +import javax.validation.constraints.NotEmpty;
  11 +import javax.validation.constraints.NotNull;
  12 +
  13 +@ApiModel("管理后台 - 流程任务的更新负责人的 Request VO")
  14 +@Data
  15 +public class BpmTaskUpdateAssigneeReqVO {
  16 +
  17 + @ApiModelProperty(value = "任务编号", required = true, example = "1024")
  18 + @NotEmpty(message = "任务编号不能为空")
  19 + private String id;
  20 +
  21 + @ApiModelProperty(value = "新审批人的用户编号", required = true, example = "2048")
  22 + @NotNull(message = "新审批人的用户编号不能为空")
  23 + private Long assigneeUserId;
  24 +
  25 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/app/package-info.java 0 → 100644
  1 +/**
  2 + * 占位
  3 + */
  4 +package cn.iocoder.yudao.module.bpm.controller.app;
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/package-info.java 0 → 100644
  1 +/**
  2 + * 提供 RESTful API 给前端:
  3 + * 1. admin 包:提供给管理后台 yudao-ui-admin 前端项目
  4 + * 2. app 包:提供给用户 APP yudao-ui-app 前端项目,它的 Controller 和 VO 都要添加 App 前缀,用于和管理后台进行区分
  5 + */
  6 +package cn.iocoder.yudao.module.bpm.controller;
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmFormConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.convert.definition;
  2 +
  3 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormCreateReqVO;
  4 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormRespVO;
  5 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormSimpleRespVO;
  6 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormUpdateReqVO;
  7 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
  8 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  9 +import org.mapstruct.Mapper;
  10 +import org.mapstruct.factory.Mappers;
  11 +
  12 +import java.util.List;
  13 +
  14 +/**
  15 + * 动态表单 Convert
  16 + *
  17 + * @author 芋艿
  18 + */
  19 +@Mapper
  20 +public interface BpmFormConvert {
  21 +
  22 + BpmFormConvert INSTANCE = Mappers.getMapper(BpmFormConvert.class);
  23 +
  24 + BpmFormDO convert(BpmFormCreateReqVO bean);
  25 +
  26 + BpmFormDO convert(BpmFormUpdateReqVO bean);
  27 +
  28 + BpmFormRespVO convert(BpmFormDO bean);
  29 +
  30 + List<BpmFormSimpleRespVO> convertList2(List<BpmFormDO> list);
  31 +
  32 + PageResult<BpmFormRespVO> convertPage(PageResult<BpmFormDO> page);
  33 +
  34 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.convert.definition;
  2 +
  3 +import cn.hutool.core.util.StrUtil;
  4 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  5 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
  6 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*;
  7 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
  8 +import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
  9 +import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
  10 +import org.flowable.common.engine.impl.db.SuspensionState;
  11 +import org.flowable.engine.repository.Deployment;
  12 +import org.flowable.engine.repository.Model;
  13 +import org.flowable.engine.repository.ProcessDefinition;
  14 +import org.mapstruct.Mapper;
  15 +import org.mapstruct.MappingTarget;
  16 +import org.mapstruct.factory.Mappers;
  17 +
  18 +import java.util.List;
  19 +import java.util.Map;
  20 +import java.util.Objects;
  21 +
  22 +/**
  23 + * 流程模型 Convert
  24 + *
  25 + * @author yunlongn
  26 + */
  27 +@Mapper
  28 +public interface BpmModelConvert {
  29 +
  30 + BpmModelConvert INSTANCE = Mappers.getMapper(BpmModelConvert.class);
  31 +
  32 + default List<BpmModelPageItemRespVO> convertList(List<Model> list, Map<Long, BpmFormDO> formMap,
  33 + Map<String, Deployment> deploymentMap,
  34 + Map<String, ProcessDefinition> processDefinitionMap) {
  35 + return CollectionUtils.convertList(list, model -> {
  36 + BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class);
  37 + BpmFormDO form = metaInfo != null ? formMap.get(metaInfo.getFormId()) : null;
  38 + Deployment deployment = model.getDeploymentId() != null ? deploymentMap.get(model.getDeploymentId()) : null;
  39 + ProcessDefinition processDefinition = model.getDeploymentId() != null ? processDefinitionMap.get(model.getDeploymentId()) : null;
  40 + return convert(model, form, deployment, processDefinition);
  41 + });
  42 + }
  43 +
  44 + default BpmModelPageItemRespVO convert(Model model, BpmFormDO form, Deployment deployment, ProcessDefinition processDefinition) {
  45 + BpmModelPageItemRespVO modelRespVO = new BpmModelPageItemRespVO();
  46 + modelRespVO.setId(model.getId());
  47 + modelRespVO.setCreateTime(model.getCreateTime());
  48 + // 通用 copy
  49 + copyTo(model, modelRespVO);
  50 + // Form
  51 + if (form != null) {
  52 + modelRespVO.setFormId(form.getId());
  53 + modelRespVO.setFormName(form.getName());
  54 + }
  55 + // ProcessDefinition
  56 + modelRespVO.setProcessDefinition(this.convert(processDefinition));
  57 + if (modelRespVO.getProcessDefinition() != null) {
  58 + modelRespVO.getProcessDefinition().setSuspensionState(processDefinition.isSuspended() ?
  59 + SuspensionState.SUSPENDED.getStateCode() : SuspensionState.ACTIVE.getStateCode());
  60 + modelRespVO.getProcessDefinition().setDeploymentTime(deployment.getDeploymentTime());
  61 + }
  62 + return modelRespVO;
  63 + }
  64 +
  65 + default BpmModelRespVO convert(Model model) {
  66 + BpmModelRespVO modelRespVO = new BpmModelRespVO();
  67 + modelRespVO.setId(model.getId());
  68 + modelRespVO.setCreateTime(model.getCreateTime());
  69 + // 通用 copy
  70 + copyTo(model, modelRespVO);
  71 + return modelRespVO;
  72 + }
  73 +
  74 + default void copyTo(Model model, BpmModelBaseVO to) {
  75 + to.setName(model.getName());
  76 + to.setKey(model.getKey());
  77 + to.setCategory(model.getCategory());
  78 + // metaInfo
  79 + BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class);
  80 + copyTo(metaInfo, to);
  81 + }
  82 +
  83 + BpmModelCreateReqVO convert(BpmModeImportReqVO bean);
  84 +
  85 + default BpmProcessDefinitionCreateReqDTO convert2(Model model, BpmFormDO form) {
  86 + BpmProcessDefinitionCreateReqDTO createReqDTO = new BpmProcessDefinitionCreateReqDTO();
  87 + createReqDTO.setModelId(model.getId());
  88 + createReqDTO.setName(model.getName());
  89 + createReqDTO.setKey(model.getKey());
  90 + createReqDTO.setCategory(model.getCategory());
  91 + BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class);
  92 + // metaInfo
  93 + copyTo(metaInfo, createReqDTO);
  94 + // form
  95 + if (form != null) {
  96 + createReqDTO.setFormConf(form.getConf());
  97 + createReqDTO.setFormFields(form.getFields());
  98 + }
  99 + return createReqDTO;
  100 + }
  101 +
  102 + void copyTo(BpmModelMetaInfoRespDTO from, @MappingTarget BpmProcessDefinitionCreateReqDTO to);
  103 +
  104 + void copyTo(BpmModelMetaInfoRespDTO from, @MappingTarget BpmModelBaseVO to);
  105 +
  106 + BpmModelPageItemRespVO.ProcessDefinition convert(ProcessDefinition bean);
  107 +
  108 + default void copy(Model model, BpmModelCreateReqVO bean) {
  109 + model.setName(bean.getName());
  110 + model.setKey(bean.getKey());
  111 + model.setMetaInfo(buildMetaInfoStr(null, bean.getDescription(), null, null,
  112 + null, null));
  113 + }
  114 +
  115 + default void copy(Model model, BpmModelUpdateReqVO bean) {
  116 + model.setName(bean.getName());
  117 + model.setCategory(bean.getCategory());
  118 + model.setMetaInfo(buildMetaInfoStr(JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class),
  119 + bean.getDescription(), bean.getFormType(), bean.getFormId(),
  120 + bean.getFormCustomCreatePath(), bean.getFormCustomViewPath()));
  121 + }
  122 +
  123 + default String buildMetaInfoStr(BpmModelMetaInfoRespDTO metaInfo, String description, Integer formType,
  124 + Long formId, String formCustomCreatePath, String formCustomViewPath) {
  125 + if (metaInfo == null) {
  126 + metaInfo = new BpmModelMetaInfoRespDTO();
  127 + }
  128 + // 只有非空,才进行设置,避免更新时的覆盖
  129 + if (StrUtil.isNotEmpty(description)) {
  130 + metaInfo.setDescription(description);
  131 + }
  132 + if (Objects.nonNull(formType)) {
  133 + metaInfo.setFormType(formType);
  134 + metaInfo.setFormId(formId);
  135 + metaInfo.setFormCustomCreatePath(formCustomCreatePath);
  136 + metaInfo.setFormCustomViewPath(formCustomViewPath);
  137 + }
  138 + return JsonUtils.toJsonString(metaInfo);
  139 + }
  140 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.convert.definition;
  2 +
  3 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  4 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
  5 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
  6 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
  7 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
  8 +import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
  9 +import org.flowable.common.engine.impl.db.SuspensionState;
  10 +import org.flowable.engine.repository.Deployment;
  11 +import org.flowable.engine.repository.ProcessDefinition;
  12 +import org.mapstruct.Mapper;
  13 +import org.mapstruct.Mapping;
  14 +import org.mapstruct.MappingTarget;
  15 +import org.mapstruct.Named;
  16 +import org.mapstruct.factory.Mappers;
  17 +
  18 +import java.util.List;
  19 +import java.util.Map;
  20 +
  21 +/**
  22 + * Bpm 流程定义的 Convert
  23 + *
  24 + * @author yunlong.li
  25 + */
  26 +@Mapper
  27 +public interface BpmProcessDefinitionConvert {
  28 +
  29 + BpmProcessDefinitionConvert INSTANCE = Mappers.getMapper(BpmProcessDefinitionConvert.class);
  30 +
  31 + BpmProcessDefinitionPageItemRespVO convert(ProcessDefinition bean);
  32 +
  33 + BpmProcessDefinitionExtDO convert2(BpmProcessDefinitionCreateReqDTO bean);
  34 +
  35 + default List<BpmProcessDefinitionPageItemRespVO> convertList(List<ProcessDefinition> list, Map<String, Deployment> deploymentMap,
  36 + Map<String, BpmProcessDefinitionExtDO> processDefinitionDOMap, Map<Long, BpmFormDO> formMap) {
  37 + return CollectionUtils.convertList(list, definition -> {
  38 + Deployment deployment = definition.getDeploymentId() != null ? deploymentMap.get(definition.getDeploymentId()) : null;
  39 + BpmProcessDefinitionExtDO definitionDO = processDefinitionDOMap.get(definition.getId());
  40 + BpmFormDO form = definitionDO != null ? formMap.get(definitionDO.getFormId()) : null;
  41 + return convert(definition, deployment, definitionDO, form);
  42 + });
  43 + }
  44 +
  45 + default List<BpmProcessDefinitionRespVO> convertList3(List<ProcessDefinition> list,
  46 + Map<String, BpmProcessDefinitionExtDO> processDefinitionDOMap) {
  47 + return CollectionUtils.convertList(list, processDefinition -> {
  48 + BpmProcessDefinitionRespVO respVO = convert3(processDefinition);
  49 + BpmProcessDefinitionExtDO processDefinitionExtDO = processDefinitionDOMap.get(processDefinition.getId());
  50 + // 复制通用属性
  51 + copyTo(processDefinitionExtDO, respVO);
  52 + return respVO;
  53 + });
  54 + }
  55 +
  56 + @Mapping(source = "suspended", target = "suspensionState", qualifiedByName = "convertSuspendedToSuspensionState")
  57 + BpmProcessDefinitionRespVO convert3(ProcessDefinition bean);
  58 +
  59 + @Named("convertSuspendedToSuspensionState")
  60 + default Integer convertSuspendedToSuspensionState(boolean suspended) {
  61 + return suspended ? SuspensionState.SUSPENDED.getStateCode() :
  62 + SuspensionState.ACTIVE.getStateCode();
  63 + }
  64 +
  65 + default BpmProcessDefinitionPageItemRespVO convert(ProcessDefinition bean, Deployment deployment,
  66 + BpmProcessDefinitionExtDO processDefinitionExtDO, BpmFormDO form) {
  67 + BpmProcessDefinitionPageItemRespVO respVO = convert(bean);
  68 + respVO.setSuspensionState(bean.isSuspended() ? SuspensionState.SUSPENDED.getStateCode() : SuspensionState.ACTIVE.getStateCode());
  69 + if (deployment != null) {
  70 + respVO.setDeploymentTime(deployment.getDeploymentTime());
  71 + }
  72 + if (form != null) {
  73 + respVO.setFormName(form.getName());
  74 + }
  75 + // 复制通用属性
  76 + copyTo(processDefinitionExtDO, respVO);
  77 + return respVO;
  78 + }
  79 +
  80 + @Mapping(source = "from.id", target = "to.id", ignore = true)
  81 + void copyTo(BpmProcessDefinitionExtDO from, @MappingTarget BpmProcessDefinitionRespVO to);
  82 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmTaskAssignRuleConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.convert.definition;
  2 +
  3 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  4 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleCreateReqVO;
  5 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO;
  6 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO;
  7 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
  8 +import org.flowable.bpmn.model.UserTask;
  9 +import org.mapstruct.Mapper;
  10 +import org.mapstruct.factory.Mappers;
  11 +
  12 +import java.util.List;
  13 +import java.util.Map;
  14 +
  15 +@Mapper
  16 +public interface BpmTaskAssignRuleConvert {
  17 + BpmTaskAssignRuleConvert INSTANCE = Mappers.getMapper(BpmTaskAssignRuleConvert.class);
  18 +
  19 + default List<BpmTaskAssignRuleRespVO> convertList(List<UserTask> tasks, List<BpmTaskAssignRuleDO> rules) {
  20 + Map<String, BpmTaskAssignRuleDO> ruleMap = CollectionUtils.convertMap(rules, BpmTaskAssignRuleDO::getTaskDefinitionKey);
  21 + // 以 UserTask 为主维度,原因是:流程图编辑后,一些规则实际就没用了。
  22 + return CollectionUtils.convertList(tasks, task -> {
  23 + BpmTaskAssignRuleRespVO respVO = convert(ruleMap.get(task.getId()));
  24 + if (respVO == null) {
  25 + respVO = new BpmTaskAssignRuleRespVO();
  26 + respVO.setTaskDefinitionKey(task.getId());
  27 + }
  28 + respVO.setTaskDefinitionName(task.getName());
  29 + return respVO;
  30 + });
  31 + }
  32 +
  33 + BpmTaskAssignRuleRespVO convert(BpmTaskAssignRuleDO bean);
  34 +
  35 + BpmTaskAssignRuleDO convert(BpmTaskAssignRuleCreateReqVO bean);
  36 +
  37 + BpmTaskAssignRuleDO convert(BpmTaskAssignRuleUpdateReqVO bean);
  38 +
  39 + List<BpmTaskAssignRuleDO> convertList2(List<BpmTaskAssignRuleRespVO> list);
  40 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmUserGroupConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.convert.definition;
  2 +
  3 +import java.util.*;
  4 +
  5 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupCreateReqVO;
  6 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupRespVO;
  7 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupUpdateReqVO;
  8 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
  9 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  10 +
  11 +import org.mapstruct.Mapper;
  12 +import org.mapstruct.Named;
  13 +import org.mapstruct.factory.Mappers;
  14 +
  15 +/**
  16 + * 用户组 Convert
  17 + *
  18 + * @author 芋道源码
  19 + */
  20 +@Mapper
  21 +public interface BpmUserGroupConvert {
  22 +
  23 + BpmUserGroupConvert INSTANCE = Mappers.getMapper(BpmUserGroupConvert.class);
  24 +
  25 + BpmUserGroupDO convert(BpmUserGroupCreateReqVO bean);
  26 +
  27 + BpmUserGroupDO convert(BpmUserGroupUpdateReqVO bean);
  28 +
  29 + BpmUserGroupRespVO convert(BpmUserGroupDO bean);
  30 +
  31 + List<BpmUserGroupRespVO> convertList(List<BpmUserGroupDO> list);
  32 +
  33 + PageResult<BpmUserGroupRespVO> convertPage(PageResult<BpmUserGroupDO> page);
  34 +
  35 + @Named("convertList2")
  36 + List<BpmUserGroupRespVO> convertList2(List<BpmUserGroupDO> list);
  37 +
  38 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/message/BpmMessageConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.convert.message;
  2 +
  3 +import cn.iocoder.yudao.module.system.api.sms.dto.send.SmsSendSingleToUserReqDTO;
  4 +import org.mapstruct.Mapper;
  5 +import org.mapstruct.factory.Mappers;
  6 +
  7 +import java.util.Map;
  8 +
  9 +@Mapper
  10 +public interface BpmMessageConvert {
  11 +
  12 + BpmMessageConvert INSTANCE = Mappers.getMapper(BpmMessageConvert.class);
  13 +
  14 + SmsSendSingleToUserReqDTO convert(Long userId, String templateCode, Map<String, Object> templateParams);
  15 +
  16 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/oa/BpmOALeaveConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.convert.oa;
  2 +
  3 +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOALeaveCreateReqVO;
  4 +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOALeaveRespVO;
  5 +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALeaveDO;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  7 +import org.mapstruct.Mapper;
  8 +import org.mapstruct.factory.Mappers;
  9 +
  10 +import java.util.List;
  11 +
  12 +/**
  13 + * 请假申请 Convert
  14 + *
  15 + * @author 芋艿
  16 + */
  17 +@Mapper
  18 +public interface BpmOALeaveConvert {
  19 +
  20 + BpmOALeaveConvert INSTANCE = Mappers.getMapper(BpmOALeaveConvert.class);
  21 +
  22 + BpmOALeaveDO convert(BpmOALeaveCreateReqVO bean);
  23 +
  24 + BpmOALeaveRespVO convert(BpmOALeaveDO bean);
  25 +
  26 + List<BpmOALeaveRespVO> convertList(List<BpmOALeaveDO> list);
  27 +
  28 + PageResult<BpmOALeaveRespVO> convertPage(PageResult<BpmOALeaveDO> page);
  29 +
  30 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/package-info.java 0 → 100644
  1 +/**
  2 + * 提供 POJO 类的实体转换
  3 + *
  4 + * 目前使用 MapStruct 框架
  5 + */
  6 +package cn.iocoder.yudao.module.bpm.convert;
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmActivityConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.convert.task;
  2 +
  3 +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity.BpmActivityRespVO;
  4 +import org.flowable.engine.history.HistoricActivityInstance;
  5 +import org.mapstruct.Mapper;
  6 +import org.mapstruct.Mapping;
  7 +import org.mapstruct.Mappings;
  8 +import org.mapstruct.factory.Mappers;
  9 +
  10 +import java.util.List;
  11 +
  12 +/**
  13 + * BPM 活动 Convert
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +@Mapper
  18 +public interface BpmActivityConvert {
  19 +
  20 + BpmActivityConvert INSTANCE = Mappers.getMapper(BpmActivityConvert.class);
  21 +
  22 + List<BpmActivityRespVO> convertList(List<HistoricActivityInstance> list);
  23 +
  24 + @Mappings({
  25 + @Mapping(source = "activityId", target = "key"),
  26 + @Mapping(source = "activityType", target = "type")
  27 + })
  28 + BpmActivityRespVO convert(HistoricActivityInstance bean);
  29 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmProcessInstanceConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.convert.task;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
  5 +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstancePageItemRespVO;
  6 +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceRespVO;
  7 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
  8 +import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
  9 +import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEvent;
  10 +import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceApproveReqDTO;
  11 +import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceRejectReqDTO;
  12 +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
  13 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  14 +import org.flowable.engine.history.HistoricProcessInstance;
  15 +import org.flowable.engine.repository.ProcessDefinition;
  16 +import org.flowable.engine.runtime.ProcessInstance;
  17 +import org.flowable.task.api.Task;
  18 +import org.mapstruct.Mapper;
  19 +import org.mapstruct.Mapping;
  20 +import org.mapstruct.MappingTarget;
  21 +import org.mapstruct.Mappings;
  22 +import org.mapstruct.factory.Mappers;
  23 +
  24 +import java.util.List;
  25 +import java.util.Map;
  26 +import java.util.Optional;
  27 +
  28 +/**
  29 + * 流程实例 Convert
  30 + *
  31 + * @author 芋道源码
  32 + */
  33 +@Mapper
  34 +public interface BpmProcessInstanceConvert {
  35 +
  36 + BpmProcessInstanceConvert INSTANCE = Mappers.getMapper(BpmProcessInstanceConvert.class);
  37 +
  38 + default PageResult<BpmProcessInstancePageItemRespVO> convertPage(PageResult<BpmProcessInstanceExtDO> page,
  39 + Map<String, List<Task>> taskMap) {
  40 + List<BpmProcessInstancePageItemRespVO> list = convertList(page.getList());
  41 + list.forEach(respVO -> respVO.setTasks(convertList2(taskMap.get(respVO.getId()))));
  42 + return new PageResult<>(list, page.getTotal());
  43 + }
  44 +
  45 + List<BpmProcessInstancePageItemRespVO> convertList(List<BpmProcessInstanceExtDO> list);
  46 +
  47 + @Mapping(source = "processInstanceId", target = "id")
  48 + BpmProcessInstancePageItemRespVO convert(BpmProcessInstanceExtDO bean);
  49 +
  50 + List<BpmProcessInstancePageItemRespVO.Task> convertList2(List<Task> tasks);
  51 +
  52 + default BpmProcessInstanceRespVO convert2(HistoricProcessInstance processInstance, BpmProcessInstanceExtDO processInstanceExt,
  53 + ProcessDefinition processDefinition, BpmProcessDefinitionExtDO processDefinitionExt,
  54 + String bpmnXml, AdminUserRespDTO startUser, DeptRespDTO dept) {
  55 + BpmProcessInstanceRespVO respVO = convert2(processInstance);
  56 + copyTo(processInstanceExt, respVO);
  57 + // definition
  58 + respVO.setProcessDefinition(convert2(processDefinition));
  59 + copyTo(processDefinitionExt, respVO.getProcessDefinition());
  60 + respVO.getProcessDefinition().setBpmnXml(bpmnXml);
  61 + // user
  62 + if (startUser != null) {
  63 + respVO.setStartUser(convert2(startUser));
  64 + if (dept != null) {
  65 + respVO.getStartUser().setDeptName(dept.getName());
  66 + }
  67 + }
  68 + return respVO;
  69 + }
  70 +
  71 + BpmProcessInstanceRespVO convert2(HistoricProcessInstance bean);
  72 +
  73 + @Mapping(source = "from.id", target = "to.id", ignore = true)
  74 + void copyTo(BpmProcessInstanceExtDO from, @MappingTarget BpmProcessInstanceRespVO to);
  75 +
  76 + BpmProcessInstanceRespVO.ProcessDefinition convert2(ProcessDefinition bean);
  77 +
  78 + @Mapping(source = "from.id", target = "to.id", ignore = true)
  79 + void copyTo(BpmProcessDefinitionExtDO from, @MappingTarget BpmProcessInstanceRespVO.ProcessDefinition to);
  80 +
  81 + BpmProcessInstanceRespVO.User convert2(AdminUserRespDTO bean);
  82 +
  83 + default BpmProcessInstanceResultEvent convert(Object source, HistoricProcessInstance instance, Integer result) {
  84 + BpmProcessInstanceResultEvent event = new BpmProcessInstanceResultEvent(source);
  85 + event.setId(instance.getId());
  86 + event.setProcessDefinitionKey(instance.getProcessDefinitionKey());
  87 + event.setBusinessKey(instance.getBusinessKey());
  88 + event.setResult(result);
  89 + return event;
  90 + }
  91 +
  92 + default BpmProcessInstanceResultEvent convert(Object source, ProcessInstance instance, Integer result) {
  93 + BpmProcessInstanceResultEvent event = new BpmProcessInstanceResultEvent(source);
  94 + event.setId(instance.getId());
  95 + event.setProcessDefinitionKey(instance.getProcessDefinitionKey());
  96 + event.setBusinessKey(instance.getBusinessKey());
  97 + event.setResult(result);
  98 + return event;
  99 + }
  100 +
  101 + default BpmMessageSendWhenProcessInstanceApproveReqDTO convert2ApprovedReq(ProcessInstance instance){
  102 + return new BpmMessageSendWhenProcessInstanceApproveReqDTO()
  103 + .setStartUserId(NumberUtils.parseLong(instance.getStartUserId()))
  104 + .setProcessInstanceId(instance.getId())
  105 + .setProcessInstanceName(instance.getName());
  106 + }
  107 +
  108 + default BpmMessageSendWhenProcessInstanceRejectReqDTO convert2RejectReq(ProcessInstance instance, String comment) {
  109 + return new BpmMessageSendWhenProcessInstanceRejectReqDTO()
  110 + .setProcessInstanceName(instance.getName())
  111 + .setProcessInstanceId(instance.getId())
  112 + .setComment(comment)
  113 + .setStartUserId(NumberUtils.parseLong(instance.getStartUserId()));
  114 + }
  115 +
  116 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.convert.task;
  2 +
  3 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  4 +import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
  5 +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskDonePageItemRespVO;
  6 +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
  7 +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskTodoPageItemRespVO;
  8 +import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
  9 +import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO;
  10 +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
  11 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  12 +
  13 +import org.flowable.common.engine.impl.db.SuspensionState;
  14 +import org.flowable.engine.history.HistoricProcessInstance;
  15 +import org.flowable.engine.runtime.ProcessInstance;
  16 +import org.flowable.task.api.Task;
  17 +import org.flowable.task.api.history.HistoricTaskInstance;
  18 +import org.mapstruct.*;
  19 +import org.mapstruct.factory.Mappers;
  20 +
  21 +import java.util.List;
  22 +import java.util.Map;
  23 +
  24 +/**
  25 + * Bpm 任务 Convert
  26 + *
  27 + * @author 芋道源码
  28 + */
  29 +@Mapper
  30 +public interface BpmTaskConvert {
  31 +
  32 + BpmTaskConvert INSTANCE = Mappers.getMapper(BpmTaskConvert.class);
  33 +
  34 + default List<BpmTaskTodoPageItemRespVO> convertList1(List<Task> tasks, Map<String, ProcessInstance> processInstanceMap,
  35 + Map<Long, AdminUserRespDTO> userMap) {
  36 + return CollectionUtils.convertList(tasks, task -> {
  37 + BpmTaskTodoPageItemRespVO respVO = convert1(task);
  38 + ProcessInstance processInstance = processInstanceMap.get(task.getProcessInstanceId());
  39 + if (processInstance != null) {
  40 + AdminUserRespDTO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId()));
  41 + respVO.setProcessInstance(convert(processInstance, startUser));
  42 + }
  43 + return respVO;
  44 + });
  45 + }
  46 +
  47 + @Mapping(source = "suspended", target = "suspensionState", qualifiedByName = "convertSuspendedToSuspensionState")
  48 + BpmTaskTodoPageItemRespVO convert1(Task bean);
  49 +
  50 + @Named("convertSuspendedToSuspensionState")
  51 + default Integer convertSuspendedToSuspensionState(boolean suspended) {
  52 + return suspended ? SuspensionState.SUSPENDED.getStateCode() :
  53 + SuspensionState.ACTIVE.getStateCode();
  54 + }
  55 +
  56 + default List<BpmTaskDonePageItemRespVO> convertList2(List<HistoricTaskInstance> tasks, Map<String, BpmTaskExtDO> bpmTaskExtDOMap,
  57 + Map<String, HistoricProcessInstance> historicProcessInstanceMap,
  58 + Map<Long, AdminUserRespDTO> userMap) {
  59 + return CollectionUtils.convertList(tasks, task -> {
  60 + BpmTaskDonePageItemRespVO respVO = convert2(task);
  61 + BpmTaskExtDO taskExtDO = bpmTaskExtDOMap.get(task.getId());
  62 + copyTo(taskExtDO, respVO);
  63 + HistoricProcessInstance processInstance = historicProcessInstanceMap.get(task.getProcessInstanceId());
  64 + if (processInstance != null) {
  65 + AdminUserRespDTO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId()));
  66 + respVO.setProcessInstance(convert(processInstance, startUser));
  67 + }
  68 + return respVO;
  69 + });
  70 + }
  71 +
  72 + BpmTaskDonePageItemRespVO convert2(HistoricTaskInstance bean);
  73 +
  74 + @Mappings({
  75 + @Mapping(source = "processInstance.id", target = "id"),
  76 + @Mapping(source = "processInstance.name", target = "name"),
  77 + @Mapping(source = "processInstance.startUserId", target = "startUserId"),
  78 + @Mapping(source = "processInstance.processDefinitionId", target = "processDefinitionId"),
  79 + @Mapping(source = "startUser.nickname", target = "startUserNickname")
  80 + })
  81 + BpmTaskTodoPageItemRespVO.ProcessInstance convert(ProcessInstance processInstance, AdminUserRespDTO startUser);
  82 +
  83 + default List<BpmTaskRespVO> convertList3(List<HistoricTaskInstance> tasks, Map<String, BpmTaskExtDO> bpmTaskExtDOMap,
  84 + HistoricProcessInstance processInstance, Map<Long, AdminUserRespDTO> userMap,
  85 + Map<Long, DeptRespDTO> deptMap) {
  86 + return CollectionUtils.convertList(tasks, task -> {
  87 + BpmTaskRespVO respVO = convert3(task);
  88 + BpmTaskExtDO taskExtDO = bpmTaskExtDOMap.get(task.getId());
  89 + copyTo(taskExtDO, respVO);
  90 + if (processInstance != null) {
  91 + AdminUserRespDTO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId()));
  92 + respVO.setProcessInstance(convert(processInstance, startUser));
  93 + }
  94 + AdminUserRespDTO assignUser = userMap.get(NumberUtils.parseLong(task.getAssignee()));
  95 + if (assignUser != null) {
  96 + respVO.setAssigneeUser(convert3(assignUser));
  97 + DeptRespDTO dept = deptMap.get(assignUser.getDeptId());
  98 + if (dept != null) {
  99 + respVO.getAssigneeUser().setDeptName(dept.getName());
  100 + }
  101 + }
  102 + return respVO;
  103 + });
  104 + }
  105 +
  106 + @Mapping(source = "taskDefinitionKey", target = "definitionKey")
  107 + BpmTaskRespVO convert3(HistoricTaskInstance bean);
  108 +
  109 + BpmTaskRespVO.User convert3(AdminUserRespDTO bean);
  110 +
  111 + @Mapping(target = "id", ignore = true)
  112 + void copyTo(BpmTaskExtDO from, @MappingTarget BpmTaskDonePageItemRespVO to);
  113 +
  114 + @Mappings({
  115 + @Mapping(source = "processInstance.id", target = "id"),
  116 + @Mapping(source = "processInstance.name", target = "name"),
  117 + @Mapping(source = "processInstance.startUserId", target = "startUserId"),
  118 + @Mapping(source = "processInstance.processDefinitionId", target = "processDefinitionId"),
  119 + @Mapping(source = "startUser.nickname", target = "startUserNickname")
  120 + })
  121 + BpmTaskTodoPageItemRespVO.ProcessInstance convert(HistoricProcessInstance processInstance, AdminUserRespDTO startUser);
  122 +
  123 + default BpmTaskExtDO convert2TaskExt(Task task){
  124 + BpmTaskExtDO taskExtDO = new BpmTaskExtDO()
  125 + .setTaskId(task.getId())
  126 + .setAssigneeUserId(NumberUtils.parseLong(task.getAssignee()))
  127 + .setName(task.getName())
  128 + .setProcessDefinitionId(task.getProcessDefinitionId())
  129 + .setProcessInstanceId(task.getProcessInstanceId());
  130 + taskExtDO.setCreateTime(task.getCreateTime());
  131 + return taskExtDO;
  132 + }
  133 +
  134 + default BpmMessageSendWhenTaskCreatedReqDTO convert(ProcessInstance processInstance, AdminUserRespDTO startUser, Task task) {
  135 + BpmMessageSendWhenTaskCreatedReqDTO reqDTO = new BpmMessageSendWhenTaskCreatedReqDTO();
  136 + reqDTO.setProcessInstanceId(processInstance.getProcessInstanceId())
  137 + .setProcessInstanceName(processInstance.getName())
  138 + .setStartUserId(startUser.getId())
  139 + .setStartUserNickname(startUser.getNickname())
  140 + .setTaskId(task.getId())
  141 + .setTaskName(task.getName())
  142 + .setAssigneeUserId(NumberUtils.parseLong(task.getAssignee()));
  143 + return reqDTO;
  144 + }
  145 +}
  146 +
  147 +
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/package-info.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.convert.task;
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md 0 → 100644
  1 +<http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao>
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmFormDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.dal.dataobject.definition;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import com.baomidou.mybatisplus.annotation.TableField;
  5 +import com.baomidou.mybatisplus.annotation.TableId;
  6 +import com.baomidou.mybatisplus.annotation.TableName;
  7 +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
  8 +import lombok.*;
  9 +
  10 +import java.util.List;
  11 +
  12 +/**
  13 + * 工作流的表单定义
  14 + * 用于工作流的申请表单,需要动态配置的场景
  15 + *
  16 + * @author 芋道源码
  17 + */
  18 +@TableName(value = "bpm_form", autoResultMap = true)
  19 +@Data
  20 +@EqualsAndHashCode(callSuper = true)
  21 +@ToString(callSuper = true)
  22 +@Builder
  23 +@NoArgsConstructor
  24 +@AllArgsConstructor
  25 +public class BpmFormDO extends BaseDO {
  26 +
  27 + /**
  28 + * 编号
  29 + */
  30 + @TableId
  31 + private Long id;
  32 + /**
  33 + * 表单名
  34 + */
  35 + private String name;
  36 + /**
  37 + * 状态
  38 + */
  39 + private Integer status;
  40 + /**
  41 + * 表单的配置
  42 + */
  43 + private String conf;
  44 + /**
  45 + * 表单项的数组
  46 + *
  47 + * 目前直接将 https://github.com/JakHuang/form-generator 生成的 JSON 串,直接保存
  48 + * 定义:https://github.com/JakHuang/form-generator/issues/46
  49 + */
  50 + @TableField(typeHandler = JacksonTypeHandler.class)
  51 + private List<String> fields;
  52 + /**
  53 + * 备注
  54 + */
  55 + private String remark;
  56 +
  57 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionExtDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.dal.dataobject.definition;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
  5 +import com.baomidou.mybatisplus.annotation.TableField;
  6 +import com.baomidou.mybatisplus.annotation.TableId;
  7 +import com.baomidou.mybatisplus.annotation.TableName;
  8 +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
  9 +import lombok.*;
  10 +
  11 +import java.util.List;
  12 +
  13 +/**
  14 + * Bpm 流程定义的拓展表
  15 + * 主要解决 Activiti {@link ProcessDefinition} 不支持拓展字段,所以新建拓展表
  16 + *
  17 + * @author 芋道源码
  18 + */
  19 +@TableName(value = "bpm_process_definition_ext", autoResultMap = true)
  20 +@Data
  21 +@EqualsAndHashCode(callSuper = true)
  22 +@ToString(callSuper = true)
  23 +@Builder
  24 +@NoArgsConstructor
  25 +@AllArgsConstructor
  26 +public class BpmProcessDefinitionExtDO extends BaseDO {
  27 +
  28 + /**
  29 + * 编号
  30 + */
  31 + @TableId
  32 + private Long id;
  33 + /**
  34 + * 流程定义的编号
  35 + *
  36 + * 关联 ProcessDefinition 的 id 属性
  37 + */
  38 + private String processDefinitionId;
  39 + /**
  40 + * 流程模型的编号
  41 + *
  42 + * 关联 Model 的 id 属性
  43 + */
  44 + private String modelId;
  45 + /**
  46 + * 描述
  47 + */
  48 + private String description;
  49 +
  50 + /**
  51 + * 表单类型
  52 + *
  53 + * 关联 {@link BpmModelFormTypeEnum}
  54 + */
  55 + private Integer formType;
  56 + /**
  57 + * 动态表单编号
  58 + * 在表单类型为 {@link BpmModelFormTypeEnum#NORMAL} 时
  59 + *
  60 + * 关联 {@link BpmFormDO#getId()}
  61 + */
  62 + private Long formId;
  63 + /**
  64 + * 表单的配置
  65 + * 在表单类型为 {@link BpmModelFormTypeEnum#NORMAL} 时
  66 + *
  67 + * 冗余 {@link BpmFormDO#getConf()}
  68 + */
  69 + private String formConf;
  70 + /**
  71 + * 表单项的数组
  72 + * 在表单类型为 {@link BpmModelFormTypeEnum#NORMAL} 时
  73 + *
  74 + * 冗余 {@link BpmFormDO#getFields()} ()}
  75 + */
  76 + @TableField(typeHandler = JacksonTypeHandler.class)
  77 + private List<String> formFields;
  78 + /**
  79 + * 自定义表单的提交路径,使用 Vue 的路由地址
  80 + * 在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时
  81 + */
  82 + private String formCustomCreatePath;
  83 + /**
  84 + * 自定义表单的查看路径,使用 Vue 的路由地址
  85 + * 在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时
  86 + */
  87 + private String formCustomViewPath;
  88 +
  89 +
  90 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmTaskAssignRuleDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.dal.dataobject.definition;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler;
  5 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
  6 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
  7 +import com.baomidou.mybatisplus.annotation.TableField;
  8 +import com.baomidou.mybatisplus.annotation.TableId;
  9 +import com.baomidou.mybatisplus.annotation.TableName;
  10 +import lombok.*;
  11 +
  12 +import java.util.Set;
  13 +
  14 +/**
  15 + * Bpm 任务分配的规则表,用于自定义配置每个任务的负责人、候选人的分配规则。
  16 + * 也就是说,废弃 BPMN 原本的 UserTask 设置的 assignee、candidateUsers 等配置,而是通过使用该规则进行计算对应的负责人。
  17 + *
  18 + * 1. 默认情况下,{@link #processDefinitionId} 为 {@link #PROCESS_DEFINITION_ID_NULL} 值,表示贵改则与流程模型关联
  19 + * 2. 在流程模型部署后,会将他的所有规则记录,复制出一份新部署出来的流程定义,通过设置 {@link #processDefinitionId} 为新的流程定义的编号进行关联
  20 + *
  21 + * @author 芋道源码
  22 + */
  23 +@TableName(value = "bpm_task_assign_rule", autoResultMap = true)
  24 +@Data
  25 +@EqualsAndHashCode(callSuper = true)
  26 +@ToString(callSuper = true)
  27 +@Builder
  28 +@NoArgsConstructor
  29 +@AllArgsConstructor
  30 +public class BpmTaskAssignRuleDO extends BaseDO {
  31 +
  32 + /**
  33 + * {@link #processDefinitionId} 空串,用于标识属于流程模型,而不属于流程定义
  34 + */
  35 + public static final String PROCESS_DEFINITION_ID_NULL = "";
  36 +
  37 + /**
  38 + * 编号
  39 + */
  40 + @TableId
  41 + private Long id;
  42 +
  43 + /**
  44 + * 流程模型编号
  45 + *
  46 + * 关联 Model 的 id 属性
  47 + */
  48 + private String modelId;
  49 + /**
  50 + * 流程定义编号
  51 + *
  52 + * 关联 ProcessDefinition 的 id 属性
  53 + */
  54 + private String processDefinitionId;
  55 + /**
  56 + * 流程任务的定义 Key
  57 + *
  58 + * 关联 Task 的 taskDefinitionKey 属性
  59 + */
  60 + private String taskDefinitionKey;
  61 +
  62 + /**
  63 + * 规则类型
  64 + *
  65 + * 枚举 {@link BpmTaskAssignRuleTypeEnum}
  66 + */
  67 + @TableField("`type`")
  68 + private Integer type;
  69 + /**
  70 + * 规则值数组,一般关联指定表的编号
  71 + * 根据 type 不同,对应的值是不同的:
  72 + *
  73 + * 1. {@link BpmTaskAssignRuleTypeEnum#ROLE} 时:角色编号
  74 + * 2. {@link BpmTaskAssignRuleTypeEnum#DEPT_MEMBER} 时:部门编号
  75 + * 3. {@link BpmTaskAssignRuleTypeEnum#DEPT_LEADER} 时:部门编号
  76 + * 4. {@link BpmTaskAssignRuleTypeEnum#USER} 时:用户编号
  77 + * 5. {@link BpmTaskAssignRuleTypeEnum#USER_GROUP} 时:用户组编号
  78 + * 6. {@link BpmTaskAssignRuleTypeEnum#SCRIPT} 时:脚本编号,目前通过 {@link BpmTaskRuleScriptEnum#getId()} 标识
  79 + */
  80 + @TableField(typeHandler = JsonLongSetTypeHandler.class)
  81 + private Set<Long> options;
  82 +
  83 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmTaskMessageRuleDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.dal.dataobject.definition;
  2 +
  3 +// TODO 芋艿:先埋个坑。任务消息的配置规则。说白了,就是不同的
  4 +public class BpmTaskMessageRuleDO {
  5 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmUserGroupDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.dal.dataobject.definition;
  2 +
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  4 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  5 +import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler;
  6 +import com.baomidou.mybatisplus.annotation.TableField;
  7 +import com.baomidou.mybatisplus.annotation.TableId;
  8 +import com.baomidou.mybatisplus.annotation.TableName;
  9 +import lombok.*;
  10 +
  11 +import java.util.Set;
  12 +
  13 +/**
  14 + * Bpm 用户组
  15 + *
  16 + * @author 芋道源码
  17 + */
  18 +@TableName(value = "bpm_user_group", autoResultMap = true)
  19 +@Data
  20 +@EqualsAndHashCode(callSuper = true)
  21 +@ToString(callSuper = true)
  22 +@Builder
  23 +@NoArgsConstructor
  24 +@AllArgsConstructor
  25 +public class BpmUserGroupDO extends BaseDO {
  26 +
  27 + /**
  28 + * 编号,自增
  29 + */
  30 + @TableId
  31 + private Long id;
  32 + /**
  33 + * 组名
  34 + */
  35 + private String name;
  36 + /**
  37 + * 描述
  38 + */
  39 + private String description;
  40 + /**
  41 + * 状态
  42 + *
  43 + * 枚举 {@link CommonStatusEnum}
  44 + */
  45 + private Integer status;
  46 + /**
  47 + * 成员用户编号数组
  48 + */
  49 + @TableField(typeHandler = JsonLongSetTypeHandler.class)
  50 + private Set<Long> memberUserIds;
  51 +
  52 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOALeaveDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.dal.dataobject.oa;
  2 +
  3 +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
  4 +import lombok.*;
  5 +import java.util.*;
  6 +import com.baomidou.mybatisplus.annotation.*;
  7 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  8 +
  9 +/**
  10 + * OA 请假申请 DO
  11 + *
  12 + * {@link #day} 请假天数,目前先简单做。一般是分成请假上午和下午,可以是 1 整天,可以是 0.5 半天
  13 + *
  14 + * @author jason
  15 + * @author 芋道源码
  16 + */
  17 +@TableName("bpm_oa_leave")
  18 +@Data
  19 +@EqualsAndHashCode(callSuper = true)
  20 +@ToString(callSuper = true)
  21 +@Builder
  22 +@NoArgsConstructor
  23 +@AllArgsConstructor
  24 +public class BpmOALeaveDO extends BaseDO {
  25 +
  26 + /**
  27 + * 请假表单主键
  28 + */
  29 + @TableId
  30 + private Long id;
  31 + /**
  32 + * 申请人的用户编号
  33 + *
  34 + * 关联 AdminUserDO 的 id 属性
  35 + */
  36 + private Long userId;
  37 + /**
  38 + * 请假类型
  39 + */
  40 + @TableField("`type`")
  41 + private String type;
  42 + /**
  43 + * 原因
  44 + */
  45 + private String reason;
  46 + /**
  47 + * 开始时间
  48 + */
  49 + private Date startTime;
  50 + /**
  51 + * 结束时间
  52 + */
  53 + private Date endTime;
  54 + /**
  55 + * 请假天数
  56 + */
  57 + private Long day;
  58 + /**
  59 + * 请假的结果
  60 + *
  61 + * 枚举 {@link BpmProcessInstanceResultEnum}
  62 + * 考虑到简单,所以直接复用了 BpmProcessInstanceResultEnum 枚举,也可以自己定义一个枚举哈
  63 + */
  64 + private Integer result;
  65 +
  66 + /**
  67 + * 对应的流程编号
  68 + *
  69 + * 关联 ProcessInstance 的 id 属性
  70 + */
  71 + private String processInstanceId;
  72 +
  73 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmProcessInstanceExtDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.dal.dataobject.task;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
  5 +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
  6 +import com.baomidou.mybatisplus.annotation.TableField;
  7 +import com.baomidou.mybatisplus.annotation.TableId;
  8 +import com.baomidou.mybatisplus.annotation.TableName;
  9 +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
  10 +import lombok.Data;
  11 +import lombok.EqualsAndHashCode;
  12 +import lombok.ToString;
  13 +
  14 +import java.util.Date;
  15 +import java.util.Map;
  16 +
  17 +/**
  18 + * Bpm 流程实例的拓展表
  19 + * 主要解决 Activiti ProcessInstance 和 HistoricProcessInstance 不支持拓展字段,所以新建拓展表
  20 + *
  21 + * @author 芋道源码
  22 + */
  23 +@TableName(value = "bpm_process_instance_ext", autoResultMap = true)
  24 +@Data
  25 +@EqualsAndHashCode(callSuper = true)
  26 +@ToString(callSuper = true)
  27 +public class BpmProcessInstanceExtDO extends BaseDO {
  28 +
  29 + /**
  30 + * 编号,自增
  31 + */
  32 + @TableId
  33 + private Long id;
  34 + /**
  35 + * 发起流程的用户编号
  36 + *
  37 + * 冗余 HistoricProcessInstance 的 startUserId 属性
  38 + */
  39 + private Long startUserId;
  40 + /**
  41 + * 流程实例的名字
  42 + *
  43 + * 冗余 ProcessInstance 的 name 属性,用于筛选
  44 + */
  45 + private String name;
  46 + /**
  47 + * 流程实例的编号
  48 + *
  49 + * 关联 ProcessInstance 的 id 属性
  50 + */
  51 + private String processInstanceId;
  52 + /**
  53 + * 流程定义的编号
  54 + *
  55 + * 关联 ProcessDefinition 的 id 属性
  56 + */
  57 + private String processDefinitionId;
  58 + /**
  59 + * 流程分类
  60 + *
  61 + * 冗余 ProcessDefinition 的 category 属性
  62 + * 数据字典 bpm_model_category
  63 + */
  64 + private String category;
  65 + /**
  66 + * 流程实例的状态
  67 + *
  68 + * 枚举 {@link BpmProcessInstanceStatusEnum}
  69 + */
  70 + private Integer status;
  71 + /**
  72 + * 流程实例的结果
  73 + *
  74 + * 枚举 {@link BpmProcessInstanceResultEnum}
  75 + */
  76 + private Integer result;
  77 + /**
  78 + * 结束时间
  79 + *
  80 + * 冗余 HistoricProcessInstance 的 endTime 属性
  81 + */
  82 + private Date endTime;
  83 +
  84 + /**
  85 + * 提交的表单值
  86 + */
  87 + @TableField(typeHandler = JacksonTypeHandler.class)
  88 + private Map<String, Object> formVariables;
  89 +
  90 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmTaskExtDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.dal.dataobject.task;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
  5 +import com.baomidou.mybatisplus.annotation.TableId;
  6 +import com.baomidou.mybatisplus.annotation.TableName;
  7 +import lombok.Data;
  8 +import lombok.EqualsAndHashCode;
  9 +import lombok.ToString;
  10 +
  11 +import java.util.Date;
  12 +
  13 +/**
  14 + * Bpm 流程任务的拓展表
  15 + * 主要解决 Activiti Task 和 HistoricTaskInstance 不支持拓展字段,所以新建拓展表
  16 + *
  17 + * @author 芋道源码
  18 + */
  19 +@TableName(value = "bpm_task_ext", autoResultMap = true)
  20 +@Data
  21 +@EqualsAndHashCode(callSuper = true)
  22 +@ToString(callSuper = true)
  23 +public class BpmTaskExtDO extends BaseDO {
  24 +
  25 + /**
  26 + * 编号,自增
  27 + */
  28 + @TableId
  29 + private Long id;
  30 + /**
  31 + * 任务的审批人
  32 + *
  33 + * 冗余 Task 的 assignee 属性
  34 + */
  35 + private Long assigneeUserId;
  36 + /**
  37 + * 任务的名字
  38 + *
  39 + * 冗余 Task 的 name 属性,为了筛选
  40 + */
  41 + private String name;
  42 + /**
  43 + * 任务的编号
  44 + *
  45 + * 关联 Task 的 id 属性
  46 + */
  47 + private String taskId;
  48 +// /**
  49 +// * 任务的标识
  50 +// *
  51 +// * 关联 {@link Task#getTaskDefinitionKey()}
  52 +// */
  53 +// private String definitionKey;
  54 + /**
  55 + * 任务的结果
  56 + *
  57 + * 枚举 {@link BpmProcessInstanceResultEnum}
  58 + */
  59 + private Integer result;
  60 + /**
  61 + * 审批建议
  62 + */
  63 + private String comment;
  64 + /**
  65 + * 任务的结束时间
  66 + *
  67 + * 冗余 HistoricTaskInstance 的 endTime 属性
  68 + */
  69 + private Date endTime;
  70 +
  71 + /**
  72 + * 流程实例的编号
  73 + *
  74 + * 关联 ProcessInstance 的 id 属性
  75 + */
  76 + private String processInstanceId;
  77 + /**
  78 + * 流程定义的编号
  79 + *
  80 + * 关联 ProcessDefinition 的 id 属性
  81 + */
  82 + private String processDefinitionId;
  83 +
  84 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmFormMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.dal.mysql.definition;
  2 +
  3 +
  4 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormPageReqVO;
  5 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  7 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  8 +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
  9 +import org.apache.ibatis.annotations.Mapper;
  10 +
  11 +/**
  12 + * 动态表单 Mapper
  13 + *
  14 + * @author 风里雾里
  15 + */
  16 +@Mapper
  17 +public interface BpmFormMapper extends BaseMapperX<BpmFormDO> {
  18 +
  19 + default PageResult<BpmFormDO> selectPage(BpmFormPageReqVO reqVO) {
  20 + return selectPage(reqVO, new QueryWrapperX<BpmFormDO>()
  21 + .likeIfPresent("name", reqVO.getName())
  22 + .orderByDesc("id"));
  23 + }
  24 +
  25 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmProcessDefinitionExtMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.dal.mysql.definition;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  4 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
  5 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  6 +import org.apache.ibatis.annotations.Mapper;
  7 +
  8 +import java.util.Collection;
  9 +import java.util.List;
  10 +
  11 +@Mapper
  12 +public interface BpmProcessDefinitionExtMapper extends BaseMapperX<BpmProcessDefinitionExtDO> {
  13 +
  14 + default List<BpmProcessDefinitionExtDO> selectListByProcessDefinitionIds(Collection<String> processDefinitionIds) {
  15 + return selectList("process_definition_id", processDefinitionIds);
  16 + }
  17 +
  18 + default BpmProcessDefinitionExtDO selectByProcessDefinitionId(String processDefinitionId) {
  19 + return selectOne("process_definition_id", processDefinitionId);
  20 + }
  21 +
  22 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmTaskAssignRuleMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.dal.mysql.definition;
  2 +
  3 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
  4 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  5 +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
  6 +import org.apache.ibatis.annotations.Mapper;
  7 +import org.springframework.lang.Nullable;
  8 +
  9 +import java.util.List;
  10 +
  11 +@Mapper
  12 +public interface BpmTaskAssignRuleMapper extends BaseMapperX<BpmTaskAssignRuleDO> {
  13 +
  14 + default List<BpmTaskAssignRuleDO> selectListByProcessDefinitionId(String processDefinitionId,
  15 + @Nullable String taskDefinitionKey) {
  16 + return selectList(new QueryWrapperX<BpmTaskAssignRuleDO>()
  17 + .eq("process_definition_id", processDefinitionId)
  18 + .eqIfPresent("task_definition_key", taskDefinitionKey));
  19 + }
  20 +
  21 + default List<BpmTaskAssignRuleDO> selectListByModelId(String modelId) {
  22 + return selectList(new QueryWrapperX<BpmTaskAssignRuleDO>()
  23 + .eq("model_id", modelId)
  24 + .eq("process_definition_id", BpmTaskAssignRuleDO.PROCESS_DEFINITION_ID_NULL));
  25 + }
  26 +
  27 + default BpmTaskAssignRuleDO selectListByModelIdAndTaskDefinitionKey(String modelId,
  28 + String taskDefinitionKey) {
  29 + return selectOne(new QueryWrapperX<BpmTaskAssignRuleDO>()
  30 + .eq("model_id", modelId)
  31 + .eq("process_definition_id", BpmTaskAssignRuleDO.PROCESS_DEFINITION_ID_NULL)
  32 + .eq("task_definition_key", taskDefinitionKey));
  33 + }
  34 +
  35 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmUserGroupMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.dal.mysql.definition;
  2 +
  3 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupPageReqVO;
  4 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  7 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  8 +import org.apache.ibatis.annotations.Mapper;
  9 +
  10 +import java.util.List;
  11 +
  12 +/**
  13 + * 用户组 Mapper
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +@Mapper
  18 +public interface BpmUserGroupMapper extends BaseMapperX<BpmUserGroupDO> {
  19 +
  20 + default PageResult<BpmUserGroupDO> selectPage(BpmUserGroupPageReqVO reqVO) {
  21 + return selectPage(reqVO, new LambdaQueryWrapperX<BpmUserGroupDO>()
  22 + .likeIfPresent(BpmUserGroupDO::getName, reqVO.getName())
  23 + .eqIfPresent(BpmUserGroupDO::getStatus, reqVO.getStatus())
  24 + .betweenIfPresent(BpmUserGroupDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
  25 + .orderByDesc(BpmUserGroupDO::getId));
  26 + }
  27 +
  28 + default List<BpmUserGroupDO> selectListByStatus(Integer status) {
  29 + return selectList(BpmUserGroupDO::getStatus, status);
  30 + }
  31 +
  32 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOALeaveMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.dal.mysql.oa;
  2 +
  3 +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOALeavePageReqVO;
  4 +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALeaveDO;
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  7 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  8 +import org.apache.ibatis.annotations.Mapper;
  9 +
  10 +/**
  11 + * 请假申请 Mapper
  12 + *
  13 + * @author jason
  14 + * @author 芋道源码
  15 + */
  16 +@Mapper
  17 +public interface BpmOALeaveMapper extends BaseMapperX<BpmOALeaveDO> {
  18 +
  19 + default PageResult<BpmOALeaveDO> selectPage(Long userId, BpmOALeavePageReqVO reqVO) {
  20 + return selectPage(reqVO, new LambdaQueryWrapperX<BpmOALeaveDO>()
  21 + .eqIfPresent(BpmOALeaveDO::getUserId, userId)
  22 + .eqIfPresent(BpmOALeaveDO::getResult, reqVO.getResult())
  23 + .eqIfPresent(BpmOALeaveDO::getType, reqVO.getType())
  24 + .likeIfPresent(BpmOALeaveDO::getReason, reqVO.getReason())
  25 + .betweenIfPresent(BpmOALeaveDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
  26 + .orderByDesc(BpmOALeaveDO::getId));
  27 + }
  28 +
  29 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmProcessInstanceExtMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.dal.mysql.task;
  2 +
  3 +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceMyPageReqVO;
  4 +import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  7 +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
  8 +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  9 +import org.apache.ibatis.annotations.Mapper;
  10 +
  11 +@Mapper
  12 +public interface BpmProcessInstanceExtMapper extends BaseMapperX<BpmProcessInstanceExtDO> {
  13 +
  14 + default PageResult<BpmProcessInstanceExtDO> selectPage(Long userId, BpmProcessInstanceMyPageReqVO reqVO) {
  15 + return selectPage(reqVO, new QueryWrapperX<BpmProcessInstanceExtDO>()
  16 + .eqIfPresent("start_user_id", userId)
  17 + .likeIfPresent("name", reqVO.getName())
  18 + .eqIfPresent("process_definition_id", reqVO.getProcessDefinitionId())
  19 + .eqIfPresent("category", reqVO.getCategory())
  20 + .eqIfPresent("status", reqVO.getStatus())
  21 + .eqIfPresent("result", reqVO.getResult())
  22 + .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
  23 + .orderByDesc("id"));
  24 + }
  25 +
  26 + default BpmProcessInstanceExtDO selectByProcessInstanceId(String processDefinitionId) {
  27 + return selectOne("process_instance_id", processDefinitionId);
  28 + }
  29 +
  30 + default void updateByProcessInstanceId(BpmProcessInstanceExtDO updateObj) {
  31 + update(updateObj, new QueryWrapper<BpmProcessInstanceExtDO>()
  32 + .eq("process_instance_id", updateObj.getProcessInstanceId()));
  33 + }
  34 +
  35 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmTaskExtMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.dal.mysql.task;
  2 +
  3 +import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
  4 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  5 +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  6 +import org.apache.ibatis.annotations.Mapper;
  7 +
  8 +import java.util.Collection;
  9 +import java.util.List;
  10 +
  11 +@Mapper
  12 +public interface BpmTaskExtMapper extends BaseMapperX<BpmTaskExtDO> {
  13 +
  14 + default void updateByTaskId(BpmTaskExtDO entity) {
  15 + update(entity, new LambdaQueryWrapper<BpmTaskExtDO>().eq(BpmTaskExtDO::getTaskId, entity.getTaskId()));
  16 + }
  17 +
  18 + default List<BpmTaskExtDO> selectListByTaskIds(Collection<String> taskIds) {
  19 + return selectList(BpmTaskExtDO::getTaskId, taskIds);
  20 + }
  21 +
  22 + default List<BpmTaskExtDO> selectListByProcessInstanceId(String processInstanceId) {
  23 + return selectList("process_instance_id", processInstanceId);
  24 + }
  25 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmModelFormTypeEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.enums.definition;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Getter;
  5 +
  6 +/**
  7 + * BPM 模型的表单类型的枚举
  8 + *
  9 + * @author 芋道源码
  10 + */
  11 +@Getter
  12 +@AllArgsConstructor
  13 +public enum BpmModelFormTypeEnum {
  14 +
  15 + NORMAL(10, "流程表单"), // 对应 BpmFormDO
  16 + CUSTOM(20, "业务表单") // 业务自己定义的表单,自己进行数据的存储
  17 + ;
  18 +
  19 + private final Integer type;
  20 + private final String desc;
  21 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskAssignRuleTypeEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.enums.definition;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Getter;
  5 +
  6 +/**
  7 + * BPM 任务分配规则的类型枚举
  8 + *
  9 + * @author 芋道源码
  10 + */
  11 +@Getter
  12 +@AllArgsConstructor
  13 +public enum BpmTaskAssignRuleTypeEnum {
  14 +
  15 + ROLE(10, "角色"),
  16 +
  17 + DEPT_MEMBER(20, "部门的成员"), // 包括负责人
  18 + DEPT_LEADER(21, "部门的负责人"),
  19 + POST(22, "岗位"),
  20 +
  21 + USER(30, "用户"),
  22 +
  23 + USER_GROUP(40, "用户组"),
  24 +
  25 + SCRIPT(50, "自定义脚本"), // 例如说,发起人所在部门的领导、发起人所在部门的领导的领导
  26 + ;
  27 +
  28 + /**
  29 + * 类型
  30 + */
  31 + private final Integer type;
  32 + /**
  33 + * 描述
  34 + */
  35 + private final String desc;
  36 +
  37 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskRuleScriptEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.enums.definition;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Getter;
  5 +
  6 +/**
  7 + * BPM 任务规则的脚本枚举
  8 + * 目前暂时通过 TODO 芋艿:硬编码,未来可以考虑 Groovy 动态脚本的方式
  9 + *
  10 + * @author 芋道源码
  11 + */
  12 +@Getter
  13 +@AllArgsConstructor
  14 +public enum BpmTaskRuleScriptEnum {
  15 +
  16 + START_USER(10L, "流程发起人"),
  17 +
  18 + LEADER_X1(20L, "流程发起人的一级领导"),
  19 + LEADER_X2(21L, "流程发起人的二级领导");
  20 +
  21 + /**
  22 + * 脚本编号
  23 + */
  24 + private final Long id;
  25 + /**
  26 + * 脚本描述
  27 + */
  28 + private final String desc;
  29 +
  30 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/enums/message/BpmMessageEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.enums.message;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Getter;
  5 +
  6 +/**
  7 + * Bpm 消息的枚举
  8 + *
  9 + * @author 芋道源码
  10 + */
  11 +@AllArgsConstructor
  12 +@Getter
  13 +public enum BpmMessageEnum {
  14 +
  15 + PROCESS_INSTANCE_APPROVE("bpm_process_instance_approve"), // 流程任务被审批通过时,发送给申请人
  16 + PROCESS_INSTANCE_REJECT("bpm_process_instance_reject"), // 流程任务被审批不通过时,发送给申请人
  17 + TASK_ASSIGNED("bpm_task_assigned"); // 任务被分配时,发送给审批人
  18 +
  19 + /**
  20 + * 短信模板的标识
  21 + *
  22 + * 关联 SmsTemplateDO 的 code 属性
  23 + */
  24 + private final String smsTemplateCode;
  25 +
  26 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceDeleteReasonEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.enums.task;
  2 +
  3 +import cn.hutool.core.util.StrUtil;
  4 +import lombok.AllArgsConstructor;
  5 +import lombok.Getter;
  6 +
  7 +/**
  8 + * 流程实例的删除原因
  9 + *
  10 + * @author 芋道源码
  11 + */
  12 +@Getter
  13 +@AllArgsConstructor
  14 +public enum BpmProcessInstanceDeleteReasonEnum {
  15 +
  16 + REJECT_TASK("不通过任务,原因:{}"), // 修改文案时,需要注意 isRejectReason 方法
  17 + CANCEL_TASK("主动取消任务,原因:{}");
  18 +
  19 + private final String reason;
  20 +
  21 + /**
  22 + * 格式化理由
  23 + *
  24 + * @param args 参数
  25 + * @return 理由
  26 + */
  27 + public String format(Object... args) {
  28 + return StrUtil.format(reason, args);
  29 + }
  30 +
  31 + // ========== 逻辑 ==========
  32 +
  33 + public static boolean isRejectReason(String reason) {
  34 + return StrUtil.startWith(reason, "不通过任务,原因:");
  35 + }
  36 +
  37 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceResultEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.enums.task;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Getter;
  5 +
  6 +/**
  7 + * 流程实例的结果
  8 + *
  9 + * @author jason
  10 + */
  11 +@Getter
  12 +@AllArgsConstructor
  13 +public enum BpmProcessInstanceResultEnum {
  14 +
  15 + PROCESS(1, "处理中"),
  16 + APPROVE(2, "通过"),
  17 + REJECT(3, "不通过"),
  18 + CANCEL(4, "已取消");
  19 +
  20 + /**
  21 + * 结果
  22 + */
  23 + private final Integer result;
  24 + /**
  25 + * 描述
  26 + */
  27 + private final String desc;
  28 +
  29 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceStatusEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.enums.task;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Getter;
  5 +
  6 +/**
  7 + * 流程实例的状态
  8 + *
  9 + * @author 芋道源码
  10 + */
  11 +@Getter
  12 +@AllArgsConstructor
  13 +public enum BpmProcessInstanceStatusEnum {
  14 +
  15 + RUNNING(1, "进行中"),
  16 + FINISH(2, "已完成");
  17 +
  18 + /**
  19 + * 状态
  20 + */
  21 + private final Integer status;
  22 + /**
  23 + * 描述
  24 + */
  25 + private final String desc;
  26 +
  27 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/config/BpmCommonConfiguration.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.bpm.config;
  2 +
  3 +import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher;
  4 +import org.springframework.context.ApplicationEventPublisher;
  5 +import org.springframework.context.annotation.Bean;
  6 +import org.springframework.context.annotation.Configuration;
  7 +
  8 +/**
  9 + * BPM 通用的 Configuration 配置类,提供给 Activiti 和 Flowable
  10 + */
  11 +@Configuration
  12 +public class BpmCommonConfiguration {
  13 +
  14 + @Bean
  15 + public BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher(ApplicationEventPublisher publisher) {
  16 + return new BpmProcessInstanceResultEventPublisher(publisher);
  17 + }
  18 +
  19 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/event/BpmProcessInstanceResultEvent.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.bpm.core.event;
  2 +
  3 +import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
  4 +import lombok.Data;
  5 +import org.springframework.context.ApplicationEvent;
  6 +
  7 +import javax.validation.constraints.NotNull;
  8 +
  9 +/**
  10 + * 流程实例的结果发生变化的 Event
  11 + * 定位:由于额外增加了 {@link BpmProcessInstanceExtDO#getResult()} 结果,所以增加该事件
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@SuppressWarnings("ALL")
  16 +@Data
  17 +public class BpmProcessInstanceResultEvent extends ApplicationEvent {
  18 +
  19 + /**
  20 + * 流程实例的编号
  21 + */
  22 + @NotNull(message = "流程实例的编号不能为空")
  23 + private String id;
  24 + /**
  25 + * 流程实例的 key
  26 + */
  27 + @NotNull(message = "流程实例的 key 不能为空")
  28 + private String processDefinitionKey;
  29 + /**
  30 + * 流程实例的结果
  31 + */
  32 + @NotNull(message = "流程实例的结果不能为空")
  33 + private Integer result;
  34 + /**
  35 + * 流程实例对应的业务标识
  36 + * 例如说,请假
  37 + */
  38 + private String businessKey;
  39 +
  40 + public BpmProcessInstanceResultEvent(Object source) {
  41 + super(source);
  42 + }
  43 +
  44 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/event/BpmProcessInstanceResultEventListener.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.bpm.core.event;
  2 +
  3 +import cn.hutool.core.util.StrUtil;
  4 +import org.springframework.context.ApplicationListener;
  5 +
  6 +/**
  7 + * {@link BpmProcessInstanceResultEvent} 的监听器
  8 + *
  9 + * @author 芋道源码
  10 + */
  11 +public abstract class BpmProcessInstanceResultEventListener
  12 + implements ApplicationListener<BpmProcessInstanceResultEvent> {
  13 +
  14 + @Override
  15 + public final void onApplicationEvent(BpmProcessInstanceResultEvent event) {
  16 + if (!StrUtil.equals(event.getProcessDefinitionKey(), getProcessDefinitionKey())) {
  17 + return;
  18 + }
  19 + onEvent(event);
  20 + }
  21 +
  22 + /**
  23 + * @return 返回监听的流程定义 Key
  24 + */
  25 + protected abstract String getProcessDefinitionKey();
  26 +
  27 + /**
  28 + * 处理事件
  29 + *
  30 + * @param event 事件
  31 + */
  32 + protected abstract void onEvent(BpmProcessInstanceResultEvent event);
  33 +
  34 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/event/BpmProcessInstanceResultEventPublisher.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.bpm.core.event;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import org.springframework.context.ApplicationEventPublisher;
  5 +import org.springframework.validation.annotation.Validated;
  6 +
  7 +import javax.validation.Valid;
  8 +
  9 +/**
  10 + * {@link BpmProcessInstanceResultEvent} 的生产者
  11 + *
  12 + * @author 芋道源码
  13 + */
  14 +@AllArgsConstructor
  15 +@Validated
  16 +public class BpmProcessInstanceResultEventPublisher {
  17 +
  18 + private final ApplicationEventPublisher publisher;
  19 +
  20 + public void sendProcessInstanceResultEvent(@Valid BpmProcessInstanceResultEvent event) {
  21 + publisher.publishEvent(event);
  22 + }
  23 +
  24 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/event/package-info.java 0 → 100644
  1 +/**
  2 + * 自定义 Event 实现,提供方便业务接入的 Listener!
  3 + *
  4 + * @author 芋道源码
  5 + */
  6 +package cn.iocoder.yudao.module.bpm.framework.bpm.core.event;
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/package-info.java 0 → 100644
  1 +/**
  2 + * 占位
  3 + */
  4 +package cn.iocoder.yudao.module.bpm.framework.bpm.core;
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/package-info.java 0 → 100644
  1 +/**
  2 + * 提供给 Activiti 和 Flowable 的通用封装
  3 + *
  4 + * @author 芋道源码
  5 + */
  6 +package cn.iocoder.yudao.module.bpm.framework.bpm;
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/config/BpmFlowableConfiguration.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.config;
  2 +
  3 +import cn.hutool.core.collection.ListUtil;
  4 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.BpmActivityBehaviorFactory;
  5 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
  6 +import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
  7 +import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
  8 +import cn.iocoder.yudao.module.system.api.dept.DeptApi;
  9 +import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
  10 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  11 +import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
  12 +import org.flowable.spring.SpringProcessEngineConfiguration;
  13 +import org.flowable.spring.boot.EngineConfigurationConfigurer;
  14 +import org.springframework.beans.factory.ObjectProvider;
  15 +import org.springframework.context.annotation.Bean;
  16 +import org.springframework.context.annotation.Configuration;
  17 +
  18 +import java.util.List;
  19 +
  20 +/**
  21 + * BPM 模块的 Flowable 配置类
  22 + *
  23 + * @author jason
  24 + */
  25 +@Configuration
  26 +public class BpmFlowableConfiguration {
  27 +
  28 + /**
  29 + * BPM 模块的 ProcessEngineConfigurationConfigurer 实现类:
  30 + *
  31 + * 1. 设置各种监听器
  32 + * 2. 设置自定义的 ActivityBehaviorFactory 实现
  33 + */
  34 + @Bean
  35 + public EngineConfigurationConfigurer<SpringProcessEngineConfiguration> bpmProcessEngineConfigurationConfigurer(
  36 + ObjectProvider<FlowableEventListener> listeners,
  37 + BpmActivityBehaviorFactory bpmActivityBehaviorFactory) {
  38 + return configuration -> {
  39 + // 注册监听器,例如说 BpmActivitiEventListener
  40 + configuration.setEventListeners(ListUtil.toList(listeners.iterator()));
  41 + // 设置 ActivityBehaviorFactory 实现类,用于流程任务的审核人的自定义
  42 + configuration.setActivityBehaviorFactory(bpmActivityBehaviorFactory);
  43 + };
  44 + }
  45 +
  46 + @Bean
  47 + public BpmActivityBehaviorFactory bpmActivityBehaviorFactory(BpmTaskAssignRuleService taskRuleService,
  48 + BpmUserGroupService userGroupService,
  49 + PermissionApi permissionApi,
  50 + DeptApi deptApi,
  51 + AdminUserApi adminUserApi,
  52 + List<BpmTaskAssignScript> scripts) {
  53 + BpmActivityBehaviorFactory bpmActivityBehaviorFactory = new BpmActivityBehaviorFactory();
  54 + bpmActivityBehaviorFactory.setBpmTaskRuleService(taskRuleService);
  55 + bpmActivityBehaviorFactory.setUserGroupService(userGroupService);
  56 + bpmActivityBehaviorFactory.setAdminUserApi(adminUserApi);
  57 + bpmActivityBehaviorFactory.setPermissionApi(permissionApi);
  58 + bpmActivityBehaviorFactory.setDeptApi(deptApi);
  59 + bpmActivityBehaviorFactory.setScripts(scripts);
  60 + return bpmActivityBehaviorFactory;
  61 + }
  62 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmActivityBehaviorFactory.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior;
  2 +
  3 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
  4 +import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
  5 +import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
  6 +import cn.iocoder.yudao.module.system.api.dept.DeptApi;
  7 +import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
  8 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  9 +import lombok.Data;
  10 +import lombok.EqualsAndHashCode;
  11 +import lombok.Setter;
  12 +import lombok.ToString;
  13 +import org.flowable.bpmn.model.UserTask;
  14 +import org.flowable.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
  15 +import org.flowable.engine.impl.bpmn.parser.factory.DefaultActivityBehaviorFactory;
  16 +
  17 +import java.util.List;
  18 +
  19 +/**
  20 + * 自定义的 ActivityBehaviorFactory 实现类,目的如下:
  21 + * 1. 自定义 {@link #createUserTaskActivityBehavior(UserTask)}:实现自定义的流程任务的 assignee 负责人的分配
  22 + *
  23 + * @author 芋道源码
  24 + */
  25 +@Data
  26 +@EqualsAndHashCode(callSuper = true)
  27 +@ToString(callSuper = true)
  28 +public class BpmActivityBehaviorFactory extends DefaultActivityBehaviorFactory {
  29 +
  30 + @Setter
  31 + private BpmTaskAssignRuleService bpmTaskRuleService;
  32 + @Setter
  33 + private BpmUserGroupService userGroupService;
  34 +
  35 + @Setter
  36 + private PermissionApi permissionApi;
  37 + @Setter
  38 + private DeptApi deptApi;
  39 + @Setter
  40 + private AdminUserApi adminUserApi;
  41 + @Setter
  42 + private List<BpmTaskAssignScript> scripts;
  43 +
  44 + @Override
  45 + public UserTaskActivityBehavior createUserTaskActivityBehavior(UserTask userTask) {
  46 + BpmUserTaskActivityBehavior userTaskActivityBehavior = new BpmUserTaskActivityBehavior(userTask);
  47 + userTaskActivityBehavior.setBpmTaskRuleService(bpmTaskRuleService);
  48 + userTaskActivityBehavior.setPermissionApi(permissionApi);
  49 + userTaskActivityBehavior.setDeptApi(deptApi);
  50 + userTaskActivityBehavior.setUserGroupService(userGroupService);
  51 + userTaskActivityBehavior.setAdminUserApi(adminUserApi);
  52 + userTaskActivityBehavior.setScripts(scripts);
  53 + return userTaskActivityBehavior;
  54 + }
  55 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmUserTaskActivityBehavior.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.RandomUtil;
  5 +import cn.hutool.core.util.StrUtil;
  6 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  7 +import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
  8 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
  9 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
  10 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
  11 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
  12 +import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
  13 +import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
  14 +import cn.iocoder.yudao.module.system.api.dept.DeptApi;
  15 +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
  16 +import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
  17 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  18 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  19 +import com.google.common.annotations.VisibleForTesting;
  20 +import lombok.Setter;
  21 +import lombok.extern.slf4j.Slf4j;
  22 +import org.flowable.bpmn.model.UserTask;
  23 +import org.flowable.common.engine.api.FlowableException;
  24 +import org.flowable.common.engine.impl.el.ExpressionManager;
  25 +import org.flowable.engine.delegate.DelegateExecution;
  26 +import org.flowable.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
  27 +import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
  28 +import org.flowable.engine.impl.util.TaskHelper;
  29 +import org.flowable.task.service.TaskService;
  30 +import org.flowable.task.service.impl.persistence.entity.TaskEntity;
  31 +
  32 +import java.util.*;
  33 +
  34 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  35 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
  36 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
  37 +import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
  38 +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_ASSIGN_SCRIPT_NOT_EXISTS;
  39 +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_CREATE_FAIL_NO_CANDIDATE_USER;
  40 +
  41 +/**
  42 + * 自定义的流程任务的 assignee 负责人的分配
  43 + * 第一步,获得对应的分配规则;
  44 + * 第二步,根据分配规则,计算出分配任务的候选人。如果找不到,则直接报业务异常,不继续执行后续的流程;
  45 + * 第三步,随机选择一个候选人,则选择作为 assignee 负责人。
  46 + *
  47 + * @author 芋道源码
  48 + */
  49 +@Slf4j
  50 +public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior {
  51 +
  52 + @Setter
  53 + private BpmTaskAssignRuleService bpmTaskRuleService;
  54 + @Setter
  55 + private BpmUserGroupService userGroupService;
  56 + @Setter
  57 + private DeptApi deptApi;
  58 + @Setter
  59 + private AdminUserApi adminUserApi;
  60 + @Setter
  61 + private PermissionApi permissionApi;
  62 +
  63 + /**
  64 + * 任务分配脚本
  65 + */
  66 + private Map<Long, BpmTaskAssignScript> scriptMap = Collections.emptyMap();
  67 +
  68 + public BpmUserTaskActivityBehavior(UserTask userTask) {
  69 + super(userTask);
  70 + }
  71 +
  72 + public void setScripts(List<BpmTaskAssignScript> scripts) {
  73 + this.scriptMap = convertMap(scripts, script -> script.getEnum().getId());
  74 + }
  75 +
  76 + @Override
  77 + @DataPermission(enable = false) // 不需要处理数据权限, 不然会有问题,查询不到数据
  78 + protected void handleAssignments(TaskService taskService, String assignee, String owner, List<String> candidateUsers, List<String> candidateGroups, TaskEntity task, ExpressionManager expressionManager, DelegateExecution execution, ProcessEngineConfigurationImpl processEngineConfiguration) {
  79 + boolean isMultiInstance = hasMultiInstanceCharacteristics();
  80 + if(isMultiInstance){
  81 + //多实例 会签/或签,执行多次每个人 待办人都在execution里面获取
  82 + Integer assigneeUserId = execution.getVariableLocal("user", Integer.class);
  83 + TaskHelper.changeTaskAssignee(task, String.valueOf(assigneeUserId));
  84 + }else {
  85 + // 第一步,获得任务的规则
  86 + BpmTaskAssignRuleDO rule = getTaskRule(task);
  87 + // 第二步,获得任务的候选用户们
  88 + Set<Long> candidateUserIds = calculateTaskCandidateUsers(task, rule);
  89 + // 第三步,设置一个作为负责人
  90 + Long assigneeUserId = chooseTaskAssignee(candidateUserIds);
  91 + TaskHelper.changeTaskAssignee(task, String.valueOf(assigneeUserId));
  92 + }
  93 +
  94 + }
  95 +
  96 + private BpmTaskAssignRuleDO getTaskRule(TaskEntity task) {
  97 + List<BpmTaskAssignRuleDO> taskRules = bpmTaskRuleService.getTaskAssignRuleListByProcessDefinitionId(task.getProcessDefinitionId(),
  98 + task.getTaskDefinitionKey());
  99 + if (CollUtil.isEmpty(taskRules)) {
  100 + throw new FlowableException(StrUtil.format("流程任务({}/{}/{}) 找不到符合的任务规则",
  101 + task.getId(), task.getProcessDefinitionId(), task.getTaskDefinitionKey()));
  102 + }
  103 + if (taskRules.size() > 1) {
  104 + throw new FlowableException(StrUtil.format("流程任务({}/{}/{}) 找到过多任务规则({})",
  105 + task.getId(), task.getProcessDefinitionId(), task.getTaskDefinitionKey(), taskRules.size()));
  106 + }
  107 + return taskRules.get(0);
  108 + }
  109 +
  110 + Set<Long> calculateTaskCandidateUsers(TaskEntity task, BpmTaskAssignRuleDO rule) {
  111 + Set<Long> assigneeUserIds = null;
  112 + if (Objects.equals(BpmTaskAssignRuleTypeEnum.ROLE.getType(), rule.getType())) {
  113 + assigneeUserIds = calculateTaskCandidateUsersByRole(task, rule);
  114 + } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType(), rule.getType())) {
  115 + assigneeUserIds = calculateTaskCandidateUsersByDeptMember(task, rule);
  116 + } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType(), rule.getType())) {
  117 + assigneeUserIds = calculateTaskCandidateUsersByDeptLeader(task, rule);
  118 + } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.POST.getType(), rule.getType())) {
  119 + assigneeUserIds = calculateTaskCandidateUsersByPost(task, rule);
  120 + } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER.getType(), rule.getType())) {
  121 + assigneeUserIds = calculateTaskCandidateUsersByUser(task, rule);
  122 + } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER_GROUP.getType(), rule.getType())) {
  123 + assigneeUserIds = calculateTaskCandidateUsersByUserGroup(task, rule);
  124 + } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.SCRIPT.getType(), rule.getType())) {
  125 + assigneeUserIds = calculateTaskCandidateUsersByScript(task, rule);
  126 + }
  127 +
  128 + // 移除被禁用的用户
  129 + removeDisableUsers(assigneeUserIds);
  130 + // 如果候选人为空,抛出异常 TODO 芋艿:没候选人的策略选择。1 - 挂起;2 - 直接结束;3 - 强制一个兜底人
  131 + if (CollUtil.isEmpty(assigneeUserIds)) {
  132 + log.error("[calculateTaskCandidateUsers][流程任务({}/{}/{}) 任务规则({}) 找不到候选人]",
  133 + task.getId(), task.getProcessDefinitionId(), task.getTaskDefinitionKey(), toJsonString(rule));
  134 + throw exception(TASK_CREATE_FAIL_NO_CANDIDATE_USER);
  135 + }
  136 + return assigneeUserIds;
  137 + }
  138 +
  139 + private Set<Long> calculateTaskCandidateUsersByRole(TaskEntity task, BpmTaskAssignRuleDO rule) {
  140 + return permissionApi.getUserRoleIdListByRoleIds(rule.getOptions());
  141 + }
  142 +
  143 + private Set<Long> calculateTaskCandidateUsersByDeptMember(TaskEntity task, BpmTaskAssignRuleDO rule) {
  144 + List<AdminUserRespDTO> users = adminUserApi.getUsersByDeptIds(rule.getOptions());
  145 + return convertSet(users, AdminUserRespDTO::getId);
  146 + }
  147 +
  148 + private Set<Long> calculateTaskCandidateUsersByDeptLeader(TaskEntity task, BpmTaskAssignRuleDO rule) {
  149 + List<DeptRespDTO> depts = deptApi.getDepts(rule.getOptions());
  150 + return convertSet(depts, DeptRespDTO::getLeaderUserId);
  151 + }
  152 +
  153 + private Set<Long> calculateTaskCandidateUsersByPost(TaskEntity task, BpmTaskAssignRuleDO rule) {
  154 + List<AdminUserRespDTO> users = adminUserApi.getUsersByPostIds(rule.getOptions());
  155 + return convertSet(users, AdminUserRespDTO::getId);
  156 + }
  157 +
  158 + private Set<Long> calculateTaskCandidateUsersByUser(TaskEntity task, BpmTaskAssignRuleDO rule) {
  159 + return rule.getOptions();
  160 + }
  161 +
  162 + private Set<Long> calculateTaskCandidateUsersByUserGroup(TaskEntity task, BpmTaskAssignRuleDO rule) {
  163 + List<BpmUserGroupDO> userGroups = userGroupService.getUserGroupList(rule.getOptions());
  164 + Set<Long> userIds = new HashSet<>();
  165 + userGroups.forEach(group -> userIds.addAll(group.getMemberUserIds()));
  166 + return userIds;
  167 + }
  168 +
  169 + private Set<Long> calculateTaskCandidateUsersByScript(TaskEntity task, BpmTaskAssignRuleDO rule) {
  170 + // 获得对应的脚本
  171 + List<BpmTaskAssignScript> scripts = new ArrayList<>(rule.getOptions().size());
  172 + rule.getOptions().forEach(id -> {
  173 + BpmTaskAssignScript script = scriptMap.get(id);
  174 + if (script == null) {
  175 + throw exception(TASK_ASSIGN_SCRIPT_NOT_EXISTS, id);
  176 + }
  177 + scripts.add(script);
  178 + });
  179 + // 逐个计算任务
  180 + Set<Long> userIds = new HashSet<>();
  181 + scripts.forEach(script -> CollUtil.addAll(userIds, script.calculateTaskCandidateUsers(task)));
  182 + return userIds;
  183 + }
  184 +
  185 + private Long chooseTaskAssignee(Set<Long> candidateUserIds) {
  186 + // TODO 芋艿:未来可以优化下,改成轮询的策略
  187 + int index = RandomUtil.randomInt(candidateUserIds.size());
  188 + return CollUtil.get(candidateUserIds, index);
  189 + }
  190 +
  191 + @VisibleForTesting
  192 + void removeDisableUsers(Set<Long> assigneeUserIds) {
  193 + if (CollUtil.isEmpty(assigneeUserIds)) {
  194 + return;
  195 + }
  196 + //TODO 芋艿 这里有数据权限的问题。默认会加上数据权限 dept_id IN (deptId). 导致查询不到数据
  197 + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(assigneeUserIds);
  198 + assigneeUserIds.removeIf(id -> {
  199 + AdminUserRespDTO user = userMap.get(id);
  200 + return user == null || !CommonStatusEnum.ENABLE.getStatus().equals(user.getStatus());
  201 + });
  202 + }
  203 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/BpmTaskAssignScript.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script;
  2 +
  3 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
  4 +import org.flowable.task.service.impl.persistence.entity.TaskEntity;
  5 +
  6 +import java.util.Set;
  7 +
  8 +/**
  9 + * Bpm 任务分配的自定义 Script 脚本
  10 + * 使用场景:
  11 + * 1. 设置审批人为发起人
  12 + * 2. 设置审批人为发起人的 Leader
  13 + * 3. 甚至审批人为发起人的 Leader 的 Leader
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +public interface BpmTaskAssignScript {
  18 +
  19 + /**
  20 + * 基于流程任务,获得任务的候选用户们
  21 + *
  22 + * @param task 任务
  23 + * @return 候选人用户的编号数组
  24 + */
  25 + Set<Long> calculateTaskCandidateUsers(TaskEntity task);
  26 +
  27 + /**
  28 + * 获得枚举值
  29 + *
  30 + * @return 枚举值
  31 + */
  32 + BpmTaskRuleScriptEnum getEnum();
  33 +}
  34 +
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderAbstractScript.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
  2 +
  3 +import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
  4 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
  5 +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
  6 +import cn.iocoder.yudao.module.system.api.dept.DeptApi;
  7 +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
  8 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  9 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  10 +
  11 +import org.flowable.engine.runtime.ProcessInstance;
  12 +import org.flowable.task.service.impl.persistence.entity.TaskEntity;
  13 +import org.springframework.context.annotation.Lazy;
  14 +import org.springframework.util.Assert;
  15 +
  16 +import javax.annotation.Resource;
  17 +import java.util.Set;
  18 +
  19 +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
  20 +import static java.util.Collections.emptySet;
  21 +
  22 +/**
  23 + * 分配给发起人的 Leader 审批的 Script 实现类
  24 + * 目前 Leader 的定义是,
  25 + *
  26 + * @author 芋道源码
  27 + */
  28 +public abstract class BpmTaskAssignLeaderAbstractScript implements BpmTaskAssignScript {
  29 +
  30 + @Resource
  31 + private AdminUserApi adminUserApi;
  32 + @Resource
  33 + private DeptApi deptApi;
  34 + @Resource
  35 + @Lazy // 解决循环依赖
  36 + private BpmProcessInstanceService bpmProcessInstanceService;
  37 +
  38 + protected Set<Long> calculateTaskCandidateUsers(TaskEntity task, int level) {
  39 + Assert.isTrue(level > 0, "level 必须大于 0");
  40 + // 获得发起人
  41 + ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(task.getProcessInstanceId());
  42 + Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId());
  43 + // 获得对应 leve 的部门
  44 + DeptRespDTO dept = null;
  45 + for (int i = 0; i < level; i++) {
  46 + // 获得 level 对应的部门
  47 + if (dept == null) {
  48 + dept = getStartUserDept(startUserId);
  49 + if (dept == null) { // 找不到发起人的部门,所以无法使用该规则
  50 + return emptySet();
  51 + }
  52 + } else {
  53 + DeptRespDTO parentDept = deptApi.getDept(dept.getParentId());
  54 + if (parentDept == null) { // 找不到父级部门,所以只好结束寻找。原因是:例如说,级别比较高的人,所在部门层级比较少
  55 + break;
  56 + }
  57 + dept = parentDept;
  58 + }
  59 + }
  60 + return dept.getLeaderUserId() != null ? asSet(dept.getLeaderUserId()) : emptySet();
  61 + }
  62 +
  63 + private DeptRespDTO getStartUserDept(Long startUserId) {
  64 + AdminUserRespDTO startUser = adminUserApi.getUser(startUserId);
  65 + if (startUser.getDeptId() == null) { // 找不到部门,所以无法使用该规则
  66 + return null;
  67 + }
  68 + return deptApi.getDept(startUser.getDeptId());
  69 + }
  70 +
  71 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
  2 +
  3 +import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
  4 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
  5 +import org.flowable.task.service.impl.persistence.entity.TaskEntity;
  6 +import org.springframework.stereotype.Component;
  7 +
  8 +import java.util.Set;
  9 +
  10 +/**
  11 + * 分配给发起人的一级 Leader 审批的 Script 实现类
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@Component
  16 +public class BpmTaskAssignLeaderX1Script extends BpmTaskAssignLeaderAbstractScript {
  17 +
  18 + @Override
  19 + @DataPermission(enable = false) // 不需要处理数据权限, 不然会有问题,查询不到数据
  20 + public Set<Long> calculateTaskCandidateUsers(TaskEntity task) {
  21 + return calculateTaskCandidateUsers(task, 1);
  22 + }
  23 +
  24 + @Override
  25 + public BpmTaskRuleScriptEnum getEnum() {
  26 + return BpmTaskRuleScriptEnum.LEADER_X1;
  27 + }
  28 +
  29 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
  2 +
  3 +import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
  4 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
  5 +import org.flowable.task.service.impl.persistence.entity.TaskEntity;
  6 +import org.springframework.stereotype.Component;
  7 +
  8 +import java.util.Set;
  9 +
  10 +/**
  11 + * 分配给发起人的二级 Leader 审批的 Script 实现类
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@Component
  16 +public class BpmTaskAssignLeaderX2Script extends BpmTaskAssignLeaderAbstractScript {
  17 +
  18 + @Override
  19 + @DataPermission(enable = false) // 不需要处理数据权限, 不然会有问题,查询不到数据
  20 + public Set<Long> calculateTaskCandidateUsers(TaskEntity task) {
  21 + return calculateTaskCandidateUsers(task, 2);
  22 + }
  23 +
  24 + @Override
  25 + public BpmTaskRuleScriptEnum getEnum() {
  26 + return BpmTaskRuleScriptEnum.LEADER_X2;
  27 + }
  28 +
  29 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignStartUserScript.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
  2 +
  3 +import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
  4 +import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
  5 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
  6 +
  7 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
  8 +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
  9 +import org.flowable.engine.runtime.ProcessInstance;
  10 +import org.flowable.task.service.impl.persistence.entity.TaskEntity;
  11 +import org.springframework.context.annotation.Lazy;
  12 +import org.springframework.stereotype.Component;
  13 +
  14 +import javax.annotation.Resource;
  15 +import java.util.Set;
  16 +
  17 +/**
  18 + * 分配给发起人审批的 Script 实现类
  19 + *
  20 + * @author 芋道源码
  21 + */
  22 +@Component
  23 +public class BpmTaskAssignStartUserScript implements BpmTaskAssignScript {
  24 +
  25 + @Resource
  26 + @Lazy // 解决循环依赖
  27 + private BpmProcessInstanceService bpmProcessInstanceService;
  28 +
  29 + @Override
  30 + public Set<Long> calculateTaskCandidateUsers(TaskEntity task) {
  31 + ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(task.getProcessInstanceId());
  32 + Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId());
  33 + return SetUtils.asSet(startUserId);
  34 + }
  35 +
  36 + @Override
  37 + public BpmTaskRuleScriptEnum getEnum() {
  38 + return BpmTaskRuleScriptEnum.START_USER;
  39 + }
  40 +
  41 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmProcessInstanceEventListener.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.listener;
  2 +
  3 +import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
  4 +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
  5 +import com.google.common.collect.ImmutableSet;
  6 +import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
  7 +import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
  8 +import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener;
  9 +import org.flowable.engine.delegate.event.FlowableCancelledEvent;
  10 +import org.flowable.engine.delegate.event.FlowableProcessStartedEvent;
  11 +import org.flowable.engine.runtime.ProcessInstance;
  12 +import org.springframework.context.annotation.Lazy;
  13 +import org.springframework.stereotype.Component;
  14 +
  15 +import javax.annotation.Resource;
  16 +import java.util.Set;
  17 +/**
  18 + * 监听 {@link ProcessInstance} 的开始与完成,创建与更新对应的 {@link BpmProcessInstanceExtDO} 记录
  19 + *
  20 + * @author jason
  21 + */
  22 +@Component
  23 +public class BpmProcessInstanceEventListener extends AbstractFlowableEngineEventListener {
  24 +
  25 + @Resource
  26 + @Lazy
  27 + private BpmProcessInstanceService processInstanceService;
  28 +
  29 + public static final Set<FlowableEngineEventType> PROCESS_INSTANCE_EVENTS = ImmutableSet.<FlowableEngineEventType>builder()
  30 + .add(FlowableEngineEventType.PROCESS_CREATED)
  31 + .add(FlowableEngineEventType.PROCESS_CANCELLED)
  32 + .add(FlowableEngineEventType.PROCESS_COMPLETED)
  33 + .build();
  34 +
  35 + public BpmProcessInstanceEventListener(){
  36 + super(PROCESS_INSTANCE_EVENTS);
  37 + }
  38 +
  39 + @Override
  40 + protected void processCreated(FlowableEngineEntityEvent event) {
  41 + processInstanceService.createProcessInstanceExt((ProcessInstance)event.getEntity());
  42 + }
  43 +
  44 + @Override
  45 + protected void processCancelled(FlowableCancelledEvent event) {
  46 + processInstanceService.updateProcessInstanceExtCancel(event);
  47 + }
  48 +
  49 + @Override
  50 + protected void processCompleted(FlowableEngineEntityEvent event) {
  51 + processInstanceService.updateProcessInstanceExtComplete((ProcessInstance)event.getEntity());
  52 + }
  53 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.listener;
  2 +
  3 +import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
  4 +import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService;
  5 +import com.google.common.collect.ImmutableSet;
  6 +import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
  7 +import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
  8 +import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener;
  9 +import org.flowable.task.api.Task;
  10 +import org.springframework.context.annotation.Lazy;
  11 +import org.springframework.stereotype.Component;
  12 +
  13 +import javax.annotation.Resource;
  14 +import java.util.Set;
  15 +
  16 +/**
  17 + * 监听 {@link org.flowable.task.api.Task} 的开始与完成,创建与更新对应的 {@link BpmTaskExtDO} 记录
  18 + *
  19 + * @author jason
  20 + */
  21 +@Component
  22 +public class BpmTaskEventListener extends AbstractFlowableEngineEventListener {
  23 +
  24 + @Resource
  25 + @Lazy // 解决循环依赖
  26 + private BpmTaskService taskService;
  27 +
  28 + public static final Set<FlowableEngineEventType> TASK_EVENTS = ImmutableSet.<FlowableEngineEventType>builder()
  29 + .add(FlowableEngineEventType.TASK_CREATED)
  30 + .add(FlowableEngineEventType.TASK_ASSIGNED)
  31 + .add(FlowableEngineEventType.TASK_COMPLETED)
  32 + .build();
  33 +
  34 + public BpmTaskEventListener(){
  35 + super(TASK_EVENTS);
  36 + }
  37 +
  38 + @Override
  39 + protected void taskCreated(FlowableEngineEntityEvent event) {
  40 + taskService.createTaskExt((Task) event.getEntity());
  41 + }
  42 +
  43 + @Override
  44 + protected void taskCompleted(FlowableEngineEntityEvent event) {
  45 + taskService.updateTaskExtComplete((Task)event.getEntity());
  46 + }
  47 +
  48 + @Override
  49 + protected void taskAssigned(FlowableEngineEntityEvent event) {
  50 + taskService.updateTaskExtAssign((Task)event.getEntity());
  51 + }
  52 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/package-info.java 0 → 100644
  1 +/**
  2 + * 属于 bpm 模块的 framework 封装
  3 + *
  4 + * @author 芋道源码
  5 + */
  6 +package cn.iocoder.yudao.module.bpm.framework;
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/package-info.java 0 → 100644
  1 +/**
  2 + * bpm 包下,业务流程管理(Business Process Management),我们放工作流的功能,基于 activiti 7 版本实现。
  3 + * 例如说:流程定义、表单配置、审核中心(我的申请、我的待办、我的已办)等等
  4 + *
  5 + * bpm 解释:https://baike.baidu.com/item/BPM/1933
  6 + *
  7 + * 1. Controller URL:以 /bpm/ 开头,避免和其它 Module 冲突
  8 + * 2. DataObject 表名:以 bpm_ 开头,方便在数据库中区分
  9 + *
  10 + * 注意,由于 Bpm 模块下,容易和其它模块重名,所以类名都加载 Pay 的前缀~
  11 + */
  12 +package cn.iocoder.yudao.module.bpm;
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.definition;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormCreateReqVO;
  5 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormPageReqVO;
  6 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormUpdateReqVO;
  7 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
  8 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  9 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  10 +
  11 +import javax.validation.Valid;
  12 +import java.util.Collection;
  13 +import java.util.Collections;
  14 +import java.util.List;
  15 +import java.util.Map;
  16 +
  17 +
  18 +/**
  19 + * 动态表单 Service 接口
  20 + *
  21 + * @author @风里雾里
  22 + */
  23 +public interface BpmFormService {
  24 +
  25 + /**
  26 + * 创建动态表单
  27 + *
  28 + * @param createReqVO 创建信息
  29 + * @return 编号
  30 + */
  31 + Long createForm(@Valid BpmFormCreateReqVO createReqVO);
  32 +
  33 + /**
  34 + * 更新动态表单
  35 + *
  36 + * @param updateReqVO 更新信息
  37 + */
  38 + void updateForm(@Valid BpmFormUpdateReqVO updateReqVO);
  39 +
  40 + /**
  41 + * 删除动态表单
  42 + *
  43 + * @param id 编号
  44 + */
  45 + void deleteForm(Long id);
  46 +
  47 + /**
  48 + * 获得动态表单
  49 + *
  50 + * @param id 编号
  51 + * @return 动态表单
  52 + */
  53 + BpmFormDO getForm(Long id);
  54 +
  55 + /**
  56 + * 获得动态表单列表
  57 + *
  58 + * @return 动态表单列表
  59 + */
  60 + List<BpmFormDO> getFormList();
  61 +
  62 + /**
  63 + * 获得动态表单列表
  64 + *
  65 + * @param ids 编号
  66 + * @return 动态表单列表
  67 + */
  68 + List<BpmFormDO> getFormList(Collection<Long> ids);
  69 +
  70 + /**
  71 + * 获得动态表单 Map
  72 + *
  73 + * @param ids 编号
  74 + * @return 动态表单 Map
  75 + */
  76 + default Map<Long, BpmFormDO> getFormMap(Collection<Long> ids) {
  77 + if (CollUtil.isEmpty(ids)) {
  78 + return Collections.emptyMap();
  79 + }
  80 + return CollectionUtils.convertMap(this.getFormList(ids), BpmFormDO::getId);
  81 + }
  82 +
  83 + /**
  84 + * 获得动态表单分页
  85 + *
  86 + * @param pageReqVO 分页查询
  87 + * @return 动态表单分页
  88 + */
  89 + PageResult<BpmFormDO> getFormPage(BpmFormPageReqVO pageReqVO);
  90 +
  91 + /**
  92 + * 校验流程表单已配置
  93 + *
  94 + * @param configStr configStr 字段
  95 + * @return 流程表单
  96 + */
  97 + BpmFormDO checkFormConfig(String configStr);
  98 +
  99 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.definition;
  2 +
  3 +import cn.hutool.core.lang.Assert;
  4 +import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
  5 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormCreateReqVO;
  6 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormPageReqVO;
  7 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormUpdateReqVO;
  8 +import cn.iocoder.yudao.module.bpm.convert.definition.BpmFormConvert;
  9 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
  10 +import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmFormMapper;
  11 +import cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants;
  12 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
  13 +import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmFormFieldRespDTO;
  14 +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
  15 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  16 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
  17 +import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
  18 +import org.springframework.stereotype.Service;
  19 +import org.springframework.validation.annotation.Validated;
  20 +
  21 +import javax.annotation.Resource;
  22 +import java.util.*;
  23 +
  24 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  25 +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
  26 +
  27 +/**
  28 + * 动态表单 Service 实现类
  29 + *
  30 + * @author 风里雾里
  31 + */
  32 +@Service
  33 +@Validated
  34 +public class BpmFormServiceImpl implements BpmFormService {
  35 +
  36 + @Resource
  37 + private BpmFormMapper formMapper;
  38 +
  39 + @Override
  40 + public Long createForm(BpmFormCreateReqVO createReqVO) {
  41 + this.checkFields(createReqVO.getFields());
  42 + // 插入
  43 + BpmFormDO form = BpmFormConvert.INSTANCE.convert(createReqVO);
  44 + formMapper.insert(form);
  45 + // 返回
  46 + return form.getId();
  47 + }
  48 +
  49 + @Override
  50 + public void updateForm(BpmFormUpdateReqVO updateReqVO) {
  51 + this.checkFields(updateReqVO.getFields());
  52 + // 校验存在
  53 + this.validateFormExists(updateReqVO.getId());
  54 + // 更新
  55 + BpmFormDO updateObj = BpmFormConvert.INSTANCE.convert(updateReqVO);
  56 + formMapper.updateById(updateObj);
  57 + }
  58 +
  59 + @Override
  60 + public void deleteForm(Long id) {
  61 + // 校验存在
  62 + this.validateFormExists(id);
  63 + // 删除
  64 + formMapper.deleteById(id);
  65 + }
  66 +
  67 + private void validateFormExists(Long id) {
  68 + if (formMapper.selectById(id) == null) {
  69 + throw ServiceExceptionUtil.exception(ErrorCodeConstants.FORM_NOT_EXISTS);
  70 + }
  71 + }
  72 +
  73 + @Override
  74 + public BpmFormDO getForm(Long id) {
  75 + return formMapper.selectById(id);
  76 + }
  77 +
  78 + @Override
  79 + public List<BpmFormDO> getFormList() {
  80 + return formMapper.selectList();
  81 + }
  82 +
  83 + @Override
  84 + public List<BpmFormDO> getFormList(Collection<Long> ids) {
  85 + return formMapper.selectBatchIds(ids);
  86 + }
  87 +
  88 + @Override
  89 + public PageResult<BpmFormDO> getFormPage(BpmFormPageReqVO pageReqVO) {
  90 + return formMapper.selectPage(pageReqVO);
  91 + }
  92 +
  93 +
  94 + @Override
  95 + public BpmFormDO checkFormConfig(String configStr) {
  96 + BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(configStr, BpmModelMetaInfoRespDTO.class);
  97 + if (metaInfo == null || metaInfo.getFormType() == null) {
  98 + throw exception(MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG);
  99 + }
  100 + // 校验表单存在
  101 + if (Objects.equals(metaInfo.getFormType(), BpmModelFormTypeEnum.NORMAL.getType())) {
  102 + BpmFormDO form = getForm(metaInfo.getFormId());
  103 + if (form == null) {
  104 + throw exception(FORM_NOT_EXISTS);
  105 + }
  106 + return form;
  107 + }
  108 + return null;
  109 + }
  110 +
  111 + private void checkKeyNCName(String key) {
  112 + if (!ValidationUtils.isXmlNCName(key)) {
  113 + throw exception(MODEL_KEY_VALID);
  114 + }
  115 + }
  116 + /**
  117 + * 校验 Field,避免 field 重复
  118 + *
  119 + * @param fields field 数组
  120 + */
  121 + private void checkFields(List<String> fields) {
  122 + Map<String, String> fieldMap = new HashMap<>(); // key 是 vModel,value 是 label
  123 + for (String field : fields) {
  124 + BpmFormFieldRespDTO fieldDTO = JsonUtils.parseObject(field, BpmFormFieldRespDTO.class);
  125 + Assert.notNull(fieldDTO);
  126 + String oldLabel = fieldMap.put(fieldDTO.getVModel(), fieldDTO.getLabel());
  127 + // 如果不存在,则直接返回
  128 + if (oldLabel == null) {
  129 + continue;
  130 + }
  131 + // 如果存在,则报错
  132 + throw ServiceExceptionUtil.exception(ErrorCodeConstants.FORM_FIELD_REPEAT, oldLabel, fieldDTO.getLabel(), fieldDTO.getVModel());
  133 + }
  134 + }
  135 +
  136 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.definition;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*;
  5 +import org.flowable.bpmn.model.BpmnModel;
  6 +
  7 +import javax.validation.Valid;
  8 +
  9 +/**
  10 + * Flowable流程模型接口
  11 + *
  12 + * @author yunlongn
  13 + */
  14 +public interface BpmModelService {
  15 + /**
  16 + * 获得流程模型分页
  17 + *
  18 + * @param pageVO 分页查询
  19 + * @return 流程模型分页
  20 + */
  21 + PageResult<BpmModelPageItemRespVO> getModelPage(BpmModelPageReqVO pageVO);
  22 +
  23 + /**
  24 + * 创建流程模型
  25 + *
  26 + * @param modelVO 创建信息
  27 + * @param bpmnXml BPMN XML
  28 + * @return 创建的流程模型的编号
  29 + */
  30 + String createModel(@Valid BpmModelCreateReqVO modelVO, String bpmnXml);
  31 +
  32 + /**
  33 + * 获得流程模块
  34 + *
  35 + * @param id 编号
  36 + * @return 流程模型
  37 + */
  38 + BpmModelRespVO getModel(String id);
  39 +
  40 + /**
  41 + * 修改流程模型
  42 + *
  43 + * @param updateReqVO 更新信息
  44 + */
  45 + void updateModel(@Valid BpmModelUpdateReqVO updateReqVO);
  46 +
  47 + /**
  48 + * 将流程模型,部署成一个流程定义
  49 + *
  50 + * @param id 编号
  51 + */
  52 + void deployModel(String id);
  53 +
  54 + /**
  55 + * 删除模型
  56 + *
  57 + * @param id 编号
  58 + */
  59 + void deleteModel(String id);
  60 +
  61 + /**
  62 + * 修改模型的状态,实际更新的部署的流程定义的状态
  63 + *
  64 + * @param id 编号
  65 + * @param state 状态
  66 + */
  67 + void updateModelState(String id, Integer state);
  68 +
  69 + /**
  70 + * 获得流程模型编号对应的 BPMN Model
  71 + *
  72 + * @param id 流程模型编号
  73 + * @return BPMN Model
  74 + */
  75 + BpmnModel getBpmnModel(String id);
  76 +
  77 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.definition;
  2 +
  3 +import cn.hutool.core.util.ArrayUtil;
  4 +import cn.hutool.core.util.StrUtil;
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  7 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
  8 +import cn.iocoder.yudao.framework.common.util.object.PageUtils;
  9 +import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
  10 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*;
  11 +import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert;
  12 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
  13 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
  14 +import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
  15 +import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
  16 +import lombok.extern.slf4j.Slf4j;
  17 +import org.flowable.bpmn.converter.BpmnXMLConverter;
  18 +import org.flowable.bpmn.model.BpmnModel;
  19 +import org.flowable.common.engine.impl.db.SuspensionState;
  20 +import org.flowable.common.engine.impl.util.io.BytesStreamSource;
  21 +import org.flowable.engine.RepositoryService;
  22 +import org.flowable.engine.repository.Deployment;
  23 +import org.flowable.engine.repository.Model;
  24 +import org.flowable.engine.repository.ModelQuery;
  25 +import org.flowable.engine.repository.ProcessDefinition;
  26 +import org.springframework.stereotype.Service;
  27 +import org.springframework.transaction.annotation.Transactional;
  28 +import org.springframework.util.ObjectUtils;
  29 +import org.springframework.validation.annotation.Validated;
  30 +
  31 +import javax.annotation.Resource;
  32 +import javax.validation.Valid;
  33 +import java.util.*;
  34 +
  35 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  36 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
  37 +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
  38 +
  39 +/**
  40 + * Flowable流程模型实现
  41 + * 主要进行 Flowable {@link Model} 的维护
  42 + *
  43 + * @author yunlongn
  44 + * @author 芋道源码
  45 + * @author jason
  46 + */
  47 +@Service
  48 +@Validated
  49 +@Slf4j
  50 +public class BpmModelServiceImpl implements BpmModelService {
  51 +
  52 + @Resource
  53 + private RepositoryService repositoryService;
  54 + @Resource
  55 + private BpmProcessDefinitionService processDefinitionService;
  56 + @Resource
  57 + private BpmFormService bpmFormService;
  58 + @Resource
  59 + private BpmTaskAssignRuleService taskAssignRuleService;
  60 +
  61 + @Override
  62 + public PageResult<BpmModelPageItemRespVO> getModelPage(BpmModelPageReqVO pageVO) {
  63 + ModelQuery modelQuery = repositoryService.createModelQuery();
  64 + if (StrUtil.isNotBlank(pageVO.getKey())) {
  65 + modelQuery.modelKey(pageVO.getKey());
  66 + }
  67 + if (StrUtil.isNotBlank(pageVO.getName())) {
  68 + modelQuery.modelNameLike("%" + pageVO.getName() + "%"); // 模糊匹配
  69 + }
  70 + if (StrUtil.isNotBlank(pageVO.getCategory())) {
  71 + modelQuery.modelCategory(pageVO.getCategory());
  72 + }
  73 + // 执行查询
  74 + List<Model> models = modelQuery.orderByCreateTime().desc()
  75 + .listPage(PageUtils.getStart(pageVO), pageVO.getPageSize());
  76 +
  77 + // 获得 Form Map
  78 + Set<Long> formIds = CollectionUtils.convertSet(models, model -> {
  79 + BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class);
  80 + return metaInfo != null ? metaInfo.getFormId() : null;
  81 + });
  82 + Map<Long, BpmFormDO> formMap = bpmFormService.getFormMap(formIds);
  83 +
  84 + // 获得 Deployment Map
  85 + Set<String> deploymentIds = new HashSet<>();
  86 + models.forEach(model -> CollectionUtils.addIfNotNull(deploymentIds, model.getDeploymentId()));
  87 + Map<String, Deployment> deploymentMap = processDefinitionService.getDeploymentMap(deploymentIds);
  88 + // 获得 ProcessDefinition Map
  89 + List<ProcessDefinition> processDefinitions = processDefinitionService.getProcessDefinitionListByDeploymentIds(deploymentIds);
  90 + Map<String, ProcessDefinition> processDefinitionMap = convertMap(processDefinitions, ProcessDefinition::getDeploymentId);
  91 +
  92 + // 拼接结果
  93 + long modelCount = modelQuery.count();
  94 + return new PageResult<>(BpmModelConvert.INSTANCE.convertList(models, formMap, deploymentMap, processDefinitionMap), modelCount);
  95 + }
  96 +
  97 + @Override
  98 + @Transactional(rollbackFor = Exception.class)
  99 + public String createModel(@Valid BpmModelCreateReqVO createReqVO, String bpmnXml) {
  100 + checkKeyNCName(createReqVO.getKey());
  101 + // 校验流程标识已经存在
  102 + Model keyModel = this.getModelByKey(createReqVO.getKey());
  103 + if (keyModel != null) {
  104 + throw exception(MODEL_KEY_EXISTS, createReqVO.getKey());
  105 + }
  106 +
  107 + // 创建流程定义
  108 + Model model = repositoryService.newModel();
  109 + BpmModelConvert.INSTANCE.copy(model, createReqVO);
  110 + // 保存流程定义
  111 + repositoryService.saveModel(model);
  112 + // 保存 BPMN XML
  113 + saveModelBpmnXml(model, bpmnXml);
  114 + return model.getId();
  115 + }
  116 +
  117 + private Model getModelByKey(String key) {
  118 + return repositoryService.createModelQuery().modelKey(key).singleResult();
  119 + }
  120 +
  121 + @Override
  122 + public BpmModelRespVO getModel(String id) {
  123 + Model model = repositoryService.getModel(id);
  124 + if (model == null) {
  125 + return null;
  126 + }
  127 + BpmModelRespVO modelRespVO = BpmModelConvert.INSTANCE.convert(model);
  128 + // 拼接 bpmn XML
  129 + byte[] bpmnBytes = repositoryService.getModelEditorSource(id);
  130 + modelRespVO.setBpmnXml(StrUtil.utf8Str(bpmnBytes));
  131 + return modelRespVO;
  132 + }
  133 +
  134 + @Override
  135 + @Transactional(rollbackFor = Exception.class) // 因为进行多个操作,所以开启事务
  136 + public void updateModel(@Valid BpmModelUpdateReqVO updateReqVO) {
  137 + // 校验流程模型存在
  138 + Model model = repositoryService.getModel(updateReqVO.getId());
  139 + if (model == null) {
  140 + throw exception(MODEL_NOT_EXISTS);
  141 + }
  142 +
  143 + // 修改流程定义
  144 + BpmModelConvert.INSTANCE.copy(model, updateReqVO);
  145 + // 更新模型
  146 + repositoryService.saveModel(model);
  147 + // 更新 BPMN XML
  148 + saveModelBpmnXml(model, updateReqVO.getBpmnXml());
  149 + }
  150 +
  151 + @Override
  152 + @Transactional(rollbackFor = Exception.class) // 因为进行多个操作,所以开启事务
  153 + public void deployModel(String id) {
  154 + // 校验流程模型存在
  155 + Model model = repositoryService.getModel(id);
  156 + if (ObjectUtils.isEmpty(model)) {
  157 + throw exception(MODEL_NOT_EXISTS);
  158 + }
  159 + // 校验流程图
  160 + byte[] bpmnBytes = repositoryService.getModelEditorSource(model.getId());
  161 + if (bpmnBytes == null) {
  162 + throw exception(MODEL_NOT_EXISTS);
  163 + }
  164 + // TODO 芋艿:校验流程图的有效性;例如说,是否有开始的元素,是否有结束的元素;
  165 + // 校验表单已配
  166 + BpmFormDO form = checkFormConfig(model.getMetaInfo());
  167 + //校验任务分配规则已配置
  168 + taskAssignRuleService.checkTaskAssignRuleAllConfig(id);
  169 +
  170 + BpmProcessDefinitionCreateReqDTO definitionCreateReqDTO = BpmModelConvert.INSTANCE.convert2(model, form).setBpmnBytes(bpmnBytes);
  171 + //校验模型是否发生修改。如果未修改,则不允许创建
  172 + if (processDefinitionService.isProcessDefinitionEquals(definitionCreateReqDTO)) { // 流程定义的信息相等
  173 + ProcessDefinition oldProcessInstance = processDefinitionService.getProcessDefinitionByDeploymentId(model.getDeploymentId());
  174 + if (oldProcessInstance != null && taskAssignRuleService.isTaskAssignRulesEquals(model.getId(), oldProcessInstance.getId())) {
  175 + throw exception(MODEL_DEPLOY_FAIL_TASK_INFO_EQUALS);
  176 + }
  177 + }
  178 + // 创建流程定义
  179 + String definitionId = processDefinitionService.createProcessDefinition(definitionCreateReqDTO);
  180 +
  181 + // 将老的流程定义进行挂起。也就是说,只有最新部署的流程定义,才可以发起任务。
  182 + updateProcessDefinitionSuspended(model.getDeploymentId());
  183 +
  184 + // 更新 model 的 deploymentId,进行关联
  185 + ProcessDefinition definition = processDefinitionService.getProcessDefinition(definitionId);
  186 + model.setDeploymentId(definition.getDeploymentId());
  187 + repositoryService.saveModel(model);
  188 +
  189 + //复制任务分配规则
  190 + taskAssignRuleService.copyTaskAssignRules(id, definition.getId());
  191 + }
  192 +
  193 +
  194 + @Override
  195 + @Transactional(rollbackFor = Exception.class)
  196 + public void deleteModel(String id) {
  197 + // 校验流程模型存在
  198 + Model model = repositoryService.getModel(id);
  199 + if (model == null) {
  200 + throw exception(MODEL_NOT_EXISTS);
  201 + }
  202 + // 执行删除
  203 + repositoryService.deleteModel(id);
  204 + // 禁用流程实例
  205 + updateProcessDefinitionSuspended(model.getDeploymentId());
  206 + }
  207 +
  208 + @Override
  209 + public void updateModelState(String id, Integer state) {
  210 + // 校验流程模型存在
  211 + Model model = repositoryService.getModel(id);
  212 + if (model == null) {
  213 + throw exception(MODEL_NOT_EXISTS);
  214 + }
  215 + // 校验流程定义存在
  216 + ProcessDefinition definition = processDefinitionService.getProcessDefinitionByDeploymentId(model.getDeploymentId());
  217 + if (definition == null) {
  218 + throw exception(PROCESS_DEFINITION_NOT_EXISTS);
  219 + }
  220 +
  221 + // 更新状态
  222 + processDefinitionService.updateProcessDefinitionState(definition.getId(), state);
  223 + }
  224 +
  225 + @Override
  226 + public BpmnModel getBpmnModel(String id) {
  227 + byte[] bpmnBytes = repositoryService.getModelEditorSource(id);
  228 + if (ArrayUtil.isEmpty(bpmnBytes)) {
  229 + return null;
  230 + }
  231 + BpmnXMLConverter converter = new BpmnXMLConverter();
  232 + return converter.convertToBpmnModel(new BytesStreamSource(bpmnBytes), true, true);
  233 + }
  234 +
  235 + private void checkKeyNCName(String key) {
  236 + if (!ValidationUtils.isXmlNCName(key)) {
  237 + throw exception(MODEL_KEY_VALID);
  238 + }
  239 + }
  240 +
  241 + /**
  242 + * 校验流程表单已配置
  243 + *
  244 + * @param metaInfoStr 流程模型 metaInfo 字段
  245 + * @return 流程表单
  246 + */
  247 + private BpmFormDO checkFormConfig(String metaInfoStr) {
  248 + BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(metaInfoStr, BpmModelMetaInfoRespDTO.class);
  249 + if (metaInfo == null || metaInfo.getFormType() == null) {
  250 + throw exception(MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG);
  251 + }
  252 + // 校验表单存在
  253 + if (Objects.equals(metaInfo.getFormType(), BpmModelFormTypeEnum.NORMAL.getType())) {
  254 + BpmFormDO form = bpmFormService.getForm(metaInfo.getFormId());
  255 + if (form == null) {
  256 + throw exception(FORM_NOT_EXISTS);
  257 + }
  258 + return form;
  259 + }
  260 + return null;
  261 + }
  262 +
  263 + private void saveModelBpmnXml(Model model, String bpmnXml) {
  264 + if (StrUtil.isEmpty(bpmnXml)) {
  265 + return;
  266 + }
  267 + repositoryService.addModelEditorSource(model.getId(), StrUtil.utf8Bytes(bpmnXml));
  268 + }
  269 +
  270 + /**
  271 + * 挂起 deploymentId 对应的流程定义。 这里一个deploymentId 只关联一个流程定义
  272 + * @param deploymentId 流程发布Id.
  273 + */
  274 + private void updateProcessDefinitionSuspended(String deploymentId) {
  275 + if (StrUtil.isEmpty(deploymentId)) {
  276 + return;
  277 + }
  278 + ProcessDefinition oldDefinition = processDefinitionService.getProcessDefinitionByDeploymentId(deploymentId);
  279 + if (oldDefinition == null) {
  280 + return;
  281 + }
  282 + processDefinitionService.updateProcessDefinitionState(oldDefinition.getId(), SuspensionState.SUSPENDED.getStateCode());
  283 + }
  284 +
  285 +
  286 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.definition;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  5 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO;
  6 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
  7 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO;
  8 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
  9 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
  10 +import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
  11 +import org.flowable.bpmn.model.BpmnModel;
  12 +import org.flowable.engine.repository.Deployment;
  13 +import org.flowable.engine.repository.ProcessDefinition;
  14 +
  15 +import javax.validation.Valid;
  16 +import java.util.List;
  17 +import java.util.Map;
  18 +import java.util.Set;
  19 +/**
  20 + * Flowable流程定义接口
  21 + *
  22 + * @author yunlong.li
  23 + * @author ZJQ
  24 + * @author 芋道源码
  25 + */
  26 +public interface BpmProcessDefinitionService {
  27 +
  28 + /**
  29 + * 获得流程定义分页
  30 + *
  31 + * @param pageReqVO 分页入参
  32 + * @return 流程定义 Page
  33 + */
  34 + PageResult<BpmProcessDefinitionPageItemRespVO> getProcessDefinitionPage(BpmProcessDefinitionPageReqVO pageReqVO);
  35 +
  36 + /**
  37 + * 获得流程定义列表
  38 + *
  39 + * @param listReqVO 列表入参
  40 + * @return 流程定义列表
  41 + */
  42 + List<BpmProcessDefinitionRespVO> getProcessDefinitionList(BpmProcessDefinitionListReqVO listReqVO);
  43 +
  44 + /**
  45 + * 创建流程定义
  46 + *
  47 + * @param createReqDTO 创建信息
  48 + * @return 流程编号
  49 + */
  50 + String createProcessDefinition(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO);
  51 +
  52 + /**
  53 + * 更新流程定义状态
  54 + *
  55 + * @param id 流程定义的编号
  56 + * @param state 状态
  57 + */
  58 + void updateProcessDefinitionState(String id, Integer state);
  59 +
  60 + /**
  61 + * 获得流程定义对应的 BPMN XML
  62 + *
  63 + * @param id 流程定义编号
  64 + * @return BPMN XML
  65 + */
  66 + String getProcessDefinitionBpmnXML(String id);
  67 +
  68 + /**
  69 + * 获得需要创建的流程定义,是否和当前激活的流程定义相等
  70 + *
  71 + * @param createReqDTO 创建信息
  72 + * @return 是否相等
  73 + */
  74 + boolean isProcessDefinitionEquals(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO);
  75 +
  76 + /**
  77 + * 获得编号对应的 BpmProcessDefinitionExtDO
  78 + *
  79 + * @param id 编号
  80 + * @return 流程定义拓展
  81 + */
  82 + BpmProcessDefinitionExtDO getProcessDefinitionExt(String id);
  83 +
  84 + /**
  85 + * 获得编号对应的 ProcessDefinition
  86 + *
  87 + * @param id 编号
  88 + * @return 流程定义
  89 + */
  90 + ProcessDefinition getProcessDefinition(String id);
  91 +
  92 + /**
  93 + * 获得编号对应的 ProcessDefinition
  94 + *
  95 + * 相比 {@link #getProcessDefinition(String)} 方法,category 的取值是正确
  96 + *
  97 + * @param id 编号
  98 + * @return 流程定义
  99 + */
  100 + ProcessDefinition getProcessDefinition2(String id);
  101 +
  102 + /**
  103 + * 获得 deploymentId 对应的 ProcessDefinition
  104 + *
  105 + * @param deploymentId 部署编号
  106 + * @return 流程定义
  107 + */
  108 + ProcessDefinition getProcessDefinitionByDeploymentId(String deploymentId);
  109 +
  110 + /**
  111 + * 获得 deploymentIds 对应的 ProcessDefinition 数组
  112 + *
  113 + * @param deploymentIds 部署编号的数组
  114 + * @return 流程定义的数组
  115 + */
  116 + List<ProcessDefinition> getProcessDefinitionListByDeploymentIds(Set<String> deploymentIds);
  117 +
  118 + /**
  119 + * 获得流程定义标识对应的激活的流程定义
  120 + *
  121 + * @param key 流程定义的标识
  122 + * @return 流程定义
  123 + */
  124 + ProcessDefinition getActiveProcessDefinition(String key);
  125 +
  126 + /**
  127 + * 获得 ids 对应的 Deployment Map
  128 + *
  129 + * @param ids 部署编号的数组
  130 + * @return 流程部署 Map
  131 + */
  132 + default Map<String, Deployment> getDeploymentMap(Set<String> ids) {
  133 + return CollectionUtils.convertMap(getDeployments(ids), Deployment::getId);
  134 + }
  135 +
  136 + /**
  137 + * 获得 ids 对应的 Deployment 数组
  138 + *
  139 + * @param ids 部署编号的数组
  140 + * @return 流程部署的数组
  141 + */
  142 + List<Deployment> getDeployments(Set<String> ids);
  143 +
  144 + /**
  145 + * 获得 id 对应的 Deployment
  146 + *
  147 + * @param id 部署编号
  148 + * @return 流程部署
  149 + */
  150 + Deployment getDeployment(String id);
  151 +
  152 + /**
  153 + * 获得 Bpmn 模型
  154 + *
  155 + * @param processDefinitionId 流程定义的编号
  156 + * @return Bpmn 模型
  157 + */
  158 + BpmnModel getBpmnModel(String processDefinitionId);
  159 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.definition;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.ObjectUtil;
  5 +import cn.hutool.core.util.StrUtil;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  7 +import cn.iocoder.yudao.framework.common.util.object.PageUtils;
  8 +import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils;
  9 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO;
  10 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
  11 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO;
  12 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
  13 +import cn.iocoder.yudao.module.bpm.convert.definition.BpmProcessDefinitionConvert;
  14 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
  15 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
  16 +import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmProcessDefinitionExtMapper;
  17 +import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
  18 +import lombok.extern.slf4j.Slf4j;
  19 +import org.flowable.bpmn.converter.BpmnXMLConverter;
  20 +import org.flowable.bpmn.model.BpmnModel;
  21 +import org.flowable.common.engine.impl.db.SuspensionState;
  22 +import org.flowable.common.engine.impl.util.io.BytesStreamSource;
  23 +import org.flowable.engine.RepositoryService;
  24 +import org.flowable.engine.repository.Deployment;
  25 +import org.flowable.engine.repository.ProcessDefinition;
  26 +import org.flowable.engine.repository.ProcessDefinitionQuery;
  27 +import org.springframework.stereotype.Service;
  28 +import org.springframework.validation.annotation.Validated;
  29 +
  30 +import javax.annotation.Resource;
  31 +import javax.validation.Valid;
  32 +import java.util.*;
  33 +
  34 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  35 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
  36 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
  37 +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_DEFINITION_KEY_NOT_MATCH;
  38 +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_DEFINITION_NAME_NOT_MATCH;
  39 +import static java.util.Collections.emptyList;
  40 +
  41 +/**
  42 + * 流程定义实现
  43 + * 主要进行 Flowable {@link ProcessDefinition} 和 {@link Deployment} 的维护
  44 + *
  45 + * @author yunlongn
  46 + * @author ZJQ
  47 + * @author 芋道源码
  48 + */
  49 +@Service
  50 +@Validated
  51 +@Slf4j
  52 +public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionService {
  53 +
  54 + private static final String BPMN_FILE_SUFFIX = ".bpmn";
  55 +
  56 + @Resource
  57 + private RepositoryService repositoryService;
  58 +
  59 + @Resource
  60 + private BpmProcessDefinitionExtMapper processDefinitionMapper;
  61 +
  62 + @Resource
  63 + private BpmFormService formService;
  64 +
  65 + @Override
  66 + public ProcessDefinition getProcessDefinition(String id) {
  67 + return repositoryService.getProcessDefinition(id);
  68 + }
  69 +
  70 + @Override
  71 + public ProcessDefinition getProcessDefinition2(String id) {
  72 + return repositoryService.createProcessDefinitionQuery().processDefinitionId(id).singleResult();
  73 + }
  74 +
  75 + @Override
  76 + public ProcessDefinition getProcessDefinitionByDeploymentId(String deploymentId) {
  77 + if (StrUtil.isEmpty(deploymentId)) {
  78 + return null;
  79 + }
  80 + return repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
  81 + }
  82 +
  83 + @Override
  84 + public List<ProcessDefinition> getProcessDefinitionListByDeploymentIds(Set<String> deploymentIds) {
  85 + if (CollUtil.isEmpty(deploymentIds)) {
  86 + return emptyList();
  87 + }
  88 + return repositoryService.createProcessDefinitionQuery().deploymentIds(deploymentIds).list();
  89 + }
  90 +
  91 + @Override
  92 + public ProcessDefinition getActiveProcessDefinition(String key) {
  93 + return repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).active().singleResult();
  94 + }
  95 +
  96 + @Override
  97 + public List<Deployment> getDeployments(Set<String> ids) {
  98 + if (CollUtil.isEmpty(ids)) {
  99 + return emptyList();
  100 + }
  101 + List<Deployment> list = new ArrayList<>(ids.size());
  102 + for (String id : ids) {
  103 + addIfNotNull(list, getDeployment(id));
  104 + }
  105 + return list;
  106 + }
  107 +
  108 + @Override
  109 + public Deployment getDeployment(String id) {
  110 + if (StrUtil.isEmpty(id)) {
  111 + return null;
  112 + }
  113 + return repositoryService.createDeploymentQuery().deploymentId(id).singleResult();
  114 + }
  115 +
  116 + @Override
  117 + public BpmnModel getBpmnModel(String processDefinitionId) {
  118 + return repositoryService.getBpmnModel(processDefinitionId);
  119 + }
  120 +
  121 + @Override
  122 + public String createProcessDefinition(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO) {
  123 + // 创建 Deployment 部署
  124 + Deployment deploy = repositoryService.createDeployment()
  125 + .key(createReqDTO.getKey()).name(createReqDTO.getName()).category(createReqDTO.getCategory())
  126 + .addBytes(createReqDTO.getKey() + BPMN_FILE_SUFFIX, createReqDTO.getBpmnBytes())
  127 + .deploy();
  128 +
  129 + // 设置 ProcessDefinition 的 category 分类
  130 + ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deploy.getId()).singleResult();
  131 + repositoryService.setProcessDefinitionCategory(definition.getId(), createReqDTO.getCategory());
  132 + // 注意 1,ProcessDefinition 的 key 和 name 是通过 BPMN 中的 <bpmn2:process /> 的 id 和 name 决定
  133 + // 注意 2,目前该项目的设计上,需要保证 Model、Deployment、ProcessDefinition 使用相同的 key,保证关联性。
  134 + // 否则,会导致 ProcessDefinition 的分页无法查询到。
  135 + if (!Objects.equals(definition.getKey(), createReqDTO.getKey())) {
  136 + throw exception(PROCESS_DEFINITION_KEY_NOT_MATCH, createReqDTO.getKey(), definition.getKey());
  137 + }
  138 + if (!Objects.equals(definition.getName(), createReqDTO.getName())) {
  139 + throw exception(PROCESS_DEFINITION_NAME_NOT_MATCH, createReqDTO.getName(), definition.getName());
  140 + }
  141 +
  142 + // 插入拓展表
  143 + BpmProcessDefinitionExtDO definitionDO = BpmProcessDefinitionConvert.INSTANCE.convert2(createReqDTO)
  144 + .setProcessDefinitionId(definition.getId());
  145 + processDefinitionMapper.insert(definitionDO);
  146 + return definition.getId();
  147 + }
  148 +
  149 + @Override
  150 + public void updateProcessDefinitionState(String id, Integer state) {
  151 + // 激活
  152 + if (Objects.equals(SuspensionState.ACTIVE.getStateCode(), state)) {
  153 + repositoryService.activateProcessDefinitionById(id, false, null);
  154 + return;
  155 + }
  156 + // 挂起
  157 + if (Objects.equals(SuspensionState.SUSPENDED.getStateCode(), state)) {
  158 + // suspendProcessInstances = false,进行中的任务,不进行挂起。
  159 + // 原因:只要新的流程不允许发起即可,老流程继续可以执行。
  160 + repositoryService.suspendProcessDefinitionById(id, false, null);
  161 + return;
  162 + }
  163 + log.error("[updateProcessDefinitionState][流程定义({}) 修改未知状态({})]", id, state);
  164 + }
  165 +
  166 + @Override
  167 + public String getProcessDefinitionBpmnXML(String id) {
  168 + BpmnModel bpmnModel = repositoryService.getBpmnModel(id);
  169 + if (bpmnModel == null) {
  170 + return null;
  171 + }
  172 + BpmnXMLConverter converter = new BpmnXMLConverter();
  173 + return StrUtil.utf8Str(converter.convertToXML(bpmnModel));
  174 + }
  175 +
  176 + @Override
  177 + public boolean isProcessDefinitionEquals(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO) {
  178 + // 校验 name、description 是否更新
  179 + ProcessDefinition oldProcessDefinition = getActiveProcessDefinition(createReqDTO.getKey());
  180 + if (oldProcessDefinition == null) {
  181 + return false;
  182 + }
  183 + BpmProcessDefinitionExtDO oldProcessDefinitionExt = getProcessDefinitionExt(oldProcessDefinition.getId());
  184 + if (!StrUtil.equals(createReqDTO.getName(), oldProcessDefinition.getName())
  185 + || !StrUtil.equals(createReqDTO.getDescription(), oldProcessDefinitionExt.getDescription())
  186 + || !StrUtil.equals(createReqDTO.getCategory(), oldProcessDefinition.getCategory())) {
  187 + return false;
  188 + }
  189 + // 校验 form 信息是否更新
  190 + if (!ObjectUtil.equal(createReqDTO.getFormType(), oldProcessDefinitionExt.getFormType())
  191 + || !ObjectUtil.equal(createReqDTO.getFormId(), oldProcessDefinitionExt.getFormId())
  192 + || !ObjectUtil.equal(createReqDTO.getFormConf(), oldProcessDefinitionExt.getFormConf())
  193 + || !ObjectUtil.equal(createReqDTO.getFormFields(), oldProcessDefinitionExt.getFormFields())
  194 + || !ObjectUtil.equal(createReqDTO.getFormCustomCreatePath(), oldProcessDefinitionExt.getFormCustomCreatePath())
  195 + || !ObjectUtil.equal(createReqDTO.getFormCustomViewPath(), oldProcessDefinitionExt.getFormCustomViewPath())) {
  196 + return false;
  197 + }
  198 + // 校验 BPMN XML 信息
  199 + BpmnModel newModel = buildBpmnModel(createReqDTO.getBpmnBytes());
  200 + BpmnModel oldModel = getBpmnModel(oldProcessDefinition.getId());
  201 + //TODO 貌似 flowable 不修改这个也不同。需要看看。 sourceSystemId 不同
  202 + if (FlowableUtils.equals(oldModel, newModel)) {
  203 + return false;
  204 + }
  205 + // 最终发现都一致,则返回 true
  206 + return true;
  207 + }
  208 +
  209 + /**
  210 + * 构建对应的 BPMN Model
  211 + *
  212 + * @param bpmnBytes 原始的 BPMN XML 字节数组
  213 + * @return BPMN Model
  214 + */
  215 + private BpmnModel buildBpmnModel(byte[] bpmnBytes) {
  216 + // 转换成 BpmnModel 对象
  217 + BpmnXMLConverter converter = new BpmnXMLConverter();
  218 + return converter.convertToBpmnModel(new BytesStreamSource(bpmnBytes), true, true);
  219 + }
  220 +
  221 +
  222 +
  223 + @Override
  224 + public BpmProcessDefinitionExtDO getProcessDefinitionExt(String id) {
  225 + return processDefinitionMapper.selectByProcessDefinitionId(id);
  226 + }
  227 +
  228 + @Override
  229 + public List<BpmProcessDefinitionRespVO> getProcessDefinitionList(BpmProcessDefinitionListReqVO listReqVO) {
  230 + // 拼接查询条件
  231 + ProcessDefinitionQuery definitionQuery = repositoryService.createProcessDefinitionQuery();
  232 + if (Objects.equals(SuspensionState.SUSPENDED.getStateCode(), listReqVO.getSuspensionState())) {
  233 + definitionQuery.suspended();
  234 + } else if (Objects.equals(SuspensionState.ACTIVE.getStateCode(), listReqVO.getSuspensionState())) {
  235 + definitionQuery.active();
  236 + }
  237 + // 执行查询
  238 + List<ProcessDefinition> processDefinitions = definitionQuery.list();
  239 + if (CollUtil.isEmpty(processDefinitions)) {
  240 + return Collections.emptyList();
  241 + }
  242 +
  243 + // 获得 BpmProcessDefinitionDO Map
  244 + List<BpmProcessDefinitionExtDO> processDefinitionDOs = processDefinitionMapper.selectListByProcessDefinitionIds(
  245 + convertList(processDefinitions, ProcessDefinition::getId));
  246 + Map<String, BpmProcessDefinitionExtDO> processDefinitionDOMap = convertMap(processDefinitionDOs,
  247 + BpmProcessDefinitionExtDO::getProcessDefinitionId);
  248 + // 执行查询,并返回
  249 + return BpmProcessDefinitionConvert.INSTANCE.convertList3(processDefinitions, processDefinitionDOMap);
  250 + }
  251 +
  252 + @Override
  253 + public PageResult<BpmProcessDefinitionPageItemRespVO> getProcessDefinitionPage(BpmProcessDefinitionPageReqVO pageVO) {
  254 + ProcessDefinitionQuery definitionQuery = repositoryService.createProcessDefinitionQuery();
  255 + if (StrUtil.isNotBlank(pageVO.getKey())) {
  256 + definitionQuery.processDefinitionKey(pageVO.getKey());
  257 + }
  258 +
  259 + // 执行查询
  260 + List<ProcessDefinition> processDefinitions = definitionQuery.orderByProcessDefinitionVersion().desc()
  261 + .listPage(PageUtils.getStart(pageVO), pageVO.getPageSize());
  262 +
  263 + if (CollUtil.isEmpty(processDefinitions)) {
  264 + return new PageResult<>(emptyList(), definitionQuery.count());
  265 + }
  266 + // 获得 Deployment Map
  267 + Set<String> deploymentIds = new HashSet<>();
  268 + processDefinitions.forEach(definition -> addIfNotNull(deploymentIds, definition.getDeploymentId()));
  269 + Map<String, Deployment> deploymentMap = getDeploymentMap(deploymentIds);
  270 +
  271 + // 获得 BpmProcessDefinitionDO Map
  272 + List<BpmProcessDefinitionExtDO> processDefinitionDOs = processDefinitionMapper.selectListByProcessDefinitionIds(
  273 + convertList(processDefinitions, ProcessDefinition::getId));
  274 + Map<String, BpmProcessDefinitionExtDO> processDefinitionDOMap = convertMap(processDefinitionDOs,
  275 + BpmProcessDefinitionExtDO::getProcessDefinitionId);
  276 +
  277 + // 获得 Form Map
  278 + Set<Long> formIds = convertSet(processDefinitionDOs, BpmProcessDefinitionExtDO::getFormId);
  279 + Map<Long, BpmFormDO> formMap = formService.getFormMap(formIds);
  280 +
  281 + // 拼接结果
  282 + long definitionCount = definitionQuery.count();
  283 + return new PageResult<>(BpmProcessDefinitionConvert.INSTANCE.convertList(processDefinitions, deploymentMap,
  284 + processDefinitionDOMap, formMap), definitionCount);
  285 + }
  286 +
  287 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.definition;
  2 +
  3 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleCreateReqVO;
  4 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO;
  5 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO;
  6 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
  7 +import org.springframework.lang.Nullable;
  8 +
  9 +import javax.validation.Valid;
  10 +import java.util.List;
  11 +
  12 +/**
  13 + * BPM 任务分配规则 Service 接口
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +public interface BpmTaskAssignRuleService {
  18 +
  19 + /**
  20 + * 获得流程定义的任务分配规则数组
  21 + *
  22 + * @param processDefinitionId 流程定义的编号
  23 + * @param taskDefinitionKey 流程任务定义的 Key。允许空
  24 + * @return 任务规则数组
  25 + */
  26 + List<BpmTaskAssignRuleDO> getTaskAssignRuleListByProcessDefinitionId(String processDefinitionId,
  27 + @Nullable String taskDefinitionKey);
  28 +
  29 + /**
  30 + * 获得流程模型的任务规则数组
  31 + *
  32 + * @param modelId 流程模型的编号
  33 + * @return 任务规则数组
  34 + */
  35 + List<BpmTaskAssignRuleDO> getTaskAssignRuleListByModelId(String modelId);
  36 +
  37 + /**
  38 + * 获得流程定义的任务分配规则数组
  39 + *
  40 + * @param modelId 流程模型的编号
  41 + * @param processDefinitionId 流程定义的编号
  42 + * @return 任务规则数组
  43 + */
  44 + List<BpmTaskAssignRuleRespVO> getTaskAssignRuleList(String modelId, String processDefinitionId);
  45 +
  46 + /**
  47 + * 创建任务分配规则
  48 + *
  49 + * @param reqVO 创建信息
  50 + * @return 规则编号
  51 + */
  52 + Long createTaskAssignRule(@Valid BpmTaskAssignRuleCreateReqVO reqVO);
  53 +
  54 + /**
  55 + * 更新任务分配规则
  56 + *
  57 + * @param reqVO 创建信息
  58 + */
  59 + void updateTaskAssignRule(@Valid BpmTaskAssignRuleUpdateReqVO reqVO);
  60 +
  61 + /**
  62 + * 判断指定流程模型和流程定义的分配规则是否相等
  63 + *
  64 + * @param modelId 流程模型编号
  65 + * @param processDefinitionId 流程定义编号
  66 + * @return 是否相等
  67 + */
  68 + boolean isTaskAssignRulesEquals(String modelId, String processDefinitionId);
  69 +
  70 + /**
  71 + * 将流程流程模型的任务分配规则,复制一份给流程定义
  72 + * 目的:每次流程模型部署时,都会生成一个新的流程定义,此时考虑到每次部署的流程不可变性,所以需要复制一份给该流程定义
  73 + *
  74 + * @param fromModelId 流程模型编号
  75 + * @param toProcessDefinitionId 流程定义编号
  76 + */
  77 + void copyTaskAssignRules(String fromModelId, String toProcessDefinitionId);
  78 +
  79 + /**
  80 + * 校验流程模型的任务分配规则全部都配置了
  81 + * 目的:如果有规则未配置,会导致流程任务找不到负责人,进而流程无法进行下去!
  82 + *
  83 + * @param id 流程模型编号
  84 + */
  85 + void checkTaskAssignRuleAllConfig(String id);
  86 +
  87 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.definition;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.ObjectUtil;
  5 +import cn.hutool.core.util.StrUtil;
  6 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  7 +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
  8 +import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils;
  9 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleCreateReqVO;
  10 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO;
  11 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO;
  12 +import cn.iocoder.yudao.module.bpm.convert.definition.BpmTaskAssignRuleConvert;
  13 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
  14 +import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper;
  15 +import cn.iocoder.yudao.module.bpm.enums.DictTypeConstants;
  16 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
  17 +import cn.iocoder.yudao.module.system.api.dept.DeptApi;
  18 +import cn.iocoder.yudao.module.system.api.dept.PostApi;
  19 +import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
  20 +import cn.iocoder.yudao.module.system.api.permission.RoleApi;
  21 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  22 +import lombok.extern.slf4j.Slf4j;
  23 +import org.flowable.bpmn.model.BpmnModel;
  24 +import org.flowable.bpmn.model.UserTask;
  25 +import org.springframework.context.annotation.Lazy;
  26 +import org.springframework.stereotype.Service;
  27 +import org.springframework.validation.annotation.Validated;
  28 +
  29 +import javax.annotation.Resource;
  30 +import javax.validation.Valid;
  31 +import java.util.*;
  32 +
  33 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  34 +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
  35 +
  36 +/**
  37 + * BPM 任务分配规则 Service 实现类
  38 + */
  39 +@Service
  40 +@Validated
  41 +@Slf4j
  42 +public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService{
  43 +
  44 + @Resource
  45 + private BpmTaskAssignRuleMapper taskRuleMapper;
  46 + @Resource
  47 + @Lazy // 解决循环依赖
  48 + private BpmModelService modelService;
  49 + @Resource
  50 + @Lazy // 解决循环依赖
  51 + private BpmProcessDefinitionService processDefinitionService;
  52 + @Resource
  53 + private BpmUserGroupService userGroupService;
  54 + @Resource
  55 + private RoleApi roleApi;
  56 + @Resource
  57 + private DeptApi deptApi;
  58 + @Resource
  59 + private PostApi postApi;
  60 + @Resource
  61 + private AdminUserApi adminUserApi;
  62 + @Resource
  63 + private DictDataApi dictDataApi;
  64 +
  65 + @Override
  66 + public List<BpmTaskAssignRuleDO> getTaskAssignRuleListByProcessDefinitionId(String processDefinitionId, String taskDefinitionKey) {
  67 + return taskRuleMapper.selectListByProcessDefinitionId(processDefinitionId, taskDefinitionKey);
  68 + }
  69 +
  70 + @Override
  71 + public List<BpmTaskAssignRuleDO> getTaskAssignRuleListByModelId(String modelId) {
  72 + return taskRuleMapper.selectListByModelId(modelId);
  73 + }
  74 +
  75 + @Override
  76 + public List<BpmTaskAssignRuleRespVO> getTaskAssignRuleList(String modelId, String processDefinitionId) {
  77 + // 获得规则
  78 + List<BpmTaskAssignRuleDO> rules = Collections.emptyList();
  79 + BpmnModel model = null;
  80 + if (StrUtil.isNotEmpty(modelId)) {
  81 + rules = getTaskAssignRuleListByModelId(modelId);
  82 + model = modelService.getBpmnModel(modelId);
  83 + } else if (StrUtil.isNotEmpty(processDefinitionId)) {
  84 + rules = getTaskAssignRuleListByProcessDefinitionId(processDefinitionId, null);
  85 + model = processDefinitionService.getBpmnModel(processDefinitionId);
  86 + }
  87 + if (model == null) {
  88 + return Collections.emptyList();
  89 + }
  90 + // 获得用户任务,只有用户任务才可以设置分配规则
  91 + List<UserTask> userTasks = FlowableUtils.getBpmnModelElements(model, UserTask.class);
  92 + if (CollUtil.isEmpty(userTasks)) {
  93 + return Collections.emptyList();
  94 + }
  95 + // 转换数据
  96 + return BpmTaskAssignRuleConvert.INSTANCE.convertList(userTasks, rules);
  97 + }
  98 +
  99 + @Override
  100 + public Long createTaskAssignRule(@Valid BpmTaskAssignRuleCreateReqVO reqVO) {
  101 + // 校验参数
  102 + validTaskAssignRuleOptions(reqVO.getType(), reqVO.getOptions());
  103 + // 校验是否已经配置
  104 + BpmTaskAssignRuleDO existRule = taskRuleMapper.selectListByModelIdAndTaskDefinitionKey(
  105 + reqVO.getModelId(), reqVO.getTaskDefinitionKey());
  106 + if (existRule != null) {
  107 + throw exception(TASK_ASSIGN_RULE_EXISTS, reqVO.getModelId(), reqVO.getTaskDefinitionKey());
  108 + }
  109 +
  110 + // 存储
  111 + BpmTaskAssignRuleDO rule = BpmTaskAssignRuleConvert.INSTANCE.convert(reqVO)
  112 + .setProcessDefinitionId(BpmTaskAssignRuleDO.PROCESS_DEFINITION_ID_NULL); // 只有流程模型,才允许新建
  113 + taskRuleMapper.insert(rule);
  114 + return rule.getId();
  115 + }
  116 +
  117 + @Override
  118 + public void updateTaskAssignRule(@Valid BpmTaskAssignRuleUpdateReqVO reqVO) {
  119 + // 校验参数
  120 + validTaskAssignRuleOptions(reqVO.getType(), reqVO.getOptions());
  121 + // 校验是否存在
  122 + BpmTaskAssignRuleDO existRule = taskRuleMapper.selectById(reqVO.getId());
  123 + if (existRule == null) {
  124 + throw exception(TASK_ASSIGN_RULE_NOT_EXISTS);
  125 + }
  126 + // 只允许修改流程模型的规则
  127 + if (!Objects.equals(BpmTaskAssignRuleDO.PROCESS_DEFINITION_ID_NULL, existRule.getProcessDefinitionId())) {
  128 + throw exception(TASK_UPDATE_FAIL_NOT_MODEL);
  129 + }
  130 +
  131 + // 执行更新
  132 + taskRuleMapper.updateById(BpmTaskAssignRuleConvert.INSTANCE.convert(reqVO));
  133 + }
  134 +
  135 + @Override
  136 + public boolean isTaskAssignRulesEquals(String modelId, String processDefinitionId) {
  137 + // 调用 VO 接口的原因是,过滤掉流程模型不需要的规则,保持和 copyTaskAssignRules 方法的一致性
  138 + List<BpmTaskAssignRuleRespVO> modelRules = getTaskAssignRuleList(modelId, null);
  139 + List<BpmTaskAssignRuleRespVO> processInstanceRules = getTaskAssignRuleList(null, processDefinitionId);
  140 + if (modelRules.size() != processInstanceRules.size()) {
  141 + return false;
  142 + }
  143 +
  144 + // 遍历,匹配对应的规则
  145 + Map<String, BpmTaskAssignRuleRespVO> processInstanceRuleMap = CollectionUtils.convertMap(processInstanceRules,
  146 + BpmTaskAssignRuleRespVO::getTaskDefinitionKey);
  147 + for (BpmTaskAssignRuleRespVO modelRule : modelRules) {
  148 + BpmTaskAssignRuleRespVO processInstanceRule = processInstanceRuleMap.get(modelRule.getTaskDefinitionKey());
  149 + if (processInstanceRule == null) {
  150 + return false;
  151 + }
  152 + if (!ObjectUtil.equals(modelRule.getType(), processInstanceRule.getType())
  153 + || !ObjectUtil.equal(modelRule.getOptions(), processInstanceRule.getOptions())) {
  154 + return false;
  155 + }
  156 + }
  157 + return true;
  158 + }
  159 +
  160 + @Override
  161 + public void copyTaskAssignRules(String fromModelId, String toProcessDefinitionId) {
  162 + List<BpmTaskAssignRuleRespVO> rules = getTaskAssignRuleList(fromModelId, null);
  163 + if (CollUtil.isEmpty(rules)) {
  164 + return;
  165 + }
  166 + // 开始复制
  167 + List<BpmTaskAssignRuleDO> newRules = BpmTaskAssignRuleConvert.INSTANCE.convertList2(rules);
  168 + newRules.forEach(rule -> rule.setProcessDefinitionId(toProcessDefinitionId).setId(null)
  169 + .setCreateTime(null).setUpdateTime(null));
  170 + taskRuleMapper.insertBatch(newRules);
  171 + }
  172 +
  173 + @Override
  174 + public void checkTaskAssignRuleAllConfig(String id) {
  175 + // 一个用户任务都没配置,所以无需配置规则
  176 + List<BpmTaskAssignRuleRespVO> taskAssignRules = getTaskAssignRuleList(id, null);
  177 + if (CollUtil.isEmpty(taskAssignRules)) {
  178 + return;
  179 + }
  180 + // 校验未配置规则的任务
  181 + taskAssignRules.forEach(rule -> {
  182 + if (CollUtil.isEmpty(rule.getOptions())) {
  183 + throw exception(MODEL_DEPLOY_FAIL_TASK_ASSIGN_RULE_NOT_CONFIG, rule.getTaskDefinitionName());
  184 + }
  185 + });
  186 + }
  187 +
  188 + private void validTaskAssignRuleOptions(Integer type, Set<Long> options) {
  189 + if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.ROLE.getType())) {
  190 + roleApi.validRoles(options);
  191 + } else if (ObjectUtils.equalsAny(type, BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType(),
  192 + BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType())) {
  193 + deptApi.validDepts(options);
  194 + } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.POST.getType())) {
  195 + postApi.validPosts(options);
  196 + } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.USER.getType())) {
  197 + adminUserApi.validUsers(options);
  198 + } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.USER_GROUP.getType())) {
  199 + userGroupService.validUserGroups(options);
  200 + } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.SCRIPT.getType())) {
  201 + dictDataApi.validDictDatas(DictTypeConstants.TASK_ASSIGN_SCRIPT,
  202 + CollectionUtils.convertSet(options, String::valueOf));
  203 + } else {
  204 + throw new IllegalArgumentException(StrUtil.format("未知的规则类型({})", type));
  205 + }
  206 + }
  207 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.definition;
  2 +
  3 +import java.util.*;
  4 +import javax.validation.*;
  5 +
  6 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupCreateReqVO;
  7 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupPageReqVO;
  8 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupUpdateReqVO;
  9 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
  10 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  11 +
  12 +/**
  13 + * 用户组 Service 接口
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +public interface BpmUserGroupService {
  18 +
  19 + /**
  20 + * 创建用户组
  21 + *
  22 + * @param createReqVO 创建信息
  23 + * @return 编号
  24 + */
  25 + Long createUserGroup(@Valid BpmUserGroupCreateReqVO createReqVO);
  26 +
  27 + /**
  28 + * 更新用户组
  29 + *
  30 + * @param updateReqVO 更新信息
  31 + */
  32 + void updateUserGroup(@Valid BpmUserGroupUpdateReqVO updateReqVO);
  33 +
  34 + /**
  35 + * 删除用户组
  36 + *
  37 + * @param id 编号
  38 + */
  39 + void deleteUserGroup(Long id);
  40 +
  41 + /**
  42 + * 获得用户组
  43 + *
  44 + * @param id 编号
  45 + * @return 用户组
  46 + */
  47 + BpmUserGroupDO getUserGroup(Long id);
  48 +
  49 + /**
  50 + * 获得用户组列表
  51 + *
  52 + * @param ids 编号
  53 + * @return 用户组列表
  54 + */
  55 + List<BpmUserGroupDO> getUserGroupList(Collection<Long> ids);
  56 +
  57 + /**
  58 + * 获得指定状态的用户组列表
  59 + *
  60 + * @param status 状态
  61 + * @return 用户组列表
  62 + */
  63 + List<BpmUserGroupDO> getUserGroupListByStatus(Integer status);
  64 +
  65 + /**
  66 + * 获得用户组分页
  67 + *
  68 + * @param pageReqVO 分页查询
  69 + * @return 用户组分页
  70 + */
  71 + PageResult<BpmUserGroupDO> getUserGroupPage(BpmUserGroupPageReqVO pageReqVO);
  72 +
  73 + /**
  74 + * 校验用户组们是否有效。如下情况,视为无效:
  75 + * 1. 用户组编号不存在
  76 + * 2. 用户组被禁用
  77 + *
  78 + * @param ids 用户组编号数组
  79 + */
  80 + void validUserGroups(Set<Long> ids);
  81 +
  82 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.definition;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupCreateReqVO;
  5 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupPageReqVO;
  6 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupUpdateReqVO;
  7 +import cn.iocoder.yudao.module.bpm.convert.definition.BpmUserGroupConvert;
  8 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
  9 +import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmUserGroupMapper;
  10 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  11 +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
  12 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  13 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  14 +import org.springframework.stereotype.Service;
  15 +import org.springframework.validation.annotation.Validated;
  16 +
  17 +import javax.annotation.Resource;
  18 +import java.util.Collection;
  19 +import java.util.List;
  20 +import java.util.Map;
  21 +import java.util.Set;
  22 +
  23 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  24 +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
  25 +
  26 +/**
  27 + * 用户组 Service 实现类
  28 + *
  29 + * @author 芋道源码
  30 + */
  31 +@Service
  32 +@Validated
  33 +public class BpmUserGroupServiceImpl implements BpmUserGroupService {
  34 +
  35 + @Resource
  36 + private BpmUserGroupMapper userGroupMapper;
  37 +
  38 + @Override
  39 + public Long createUserGroup(BpmUserGroupCreateReqVO createReqVO) {
  40 + // 插入
  41 + BpmUserGroupDO userGroup = BpmUserGroupConvert.INSTANCE.convert(createReqVO);
  42 + userGroupMapper.insert(userGroup);
  43 + // 返回
  44 + return userGroup.getId();
  45 + }
  46 +
  47 + @Override
  48 + public void updateUserGroup(BpmUserGroupUpdateReqVO updateReqVO) {
  49 + // 校验存在
  50 + this.validateUserGroupExists(updateReqVO.getId());
  51 + // 更新
  52 + BpmUserGroupDO updateObj = BpmUserGroupConvert.INSTANCE.convert(updateReqVO);
  53 + userGroupMapper.updateById(updateObj);
  54 + }
  55 +
  56 + @Override
  57 + public void deleteUserGroup(Long id) {
  58 + // 校验存在
  59 + this.validateUserGroupExists(id);
  60 + // 删除
  61 + userGroupMapper.deleteById(id);
  62 + }
  63 +
  64 + private void validateUserGroupExists(Long id) {
  65 + if (userGroupMapper.selectById(id) == null) {
  66 + throw ServiceExceptionUtil.exception(USER_GROUP_NOT_EXISTS);
  67 + }
  68 + }
  69 +
  70 + @Override
  71 + public BpmUserGroupDO getUserGroup(Long id) {
  72 + return userGroupMapper.selectById(id);
  73 + }
  74 +
  75 + @Override
  76 + public List<BpmUserGroupDO> getUserGroupList(Collection<Long> ids) {
  77 + return userGroupMapper.selectBatchIds(ids);
  78 + }
  79 +
  80 +
  81 + @Override
  82 + public List<BpmUserGroupDO> getUserGroupListByStatus(Integer status) {
  83 + return userGroupMapper.selectListByStatus(status);
  84 + }
  85 +
  86 + @Override
  87 + public PageResult<BpmUserGroupDO> getUserGroupPage(BpmUserGroupPageReqVO pageReqVO) {
  88 + return userGroupMapper.selectPage(pageReqVO);
  89 + }
  90 +
  91 + @Override
  92 + public void validUserGroups(Set<Long> ids) {
  93 + if (CollUtil.isEmpty(ids)) {
  94 + return;
  95 + }
  96 + // 获得用户组信息
  97 + List<BpmUserGroupDO> userGroups = userGroupMapper.selectBatchIds(ids);
  98 + Map<Long, BpmUserGroupDO> userGroupMap = CollectionUtils.convertMap(userGroups, BpmUserGroupDO::getId);
  99 + // 校验
  100 + ids.forEach(id -> {
  101 + BpmUserGroupDO userGroup = userGroupMap.get(id);
  102 + if (userGroup == null) {
  103 + throw ServiceExceptionUtil.exception(USER_GROUP_NOT_EXISTS);
  104 + }
  105 + if (!CommonStatusEnum.ENABLE.getStatus().equals(userGroup.getStatus())) {
  106 + throw exception(USER_GROUP_IS_DISABLE, userGroup.getName());
  107 + }
  108 + });
  109 + }
  110 +
  111 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmFormFieldRespDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.definition.dto;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonProperty;
  4 +import lombok.Data;
  5 +
  6 +/**
  7 + * Bpm 表单的 Field 表单项 Response DTO
  8 + * 字段的定义,可见 https://github.com/JakHuang/form-generator/issues/46 文档
  9 + *
  10 + * @author 芋道源码
  11 + */
  12 +@Data
  13 +public class BpmFormFieldRespDTO {
  14 +
  15 + /**
  16 + * 表单标题
  17 + */
  18 + private String label;
  19 + /**
  20 + * 表单字段的属性名,可自定义
  21 + */
  22 + @JsonProperty(value = "vModel")
  23 + private String vModel;
  24 +
  25 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmModelMetaInfoRespDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.definition.dto;
  2 +
  3 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
  4 +import lombok.Data;
  5 +
  6 +/**
  7 + * BPM 流程 MetaInfo Response DTO
  8 + * 主要用于 { Model#setMetaInfo(String)} 的存储
  9 + *
  10 + * @author 芋道源码
  11 + */
  12 +@Data
  13 +public class BpmModelMetaInfoRespDTO {
  14 +
  15 + /**
  16 + * 流程描述
  17 + */
  18 + private String description;
  19 + /**
  20 + * 表单类型
  21 + */
  22 + private Integer formType;
  23 + /**
  24 + * 表单编号
  25 + * 在表单类型为 {@link BpmModelFormTypeEnum#NORMAL} 时
  26 + */
  27 + private Long formId;
  28 + /**
  29 + * 自定义表单的提交路径,使用 Vue 的路由地址
  30 + * 在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时
  31 + */
  32 + private String formCustomCreatePath;
  33 + /**
  34 + * 自定义表单的查看路径,使用 Vue 的路由地址
  35 + * 在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时
  36 + */
  37 + private String formCustomViewPath;
  38 +
  39 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmProcessDefinitionCreateReqDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.definition.dto;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.StrUtil;
  5 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
  6 +import lombok.Data;
  7 +
  8 +import javax.validation.constraints.AssertTrue;
  9 +import javax.validation.constraints.NotEmpty;
  10 +import javax.validation.constraints.NotNull;
  11 +import java.util.List;
  12 +import java.util.Objects;
  13 +
  14 +/**
  15 + * 流程定义创建 Request DTO
  16 + */
  17 +@Data
  18 +public class BpmProcessDefinitionCreateReqDTO {
  19 +
  20 + // ========== 模型相关 ==========
  21 +
  22 + /**
  23 + * 流程模型的编号
  24 + */
  25 + @NotEmpty(message = "流程模型编号不能为空")
  26 + private String modelId;
  27 + /**
  28 + * 流程标识
  29 + */
  30 + @NotEmpty(message = "流程标识不能为空")
  31 + private String key;
  32 + /**
  33 + * 流程名称
  34 + */
  35 + @NotEmpty(message = "流程名称不能为空")
  36 + private String name;
  37 + /**
  38 + * 流程描述
  39 + */
  40 + private String description;
  41 + /**
  42 + * 流程分类
  43 + * 参见 bpm_model_category 数据字典
  44 + */
  45 + @NotEmpty(message = "流程分类不能为空")
  46 + private String category;
  47 + /**
  48 + * BPMN XML
  49 + */
  50 + @NotEmpty(message = "BPMN XML 不能为空")
  51 + private byte[] bpmnBytes;
  52 +
  53 + // ========== 表单相关 ==========
  54 +
  55 + /**
  56 + * 表单类型
  57 + */
  58 + @NotNull(message = "表单类型不能为空")
  59 + private Integer formType;
  60 + /**
  61 + * 动态表单编号
  62 + * 在表单类型为 {@link BpmModelFormTypeEnum#NORMAL} 时
  63 + */
  64 + private Long formId;
  65 + /**
  66 + * 表单的配置
  67 + * 在表单类型为 {@link BpmModelFormTypeEnum#NORMAL} 时
  68 + */
  69 + private String formConf;
  70 + /**
  71 + * 表单项的数组
  72 + * 在表单类型为 {@link BpmModelFormTypeEnum#NORMAL} 时
  73 + */
  74 + private List<String> formFields;
  75 + /**
  76 + * 自定义表单的提交路径,使用 Vue 的路由地址
  77 + * 在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时
  78 + */
  79 + private String formCustomCreatePath;
  80 + /**
  81 + * 自定义表单的查看路径,使用 Vue 的路由地址
  82 + * 在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时
  83 + */
  84 + private String formCustomViewPath;
  85 +
  86 + @AssertTrue(message = "流程表单信息不全")
  87 + public boolean isNormalFormTypeValid() {
  88 + // 如果非业务表单,则直接通过
  89 + if (!Objects.equals(formType, BpmModelFormTypeEnum.NORMAL.getType())) {
  90 + return true;
  91 + }
  92 + return formId != null && StrUtil.isNotEmpty(formConf) && CollUtil.isNotEmpty(formFields);
  93 + }
  94 +
  95 + @AssertTrue(message = "业务表单信息不全")
  96 + public boolean isNormalCustomTypeValid() {
  97 + // 如果非业务表单,则直接通过
  98 + if (!Objects.equals(formType, BpmModelFormTypeEnum.CUSTOM.getType())) {
  99 + return true;
  100 + }
  101 + return StrUtil.isNotEmpty(formCustomCreatePath) && StrUtil.isNotEmpty(formCustomViewPath);
  102 + }
  103 +
  104 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/message/BpmMessageService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.message;
  2 +
  3 +import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceApproveReqDTO;
  4 +import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceRejectReqDTO;
  5 +import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO;
  6 +
  7 +import javax.validation.Valid;
  8 +
  9 +/**
  10 + * BPM 消息 Service 接口
  11 + *
  12 + * TODO 芋艿:未来支持消息的可配置;不同的流程,在什么场景下,需要发送什么消息,消息的内容是什么;
  13 + *
  14 + * @author 芋道源码
  15 + */
  16 +public interface BpmMessageService {
  17 +
  18 + /**
  19 + * 发送流程实例被通过的消息
  20 + *
  21 + * @param reqDTO 发送信息
  22 + */
  23 + void sendMessageWhenProcessInstanceApprove(@Valid BpmMessageSendWhenProcessInstanceApproveReqDTO reqDTO);
  24 +
  25 + /**
  26 + * 发送流程实例被不通过的消息
  27 + *
  28 + * @param reqDTO 发送信息
  29 + */
  30 + void sendMessageWhenProcessInstanceReject(@Valid BpmMessageSendWhenProcessInstanceRejectReqDTO reqDTO);
  31 +
  32 + /**
  33 + * 发送任务被分配的消息
  34 + *
  35 + * @param reqDTO 发送信息
  36 + */
  37 + void sendMessageWhenTaskAssigned(@Valid BpmMessageSendWhenTaskCreatedReqDTO reqDTO);
  38 +
  39 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/message/BpmMessageServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.message;
  2 +
  3 +import cn.iocoder.yudao.framework.web.config.WebProperties;
  4 +import cn.iocoder.yudao.module.bpm.convert.message.BpmMessageConvert;
  5 +import cn.iocoder.yudao.module.bpm.enums.message.BpmMessageEnum;
  6 +import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceApproveReqDTO;
  7 +import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceRejectReqDTO;
  8 +import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO;
  9 +import cn.iocoder.yudao.module.system.api.sms.SmsSendApi;
  10 +import lombok.extern.slf4j.Slf4j;
  11 +import org.springframework.stereotype.Service;
  12 +import org.springframework.validation.annotation.Validated;
  13 +
  14 +import javax.annotation.Resource;
  15 +import java.util.HashMap;
  16 +import java.util.Map;
  17 +
  18 +/**
  19 + * BPM 消息 Service 实现类
  20 + *
  21 + * @author 芋道源码
  22 + */
  23 +@Service
  24 +@Validated
  25 +@Slf4j
  26 +public class BpmMessageServiceImpl implements BpmMessageService {
  27 +
  28 + @Resource
  29 + private SmsSendApi smsSendApi;
  30 +
  31 + @Resource
  32 + private WebProperties webProperties;
  33 +
  34 + @Override
  35 + public void sendMessageWhenProcessInstanceApprove(BpmMessageSendWhenProcessInstanceApproveReqDTO reqDTO) {
  36 + Map<String, Object> templateParams = new HashMap<>();
  37 + templateParams.put("processInstanceName", reqDTO.getProcessInstanceName());
  38 + templateParams.put("detailUrl", getProcessInstanceDetailUrl(reqDTO.getProcessInstanceId()));
  39 + smsSendApi.sendSingleSmsToAdmin(BpmMessageConvert.INSTANCE.convert(reqDTO.getStartUserId(),
  40 + BpmMessageEnum.PROCESS_INSTANCE_APPROVE.getSmsTemplateCode(), templateParams));
  41 + }
  42 +
  43 + @Override
  44 + public void sendMessageWhenProcessInstanceReject(BpmMessageSendWhenProcessInstanceRejectReqDTO reqDTO) {
  45 + Map<String, Object> templateParams = new HashMap<>();
  46 + templateParams.put("processInstanceName", reqDTO.getProcessInstanceName());
  47 + templateParams.put("comment", reqDTO.getComment());
  48 + templateParams.put("detailUrl", getProcessInstanceDetailUrl(reqDTO.getProcessInstanceId()));
  49 + smsSendApi.sendSingleSmsToAdmin(BpmMessageConvert.INSTANCE.convert(reqDTO.getStartUserId(),
  50 + BpmMessageEnum.PROCESS_INSTANCE_REJECT.getSmsTemplateCode(), templateParams));
  51 + }
  52 +
  53 + @Override
  54 + public void sendMessageWhenTaskAssigned(BpmMessageSendWhenTaskCreatedReqDTO reqDTO) {
  55 + Map<String, Object> templateParams = new HashMap<>();
  56 + templateParams.put("processInstanceName", reqDTO.getProcessInstanceName());
  57 + templateParams.put("taskName", reqDTO.getTaskName());
  58 + templateParams.put("startUserNickname", reqDTO.getStartUserNickname());
  59 + templateParams.put("detailUrl", getProcessInstanceDetailUrl(reqDTO.getProcessInstanceId()));
  60 + smsSendApi.sendSingleSmsToAdmin(BpmMessageConvert.INSTANCE.convert(reqDTO.getStartUserId(),
  61 + BpmMessageEnum.TASK_ASSIGNED.getSmsTemplateCode(), templateParams));
  62 + }
  63 +
  64 + private String getProcessInstanceDetailUrl(String taskId) {
  65 + return webProperties.getAdminUi().getUrl() + "/bpm/process-instance/detail?id=" + taskId;
  66 + }
  67 +
  68 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/message/dto/BpmMessageSendWhenProcessInstanceApproveReqDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.message.dto;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import javax.validation.constraints.NotEmpty;
  6 +import javax.validation.constraints.NotNull;
  7 +
  8 +/**
  9 + * BPM 发送流程实例被通过 Request DTO
  10 + */
  11 +@Data
  12 +public class BpmMessageSendWhenProcessInstanceApproveReqDTO {
  13 +
  14 + /**
  15 + * 流程实例的编号
  16 + */
  17 + @NotEmpty(message = "流程实例的编号不能为空")
  18 + private String processInstanceId;
  19 + /**
  20 + * 流程实例的名字
  21 + */
  22 + @NotEmpty(message = "流程实例的名字不能为空")
  23 + private String processInstanceName;
  24 + @NotNull(message = "发起人的用户编号")
  25 + private Long startUserId;
  26 +
  27 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/message/dto/BpmMessageSendWhenProcessInstanceRejectReqDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.message.dto;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import javax.validation.constraints.NotEmpty;
  6 +import javax.validation.constraints.NotNull;
  7 +
  8 +/**
  9 + * BPM 发送流程实例被不通过 Request DTO
  10 + */
  11 +@Data
  12 +public class BpmMessageSendWhenProcessInstanceRejectReqDTO {
  13 +
  14 + /**
  15 + * 流程实例的编号
  16 + */
  17 + @NotEmpty(message = "流程实例的编号不能为空")
  18 + private String processInstanceId;
  19 + /**
  20 + * 流程实例的名字
  21 + */
  22 + @NotEmpty(message = "流程实例的名字不能为空")
  23 + private String processInstanceName;
  24 + @NotNull(message = "发起人的用户编号")
  25 + private Long startUserId;
  26 +
  27 + /**
  28 + * 不通过理由
  29 + */
  30 + @NotEmpty(message = "不通过理由不能为空")
  31 + private String comment;
  32 +
  33 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/message/dto/BpmMessageSendWhenTaskCreatedReqDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.message.dto;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import javax.validation.constraints.NotEmpty;
  6 +import javax.validation.constraints.NotNull;
  7 +
  8 +/**
  9 + * BPM 发送任务被分配 Request DTO
  10 + */
  11 +@Data
  12 +public class BpmMessageSendWhenTaskCreatedReqDTO {
  13 +
  14 + /**
  15 + * 流程实例的编号
  16 + */
  17 + @NotEmpty(message = "流程实例的编号不能为空")
  18 + private String processInstanceId;
  19 + /**
  20 + * 流程实例的名字
  21 + */
  22 + @NotEmpty(message = "流程实例的名字不能为空")
  23 + private String processInstanceName;
  24 + @NotNull(message = "发起人的用户编号")
  25 + private Long startUserId;
  26 + @NotEmpty(message = "发起人的昵称")
  27 + private String startUserNickname;
  28 +
  29 + /**
  30 + * 流程任务的编号
  31 + */
  32 + @NotEmpty(message = "流程任务的编号不能为空")
  33 + private String taskId;
  34 + /**
  35 + * 流程任务的名字
  36 + */
  37 + @NotEmpty(message = "流程任务的名字不能为空")
  38 + private String taskName;
  39 +
  40 + /**
  41 + * 审批人的用户编号
  42 + */
  43 + @NotNull(message = "审批人的用户编号不能为空")
  44 + private Long assigneeUserId;
  45 +
  46 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALeaveService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.oa;
  2 +
  3 +
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOALeaveCreateReqVO;
  6 +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOALeavePageReqVO;
  7 +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALeaveDO;
  8 +
  9 +import javax.validation.Valid;
  10 +
  11 +/**
  12 + * 请假申请 Service 接口
  13 + *
  14 + * @author jason
  15 + * @author 芋道源码
  16 + */
  17 +public interface BpmOALeaveService {
  18 +
  19 + /**
  20 + * 创建请假申请
  21 + *
  22 + * @param userId 用户编号
  23 + * @param createReqVO 创建信息
  24 + * @return 编号
  25 + */
  26 + Long createLeave(Long userId, @Valid BpmOALeaveCreateReqVO createReqVO);
  27 +
  28 + /**
  29 + * 更新请假申请的状态
  30 + *
  31 + * @param id 编号
  32 + * @param result 结果
  33 + */
  34 + void updateLeaveResult(Long id, Integer result);
  35 +
  36 + /**
  37 + * 获得请假申请
  38 + *
  39 + * @param id 编号
  40 + * @return 请假申请
  41 + */
  42 + BpmOALeaveDO getLeave(Long id);
  43 +
  44 + /**
  45 + * 获得请假申请分页
  46 + *
  47 + * @param userId 用户编号
  48 + * @param pageReqVO 分页查询
  49 + * @return 请假申请分页
  50 + */
  51 + PageResult<BpmOALeaveDO> getLeavePage(Long userId, BpmOALeavePageReqVO pageReqVO);
  52 +
  53 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALeaveServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.oa;
  2 +
  3 +import cn.hutool.core.date.DateUtil;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
  6 +import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
  7 +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOALeaveCreateReqVO;
  8 +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOALeavePageReqVO;
  9 +import cn.iocoder.yudao.module.bpm.convert.oa.BpmOALeaveConvert;
  10 +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALeaveDO;
  11 +import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOALeaveMapper;
  12 +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
  13 +import org.springframework.stereotype.Service;
  14 +import org.springframework.transaction.annotation.Transactional;
  15 +import org.springframework.validation.annotation.Validated;
  16 +
  17 +import javax.annotation.Resource;
  18 +import java.util.HashMap;
  19 +import java.util.Map;
  20 +
  21 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  22 +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.OA_LEAVE_NOT_EXISTS;
  23 +
  24 +/**
  25 + * OA 请假申请 Service 实现类
  26 + *
  27 + * @author jason
  28 + * @author 芋道源码
  29 + */
  30 +@Service
  31 +@Validated
  32 +public class BpmOALeaveServiceImpl implements BpmOALeaveService {
  33 +
  34 + /**
  35 + * OA 请假对应的流程定义 KEY
  36 + */
  37 + public static final String PROCESS_KEY = "oa_leave";
  38 +
  39 + @Resource
  40 + private BpmOALeaveMapper leaveMapper;
  41 +
  42 + @Resource
  43 + private BpmProcessInstanceApi processInstanceApi;
  44 +
  45 + @Override
  46 + @Transactional(rollbackFor = Exception.class)
  47 + public Long createLeave(Long userId, BpmOALeaveCreateReqVO createReqVO) {
  48 + // 插入 OA 请假单
  49 + long day = DateUtil.betweenDay(createReqVO.getStartTime(), createReqVO.getEndTime(), false);
  50 + BpmOALeaveDO leave = BpmOALeaveConvert.INSTANCE.convert(createReqVO).setUserId(userId).setDay(day)
  51 + .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
  52 + leaveMapper.insert(leave);
  53 +
  54 + // 发起 BPM 流程
  55 + Map<String, Object> processInstanceVariables = new HashMap<>();
  56 + processInstanceVariables.put("day", day);
  57 + String processInstanceId = processInstanceApi.createProcessInstance(userId,
  58 + new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY)
  59 + .setVariables(processInstanceVariables).setBusinessKey(String.valueOf(leave.getId())));
  60 +
  61 + // 将工作流的编号,更新到 OA 请假单中
  62 + leaveMapper.updateById(new BpmOALeaveDO().setId(leave.getId()).setProcessInstanceId(processInstanceId));
  63 + return leave.getId();
  64 + }
  65 +
  66 + @Override
  67 + public void updateLeaveResult(Long id, Integer result) {
  68 + validateLeaveExists(id);
  69 + leaveMapper.updateById(new BpmOALeaveDO().setId(id).setResult(result));
  70 + }
  71 +
  72 + private void validateLeaveExists(Long id) {
  73 + if (leaveMapper.selectById(id) == null) {
  74 + throw exception(OA_LEAVE_NOT_EXISTS);
  75 + }
  76 + }
  77 +
  78 + @Override
  79 + public BpmOALeaveDO getLeave(Long id) {
  80 + return leaveMapper.selectById(id);
  81 + }
  82 +
  83 + @Override
  84 + public PageResult<BpmOALeaveDO> getLeavePage(Long userId, BpmOALeavePageReqVO pageReqVO) {
  85 + return leaveMapper.selectPage(userId, pageReqVO);
  86 + }
  87 +
  88 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/listener/BpmOALeaveResultListener.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.oa.listener;
  2 +
  3 +import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEvent;
  4 +import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventListener;
  5 +import cn.iocoder.yudao.module.bpm.service.oa.BpmOALeaveService;
  6 +import cn.iocoder.yudao.module.bpm.service.oa.BpmOALeaveServiceImpl;
  7 +import org.springframework.stereotype.Component;
  8 +
  9 +import javax.annotation.Resource;
  10 +
  11 +/**
  12 + * OA 请假单的结果的监听器实现类
  13 + *
  14 + * @author 芋道源码
  15 + */
  16 +@Component
  17 +public class BpmOALeaveResultListener extends BpmProcessInstanceResultEventListener {
  18 +
  19 + @Resource
  20 + private BpmOALeaveService leaveService;
  21 +
  22 + @Override
  23 + protected String getProcessDefinitionKey() {
  24 + return BpmOALeaveServiceImpl.PROCESS_KEY;
  25 + }
  26 +
  27 + @Override
  28 + protected void onEvent(BpmProcessInstanceResultEvent event) {
  29 + leaveService.updateLeaveResult(Long.parseLong(event.getBusinessKey()), event.getResult());
  30 + }
  31 +
  32 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmActivityService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.task;
  2 +
  3 +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity.BpmActivityRespVO;
  4 +
  5 +import java.util.List;
  6 +
  7 +/**
  8 + * BPM 活动实例 Service 接口
  9 + *
  10 + * @author 芋道源码
  11 + */
  12 +public interface BpmActivityService {
  13 +
  14 + /**
  15 + * 获得指定流程实例的活动实例列表
  16 + *
  17 + * @param processInstanceId 流程实例的编号
  18 + * @return 活动实例列表
  19 + */
  20 + List<BpmActivityRespVO> getActivityListByProcessInstanceId(String processInstanceId);
  21 +
  22 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmActivityServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.task;
  2 +
  3 +import cn.hutool.core.io.IoUtil;
  4 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  5 +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity.BpmActivityRespVO;
  6 +import cn.iocoder.yudao.module.bpm.convert.task.BpmActivityConvert;
  7 +import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
  8 +import lombok.extern.slf4j.Slf4j;
  9 +
  10 +import org.flowable.bpmn.model.BpmnModel;
  11 +import org.flowable.engine.HistoryService;
  12 +import org.flowable.engine.history.HistoricActivityInstance;
  13 +import org.flowable.engine.history.HistoricProcessInstance;
  14 +import org.flowable.image.ProcessDiagramGenerator;
  15 +import org.springframework.stereotype.Service;
  16 +import org.springframework.validation.annotation.Validated;
  17 +
  18 +import javax.annotation.Resource;
  19 +import java.io.InputStream;
  20 +import java.util.Collections;
  21 +import java.util.List;
  22 +
  23 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  24 +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_DEFINITION_BPMN_MODEL_NOT_EXISTS;
  25 +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_INSTANCE_NOT_EXISTS;
  26 +
  27 +/**
  28 + * BPM 活动实例 Service 实现类
  29 + *
  30 + * @author 芋道源码
  31 + */
  32 +@Service
  33 +@Slf4j
  34 +@Validated
  35 +public class BpmActivityServiceImpl implements BpmActivityService {
  36 +
  37 + @Resource
  38 + private HistoryService historyService;
  39 +
  40 + @Override
  41 + public List<BpmActivityRespVO> getActivityListByProcessInstanceId(String processInstanceId) {
  42 + List<HistoricActivityInstance> activityList = historyService.createHistoricActivityInstanceQuery()
  43 + .processInstanceId(processInstanceId).list();
  44 + return BpmActivityConvert.INSTANCE.convertList(activityList);
  45 + }
  46 +
  47 +
  48 +
  49 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.task;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  5 +import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
  6 +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*;
  7 +import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
  8 +import org.flowable.engine.delegate.event.FlowableCancelledEvent;
  9 +import org.flowable.engine.history.HistoricProcessInstance;
  10 +import org.flowable.engine.runtime.ProcessInstance;
  11 +
  12 +import javax.validation.Valid;
  13 +import java.util.List;
  14 +import java.util.Map;
  15 +import java.util.Set;
  16 +
  17 +/**
  18 + * 流程实例 Service 接口
  19 + *
  20 + * @author 芋道源码
  21 + */
  22 +public interface BpmProcessInstanceService {
  23 +
  24 + /**
  25 + * 获得流程实例
  26 + *
  27 + * @param id 流程实例的编号
  28 + * @return 流程实例
  29 + */
  30 + ProcessInstance getProcessInstance(String id);
  31 +
  32 + /**
  33 + * 获得流程实例列表
  34 + *
  35 + * @param ids 流程实例的编号集合
  36 + * @return 流程实例列表
  37 + */
  38 + List<ProcessInstance> getProcessInstances(Set<String> ids);
  39 +
  40 + /**
  41 + * 获得流程实例 Map
  42 + *
  43 + * @param ids 流程实例的编号集合
  44 + * @return 流程实例列表 Map
  45 + */
  46 + default Map<String, ProcessInstance> getProcessInstanceMap(Set<String> ids) {
  47 + return CollectionUtils.convertMap(getProcessInstances(ids), ProcessInstance::getProcessInstanceId);
  48 + }
  49 +
  50 + /**
  51 + * 获得流程实例的分页
  52 + *
  53 + * @param userId 用户编号
  54 + * @param pageReqVO 分页请求
  55 + * @return 流程实例的分页
  56 + */
  57 + PageResult<BpmProcessInstancePageItemRespVO> getMyProcessInstancePage(Long userId,
  58 + @Valid BpmProcessInstanceMyPageReqVO pageReqVO);
  59 + /**
  60 + * 创建流程实例(提供给前端)
  61 + *
  62 + * @param userId 用户编号
  63 + * @param createReqVO 创建信息
  64 + * @return 实例的编号
  65 + */
  66 + String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO);
  67 +
  68 + /**
  69 + * 创建流程实例(提供给内部)
  70 + *
  71 + * @param userId 用户编号
  72 + * @param createReqDTO 创建信息
  73 + * @return 实例的编号
  74 + */
  75 + String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO);
  76 +
  77 + /**
  78 + * 获得流程实例 VO 信息
  79 + *
  80 + * @param id 流程实例的编号
  81 + * @return 流程实例
  82 + */
  83 + BpmProcessInstanceRespVO getProcessInstanceVO(String id);
  84 +
  85 + /**
  86 + * 取消流程实例
  87 + *
  88 + * @param userId 用户编号
  89 + * @param cancelReqVO 取消信息
  90 + */
  91 + void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO);
  92 +
  93 + /**
  94 + * 获得历史的流程实例
  95 + *
  96 + * @param id 流程实例的编号
  97 + * @return 历史的流程实例
  98 + */
  99 + HistoricProcessInstance getHistoricProcessInstance(String id);
  100 +
  101 + /**
  102 + * 获得历史的流程实例列表
  103 + *
  104 + * @param ids 流程实例的编号集合
  105 + * @return 历史的流程实例列表
  106 + */
  107 + List<HistoricProcessInstance> getHistoricProcessInstances(Set<String> ids);
  108 +
  109 + /**
  110 + * 获得历史的流程实例 Map
  111 + *
  112 + * @param ids 流程实例的编号集合
  113 + * @return 历史的流程实例列表 Map
  114 + */
  115 + default Map<String, HistoricProcessInstance> getHistoricProcessInstanceMap(Set<String> ids) {
  116 + return CollectionUtils.convertMap(getHistoricProcessInstances(ids), HistoricProcessInstance::getId);
  117 + }
  118 +
  119 + /**
  120 + * 创建 ProcessInstance 拓展记录
  121 + *
  122 + * @param instance 流程任务
  123 + */
  124 + void createProcessInstanceExt(ProcessInstance instance);
  125 +
  126 + /**
  127 + * 更新 ProcessInstance 拓展记录为取消
  128 + *
  129 + * @param event 流程取消事件
  130 + */
  131 + void updateProcessInstanceExtCancel(FlowableCancelledEvent event);
  132 +
  133 + /**
  134 + * 更新 ProcessInstance 拓展记录为完成
  135 + *
  136 + * @param instance 流程任务
  137 + */
  138 + void updateProcessInstanceExtComplete(ProcessInstance instance);
  139 +
  140 + /**
  141 + * 更新 ProcessInstance 拓展记录为不通过
  142 + *
  143 + * @param id 流程编号
  144 + * @param comment 理由。例如说,审批不通过时,需要传递该值
  145 + */
  146 + void updateProcessInstanceExtReject(String id, String comment);
  147 +
  148 +
  149 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.task;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.lang.Assert;
  5 +import cn.hutool.core.util.StrUtil;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  7 +import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
  8 +import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
  9 +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*;
  10 +import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert;
  11 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
  12 +import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
  13 +import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper;
  14 +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum;
  15 +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
  16 +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
  17 +import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher;
  18 +import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
  19 +import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;
  20 +import cn.iocoder.yudao.module.system.api.dept.DeptApi;
  21 +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
  22 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  23 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  24 +import lombok.extern.slf4j.Slf4j;
  25 +import org.flowable.engine.HistoryService;
  26 +import org.flowable.engine.RuntimeService;
  27 +import org.flowable.engine.delegate.event.FlowableCancelledEvent;
  28 +import org.flowable.engine.history.HistoricProcessInstance;
  29 +import org.flowable.engine.repository.ProcessDefinition;
  30 +import org.flowable.engine.runtime.ProcessInstance;
  31 +import org.flowable.task.api.Task;
  32 +import org.springframework.context.annotation.Lazy;
  33 +import org.springframework.scheduling.annotation.Async;
  34 +import org.springframework.stereotype.Service;
  35 +import org.springframework.transaction.annotation.Transactional;
  36 +import org.springframework.validation.annotation.Validated;
  37 +
  38 +import javax.annotation.Resource;
  39 +import javax.validation.Valid;
  40 +import java.util.*;
  41 +
  42 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  43 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
  44 +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
  45 +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF;
  46 +
  47 +/**
  48 + * 流程实例 Service 实现类
  49 + *
  50 + * ProcessDefinition & ProcessInstance & Execution & Task 的关系:
  51 + * 1. https://blog.csdn.net/bobozai86/article/details/105210414
  52 + *
  53 + * HistoricProcessInstance & ProcessInstance 的关系:
  54 + * 1.https://my.oschina.net/843294669/blog/719024
  55 + * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例
  56 + *
  57 + * @author 芋道源码
  58 + */
  59 +@Service
  60 +@Validated
  61 +@Slf4j
  62 +public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService {
  63 +
  64 + @Resource
  65 + private RuntimeService runtimeService;
  66 + @Resource
  67 + private BpmProcessInstanceExtMapper processInstanceExtMapper;
  68 + @Resource
  69 + @Lazy // 解决循环依赖
  70 + private BpmTaskService taskService;
  71 + @Resource
  72 + private BpmProcessDefinitionService processDefinitionService;
  73 + @Resource
  74 + private HistoryService historyService;
  75 + @Resource
  76 + private AdminUserApi adminUserApi;
  77 + @Resource
  78 + private DeptApi deptApi;
  79 + @Resource
  80 + private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher;
  81 + @Resource
  82 + private BpmMessageService messageService;
  83 + @Override
  84 + public ProcessInstance getProcessInstance(String id) {
  85 + return runtimeService.createProcessInstanceQuery().processInstanceId(id).singleResult();
  86 + }
  87 +
  88 + @Override
  89 + public List<ProcessInstance> getProcessInstances(Set<String> ids) {
  90 + return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list();
  91 + }
  92 +
  93 + @Override
  94 + public PageResult<BpmProcessInstancePageItemRespVO> getMyProcessInstancePage(Long userId,
  95 + BpmProcessInstanceMyPageReqVO pageReqVO) {
  96 + // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页
  97 + PageResult<BpmProcessInstanceExtDO> pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO);
  98 + if (CollUtil.isEmpty(pageResult.getList())) {
  99 + return new PageResult<>(pageResult.getTotal());
  100 + }
  101 +
  102 + // 获得流程 Task Map
  103 + List<String> processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId);
  104 + Map<String, List<Task>> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds);
  105 + // 转换返回
  106 + return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap);
  107 + }
  108 +
  109 + @Override
  110 + @Transactional(rollbackFor = Exception.class)
  111 + public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) {
  112 + // 获得流程定义
  113 + ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId());
  114 + // 发起流程
  115 + return createProcessInstance0(userId, definition, createReqVO.getVariables(), null);
  116 + }
  117 +
  118 + @Override
  119 + public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) {
  120 + // 获得流程定义
  121 + ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey());
  122 + // 发起流程
  123 + return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey());
  124 + }
  125 +
  126 + @Override
  127 + public BpmProcessInstanceRespVO getProcessInstanceVO(String id) {
  128 + // 获得流程实例
  129 + HistoricProcessInstance processInstance = getHistoricProcessInstance(id);
  130 + if (processInstance == null) {
  131 + return null;
  132 + }
  133 + BpmProcessInstanceExtDO processInstanceExt = processInstanceExtMapper.selectByProcessInstanceId(id);
  134 + Assert.notNull(processInstanceExt, "流程实例拓展({}) 不存在", id);
  135 +
  136 + // 获得流程定义
  137 + ProcessDefinition processDefinition = processDefinitionService
  138 + .getProcessDefinition(processInstance.getProcessDefinitionId());
  139 + Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId());
  140 + BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt(
  141 + processInstance.getProcessDefinitionId());
  142 + Assert.notNull(processDefinitionExt, "流程定义拓展({}) 不存在", id);
  143 + String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId());
  144 +
  145 + // 获得 User
  146 + AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId()));
  147 + DeptRespDTO dept = null;
  148 + if (startUser != null) {
  149 + dept = deptApi.getDept(startUser.getDeptId());
  150 + }
  151 +
  152 + // 拼接结果
  153 + return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processInstanceExt,
  154 + processDefinition, processDefinitionExt, bpmnXml, startUser, dept);
  155 + }
  156 +
  157 + @Override
  158 + public void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) {
  159 + // 校验流程实例存在
  160 + ProcessInstance instance = getProcessInstance(cancelReqVO.getId());
  161 + if (instance == null) {
  162 + throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS);
  163 + }
  164 + // 只能取消自己的
  165 + if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) {
  166 + throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF);
  167 + }
  168 +
  169 + // 通过删除流程实例,实现流程实例的取消,
  170 + // 删除流程实例,正则执行任务ACT_RU_TASK. 任务会被删除。通过历史表查询
  171 + deleteProcessInstance(cancelReqVO.getId(),
  172 + BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason()));
  173 + }
  174 +
  175 + /**
  176 + * 获得历史的流程实例
  177 + *
  178 + * @param id 流程实例的编号
  179 + * @return 历史的流程实例
  180 + */
  181 + @Override
  182 + public HistoricProcessInstance getHistoricProcessInstance(String id) {
  183 + return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult();
  184 + }
  185 +
  186 + @Override
  187 + public List<HistoricProcessInstance> getHistoricProcessInstances(Set<String> ids) {
  188 + return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list();
  189 + }
  190 +
  191 + @Override
  192 + public void createProcessInstanceExt(ProcessInstance instance) {
  193 + // 获得流程定义
  194 + ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId());
  195 + // 插入 BpmProcessInstanceExtDO 对象
  196 + BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO()
  197 + .setProcessInstanceId(instance.getId())
  198 + .setProcessDefinitionId(definition.getId())
  199 + .setName(instance.getProcessDefinitionName())
  200 + .setStartUserId(Long.valueOf(instance.getStartUserId()))
  201 + .setCategory(definition.getCategory())
  202 + .setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus())
  203 + .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
  204 +
  205 + processInstanceExtMapper.insert(instanceExtDO);
  206 + }
  207 +
  208 + @Override
  209 + public void updateProcessInstanceExtCancel(FlowableCancelledEvent event) {
  210 + // 判断是否为 Reject 不通过。如果是,则不进行更新
  211 + if (BpmProcessInstanceDeleteReasonEnum.isRejectReason((String)event.getCause())) {
  212 + return;
  213 + }
  214 +
  215 + // 需要主动查询,因为 instance 只有 id 属性
  216 + // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance
  217 + HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId());
  218 + // 更新拓展表
  219 + BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO()
  220 + .setProcessInstanceId(event.getProcessInstanceId())
  221 + .setEndTime(new Date()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置
  222 + .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
  223 + .setResult(BpmProcessInstanceResultEnum.CANCEL.getResult());
  224 +
  225 + processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
  226 +
  227 + // 发送流程实例的状态事件
  228 + processInstanceResultEventPublisher.sendProcessInstanceResultEvent(
  229 + BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult()));
  230 + }
  231 +
  232 + @Override
  233 + public void updateProcessInstanceExtComplete(ProcessInstance instance) {
  234 + // 需要主动查询,因为 instance 只有 id 属性
  235 + // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance
  236 + HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId());
  237 + // 更新拓展表
  238 + BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO()
  239 + .setProcessInstanceId(instance.getProcessInstanceId())
  240 + .setEndTime(new Date()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置
  241 + .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
  242 + .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); // 如果正常完全,说明审批通过
  243 + processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
  244 +
  245 + // 发送流程被通过的消息
  246 + messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance));
  247 +
  248 + // 发送流程实例的状态事件
  249 + processInstanceResultEventPublisher.sendProcessInstanceResultEvent(
  250 + BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult()));
  251 + }
  252 +
  253 + @Transactional(rollbackFor = Exception.class)
  254 + public void updateProcessInstanceExtReject(String id, String comment) {
  255 + // 需要主动查询,因为 instance 只有 id 属性
  256 + ProcessInstance processInstance = getProcessInstance(id);
  257 + // 删除流程实例,以实现驳回任务时,取消整个审批流程
  258 + deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(comment)));
  259 +
  260 + // 更新 status + result
  261 + // 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法,
  262 + // 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL,显然和 result 不一定是一致的
  263 + BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id)
  264 + .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
  265 + .setResult(BpmProcessInstanceResultEnum.REJECT.getResult());
  266 + processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
  267 +
  268 + // 发送流程被不通过的消息
  269 + messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, comment));
  270 +
  271 + // 发送流程实例的状态事件
  272 + processInstanceResultEventPublisher.sendProcessInstanceResultEvent(
  273 + BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult()));
  274 + }
  275 +
  276 + private void deleteProcessInstance(String id, String reason) {
  277 + runtimeService.deleteProcessInstance(id, reason);
  278 + }
  279 +
  280 + private String createProcessInstance0(Long userId, ProcessDefinition definition,
  281 + Map<String, Object> variables, String businessKey) {
  282 + // 校验流程定义
  283 + if (definition == null) {
  284 + throw exception(PROCESS_DEFINITION_NOT_EXISTS);
  285 + }
  286 + if (definition.isSuspended()) {
  287 + throw exception(PROCESS_DEFINITION_IS_SUSPENDED);
  288 + }
  289 +
  290 + // 创建流程实例
  291 + ProcessInstance instance = runtimeService.startProcessInstanceById(definition.getId(), businessKey, variables);
  292 + // 设置流程名字
  293 + runtimeService.setProcessInstanceName(instance.getId(), definition.getName());
  294 +
  295 + // 补全流程实例的拓展表
  296 + //TODO startProcessInstance流程里面修改了 BpmProcessInstanceExt,没有提交,和下面的更新 锁持有冲突了,异步更新这个表
  297 +// processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()).setFormVariables(variables));
  298 + BpmProcessInstanceExtDO bpmProcessInstanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()).setFormVariables(variables);
  299 + asyncUpdateProcesInstance(bpmProcessInstanceExtDO);
  300 + return instance.getId();
  301 + }
  302 +
  303 + @Async
  304 + public void asyncUpdateProcesInstance(BpmProcessInstanceExtDO bpmProcessInstanceExtDO){
  305 + log.info("asyncUpdateProcesInstance ,cause MySQL Dead Lock");
  306 + processInstanceExtMapper.updateByProcessInstanceId(bpmProcessInstanceExtDO);
  307 +
  308 + }
  309 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.task;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  5 +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
  6 +import org.flowable.task.api.Task;
  7 +
  8 +
  9 +import javax.validation.Valid;
  10 +import java.util.List;
  11 +import java.util.Map;
  12 +
  13 +/**
  14 + * 流程任务实例 Service 接口
  15 + *
  16 + * @author jason
  17 + * @author 芋道源码
  18 + */
  19 +public interface BpmTaskService {
  20 + /**
  21 + * 获得待办的流程任务分页
  22 + *
  23 + * @param userId 用户编号
  24 + * @param pageReqVO 分页请求
  25 + * @return 流程任务分页
  26 + */
  27 + PageResult<BpmTaskTodoPageItemRespVO> getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageReqVO);
  28 + /**
  29 + * 获得已办的流程任务分页
  30 + *
  31 + * @param userId 用户编号
  32 + * @param pageReqVO 分页请求
  33 + * @return 流程任务分页
  34 + */
  35 + PageResult<BpmTaskDonePageItemRespVO> getDoneTaskPage(Long userId, BpmTaskDonePageReqVO pageReqVO);
  36 +
  37 + /**
  38 + * 获得流程任务 Map
  39 + *
  40 + * @param processInstanceIds 流程实例的编号数组
  41 + * @return 流程任务 Map
  42 + */
  43 + default Map<String, List<Task>> getTaskMapByProcessInstanceIds(List<String> processInstanceIds) {
  44 + return CollectionUtils.convertMultiMap(getTasksByProcessInstanceIds(processInstanceIds),
  45 + Task::getProcessInstanceId);
  46 + }
  47 +
  48 + /**
  49 + * 获得流程任务列表
  50 + *
  51 + * @param processInstanceIds 流程实例的编号数组
  52 + * @return 流程任务列表
  53 + */
  54 + List<Task> getTasksByProcessInstanceIds(List<String> processInstanceIds);
  55 +
  56 + /**
  57 + * 获得指令流程实例的流程任务列表,包括所有状态的
  58 + *
  59 + * @param processInstanceId 流程实例的编号
  60 + * @return 流程任务列表
  61 + */
  62 + List<BpmTaskRespVO> getTaskListByProcessInstanceId(String processInstanceId);
  63 +
  64 + /**
  65 + * 通过任务
  66 + *
  67 + * @param userId 用户编号
  68 + * @param reqVO 通过请求
  69 + */
  70 + void approveTask(Long userId, @Valid BpmTaskApproveReqVO reqVO);
  71 +
  72 + /**
  73 + * 不通过任务
  74 + *
  75 + * @param userId 用户编号
  76 + * @param reqVO 不通过请求
  77 + */
  78 + void rejectTask(Long userId, @Valid BpmTaskRejectReqVO reqVO);
  79 + /**
  80 + * 回退任务
  81 + *
  82 + * @param taskId 任务编号
  83 + */
  84 + void backTask(String taskId,String destinationTaskDefKey);
  85 +
  86 + /**
  87 + * 将流程任务分配给指定用户
  88 + *
  89 + * @param userId 用户编号
  90 + * @param reqVO 分配请求
  91 + */
  92 + void updateTaskAssignee(Long userId, BpmTaskUpdateAssigneeReqVO reqVO);
  93 +
  94 + /**
  95 + * 将流程任务分配给指定用户
  96 + *
  97 + * @param id 流程任务编号
  98 + * @param userId 用户编号
  99 + */
  100 + void updateTaskAssignee(String id, Long userId);
  101 +
  102 + /**
  103 + * 创建 Task 拓展记录
  104 + *
  105 + * @param task 任务实体
  106 + */
  107 + void createTaskExt(Task task);
  108 +
  109 + /**
  110 + * 更新 Task 拓展记录为完成
  111 + *
  112 + * @param task 任务实体
  113 + */
  114 + void updateTaskExtComplete(Task task);
  115 +
  116 + /**
  117 + * 更新 Task 拓展记录,并发送通知
  118 + *
  119 + * @param task 任务实体
  120 + */
  121 + void updateTaskExtAssign(Task task);
  122 +
  123 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.task;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.StrUtil;
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
  7 +import cn.iocoder.yudao.framework.common.util.object.PageUtils;
  8 +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
  9 +import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert;
  10 +import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
  11 +import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmTaskExtMapper;
  12 +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
  13 +import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;
  14 +import cn.iocoder.yudao.module.system.api.dept.DeptApi;
  15 +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
  16 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  17 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  18 +import lombok.extern.slf4j.Slf4j;
  19 +import org.flowable.engine.HistoryService;
  20 +import org.flowable.engine.RuntimeService;
  21 +import org.flowable.engine.TaskService;
  22 +import org.flowable.engine.history.HistoricProcessInstance;
  23 +import org.flowable.engine.runtime.ProcessInstance;
  24 +import org.flowable.task.api.Task;
  25 +import org.flowable.task.api.TaskQuery;
  26 +import org.flowable.task.api.history.HistoricTaskInstance;
  27 +import org.flowable.task.api.history.HistoricTaskInstanceQuery;
  28 +import org.springframework.stereotype.Service;
  29 +import org.springframework.transaction.annotation.Transactional;
  30 +import org.springframework.transaction.support.TransactionSynchronization;
  31 +import org.springframework.transaction.support.TransactionSynchronizationManager;
  32 +
  33 +import javax.annotation.Resource;
  34 +import javax.validation.Valid;
  35 +import java.util.*;
  36 +
  37 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  38 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
  39 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
  40 +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
  41 +
  42 +/**
  43 + * 流程任务实例 Service 实现类
  44 + *
  45 + * @author 芋道源码
  46 + * @author jason
  47 + */
  48 +@Slf4j
  49 +@Service
  50 +public class BpmTaskServiceImpl implements BpmTaskService{
  51 +
  52 + @Resource
  53 + private TaskService taskService;
  54 + @Resource
  55 + private RuntimeService runtimeService;
  56 + @Resource
  57 + private HistoryService historyService;
  58 +
  59 + @Resource
  60 + private BpmProcessInstanceService processInstanceService;
  61 + @Resource
  62 + private AdminUserApi adminUserApi;
  63 + @Resource
  64 + private DeptApi deptApi;
  65 + @Resource
  66 + private BpmTaskExtMapper taskExtMapper;
  67 + @Resource
  68 + private BpmMessageService messageService;
  69 +
  70 + @Override
  71 + public PageResult<BpmTaskTodoPageItemRespVO> getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageVO) {
  72 + // 查询待办任务
  73 + TaskQuery taskQuery = taskService.createTaskQuery()
  74 + .taskAssignee(String.valueOf(userId)) // 分配给自己
  75 + .orderByTaskCreateTime().desc(); // 创建时间倒序
  76 + if (StrUtil.isNotBlank(pageVO.getName())) {
  77 + taskQuery.taskNameLike("%" + pageVO.getName() + "%");
  78 + }
  79 + if (pageVO.getBeginCreateTime() != null) {
  80 + taskQuery.taskCreatedAfter(pageVO.getBeginCreateTime());
  81 + }
  82 + if (pageVO.getEndCreateTime() != null) {
  83 + taskQuery.taskCreatedBefore(pageVO.getEndCreateTime());
  84 + }
  85 + // 执行查询
  86 + List<Task> tasks = taskQuery.listPage(PageUtils.getStart(pageVO), pageVO.getPageSize());
  87 + if (CollUtil.isEmpty(tasks)) {
  88 + return PageResult.empty(taskQuery.count());
  89 + }
  90 +
  91 + // 获得 ProcessInstance Map
  92 + Map<String, ProcessInstance> processInstanceMap = processInstanceService.getProcessInstanceMap(
  93 + convertSet(tasks, Task::getProcessInstanceId));
  94 + // 获得 User Map
  95 + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
  96 + convertSet(processInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId())));
  97 + // 拼接结果
  98 + return new PageResult<>(BpmTaskConvert.INSTANCE.convertList1(tasks, processInstanceMap, userMap),
  99 + taskQuery.count());
  100 + }
  101 +
  102 + @Override
  103 + public PageResult<BpmTaskDonePageItemRespVO> getDoneTaskPage(Long userId, BpmTaskDonePageReqVO pageVO) {
  104 + // 查询已办任务
  105 + HistoricTaskInstanceQuery taskQuery = historyService.createHistoricTaskInstanceQuery()
  106 + .finished() // 已完成
  107 + .taskAssignee(String.valueOf(userId)) // 分配给自己
  108 + .orderByHistoricTaskInstanceEndTime().desc(); // 审批时间倒序
  109 + if (StrUtil.isNotBlank(pageVO.getName())) {
  110 + taskQuery.taskNameLike("%" + pageVO.getName() + "%");
  111 + }
  112 + if (pageVO.getBeginCreateTime() != null) {
  113 + taskQuery.taskCreatedAfter(pageVO.getBeginCreateTime());
  114 + }
  115 + if (pageVO.getEndCreateTime() != null) {
  116 + taskQuery.taskCreatedBefore(pageVO.getEndCreateTime());
  117 + }
  118 + // 执行查询
  119 + List<HistoricTaskInstance> tasks = taskQuery.listPage(PageUtils.getStart(pageVO), pageVO.getPageSize());
  120 + if (CollUtil.isEmpty(tasks)) {
  121 + return PageResult.empty(taskQuery.count());
  122 + }
  123 +
  124 + // 获得 TaskExtDO Map
  125 + List<BpmTaskExtDO> bpmTaskExtDOs = taskExtMapper.selectListByTaskIds(convertSet(tasks, HistoricTaskInstance::getId));
  126 + Map<String, BpmTaskExtDO> bpmTaskExtDOMap = convertMap(bpmTaskExtDOs, BpmTaskExtDO::getTaskId);
  127 + // 获得 ProcessInstance Map
  128 + Map<String, HistoricProcessInstance> historicProcessInstanceMap = processInstanceService.getHistoricProcessInstanceMap(
  129 + convertSet(tasks, HistoricTaskInstance::getProcessInstanceId));
  130 + // 获得 User Map
  131 + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
  132 + convertSet(historicProcessInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId())));
  133 + // 拼接结果
  134 + return new PageResult<>(BpmTaskConvert.INSTANCE.convertList2(tasks, bpmTaskExtDOMap, historicProcessInstanceMap, userMap),
  135 + taskQuery.count());
  136 + }
  137 +
  138 + @Override
  139 + public List<Task> getTasksByProcessInstanceIds(List<String> processInstanceIds) {
  140 + if (CollUtil.isEmpty(processInstanceIds)) {
  141 + return Collections.emptyList();
  142 + }
  143 + return taskService.createTaskQuery().processInstanceIdIn(processInstanceIds).list();
  144 + }
  145 +
  146 + @Override
  147 + public List<BpmTaskRespVO> getTaskListByProcessInstanceId(String processInstanceId) {
  148 + // 获得任务列表
  149 + List<HistoricTaskInstance> tasks = historyService.createHistoricTaskInstanceQuery()
  150 + .processInstanceId(processInstanceId)
  151 + .orderByHistoricTaskInstanceStartTime().desc() // 创建时间倒序
  152 + .list();
  153 + if (CollUtil.isEmpty(tasks)) {
  154 + return Collections.emptyList();
  155 + }
  156 +
  157 + // 获得 TaskExtDO Map
  158 + List<BpmTaskExtDO> bpmTaskExtDOs = taskExtMapper.selectListByTaskIds(convertSet(tasks, HistoricTaskInstance::getId));
  159 + Map<String, BpmTaskExtDO> bpmTaskExtDOMap = convertMap(bpmTaskExtDOs, BpmTaskExtDO::getTaskId);
  160 + // 获得 ProcessInstance Map
  161 + HistoricProcessInstance processInstance = processInstanceService.getHistoricProcessInstance(processInstanceId);
  162 + // 获得 User Map
  163 + Set<Long> userIds = convertSet(tasks, task -> NumberUtils.parseLong(task.getAssignee()));
  164 + userIds.add(NumberUtils.parseLong(processInstance.getStartUserId()));
  165 + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds);
  166 + // 获得 Dept Map
  167 + Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
  168 +
  169 + // 拼接数据
  170 + return BpmTaskConvert.INSTANCE.convertList3(tasks, bpmTaskExtDOMap, processInstance, userMap, deptMap);
  171 + }
  172 +
  173 + @Override
  174 + @Transactional(rollbackFor = Exception.class)
  175 + public void approveTask(Long userId, @Valid BpmTaskApproveReqVO reqVO) {
  176 + // 校验任务存在
  177 + Task task = checkTask(userId, reqVO.getId());
  178 + // 校验流程实例存在
  179 + ProcessInstance instance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
  180 + if (instance == null) {
  181 + throw exception(PROCESS_INSTANCE_NOT_EXISTS);
  182 + }
  183 +
  184 + // 完成任务,审批通过
  185 + taskService.complete(task.getId(), instance.getProcessVariables());
  186 + // 更新任务拓展表为通过
  187 + taskExtMapper.updateByTaskId(new BpmTaskExtDO().setTaskId(task.getId())
  188 + .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()).setComment(reqVO.getComment()));
  189 + }
  190 +
  191 + @Override
  192 + @Transactional(rollbackFor = Exception.class)
  193 + public void rejectTask(Long userId, @Valid BpmTaskRejectReqVO reqVO) {
  194 + Task task = checkTask(userId, reqVO.getId());
  195 + // 校验流程实例存在
  196 + ProcessInstance instance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
  197 + if (instance == null) {
  198 + throw exception(PROCESS_INSTANCE_NOT_EXISTS);
  199 + }
  200 +
  201 + // 更新流程实例为不通过
  202 + processInstanceService.updateProcessInstanceExtReject(instance.getProcessInstanceId(), reqVO.getComment());
  203 +
  204 + // 更新任务拓展表为不通过
  205 + taskExtMapper.updateByTaskId(new BpmTaskExtDO().setTaskId(task.getId())
  206 + .setResult(BpmProcessInstanceResultEnum.REJECT.getResult()).setComment(reqVO.getComment()));
  207 + }
  208 +
  209 + @Override
  210 + public void backTask(String taskId,String destinationTaskDefKey) {
  211 + Task currentTask = taskService.createTaskQuery().taskId(taskId).singleResult();
  212 +
  213 + runtimeService.createChangeActivityStateBuilder()
  214 + .processInstanceId(currentTask.getProcessInstanceId())
  215 + .moveActivityIdTo(currentTask.getTaskDefinitionKey(), destinationTaskDefKey)
  216 + .changeState();
  217 + }
  218 +
  219 + @Override
  220 + public void updateTaskAssignee(Long userId, BpmTaskUpdateAssigneeReqVO reqVO) {
  221 + // 校验任务存在
  222 + Task task = checkTask(userId, reqVO.getId());
  223 + // 更新负责人
  224 + updateTaskAssignee(task.getId(), reqVO.getAssigneeUserId());
  225 + }
  226 +
  227 + @Override
  228 + public void updateTaskAssignee(String id, Long userId) {
  229 + taskService.setAssignee(id, String.valueOf(userId));
  230 + }
  231 +
  232 +
  233 + @Override
  234 + public void createTaskExt(Task task) {
  235 + BpmTaskExtDO taskExtDO = BpmTaskConvert.INSTANCE.convert2TaskExt(task)
  236 + .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
  237 + taskExtMapper.insert(taskExtDO);
  238 + }
  239 +
  240 + @Override
  241 + public void updateTaskExtComplete(Task task) {
  242 + BpmTaskExtDO taskExtDO = BpmTaskConvert.INSTANCE.convert2TaskExt(task)
  243 + .setEndTime(new Date());
  244 + taskExtMapper.updateByTaskId(taskExtDO);
  245 + }
  246 +
  247 + @Override
  248 + public void updateTaskExtAssign(Task task) {
  249 + BpmTaskExtDO taskExtDO = new BpmTaskExtDO()
  250 + .setAssigneeUserId(NumberUtils.parseLong(task.getAssignee()))
  251 + .setTaskId(task.getId());
  252 + taskExtMapper.updateByTaskId(taskExtDO);
  253 + // 发送通知。在事务提交时,批量执行操作,所以直接查询会无法查询到 ProcessInstance,所以这里是通过监听事务的提交来实现。
  254 + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
  255 + @Override
  256 + public void afterCommit() {
  257 + ProcessInstance processInstance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
  258 + AdminUserRespDTO startUser = adminUserApi.getUser(Long.valueOf(processInstance.getStartUserId()));
  259 + messageService.sendMessageWhenTaskAssigned(BpmTaskConvert.INSTANCE.convert(processInstance, startUser, task));
  260 + }
  261 + });
  262 + }
  263 +
  264 + /**
  265 + * 校验任务是否存在, 并且是否是分配给自己的任务
  266 + * @param userId 用户 id
  267 + * @param taskId task id
  268 + */
  269 + private Task checkTask(Long userId, String taskId) {
  270 + Task task = getTask(taskId);
  271 + if (task == null) {
  272 + throw exception(TASK_COMPLETE_FAIL_NOT_EXISTS);
  273 + }
  274 + if (!Objects.equals(userId, NumberUtils.parseLong(task.getAssignee()))) {
  275 + throw exception(TASK_COMPLETE_FAIL_ASSIGN_NOT_SELF);
  276 + }
  277 + return task;
  278 + }
  279 +
  280 + private Task getTask(String id) {
  281 + return taskService.createTaskQuery().taskId(id).singleResult();
  282 + }
  283 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/package-info.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.task;
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormServiceTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.definition;
  2 +
  3 +import cn.hutool.core.util.RandomUtil;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
  6 +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
  7 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormCreateReqVO;
  8 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormPageReqVO;
  9 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormUpdateReqVO;
  10 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
  11 +import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmFormMapper;
  12 +import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmFormFieldRespDTO;
  13 +import org.junit.jupiter.api.Test;
  14 +import org.springframework.context.annotation.Import;
  15 +
  16 +import javax.annotation.Resource;
  17 +import java.util.List;
  18 +import java.util.stream.Collectors;
  19 +import java.util.stream.Stream;
  20 +
  21 +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
  22 +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
  23 +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
  24 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
  25 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  26 +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.FORM_NOT_EXISTS;
  27 +import static org.junit.jupiter.api.Assertions.*;
  28 +
  29 +/**
  30 + * {@link BpmFormServiceImpl} 的单元测试类
  31 + *
  32 + * @author 芋道源码
  33 + */
  34 +@Import(BpmFormServiceImpl.class)
  35 +public class BpmFormServiceTest extends BaseDbUnitTest {
  36 +
  37 + @Resource
  38 + private BpmFormServiceImpl formService;
  39 +
  40 + @Resource
  41 + private BpmFormMapper formMapper;
  42 +
  43 + @Test
  44 + public void testCreateForm_success() {
  45 + // 准备参数
  46 + BpmFormCreateReqVO reqVO = randomPojo(BpmFormCreateReqVO.class, o -> {
  47 + o.setConf("{}");
  48 + o.setFields(randomFields());
  49 + });
  50 +
  51 + // 调用
  52 + Long formId = formService.createForm(reqVO);
  53 + // 断言
  54 + assertNotNull(formId);
  55 + // 校验记录的属性是否正确
  56 + BpmFormDO form = formMapper.selectById(formId);
  57 + assertPojoEquals(reqVO, form);
  58 + }
  59 +
  60 + @Test
  61 + public void testUpdateForm_success() {
  62 + // mock 数据
  63 + BpmFormDO dbForm = randomPojo(BpmFormDO.class, o -> {
  64 + o.setConf("{}");
  65 + o.setFields(randomFields());
  66 + });
  67 + formMapper.insert(dbForm);// @Sql: 先插入出一条存在的数据
  68 + // 准备参数
  69 + BpmFormUpdateReqVO reqVO = randomPojo(BpmFormUpdateReqVO.class, o -> {
  70 + o.setId(dbForm.getId()); // 设置更新的 ID
  71 + o.setConf("{'yudao': 'yuanma'}");
  72 + o.setFields(randomFields());
  73 + });
  74 +
  75 + // 调用
  76 + formService.updateForm(reqVO);
  77 + // 校验是否更新正确
  78 + BpmFormDO form = formMapper.selectById(reqVO.getId()); // 获取最新的
  79 + assertPojoEquals(reqVO, form);
  80 + }
  81 +
  82 + @Test
  83 + public void testUpdateForm_notExists() {
  84 + // 准备参数
  85 + BpmFormUpdateReqVO reqVO = randomPojo(BpmFormUpdateReqVO.class, o -> {
  86 + o.setConf("{'yudao': 'yuanma'}");
  87 + o.setFields(randomFields());
  88 + });
  89 +
  90 + // 调用, 并断言异常
  91 + assertServiceException(() -> formService.updateForm(reqVO), FORM_NOT_EXISTS);
  92 + }
  93 +
  94 + @Test
  95 + public void testDeleteForm_success() {
  96 + // mock 数据
  97 + BpmFormDO dbForm = randomPojo(BpmFormDO.class);
  98 + formMapper.insert(dbForm);// @Sql: 先插入出一条存在的数据
  99 + // 准备参数
  100 + Long id = dbForm.getId();
  101 +
  102 + // 调用
  103 + formService.deleteForm(id);
  104 + // 校验数据不存在了
  105 + assertNull(formMapper.selectById(id));
  106 + }
  107 +
  108 + @Test
  109 + public void testDeleteForm_notExists() {
  110 + // 准备参数
  111 + Long id = randomLongId();
  112 +
  113 + // 调用, 并断言异常
  114 + assertServiceException(() -> formService.deleteForm(id), FORM_NOT_EXISTS);
  115 + }
  116 +
  117 + @Test
  118 + public void testGetFormPage() {
  119 + // mock 数据
  120 + BpmFormDO dbForm = randomPojo(BpmFormDO.class, o -> { // 等会查询到
  121 + o.setName("芋道源码");
  122 + });
  123 + formMapper.insert(dbForm);
  124 + // 测试 name 不匹配
  125 + formMapper.insert(cloneIgnoreId(dbForm, o -> o.setName("源码")));
  126 + // 准备参数
  127 + BpmFormPageReqVO reqVO = new BpmFormPageReqVO();
  128 + reqVO.setName("芋道");
  129 +
  130 + // 调用
  131 + PageResult<BpmFormDO> pageResult = formService.getFormPage(reqVO);
  132 + // 断言
  133 + assertEquals(1, pageResult.getTotal());
  134 + assertEquals(1, pageResult.getList().size());
  135 + assertPojoEquals(dbForm, pageResult.getList().get(0));
  136 + }
  137 +
  138 + private List<String> randomFields() {
  139 + int size = RandomUtil.randomInt(1, 3);
  140 + return Stream.iterate(0, i -> i).limit(size)
  141 + .map(i -> JsonUtils.toJsonString(randomPojo(BpmFormFieldRespDTO.class)))
  142 + .collect(Collectors.toList());
  143 + }
  144 +
  145 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.definition;
  2 +
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.framework.common.util.date.DateUtils;
  6 +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
  7 +import cn.iocoder.yudao.framework.test.core.util.AssertUtils;
  8 +import cn.iocoder.yudao.framework.test.core.util.RandomUtils;
  9 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupCreateReqVO;
  10 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupPageReqVO;
  11 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupUpdateReqVO;
  12 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
  13 +import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmUserGroupMapper;
  14 +import org.junit.jupiter.api.Assertions;
  15 +import org.junit.jupiter.api.Test;
  16 +import org.springframework.context.annotation.Import;
  17 +
  18 +import javax.annotation.Resource;
  19 +
  20 +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
  21 +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.USER_GROUP_NOT_EXISTS;
  22 +
  23 +/**
  24 +* {@link BpmUserGroupServiceImpl} 的单元测试类
  25 +*
  26 +* @author 芋道源码
  27 +*/
  28 +@Import(BpmUserGroupServiceImpl.class)
  29 +public class BpmUserGroupServiceTest extends BaseDbUnitTest {
  30 +
  31 + @Resource
  32 + private BpmUserGroupServiceImpl userGroupService;
  33 +
  34 + @Resource
  35 + private BpmUserGroupMapper userGroupMapper;
  36 +
  37 + @Test
  38 + public void testCreateUserGroup_success() {
  39 + // 准备参数
  40 + BpmUserGroupCreateReqVO reqVO = RandomUtils.randomPojo(BpmUserGroupCreateReqVO.class);
  41 +
  42 + // 调用
  43 + Long userGroupId = userGroupService.createUserGroup(reqVO);
  44 + // 断言
  45 + Assertions.assertNotNull(userGroupId);
  46 + // 校验记录的属性是否正确
  47 + BpmUserGroupDO userGroup = userGroupMapper.selectById(userGroupId);
  48 + AssertUtils.assertPojoEquals(reqVO, userGroup);
  49 + }
  50 +
  51 + @Test
  52 + public void testUpdateUserGroup_success() {
  53 + // mock 数据
  54 + BpmUserGroupDO dbUserGroup = RandomUtils.randomPojo(BpmUserGroupDO.class);
  55 + userGroupMapper.insert(dbUserGroup);// @Sql: 先插入出一条存在的数据
  56 + // 准备参数
  57 + BpmUserGroupUpdateReqVO reqVO = RandomUtils.randomPojo(BpmUserGroupUpdateReqVO.class, o -> {
  58 + o.setId(dbUserGroup.getId()); // 设置更新的 ID
  59 + });
  60 +
  61 + // 调用
  62 + userGroupService.updateUserGroup(reqVO);
  63 + // 校验是否更新正确
  64 + BpmUserGroupDO userGroup = userGroupMapper.selectById(reqVO.getId()); // 获取最新的
  65 + AssertUtils.assertPojoEquals(reqVO, userGroup);
  66 + }
  67 +
  68 + @Test
  69 + public void testUpdateUserGroup_notExists() {
  70 + // 准备参数
  71 + BpmUserGroupUpdateReqVO reqVO = RandomUtils.randomPojo(BpmUserGroupUpdateReqVO.class);
  72 +
  73 + // 调用, 并断言异常
  74 + AssertUtils.assertServiceException(() -> userGroupService.updateUserGroup(reqVO), USER_GROUP_NOT_EXISTS);
  75 + }
  76 +
  77 + @Test
  78 + public void testDeleteUserGroup_success() {
  79 + // mock 数据
  80 + BpmUserGroupDO dbUserGroup = RandomUtils.randomPojo(BpmUserGroupDO.class);
  81 + userGroupMapper.insert(dbUserGroup);// @Sql: 先插入出一条存在的数据
  82 + // 准备参数
  83 + Long id = dbUserGroup.getId();
  84 +
  85 + // 调用
  86 + userGroupService.deleteUserGroup(id);
  87 + // 校验数据不存在了
  88 + Assertions.assertNull(userGroupMapper.selectById(id));
  89 + }
  90 +
  91 + @Test
  92 + public void testDeleteUserGroup_notExists() {
  93 + // 准备参数
  94 + Long id = RandomUtils.randomLongId();
  95 +
  96 + // 调用, 并断言异常
  97 + AssertUtils.assertServiceException(() -> userGroupService.deleteUserGroup(id), USER_GROUP_NOT_EXISTS);
  98 + }
  99 +
  100 + @Test
  101 + public void testGetUserGroupPage() {
  102 + // mock 数据
  103 + BpmUserGroupDO dbUserGroup = RandomUtils.randomPojo(BpmUserGroupDO.class, o -> { // 等会查询到
  104 + o.setName("芋道源码");
  105 + o.setStatus(CommonStatusEnum.ENABLE.getStatus());
  106 + o.setCreateTime(DateUtils.buildTime(2021, 11, 11));
  107 + });
  108 + userGroupMapper.insert(dbUserGroup);
  109 + // 测试 name 不匹配
  110 + userGroupMapper.insert(cloneIgnoreId(dbUserGroup, o -> o.setName("芋道")));
  111 + // 测试 status 不匹配
  112 + userGroupMapper.insert(cloneIgnoreId(dbUserGroup, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
  113 + // 测试 createTime 不匹配
  114 + userGroupMapper.insert(cloneIgnoreId(dbUserGroup, o -> o.setCreateTime(DateUtils.buildTime(2021, 12, 12))));
  115 + // 准备参数
  116 + BpmUserGroupPageReqVO reqVO = new BpmUserGroupPageReqVO();
  117 + reqVO.setName("源码");
  118 + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
  119 + reqVO.setBeginCreateTime(DateUtils.buildTime(2021, 11, 10));
  120 + reqVO.setEndCreateTime(DateUtils.buildTime(2021, 11, 12));
  121 +
  122 + // 调用
  123 + PageResult<BpmUserGroupDO> pageResult = userGroupService.getUserGroupPage(reqVO);
  124 + // 断言
  125 + Assertions.assertEquals(1, pageResult.getTotal());
  126 + Assertions.assertEquals(1, pageResult.getList().size());
  127 + AssertUtils.assertPojoEquals(dbUserGroup, pageResult.getList().get(0));
  128 + }
  129 +
  130 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/test/resources/application-unit-test.yaml 0 → 100644
  1 +spring:
  2 + main:
  3 + lazy-initialization: true # 开启懒加载,加快速度
  4 + banner-mode: off # 单元测试,禁用 Banner
  5 +
  6 +--- #################### 数据库相关配置 ####################
  7 +
  8 +spring:
  9 + # 数据源配置项
  10 + datasource:
  11 + name: ruoyi-vue-pro
  12 + url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false; # MODE 使用 MySQL 模式;DATABASE_TO_UPPER 配置表和字段使用小写
  13 + driver-class-name: org.h2.Driver
  14 + username: sa
  15 + password:
  16 + druid:
  17 + async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度
  18 + initial-size: 1 # 单元测试,配置为 1,提升启动速度
  19 + sql:
  20 + init:
  21 + schema-locations: classpath:/sql/create_tables.sql
  22 +
  23 +mybatis:
  24 + lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试
  25 +
  26 +--- #################### 定时任务相关配置 ####################
  27 +
  28 +--- #################### 配置中心相关配置 ####################
  29 +
  30 +--- #################### 服务保障相关配置 ####################
  31 +
  32 +# Lock4j 配置项(单元测试,禁用 Lock4j)
  33 +
  34 +# Resilience4j 配置项
  35 +
  36 +--- #################### 监控相关配置 ####################
  37 +
  38 +--- #################### 芋道相关配置 ####################
  39 +
  40 +# 芋道配置项,设置当前项目所有自定义的配置
  41 +yudao:
  42 + info:
  43 + base-package: cn.iocoder.yudao.module
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/test/resources/logback.xml 0 → 100644
  1 +<configuration>
  2 + <!-- 引用 Spring Boot 的 logback 基础配置 -->
  3 + <include resource="org/springframework/boot/logging/logback/defaults.xml" />
  4 +</configuration>
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/test/resources/sql/clean.sql 0 → 100644
  1 +DELETE FROM "bpm_form";
  2 +DELETE FROM "bpm_user_group";
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/test/resources/sql/create_tables.sql 0 → 100644
  1 +CREATE TABLE IF NOT EXISTS "bpm_user_group" (
  2 + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
  3 + "name" varchar(63) NOT NULL,
  4 + "description" varchar(255) NOT NULL,
  5 + "status" tinyint NOT NULL,
  6 + "member_user_ids" varchar(255) NOT NULL,
  7 + "creator" varchar(64) DEFAULT '',
  8 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  9 + "updater" varchar(64) DEFAULT '',
  10 + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  11 + "deleted" bit NOT NULL DEFAULT FALSE,
  12 + PRIMARY KEY ("id")
  13 +) COMMENT '用户组';
  14 +
  15 +CREATE TABLE IF NOT EXISTS "bpm_form" (
  16 + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
  17 + "name" varchar(63) NOT NULL,
  18 + "status" tinyint NOT NULL,
  19 + "fields" varchar(255) NOT NULL,
  20 + "conf" varchar(255) NOT NULL,
  21 + "remark" varchar(255),
  22 + "creator" varchar(64) DEFAULT '',
  23 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  24 + "updater" varchar(64) DEFAULT '',
  25 + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  26 + "deleted" bit NOT NULL DEFAULT FALSE,
  27 + PRIMARY KEY ("id")
  28 +) COMMENT '动态表单';
... ...
yudao-server/pom.xml
... ... @@ -45,7 +45,7 @@
45 45 <!-- 默认引入 yudao-module-bpm-biz-flowable 实现,可以替换为 yudao-module-bpm-biz-activiti 实现-->
46 46 <dependency>
47 47 <groupId>cn.iocoder.boot</groupId>
48   - <artifactId>yudao-module-bpm-biz-flowable</artifactId>
  48 + <artifactId>yudao-module-bpm-biz</artifactId>
49 49 <version>${revision}</version>
50 50 </dependency>
51 51 <!-- <dependency>-->
... ...