Merge remote-tracking branch 'origin/feature/bpm' into feature/bpm
This commit is contained in:
commit
d36fc98f01
|
@ -128,7 +128,7 @@ public class YudaoWebSecurityConfigurerAdapter {
|
||||||
// ①:全局共享规则
|
// ①:全局共享规则
|
||||||
.authorizeHttpRequests(c -> c
|
.authorizeHttpRequests(c -> c
|
||||||
// 1.1 静态资源,可匿名访问
|
// 1.1 静态资源,可匿名访问
|
||||||
.requestMatchers(HttpMethod.GET, "/*.html", "/*.html", "/*.css", "/*.js").permitAll()
|
.requestMatchers(HttpMethod.GET, "/*.html", "/*.css", "/*.js").permitAll()
|
||||||
// 1.2 设置 @PermitAll 无需认证
|
// 1.2 设置 @PermitAll 无需认证
|
||||||
.requestMatchers(HttpMethod.GET, permitAllUrls.get(HttpMethod.GET).toArray(new String[0])).permitAll()
|
.requestMatchers(HttpMethod.GET, permitAllUrls.get(HttpMethod.GET).toArray(new String[0])).permitAll()
|
||||||
.requestMatchers(HttpMethod.POST, permitAllUrls.get(HttpMethod.POST).toArray(new String[0])).permitAll()
|
.requestMatchers(HttpMethod.POST, permitAllUrls.get(HttpMethod.POST).toArray(new String[0])).permitAll()
|
||||||
|
|
|
@ -38,6 +38,7 @@ public interface ErrorCodeConstants {
|
||||||
ErrorCode PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_CONFIG = new ErrorCode(1_009_004_003, "任务({})的候选人未配置");
|
ErrorCode PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_CONFIG = new ErrorCode(1_009_004_003, "任务({})的候选人未配置");
|
||||||
ErrorCode PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_EXISTS = new ErrorCode(1_009_004_004, "任务({})的候选人({})不存在");
|
ErrorCode PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_EXISTS = new ErrorCode(1_009_004_004, "任务({})的候选人({})不存在");
|
||||||
ErrorCode PROCESS_INSTANCE_START_USER_CAN_START = new ErrorCode(1_009_004_005, "发起流程失败,你没有权限发起该流程");
|
ErrorCode PROCESS_INSTANCE_START_USER_CAN_START = new ErrorCode(1_009_004_005, "发起流程失败,你没有权限发起该流程");
|
||||||
|
ErrorCode PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW = new ErrorCode(1_009_004_005, "流程取消失败,该流程不允许取消");
|
||||||
|
|
||||||
// ========== 流程任务 1-009-005-000 ==========
|
// ========== 流程任务 1-009-005-000 ==========
|
||||||
ErrorCode TASK_OPERATE_FAIL_ASSIGN_NOT_SELF = new ErrorCode(1_009_005_001, "操作失败,原因:该任务的审批人不是你");
|
ErrorCode TASK_OPERATE_FAIL_ASSIGN_NOT_SELF = new ErrorCode(1_009_005_001, "操作失败,原因:该任务的审批人不是你");
|
||||||
|
@ -55,6 +56,7 @@ public interface ErrorCodeConstants {
|
||||||
ErrorCode TASK_TRANSFER_FAIL_USER_NOT_EXISTS = new ErrorCode(1_009_005_014, "任务转办失败,转办人不存在");
|
ErrorCode TASK_TRANSFER_FAIL_USER_NOT_EXISTS = new ErrorCode(1_009_005_014, "任务转办失败,转办人不存在");
|
||||||
ErrorCode TASK_CREATE_FAIL_NO_CANDIDATE_USER = new ErrorCode(1_009_006_003, "操作失败,原因:找不到任务的审批人!");
|
ErrorCode TASK_CREATE_FAIL_NO_CANDIDATE_USER = new ErrorCode(1_009_006_003, "操作失败,原因:找不到任务的审批人!");
|
||||||
ErrorCode TASK_SIGNATURE_NOT_EXISTS = new ErrorCode(1_009_005_015, "签名不能为空!");
|
ErrorCode TASK_SIGNATURE_NOT_EXISTS = new ErrorCode(1_009_005_015, "签名不能为空!");
|
||||||
|
ErrorCode TASK_REASON_REQUIRE = new ErrorCode(1_009_005_016, "审批意见不能为空!");
|
||||||
|
|
||||||
// ========== 动态表单模块 1-009-010-000 ==========
|
// ========== 动态表单模块 1-009-010-000 ==========
|
||||||
ErrorCode FORM_NOT_EXISTS = new ErrorCode(1_009_010_000, "动态表单不存在");
|
ErrorCode FORM_NOT_EXISTS = new ErrorCode(1_009_010_000, "动态表单不存在");
|
||||||
|
|
|
@ -161,6 +161,15 @@ public class BpmModelController {
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/clean")
|
||||||
|
@Operation(summary = "清理模型")
|
||||||
|
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||||
|
@PreAuthorize("@ss.hasPermission('bpm:model:clean')")
|
||||||
|
public CommonResult<Boolean> cleanModel(@RequestParam("id") String id) {
|
||||||
|
modelService.cleanModel(getLoginUserId(), id);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
// ========== 仿钉钉/飞书的精简模型 =========
|
// ========== 仿钉钉/飞书的精简模型 =========
|
||||||
|
|
||||||
@GetMapping("/simple/get")
|
@GetMapping("/simple/get")
|
||||||
|
|
|
@ -62,4 +62,7 @@ public class BpmModelMetaInfoVO {
|
||||||
@Schema(description = "排序", example = "1")
|
@Schema(description = "排序", example = "1")
|
||||||
private Long sort; // 创建时,后端自动生成
|
private Long sort; // 创建时,后端自动生成
|
||||||
|
|
||||||
|
@Schema(description = "允许撤销审批中的申请", example = "true")
|
||||||
|
private Boolean allowCancelRunningProcess;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,9 @@ public class BpmSimpleModelNodeVO {
|
||||||
@Schema(description = "是否需要签名", example = "false")
|
@Schema(description = "是否需要签名", example = "false")
|
||||||
private Boolean signEnable;
|
private Boolean signEnable;
|
||||||
|
|
||||||
|
@Schema(description = "是否填写审批意见", example = "false")
|
||||||
|
private Boolean reasonRequire;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 审批节点拒绝处理
|
* 审批节点拒绝处理
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -101,9 +101,8 @@ public class BpmApprovalDetailRespVO {
|
||||||
@Schema(description = "审批意见", example = "同意")
|
@Schema(description = "审批意见", example = "同意")
|
||||||
private String reason;
|
private String reason;
|
||||||
|
|
||||||
// TODO @lesan:改成 signPicUrl 会好点
|
|
||||||
@Schema(description = "签名", example = "https://www.iocoder.cn/sign.png")
|
@Schema(description = "签名", example = "https://www.iocoder.cn/sign.png")
|
||||||
private String sign;
|
private String signPicUrl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,11 @@ public class BpmTaskApproveReqVO {
|
||||||
@NotEmpty(message = "任务编号不能为空")
|
@NotEmpty(message = "任务编号不能为空")
|
||||||
private String id;
|
private String id;
|
||||||
|
|
||||||
@Schema(description = "审批意见", requiredMode = Schema.RequiredMode.REQUIRED, example = "不错不错!")
|
@Schema(description = "审批意见", example = "不错不错!")
|
||||||
@NotEmpty(message = "审批意见不能为空")
|
|
||||||
private String reason;
|
private String reason;
|
||||||
|
|
||||||
// TODO @lesan:改成 signPicUrl 会好点
|
|
||||||
@Schema(description = "签名", example = "https://www.iocoder.cn/sign.png")
|
@Schema(description = "签名", example = "https://www.iocoder.cn/sign.png")
|
||||||
private String sign;
|
private String signPicUrl;
|
||||||
|
|
||||||
@Schema(description = "变量实例(动态表单)", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "变量实例(动态表单)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private Map<String, Object> variables;
|
private Map<String, Object> variables;
|
||||||
|
|
|
@ -14,7 +14,6 @@ public class BpmTaskRejectReqVO {
|
||||||
private String id;
|
private String id;
|
||||||
|
|
||||||
@Schema(description = "审批意见", requiredMode = Schema.RequiredMode.REQUIRED, example = "不错不错!")
|
@Schema(description = "审批意见", requiredMode = Schema.RequiredMode.REQUIRED, example = "不错不错!")
|
||||||
@NotEmpty(message = "审批意见不能为空")
|
|
||||||
private String reason;
|
private String reason;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,9 +78,12 @@ public class BpmTaskRespVO {
|
||||||
@Schema(description = "操作按钮设置值")
|
@Schema(description = "操作按钮设置值")
|
||||||
private Map<Integer, OperationButtonSetting> buttonsSetting;
|
private Map<Integer, OperationButtonSetting> buttonsSetting;
|
||||||
|
|
||||||
@Schema(description = "是否需要签名")
|
@Schema(description = "是否需要签名", example = "false")
|
||||||
private Boolean signEnable;
|
private Boolean signEnable;
|
||||||
|
|
||||||
|
@Schema(description = "是否填写审批意见", example = "false")
|
||||||
|
private Boolean reasonRequire;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@Schema(description = "流程实例")
|
@Schema(description = "流程实例")
|
||||||
public static class ProcessInstance {
|
public static class ProcessInstance {
|
||||||
|
|
|
@ -187,7 +187,7 @@ public interface BpmProcessInstanceConvert {
|
||||||
}
|
}
|
||||||
return BeanUtils.toBean(task, BpmApprovalDetailRespVO.ActivityNodeTask.class)
|
return BeanUtils.toBean(task, BpmApprovalDetailRespVO.ActivityNodeTask.class)
|
||||||
.setStatus(FlowableUtils.getTaskStatus(task)).setReason(FlowableUtils.getTaskReason(task))
|
.setStatus(FlowableUtils.getTaskStatus(task)).setReason(FlowableUtils.getTaskReason(task))
|
||||||
.setSign(FlowableUtils.getTaskSign(task));
|
.setSignPicUrl(FlowableUtils.getTaskSignPicUrl(task));
|
||||||
}
|
}
|
||||||
|
|
||||||
default Set<Long> parseUserIds(HistoricProcessInstance processInstance,
|
default Set<Long> parseUserIds(HistoricProcessInstance processInstance,
|
||||||
|
|
|
@ -150,4 +150,9 @@ public class BpmProcessDefinitionInfoDO extends BaseDO {
|
||||||
@TableField(typeHandler = StringListTypeHandler.class) // 为了可以使用 find_in_set 进行过滤
|
@TableField(typeHandler = StringListTypeHandler.class) // 为了可以使用 find_in_set 进行过滤
|
||||||
private List<Long> managerUserIds;
|
private List<Long> managerUserIds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否允许撤销审批中的申请
|
||||||
|
*/
|
||||||
|
private Boolean allowCancelRunningProcess;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,4 +115,9 @@ public interface BpmnModelConstants {
|
||||||
*/
|
*/
|
||||||
String SIGN_ENABLE = "signEnable";
|
String SIGN_ENABLE = "signEnable";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审批意见是否必填
|
||||||
|
*/
|
||||||
|
String REASON_REQUIRE = "reasonRequire";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,13 @@ public class BpmnVariableConstants {
|
||||||
* @see ProcessInstance#getProcessVariables()
|
* @see ProcessInstance#getProcessVariables()
|
||||||
*/
|
*/
|
||||||
public static final String PROCESS_INSTANCE_VARIABLE_RETURN_FLAG = "RETURN_FLAG_%s";
|
public static final String PROCESS_INSTANCE_VARIABLE_RETURN_FLAG = "RETURN_FLAG_%s";
|
||||||
|
/**
|
||||||
|
* 流程实例的变量 - 是否跳过表达式
|
||||||
|
*
|
||||||
|
* @see ProcessInstance#getProcessVariables()
|
||||||
|
* @see <a href="https://blog.csdn.net/weixin_42065235/article/details/126039993">Flowable/Activiti之SkipExpression 完成自动审批</a>
|
||||||
|
*/
|
||||||
|
public static final String PROCESS_INSTANCE_SKIP_EXPRESSION_ENABLED = "_FLOWABLE_SKIP_EXPRESSION_ENABLED";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 任务的变量 - 状态
|
* 任务的变量 - 状态
|
||||||
|
@ -58,8 +65,9 @@ public class BpmnVariableConstants {
|
||||||
* @see org.flowable.task.api.Task#getTaskLocalVariables()
|
* @see org.flowable.task.api.Task#getTaskLocalVariables()
|
||||||
*/
|
*/
|
||||||
public static final String TASK_VARIABLE_REASON = "TASK_REASON";
|
public static final String TASK_VARIABLE_REASON = "TASK_REASON";
|
||||||
|
/**
|
||||||
// TODO @lesan:TASK_SIGN_PIC_URL 。。。虽然长一点,嘿嘿
|
* 任务变量 - 签名图片 URL
|
||||||
public static final String TASK_VARIABLE_SIGN = "TASK_SIGN";
|
*/
|
||||||
|
public static final String TASK_SIGN_PIC_URL = "TASK_SIGN_PIC_URL";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,10 +39,10 @@ public class BpmProcessInstanceEventListener extends AbstractFlowableEngineEvent
|
||||||
processInstanceService.processProcessInstanceCompleted((ProcessInstance)event.getEntity());
|
processInstanceService.processProcessInstanceCompleted((ProcessInstance)event.getEntity());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override // 特殊情况:当跳转到 EndEvent 流程实例未结束, 会执行 deleteProcessInstance 方法
|
||||||
// 特殊情况:当跳转到 EndEvent 流程实例未结束, 会执行 deleteProcessInstance 方法。
|
|
||||||
protected void processCancelled(FlowableCancelledEvent event) {
|
protected void processCancelled(FlowableCancelledEvent event) {
|
||||||
ProcessInstance processInstance = processInstanceService.getProcessInstance(event.getProcessInstanceId());
|
ProcessInstance processInstance = processInstanceService.getProcessInstance(event.getProcessInstanceId());
|
||||||
processInstanceService.processProcessInstanceCompleted(processInstance);
|
processInstanceService.processProcessInstanceCompleted(processInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -365,6 +365,23 @@ public class BpmnModelUtils {
|
||||||
return Convert.toBool(extensionElements.get(0).getElementText(), false);
|
return Convert.toBool(extensionElements.get(0).getElementText(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void addReasonRequire(Boolean reasonRequire, FlowElement userTask) {
|
||||||
|
addExtensionElement(userTask, REASON_REQUIRE,
|
||||||
|
ObjUtil.isNotNull(reasonRequire) ? reasonRequire.toString() : Boolean.FALSE.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Boolean parseReasonRequire(BpmnModel bpmnModel, String flowElementId) {
|
||||||
|
FlowElement flowElement = getFlowElementById(bpmnModel, flowElementId);
|
||||||
|
if (flowElement == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
List<ExtensionElement> extensionElements = flowElement.getExtensionElements().get(REASON_REQUIRE);
|
||||||
|
if (CollUtil.isEmpty(extensionElements)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Convert.toBool(extensionElements.get(0).getElementText(), false);
|
||||||
|
}
|
||||||
|
|
||||||
public static void addListenerConfig(FlowableListener flowableListener, BpmSimpleModelNodeVO.ListenerHandler handler) {
|
public static void addListenerConfig(FlowableListener flowableListener, BpmSimpleModelNodeVO.ListenerHandler handler) {
|
||||||
FieldExtension fieldExtension = new FieldExtension();
|
FieldExtension fieldExtension = new FieldExtension();
|
||||||
fieldExtension.setFieldName("listenerConfig");
|
fieldExtension.setFieldName("listenerConfig");
|
||||||
|
|
|
@ -213,9 +213,14 @@ public class FlowableUtils {
|
||||||
return (String) task.getTaskLocalVariables().get(BpmnVariableConstants.TASK_VARIABLE_REASON);
|
return (String) task.getTaskLocalVariables().get(BpmnVariableConstants.TASK_VARIABLE_REASON);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO @lesan:这个方法名,也改咧
|
/**
|
||||||
public static String getTaskSign(TaskInfo task) {
|
* 获得任务的签名图片 URL
|
||||||
return (String) task.getTaskLocalVariables().get(BpmnVariableConstants.TASK_VARIABLE_SIGN);
|
*
|
||||||
|
* @param task 任务
|
||||||
|
* @return 签名图片 URL
|
||||||
|
*/
|
||||||
|
public static String getTaskSignPicUrl(TaskInfo task) {
|
||||||
|
return (String) task.getTaskLocalVariables().get(BpmnVariableConstants.TASK_SIGN_PIC_URL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -441,6 +441,8 @@ public class SimpleModelUtils {
|
||||||
addUserTaskListener(node, userTask);
|
addUserTaskListener(node, userTask);
|
||||||
// 添加是否需要签名
|
// 添加是否需要签名
|
||||||
addSignEnable(node.getSignEnable(), userTask);
|
addSignEnable(node.getSignEnable(), userTask);
|
||||||
|
// 审批意见
|
||||||
|
addReasonRequire(node.getReasonRequire(), userTask);
|
||||||
return userTask;
|
return userTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,6 +88,14 @@ public interface BpmModelService {
|
||||||
*/
|
*/
|
||||||
void deleteModel(Long userId, String id);
|
void deleteModel(Long userId, String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理模型,包括流程实例
|
||||||
|
*
|
||||||
|
* @param userId 用户编号
|
||||||
|
* @param id 编号
|
||||||
|
*/
|
||||||
|
void cleanModel(Long userId, String id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改模型的状态,实际更新的部署的流程定义的状态
|
* 修改模型的状态,实际更新的部署的流程定义的状态
|
||||||
*
|
*
|
||||||
|
|
|
@ -14,6 +14,7 @@ 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.dal.dataobject.definition.BpmFormDO;
|
||||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
|
import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
|
||||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelTypeEnum;
|
import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelTypeEnum;
|
||||||
|
import cn.iocoder.yudao.module.bpm.enums.task.BpmReasonEnum;
|
||||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker;
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker;
|
||||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
|
||||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
|
||||||
|
@ -25,10 +26,14 @@ import org.flowable.bpmn.model.BpmnModel;
|
||||||
import org.flowable.bpmn.model.StartEvent;
|
import org.flowable.bpmn.model.StartEvent;
|
||||||
import org.flowable.bpmn.model.UserTask;
|
import org.flowable.bpmn.model.UserTask;
|
||||||
import org.flowable.common.engine.impl.db.SuspensionState;
|
import org.flowable.common.engine.impl.db.SuspensionState;
|
||||||
|
import org.flowable.engine.HistoryService;
|
||||||
import org.flowable.engine.RepositoryService;
|
import org.flowable.engine.RepositoryService;
|
||||||
|
import org.flowable.engine.RuntimeService;
|
||||||
|
import org.flowable.engine.history.HistoricProcessInstance;
|
||||||
import org.flowable.engine.repository.Model;
|
import org.flowable.engine.repository.Model;
|
||||||
import org.flowable.engine.repository.ModelQuery;
|
import org.flowable.engine.repository.ModelQuery;
|
||||||
import org.flowable.engine.repository.ProcessDefinition;
|
import org.flowable.engine.repository.ProcessDefinition;
|
||||||
|
import org.flowable.engine.runtime.ProcessInstance;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
@ -63,6 +68,11 @@ public class BpmModelServiceImpl implements BpmModelService {
|
||||||
@Resource
|
@Resource
|
||||||
private BpmTaskCandidateInvoker taskCandidateInvoker;
|
private BpmTaskCandidateInvoker taskCandidateInvoker;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private HistoryService historyService;
|
||||||
|
@Resource
|
||||||
|
private RuntimeService runtimeService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Model> getModelList(String name) {
|
public List<Model> getModelList(String name) {
|
||||||
ModelQuery modelQuery = repositoryService.createModelQuery();
|
ModelQuery modelQuery = repositoryService.createModelQuery();
|
||||||
|
@ -246,6 +256,31 @@ public class BpmModelServiceImpl implements BpmModelService {
|
||||||
updateProcessDefinitionSuspended(model.getDeploymentId());
|
updateProcessDefinitionSuspended(model.getDeploymentId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cleanModel(Long userId, String id) {
|
||||||
|
// 1. 校验流程模型存在
|
||||||
|
Model model = validateModelManager(id, userId);
|
||||||
|
|
||||||
|
// 2. 清理所有流程数据
|
||||||
|
// TODO @芋艿:这里没有找到批量操作的方法,会不会有性能问题~;
|
||||||
|
// TODO @lesan:建议按照顺序?1)List<ProcessInstance> processInstances 循环处理;然后删除删除一个示实例,接着删除它的 history;
|
||||||
|
// 2.1 先取消所有正在运行的流程
|
||||||
|
List<ProcessInstance> processInstances = runtimeService.createProcessInstanceQuery()
|
||||||
|
.processDefinitionKey(model.getKey()).list();
|
||||||
|
processInstances.forEach(processInstance -> {
|
||||||
|
runtimeService.deleteProcessInstance(processInstance.getId(),
|
||||||
|
BpmReasonEnum.CANCEL_BY_SYSTEM.getReason());
|
||||||
|
});
|
||||||
|
// 2.2 再从历史中删除所有相关的流程数据
|
||||||
|
List<HistoricProcessInstance> historicProcessInstances = historyService.createHistoricProcessInstanceQuery()
|
||||||
|
.processDefinitionKey(model.getKey()).list();
|
||||||
|
historicProcessInstances.forEach(historicProcessInstance -> {
|
||||||
|
historyService.deleteHistoricProcessInstance(historicProcessInstance.getId());
|
||||||
|
});
|
||||||
|
// TODO @lesan:流程任务,是不是也要清理哈?
|
||||||
|
// TODO @lesan:抄送是不是也要清理;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateModelState(Long userId, String id, Integer state) {
|
public void updateModelState(Long userId, String id, Integer state) {
|
||||||
// 1.1 校验流程模型存在
|
// 1.1 校验流程模型存在
|
||||||
|
|
|
@ -595,6 +595,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
||||||
variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_ID, userId); // 设置流程变量,发起人 ID
|
variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_ID, userId); // 设置流程变量,发起人 ID
|
||||||
variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS, // 流程实例状态:审批中
|
variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS, // 流程实例状态:审批中
|
||||||
BpmProcessInstanceStatusEnum.RUNNING.getStatus());
|
BpmProcessInstanceStatusEnum.RUNNING.getStatus());
|
||||||
|
variables.put(BpmnVariableConstants.PROCESS_INSTANCE_SKIP_EXPRESSION_ENABLED, true); // 跳过表达式需要添加此变量为 true,不影响没配置 skipExpression 的节点
|
||||||
if (CollUtil.isNotEmpty(startUserSelectAssignees)) {
|
if (CollUtil.isNotEmpty(startUserSelectAssignees)) {
|
||||||
variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES, startUserSelectAssignees);
|
variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES, startUserSelectAssignees);
|
||||||
}
|
}
|
||||||
|
@ -641,6 +642,13 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
||||||
if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) {
|
if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) {
|
||||||
throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF);
|
throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF);
|
||||||
}
|
}
|
||||||
|
// 1.3 校验允许撤销审批中的申请
|
||||||
|
BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.getProcessDefinitionInfo(instance.getProcessDefinitionId());
|
||||||
|
Assert.notNull(processDefinitionInfo, "流程定义({})不存在", processDefinitionInfo);
|
||||||
|
if (processDefinitionInfo.getAllowCancelRunningProcess() != null // 防止未配置 AllowCancelRunningProcess , 默认为可取消
|
||||||
|
&& Boolean.FALSE.equals(processDefinitionInfo.getAllowCancelRunningProcess())) {
|
||||||
|
throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW);
|
||||||
|
}
|
||||||
|
|
||||||
// 2. 取消流程
|
// 2. 取消流程
|
||||||
updateProcessInstanceCancel(cancelReqVO.getId(),
|
updateProcessInstanceCancel(cancelReqVO.getId(),
|
||||||
|
|
|
@ -64,6 +64,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
|
||||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
|
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
|
||||||
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_RETURN_FLAG;
|
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_RETURN_FLAG;
|
||||||
|
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.parseReasonRequire;
|
||||||
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.parseSignEnable;
|
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.parseSignEnable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -163,6 +164,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
||||||
Map<Integer, BpmTaskRespVO.OperationButtonSetting> buttonsSetting = BpmnModelUtils.parseButtonsSetting(
|
Map<Integer, BpmTaskRespVO.OperationButtonSetting> buttonsSetting = BpmnModelUtils.parseButtonsSetting(
|
||||||
bpmnModel, todoTask.getTaskDefinitionKey());
|
bpmnModel, todoTask.getTaskDefinitionKey());
|
||||||
Boolean signEnable = parseSignEnable(bpmnModel, todoTask.getTaskDefinitionKey());
|
Boolean signEnable = parseSignEnable(bpmnModel, todoTask.getTaskDefinitionKey());
|
||||||
|
Boolean reasonRequire = parseReasonRequire(bpmnModel, todoTask.getTaskDefinitionKey());
|
||||||
|
|
||||||
// 4. 任务表单
|
// 4. 任务表单
|
||||||
BpmFormDO taskForm = null;
|
BpmFormDO taskForm = null;
|
||||||
|
@ -171,7 +173,8 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
||||||
}
|
}
|
||||||
|
|
||||||
return BpmTaskConvert.INSTANCE.buildTodoTask(todoTask, childrenTasks, buttonsSetting, taskForm)
|
return BpmTaskConvert.INSTANCE.buildTodoTask(todoTask, childrenTasks, buttonsSetting, taskForm)
|
||||||
.setSignEnable(signEnable);
|
.setSignEnable(signEnable)
|
||||||
|
.setReasonRequire(reasonRequire);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -485,9 +488,14 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
||||||
// 1.3 校验签名
|
// 1.3 校验签名
|
||||||
BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(task.getProcessDefinitionId());
|
BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(task.getProcessDefinitionId());
|
||||||
Boolean signEnable = parseSignEnable(bpmnModel, task.getTaskDefinitionKey());
|
Boolean signEnable = parseSignEnable(bpmnModel, task.getTaskDefinitionKey());
|
||||||
if (signEnable && StrUtil.isEmpty(reqVO.getSign())) {
|
if (signEnable && StrUtil.isEmpty(reqVO.getSignPicUrl())) {
|
||||||
throw exception(TASK_SIGNATURE_NOT_EXISTS);
|
throw exception(TASK_SIGNATURE_NOT_EXISTS);
|
||||||
}
|
}
|
||||||
|
// 1.4 校验审批意见
|
||||||
|
Boolean reasonRequire = parseReasonRequire(bpmnModel, task.getTaskDefinitionKey());
|
||||||
|
if (reasonRequire && StrUtil.isEmpty(reqVO.getReason())) {
|
||||||
|
throw exception(TASK_REASON_REQUIRE);
|
||||||
|
}
|
||||||
|
|
||||||
// 情况一:被委派的任务,不调用 complete 去完成任务
|
// 情况一:被委派的任务,不调用 complete 去完成任务
|
||||||
if (DelegationState.PENDING.equals(task.getDelegationState())) {
|
if (DelegationState.PENDING.equals(task.getDelegationState())) {
|
||||||
|
@ -505,7 +513,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
||||||
// 2.1 更新 task 状态、原因、签字
|
// 2.1 更新 task 状态、原因、签字
|
||||||
updateTaskStatusAndReason(task.getId(), BpmTaskStatusEnum.APPROVE.getStatus(), reqVO.getReason());
|
updateTaskStatusAndReason(task.getId(), BpmTaskStatusEnum.APPROVE.getStatus(), reqVO.getReason());
|
||||||
if (signEnable) {
|
if (signEnable) {
|
||||||
taskService.setVariableLocal(task.getId(), BpmnVariableConstants.TASK_VARIABLE_SIGN, reqVO.getSign());
|
taskService.setVariableLocal(task.getId(), BpmnVariableConstants.TASK_SIGN_PIC_URL, reqVO.getSignPicUrl());
|
||||||
}
|
}
|
||||||
// 2.2 添加评论
|
// 2.2 添加评论
|
||||||
taskService.addComment(task.getId(), task.getProcessInstanceId(), BpmCommentTypeEnum.APPROVE.getType(),
|
taskService.addComment(task.getId(), task.getProcessInstanceId(), BpmCommentTypeEnum.APPROVE.getType(),
|
||||||
|
@ -859,10 +867,11 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
||||||
.moveActivityIdsToSingleActivityId(activityIds, endEvent.getId())
|
.moveActivityIdsToSingleActivityId(activityIds, endEvent.getId())
|
||||||
.changeState();
|
.changeState();
|
||||||
|
|
||||||
// 3. 如果跳转到 EndEvent 流程还未结束, 执行 deleteProcessInstance 方法。
|
// 3. 特殊:如果跳转到 EndEvent 流程还未结束, 执行 deleteProcessInstance 方法
|
||||||
List<Execution> executionList = runtimeService.createExecutionQuery().processInstanceId(processInstanceId).list();
|
// TODO 芋艿:目前发现并行分支情况下,会存在这个情况,后续看看有没更好的方案;
|
||||||
if (CollUtil.isNotEmpty(executionList)) {
|
List<Execution> executions = runtimeService.createExecutionQuery().processInstanceId(processInstanceId).list();
|
||||||
log.warn("执行跳转到 EndEvent 后, 流程实例未结束。执行 [deleteProcessInstance] 方法");
|
if (CollUtil.isNotEmpty(executions)) {
|
||||||
|
log.warn("[moveTaskToEnd][执行跳转到 EndEvent 后, 流程实例未结束,强制执行 deleteProcessInstance 方法]");
|
||||||
runtimeService.deleteProcessInstance(processInstanceId, reason);
|
runtimeService.deleteProcessInstance(processInstanceId, reason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ import static cn.iocoder.yudao.framework.pay.core.client.impl.weixin.WxPayClient
|
||||||
/**
|
/**
|
||||||
* 微信支付抽象类,实现微信统一的接口、以及部分实现(退款)
|
* 微信支付抽象类,实现微信统一的接口、以及部分实现(退款)
|
||||||
*
|
*
|
||||||
* @author 遇到源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientConfig> {
|
public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientConfig> {
|
||||||
|
|
Loading…
Reference in New Issue