|
@@ -2,25 +2,42 @@ package com.ningdatech.pmapi.todocenter.manage; |
|
|
import cn.hutool.core.collection.CollectionUtil; |
|
|
import cn.hutool.core.collection.CollectionUtil; |
|
|
import cn.hutool.core.util.ObjectUtil; |
|
|
import cn.hutool.core.util.ObjectUtil; |
|
|
import cn.hutool.core.util.StrUtil; |
|
|
import cn.hutool.core.util.StrUtil; |
|
|
|
|
|
import cn.hutool.json.JSONUtil; |
|
|
import com.alibaba.excel.EasyExcel; |
|
|
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.conditions.query.QueryWrapper; |
|
|
|
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|
|
|
|
|
import com.ningdatech.basic.enumeration.Status; |
|
|
import com.ningdatech.basic.exception.BizException; |
|
|
import com.ningdatech.basic.exception.BizException; |
|
|
import com.ningdatech.basic.util.NdDateUtils; |
|
|
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.constant.ProjectDeclareConstants; |
|
|
import com.ningdatech.pmapi.common.util.ExcelDownUtil; |
|
|
import com.ningdatech.pmapi.common.util.ExcelDownUtil; |
|
|
import com.ningdatech.pmapi.common.util.ExcelExportStyle; |
|
|
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.entity.ProgressNode; |
|
|
import com.ningdatech.pmapi.todocenter.bean.vo.ProcessProgressDetailVo; |
|
|
import com.ningdatech.pmapi.todocenter.bean.vo.ProcessProgressDetailVo; |
|
|
import com.ningdatech.pmapi.todocenter.constant.HisProInsEndActId; |
|
|
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.enums.ProcessStatusEnum; |
|
|
import com.ningdatech.pmapi.todocenter.extension.cmd.BackToHisApprovalNodeCmd; |
|
|
import com.ningdatech.pmapi.todocenter.extension.cmd.BackToHisApprovalNodeCmd; |
|
|
import com.ningdatech.pmapi.todocenter.model.dto.req.ReqProcessHandlerDTO; |
|
|
import com.ningdatech.pmapi.todocenter.model.dto.req.ReqProcessHandlerDTO; |
|
|
import com.ningdatech.pmapi.todocenter.model.dto.res.ResToBeProjectListExportDTO; |
|
|
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.ningdatech.pmapi.user.util.LoginUserUtil; |
|
|
import com.wflow.bean.do_.UserDo; |
|
|
import com.wflow.bean.do_.UserDo; |
|
|
import com.wflow.bean.entity.WflowCcTasks; |
|
|
import com.wflow.bean.entity.WflowCcTasks; |
|
|
import com.wflow.bean.entity.WflowModelHistorys; |
|
|
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.WflowCcTasksMapper; |
|
|
import com.wflow.mapper.WflowModelHistorysMapper; |
|
|
import com.wflow.mapper.WflowModelHistorysMapper; |
|
|
import com.wflow.service.OrgRepositoryService; |
|
|
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.*; |
|
|
import com.wflow.workflow.service.FormService; |
|
|
import com.wflow.workflow.service.FormService; |
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
|
|
|
import org.apache.commons.lang3.StringUtils; |
|
|
import org.assertj.core.util.Maps; |
|
|
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.*; |
|
|
import org.flowable.engine.history.HistoricActivityInstance; |
|
|
import org.flowable.engine.history.HistoricActivityInstance; |
|
|
import org.flowable.engine.history.HistoricProcessInstance; |
|
|
import org.flowable.engine.history.HistoricProcessInstance; |
|
|
|
|
|
import org.flowable.engine.impl.util.ProcessDefinitionUtil; |
|
|
import org.flowable.engine.repository.ProcessDefinition; |
|
|
import org.flowable.engine.repository.ProcessDefinition; |
|
|
import org.flowable.engine.runtime.Execution; |
|
|
import org.flowable.engine.runtime.Execution; |
|
|
import org.flowable.engine.runtime.ProcessInstance; |
|
|
import org.flowable.engine.runtime.ProcessInstance; |
|
@@ -58,10 +79,12 @@ import lombok.RequiredArgsConstructor; |
|
|
|
|
|
|
|
|
import javax.servlet.http.HttpServletResponse; |
|
|
import javax.servlet.http.HttpServletResponse; |
|
|
import java.io.IOException; |
|
|
import java.io.IOException; |
|
|
import java.time.LocalDateTime; |
|
|
|
|
|
import java.util.*; |
|
|
import java.util.*; |
|
|
import java.util.stream.Collectors; |
|
|
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 |
|
|
* @author CMM |
|
|
* @since 2023/01/12 16:09 |
|
|
* @since 2023/01/12 16:09 |
|
@@ -84,9 +107,20 @@ public class TodoCenterManage { |
|
|
private final OrgRepositoryService orgRepositoryService; |
|
|
private final OrgRepositoryService orgRepositoryService; |
|
|
private final ProcessTaskService processTaskService; |
|
|
private final ProcessTaskService processTaskService; |
|
|
private final WflowCcTasksMapper ccTasksMapper; |
|
|
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) { |
|
|
public PageVo<ResToBeProcessedDTO> queryProjectList(ReqToBeProcessedDTO param) { |
|
|
// 获取登录用户ID |
|
|
// 获取登录用户ID |
|
|
Long userId = LoginUserUtil.getUserId(); |
|
|
|
|
|
|
|
|
// long userId = LoginUserUtil.getUserId(); |
|
|
|
|
|
int userId = 381496; |
|
|
// 获取入参分页信息 |
|
|
// 获取入参分页信息 |
|
|
Integer pageSize = param.getPageSize(); |
|
|
Integer pageSize = param.getPageSize(); |
|
|
Integer pageNumber = param.getPageNumber(); |
|
|
Integer pageNumber = param.getPageNumber(); |
|
@@ -106,6 +140,7 @@ public class TodoCenterManage { |
|
|
String status = instanceProgress.getStatus(); |
|
|
String status = instanceProgress.getStatus(); |
|
|
Boolean temporarySupplement = (Boolean) formData.get(ProjectDeclareConstants.BasicInformation.TEMPORARY_SUPPLEMENT); |
|
|
Boolean temporarySupplement = (Boolean) formData.get(ProjectDeclareConstants.BasicInformation.TEMPORARY_SUPPLEMENT); |
|
|
ResToBeProcessedDTO res = new ResToBeProcessedDTO(); |
|
|
ResToBeProcessedDTO res = new ResToBeProcessedDTO(); |
|
|
|
|
|
temporarySupplement = true; |
|
|
if (temporarySupplement.equals(param.getIsSupplement())) { |
|
|
if (temporarySupplement.equals(param.getIsSupplement())) { |
|
|
ProcessDefinition processDef = repositoryService.createProcessDefinitionQuery() |
|
|
ProcessDefinition processDef = repositoryService.createProcessDefinitionQuery() |
|
|
.processDefinitionId(task.getProcessDefinitionId()) |
|
|
.processDefinitionId(task.getProcessDefinitionId()) |
|
@@ -143,21 +178,26 @@ public class TodoCenterManage { |
|
|
res.setProcessLaunchTime(NdDateUtils.date2LocalDateTime(processInstance.getStartTime())); |
|
|
res.setProcessLaunchTime(NdDateUtils.date2LocalDateTime(processInstance.getStartTime())); |
|
|
} |
|
|
} |
|
|
return res; |
|
|
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)) { |
|
|
if (CollectionUtil.isNotEmpty(staterUsers)) { |
|
|
Map<String, OrgUser> userMap = userDeptOrLeaderService.getUserMapByIds(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) { |
|
|
public void exportProjectList(HttpServletResponse response, ReqToBeProcessedDTO param) { |
|
|
PageVo<ResToBeProcessedDTO> page = |
|
|
PageVo<ResToBeProcessedDTO> page = |
|
|
queryProjectList(param); |
|
|
queryProjectList(param); |
|
@@ -180,50 +220,44 @@ public class TodoCenterManage { |
|
|
throw new RuntimeException(e); |
|
|
throw new RuntimeException(e); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 流程处理相关操作 |
|
|
|
|
|
* @param param |
|
|
|
|
|
* @return void |
|
|
|
|
|
* @author CMM |
|
|
|
|
|
* @since 2023/02/01 17:43 |
|
|
|
|
|
*/ |
|
|
public void handler(ReqProcessHandlerDTO param) { |
|
|
public void handler(ReqProcessHandlerDTO param) { |
|
|
Long userId = LoginUserUtil.getUserId(); |
|
|
Long userId = LoginUserUtil.getUserId(); |
|
|
Task task = taskService.createTaskQuery().taskId(param.getTaskId()).active().singleResult(); |
|
|
Task task = taskService.createTaskQuery().taskId(param.getTaskId()).active().singleResult(); |
|
|
HashMap<String, Object> formData = new HashMap<>(32); |
|
|
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)) { |
|
|
if (Objects.isNull(task)) { |
|
|
throw new BizException("任务不存在"); |
|
|
throw new BizException("任务不存在"); |
|
|
} |
|
|
} |
|
|
|
|
|
if (hasComment(param.getAuditInfo())) { |
|
|
|
|
|
taskService.addComment(param.getTaskId(), param.getInstanceId(), JSONObject.toJSONString(param.getAuditInfo())); |
|
|
|
|
|
} |
|
|
switch (param.getAction()) { |
|
|
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); |
|
|
formService.updateInstanceFormData(param.getInstanceId(), formData); |
|
|
doPass(task, param); |
|
|
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); |
|
|
formService.updateInstanceFormData(param.getInstanceId(), formData); |
|
|
doSealPass(task, param); |
|
|
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); |
|
|
formService.updateInstanceFormData(param.getInstanceId(), formData); |
|
|
doReject(task, param); |
|
|
doReject(task, param); |
|
|
break; |
|
|
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); |
|
|
formService.updateInstanceFormData(param.getInstanceId(), formData); |
|
|
doBackTask(task.getTaskDefinitionKey(), userId, param); |
|
|
|
|
|
|
|
|
doBackTask(task, userId, param); |
|
|
break; |
|
|
break; |
|
|
// 撤回 |
|
|
// 撤回 |
|
|
case withdraw: |
|
|
|
|
|
|
|
|
case WITHDRAW: |
|
|
doWithDrawProcess(task); |
|
|
doWithDrawProcess(task); |
|
|
break; |
|
|
break; |
|
|
default: |
|
|
default: |
|
@@ -233,21 +267,41 @@ public class TodoCenterManage { |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* 审批任务:驳回 |
|
|
* 审批任务:驳回 |
|
|
* |
|
|
|
|
|
* @param task 当前任务 |
|
|
* @param task 当前任务 |
|
|
* @param param 参数 |
|
|
* @param param 参数 |
|
|
*/ |
|
|
*/ |
|
|
private void doReject(Task task, ReqProcessHandlerDTO param) { |
|
|
private void doReject(Task task, ReqProcessHandlerDTO param) { |
|
|
Map<String, Object> var = new HashMap<>(16); |
|
|
Map<String, Object> var = new HashMap<>(16); |
|
|
var.put("approve_" + task.getId(), param.getAction()); |
|
|
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); |
|
|
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 task 当前任务 |
|
|
* @param param 参数 |
|
|
* @param param 参数 |
|
|
*/ |
|
|
*/ |
|
@@ -255,61 +309,240 @@ public class TodoCenterManage { |
|
|
Map<String, Object> var = new HashMap<>(16); |
|
|
Map<String, Object> var = new HashMap<>(16); |
|
|
var.put("approve_" + task.getId(), param.getAction()); |
|
|
var.put("approve_" + task.getId(), param.getAction()); |
|
|
// TODO 判断项目申报单位级别,区县单位申报有上级主管单位意见栏,市级单位没有 |
|
|
// TODO 判断项目申报单位级别,区县单位申报有上级主管单位意见栏,市级单位没有 |
|
|
|
|
|
|
|
|
// TODO 市级单位:为大数据局;区县单位:为大数据中心(根据附件区分?) |
|
|
// TODO 市级单位:为大数据局;区县单位:为大数据中心(根据附件区分?) |
|
|
|
|
|
|
|
|
taskService.complete(param.getTaskId(), var); |
|
|
taskService.complete(param.getTaskId(), var); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* 审批任务:通过 |
|
|
* 审批任务:通过 |
|
|
* |
|
|
|
|
|
* @param task 当前任务 |
|
|
* @param task 当前任务 |
|
|
* @param param 参数 |
|
|
* @param param 参数 |
|
|
*/ |
|
|
*/ |
|
|
private void doPass(Task task, ReqProcessHandlerDTO param) { |
|
|
private void doPass(Task task, ReqProcessHandlerDTO param) { |
|
|
|
|
|
|
|
|
|
|
|
String projectName = getProjectName(task); |
|
|
Map<String, Object> var = new HashMap<>(16); |
|
|
Map<String, Object> var = new HashMap<>(16); |
|
|
var.put("approve_" + task.getId(), param.getAction()); |
|
|
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 当前任务 |
|
|
* @param task 当前任务 |
|
|
*/ |
|
|
*/ |
|
|
private void doWithDrawProcess(Task 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() |
|
|
List<Execution> executions = runtimeService.createExecutionQuery() |
|
|
.processInstanceId(task.getProcessInstanceId()) |
|
|
.processInstanceId(task.getProcessInstanceId()) |
|
|
.onlyChildExecutions().list(); |
|
|
.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())); |
|
|
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()) |
|
|
.startTime(instance.getStartTime()) |
|
|
.finishTime(instance.getStartTime()) |
|
|
.finishTime(instance.getStartTime()) |
|
|
.taskId("root") |
|
|
.taskId("root") |
|
|
.result(ReqProcessHandlerDTO.Action.pass) |
|
|
|
|
|
|
|
|
.result(ProcessHandlerEnum.PASS) |
|
|
.build()); |
|
|
.build()); |
|
|
// 提取全量表单数据 |
|
|
// 提取全量表单数据 |
|
|
Map<String, Object> formData = formDatas.stream().collect(Collectors.toMap(HistoricVariableInstance::getVariableName, HistoricVariableInstance::getValue)); |
|
|
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())){ |
|
|
if (Objects.isNull(instance.getEndActivityId())){ |
|
|
res.setStatus(ProcessStatusEnum.UNDER_REVIEW.name()); |
|
|
res.setStatus(ProcessStatusEnum.UNDER_REVIEW.name()); |
|
|
} else if (HisProInsEndActId.BACK.equals(instance.getEndActivityId())) { |
|
|
} else if (HisProInsEndActId.BACK.equals(instance.getEndActivityId())) { |
|
|
|
|
|
// TODO 被退回的审核节点状态这里只是暂时这么判断,具体怎么保存这个退回状态,后面讨论 |
|
|
res.setStatus(ProcessStatusEnum.BE_BACKED.name()); |
|
|
res.setStatus(ProcessStatusEnum.BE_BACKED.name()); |
|
|
} else if (HisProInsEndActId.REJECT.equals(instance.getEndActivityId())) { |
|
|
} else if (HisProInsEndActId.REJECT.equals(instance.getEndActivityId())) { |
|
|
res.setStatus(ProcessStatusEnum.BE_REJECTED.name()); |
|
|
res.setStatus(ProcessStatusEnum.BE_REJECTED.name()); |
|
@@ -426,9 +660,9 @@ public class TodoCenterManage { |
|
|
.processInstanceId(instanceId).orderByHistoricActivityInstanceStartTime().asc().list(); |
|
|
.processInstanceId(instanceId).orderByHistoricActivityInstanceStartTime().asc().list(); |
|
|
Set<String> userSet = new HashSet<>(); |
|
|
Set<String> userSet = new HashSet<>(); |
|
|
//获取节点处理结果 |
|
|
//获取节点处理结果 |
|
|
Map<String, ReqProcessHandlerDTO.Action> varMap = historyService.createHistoricVariableInstanceQuery() |
|
|
|
|
|
|
|
|
Map<String, ProcessHandlerEnum> varMap = historyService.createHistoricVariableInstanceQuery() |
|
|
.processInstanceId(instanceId).variableNameLike("approve_%").list().stream() |
|
|
.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 -> { |
|
|
List<ProgressNode> progressNodes = list.stream().filter(his -> ObjectUtil.isNotNull(his.getTaskId())).map(his -> { |
|
|
Object props = nodeProps.get(his.getActivityId()); |
|
|
Object props = nodeProps.get(his.getActivityId()); |
|
|
ApprovalModeEnum approvalMode = null; |
|
|
ApprovalModeEnum approvalMode = null; |
|
|