Merge branch 'feature/bpm' of gitee.com:zhijiantianya/ruoyi-vue-pro into feature/bpm

This commit is contained in:
Lesan
2024-11-25 01:55:51 +00:00
committed by Gitee
92 changed files with 1048 additions and 232 deletions

View File

@@ -4,7 +4,10 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* BPM 流程分类 DO

View File

@@ -1,11 +1,15 @@
package cn.iocoder.yudao.module.bpm.dal.dataobject.definition;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import lombok.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@@ -16,6 +20,7 @@ import java.util.List;
* @author 芋道源码
*/
@TableName(value = "bpm_form", autoResultMap = true)
@KeySequence("bpm_form_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@Builder
@NoArgsConstructor

View File

@@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.mybatis.core.type.StringListTypeHandler;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelTypeEnum;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
@@ -26,6 +27,7 @@ import java.util.List;
* @author 芋道源码
*/
@TableName(value = "bpm_process_definition_info", autoResultMap = true)
@KeySequence("bpm_process_definition_info_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@Builder
@NoArgsConstructor

View File

@@ -1,11 +1,10 @@
package cn.iocoder.yudao.module.bpm.dal.dataobject.definition;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
/**
* BPM 流程表达式 DO

View File

@@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.bpm.dal.dataobject.definition;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
@@ -16,6 +17,7 @@ import lombok.NoArgsConstructor;
* @author 芋道源码
*/
@TableName(value = "bpm_process_listener")
@KeySequence("bpm_process_listener_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@Builder
@NoArgsConstructor

View File

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.bpm.dal.dataobject.definition;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
@@ -19,6 +20,7 @@ import java.util.Set;
* @author 芋道源码
*/
@TableName(value = "bpm_user_group", autoResultMap = true)
@KeySequence("bpm_user_group_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@Builder
@NoArgsConstructor

View File

@@ -2,9 +2,13 @@ package cn.iocoder.yudao.module.bpm.dal.dataobject.oa;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@@ -17,6 +21,7 @@ import java.time.LocalDateTime;
* @author 芋道源码
*/
@TableName("bpm_oa_leave")
@KeySequence("bpm_oa_leave_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@Builder
@NoArgsConstructor

View File

@@ -1,11 +1,15 @@
package cn.iocoder.yudao.module.bpm.dal.dataobject.task;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import org.flowable.bpmn.model.FlowNode;
import org.flowable.task.api.history.HistoricTaskInstance;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 流程抄送 DO
@@ -14,6 +18,7 @@ import org.flowable.task.api.history.HistoricTaskInstance;
* @since 2024-01-22
*/
@TableName(value = "bpm_process_instance_copy", autoResultMap = true)
@KeySequence("bpm_process_instance_copy_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@Builder
@NoArgsConstructor

View File

@@ -0,0 +1,56 @@
package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.form;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.dept.AbstractBpmTaskCandidateDeptLeaderStrategy;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.delegate.DelegateExecution;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.Set;
/**
* 表单内部门负责人 {@link BpmTaskCandidateStrategy} 实现类
*
* @author jason
*/
@Component
public class BpmTaskCandidateFormSDeptLeaderStrategy extends AbstractBpmTaskCandidateDeptLeaderStrategy {
@Override
public BpmTaskCandidateStrategyEnum getStrategy() {
return BpmTaskCandidateStrategyEnum.FORM_DEPT_LEADER;
}
@Override
public void validateParam(String param) {
// 参数格式: | 分隔1左边为表单内部门字段。2右边为部门层级
String[] params = param.split("\\|");
Assert.isTrue(params.length == 2, "参数格式不匹配");
Assert.notEmpty(param, "表单内部门字段不能为空");
int level = Integer.parseInt(params[1]);
Assert.isTrue(level > 0, "部门层级必须大于 0");
}
@Override
public Set<Long> calculateUsersByTask(DelegateExecution execution, String param) {
String[] params = param.split("\\|");
Object result = execution.getVariable(params[0]);
int level = Integer.parseInt(params[1]);
return super.getMultiLevelDeptLeaderIds(Convert.toList(Long.class, result), level);
}
@Override
public Set<Long> calculateUsersByActivity(BpmnModel bpmnModel, String activityId,
String param, Long startUserId, String processDefinitionId,
Map<String, Object> processVariables) {
String[] params = param.split("\\|");
Object result = processVariables == null ? null : processVariables.get(params[0]);
int level = Integer.parseInt(params[1]);
return super.getMultiLevelDeptLeaderIds(Convert.toList(Long.class, result), level);
}
}

View File

@@ -0,0 +1,47 @@
package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.form;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.user.BpmTaskCandidateUserStrategy;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.delegate.DelegateExecution;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.Set;
/**
* 表单内用户字段 {@link BpmTaskCandidateUserStrategy} 实现类
*
* @author jason
*/
@Component
public class BpmTaskCandidateFormUserStrategy implements BpmTaskCandidateStrategy {
@Override
public BpmTaskCandidateStrategyEnum getStrategy() {
return BpmTaskCandidateStrategyEnum.FORM_USER;
}
@Override
public void validateParam(String param) {
Assert.notEmpty(param, "表单内用户字段不能为空");
}
@Override
public Set<Long> calculateUsersByTask(DelegateExecution execution, String param) {
Object result = execution.getVariable(param);
return Convert.toSet(Long.class, result);
}
@Override
public Set<Long> calculateUsersByActivity(BpmnModel bpmnModel, String activityId,
String param, Long startUserId, String processDefinitionId,
Map<String, Object> processVariables) {
Object result = processVariables == null ? null : processVariables.get(param);
return Convert.toSet(Long.class, result);
}
}

View File

@@ -29,6 +29,8 @@ public enum BpmTaskCandidateStrategyEnum implements IntArrayValuable {
START_USER_DEPT_LEADER(37, "发起人部门负责人"),
START_USER_DEPT_LEADER_MULTI(38, "发起人连续多级部门的负责人"),
USER_GROUP(40, "用户组"),
FORM_USER(50, "表单内用户字段"),
FORM_DEPT_LEADER(51, "表单内部门负责人"),
EXPRESSION(60, "流程表达式"), // 表达式 ExpressionManager
ASSIGN_EMPTY(1, "审批人为空"),
;

View File

@@ -29,7 +29,12 @@ public class BpmnVariableConstants {
* @see ProcessInstance#getProcessVariables()
*/
public static final String PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES = "PROCESS_START_USER_SELECT_ASSIGNEES";
/**
* 流程实例的变量 - 发起用户 ID
*
* @see ProcessInstance#getProcessVariables()
*/
public static final String PROCESS_INSTANCE_VARIABLE_START_USER_ID = "PROCESS_START_USER_ID";
/**
* 流程实例的变量 - 用于判断流程实例变量节点是否驳回. 格式 RETURN_FLAG_{节点 id}
*

View File

@@ -520,8 +520,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
activityInstance -> activityInstance.getEndTime() != null
&& ObjectUtil.equals(activityInstance.getActivityType(), BpmnXMLConstants.ELEMENT_SEQUENCE_FLOW));
// 特殊:会签情况下,会有部分已完成(审批)、部分未完成(待审批),此时需要 finishedTaskActivityIds 移除掉
// unfinishedTaskActivityIds.removeAll(finishedTaskActivityIds);
finishedTaskActivityIds.removeAll(unfinishedTaskActivityIds);
unfinishedTaskActivityIds.removeAll(finishedTaskActivityIds);
// 特殊:如果流程实例被拒绝,则需要计算是哪个活动节点。
// 注意,只取最后一个。因为会存在多次拒绝的情况,拒绝驳回到指定节点
Set<String> rejectTaskActivityIds = CollUtil.newHashSet();
@@ -589,6 +588,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
variables = new HashMap<>();
}
FlowableUtils.filterProcessInstanceFormVariable(variables); // 过滤一下,避免 ProcessInstance 系统级的变量被占用
variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_ID, userId); // 设置流程变量,发起人 ID
variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS, // 流程实例状态:审批中
BpmProcessInstanceStatusEnum.RUNNING.getStatus());
if (CollUtil.isNotEmpty(startUserSelectAssignees)) {

View File

@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.o
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
import org.flowable.engine.delegate.DelegateExecution;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.MockedStatic;
@@ -16,6 +17,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.*;
@Disabled // TODO 芋艿:临时注释
public class BpmTaskCandidateExpressionStrategyTest extends BaseMockitoUnitTest {
@InjectMocks

View File

@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.u
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
@@ -16,6 +17,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
@Disabled // TODO 芋艿:临时注释
public class BpmTaskCandidateGroupStrategyTest extends BaseMockitoUnitTest {
@InjectMocks

View File

@@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.module.system.api.dept.PostApi;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
@@ -17,6 +18,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
@Disabled // TODO 芋艿:临时注释
public class BpmTaskCandidatePostStrategyTest extends BaseMockitoUnitTest {
@InjectMocks

View File

@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.u
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
import cn.iocoder.yudao.module.system.api.permission.RoleApi;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
@@ -14,6 +15,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
@Disabled // TODO 芋艿:临时注释
public class BpmTaskCandidateRoleStrategyTest extends BaseMockitoUnitTest {
@InjectMocks

View File

@@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.user;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
@@ -9,6 +10,7 @@ import java.util.Set;
import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
import static org.junit.jupiter.api.Assertions.assertEquals;
@Disabled // TODO 芋艿:临时注释
public class BpmTaskCandidateUserStrategyTest extends BaseMockitoUnitTest {
@InjectMocks