Browse Source

流程处理-退回处理

master
CMM 1 year ago
parent
commit
3a4f63252b
9 changed files with 122 additions and 60 deletions
  1. +0
    -1
      pmapi/src/main/java/com/ningdatech/pmapi/common/constant/CommonConstant.java
  2. +2
    -1
      pmapi/src/main/java/com/ningdatech/pmapi/common/constant/StateMachineConstants.java
  3. +2
    -2
      pmapi/src/main/java/com/ningdatech/pmapi/common/statemachine/action/ProjectDeclareAction.java
  4. +2
    -2
      pmapi/src/main/java/com/ningdatech/pmapi/common/statemachine/action/ProjectDeclareChoiceAction.java
  5. +2
    -2
      pmapi/src/main/java/com/ningdatech/pmapi/common/statemachine/factory/ProjectDeclareGuardFactory.java
  6. +5
    -5
      pmapi/src/main/java/com/ningdatech/pmapi/common/statemachine/util/StateMachineUtils.java
  7. +1
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/constant/WorkNotice.java
  8. +21
    -20
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/extension/cmd/BackToHisApprovalNodeCmd.java
  9. +87
    -27
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/manage/TodoCenterManage.java

+ 0
- 1
pmapi/src/main/java/com/ningdatech/pmapi/common/constant/CommonConstant.java View File

@@ -10,7 +10,6 @@ public class CommonConstant {
public static final String COOKIE_KEY = "ND_JSESSION";

public static final Integer EXPORT_PAGE_NUMBER = 1;

public static final Integer EXPORT_PAGE_SIZE = 100000;
public static final String CALL_STATUS = "status";
public static final String CALL_STATUS_OK_VALUE = "ok";


pmapi/src/main/java/com/ningdatech/pmapi/common/constant/StateMachineHeaderNameConstants.java → pmapi/src/main/java/com/ningdatech/pmapi/common/constant/StateMachineConstants.java View File

@@ -5,8 +5,9 @@ package com.ningdatech.pmapi.common.constant;
* @since 2023/02/07 16:24
*/

public class StateMachineHeaderNameConstants {
public class StateMachineConstants {

public static final String PROJECT_DECLARE = "projectDeclare";
public static final String LI_SHUI_CITY_AREA_CODE = "331100";

}

+ 2
- 2
pmapi/src/main/java/com/ningdatech/pmapi/common/statemachine/action/ProjectDeclareAction.java View File

@@ -1,6 +1,6 @@
package com.ningdatech.pmapi.common.statemachine.action;

import com.ningdatech.pmapi.common.constant.StateMachineHeaderNameConstants;
import com.ningdatech.pmapi.common.constant.StateMachineConstants;
import com.ningdatech.pmapi.common.statemachine.builder.ProjectDeclareStateMachineBuilder;
import com.ningdatech.pmapi.common.statemachine.util.StateMachineUtils;
import com.ningdatech.pmapi.common.statemachine.event.ProjectStatusChangeEvent;
@@ -23,7 +23,7 @@ import org.springframework.statemachine.annotation.WithStateMachine;
@WithStateMachine(id = ProjectDeclareStateMachineBuilder.MACHINEID_TO)
public class ProjectDeclareAction {

private static final String PROJECT_DECLARE = StateMachineHeaderNameConstants.PROJECT_DECLARE;
private static final String PROJECT_DECLARE = StateMachineConstants.PROJECT_DECLARE;

@OnTransition(source = "UNDER_INTERNAL_AUDIT", target = "PENDING_PREQUALIFICATION")
public void UNDER_INTERNAL_PASS(Message<ProjectStatusChangeEvent> message) {


+ 2
- 2
pmapi/src/main/java/com/ningdatech/pmapi/common/statemachine/action/ProjectDeclareChoiceAction.java View File

@@ -1,6 +1,6 @@
package com.ningdatech.pmapi.common.statemachine.action;

import com.ningdatech.pmapi.common.constant.StateMachineHeaderNameConstants;
import com.ningdatech.pmapi.common.constant.StateMachineConstants;
import com.ningdatech.pmapi.common.statemachine.util.StateMachineUtils;
import com.ningdatech.pmapi.common.statemachine.event.ProjectStatusChangeEvent;
import com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum;
@@ -18,7 +18,7 @@ import org.springframework.statemachine.action.Action;
@Slf4j
public class ProjectDeclareChoiceAction implements Action<ProjectStatusEnum, ProjectStatusChangeEvent> {

private static final String PROJECT_DECLARE = StateMachineHeaderNameConstants.PROJECT_DECLARE;
private static final String PROJECT_DECLARE = StateMachineConstants.PROJECT_DECLARE;

@Override
public void execute(StateContext<ProjectStatusEnum, ProjectStatusChangeEvent> stateContext) {


+ 2
- 2
pmapi/src/main/java/com/ningdatech/pmapi/common/statemachine/factory/ProjectDeclareGuardFactory.java View File

@@ -1,6 +1,6 @@
package com.ningdatech.pmapi.common.statemachine.factory;

import com.ningdatech.pmapi.common.constant.StateMachineHeaderNameConstants;
import com.ningdatech.pmapi.common.constant.StateMachineConstants;
import com.ningdatech.pmapi.common.statemachine.util.StateMachineUtils;
import com.ningdatech.pmapi.common.statemachine.event.ProjectStatusChangeEvent;
import com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum;
@@ -16,7 +16,7 @@ import org.springframework.statemachine.guard.Guard;
*/

public class ProjectDeclareGuardFactory {
private static final String PROJECT_DECLARE = StateMachineHeaderNameConstants.PROJECT_DECLARE;
private static final String PROJECT_DECLARE = StateMachineConstants.PROJECT_DECLARE;

public class PendingPreQualificationChoiceGuard implements Guard<ProjectStatusEnum, ProjectStatusChangeEvent> {
@Override


+ 5
- 5
pmapi/src/main/java/com/ningdatech/pmapi/common/statemachine/util/StateMachineUtils.java View File

@@ -2,7 +2,7 @@ package com.ningdatech.pmapi.common.statemachine.util;

import com.ningdatech.basic.exception.BizException;
import com.ningdatech.pmapi.common.constant.ProjectDeclareConstants;
import com.ningdatech.pmapi.common.constant.StateMachineHeaderNameConstants;
import com.ningdatech.pmapi.common.constant.StateMachineConstants;
import com.ningdatech.pmapi.common.statemachine.builder.ProjectDeclareStateMachineBuilder;
import com.ningdatech.pmapi.common.statemachine.event.ProjectStatusChangeEvent;
import com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum;
@@ -29,7 +29,7 @@ import java.util.Objects;
@RequiredArgsConstructor
public class StateMachineUtils {

private static final String PROJECT_DECLARE = StateMachineHeaderNameConstants.PROJECT_DECLARE;
private static final String PROJECT_DECLARE = StateMachineConstants.PROJECT_DECLARE;

private final ProjectDeclareStateMachineBuilder projectDeclareStateMachineBuilder;

@@ -64,7 +64,7 @@ public class StateMachineUtils {
}

/**
* 判断项目建设层级是否为市级项目
* 判断申报项目是否为市级项目
*
* @param project
* @return boolean
@@ -72,8 +72,8 @@ public class StateMachineUtils {
* @since 2023/02/07 17:05
*/
public static boolean isCityProject(Project project) {
if (ProjectDeclareConstants.Number.CITY_BUILD_LEVEL.equals(project.getBuildLevel()) ||
ProjectDeclareConstants.Number.CITY_SELF_BUILD_LEVEL.equals(project.getBuildLevel())) {
String areaCode = project.getAreaCode();
if (areaCode.equals(StateMachineConstants.LI_SHUI_CITY_AREA_CODE)) {
return true;
}
return false;


+ 1
- 0
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/constant/WorkNotice.java View File

@@ -7,6 +7,7 @@ package com.ningdatech.pmapi.todocenter.constant;
public interface WorkNotice {
public final String PASS_MSG_TEMPLATE = "标题:审核任务 内容:【%s】的【%s】需要您审核。";
public final String PASS_MSG_TEMPLATE2 = "【%s】已通过【%s】,请及时开始下一步操作。";
public final String PASS_MSG_TEMPLATE3 = "【%s】的【%s】被退回,请及时处理。";


}

+ 21
- 20
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/extension/cmd/BackToHisApprovalNodeCmd.java View File

@@ -4,9 +4,17 @@ import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum;
import com.ningdatech.pmapi.projectlib.model.entity.Project;
import com.ningdatech.pmapi.projectlib.service.IProjectService;
import com.ningdatech.pmapi.todocenter.enumeration.ProcessStatusEnum;
import com.wflow.workflow.enums.ProcessHandlerEnum;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.assertj.core.util.Sets;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowNode;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.UserTask;
@@ -14,6 +22,7 @@ import org.flowable.common.engine.api.FlowableException;
import org.flowable.common.engine.api.FlowableObjectNotFoundException;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.impl.delegate.ActivityBehavior;
@@ -32,21 +41,15 @@ import com.wflow.workflow.utils.FlowableUtils;
* @date : 2022/10/14
*/
@RequiredArgsConstructor
@AllArgsConstructor
public class BackToHisApprovalNodeCmd implements Command<String>, Serializable {

private static final long serialVersionUID = -80075781855060928L;
protected TaskService taskService;

protected RuntimeService runtimeService;
protected BpmnModel bpmnModel;
protected String taskId;
protected String targetNodeId;

public BackToHisApprovalNodeCmd(RuntimeService runtimeService, String taskId, String targetNodeId) {
this.runtimeService = runtimeService;
this.taskId = taskId;
this.targetNodeId = targetNodeId;
}

@Override
public String execute(CommandContext commandContext) {

@@ -60,28 +63,30 @@ public class BackToHisApprovalNodeCmd implements Command<String>, Serializable {
String sourceNodeId = task.getTaskDefinitionKey();
String processInstanceId = task.getProcessInstanceId();
String processDefinitionId = task.getProcessDefinitionId();

//获取流程定义
Process process = ProcessDefinitionUtil.getProcess(processDefinitionId);
FlowNode sourceFlowElement = (FlowNode) process.getFlowElement(sourceNodeId, true);

// 传节点定义key 获取当前节点
FlowNode sourceFlowElement = (FlowNode) bpmnModel.getFlowElement(sourceNodeId);

// 只支持从用户任务退回
if (!(sourceFlowElement instanceof UserTask)) {
throw new FlowableException("只能从审批节点进行回退");
}
FlowNode targetFlowElement = (FlowNode) process.getFlowElement(targetNodeId, true);
FlowNode targetFlowElement = (FlowNode) bpmnModel.getFlowElement(targetNodeId);
// 退回节点到当前节点不可达到,不允许退回
if (!ExecutionGraphUtil.isReachable(processDefinitionId, targetNodeId, sourceNodeId)) {
throw new FlowableException("无法回退到目标节点");
}
//目标节点如果相对当前节点是在子流程内部,则无法直接退回,目前处理是只能退回到子流程开始节点

// 目标节点如果相对当前节点是在子流程内部,则无法直接退回,目前处理是只能退回到子流程开始节点
String[] sourceAndTargetRealActivityId = FlowableUtils.getSourceAndTargetRealActivityId(sourceFlowElement, targetFlowElement);
// 实际应操作的当前节点ID
String sourceRealActivityId = sourceAndTargetRealActivityId[0];

//// 实际应操作的目标节点ID
//String targetRealActivityId = sourceAndTargetRealActivityId[1];

// 实际应操作的目标节点的发起人ID
String targetRealActivityId = sourceAndTargetRealActivityId[0];
// 实际应操作的目标节点ID
String targetRealActivityId = sourceAndTargetRealActivityId[1];

Map<String, Set<String>> specialGatewayNodes = FlowableUtils.getSpecialGatewayElements(process);
// 当前节点处在的并行网关list
@@ -146,10 +151,6 @@ public class BackToHisApprovalNodeCmd implements Command<String>, Serializable {
if (targetRealSpecialGateway != null) {
createTargetInSpecialGatewayEndExecutions(commandContext, realExecutions, process, targetInSpecialGatewayList, targetRealSpecialGateway);
}
// TODO 调用原生的execute方法 在流程实例表中END_ACT_ID添加对应的字段标识
Map<String, Object> var = new HashMap<>(16);
var.put("approve_" + task.getId(), ProcessHandlerEnum.BACK);
taskService.complete(task.getId(), var);
return targetRealActivityId;
}



+ 87
- 27
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/manage/TodoCenterManage.java View File

@@ -100,8 +100,7 @@ import java.util.stream.Collectors;

import static cn.hutool.core.collection.CollUtil.isEmpty;
import static cn.hutool.core.collection.CollUtil.isNotEmpty;
import static com.ningdatech.pmapi.todocenter.constant.WorkNotice.PASS_MSG_TEMPLATE;
import static com.ningdatech.pmapi.todocenter.constant.WorkNotice.PASS_MSG_TEMPLATE2;
import static com.ningdatech.pmapi.todocenter.constant.WorkNotice.*;

/**
* @author CMM
@@ -319,8 +318,8 @@ public class TodoCenterManage {
// Long userId = LoginUserUtil.getUserId();

// Long userId = 381496L;
Long userId = 6418616L;
// Long userId = 6418616L;
Long userId = 61769799L;

// 若进行的是撤回操作(流程发起人和当前流程审核人的前一个审核人操作)
if (param.getAction().equals(ProcessHandlerEnum.WITHDRAW)){
@@ -392,7 +391,7 @@ public class TodoCenterManage {
// TODO 中止流程并使项目进入对应状态,给项目创建人、流程发起人发送浙政钉工作通知:【项目名称】的【流程名称】被驳回,请及时处理。
// sendWorkNoticeToStartUser(task, projectName, rootNode);

// 更新项目状态
// 更新项目状态和流程状态
updateRejectProjectStatus(userId,declaredProject);
taskService.complete(param.getTaskId(), var);
}
@@ -417,7 +416,10 @@ public class TodoCenterManage {
} catch (Exception e) {
throw new BizException("状态机执行失败!");
}
// 更新项目状态到下一个状态
// 更新流程状态、项目状态到下一个状态
declaredProject.setProcessStatus(ProcessStatusEnum.BE_REJECTED.getCode());
declaredProject.setUpdateOn(LocalDateTime.now());
declaredProject.setUpdateBy(userId);
projectService.updateById(declaredProject);
}

@@ -483,23 +485,39 @@ public class TodoCenterManage {
managementService.executeCommand(new SaveCommentCmd(param.getTaskId(), param.getInstanceId(),
String.valueOf(userId), JSONObject.toJSONString(param.getAuditInfo())));
}
// 如果流程状态是被退回状态,流程通过后,当前审核人一定不是最后一个审核人(至多是最后一个),更新流程状态为审核中
if (ProcessStatusEnum.BE_BACKED.getCode().equals(declaredProject.getProcessStatus())){
// 通过该任务,流程到下一审核人处
taskService.complete(param.getTaskId(), var);
// 更新流程状态为审核中
declaredProject.setProcessStatus(ProcessStatusEnum.UNDER_REVIEW.getCode());
declaredProject.setUpdateOn(LocalDateTime.now());
declaredProject.setUpdateBy(userId);
projectService.updateById(declaredProject);
// 获取此时待审核任务
Task currentTask = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
// 获取审核人信息,向审核人发送工作通知
String currentUserId = currentTask.getAssignee();
// UserInfo auditUserInfo = userInfoService.getById(Long.valueOf(currentUserId));
// TODO 获取浙政钉用户dingKey,向其发送浙政钉工作通知
String msg = String.format(PASS_MSG_TEMPLATE, null, projectName);
// sendWorkNotice(auditUserInfo,msg);
return;
}
// 获取bpm对象
BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
// 传节点定义key 获取当前节点
// 若不是被退回项目,传节点定义key 获取当前节点
FlowNode currentNode = (FlowNode) bpmnModel.getFlowElement(task.getTaskDefinitionKey());


// TODO 若当前流程是预审流程,需要在提交预审申报的时候,调用状态机判断申报后的项目状态,
// 若是省级部门联审中,要对接外部接口,获取省级部门联审的结果,更新项目状态(预审申报提交的时候处理)

// 需要先通过后才能有下一个节点的信息
taskService.complete(param.getTaskId(), var);

// 获取流程下一个节点的审核用户ID
String nextUserId = getNextUserId(currentNode, processInstanceId);
// 获取当前流程状态
// 获取当前项目状态
Integer status = declaredProject.getStatus();
// 若当前登录用户是最后一个审批人
// 若当前登录用户是最后一个审批人,需更新流程状态为审核完成,项目状态到下个状态
HistoricProcessInstance instance = historyService
.createHistoricProcessInstanceQuery()
.processInstanceId(processInstanceId)
@@ -533,7 +551,7 @@ public class TodoCenterManage {
// TODO 向其发送浙政钉工作通知 获取根节点的孩子节点(即发起人节点),向其发送浙政钉工作通知
// 获取根节点即流程发起节点
// FlowNode rootNode = (FlowNode) bpmnModel.getFlowElement("root");
// sendWorkNoticeToStartUser(task, projectName, rootNode);
// sendPassWorkNoticeToStartUser(task, projectName, rootNode);
}
}

@@ -557,7 +575,10 @@ public class TodoCenterManage {
} catch (Exception e) {
throw new BizException("状态机执行失败!");
}
// 更新项目状态到下一个状态
// 更新流程状态、项目状态到下一个状态
declaredProject.setProcessStatus(ProcessStatusEnum.APPROVED.getCode());
declaredProject.setUpdateOn(LocalDateTime.now());
declaredProject.setUpdateBy(userId);
projectService.updateById(declaredProject);
}

@@ -571,7 +592,7 @@ public class TodoCenterManage {
* @author CMM
* @since 2023/02/03
*/
private void sendWorkNoticeToStartUser(Task task, String projectName, FlowNode rootNode) {
private void sendPassWorkNoticeToStartUser(Task task, String projectName, FlowNode rootNode) {
String startUserId = getRootUserId(rootNode, task.getProcessInstanceId());
UserInfo startUserInfo = userInfoService.getById(Long.valueOf(startUserId));
// 从历史表获取最新版本的流程
@@ -618,7 +639,7 @@ public class TodoCenterManage {
*
* @param currentNode 当前节点
* @param processInstanceId
* @return java.lang.String 下一个节点的浙政钉用户ID
* @return java.lang.String 下一个节点的审核用户ID
* @author CMM
* @since 2023/02/02
*/
@@ -732,7 +753,7 @@ public class TodoCenterManage {
// 判断当前登录用户是否是流程发起人
if (startUserId.equals(String.valueOf(userId))) {
// TODO 若是流程发起人点击撤回,项目回到上一个状态,并删除当前审核人对应的待办记录
// 若是流程发起人点击撤回,项目回到上一个状态,需调用状态机更新项目状态
// 若是流程发起人点击撤回,项目回到上一个状态,需调用状态机更新项目状态,流程状态更新为审核通过
switch (Objects.requireNonNull(ProjectStatusEnum.getValue(status))) {
// 当前项目状态是单位内部审核中
case UNDER_INTERNAL_AUDIT:
@@ -778,7 +799,7 @@ public class TodoCenterManage {
// TODO 判断前一个审核人的部门和当前登录用户的部门是否是同一个,如果是同一个才可以撤回,否则抛出异常
Boolean orgFlag = true;
if (orgFlag){
// 注意:是前一个审核人,说明此时仍在一个审核流程中,项目状态不需要改变
// 注意:是前一个审核人,说明此时仍在一个审核流程中,项目状态不需要改变,流程状态也不要改变,仍为审核中
// 在审核记录中移除前一个审核人提交过的审核意见
Comment comment = taskService.getProcessInstanceComments(processInstanceId).stream()
.filter(c -> c.getTaskId().equals(handledTaskInstance.getId()))
@@ -827,6 +848,9 @@ public class TodoCenterManage {
throw new BizException("状态机执行失败!");
}
// 更新项目状态
declaredProject.setProcessStatus(ProcessStatusEnum.APPROVED.getCode());
declaredProject.setUpdateOn(LocalDateTime.now());
declaredProject.setUpdateBy(userId);
projectService.updateById(declaredProject);
}

@@ -842,19 +866,55 @@ public class TodoCenterManage {
Project declaredProject = projectService
.getOne(Wrappers.lambdaQuery(Project.class).eq(Project::getInstCode, task.getProcessInstanceId()));
String projectName = declaredProject.getProjectName();
// 获取流程定义
Process process = ProcessDefinitionUtil.getProcess(task.getProcessDefinitionId());
// 获取根节点即流程发起节点
FlowNode rootNode = (FlowNode) process.getFlowElement("root", true);
// TODO 流程变成【被退回】状态,待我处理中,为流程发起人增加一条待办记录,给项目创建人、流程发起人发送浙政钉工作通知:【项目名称】的【流程名称】被退回,请及时处理。
sendWorkNoticeToStartUser(task, projectName, rootNode);

// 保存审核意见
if (hasComment(param.getAuditInfo())) {
// 执行自定义的保存评论的功能
managementService.executeCommand(new SaveCommentCmd(param.getTaskId(), param.getInstanceId(),
String.valueOf(userId), JSONObject.toJSONString(param.getAuditInfo())));
}

// 获取bpm对象
BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
// 传节点定义key 获取根节点即流程发起节点
FlowNode rootNode = (FlowNode) bpmnModel.getFlowElement("root");

// TODO 流程变成【被退回】状态,待我处理中,为流程发起人增加一条待办记录,
// 执行自定义回退逻辑,回退到流程发起人
managementService
.executeCommand(new BackToHisApprovalNodeCmd(runtimeService, param.getTaskId(), rootNode.getId()));
// 注意:因为审核人有执行退回的权限,且是退回到流程发起人,说明是在同一个流程实例中,所以项目状态不需要更新
managementService.executeCommand(new BackToHisApprovalNodeCmd(runtimeService,bpmnModel,param.getTaskId(), rootNode.getId()));
runtimeService.setVariables(param.getInstanceId(),
Maps.newHashMap("approve_" + param.getTaskId(), param.getAction()));
log.info("用户[{}] 退回流程[{}] [{} -> {}]", userId, param.getInstanceId(), task.getTaskDefinitionKey(),
log.info("用户[{}] 退回流程[{}] [{} -> {}]", userId, param.getInstanceId(),
task.getTaskDefinitionKey(),
param.getTargetNode());
// 更新申报项目表中的流程状态为被退回
declaredProject.setProcessStatus(ProcessStatusEnum.BE_BACKED.getCode());
declaredProject.setUpdateOn(LocalDateTime.now());
declaredProject.setUpdateBy(userId);
projectService.updateById(declaredProject);
// TODO 给项目创建人、流程发起人发送浙政钉工作通知:【项目名称】的【流程名称】被退回,请及时处理。
// sendBackWorkNoticeToStartUser(task, projectName, rootNode);

}

/**
* 给流程发起人发送流程退回工作通知
* @param task
* @param projectName
* @param rootNode
* @return void
* @author CMM
* @since 2023/02/14 15:32
*/
private void sendBackWorkNoticeToStartUser(Task task, String projectName, FlowNode rootNode) {
String startUserId = getRootUserId(rootNode, task.getProcessInstanceId());
UserInfo startUserInfo = userInfoService.getById(Long.valueOf(startUserId));
// 从历史表获取最新版本的流程
WflowModels wflowModels = getLastWflowModels(task);
String formName = wflowModels.getFormName();
String msg = String.format(PASS_MSG_TEMPLATE3, projectName, formName);
sendWorkNotice(startUserInfo, msg);
}

/**


Loading…
Cancel
Save