commit
987bf3ebe9
|
@ -4,8 +4,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
|||
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
@ -17,6 +15,9 @@ public class BpmTaskPageReqVO extends PageParam {
|
|||
@Schema(description = "流程任务名", example = "芋道")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "流程分类", example = "1")
|
||||
private String category;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
|
|
@ -124,12 +124,18 @@ public interface BpmTaskConvert {
|
|||
}
|
||||
|
||||
default BpmTaskRespVO buildTodoTask(Task todoTask, List<Task> childrenTasks,
|
||||
Map<Integer, BpmTaskRespVO.OperationButtonSetting> buttonsSetting) {
|
||||
return BeanUtils.toBean(todoTask, BpmTaskRespVO.class)
|
||||
Map<Integer, BpmTaskRespVO.OperationButtonSetting> buttonsSetting,
|
||||
BpmFormDO form) {
|
||||
BpmTaskRespVO bpmTaskRespVO = BeanUtils.toBean(todoTask, BpmTaskRespVO.class)
|
||||
.setStatus(FlowableUtils.getTaskStatus(todoTask)).setReason(FlowableUtils.getTaskReason(todoTask))
|
||||
.setButtonsSetting(buttonsSetting)
|
||||
.setChildren(convertList(childrenTasks, childTask -> BeanUtils.toBean(childTask, BpmTaskRespVO.class)
|
||||
.setStatus(FlowableUtils.getTaskStatus(childTask))));
|
||||
if (form != null) {
|
||||
bpmTaskRespVO.setFormId(form.getId()).setFormName(form.getName())
|
||||
.setFormConf(form.getConf()).setFormFields(form.getFields());
|
||||
}
|
||||
return bpmTaskRespVO;
|
||||
}
|
||||
|
||||
default BpmMessageSendWhenTaskCreatedReqDTO convert(ProcessInstance processInstance, AdminUserRespDTO startUser,
|
||||
|
|
|
@ -54,13 +54,13 @@ public class BpmParallelMultiInstanceBehavior extends ParallelMultiInstanceBehav
|
|||
Set<Long> assigneeUserIds = (Set<Long>) execution.getVariable(super.collectionVariable, Set.class);
|
||||
if (assigneeUserIds == null) {
|
||||
assigneeUserIds = taskCandidateInvoker.calculateUsersByTask(execution);
|
||||
execution.setVariable(super.collectionVariable, assigneeUserIds);
|
||||
if (CollUtil.isEmpty(assigneeUserIds)) {
|
||||
// 特殊:如果没有处理人的情况下,至少有一个 null 空元素,避免自动通过!
|
||||
// 这样,保证在 BpmUserTaskActivityBehavior 至少创建出一个 Task 任务
|
||||
// 用途:1)审批人为空时;2)审批类型为自动通过、自动拒绝时
|
||||
assigneeUserIds = SetUtils.asSet((Long) null);
|
||||
}
|
||||
execution.setVariableLocal(super.collectionVariable, assigneeUserIds);
|
||||
}
|
||||
return assigneeUserIds.size();
|
||||
}
|
||||
|
|
|
@ -43,17 +43,18 @@ public class BpmSequentialMultiInstanceBehavior extends SequentialMultiInstanceB
|
|||
super.collectionElementVariable = FlowableUtils.formatExecutionCollectionElementVariable(execution.getCurrentActivityId());
|
||||
|
||||
// 第二步,获取任务的所有处理人
|
||||
// 不使用 execution.getVariable 原因:目前依次审批任务回退后 collectionVariable 变量没有清理, 如果重新进入该任务不会重新分配审批人
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<Long> assigneeUserIds = (Set<Long>) execution.getVariable(super.collectionVariable, Set.class);
|
||||
Set<Long> assigneeUserIds = (Set<Long>) execution.getVariableLocal(super.collectionVariable, Set.class);
|
||||
if (assigneeUserIds == null) {
|
||||
assigneeUserIds = taskCandidateInvoker.calculateUsersByTask(execution);
|
||||
execution.setVariable(super.collectionVariable, assigneeUserIds);
|
||||
if (CollUtil.isEmpty(assigneeUserIds)) {
|
||||
// 特殊:如果没有处理人的情况下,至少有一个 null 空元素,避免自动通过!
|
||||
// 这样,保证在 BpmUserTaskActivityBehavior 至少创建出一个 Task 任务
|
||||
// 用途:1)审批人为空时;2)审批类型为自动通过、自动拒绝时
|
||||
assigneeUserIds = SetUtils.asSet((Long) null);
|
||||
}
|
||||
execution.setVariableLocal(super.collectionVariable, assigneeUserIds);
|
||||
}
|
||||
return assigneeUserIds.size();
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ import java.util.Set;
|
|||
* @author jason
|
||||
*/
|
||||
@Component
|
||||
public class BpmTaskCandidateFormSDeptLeaderStrategy extends AbstractBpmTaskCandidateDeptLeaderStrategy {
|
||||
public class BpmTaskCandidateFormDeptLeaderStrategy extends AbstractBpmTaskCandidateDeptLeaderStrategy {
|
||||
|
||||
@Override
|
||||
public BpmTaskCandidateStrategyEnum getStrategy() {
|
|
@ -4,10 +4,14 @@ import cn.hutool.core.convert.Convert;
|
|||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
|
||||
import com.google.common.collect.Sets;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.common.engine.api.FlowableException;
|
||||
import org.flowable.engine.delegate.DelegateExecution;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -17,6 +21,7 @@ import java.util.Set;
|
|||
* @author 芋道源码
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class BpmTaskCandidateExpressionStrategy implements BpmTaskCandidateStrategy {
|
||||
|
||||
@Override
|
||||
|
@ -38,8 +43,16 @@ public class BpmTaskCandidateExpressionStrategy implements BpmTaskCandidateStrat
|
|||
@Override
|
||||
public Set<Long> calculateUsersByActivity(BpmnModel bpmnModel, String activityId, String param,
|
||||
Long startUserId, String processDefinitionId, Map<String, Object> processVariables) {
|
||||
Object result = FlowableUtils.getExpressionValue(processVariables, param);
|
||||
return Convert.toSet(Long.class, result);
|
||||
Map<String, Object> variables = processVariables == null ? new HashMap<>() : processVariables;
|
||||
try {
|
||||
Object result = FlowableUtils.getExpressionValue(variables, param);
|
||||
return Convert.toSet(Long.class, result);
|
||||
} catch (FlowableException ex) {
|
||||
// 预测未运行的节点时候,表达式如果包含 execution 或者不存在的流程变量会抛异常,
|
||||
log.warn("[calculateUsersByActivity][表达式({}) 变量({}) 解析报错", param, variables, ex);
|
||||
// 不能预测候选人,返回空列表, 避免流程无法进行
|
||||
return Sets.newHashSet();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -73,7 +73,6 @@ public class BpmnModelUtils {
|
|||
extensionElement.setName(name);
|
||||
attributes.forEach((key, value) -> {
|
||||
ExtensionAttribute extensionAttribute = new ExtensionAttribute(key, value);
|
||||
extensionAttribute.setNamespace(FLOWABLE_EXTENSIONS_NAMESPACE);
|
||||
extensionElement.addAttribute(extensionAttribute);
|
||||
});
|
||||
element.addExtensionElement(extensionElement);
|
||||
|
@ -278,8 +277,8 @@ public class BpmnModelUtils {
|
|||
}
|
||||
Map<String, String> fieldsPermission = MapUtil.newHashMap();
|
||||
extensionElements.forEach(element -> {
|
||||
String field = element.getAttributeValue(FLOWABLE_EXTENSIONS_NAMESPACE, FORM_FIELD_PERMISSION_ELEMENT_FIELD_ATTRIBUTE);
|
||||
String permission = element.getAttributeValue(FLOWABLE_EXTENSIONS_NAMESPACE, FORM_FIELD_PERMISSION_ELEMENT_PERMISSION_ATTRIBUTE);
|
||||
String field = element.getAttributeValue(null, FORM_FIELD_PERMISSION_ELEMENT_FIELD_ATTRIBUTE);
|
||||
String permission = element.getAttributeValue(null, FORM_FIELD_PERMISSION_ELEMENT_PERMISSION_ATTRIBUTE);
|
||||
if (StrUtil.isNotEmpty(field) && StrUtil.isNotEmpty(permission)) {
|
||||
fieldsPermission.put(field, permission);
|
||||
}
|
||||
|
@ -321,9 +320,9 @@ public class BpmnModelUtils {
|
|||
}
|
||||
Map<Integer, BpmTaskRespVO.OperationButtonSetting> buttonSettings = Maps.newHashMapWithExpectedSize(extensionElements.size());
|
||||
extensionElements.forEach(element -> {
|
||||
String id = element.getAttributeValue(FLOWABLE_EXTENSIONS_NAMESPACE, BUTTON_SETTING_ELEMENT_ID_ATTRIBUTE);
|
||||
String displayName = element.getAttributeValue(FLOWABLE_EXTENSIONS_NAMESPACE, BUTTON_SETTING_ELEMENT_DISPLAY_NAME_ATTRIBUTE);
|
||||
String enable = element.getAttributeValue(FLOWABLE_EXTENSIONS_NAMESPACE, BUTTON_SETTING_ELEMENT_ENABLE_ATTRIBUTE);
|
||||
String id = element.getAttributeValue(null, BUTTON_SETTING_ELEMENT_ID_ATTRIBUTE);
|
||||
String displayName = element.getAttributeValue(null, BUTTON_SETTING_ELEMENT_DISPLAY_NAME_ATTRIBUTE);
|
||||
String enable = element.getAttributeValue(null, BUTTON_SETTING_ELEMENT_ENABLE_ATTRIBUTE);
|
||||
if (StrUtil.isNotEmpty(id)) {
|
||||
BpmTaskRespVO.OperationButtonSetting setting = new BpmTaskRespVO.OperationButtonSetting();
|
||||
buttonSettings.put(Integer.valueOf(id), setting.setDisplayName(displayName).setEnable(Boolean.parseBoolean(enable)));
|
||||
|
@ -720,7 +719,7 @@ public class BpmnModelUtils {
|
|||
&& evalConditionExpress(variables, flow.getConditionExpression()));
|
||||
if (matchSequenceFlow == null) {
|
||||
matchSequenceFlow = CollUtil.findOne(gateway.getOutgoingFlows(),
|
||||
flow -> ObjUtil.notEqual(gateway.getDefaultFlow(), flow.getId()));
|
||||
flow -> ObjUtil.equal(gateway.getDefaultFlow(), flow.getId()));
|
||||
// 特殊:没有默认的情况下,并且只有 1 个条件,则认为它是默认的
|
||||
if (matchSequenceFlow == null && gateway.getOutgoingFlows().size() == 1) {
|
||||
matchSequenceFlow = gateway.getOutgoingFlows().get(0);
|
||||
|
@ -742,7 +741,7 @@ public class BpmnModelUtils {
|
|||
&& evalConditionExpress(variables, flow.getConditionExpression()));
|
||||
if (CollUtil.isEmpty(matchSequenceFlows)) {
|
||||
matchSequenceFlows = CollUtil.filterNew(gateway.getOutgoingFlows(),
|
||||
flow -> ObjUtil.notEqual(gateway.getDefaultFlow(), flow.getId()));
|
||||
flow -> ObjUtil.equal(gateway.getDefaultFlow(), flow.getId()));
|
||||
// 特殊:没有默认的情况下,并且只有 1 个条件,则认为它是默认的
|
||||
if (CollUtil.isEmpty(matchSequenceFlows) && gateway.getOutgoingFlows().size() == 1) {
|
||||
matchSequenceFlows = gateway.getOutgoingFlows();
|
||||
|
|
|
@ -83,7 +83,7 @@ public class SimpleModelUtils {
|
|||
|
||||
private static BpmSimpleModelNodeVO buildStartNode() {
|
||||
return new BpmSimpleModelNodeVO().setId(START_EVENT_NODE_ID)
|
||||
.setName(BpmSimpleModelNodeType.START_USER_NODE.getName())
|
||||
.setName(BpmSimpleModelNodeType.START_NODE.getName())
|
||||
.setType(BpmSimpleModelNodeType.START_NODE.getType());
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ public class BpmModelServiceImpl implements BpmModelService {
|
|||
public List<Model> getModelList(String name) {
|
||||
ModelQuery modelQuery = repositoryService.createModelQuery();
|
||||
if (StrUtil.isNotEmpty(name)) {
|
||||
modelQuery.modelNameLike(name);
|
||||
modelQuery.modelNameLike("%" + name + "%");
|
||||
}
|
||||
return modelQuery.list();
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -12,6 +12,7 @@ import cn.iocoder.yudao.framework.common.util.object.PageUtils;
|
|||
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
||||
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.BpmFormDO;
|
||||
import cn.iocoder.yudao.module.bpm.enums.definition.*;
|
||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmCommentTypeEnum;
|
||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmReasonEnum;
|
||||
|
@ -20,6 +21,7 @@ import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
|
|||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants;
|
||||
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.service.definition.BpmFormService;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
|
||||
import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;
|
||||
|
@ -91,6 +93,8 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
private BpmModelService modelService;
|
||||
@Resource
|
||||
private BpmMessageService messageService;
|
||||
@Resource
|
||||
private BpmFormService formService;
|
||||
|
||||
@Resource
|
||||
private AdminUserApi adminUserApi;
|
||||
|
@ -109,6 +113,9 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
if (StrUtil.isNotBlank(pageVO.getName())) {
|
||||
taskQuery.taskNameLike("%" + pageVO.getName() + "%");
|
||||
}
|
||||
if (StrUtil.isNotEmpty(pageVO.getCategory())) {
|
||||
taskQuery.taskCategory(pageVO.getCategory());
|
||||
}
|
||||
if (ArrayUtil.isNotEmpty(pageVO.getCreateTime())) {
|
||||
taskQuery.taskCreatedAfter(DateUtils.of(pageVO.getCreateTime()[0]));
|
||||
taskQuery.taskCreatedBefore(DateUtils.of(pageVO.getCreateTime()[1]));
|
||||
|
@ -153,7 +160,13 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
BpmnModel bpmnModel = bpmProcessDefinitionService.getProcessDefinitionBpmnModel(todoTask.getProcessDefinitionId());
|
||||
Map<Integer, BpmTaskRespVO.OperationButtonSetting> buttonsSetting = BpmnModelUtils.parseButtonsSetting(
|
||||
bpmnModel, todoTask.getTaskDefinitionKey());
|
||||
return BpmTaskConvert.INSTANCE.buildTodoTask(todoTask, childrenTasks, buttonsSetting);
|
||||
|
||||
// 4. 任务表单
|
||||
BpmFormDO taskForm = null;
|
||||
if (StrUtil.isNotBlank(todoTask.getFormKey())){
|
||||
taskForm = formService.getForm(NumberUtils.parseLong(todoTask.getFormKey()));
|
||||
}
|
||||
return BpmTaskConvert.INSTANCE.buildTodoTask(todoTask, childrenTasks, buttonsSetting, taskForm);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -188,6 +201,9 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
if (StrUtil.isNotBlank(pageVO.getName())) {
|
||||
taskQuery.taskNameLike("%" + pageVO.getName() + "%");
|
||||
}
|
||||
if (StrUtil.isNotEmpty(pageVO.getCategory())) {
|
||||
taskQuery.taskCategory(pageVO.getCategory());
|
||||
}
|
||||
if (ArrayUtil.isNotEmpty(pageVO.getCreateTime())) {
|
||||
taskQuery.taskCreatedAfter(DateUtils.of(pageVO.getCreateTime()[0]));
|
||||
taskQuery.taskCreatedBefore(DateUtils.of(pageVO.getCreateTime()[1]));
|
||||
|
@ -441,7 +457,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
* 判断指定用户,是否是当前任务的加签人
|
||||
*
|
||||
* @param userId 用户 Id
|
||||
* @param task 任务
|
||||
* @param task 任务
|
||||
* @return 是否
|
||||
*/
|
||||
private boolean isAddSignUserTask(Long userId, Task task) {
|
||||
|
@ -669,7 +685,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
reqVO.getTargetTaskDefinitionKey(), task.getProcessDefinitionId());
|
||||
|
||||
// 2. 调用 Flowable 框架的退回逻辑
|
||||
returnTask(task, targetElement, reqVO);
|
||||
returnTask(userId, task, targetElement, reqVO);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -701,11 +717,12 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
/**
|
||||
* 执行退回逻辑
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param currentTask 当前退回的任务
|
||||
* @param targetElement 需要退回到的目标任务
|
||||
* @param reqVO 前端参数封装
|
||||
*/
|
||||
public void returnTask(Task currentTask, FlowElement targetElement, BpmTaskReturnReqVO reqVO) {
|
||||
public void returnTask(Long userId, Task currentTask, FlowElement targetElement, BpmTaskReturnReqVO reqVO) {
|
||||
// 1. 获得所有需要回撤的任务 taskDefinitionKey,用于稍后的 moveActivityIdsToSingleActivityId 回撤
|
||||
// 1.1 获取所有正常进行的任务节点 Key
|
||||
List<Task> taskList = taskService.createTaskQuery().processInstanceId(currentTask.getProcessInstanceId()).list();
|
||||
|
@ -721,22 +738,29 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
if (!returnTaskKeyList.contains(task.getTaskDefinitionKey())) {
|
||||
return;
|
||||
}
|
||||
// 2.1 添加评论
|
||||
taskService.addComment(task.getId(), currentTask.getProcessInstanceId(), BpmCommentTypeEnum.RETURN.getType(),
|
||||
BpmCommentTypeEnum.RETURN.formatComment(reqVO.getReason()));
|
||||
// 2.2 更新 task 状态 + 原因
|
||||
updateTaskStatusAndReason(task.getId(), BpmTaskStatusEnum.RETURN.getStatus(), reqVO.getReason());
|
||||
|
||||
// 判断是否分配给自己任务,因为会签任务,一个节点会有多个任务
|
||||
if (isAssignUserTask(userId, task)) { // 情况一:自己的任务,进行 RETURN 标记
|
||||
// 2.1.1 添加评论
|
||||
taskService.addComment(task.getId(), currentTask.getProcessInstanceId(), BpmCommentTypeEnum.RETURN.getType(),
|
||||
BpmCommentTypeEnum.RETURN.formatComment(reqVO.getReason()));
|
||||
// 2.1.2 更新 task 状态 + 原因
|
||||
updateTaskStatusAndReason(task.getId(), BpmTaskStatusEnum.RETURN.getStatus(), reqVO.getReason());
|
||||
} else { // 情况二:别人的任务,进行 CANCEL 标记
|
||||
processTaskCanceled(task.getId());
|
||||
}
|
||||
});
|
||||
|
||||
// 3. 设置流程变量节点驳回标记:用于驳回到节点,不执行 BpmUserTaskAssignStartUserHandlerTypeEnum 策略。导致自动通过
|
||||
runtimeService.setVariable(currentTask.getProcessInstanceId(),
|
||||
String.format(PROCESS_INSTANCE_VARIABLE_RETURN_FLAG, reqVO.getTargetTaskDefinitionKey()), Boolean.TRUE);
|
||||
|
||||
// 4. 执行驳回
|
||||
// 使用 moveExecutionsToSingleActivityId 替换 moveActivityIdsToSingleActivityId 原因:
|
||||
// 当多实例任务回退的时候有问题。相关 issue: https://github.com/flowable/flowable-engine/issues/3944
|
||||
List<String> runExecutionIds = convertList(taskList, Task::getExecutionId);
|
||||
runtimeService.createChangeActivityStateBuilder()
|
||||
.processInstanceId(currentTask.getProcessInstanceId())
|
||||
.moveActivityIdsToSingleActivityId(returnTaskKeyList, // 当前要跳转的节点列表( 1 或多)
|
||||
reqVO.getTargetTaskDefinitionKey()) // targetKey 跳转到的节点(1)
|
||||
.moveExecutionsToSingleActivityId(runExecutionIds, reqVO.getTargetTaskDefinitionKey())
|
||||
.changeState();
|
||||
}
|
||||
|
||||
|
@ -1021,14 +1045,22 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
Integer assignEmptyHandlerType = BpmnModelUtils.parseAssignEmptyHandlerType(userTaskElement);
|
||||
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
|
||||
|
||||
/**
|
||||
* 特殊情况:部分情况下,TransactionSynchronizationManager 注册 afterCommit 监听时,不会被调用,但是 afterCompletion 可以
|
||||
* 例如说:第一个 task 就是配置【自动通过】或者【自动拒绝】时
|
||||
* 参见 <a href="https://gitee.com/zhijiantianya/yudao-cloud/issues/IB7V7Q">issue</a> 反馈
|
||||
*/
|
||||
@Override
|
||||
public void afterCompletion(int transactionStatus) {
|
||||
// 特殊情况:部分情况下,TransactionSynchronizationManager 注册 afterCommit 监听时,不会被调用,但是 afterCompletion 可以
|
||||
// 例如说:第一个 task 就是配置【自动通过】或者【自动拒绝】时
|
||||
if (ObjectUtil.notEqual(transactionStatus, TransactionSynchronization.STATUS_COMMITTED)) {
|
||||
// 回滚情况,直接返回
|
||||
if (ObjectUtil.equal(transactionStatus, TransactionSynchronization.STATUS_ROLLED_BACK)) {
|
||||
return;
|
||||
}
|
||||
// 特殊情况:第一个 task 【自动通过】时,第二个任务设置审批人时 transactionStatus 会为 STATUS_UNKNOWN,不知道啥原因
|
||||
if (ObjectUtil.equal(transactionStatus, TransactionSynchronization.STATUS_UNKNOWN)
|
||||
&& getTask(task.getId()) == null) {
|
||||
return;
|
||||
}
|
||||
// TODO 芋艿:可以后续优化成 getSelf();
|
||||
// 特殊情况一:【人工审核】审批人为空,根据配置是否要自动通过、自动拒绝
|
||||
if (ObjectUtil.equal(approveType, BpmUserTaskApproveTypeEnum.USER.getType())) {
|
||||
// 如果有审批人、或者拥有人,则说明不满足情况一,不自动通过、不自动拒绝
|
||||
|
@ -1036,19 +1068,19 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
return;
|
||||
}
|
||||
if (ObjectUtil.equal(assignEmptyHandlerType, BpmUserTaskAssignEmptyHandlerTypeEnum.APPROVE.getType())) {
|
||||
SpringUtil.getBean(BpmTaskService.class).approveTask(null, new BpmTaskApproveReqVO()
|
||||
getSelf().approveTask(null, new BpmTaskApproveReqVO()
|
||||
.setId(task.getId()).setReason(BpmReasonEnum.ASSIGN_EMPTY_APPROVE.getReason()));
|
||||
} else if (ObjectUtil.equal(assignEmptyHandlerType, BpmUserTaskAssignEmptyHandlerTypeEnum.REJECT.getType())) {
|
||||
SpringUtil.getBean(BpmTaskService.class).rejectTask(null, new BpmTaskRejectReqVO()
|
||||
getSelf().rejectTask(null, new BpmTaskRejectReqVO()
|
||||
.setId(task.getId()).setReason(BpmReasonEnum.ASSIGN_EMPTY_REJECT.getReason()));
|
||||
}
|
||||
// 特殊情况二:【自动审核】审批类型为自动通过、不通过
|
||||
} else {
|
||||
if (ObjectUtil.equal(approveType, BpmUserTaskApproveTypeEnum.AUTO_APPROVE.getType())) {
|
||||
SpringUtil.getBean(BpmTaskService.class).approveTask(null, new BpmTaskApproveReqVO()
|
||||
getSelf().approveTask(null, new BpmTaskApproveReqVO()
|
||||
.setId(task.getId()).setReason(BpmReasonEnum.APPROVE_TYPE_AUTO_APPROVE.getReason()));
|
||||
} else if (ObjectUtil.equal(approveType, BpmUserTaskApproveTypeEnum.AUTO_REJECT.getType())) {
|
||||
SpringUtil.getBean(BpmTaskService.class).rejectTask(null, new BpmTaskRejectReqVO()
|
||||
getSelf().rejectTask(null, new BpmTaskRejectReqVO()
|
||||
.setId(task.getId()).setReason(BpmReasonEnum.APPROVE_TYPE_AUTO_REJECT.getReason()));
|
||||
}
|
||||
}
|
||||
|
@ -1087,8 +1119,22 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
// 发送通知。在事务提交时,批量执行操作,所以直接查询会无法查询到 ProcessInstance,所以这里是通过监听事务的提交来实现。
|
||||
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
|
||||
|
||||
/**
|
||||
* 特殊情况:部分情况下,TransactionSynchronizationManager 注册 afterCommit 监听时,不会被调用,但是 afterCompletion 可以
|
||||
* 例如说:第一个 task 就是配置【自动通过】或者【自动拒绝】时
|
||||
* 参见 <a href="https://gitee.com/zhijiantianya/yudao-cloud/issues/IB7V7Q">issue</a> 反馈
|
||||
*/
|
||||
@Override
|
||||
public void afterCommit() {
|
||||
public void afterCompletion(int transactionStatus) {
|
||||
// 回滚情况,直接返回
|
||||
if (ObjectUtil.equal(transactionStatus, TransactionSynchronization.STATUS_ROLLED_BACK)) {
|
||||
return;
|
||||
}
|
||||
// 特殊情况:第一个 task 【自动通过】时,第二个任务设置审批人时 transactionStatus 会为 STATUS_UNKNOWN,不知道啥原因
|
||||
if (ObjectUtil.equal(transactionStatus, TransactionSynchronization.STATUS_UNKNOWN)
|
||||
&& getTask(task.getId()) == null) {
|
||||
return;
|
||||
}
|
||||
if (StrUtil.isEmpty(task.getAssignee())) {
|
||||
log.error("[processTaskAssigned][taskId({}) 没有分配到负责人]", task.getId());
|
||||
return;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
@ -11,6 +12,7 @@ import java.util.List;
|
|||
|
||||
@Schema(description = "管理后台 - ERP 付款单 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class ErpFinancePaymentRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23752")
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
@ -11,6 +12,7 @@ import java.util.List;
|
|||
|
||||
@Schema(description = "管理后台 - ERP 收款单 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class ErpFinanceReceiptRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23752")
|
||||
|
|
Loading…
Reference in New Issue