增加初步驳回功能

dom4j增加失败
This commit is contained in:
kemengkai 2022-05-11 10:17:40 +08:00
parent e52200a205
commit d43006dce8
50 changed files with 1078 additions and 168 deletions

View File

@ -546,6 +546,7 @@ COMMIT;
DROP TABLE IF EXISTS `bpm_task_ext`;
CREATE TABLE `bpm_task_ext` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`task_def_key` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '流程任务key',
`assignee_user_id` bigint DEFAULT NULL COMMENT '任务的审批人',
`name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '任务的名字',
`task_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '任务的编号',

View File

@ -65,6 +65,7 @@
<tencentcloud-sdk-java.version>3.1.471</tencentcloud-sdk-java.version>
<yunpian-java-sdk.version>1.2.7</yunpian-java-sdk.version>
<justauth.version>1.4.0</justauth.version>
<dom4j.version>2.1.3</dom4j.version>
</properties>
<dependencyManagement>
@ -578,7 +579,13 @@
<artifactId>justauth-spring-boot-starter</artifactId> <!-- 社交登陆(例如说,个人微信、企业微信等等) -->
<version>${justauth.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.dom4j/dom4j -->
<!-- XML读写框架 -->
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>${dom4j.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

View File

@ -58,7 +58,8 @@ public class YudaoSwaggerAutoConfiguration {
.build()
.securitySchemes(securitySchemes())
.globalRequestParameters(globalRequestParameters())
.securityContexts(securityContexts());
.securityContexts(securityContexts())
.host("http://localhost:48080");
}
// ========== apiInfo ==========

View File

@ -10,6 +10,10 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>yudao-module-bpm-biz</artifactId>
<properties>
<dom4j.version>2.1.3</dom4j.version>
</properties>
<name>${project.artifactId}</name>
<description>
bpm-base 模块,实现公用的工作流的逻辑,提供给 bpm-activiti 和 bpm-flowable 复用
@ -36,6 +40,10 @@
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-data-permission</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
</dependency>
<!-- Web 相关 -->
<dependency>
@ -77,5 +85,11 @@
<version>1.4.196</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.dom4j/dom4j -->
<!-- XML读写框架 -->
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.apache.ibatis.annotations.Param;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.TaskService;
import org.springframework.security.access.prepost.PreAuthorize;
@ -17,6 +18,7 @@ import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
import java.util.Objects;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
@ -49,10 +51,17 @@ public class BpmTaskController {
@ApiImplicitParam(name = "processInstanceId", value = "流程实例的编号", required = true, dataTypeClass = String.class)
@PreAuthorize("@ss.hasPermission('bpm:task:query')")
public CommonResult<List<BpmTaskRespVO>> getTaskListByProcessInstanceId(
@RequestParam("processInstanceId") String processInstanceId) {
@RequestParam("processInstanceId") String processInstanceId) {
return success(taskService.getTaskListByProcessInstanceId(processInstanceId));
}
@GetMapping("/get")
@ApiOperation(value = "获取审批单详情", notes = "包括完成的、未完成的")
@ApiImplicitParam(name = "taskId", value = "任务Id", required = true, dataTypeClass = String.class)
public CommonResult<Object> getTask(@Param("taskId") String processInstanceId) {
return success(taskService.getTaskInfo(processInstanceId));
}
@PutMapping("/approve")
@ApiOperation("通过任务")
@PreAuthorize("@ss.hasPermission('bpm:task:update')")
@ -76,13 +85,14 @@ public class BpmTaskController {
taskService.updateTaskAssignee(getLoginUserId(), reqVO);
return success(true);
}
@PutMapping("/back")
@ApiOperation(value = "回退")
// @PreAuthorize("@ss.hasPermission('bpm:task:back')")
public CommonResult<Boolean> backTask(@Valid @RequestBody BpmTaskUpdateAssigneeReqVO reqVO) {
// @PreAuthorize("@ss.hasPermission('bpm:task:back')")
public CommonResult<Boolean> backTask(@Valid @RequestBody BpmTaskBackReqVO reqVO) {
//先硬编码到 回退到第一个审批节点
String destinationTaskDefKey = "task01";
taskService.backTask(reqVO.getId(),destinationTaskDefKey);
return success(true);
// String destinationTaskDefKey = "task01";
return taskService.backTask(reqVO);
}
}

View File

@ -0,0 +1,43 @@
package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
/**
* @author kemengkai
* @create 2022-05-07 08:05
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BpmTaskBackReqVO {
@ApiModelProperty(value = "用户id", required = true, example = "1")
@NotEmpty(message = "用户id不能为空")
private String userId;
@ApiModelProperty(value = "流程编号id", required = true, example = "730da750-cc4f-11ec-b58e-1e429355e4a0")
@NotEmpty(message = "流程编号id不能为空")
private String procInstId;
@ApiModelProperty(value = "当前任务id", required = true, example = "730da750-cc4f-11ec-b58e-1e429355e4a0")
@NotEmpty(message = "当前任务id不能为空")
private String taskId;
@ApiModelProperty(value = "当前流程任务id", required = true, example = "Activity_1jlembv")
@NotNull(message = "当前流程任务id不能为空")
private String oldTaskDefKey;
@ApiModelProperty(value = "准备回退的流程任务id", required = true, example = "task01")
@NotNull(message = "准备回退流程任务id不能为空")
private String newTaskDefKey;
@ApiModelProperty(value = "审批结果", required = true, example = "任务驳回")
@NotNull(message = "审批结果")
private String comment;
}

View File

@ -35,5 +35,4 @@ public class BpmTaskRespVO extends BpmTaskDonePageItemRespVO {
private String deptName;
}
}

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.bpm.convert.task;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity.BpmActivityRespVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmActivityDO;
import org.flowable.engine.history.HistoricActivityInstance;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@ -19,11 +20,11 @@ public interface BpmActivityConvert {
BpmActivityConvert INSTANCE = Mappers.getMapper(BpmActivityConvert.class);
List<BpmActivityRespVO> convertList(List<HistoricActivityInstance> list);
List<BpmActivityRespVO> convertList(List<BpmActivityDO> list);
@Mappings({
@Mapping(source = "activityId", target = "key"),
@Mapping(source = "activityType", target = "type")
})
BpmActivityRespVO convert(HistoricActivityInstance bean);
BpmActivityRespVO convert(BpmActivityDO bean);
}

View File

@ -1,11 +1,13 @@
package cn.iocoder.yudao.module.bpm.convert.task;
import cn.hutool.core.util.BooleanUtil;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskDonePageItemRespVO;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskTodoPageItemRespVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceResultEnum;
import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
@ -17,9 +19,10 @@ import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.mapstruct.*;
import org.mapstruct.factory.Mappers;
import org.springframework.beans.BeanUtils;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
/**
* Bpm 任务 Convert
@ -31,8 +34,37 @@ public interface BpmTaskConvert {
BpmTaskConvert INSTANCE = Mappers.getMapper(BpmTaskConvert.class);
default List<BpmTaskTodoPageItemRespVO> convertList1(List<Task> tasks, Map<String, ProcessInstance> processInstanceMap,
Map<Long, AdminUserRespDTO> userMap) {
/**
* 复制对象
*
* @param source 要复制的对象
* @param target 目标 复制到此对象
* @param <T>
*
* @return
*/
public static <T> T copy(Object source, Class<T> target) {
if (source == null || target == null) {
return null;
}
try {
T newInstance = target.newInstance();
BeanUtils.copyProperties(source, newInstance);
return newInstance;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
default <T, K> List<K> copyList(List<T> source, Class<K> target) {
if (null == source || source.isEmpty()) {
return Collections.emptyList();
}
return source.stream().map(e -> copy(e, target)).collect(Collectors.toList());
}
default List<BpmTaskTodoPageItemRespVO> convertList1(List<Task> tasks,
Map<String, ProcessInstance> processInstanceMap, Map<Long, AdminUserRespDTO> userMap) {
return CollectionUtils.convertList(tasks, task -> {
BpmTaskTodoPageItemRespVO respVO = convert1(task);
ProcessInstance processInstance = processInstanceMap.get(task.getProcessInstanceId());
@ -49,13 +81,12 @@ public interface BpmTaskConvert {
@Named("convertSuspendedToSuspensionState")
default Integer convertSuspendedToSuspensionState(boolean suspended) {
return suspended ? SuspensionState.SUSPENDED.getStateCode() :
SuspensionState.ACTIVE.getStateCode();
return suspended ? SuspensionState.SUSPENDED.getStateCode() : SuspensionState.ACTIVE.getStateCode();
}
default List<BpmTaskDonePageItemRespVO> convertList2(List<HistoricTaskInstance> tasks, Map<String, BpmTaskExtDO> bpmTaskExtDOMap,
Map<String, HistoricProcessInstance> historicProcessInstanceMap,
Map<Long, AdminUserRespDTO> userMap) {
default List<BpmTaskDonePageItemRespVO> convertList2(List<HistoricTaskInstance> tasks,
Map<String, BpmTaskExtDO> bpmTaskExtDOMap, Map<String, HistoricProcessInstance> historicProcessInstanceMap,
Map<Long, AdminUserRespDTO> userMap) {
return CollectionUtils.convertList(tasks, task -> {
BpmTaskDonePageItemRespVO respVO = convert2(task);
BpmTaskExtDO taskExtDO = bpmTaskExtDOMap.get(task.getId());
@ -71,18 +102,16 @@ public interface BpmTaskConvert {
BpmTaskDonePageItemRespVO convert2(HistoricTaskInstance bean);
@Mappings({
@Mapping(source = "processInstance.id", target = "id"),
@Mapping(source = "processInstance.name", target = "name"),
@Mapping(source = "processInstance.startUserId", target = "startUserId"),
@Mapping(source = "processInstance.processDefinitionId", target = "processDefinitionId"),
@Mapping(source = "startUser.nickname", target = "startUserNickname")
})
@Mappings({@Mapping(source = "processInstance.id", target = "id"),
@Mapping(source = "processInstance.name", target = "name"),
@Mapping(source = "processInstance.startUserId", target = "startUserId"),
@Mapping(source = "processInstance.processDefinitionId", target = "processDefinitionId"),
@Mapping(source = "startUser.nickname", target = "startUserNickname")})
BpmTaskTodoPageItemRespVO.ProcessInstance convert(ProcessInstance processInstance, AdminUserRespDTO startUser);
default List<BpmTaskRespVO> convertList3(List<HistoricTaskInstance> tasks, Map<String, BpmTaskExtDO> bpmTaskExtDOMap,
HistoricProcessInstance processInstance, Map<Long, AdminUserRespDTO> userMap,
Map<Long, DeptRespDTO> deptMap) {
default List<BpmTaskRespVO> convertList3(List<HistoricTaskInstance> tasks,
Map<String, BpmTaskExtDO> bpmTaskExtDOMap, HistoricProcessInstance processInstance,
Map<Long, AdminUserRespDTO> userMap, Map<Long, DeptRespDTO> deptMap) {
return CollectionUtils.convertList(tasks, task -> {
BpmTaskRespVO respVO = convert3(task);
BpmTaskExtDO taskExtDO = bpmTaskExtDOMap.get(task.getId());
@ -111,37 +140,56 @@ public interface BpmTaskConvert {
@Mapping(target = "id", ignore = true)
void copyTo(BpmTaskExtDO from, @MappingTarget BpmTaskDonePageItemRespVO to);
@Mappings({
@Mapping(source = "processInstance.id", target = "id"),
@Mapping(source = "processInstance.name", target = "name"),
@Mapping(source = "processInstance.startUserId", target = "startUserId"),
@Mapping(source = "processInstance.processDefinitionId", target = "processDefinitionId"),
@Mapping(source = "startUser.nickname", target = "startUserNickname")
})
BpmTaskTodoPageItemRespVO.ProcessInstance convert(HistoricProcessInstance processInstance, AdminUserRespDTO startUser);
@Mappings({@Mapping(source = "processInstance.id", target = "id"),
@Mapping(source = "processInstance.name", target = "name"),
@Mapping(source = "processInstance.startUserId", target = "startUserId"),
@Mapping(source = "processInstance.processDefinitionId", target = "processDefinitionId"),
@Mapping(source = "startUser.nickname", target = "startUserNickname")})
BpmTaskTodoPageItemRespVO.ProcessInstance convert(HistoricProcessInstance processInstance,
AdminUserRespDTO startUser);
default BpmTaskExtDO convert2TaskExt(Task task){
BpmTaskExtDO taskExtDO = new BpmTaskExtDO()
.setTaskId(task.getId())
.setAssigneeUserId(NumberUtils.parseLong(task.getAssignee()))
.setName(task.getName())
.setProcessDefinitionId(task.getProcessDefinitionId())
.setProcessInstanceId(task.getProcessInstanceId());
default BpmTaskExtDO convert2TaskExt(Task task) {
BpmTaskExtDO taskExtDO = new BpmTaskExtDO().setTaskId(task.getId()).setTaskDefKey(task.getTaskDefinitionKey())
.setAssigneeUserId(NumberUtils.parseLong(task.getAssignee())).setName(task.getName())
.setProcessDefinitionId(task.getProcessDefinitionId()).setProcessInstanceId(task.getProcessInstanceId());
taskExtDO.setCreateTime(task.getCreateTime());
return taskExtDO;
}
default BpmMessageSendWhenTaskCreatedReqDTO convert(ProcessInstance processInstance, AdminUserRespDTO startUser, Task task) {
default BpmMessageSendWhenTaskCreatedReqDTO convert(ProcessInstance processInstance, AdminUserRespDTO startUser,
Task task) {
BpmMessageSendWhenTaskCreatedReqDTO reqDTO = new BpmMessageSendWhenTaskCreatedReqDTO();
reqDTO.setProcessInstanceId(processInstance.getProcessInstanceId())
.setProcessInstanceName(processInstance.getName())
.setStartUserId(startUser.getId())
.setStartUserNickname(startUser.getNickname())
.setTaskId(task.getId())
.setTaskName(task.getName())
.setAssigneeUserId(NumberUtils.parseLong(task.getAssignee()));
.setProcessInstanceName(processInstance.getName()).setStartUserId(startUser.getId())
.setStartUserNickname(startUser.getNickname()).setTaskId(task.getId()).setTaskName(task.getName())
.setAssigneeUserId(NumberUtils.parseLong(task.getAssignee()));
return reqDTO;
}
}
/**
* bpmTaskExtDo 类数据去重
*
* @param bpmTaskExtDOList bpmTaskExtDo 类列表
*
* @return 返回新的list
*/
default List<BpmTaskExtDO> distinct(List<BpmTaskExtDO> bpmTaskExtDOList) {
HashMap<String, BpmTaskExtDO> tmpMap = new HashMap<>(50);
List<BpmTaskExtDO> result = new ArrayList<>();
for (BpmTaskExtDO bpmTaskExtDO : bpmTaskExtDOList) {
boolean containsResult = tmpMap.containsKey(bpmTaskExtDO.getTaskDefKey());
if (BooleanUtil.isFalse(containsResult)) {
tmpMap.put(bpmTaskExtDO.getTaskDefKey(), bpmTaskExtDO);
}
BpmTaskExtDO tmpBpmTaskExtDO = tmpMap.get(bpmTaskExtDO.getTaskDefKey());
if (bpmTaskExtDO.getTaskDefKey().equals(tmpBpmTaskExtDO.getTaskDefKey())) {
if (!bpmTaskExtDO.getResult().equals(BpmProcessInstanceResultEnum.PROCESS.getResult())) {
tmpMap.remove(bpmTaskExtDO.getTaskDefKey());
tmpMap.put(bpmTaskExtDO.getTaskDefKey(), bpmTaskExtDO);
}
}
}
tmpMap.forEach((key, var) -> result.add(var));
return result;
}
}

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.bpm.dal.dataobject.definition;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmModelFormTypeEnum;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

View File

@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.bpm.dal.dataobject.definition;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskAssignRuleTypeEnum;
import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskRuleScriptEnum;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

View File

@ -1,6 +1,6 @@
package cn.iocoder.yudao.module.bpm.dal.dataobject.oa;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceResultEnum;
import lombok.*;
import java.util.*;
import com.baomidou.mybatisplus.annotation.*;

View File

@ -0,0 +1,105 @@
package cn.iocoder.yudao.module.bpm.dal.dataobject.task;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT;
/**
* 任务流程关联表
*
* @author kemengkai
* @create 2022-05-09 10:33
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BpmActivityDO {
/**
* 任务流程关联id
*/
private String id;
/**
* 审批结果
*/
private Integer rev;
/**
* 任务流程部署id
*/
private String procDefId;
/**
* 任务流程id
*/
private String processInstanceId;
/**
* 任务执行id
*/
private String executionId;
/**
* 任务key
*/
private String activityId;
/**
* 任务id
*/
private String taskId;
/**
* 调用流程id
*/
private String callProcInstId;
/**
* 任务名称
*/
private String activityName;
/**
* 任务类型
*/
private String activityType;
/**
* 任务审批人id
*/
private String assignee;
/**
* 任务开始时间
*/
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
private Date startTime;
/**
* 任务结束时间
*/
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
private Date endTime;
private Integer transactionOrder;
private Long duration;
/**
* 删除结果
*/
private String deleteReason;
/**
* 租户id
*/
private String tenantId;
}

View File

@ -1,8 +1,8 @@
package cn.iocoder.yudao.module.bpm.dal.dataobject.task;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceResultEnum;
import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceStatusEnum;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.bpm.dal.dataobject.task;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceResultEnum;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@ -27,6 +27,11 @@ public class BpmTaskExtDO extends BaseDO {
*/
@TableId
private Long id;
/**
* 流程任务key
*/
private String taskDefKey;
/**
* 任务的审批人
*

View File

@ -0,0 +1,50 @@
package cn.iocoder.yudao.module.bpm.dal.mysql.task;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmActivityDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author kemengkai
* @create 2022-05-09 09:26
*/
@Mapper
public interface BpmActivityMapper extends BaseMapperX<BpmActivityDO> {
/**
* 获取所有历史任务
*
* @return 返回历史任务
*/
List<BpmActivityDO> listAll();
/**
* 获取指定流程的历史任务
*
* @param procInstId 流程id
*
* @return 返回历史任务
*/
List<BpmActivityDO> listAllByProcInstIdAndDelete(@Param("procInstId") String procInstId);
/**
* 逻辑删除hiActInst表任务
*
* @param taskIdList 任务列表
*
* @return 返回是否成功
*/
Boolean delHiActInstByTaskId(@Param("taskIdList") List<String> taskIdList);
/**
* 逻辑删除hiTaskInst任务
*
* @param taskIdList 任务列表
*
* @return 返回是否成功
*/
Boolean delHiTaskInstByTaskId(@Param("taskIdList") List<String> taskIdList);
}

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.bpm.dal.mysql.task;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@ -20,14 +21,43 @@ public interface BpmTaskExtMapper extends BaseMapperX<BpmTaskExtDO> {
return selectList(BpmTaskExtDO::getTaskId, taskIds);
}
/**
* 查询任务
*
* @param procInstId 流程id
*
* @return 返回任务列表
*/
@TenantIgnore
List<BpmTaskExtDO> listByProcInstId(@Param("procInstId") String procInstId);
default List<BpmTaskExtDO> selectListByProcessInstanceId(String processInstanceId) {
return selectList("process_instance_id", processInstanceId);
}
/**
* 修改或签任务信息
* 删除非当前相同taskDefKey非进行中的任务
*
* @param entity 任务信息
*/
void updateUserOrSignTask(@Param("entity") BpmTaskExtDO entity);
void delTaskByProcInstIdAndTaskIdAndTaskDefKey(@Param("entity") BpmTaskExtDO entity);
/**
* 任务驳回
*
* @param taskId 任务列表
* @param comment 驳回理由
*
* @return 返回驳回结果是否成功
*/
Boolean backByTaskId(@Param("taskId") String taskId, @Param("comment") String comment);
/**
* 逻辑删除任务
*
* @param taskIdList 任务id列表
*
* @return 返回是否成功
*/
Boolean delByTaskIds(@Param("taskIdList") List<String> taskIdList);
}

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.bpm.enums.definition;
package cn.iocoder.yudao.module.bpm.domain.enums.definition;
import lombok.AllArgsConstructor;
import lombok.Getter;

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.bpm.enums.definition;
package cn.iocoder.yudao.module.bpm.domain.enums.definition;
import lombok.AllArgsConstructor;
import lombok.Getter;

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.bpm.enums.definition;
package cn.iocoder.yudao.module.bpm.domain.enums.definition;
import lombok.AllArgsConstructor;
import lombok.Getter;

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.bpm.enums.message;
package cn.iocoder.yudao.module.bpm.domain.enums.message;
import lombok.AllArgsConstructor;
import lombok.Getter;

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.bpm.enums.task;
package cn.iocoder.yudao.module.bpm.domain.enums.task;
import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.bpm.enums.task;
package cn.iocoder.yudao.module.bpm.domain.enums.task;
import lombok.AllArgsConstructor;
import lombok.Getter;
@ -15,7 +15,8 @@ public enum BpmProcessInstanceResultEnum {
PROCESS(1, "处理中"),
APPROVE(2, "通过"),
REJECT(3, "不通过"),
CANCEL(4, "已取消");
CANCEL(4, "已取消"),
BACK(5, "退回/驳回");
/**
* 结果

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.bpm.enums.task;
package cn.iocoder.yudao.module.bpm.domain.enums.task;
import lombok.AllArgsConstructor;
import lombok.Getter;

View File

@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.bpm.domain.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDate;
/**
* 审批流程VO
*
* @author kemengkai
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ApproveProcInstVO {
@ApiModelProperty("任务id")
private String id;
@ApiModelProperty("任务部署key")
private String taskDefKey;
@ApiModelProperty("任务名称")
private String name;
@ApiModelProperty("审批人登录名")
private String assignee;
@ApiModelProperty("审批人姓名")
private String assigneeName;
@ApiModelProperty("审批回复")
private String taskComment;
@ApiModelProperty("审批完成时间")
private LocalDate endTime;
}

View File

@ -0,0 +1,28 @@
package cn.iocoder.yudao.module.bpm.framework.bpm.config;
import cn.iocoder.yudao.framework.security.config.AuthorizeRequestsCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
/**
* @author kemengkai
* @create 2022-05-07 08:15
*/
@Configuration("bpmSecurityConfiguration")
public class BpmSecurityConfiguration {
@Bean("bpmAuthorizeRequestsCustomizer")
public AuthorizeRequestsCustomizer authorizeRequestsCustomizer() {
return new AuthorizeRequestsCustomizer() {
@Override
public void customize(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry) {
// 任务回退接口
registry.antMatchers(buildAdminApi("/bpm/task/back")).permitAll();
}
};
}
}

View File

@ -4,7 +4,7 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskAssignRuleTypeEnum;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;

View File

@ -7,7 +7,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskAssignRuleTypeEnum;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;

View File

@ -1,6 +1,6 @@
package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskRuleScriptEnum;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import java.util.Set;

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskRuleScriptEnum;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.springframework.stereotype.Component;

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskRuleScriptEnum;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.springframework.stereotype.Component;

View File

@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl
import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskRuleScriptEnum;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;

View File

@ -9,7 +9,7 @@ import cn.iocoder.yudao.module.bpm.convert.definition.BpmFormConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmFormMapper;
import cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmModelFormTypeEnum;
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmFormFieldRespDTO;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;

View File

@ -10,7 +10,7 @@ import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*;
import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmModelFormTypeEnum;
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
import lombok.extern.slf4j.Slf4j;

View File

@ -13,7 +13,7 @@ import cn.iocoder.yudao.module.bpm.convert.definition.BpmTaskAssignRuleConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper;
import cn.iocoder.yudao.module.bpm.enums.DictTypeConstants;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskAssignRuleTypeEnum;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.PostApi;
import cn.iocoder.yudao.module.system.api.dict.DictDataApi;

View File

@ -1,6 +1,6 @@
package cn.iocoder.yudao.module.bpm.service.definition.dto;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmModelFormTypeEnum;
import lombok.Data;
/**

View File

@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.bpm.service.definition.dto;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmModelFormTypeEnum;
import lombok.Data;
import javax.validation.constraints.AssertTrue;

View File

@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.bpm.service.message;
import cn.iocoder.yudao.framework.web.config.WebProperties;
import cn.iocoder.yudao.module.bpm.convert.message.BpmMessageConvert;
import cn.iocoder.yudao.module.bpm.enums.message.BpmMessageEnum;
import cn.iocoder.yudao.module.bpm.domain.enums.message.BpmMessageEnum;
import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceApproveReqDTO;
import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceRejectReqDTO;
import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO;

View File

@ -9,7 +9,7 @@ import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOALeavePageReqVO;
import cn.iocoder.yudao.module.bpm.convert.oa.BpmOALeaveConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALeaveDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOALeaveMapper;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceResultEnum;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

View File

@ -1,28 +1,19 @@
package cn.iocoder.yudao.module.bpm.service.task;
import cn.hutool.core.io.IoUtil;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity.BpmActivityRespVO;
import cn.iocoder.yudao.module.bpm.convert.task.BpmActivityConvert;
import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmActivityDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmActivityMapper;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.HistoryService;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.image.ProcessDiagramGenerator;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.io.InputStream;
import java.util.Collections;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_DEFINITION_BPMN_MODEL_NOT_EXISTS;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_INSTANCE_NOT_EXISTS;
/**
* BPM 活动实例 Service 实现类
@ -36,14 +27,15 @@ public class BpmActivityServiceImpl implements BpmActivityService {
@Resource
private HistoryService historyService;
@Resource
private BpmActivityMapper bpmActivityMapper;
@Override
public List<BpmActivityRespVO> getActivityListByProcessInstanceId(String processInstanceId) {
List<HistoricActivityInstance> activityList = historyService.createHistoricActivityInstanceQuery()
.processInstanceId(processInstanceId).list();
return BpmActivityConvert.INSTANCE.convertList(activityList);
@TenantIgnore
public List<BpmActivityRespVO> getActivityListByProcessInstanceId(String procInstId) {
// List<HistoricActivityInstance> activityList = historyService.createHistoricActivityInstanceQuery()
// .processInstanceId(procInstId).list();
List<BpmActivityDO> bpmActivityDOList = bpmActivityMapper.listAllByProcInstIdAndDelete(procInstId);
return BpmActivityConvert.INSTANCE.convertList(bpmActivityDOList);
}
}

View File

@ -11,9 +11,9 @@ import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceDeleteReasonEnum;
import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceResultEnum;
import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceStatusEnum;
import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher;
import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;

View File

@ -1,11 +1,11 @@
package cn.iocoder.yudao.module.bpm.service.task;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
import org.flowable.task.api.Task;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
@ -20,16 +20,19 @@ public interface BpmTaskService {
/**
* 获得待办的流程任务分页
*
* @param userId 用户编号
* @param userId 用户编号
* @param pageReqVO 分页请求
*
* @return 流程任务分页
*/
PageResult<BpmTaskTodoPageItemRespVO> getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageReqVO);
/**
* 获得已办的流程任务分页
*
* @param userId 用户编号
* @param userId 用户编号
* @param pageReqVO 分页请求
*
* @return 流程任务分页
*/
PageResult<BpmTaskDonePageItemRespVO> getDoneTaskPage(Long userId, BpmTaskDonePageReqVO pageReqVO);
@ -38,17 +41,19 @@ public interface BpmTaskService {
* 获得流程任务 Map
*
* @param processInstanceIds 流程实例的编号数组
*
* @return 流程任务 Map
*/
default Map<String, List<Task>> getTaskMapByProcessInstanceIds(List<String> processInstanceIds) {
return CollectionUtils.convertMultiMap(getTasksByProcessInstanceIds(processInstanceIds),
Task::getProcessInstanceId);
Task::getProcessInstanceId);
}
/**
* 获得流程任务列表
*
* @param processInstanceIds 流程实例的编号数组
*
* @return 流程任务列表
*/
List<Task> getTasksByProcessInstanceIds(List<String> processInstanceIds);
@ -57,15 +62,25 @@ public interface BpmTaskService {
* 获得指令流程实例的流程任务列表包括所有状态的
*
* @param processInstanceId 流程实例的编号
*
* @return 流程任务列表
*/
List<BpmTaskRespVO> getTaskListByProcessInstanceId(String processInstanceId);
/**
* 获取任务详情
*
* @param processInstanceId 流程实例的编号
*
* @return 流程任务列表
*/
List<BpmTaskRespVO> getTaskInfo(String processInstanceId);
/**
* 通过任务
*
* @param userId 用户编号
* @param reqVO 通过请求
* @param reqVO 通过请求
*/
void approveTask(Long userId, @Valid BpmTaskApproveReqVO reqVO);
@ -73,28 +88,30 @@ public interface BpmTaskService {
* 不通过任务
*
* @param userId 用户编号
* @param reqVO 不通过请求
* @param reqVO 不通过请求
*/
void rejectTask(Long userId, @Valid BpmTaskRejectReqVO reqVO);
/**
* 回退任务
*
* @param taskId 任务编号
* @param userId 用户id
* @param reqVO 回退任务信息
*/
void backTask(String taskId,String destinationTaskDefKey);
CommonResult<Boolean> backTask(BpmTaskBackReqVO reqVO);
/**
* 将流程任务分配给指定用户
*
* @param userId 用户编号
* @param reqVO 分配请求
* @param reqVO 分配请求
*/
void updateTaskAssignee(Long userId, BpmTaskUpdateAssigneeReqVO reqVO);
/**
* 将流程任务分配给指定用户
*
* @param id 流程任务编号
* @param id 流程任务编号
* @param userId 用户编号
*/
void updateTaskAssignee(String id, Long userId);

View File

@ -2,17 +2,21 @@ package cn.iocoder.yudao.module.bpm.service.task;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
import cn.iocoder.yudao.framework.common.util.object.PageUtils;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmActivityDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper;
import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmActivityMapper;
import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmTaskExtMapper;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskAssignRuleTypeEnum;
import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceResultEnum;
import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
@ -36,10 +40,12 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
/**
@ -50,7 +56,7 @@ import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
*/
@Slf4j
@Service
public class BpmTaskServiceImpl implements BpmTaskService{
public class BpmTaskServiceImpl implements BpmTaskService {
@Resource
private TaskService taskService;
@ -71,13 +77,14 @@ public class BpmTaskServiceImpl implements BpmTaskService{
private BpmMessageService messageService;
@Resource
private BpmTaskAssignRuleMapper taskAssignRuleMapper;
@Resource
private BpmActivityMapper bpmActivityMapper;
@Override
public PageResult<BpmTaskTodoPageItemRespVO> getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageVO) {
// 查询待办任务
TaskQuery taskQuery = taskService.createTaskQuery()
.taskAssignee(String.valueOf(userId)) // 分配给自己
.orderByTaskCreateTime().desc(); // 创建时间倒序
TaskQuery taskQuery = taskService.createTaskQuery().taskAssignee(String.valueOf(userId)) // 分配给自己
.orderByTaskCreateTime().desc(); // 创建时间倒序
if (StrUtil.isNotBlank(pageVO.getName())) {
taskQuery.taskNameLike("%" + pageVO.getName() + "%");
}
@ -94,23 +101,22 @@ public class BpmTaskServiceImpl implements BpmTaskService{
}
// 获得 ProcessInstance Map
Map<String, ProcessInstance> processInstanceMap = processInstanceService.getProcessInstanceMap(
convertSet(tasks, Task::getProcessInstanceId));
Map<String, ProcessInstance> processInstanceMap =
processInstanceService.getProcessInstanceMap(convertSet(tasks, Task::getProcessInstanceId));
// 获得 User Map
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
convertSet(processInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId())));
convertSet(processInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId())));
// 拼接结果
return new PageResult<>(BpmTaskConvert.INSTANCE.convertList1(tasks, processInstanceMap, userMap),
taskQuery.count());
taskQuery.count());
}
@Override
public PageResult<BpmTaskDonePageItemRespVO> getDoneTaskPage(Long userId, BpmTaskDonePageReqVO pageVO) {
// 查询已办任务
HistoricTaskInstanceQuery taskQuery = historyService.createHistoricTaskInstanceQuery()
.finished() // 已完成
.taskAssignee(String.valueOf(userId)) // 分配给自己
.orderByHistoricTaskInstanceEndTime().desc(); // 审批时间倒序
HistoricTaskInstanceQuery taskQuery = historyService.createHistoricTaskInstanceQuery().finished() // 已完成
.taskAssignee(String.valueOf(userId)) // 分配给自己
.orderByHistoricTaskInstanceEndTime().desc(); // 审批时间倒序
if (StrUtil.isNotBlank(pageVO.getName())) {
taskQuery.taskNameLike("%" + pageVO.getName() + "%");
}
@ -127,17 +133,20 @@ public class BpmTaskServiceImpl implements BpmTaskService{
}
// 获得 TaskExtDO Map
List<BpmTaskExtDO> bpmTaskExtDOs = taskExtMapper.selectListByTaskIds(convertSet(tasks, HistoricTaskInstance::getId));
List<BpmTaskExtDO> bpmTaskExtDOs =
taskExtMapper.selectListByTaskIds(convertSet(tasks, HistoricTaskInstance::getId));
Map<String, BpmTaskExtDO> bpmTaskExtDOMap = convertMap(bpmTaskExtDOs, BpmTaskExtDO::getTaskId);
// 获得 ProcessInstance Map
Map<String, HistoricProcessInstance> historicProcessInstanceMap = processInstanceService.getHistoricProcessInstanceMap(
Map<String, HistoricProcessInstance> historicProcessInstanceMap =
processInstanceService.getHistoricProcessInstanceMap(
convertSet(tasks, HistoricTaskInstance::getProcessInstanceId));
// 获得 User Map
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
convertSet(historicProcessInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId())));
convertSet(historicProcessInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId())));
// 拼接结果
return new PageResult<>(BpmTaskConvert.INSTANCE.convertList2(tasks, bpmTaskExtDOMap, historicProcessInstanceMap, userMap),
taskQuery.count());
return new PageResult<>(
BpmTaskConvert.INSTANCE.convertList2(tasks, bpmTaskExtDOMap, historicProcessInstanceMap, userMap),
taskQuery.count());
}
@Override
@ -151,17 +160,22 @@ public class BpmTaskServiceImpl implements BpmTaskService{
@Override
public List<BpmTaskRespVO> getTaskListByProcessInstanceId(String processInstanceId) {
// 获得任务列表
List<HistoricTaskInstance> tasks = historyService.createHistoricTaskInstanceQuery()
.processInstanceId(processInstanceId)
List<HistoricTaskInstance> tasks =
historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId)
.orderByHistoricTaskInstanceStartTime().desc() // 创建时间倒序
.list();
if (CollUtil.isEmpty(tasks)) {
return Collections.emptyList();
}
// 获得 TaskExtDO Map
List<BpmTaskExtDO> bpmTaskExtDOs = taskExtMapper.selectListByTaskIds(convertSet(tasks, HistoricTaskInstance::getId));
Map<String, BpmTaskExtDO> bpmTaskExtDOMap = convertMap(bpmTaskExtDOs, BpmTaskExtDO::getTaskId);
// List<BpmTaskExtDO> bpmTaskExtDOList =
// taskExtMapper.selectListByTaskIds(convertSet(tasks, HistoricTaskInstance::getId));
List<BpmTaskExtDO> bpmTaskExtDOList = taskExtMapper.listByProcInstId(processInstanceId);
// List<BpmTaskExtDO> bpmTaskExtDOList = BpmTaskConvert.INSTANCE.distinct(tmpBpmTaskExtDOList);
// bpmTaskExtDOList.forEach(var -> log.info("var = " + var));
Map<String, BpmTaskExtDO> bpmTaskExtDoMap = convertMap(bpmTaskExtDOList, BpmTaskExtDO::getTaskId);
// 获得 ProcessInstance Map
HistoricProcessInstance processInstance = processInstanceService.getHistoricProcessInstance(processInstanceId);
// 获得 User Map
@ -172,7 +186,25 @@ public class BpmTaskServiceImpl implements BpmTaskService{
Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
// 拼接数据
return BpmTaskConvert.INSTANCE.convertList3(tasks, bpmTaskExtDOMap, processInstance, userMap, deptMap);
return BpmTaskConvert.INSTANCE.convertList3(tasks, bpmTaskExtDoMap, processInstance, userMap, deptMap);
}
@Override
public List<BpmTaskRespVO> getTaskInfo(String processInstanceId) {
List<BpmTaskExtDO> bpmTaskExtDOList = taskExtMapper.listByProcInstId(processInstanceId);
Map<String, BpmTaskExtDO> bpmTaskExtDoMap = convertMap(bpmTaskExtDOList, BpmTaskExtDO::getTaskId);
// 获得 ProcessInstance Map
HistoricProcessInstance processInstance = processInstanceService.getHistoricProcessInstance(processInstanceId);
// 获得 User Map
Set<Long> userIds = bpmTaskExtDOList.stream().map(BpmTaskExtDO::getAssigneeUserId).collect(Collectors.toSet());
userIds.add(NumberUtils.parseLong(processInstance.getStartUserId()));
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds);
// 拼接数据
return new ArrayList<>();
}
@Override
@ -199,9 +231,9 @@ public class BpmTaskServiceImpl implements BpmTaskService{
task.getTaskDefinitionKey());
if (CollUtil.isNotEmpty(bpmTaskAssignRuleList) && bpmTaskAssignRuleList.size() > 0) {
if (BpmTaskAssignRuleTypeEnum.USER_OR_SIGN.getType().equals(bpmTaskAssignRuleList.get(0).getType())) {
taskExtMapper.updateUserOrSignTask(
(BpmTaskExtDO)new BpmTaskExtDO().setTaskId(task.getId()).setName(task.getName())
.setProcessInstanceId(task.getProcessInstanceId()).setDeleted(true));
taskExtMapper.delTaskByProcInstIdAndTaskIdAndTaskDefKey(
new BpmTaskExtDO().setTaskId(task.getId()).setTaskDefKey(task.getTaskDefinitionKey())
.setProcessInstanceId(task.getProcessInstanceId()));
}
}
}
@ -220,18 +252,45 @@ public class BpmTaskServiceImpl implements BpmTaskService{
processInstanceService.updateProcessInstanceExtReject(instance.getProcessInstanceId(), reqVO.getComment());
// 更新任务拓展表为不通过
taskExtMapper.updateByTaskId(new BpmTaskExtDO().setTaskId(task.getId())
.setResult(BpmProcessInstanceResultEnum.REJECT.getResult()).setComment(reqVO.getComment()));
taskExtMapper.updateByTaskId(
new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.REJECT.getResult())
.setComment(reqVO.getComment()));
}
@Override
public void backTask(String taskId,String destinationTaskDefKey) {
Task currentTask = taskService.createTaskQuery().taskId(taskId).singleResult();
@Transactional(rollbackFor = Exception.class)
@TenantIgnore
public CommonResult<Boolean> backTask(BpmTaskBackReqVO reqVO) {
Long userId = Long.valueOf(reqVO.getUserId());
// 校验任务存在
Task task = checkTask(userId, reqVO.getTaskId());
ArrayList<String> oldTaskDefKeyList = CollUtil.newArrayList(reqVO.getOldTaskDefKey());
runtimeService.createChangeActivityStateBuilder()
.processInstanceId(currentTask.getProcessInstanceId())
.moveActivityIdTo(currentTask.getTaskDefinitionKey(), destinationTaskDefKey)
.changeState();
// List<HistoricActivityInstance> hisActInstList =
// historyService.createHistoricActivityInstanceQuery().processInstanceId(reqVO.getProcInstId()).list();
List<BpmActivityDO> bpmActivityDOList = bpmActivityMapper.listAllByProcInstIdAndDelete(reqVO.getProcInstId());
// List<BpmActivityDO> bpmActivityDOList = BpmTaskConvert.INSTANCE.copyList(hisActInstList, BpmActivityDO.class);
// bpmActivityDOList.forEach(bpmActivityDO -> log.info("bpmActivityDO = " + bpmActivityDO));
List<String> taskIdList = bpmActivityDOList.stream().filter(
bpmActivityDO -> bpmActivityDO.getActivityId().equals(reqVO.getOldTaskDefKey())
&& !bpmActivityDO.getTaskId().equals(reqVO.getTaskId())).map(BpmActivityDO::getTaskId)
.collect(Collectors.toList());
// 使用flowable更改任务节点
runtimeService.createChangeActivityStateBuilder().processInstanceId(reqVO.getProcInstId())
.moveActivityIdsToSingleActivityId(oldTaskDefKeyList, reqVO.getNewTaskDefKey()).changeState();
// 逻辑删除hiActInst表任务
Boolean delHiActInstResult = bpmActivityMapper.delHiActInstByTaskId(taskIdList);
// 逻辑删除hiTaskInst表任务
Boolean delHiTaskInstResult = bpmActivityMapper.delHiTaskInstByTaskId(taskIdList);
// 更新任务拓展表
Boolean backResult = taskExtMapper.backByTaskId(reqVO.getTaskId(), reqVO.getComment());
Boolean delTaskResult = taskExtMapper.delByTaskIds(taskIdList);
if (!delHiActInstResult && !delHiTaskInstResult && !backResult && !delTaskResult) {
throw new RuntimeException("任务驳回失败!!!");
}
return CommonResult.success(true);
}
@Override
@ -247,40 +306,40 @@ public class BpmTaskServiceImpl implements BpmTaskService{
taskService.setAssignee(id, String.valueOf(userId));
}
@Override
public void createTaskExt(Task task) {
BpmTaskExtDO taskExtDO = BpmTaskConvert.INSTANCE.convert2TaskExt(task)
.setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
BpmTaskExtDO taskExtDO =
BpmTaskConvert.INSTANCE.convert2TaskExt(task).setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
taskExtMapper.insert(taskExtDO);
}
@Override
public void updateTaskExtComplete(Task task) {
BpmTaskExtDO taskExtDO = BpmTaskConvert.INSTANCE.convert2TaskExt(task)
.setEndTime(new Date());
BpmTaskExtDO taskExtDO = BpmTaskConvert.INSTANCE.convert2TaskExt(task).setEndTime(new Date());
taskExtMapper.updateByTaskId(taskExtDO);
}
@Override
public void updateTaskExtAssign(Task task) {
BpmTaskExtDO taskExtDO = new BpmTaskExtDO()
.setAssigneeUserId(NumberUtils.parseLong(task.getAssignee()))
.setTaskId(task.getId());
BpmTaskExtDO taskExtDO =
new BpmTaskExtDO().setAssigneeUserId(NumberUtils.parseLong(task.getAssignee())).setTaskId(task.getId());
taskExtMapper.updateByTaskId(taskExtDO);
// 发送通知在事务提交时批量执行操作所以直接查询会无法查询到 ProcessInstance所以这里是通过监听事务的提交来实现
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override
public void afterCommit() {
ProcessInstance processInstance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
ProcessInstance processInstance =
processInstanceService.getProcessInstance(task.getProcessInstanceId());
AdminUserRespDTO startUser = adminUserApi.getUser(Long.valueOf(processInstance.getStartUserId()));
messageService.sendMessageWhenTaskAssigned(BpmTaskConvert.INSTANCE.convert(processInstance, startUser, task));
messageService.sendMessageWhenTaskAssigned(
BpmTaskConvert.INSTANCE.convert(processInstance, startUser, task));
}
});
}
/**
* 校验任务是否存在 并且是否是分配给自己的任务
*
* @param userId 用户 id
* @param taskId task id
*/

View File

@ -0,0 +1,20 @@
package net.lab1024.smartadmin.module.business.approve.camunda.hi.task.inst.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author kemengkai
* @create 2022-01-11 15:09
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class HistoricApproveTaskDTO {
private String procInstId;
private String name;
private String assignee;
}

View File

@ -0,0 +1,105 @@
package net.lab1024.smartadmin.module.business.approve.camunda.hi.task.inst.domain.vo;
import lombok.Data;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
/**
* [ ]
*
* @author 孟凯
* @version 1.0
* @company 1024创新实验室( www.1024lab.net )
* @copyright (c) 1024创新实验室( www.1024lab.net )Inc. All rights reserved.
* @date 2022-01-17 15:14:27
* @since JDK1.8
*/
@Data
public class HiTaskinstVO {
@ApiModelProperty("ID_")
private String id;
@ApiModelProperty("TASK_DEF_KEY_")
private String taskDefKey;
@ApiModelProperty("PROC_DEF_KEY_")
private String procDefKey;
@ApiModelProperty("PROC_DEF_ID_")
private String procDefId;
@ApiModelProperty("ROOT_PROC_INST_ID_")
private String rootProcInstId;
@ApiModelProperty("PROC_INST_ID_")
private String procInstId;
@ApiModelProperty("EXECUTION_ID_")
private String executionId;
@ApiModelProperty("CASE_DEF_KEY_")
private String caseDefKey;
@ApiModelProperty("CASE_DEF_ID_")
private String caseDefId;
@ApiModelProperty("CASE_INST_ID_")
private String caseInstId;
@ApiModelProperty("CASE_EXECUTION_ID_")
private String caseExecutionId;
@ApiModelProperty("ACT_INST_ID_")
private String actInstId;
@ApiModelProperty("NAME_")
private String name;
@ApiModelProperty("PARENT_TASK_ID_")
private String parentTaskId;
@ApiModelProperty("DESCRIPTION_")
private String description;
@ApiModelProperty("OWNER_")
private String owner;
@ApiModelProperty("ASSIGNEE_")
private String assignee;
@ApiModelProperty("START_TIME_")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date startTime;
@ApiModelProperty("END_TIME_")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date endTime;
@ApiModelProperty("DURATION_")
private Long duration;
@ApiModelProperty("DELETE_REASON_")
private String deleteReason;
@ApiModelProperty("PRIORITY_")
private Integer priority;
@ApiModelProperty("DUE_DATE_")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date dueDate;
@ApiModelProperty("FOLLOW_UP_DATE_")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date followUpDate;
@ApiModelProperty("TENANT_ID_")
private String tenantId;
@ApiModelProperty("REMOVAL_TIME_")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date removalTime;
}

View File

@ -0,0 +1,263 @@
package cn.iocoder.yudao.module.business.hi.task.inst.service;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.module.bpm.domain.vo.ApproveProcInstVO;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.impl.de.odysseus.el.util.SimpleContext;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.TaskService;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
/**
* [ ]
*
* @author 孟凯
* @version 1.0
* @company 1024创新实验室(www.1024lab.net)
* @copyright (c) 1024创新实验室( www.1024lab.net )Inc. All rights reserved.
* @date 2022-01-17 15:14:27
* @since JDK1.8
*/
@Slf4j
@Service
public class HiTaskinstService {
@Autowired
private TaskService taskService;
@Autowired
private HistoryService historyService;
@Autowired
private RepositoryService repositoryService;
/**
* 获取任务具体流程信息
*
* @param procInstId 流程id
* @param procDefId 流程部署id
*
* @return 返回流程信息
*/
public List<ApproveProcInstVO> taskGetComment(String procInstId, String procDefId) {
Map<String, Object> variableMap = new HashMap<>(50);
List<HistoricVariableInstance> hisVarInstList =
historyService.createHistoricVariableInstanceQuery().processInstanceId(procInstId).list();
hisVarInstList.forEach(hisVarInst -> {
variableMap.put(hisVarInst.getName(), hisVarInst.getValue());
});
List<ApproveProcInstVO> procInstVOList = hiTaskinstDao.listByProcInstIdAndNotDelete(procInstId);
BpmnModelInstance bpmnModelInstance = repositoryService.getBpmnModel(procDefId);
DomElement document1 = bpmnModelInstance.getDocument().getElementById(procDefId.split(":")[0]);
LinkedHashMap<String, DomElement> domElementMap = new LinkedHashMap<>(50);
getChildElementToMap(document1, domElementMap);
getChildNode(procInstVOList, domElementMap, variableMap);
return procInstVOList;
}
/**
* 获取子节点信息存储到map中
*
* @param domElement 父节点
* @param domElementMap 节点map
*/
private void getChildElementToMap(DomElement domElement, LinkedHashMap<String, DomElement> domElementMap) {
List<DomElement> childElements = domElement.getChildElements();
for (DomElement childElement : childElements) {
if ("BPMNDiagram".equals(childElement.getLocalName())) {
break;
}
if ("extensionElements".equals(childElement.getLocalName())) {
break;
}
if (!"outgoing".equals(childElement.getLocalName()) && !"incoming".equals(childElement.getLocalName())) {
domElementMap.put(childElement.getAttribute("id"), childElement);
}
getChildElementToMap(childElement, domElementMap);
}
}
/**
* 获取子节点信息
*
* @param procInstVOList 流程VO列表
* @param domElementMap 节点map
* @param variableMap 流程所有的变量
*/
private void getChildNode(List<ApproveProcInstVO> procInstVOList, LinkedHashMap<String, DomElement> domElementMap,
Map<String, Object> variableMap) {
DomElement domElement = domElementMap.get(procInstVOList.get(procInstVOList.size() - 1).getTaskDefKey());
for (DomElement childElement : domElement.getChildElements()) {
if ("outgoing".equals(childElement.getLocalName())) {
DomElement tmpDomElement = domElementMap.get(childElement.getTextContent());
getChildNode(procInstVOList, domElementMap, variableMap, tmpDomElement);
}
}
}
/**
* 获取子节点信息
*
* @param procInstVOList 流程VO列表
* @param domElementMap 节点map
* @param variableMap 流程所有的变量
* @param domElement 父节点信息
*/
private void getChildNode(List<ApproveProcInstVO> procInstVOList, LinkedHashMap<String, DomElement> domElementMap,
Map<String, Object> variableMap, DomElement domElement) {
if ("exclusiveGateway".equals(domElement.getLocalName())) {
DomElement domElementChild = getNodeExclusiveGateway(domElementMap, variableMap, domElement);
getChildNode(procInstVOList, domElementMap, variableMap, domElementChild);
} else if ("userTask".equals(domElement.getLocalName())) {
getProcInstVO(procInstVOList, domElement, variableMap);
for (DomElement childElement : domElement.getChildElements()) {
if ("outgoing".equals(childElement.getLocalName())) {
DomElement tmpDomElement = domElementMap.get(childElement.getTextContent());
DomElement domElementChild = getNodeBySequenceFlow(domElementMap, tmpDomElement);
if ("endEvent".equals(domElementChild.getLocalName())) {
return;
}
getChildNode(procInstVOList, domElementMap, variableMap, domElementChild);
}
}
} else {
DomElement domElementChild = getNodeBySequenceFlow(domElementMap, domElement);
if (BeanUtil.isEmpty(domElementChild)) {
throw new RuntimeException("无流程可执行!!!");
}
if ("endEvent".equals(domElementChild.getLocalName())) {
return;
}
getChildNode(procInstVOList, domElementMap, variableMap, domElementChild);
}
}
/**
* 获取网关节点的子节点
*
* @param domElementMap 流程所有的节点
* @param variableMap 流程所有的变量
* @param domElement 父节点信息
*
* @return 返回子节点信息
*/
private DomElement getNodeExclusiveGateway(LinkedHashMap<String, DomElement> domElementMap,
Map<String, Object> variableMap, DomElement domElement) {
Boolean elExpressionFlag = Boolean.FALSE;
ArrayList<DomElement> nullChildSequenceFlowList = new ArrayList<>();
for (DomElement exclusiveGatewayChild : domElement.getChildElements()) {
if ("outgoing".equals(exclusiveGatewayChild.getLocalName()) && BooleanUtil.isFalse(elExpressionFlag)) {
DomElement sequenceFlowDomElement = domElementMap.get(exclusiveGatewayChild.getTextContent());
if (CollUtil.isNotEmpty(sequenceFlowDomElement.getChildElements())
&& sequenceFlowDomElement.getChildElements().size() > 0) {
for (DomElement conditionExpression : sequenceFlowDomElement.getChildElements()) {
if ("conditionExpression".equals(conditionExpression.getLocalName())) {
elExpressionFlag = elExpression(conditionExpression.getTextContent(), variableMap);
if (BooleanUtil.isTrue(elExpressionFlag)) {
break;
}
}
}
} else {
nullChildSequenceFlowList.add(sequenceFlowDomElement);
}
if (elExpressionFlag) {
return getNodeBySequenceFlow(domElementMap, sequenceFlowDomElement);
}
}
}
if (CollUtil.isEmpty(nullChildSequenceFlowList) && nullChildSequenceFlowList.size() < 1) {
throw new RuntimeException("网关缺少无条件流程可执行!!!");
}
if (nullChildSequenceFlowList.size() > 1) {
throw new RuntimeException("无条件流程大于1条");
}
return getNodeBySequenceFlow(domElementMap, nullChildSequenceFlowList.get(0));
}
/**
* 获取流程序列流的子节点
*
* @param domElementMap 流程所有节点
* @param domElement 父节点信息
*
* @return 返回子节点
*/
private DomElement getNodeBySequenceFlow(LinkedHashMap<String, DomElement> domElementMap, DomElement domElement) {
String targetRef = domElement.getAttribute("targetRef");
return domElementMap.get(targetRef);
}
/**
* 设置节点信息进ApproveProcInstVO
*
* @param procInstVOList ApproveProcInstVOList
* @param domElement 节点信息
* @param variableMap 流程所有变量
*/
private void getProcInstVO(List<ApproveProcInstVO> procInstVOList, DomElement domElement,
Map<String, Object> variableMap) {
String camundaNameSpaceUri = "http://camunda.org/schema/1.0/bpmn";
boolean userListFlag = false;
List<Object> approveProcInstVOList = new ArrayList<>();
for (DomElement childElement : domElement.getChildElements()) {
if ("multiInstanceLoopCharacteristics".equals(childElement.getLocalName())) {
userListFlag = true;
String collectionVar = childElement.getAttribute(camundaNameSpaceUri, "collection");
Object taskUserList = variableMap.get(collectionVar);
approveProcInstVOList = JSONUtil.parseArray(taskUserList);
}
}
if (userListFlag) {
approveProcInstVOList.forEach(tmpAssignee -> {
String assignee = String.valueOf(tmpAssignee);
ApproveProcInstVO approveProcInstVO = new ApproveProcInstVO();
approveProcInstVO.setName(domElement.getAttribute("name"));
approveProcInstVO.setTaskDefKey(domElement.getAttribute("id"));
approveProcInstVO.setAssignee(assignee);
approveProcInstVO.setAssigneeName(employeeDao.getByLoginName(assignee, 0).getActualName());
procInstVOList.add(approveProcInstVO);
});
} else {
ApproveProcInstVO approveProcInstVO = new ApproveProcInstVO();
approveProcInstVO.setName(domElement.getAttribute("name"));
approveProcInstVO.setTaskDefKey(domElement.getAttribute("id"));
approveProcInstVO.setAssignee(domElement.getAttribute(camundaNameSpaceUri, "assignee"));
approveProcInstVO.setAssigneeName(
employeeDao.getByLoginName(approveProcInstVO.getAssignee(), 0).getActualName());
procInstVOList.add(approveProcInstVO);
}
}
/**
* 网关分叉条件判断网关分叉必须要有默认出口
*
* @param elExpression el表达式
* @param variableMap 流程所有变量
*
* @return 返回true或false
*/
private Boolean elExpression(String elExpression, Map<String, Object> variableMap) {
ExpressionFactory factory = new ExpressionFactoryImpl();
SimpleContext context = new SimpleContext();
for (String k : variableMap.keySet()) {
if (variableMap.get(k) != null) {
context.setVariable(k,
factory.createValueExpression(variableMap.get(k), variableMap.get(k).getClass()));
}
}
ValueExpression e = factory.createValueExpression(context, elExpression, Boolean.class);
//el表达式和variables得到的结果
return (Boolean)e.getValue(context);
}
}

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmActivityMapper">
<update id="delHiActInstByTaskId">
UPDATE act_hi_actinst
SET delete_reason_ = 'delete task' WHERE task_id_ IN
<foreach collection="taskIdList" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</update>
<delete id="delHiTaskInstByTaskId">
UPDATE act_hi_taskinst
SET delete_reason_ = 'delete task' WHERE id_ IN
<foreach collection="taskIdList" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</delete>
<select id="listAll" resultType="cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmActivityDO">
SELECT *
FROM act_hi_taskinst;
</select>
<select id="listAllByProcInstIdAndDelete"
resultType="cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmActivityDO">
SELECT id_ AS `id`,
rev_ AS `rev`,
proc_def_id_ AS `proc_def_id`,
proc_inst_id_ AS `process_instance_id`,
execution_id_ AS `execution_id`,
act_id_ AS `activity_id`,
task_id_ AS `task_id`,
call_proc_inst_id_ AS `call_proc_inst_id`,
act_name_ AS `activity_name`,
act_type_ AS `activity_type`,
assignee_ AS `assignee`,
start_time_ AS `start_time`,
end_time_ AS `end_time`,
transaction_order_ AS `transaction_order`,
duration_ AS `duration`,
delete_reason_ AS `delete_reason`,
tenant_id_ AS `tenant_id`
FROM act_hi_actinst aha
WHERE aha.proc_inst_id_ = #{procInstId}
AND aha.act_type_ != 'sequenceFlow'
LIMIT 500;
</select>
</mapper>

View File

@ -2,8 +2,36 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmTaskExtMapper">
<update id="updateUserOrSignTask">
UPDATE bpm_task_ext SET deleted=1 WHERE process_instance_id = #{entity.processInstanceId} AND name = #{entity.name} AND task_id != #{entity.taskId}
<update id="delTaskByProcInstIdAndTaskIdAndTaskDefKey">
UPDATE bpm_task_ext
SET deleted=1
WHERE process_instance_id = #{entity.processInstanceId}
AND task_def_key = #{entity.taskDefKey}
AND task_id != #{entity.taskId}
</update>
<update id="backByTaskId">
UPDATE bpm_task_ext
SET result=2,
`comment`=#{comment}
WHERE task_id = #{taskId}
</update>
<update id="delByTaskIds">
UPDATE bpm_task_ext
SET result=1,
`deleted`= true
WHERE `task_id` IN
<foreach collection="taskIdList" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</update>
<select id="listByProcInstId" resultType="cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO">
SELECT *
FROM bpm_task_ext
WHERE `process_instance_id` = #{procInstId}
AND `deleted` = FALSE
ORDER BY create_time
LIMIT 500
</select>
</mapper>

View File

@ -8,13 +8,13 @@ import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.test.Deployment;
import org.flowable.task.api.Task;
import org.junit.Test;
import org.junit.jupiter.api.Test;
import java.text.SimpleDateFormat;
import java.util.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
/**
* @author henryyan

View File

@ -8,6 +8,7 @@ import org.springframework.security.config.annotation.web.configurers.Expression
/**
* System 模块的 Security 配置
* @author kemengkai
*/
@Configuration("systemSecurityConfiguration")
public class SecurityConfiguration {