Browse Source

待办中心待我处理处理功能

master
CMM 1 year ago
parent
commit
d98ade3012
15 changed files with 629 additions and 113 deletions
  1. +15
    -0
      pmapi/pom.xml
  2. BIN
      pmapi/src/lib/zwdd-sdk-java-1.2.0.jar
  3. +12
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/common/constant/DingConstant.java
  4. +26
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/bean/entity/Attachment.java
  5. +35
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/bean/entity/ProcessComment.java
  6. +8
    -4
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/bean/entity/ProgressNode.java
  7. +2
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/bean/vo/ProcessProgressDetailVo.java
  8. +32
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/bean/vo/ProgressNodeAuditInfoVo.java
  9. +12
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/constant/WorkNotice.java
  10. +97
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/enums/ProcessHandlerEnum.java
  11. +16
    -6
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/extension/cmd/BackToHisApprovalNodeCmd.java
  12. +300
    -66
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/manage/TodoCenterManage.java
  13. +44
    -37
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/model/dto/req/ReqProcessHandlerDTO.java
  14. +13
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/zwdd/model/MessageContent.java
  15. +17
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/zwdd/model/MessageText.java

+ 15
- 0
pmapi/pom.xml View File

@@ -258,6 +258,21 @@
<artifactId>nd-file-starter</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.ningdatech</groupId>
<artifactId>nd-zwdd-starter</artifactId>
<version>1.0.0</version>
</dependency>

<!--浙政钉-->
<dependency>
<groupId>com.alibaba.xxpt</groupId>
<artifactId>zwdd</artifactId>
<version>1.2.0</version>
<scope>system</scope>
<systemPath>${basedir}/src/lib/zwdd-sdk-java-1.2.0.jar</systemPath>
</dependency>

</dependencies>
<!-- 打包 -->
<!--配置环境的profile-->


BIN
pmapi/src/lib/zwdd-sdk-java-1.2.0.jar View File


+ 12
- 0
pmapi/src/main/java/com/ningdatech/pmapi/common/constant/DingConstant.java View File

@@ -0,0 +1,12 @@
package com.ningdatech.pmapi.common.constant;
/**
* 浙政钉常量
* @author CMM
* @since 2023/02/01 14:49
*/
public interface DingConstant {
/**
* 工作通知
*/
String WORKING_NOTICE = "/message/workNotification";
}

+ 26
- 0
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/bean/entity/Attachment.java View File

@@ -0,0 +1,26 @@
package com.ningdatech.pmapi.todocenter.bean.entity;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
* 审核附件实体
*
* @author CMM
* @since 2023/02/01 16:27
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Attachment {
private String id;
//文件名
private String name;
//文件类型
private Boolean isImage;
//访问地址
private String url;
}

+ 35
- 0
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/bean/entity/ProcessComment.java View File

@@ -0,0 +1,35 @@
package com.ningdatech.pmapi.todocenter.bean.entity;

import com.wflow.workflow.bean.vo.ProcessHandlerParamsVo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Collections;
import java.util.List;

/**
* 审核意见实体
*
* @author CMM
* @since 2023/02/01 16:25
*/
@Data
@Builder
@NoArgsConstructor
public class ProcessComment {
/**
* 文字评论
*/
protected String text;
/**
* 评论附件
*/
protected List<Attachment> attachments;

public ProcessComment(String text, List<Attachment> attachments) {
this.text = text;
this.attachments = null == attachments ? Collections.emptyList() : attachments;
}
}

+ 8
- 4
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/bean/entity/ProgressNode.java View File

@@ -1,11 +1,11 @@
package com.ningdatech.pmapi.todocenter.bean.entity;

import com.ningdatech.pmapi.todocenter.bean.vo.ProgressNodeAuditInfoVo;
import com.ningdatech.pmapi.todocenter.enums.ProcessHandlerEnum;
import com.ningdatech.pmapi.todocenter.model.dto.req.ReqProcessHandlerDTO;
import com.wflow.workflow.bean.process.OrgUser;
import com.wflow.workflow.bean.process.enums.ApprovalModeEnum;
import com.wflow.workflow.bean.process.enums.NodeTypeEnum;
import com.wflow.workflow.bean.vo.ProcessHandlerParamsVo;
import com.wflow.workflow.bean.vo.TaskCommentVo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -52,11 +52,15 @@ public class ProgressNode {
/**
* 该节点动作操作类型
*/
private ReqProcessHandlerDTO.Action action;
private ProcessHandlerEnum action;
/**
* 审核信息
*/
private List<ProgressNodeAuditInfoVo> auditInfos;
/**
* 处理结果
*/
private ReqProcessHandlerDTO.Action result;
private ProcessHandlerEnum result;
/**
* 开始时间
*/


+ 2
- 0
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/bean/vo/ProcessProgressDetailVo.java View File

@@ -1,5 +1,6 @@
package com.ningdatech.pmapi.todocenter.bean.vo;

import com.ningdatech.pmapi.common.model.FileBasicInfo;
import com.ningdatech.pmapi.todocenter.bean.entity.ProgressNode;
import com.wflow.workflow.bean.process.OrgUser;
import com.wflow.workflow.bean.process.form.Form;
@@ -8,6 +9,7 @@ import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Map;


+ 32
- 0
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/bean/vo/ProgressNodeAuditInfoVo.java View File

@@ -0,0 +1,32 @@
package com.ningdatech.pmapi.todocenter.bean.vo;

import com.ningdatech.pmapi.todocenter.bean.entity.ProcessComment;
import com.wflow.workflow.bean.process.OrgUser;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

/**
* 流程节点审核信息
*
* @author CMM
* @since 2023/02/01 16:52
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ProgressNodeAuditInfoVo extends ProcessComment {
private String id;

private String type;

private String taskId;

private String commentType;

private OrgUser user;

private Date createTime;
}

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

@@ -0,0 +1,12 @@
package com.ningdatech.pmapi.todocenter.constant;
/**
* 工作通知格式常量
* @author CMM
* @since 2023/02/01 14:56
*/
public interface WorkNotice {
public final String PASS_MSG_TEMPLATE = "标题:审核任务 内容:【%s】的【%s】需要您审核。";
public final String PASS_MSG_TEMPLATE2 = "【%s】已通过【%s】,请及时开始下一步操作。";


}

+ 97
- 0
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/enums/ProcessHandlerEnum.java View File

@@ -0,0 +1,97 @@
package com.ningdatech.pmapi.todocenter.enums;

import io.swagger.annotations.ApiModel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;

import java.util.Objects;

/**
* 流程处理类型
* @author CMM
* @since 2023/02/01 16:58
*/
@Getter
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(value = "ProcessHandlerEnum", description = "流程处理类型-枚举")
public enum ProcessHandlerEnum {
/**
* 通过
*/

PASS(1, "通过"),

/**
* 盖章并通过
*/
SEAL_PASS(2, "盖章并通过"),

/**
* 退回
*/
BACK(3,"退回"),

/**
* 撤回
*/
WITHDRAW(4,"撤回"),
/**
* 驳回
*/
REJECT(5,"驳回");


private Integer code;
private String desc;

public String getDesc() {
return desc;
}

public void setDesc(String desc) {
this.desc = desc;
}

public static String getDescByCode(Integer code) {
if(Objects.isNull(code)){
return StringUtils.EMPTY;
}
for (ProcessHandlerEnum t : ProcessHandlerEnum.values()) {
if (code.equals(t.getCode())) {
return t.desc;
}
}
return StringUtils.EMPTY;
}

public static Integer getCodeByDesc(String desc) {
if(Objects.isNull(desc)){
return null;
}
for (ProcessHandlerEnum t : ProcessHandlerEnum.values()) {
if (desc.equals(t.getCode())) {
return t.code;
}
}
return null;
}

public static ProcessHandlerEnum getEnumByValue(Integer code) {
if(Objects.isNull(code)){
return null;
}
for (ProcessHandlerEnum t : ProcessHandlerEnum.values()) {
if (code.equals(t.getCode())) {
return t;
}
}
return null;
}

public boolean eq(String val) {
return this.name().equals(val);
}
}

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

@@ -1,12 +1,11 @@
package com.ningdatech.pmapi.todocenter.extension.cmd;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
import java.util.stream.Collectors;

import com.ningdatech.pmapi.todocenter.enums.ProcessHandlerEnum;
import lombok.RequiredArgsConstructor;
import org.assertj.core.util.Sets;
import org.flowable.bpmn.model.FlowNode;
import org.flowable.bpmn.model.Process;
@@ -16,6 +15,7 @@ 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.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.impl.delegate.ActivityBehavior;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager;
@@ -31,9 +31,11 @@ import com.wflow.workflow.utils.FlowableUtils;
* @author : willian fu
* @date : 2022/10/14
*/
@RequiredArgsConstructor
public class BackToHisApprovalNodeCmd implements Command<String>, Serializable {

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

protected RuntimeService runtimeService;
protected String taskId;
@@ -74,8 +76,12 @@ public class BackToHisApprovalNodeCmd implements Command<String>, Serializable {
String[] sourceAndTargetRealActivityId = FlowableUtils.getSourceAndTargetRealActivityId(sourceFlowElement, targetFlowElement);
// 实际应操作的当前节点ID
String sourceRealActivityId = sourceAndTargetRealActivityId[0];
// 实际应操作的目标节点ID
String targetRealActivityId = sourceAndTargetRealActivityId[1];

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

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

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



+ 300
- 66
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/manage/TodoCenterManage.java View File

@@ -2,25 +2,42 @@ package com.ningdatech.pmapi.todocenter.manage;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.xxpt.gateway.shared.api.request.OapiMessageWorkNotificationRequest;
import com.alibaba.xxpt.gateway.shared.api.response.OapiMessageWorkNotificationResponse;
import com.alibaba.xxpt.gateway.shared.client.http.ExecutableClient;
import com.alibaba.xxpt.gateway.shared.client.http.IntelligentGetClient;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ningdatech.basic.enumeration.Status;
import com.ningdatech.basic.exception.BizException;
import com.ningdatech.basic.util.NdDateUtils;
import com.ningdatech.pmapi.common.constant.DingConstant;
import com.ningdatech.pmapi.common.constant.ProjectDeclareConstants;
import com.ningdatech.pmapi.common.util.ExcelDownUtil;
import com.ningdatech.pmapi.common.util.ExcelExportStyle;
import com.ningdatech.pmapi.todocenter.bean.entity.ProcessComment;
import com.ningdatech.pmapi.todocenter.bean.entity.ProgressNode;
import com.ningdatech.pmapi.todocenter.bean.vo.ProcessProgressDetailVo;
import com.ningdatech.pmapi.todocenter.constant.HisProInsEndActId;
import com.ningdatech.pmapi.todocenter.enums.ProcessHandlerEnum;
import com.ningdatech.pmapi.todocenter.enums.ProcessStatusEnum;
import com.ningdatech.pmapi.todocenter.extension.cmd.BackToHisApprovalNodeCmd;
import com.ningdatech.pmapi.todocenter.model.dto.req.ReqProcessHandlerDTO;
import com.ningdatech.pmapi.todocenter.model.dto.res.ResToBeProjectListExportDTO;
import com.ningdatech.pmapi.todocenter.zwdd.model.MessageContent;
import com.ningdatech.pmapi.todocenter.zwdd.model.MessageText;
import com.ningdatech.pmapi.user.entity.UserInfo;
import com.ningdatech.pmapi.user.service.IUserInfoService;
import com.ningdatech.pmapi.user.util.LoginUserUtil;
import com.wflow.bean.do_.UserDo;
import com.wflow.bean.entity.WflowCcTasks;
import com.wflow.bean.entity.WflowModelHistorys;
import com.wflow.bean.entity.WflowModels;
import com.wflow.exception.BusinessException;
import com.wflow.mapper.WflowCcTasksMapper;
import com.wflow.mapper.WflowModelHistorysMapper;
import com.wflow.service.OrgRepositoryService;
@@ -37,10 +54,14 @@ import com.wflow.workflow.config.WflowGlobalVarDef;
import com.wflow.workflow.service.*;
import com.wflow.workflow.service.FormService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Maps;
import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.Process;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
@@ -58,10 +79,12 @@ import lombok.RequiredArgsConstructor;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.ningdatech.pmapi.todocenter.constant.WorkNotice.PASS_MSG_TEMPLATE;
import static com.ningdatech.pmapi.todocenter.constant.WorkNotice.PASS_MSG_TEMPLATE2;

/**
* @author CMM
* @since 2023/01/12 16:09
@@ -84,9 +107,20 @@ public class TodoCenterManage {
private final OrgRepositoryService orgRepositoryService;
private final ProcessTaskService processTaskService;
private final WflowCcTasksMapper ccTasksMapper;
private final ProcessModelService processModelService;
private final IUserInfoService userInfoService;
private final ExecutableClient CLIENT;
/**
* 待办中心项目列表查询
* @param param
* @return com.ningdatech.basic.model.PageVo<com.ningdatech.pmapi.todocenter.model.dto.res.ResToBeProcessedDTO>
* @author CMM
* @since 2023/02/01 17:44
*/
public PageVo<ResToBeProcessedDTO> queryProjectList(ReqToBeProcessedDTO param) {
// 获取登录用户ID
Long userId = LoginUserUtil.getUserId();
// long userId = LoginUserUtil.getUserId();
int userId = 381496;
// 获取入参分页信息
Integer pageSize = param.getPageSize();
Integer pageNumber = param.getPageNumber();
@@ -106,6 +140,7 @@ public class TodoCenterManage {
String status = instanceProgress.getStatus();
Boolean temporarySupplement = (Boolean) formData.get(ProjectDeclareConstants.BasicInformation.TEMPORARY_SUPPLEMENT);
ResToBeProcessedDTO res = new ResToBeProcessedDTO();
temporarySupplement = true;
if (temporarySupplement.equals(param.getIsSupplement())) {
ProcessDefinition processDef = repositoryService.createProcessDefinitionQuery()
.processDefinitionId(task.getProcessDefinitionId())
@@ -143,21 +178,26 @@ public class TodoCenterManage {
res.setProcessLaunchTime(NdDateUtils.date2LocalDateTime(processInstance.getStartTime()));
}
return res;
}).collect(Collectors.toList());
List<ResToBeProcessedDTO> result = resVos.stream()
.filter(r -> r.getProjectName().equals(param.getProjectName()))
.filter(r -> r.getReportUnitName().equals(param.getReportUnitName()))
.filter(r -> r.getBudgetYear().equals(param.getBudgetYear()))
.filter(r -> r.getProcessLaunchTime().isBefore(param.getProcessLaunchStartTime()))
.filter(r -> r.getProcessLaunchTime().isAfter(param.getProcessLaunchEndTime())).collect(Collectors.toList());
//取用户信息,减少数据库查询,一次构建
}).filter(v -> StringUtils.isBlank(param.getProjectName()) || v.getProjectName().contains(param.getProjectName()))
.filter(v -> StringUtils.isBlank(param.getReportUnitName()) || v.getReportUnitName().contains(param.getReportUnitName()))
.filter(v -> Objects.isNull(param.getBudgetYear()) || v.getBudgetYear().equals(param.getBudgetYear()))
.filter(v -> Objects.isNull(param.getProcessLaunchStartTime()) || v.getProcessLaunchTime().isBefore(param.getProcessLaunchStartTime()))
.filter(v -> Objects.isNull(param.getProcessLaunchEndTime()) || v.getProcessLaunchTime().isAfter(param.getProcessLaunchEndTime()))
.collect(Collectors.toList());
if (CollectionUtil.isNotEmpty(staterUsers)) {
Map<String, OrgUser> userMap = userDeptOrLeaderService.getUserMapByIds(staterUsers);
page.setRecords(result.stream().peek(v -> v.getProcessTaskInfo().setOwner(userMap.get(v.getProcessTaskInfo().getOwnerId()))).collect(Collectors.toList()));
page.setRecords(resVos.stream().peek(v -> v.getProcessTaskInfo().setOwner(userMap.get(v.getProcessTaskInfo().getOwnerId()))).collect(Collectors.toList()));
}
return PageVo.of(resVos,page.getTotal());
return PageVo.of(resVos,resVos.size());
}

/**
* 待办中心列表导出
* @param response
* @param param
* @return void
* @author CMM
* @since 2023/02/01 17:44
*/
public void exportProjectList(HttpServletResponse response, ReqToBeProcessedDTO param) {
PageVo<ResToBeProcessedDTO> page =
queryProjectList(param);
@@ -180,50 +220,44 @@ public class TodoCenterManage {
throw new RuntimeException(e);
}
}

/**
* 流程处理相关操作
* @param param
* @return void
* @author CMM
* @since 2023/02/01 17:43
*/
public void handler(ReqProcessHandlerDTO param) {
Long userId = LoginUserUtil.getUserId();
Task task = taskService.createTaskQuery().taskId(param.getTaskId()).active().singleResult();
HashMap<String, Object> formData = new HashMap<>(32);
String format = NdDateUtils.format(LocalDateTime.now(), "yyyy-MM-dd HH:mm");
LocalDateTime auditTime = LocalDateTime.parse(format);
if (Objects.isNull(task)) {
throw new BizException("任务不存在");
}
if (hasComment(param.getAuditInfo())) {
taskService.addComment(param.getTaskId(), param.getInstanceId(), JSONObject.toJSONString(param.getAuditInfo()));
}
switch (param.getAction()) {
// 通过
case pass:
formData.put("audit_pass_opinion",param.getAuditPassOpinion());
formData.put("audit_pass_appendix",param.getAuditPassAppendix());
formData.put("audit_pass_time", auditTime);
case PASS:
formService.updateInstanceFormData(param.getInstanceId(), formData);
doPass(task, param);
// 盖章并通过
case seal_pass:
formData.put("seal_pass_opinion",param.getSealPassOpinion());
formData.put("seal_pass_appendix",param.getSealPassAppendix());
Date sealPassTime = NdDateUtils.localDateTime2Date(LocalDateTime.now());
formData.put("seal_pass_time",sealPassTime);
case SEAL_PASS:
formService.updateInstanceFormData(param.getInstanceId(), formData);
doSealPass(task, param);
// 驳回
case reject:
formData.put("audit_reject_opinion",param.getAuditRejectOpinion());
formData.put("audit_reject_appendix",param.getAuditRejectAppendix());
formData.put("audit_reject_time", auditTime);
case REJECT:
formService.updateInstanceFormData(param.getInstanceId(), formData);
doReject(task, param);
break;
// 退回
case back:
formData.put("audit_back_opinion",param.getAuditBackOpinion());
formData.put("audit_back_appendix",param.getAuditBackAppendix());
formData.put("audit_back_time", auditTime);
case BACK:
formService.updateInstanceFormData(param.getInstanceId(), formData);
doBackTask(task.getTaskDefinitionKey(), userId, param);
doBackTask(task, userId, param);
break;
// 撤回
case withdraw:
case WITHDRAW:
doWithDrawProcess(task);
break;
default:
@@ -233,21 +267,41 @@ public class TodoCenterManage {

/**
* 审批任务:驳回
*
* @param task 当前任务
* @param param 参数
*/
private void doReject(Task task, ReqProcessHandlerDTO param) {
Map<String, Object> var = new HashMap<>(16);
var.put("approve_" + task.getId(), param.getAction());
// TODO 中止流程并使项目进入对应状态
// TODO 给项目创建人、流程发起人发送浙政钉工作通知:【项目名称】的【流程名称】被驳回,请及时处理。
// TODO 中止流程并使项目进入对应状态,给项目创建人、流程发起人发送浙政钉工作通知:【项目名称】的【流程名称】被驳回,请及时处理。
//获取流程定义
Process process = ProcessDefinitionUtil.getProcess(task.getProcessDefinitionId());
String projectName = getProjectName(task);
// 获取根节点即流程发起节点
FlowNode rootNode = (FlowNode) process.getFlowElement("root", true);
// TODO 中止流程并使项目进入对应状态,给项目创建人、流程发起人发送浙政钉工作通知:【项目名称】的【流程名称】被驳回,请及时处理。
sendWorkNoticeToStartUser(task,projectName,rootNode);
taskService.complete(param.getTaskId(), var);
}
/**
* 获取最新版本的流程配置
* @param task 当前任务
* @return com.wflow.bean.entity.WflowModels
* @author CMM
* @since 2023/02/01 17:30
*/
private WflowModels getLastWflowModels(Task task) {
WflowModels wflowModels = processModelService.getOne(Wrappers.lambdaQuery(WflowModels.class)
.eq(WflowModels::getProcessDefId, task.getProcessDefinitionId()));
if (ObjectUtil.isNull(wflowModels)) {
log.warn("流程{}不存在", wflowModels.getFormId());
throw new BusinessException("不存在该表单");
}
return wflowModels;
}

/**
* 审批任务:盖章并通过
*
* @param task 当前任务
* @param param 参数
*/
@@ -255,61 +309,240 @@ public class TodoCenterManage {
Map<String, Object> var = new HashMap<>(16);
var.put("approve_" + task.getId(), param.getAction());
// TODO 判断项目申报单位级别,区县单位申报有上级主管单位意见栏,市级单位没有

// TODO 市级单位:为大数据局;区县单位:为大数据中心(根据附件区分?)

taskService.complete(param.getTaskId(), var);
}

/**
* 审批任务:通过
*
* @param task 当前任务
* @param param 参数
*/
private void doPass(Task task, ReqProcessHandlerDTO param) {

String projectName = getProjectName(task);
Map<String, Object> var = new HashMap<>(16);
var.put("approve_" + task.getId(), param.getAction());
// TODO 获取流程下一个节点的审核人
//获取流程定义
Process process = ProcessDefinitionUtil.getProcess(task.getProcessDefinitionId());
// 获取当前节点
FlowNode currentNode = (FlowNode) process.getFlowElement(task.getTaskDefinitionKey(), true);
// 获取流程下一个节点浙政钉用户ID
String nextUserId = getNextUserId(currentNode);
// 若有下一个审核人,向其发送浙政钉工作通知:标题:审核任务 内容:【单位名称】的【项目名称】需要您审核。
if (Objects.nonNull(nextUserId)){
UserInfo auditUserInfo = userInfoService.getById(Long.valueOf(nextUserId));
// TODO 向其发送浙政钉工作通知
String msg = String.format(PASS_MSG_TEMPLATE,null,projectName);
sendWorkNotice(auditUserInfo,msg);
}else {
// 若没有,向发起人发送浙政钉工作通知:【项目名称】已通过【流程名称】,请及时开始下一步操作。
// TODO 向其发送浙政钉工作通知 获取根节点的孩子节点(即发起人节点),向其发送浙政钉工作通知
// 获取根节点即流程发起节点
FlowNode rootNode = (FlowNode) process.getFlowElement("root", true);
sendWorkNoticeToStartUser(task, projectName, rootNode);
}
taskService.complete(param.getTaskId(), var);
}

// TODO 若有下一个审核人,向其发送浙政钉工作通知:标题:审核任务 内容:【单位名称】的【项目名称】需要您审核。
private void sendWorkNoticeToStartUser(Task task, String projectName, FlowNode rootNode) {
String startUserId = getRootUserId(rootNode);
UserInfo startUserInfo = userInfoService.getById(Long.valueOf(startUserId));
// 从历史表获取最新版本的流程
WflowModels wflowModels = getLastWflowModels(task);
String formName = wflowModels.getFormName();
String msg = String.format(PASS_MSG_TEMPLATE2, projectName, formName);
sendWorkNotice(startUserInfo, msg);
}

/**
* 获取流程发起节点的浙政钉用户ID
* @param rootNode 根节点
* @return java.lang.String
* @author CMM
* @since 2023/02/02 21:47
*/
private String getRootUserId(FlowNode rootNode) {
String rootUserId = null;
// 输出连线
List<SequenceFlow> outgoingFlows = rootNode.getOutgoingFlows();
// 遍历返回下一个节点信息
for (SequenceFlow currentOutgoingFlow : outgoingFlows) {
// 类型自己判断
FlowElement targetFlowElement = currentOutgoingFlow.getTargetFlowElement();
// TODO 若要会签需判断候选人
// 发起事件
if (targetFlowElement instanceof StartEvent) {
UserTask userTask = (UserTask) targetFlowElement;
rootUserId = userTask.getAssignee();
break;
}
}
return rootUserId;

// TODO 若没有,向发起人发送浙政钉工作通知:【项目名称】已通过【流程名称】,请及时开始下一步操作。
taskService.complete(param.getTaskId(), var);
}

/**
* 获取当前节点的下一个节点的浙政钉用户ID
* @param currentNode 当前节点
* @return java.lang.String 下一个节点的浙政钉用户ID
* @author CMM
* @since 2023/02/02 16:49
*/
private String getNextUserId(FlowNode currentNode) {
String nextUserId = null;
// 输出连线
List<SequenceFlow> outgoingFlows = currentNode.getOutgoingFlows();
// 遍历返回下一个节点信息
for (SequenceFlow currentOutgoingFlow : outgoingFlows) {
// 类型自己判断
FlowElement targetFlowElement = currentOutgoingFlow.getTargetFlowElement();
// TODO 若要会签需判断候选人
// 用户任务
if (targetFlowElement instanceof UserTask) {
UserTask userTask = (UserTask) targetFlowElement;
nextUserId = userTask.getAssignee();
break;
}
}
return nextUserId;
}
/**
* 获取任务节点的申报项目名称
* @param task 当前任务
* @return java.lang.String 项目名称
* @author CMM
* @since 2023/02/01 17:27
*/
private String getProjectName(Task task) {
String nodeId = task.getTaskDefinitionKey();
String instanceId = task.getProcessInstanceId();
ProcessProgressVo instanceProgress = processService.getInstanceProgress(nodeId, instanceId);
Map<String, Object> formData = instanceProgress.getFormData();
String projectName = (String) formData.get(ProjectDeclareConstants.BasicInformation.PROJECT_NAME);
return projectName;
}
/**
* 判断处理操作是否含有审核意见
* @param comment 审核意见
* @return boolean
* @author CMM
* @since 2023/02/01 17:33
*/
private boolean hasComment(ProcessComment comment) {
return Objects.nonNull(comment) && (StrUtil.isNotBlank(comment.getText())
|| CollectionUtil.isNotEmpty(comment.getAttachments()));
}
/**
* 发送浙政钉工作通知
* @param auditUserInfo 审核人信息
* @param msg 要发送的工作通知
* @return void
* @author CMM
* @since 2023/02/01 17:32
*/
private void sendWorkNotice(UserInfo auditUserInfo, String msg) {
// TODO 获取浙政钉唯一标识
String dingKey = null;
IntelligentGetClient intelligentGetClient = CLIENT.newIntelligentGetClient(DingConstant.WORKING_NOTICE);
OapiMessageWorkNotificationRequest request = new OapiMessageWorkNotificationRequest();
//消息体(参考下文示例消息格式)
MessageText messageText = new MessageText();
messageText.setMsgType("text");
MessageContent messageContent = new MessageContent();

messageContent.setContent(msg);
messageText.setText(messageContent);
request.setMsg(JSONUtil.toJsonStr(messageText));
// 构建唯一的消息ID
// String bizMsgId = "ZB_URGE_NOTICE_" + "_" + auditUserInfo.getDeptId() + "_" + auditUserInfo.getUserId();
// request.setBizMsgId(bizMsgId);
request.setBizMsgId(null);
//租户id
// request.setTenantId(GovDingProperties.tenantId.toString());
request.setReceiverIds(dingKey);
// 获取结果
OapiMessageWorkNotificationResponse apiResult = intelligentGetClient.get(request);
if (!apiResult.getSuccess() || !JSONUtil.parseObj(apiResult.getContent()).getBool("success")) {
log.warn("发送工作通知失败: {}", apiResult.getContent());
throw new BizException(Status.BAD_REQUEST.toString());
}

}
/**
* 撤销流程处理
*
* @param task 当前任务
*/
private void doWithDrawProcess(Task task) {
// TODO 若是流程发起人点击撤回,项目回到上一个状态,并删除当前审核人对应的待办记录
// TODO 若是前一个审核人点击撤回,在审核记录中移除自己提交过的审核意见、待我处理中移除当前审核人的待办记录、待我处理中增加自己的待办记录、我已处理中去掉自己之前处理的记录
//获取流程定义
Process process = ProcessDefinitionUtil.getProcess(task.getProcessDefinitionId());
// 获取当前运行流程的发起人节点信息
FlowNode rootNode = (FlowNode) process.getFlowElement("root", true);
// 获取当前节点
FlowNode currentNode = (FlowNode) process.getFlowElement(task.getTaskDefinitionKey(), true);
UserTask userTask = (UserTask) process.getFlowElement(task.getTaskDefinitionKey());
String currentUserId = userTask.getAssignee();
String rootUserId = getRootUserId(rootNode);
// 判断当前登录用户是否是流程发起人
Long userId = LoginUserUtil.getUserId();
List<Execution> executions = runtimeService.createExecutionQuery()
.processInstanceId(task.getProcessInstanceId())
.onlyChildExecutions().list();
// 强制流程指向撤回
runtimeService.createChangeActivityStateBuilder()
.processInstanceId(task.getProcessInstanceId())
.moveActivityIdTo(task.getTaskDefinitionKey(), HisProInsEndActId.WITHDRAW)
.moveExecutionsToSingleActivityId(executions.stream().map(Execution::getId)
.collect(Collectors.toList()), HisProInsEndActId.WITHDRAW)
.changeState();
if (rootUserId.equals(String.valueOf(userId))){
// TODO 若是流程发起人点击撤回,项目回到上一个状态,并删除当前审核人对应的待办记录
// 强制流程指向撤回
runtimeService.createChangeActivityStateBuilder()
.processInstanceId(task.getProcessInstanceId())
.moveActivityIdTo(task.getTaskDefinitionKey(), HisProInsEndActId.WITHDRAW)
.moveExecutionsToSingleActivityId(executions.stream().map(Execution::getId)
.collect(Collectors.toList()), HisProInsEndActId.WITHDRAW)
.changeState();
}else {
FlowElementsContainer parentContainer = currentNode.getParentContainer();
for (FlowElement flowElement : parentContainer.getFlowElements()) {
UserTask BeforeUserTask = (UserTask) flowElement;
if (BeforeUserTask.getAssignee().equals(String.valueOf(userId))){
// TODO 若是前一个审核人点击撤回,在审核记录中移除自己提交过的审核意见、
// 待我处理中移除当前审核人的待办记录、
// 待我处理中增加自己的待办记录、
// 我已处理中去掉自己之前处理的记录
// 强制流程指向撤回
runtimeService.createChangeActivityStateBuilder()
.processInstanceId(task.getProcessInstanceId())
.moveActivityIdTo(flowElement.getId(), HisProInsEndActId.WITHDRAW)
.moveExecutionsToSingleActivityId(executions.stream().map(Execution::getId)
.collect(Collectors.toList()), HisProInsEndActId.WITHDRAW)
.changeState();
break;
}
}
}
}

/**
* 退回流程处理
* @param current 当前流程定义key
* @param userId 当前登录用户ID
* @param param 参数
*
* @param task
* @param task 当前任务
* @param userId 当前登录用户ID
* @param param 参数
*/
private void doBackTask(String current, Long userId, ReqProcessHandlerDTO param) {
// TODO 流程变成【被退回】状态
// TODO 待我处理中,为流程发起人增加一条待办记录
// TODO 给项目创建人、流程发起人发送浙政钉工作通知:【项目名称】的【流程名称】被退回,请及时处理。
//执行自定义回退逻辑
managementService.executeCommand(new BackToHisApprovalNodeCmd(runtimeService, param.getTaskId(), param.getTargetNode()));
private void doBackTask(Task task, Long userId, ReqProcessHandlerDTO param) {
// 获取项目名称
String projectName = getProjectName(task);
//获取流程定义
Process process = ProcessDefinitionUtil.getProcess(task.getProcessDefinitionId());
// 获取根节点即流程发起节点
FlowNode rootNode = (FlowNode) process.getFlowElement("root", true);
// TODO 流程变成【被退回】状态,待我处理中,为流程发起人增加一条待办记录,给项目创建人、流程发起人发送浙政钉工作通知:【项目名称】的【流程名称】被退回,请及时处理。
sendWorkNoticeToStartUser(task,projectName,rootNode);
//执行自定义回退逻辑,回退到流程发起人
managementService.executeCommand(new BackToHisApprovalNodeCmd(runtimeService, param.getTaskId(), rootNode.getId()));
runtimeService.setVariables(param.getInstanceId(), Maps.newHashMap("approve_" + param.getTaskId(), param.getAction()));
log.info("用户[{}] 退回流程[{}] [{} -> {}]", userId, param.getInstanceId(), current, param.getTargetNode());
log.info("用户[{}] 退回流程[{}] [{} -> {}]", userId, param.getInstanceId(), task.getTaskDefinitionKey(), param.getTargetNode());
}

/**
@@ -356,7 +589,7 @@ public class TodoCenterManage {
.startTime(instance.getStartTime())
.finishTime(instance.getStartTime())
.taskId("root")
.result(ReqProcessHandlerDTO.Action.pass)
.result(ProcessHandlerEnum.PASS)
.build());
// 提取全量表单数据
Map<String, Object> formData = formDatas.stream().collect(Collectors.toMap(HistoricVariableInstance::getVariableName, HistoricVariableInstance::getValue));
@@ -378,6 +611,7 @@ public class TodoCenterManage {
if (Objects.isNull(instance.getEndActivityId())){
res.setStatus(ProcessStatusEnum.UNDER_REVIEW.name());
} else if (HisProInsEndActId.BACK.equals(instance.getEndActivityId())) {
// TODO 被退回的审核节点状态这里只是暂时这么判断,具体怎么保存这个退回状态,后面讨论
res.setStatus(ProcessStatusEnum.BE_BACKED.name());
} else if (HisProInsEndActId.REJECT.equals(instance.getEndActivityId())) {
res.setStatus(ProcessStatusEnum.BE_REJECTED.name());
@@ -426,9 +660,9 @@ public class TodoCenterManage {
.processInstanceId(instanceId).orderByHistoricActivityInstanceStartTime().asc().list();
Set<String> userSet = new HashSet<>();
//获取节点处理结果
Map<String, ReqProcessHandlerDTO.Action> varMap = historyService.createHistoricVariableInstanceQuery()
Map<String, ProcessHandlerEnum> varMap = historyService.createHistoricVariableInstanceQuery()
.processInstanceId(instanceId).variableNameLike("approve_%").list().stream()
.collect(Collectors.toMap(HistoricVariableInstance::getVariableName, v -> (ReqProcessHandlerDTO.Action) v.getValue()));
.collect(Collectors.toMap(HistoricVariableInstance::getVariableName, v -> (ProcessHandlerEnum) v.getValue()));
List<ProgressNode> progressNodes = list.stream().filter(his -> ObjectUtil.isNotNull(his.getTaskId())).map(his -> {
Object props = nodeProps.get(his.getActivityId());
ApprovalModeEnum approvalMode = null;


+ 44
- 37
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/model/dto/req/ReqProcessHandlerDTO.java View File

@@ -1,5 +1,7 @@
package com.ningdatech.pmapi.todocenter.model.dto.req;
import com.ningdatech.pmapi.common.model.FileBasicInfo;
import com.ningdatech.pmapi.todocenter.bean.entity.ProcessComment;
import com.ningdatech.pmapi.todocenter.enums.ProcessHandlerEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@@ -31,7 +33,7 @@ public class ReqProcessHandlerDTO {
/**
* 操作类型
*/
private Action action;
private ProcessHandlerEnum action;
/**
* 目标用户
*/
@@ -40,43 +42,48 @@ public class ReqProcessHandlerDTO {
* 目标节点
*/
private String targetNode;
/**
* 审核通过意见
*/
private String auditPassOpinion;

/**
* 审核通过附件
*/
private FileBasicInfo auditPassAppendix;
/**
* 盖章通过意见
*/
private String sealPassOpinion;

/**
* 盖章通过附件
*/
private FileBasicInfo sealPassAppendix;
/**
* 审核退回意见
*/
private String auditBackOpinion;
/**
* 审核退回附件
*/
private FileBasicInfo auditBackAppendix;
/**
* 审核驳回意见
*/
private String auditRejectOpinion;

/**
* 审核驳回附件
* 审核信息
*/
private FileBasicInfo auditRejectAppendix;
public enum Action{
//通过、盖章并通过、退回、撤回、驳回,审核意见类型
pass, seal_pass ,back, withdraw, reject;
}
private ProcessComment auditInfo;
///**
// * 审核通过意见
// */
//private String auditPassOpinion;
//
///**
// * 审核通过附件
// */
//private FileBasicInfo auditPassAppendix;
///**
// * 盖章通过意见
// */
//private String sealPassOpinion;
//
///**
// * 盖章通过附件
// */
//private FileBasicInfo sealPassAppendix;
///**
// * 审核退回意见
// */
//private String auditBackOpinion;
///**
// * 审核退回附件
// */
//private FileBasicInfo auditBackAppendix;
///**
// * 审核驳回意见
// */
//private String auditRejectOpinion;
//
///**
// * 审核驳回附件
// */
//private FileBasicInfo auditRejectAppendix;
//public enum Action{
// //通过、盖章并通过、退回、撤回、驳回
// pass, seal_pass ,back, withdraw, reject;
//}
}

+ 13
- 0
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/zwdd/model/MessageContent.java View File

@@ -0,0 +1,13 @@
package com.ningdatech.pmapi.todocenter.zwdd.model;

import lombok.Data;

/**
* 消息内容
* @author CMM
* @since 2023/02/01 14:54
*/
@Data
public class MessageContent {
private String content;
}

+ 17
- 0
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/zwdd/model/MessageText.java View File

@@ -0,0 +1,17 @@
package com.ningdatech.pmapi.todocenter.zwdd.model;

import lombok.Data;

/**
* 文本消息
* @author CMM
* @since 2023/02/01 14:53
*/
@Data
public class MessageText {

private String msgType;

private MessageContent text;

}

Loading…
Cancel
Save