commit:同步2.0版本

This commit is contained in:
Jerry
2021-10-20 12:11:51 +08:00
parent 50807a7a7e
commit abbbd90690
54 changed files with 4443 additions and 72 deletions

View File

@@ -362,6 +362,52 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
return mapper().selectList(queryWrapper);
}
/**
* 返回符合主键 in (idValues) 条件的所有数据。同时返回关联数据。
*
* @param idValues 主键值集合。
* @param relationParam 实体对象数据组装的参数构建器。
* @return 检索后的数据列表。
*/
@Override
public List<M> getInListWithRelation(Set<K> idValues, MyRelationParam relationParam) {
List<M> resultList = this.getInList(idValues);
this.buildRelationForDataList(resultList, relationParam);
return resultList;
}
/**
* 返回符合 inFilterField in (inFilterValues) 条件的所有数据。同时返回关联数据。
*
* @param inFilterField 参与(In-list)过滤的Java字段。
* @param inFilterValues 参与(In-list)过滤的Java字段值集合。
* @param relationParam 实体对象数据组装的参数构建器。
* @return 检索后的数据列表。
*/
@Override
public <T> List<M> getInListWithRelation(String inFilterField, Set<T> inFilterValues, MyRelationParam relationParam) {
List<M> resultList = this.getInList(inFilterField, inFilterValues);
this.buildRelationForDataList(resultList, relationParam);
return resultList;
}
/**
* 返回符合 inFilterField in (inFilterValues) 条件的所有数据并根据orderBy字段排序。同时返回关联数据。
*
* @param inFilterField 参与(In-list)过滤的Java字段。
* @param inFilterValues 参与(In-list)过滤的Java字段值集合。
* @param orderBy 排序字段。
* @param relationParam 实体对象数据组装的参数构建器。
* @return 检索后的数据列表。
*/
@Override
public <T> List<M> getInListWithRelation(
String inFilterField, Set<T> inFilterValues, String orderBy, MyRelationParam relationParam) {
List<M> resultList = this.getInList(inFilterField, inFilterValues, orderBy);
this.buildRelationForDataList(resultList, relationParam);
return resultList;
}
/**
* 用参数对象作为过滤条件,获取数据数量。
*

View File

@@ -121,6 +121,37 @@ public interface IBaseService<M, K extends Serializable> extends IService<M>{
*/
<T> List<M> getInList(String inFilterField, Set<T> inFilterValues, String orderBy);
/**
* 返回符合主键 in (idValues) 条件的所有数据。同时返回关联数据。
*
* @param idValues 主键值集合。
* @param relationParam 实体对象数据组装的参数构建器。
* @return 检索后的数据列表。
*/
List<M> getInListWithRelation(Set<K> idValues, MyRelationParam relationParam);
/**
* 返回符合 inFilterField in (inFilterValues) 条件的所有数据。同时返回关联数据。
*
* @param inFilterField 参与(In-list)过滤的Java字段。
* @param inFilterValues 参与(In-list)过滤的Java字段值集合。
* @param relationParam 实体对象数据组装的参数构建器。
* @return 检索后的数据列表。
*/
<T> List<M> getInListWithRelation(String inFilterField, Set<T> inFilterValues, MyRelationParam relationParam);
/**
* 返回符合 inFilterField in (inFilterValues) 条件的所有数据并根据orderBy字段排序。同时返回关联数据。
*
* @param inFilterField 参与(In-list)过滤的Java字段。
* @param inFilterValues 参与(In-list)过滤的Java字段值集合。
* @param orderBy 排序字段。
* @param relationParam 实体对象数据组装的参数构建器。
* @return 检索后的数据列表。
*/
<T> List<M> getInListWithRelation(
String inFilterField, Set<T> inFilterValues, String orderBy, MyRelationParam relationParam);
/**
* 用参数对象作为过滤条件,获取数据数量。
*

View File

@@ -5,10 +5,13 @@ import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.flow.demo.common.core.constant.AppDeviceType;
import com.flow.demo.common.core.validator.AddGroup;
import com.flow.demo.common.core.validator.UpdateGroup;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.groups.Default;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;
@@ -109,11 +112,75 @@ public class MyCommonUtil {
* @return 没有错误返回null否则返回具体的错误信息。
*/
public static <T> String getModelValidationError(T model, Class<?>...groups) {
Set<ConstraintViolation<T>> constraintViolations = VALIDATOR.validate(model, groups);
if (!constraintViolations.isEmpty()) {
Iterator<ConstraintViolation<T>> it = constraintViolations.iterator();
ConstraintViolation<T> constraint = it.next();
return constraint.getMessage();
if (model != null) {
Set<ConstraintViolation<T>> constraintViolations = VALIDATOR.validate(model, groups);
if (!constraintViolations.isEmpty()) {
Iterator<ConstraintViolation<T>> it = constraintViolations.iterator();
ConstraintViolation<T> constraint = it.next();
return constraint.getMessage();
}
}
return null;
}
/**
* 判断模型对象是否通过校验,没有通过返回具体的校验错误信息。
*
* @param model 带校验的model。
* @param forUpdate 是否为更新。
* @return 没有错误返回null否则返回具体的错误信息。
*/
public static <T> String getModelValidationError(T model, boolean forUpdate) {
if (model != null) {
Set<ConstraintViolation<T>> constraintViolations;
if (forUpdate) {
constraintViolations = VALIDATOR.validate(model, Default.class, UpdateGroup.class);
} else {
constraintViolations = VALIDATOR.validate(model, Default.class, AddGroup.class);
}
if (!constraintViolations.isEmpty()) {
Iterator<ConstraintViolation<T>> it = constraintViolations.iterator();
ConstraintViolation<T> constraint = it.next();
return constraint.getMessage();
}
}
return null;
}
/**
* 判断模型对象是否通过校验,没有通过返回具体的校验错误信息。
*
* @param modelList 带校验的model列表。
* @param groups Validate绑定的校验组。
* @return 没有错误返回null否则返回具体的错误信息。
*/
public static <T> String getModelValidationError(List<T> modelList, Class<?>... groups) {
if (CollUtil.isNotEmpty(modelList)) {
for (T model : modelList) {
String errorMessage = getModelValidationError(model, groups);
if (StrUtil.isNotBlank(errorMessage)) {
return errorMessage;
}
}
}
return null;
}
/**
* 判断模型对象是否通过校验,没有通过返回具体的校验错误信息。
*
* @param modelList 带校验的model列表。
* @param forUpdate 是否为更新。
* @return 没有错误返回null否则返回具体的错误信息。
*/
public static <T> String getModelValidationError(List<T> modelList, boolean forUpdate) {
if (CollUtil.isNotEmpty(modelList)) {
for (T model : modelList) {
String errorMessage = getModelValidationError(model, forUpdate);
if (StrUtil.isNotBlank(errorMessage)) {
return errorMessage;
}
}
}
return null;
}

View File

@@ -93,6 +93,9 @@ public class MyModelUtil {
* @return copy后的目标类型对象集合。
*/
public static <S, T> List<T> copyCollectionTo(Collection<S> sourceCollection, Class<T> targetClazz) {
if (sourceCollection == null) {
return null;
}
List<T> targetList = new LinkedList<>();
if (CollectionUtils.isNotEmpty(sourceCollection)) {
for (S source : sourceCollection) {

View File

@@ -17,13 +17,13 @@ public class DataFilterProperties {
/**
* 是否启用租户过滤。
*/
@Value("${datafilter.tenant.enabled}")
@Value("${datafilter.tenant.enabled:false}")
private Boolean enabledTenantFilter;
/**
* 是否启动数据权限过滤。
*/
@Value("${datafilter.dataperm.enabled}")
@Value("${datafilter.dataperm.enabled:false}")
private Boolean enabledDataPermFilter;
/**

View File

@@ -85,8 +85,7 @@ public class MybatisDataFilterInterceptor implements Interceptor {
if (proxy == null) {
proxy = ReflectUtil.getFieldValue(mapperProxy, "CGLIB$CALLBACK_0");
}
Class<?> mapperClass =
(Class<?>) ReflectUtil.getFieldValue(proxy, "mapperInterface");
Class<?> mapperClass = (Class<?>) ReflectUtil.getFieldValue(proxy, "mapperInterface");
if (properties.getEnabledTenantFilter()) {
loadTenantFilterData(mapperClass);
}
@@ -111,8 +110,7 @@ public class MybatisDataFilterInterceptor implements Interceptor {
tenantInfo.setFieldName(field.getName());
tenantInfo.setColumnName(MyModelUtil.mapToColumnName(field, modelClass));
// 判断当前dao中是否包括不需要自动注入租户Id过滤的方法。
DisableTenantFilter disableTenantFilter =
mapperClass.getAnnotation(DisableTenantFilter.class);
DisableTenantFilter disableTenantFilter = mapperClass.getAnnotation(DisableTenantFilter.class);
if (disableTenantFilter != null) {
// 这里开始获取当前Mapper已经声明的的SqlId中有哪些是需要排除在外的。
// 排除在外的将不进行数据过滤。
@@ -280,16 +278,14 @@ public class MybatisDataFilterInterceptor implements Interceptor {
String dataPermSessionKey = RedisKeyUtil.makeSessionDataPermIdKey(tokenData.getSessionId());
String dataPermData = redissonClient.getBucket(dataPermSessionKey).get().toString();
if (StringUtils.isBlank(dataPermData)) {
throw new NoDataPermException(
"No Related DataPerm found for SQL_ID [ " + sqlId + " ].");
throw new NoDataPermException("No Related DataPerm found for SQL_ID [ " + sqlId + " ].");
}
Map<Integer, String> dataPermMap = new HashMap<>(8);
for (Map.Entry<String, Object> entry : JSON.parseObject(dataPermData).entrySet()) {
dataPermMap.put(Integer.valueOf(entry.getKey()), entry.getValue().toString());
}
if (MapUtils.isEmpty(dataPermMap)) {
throw new NoDataPermException(
"No Related DataPerm found for SQL_ID [ " + sqlId + " ].");
throw new NoDataPermException("No Related DataPerm found for SQL_ID [ " + sqlId + " ].");
}
if (dataPermMap.containsKey(DataPermRuleType.TYPE_ALL)) {
return;

View File

@@ -0,0 +1,47 @@
package com.flow.demo.common.flow.base.service;
import com.alibaba.fastjson.JSONObject;
import com.flow.demo.common.core.base.service.BaseService;
import com.flow.demo.common.flow.constant.FlowApprovalType;
import com.flow.demo.common.flow.constant.FlowTaskStatus;
import com.flow.demo.common.flow.model.FlowTaskComment;
import com.flow.demo.common.flow.service.FlowApiService;
import com.flow.demo.common.flow.service.FlowWorkOrderService;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.Serializable;
public abstract class BaseFlowService<M, K extends Serializable> extends BaseService<M, K> {
@Autowired
private FlowApiService flowApiService;
@Autowired
private FlowWorkOrderService flowWorkOrderService;
public void startAndTakeFirst(
String processDefinitionId, K dataId, FlowTaskComment comment, JSONObject variables) {
ProcessInstance instance = flowApiService.startAndTakeFirst(
processDefinitionId, dataId, comment, variables);
flowWorkOrderService.saveNew(instance, dataId, null);
}
public void takeFirstTask(
String processInstanceId, String taskId, K dataId, FlowTaskComment comment, JSONObject variables) {
Task task = flowApiService.getProcessInstanceActiveTask(processInstanceId, taskId);
flowApiService.setBusinessKeyForProcessInstance(processInstanceId, dataId);
flowApiService.completeTask(task, comment, variables);
ProcessInstance instance = flowApiService.getProcessInstance(processInstanceId);
flowWorkOrderService.saveNew(instance, dataId, null);
}
public void takeTask(Task task, K dataId, FlowTaskComment comment, JSONObject variables) {
int flowStatus = FlowTaskStatus.APPROVING;
if (comment.getApprovalType().equals(FlowApprovalType.REFUSE)) {
flowStatus = FlowTaskStatus.REFUSED;
}
flowWorkOrderService.updateFlowStatusByBusinessKey(dataId.toString(), flowStatus);
flowApiService.completeTask(task, comment, variables);
}
}

View File

@@ -12,7 +12,7 @@ import lombok.Data;
public class FlowWorkOrderDto {
/**
* 流程状态。
* 流程状态。参考FlowTaskStatus常量值对象。
*/
private Integer flowStatus;

View File

@@ -66,7 +66,7 @@ public class FlowWorkOrder {
private String businessKey;
/**
* 流程状态。
* 流程状态。参考FlowTaskStatus常量值对象。
*/
@TableField(value = "flow_status")
private Integer flowStatus;

View File

@@ -57,6 +57,14 @@ public interface FlowWorkOrderService extends IBaseService<FlowWorkOrder, Long>
*/
List<FlowWorkOrder> getFlowWorkOrderListWithRelation(FlowWorkOrder filter, String orderBy);
/**
* 根据流程实例Id查询关联的工单对象。
*
* @param processInstanceId 流程实例Id。
* @return 工作流工单对象。
*/
FlowWorkOrder getFlowWorkOrderByProcessInstanceId(String processInstanceId);
/**
* 根据业务主键,查询是否存在指定的工单。
*
@@ -66,6 +74,13 @@ public interface FlowWorkOrderService extends IBaseService<FlowWorkOrder, Long>
*/
boolean existByBusinessKey(Object businessKey, boolean unfinished);
/**
* 根据业务数据的主键Id更新流程状态。
* @param businessKey 业务数据主键Id。
* @param flowStatus 新的流程状态值。
*/
void updateFlowStatusByBusinessKey(String businessKey, int flowStatus);
/**
* 根据流程实例Id更新流程状态。
*

View File

@@ -1,6 +1,7 @@
package com.flow.demo.common.flow.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
import com.flow.demo.common.core.constant.GlobalDeletedFlag;
import com.flow.demo.common.core.object.MyRelationParam;
@@ -109,6 +110,13 @@ public class FlowWorkOrderServiceImpl extends BaseService<FlowWorkOrder, Long> i
return resultList;
}
@Override
public FlowWorkOrder getFlowWorkOrderByProcessInstanceId(String processInstanceId) {
FlowWorkOrder filter = new FlowWorkOrder();
filter.setProcessInstanceId(processInstanceId);
return flowWorkOrderMapper.selectOne(new QueryWrapper<>(filter));
}
@Override
public boolean existByBusinessKey(Object businessKey, boolean unfinished) {
LambdaQueryWrapper<FlowWorkOrder> queryWrapper = new LambdaQueryWrapper<>();
@@ -120,6 +128,20 @@ public class FlowWorkOrderServiceImpl extends BaseService<FlowWorkOrder, Long> i
return flowWorkOrderMapper.selectCount(queryWrapper) > 0;
}
@Transactional(rollbackFor = Exception.class)
@Override
public void updateFlowStatusByBusinessKey(String businessKey, int flowStatus) {
FlowWorkOrder flowWorkOrder = new FlowWorkOrder();
flowWorkOrder.setFlowStatus(flowStatus);
if (FlowTaskStatus.FINISHED != flowStatus) {
flowWorkOrder.setUpdateTime(new Date());
flowWorkOrder.setUpdateUserId(TokenData.takeFromRequest().getUserId());
}
LambdaQueryWrapper<FlowWorkOrder> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(FlowWorkOrder::getBusinessKey, businessKey);
flowWorkOrderMapper.update(flowWorkOrder, queryWrapper);
}
@Transactional(rollbackFor = Exception.class)
@Override
public void updateFlowStatusByProcessInstanceId(String processInstanceId, int flowStatus) {

View File

@@ -7,11 +7,14 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.flow.demo.common.core.constant.ErrorCodeEnum;
import com.flow.demo.common.core.object.CallResult;
import com.flow.demo.common.core.object.ResponseResult;
import com.flow.demo.common.core.object.TokenData;
import com.flow.demo.common.core.util.MyModelUtil;
import com.flow.demo.common.flow.constant.FlowApprovalType;
import com.flow.demo.common.flow.constant.FlowConstant;
import com.flow.demo.common.flow.constant.FlowTaskStatus;
import com.flow.demo.common.flow.dto.FlowTaskCommentDto;
import com.flow.demo.common.flow.dto.FlowWorkOrderDto;
import com.flow.demo.common.flow.model.FlowEntry;
import com.flow.demo.common.flow.model.FlowEntryPublish;
@@ -22,8 +25,11 @@ import com.flow.demo.common.flow.service.FlowEntryService;
import com.flow.demo.common.flow.vo.FlowWorkOrderVo;
import com.flow.demo.common.flow.vo.TaskInfoVo;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskInfo;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -71,6 +77,103 @@ public class FlowOperationHelper {
return ResponseResult.success(flowEntry);
}
/**
* 工作流静态表单的参数验证工具方法。根据流程定义标识,获取关联的流程并对其进行合法性验证。
*
* @param processDefinitionKey 流程定义标识。
* @return 返回流程对象。
*/
public ResponseResult<FlowEntry> verifyFullAndGetFlowEntry(String processDefinitionKey) {
String errorMessage;
// 验证流程管理数据状态的合法性。
ResponseResult<FlowEntry> flowEntryResult = this.verifyAndGetFlowEntry(processDefinitionKey);
if (!flowEntryResult.isSuccess()) {
return ResponseResult.errorFrom(flowEntryResult);
}
// 验证流程一个用户任务的合法性。
FlowEntryPublish flowEntryPublish = flowEntryResult.getData().getMainFlowEntryPublish();
if (!flowEntryPublish.getActiveStatus()) {
errorMessage = "数据验证失败,当前流程发布对象已被挂起,不能启动新流程!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
ResponseResult<TaskInfoVo> taskInfoResult =
this.verifyAndGetInitialTaskInfo(flowEntryPublish, true);
if (!taskInfoResult.isSuccess()) {
return ResponseResult.errorFrom(taskInfoResult);
}
return flowEntryResult;
}
/**
* 工作流静态表单的参数验证工具方法。根据参数验证并获取指定的流程任务对象。
*
* @param processInstanceId 流程实例Id。
* @param taskId 流程任务Id。
* @param flowTaskComment 流程审批对象。
* @return 验证后的流程任务对象。
*/
public ResponseResult<Task> verifySubmitAndGetTask(
String processInstanceId, String taskId, FlowTaskCommentDto flowTaskComment) {
// 验证流程任务的合法性。
Task task = flowApiService.getProcessInstanceActiveTask(processInstanceId, taskId);
ResponseResult<TaskInfoVo> taskInfoResult = this.verifyAndGetRuntimeTaskInfo(task);
if (!taskInfoResult.isSuccess()) {
return ResponseResult.errorFrom(taskInfoResult);
}
CallResult assigneeVerifyResult = flowApiService.verifyAssigneeOrCandidateAndClaim(task);
if (!assigneeVerifyResult.isSuccess()) {
return ResponseResult.errorFrom(assigneeVerifyResult);
}
ProcessInstance instance = flowApiService.getProcessInstance(processInstanceId);
if (StrUtil.isBlank(instance.getBusinessKey())) {
return ResponseResult.success(task);
}
String errorMessage;
if (StrUtil.equals(flowTaskComment.getApprovalType(), FlowApprovalType.TRANSFER)) {
if (StrUtil.isBlank(flowTaskComment.getDelegateAssginee())) {
errorMessage = "数据验证失败,加签或转办任务指派人不能为空!!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
}
return ResponseResult.success(task);
}
/**
* 工作流静态表单的参数验证工具方法。根据参数验证并获取指定的历史流程实例对象。
* 仅当登录用户为任务的分配人时,才能通过验证。
*
* @param processInstanceId 历史流程实例Id。
* @param taskId 历史流程任务Id。
* @return 验证后并返回的历史流程实例对象。
*/
public ResponseResult<HistoricProcessInstance> verifyAndHistoricProcessInstance(String processInstanceId, String taskId) {
String errorMessage;
// 验证流程实例的合法性。
HistoricProcessInstance instance = flowApiService.getHistoricProcessInstance(processInstanceId);
if (instance == null) {
errorMessage = "数据验证失败指定的流程实例Id并不存在请刷新后重试";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
String loginName = TokenData.takeFromRequest().getLoginName();
if (StrUtil.isBlank(taskId)) {
if (!StrUtil.equals(loginName, instance.getStartUserId())) {
errorMessage = "数据验证失败,指定历史流程的发起人与当前用户不匹配!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
} else {
HistoricTaskInstance taskInstance = flowApiService.getHistoricTaskInstance(processInstanceId, taskId);
if (taskInstance == null) {
errorMessage = "数据验证失败指定的任务Id并不存在请刷新后重试";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
if (!StrUtil.equals(loginName, taskInstance.getAssignee())) {
errorMessage = "数据验证失败,历史任务的指派人与当前用户不匹配!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
}
return ResponseResult.success(instance);
}
/**
* 验证并获取流程的实时任务信息。
*

View File

@@ -51,7 +51,7 @@ public class FlowWorkOrderVo {
private String businessKey;
/**
* 流程状态。
* 流程状态。参考FlowTaskStatus常量值对象。
*/
private Integer flowStatus;

View File

@@ -117,6 +117,10 @@ public class OnlineColumnServiceImpl extends BaseService<OnlineColumn, Long> imp
public void refresh(SqlTableColumn sqlTableColumn, OnlineColumn onlineColumn) {
this.evictTableCache(onlineColumn.getTableId());
BeanUtil.copyProperties(sqlTableColumn, onlineColumn, false);
String objectFieldName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, onlineColumn.getColumnName());
onlineColumn.setObjectFieldName(objectFieldName);
String objectFieldType = convertToJavaType(onlineColumn.getColumnType());
onlineColumn.setObjectFieldType(objectFieldType);
onlineColumnMapper.updateById(onlineColumn);
}