@@ -111,4 +111,10 @@ public class ConstructionController { | |||
constructionManage.submitXcfhxApply(req); | |||
} | |||
@ApiOperation("信创符合性申请-手动新增的") | |||
@WebLog("信创符合性申请-手动新增的") | |||
@PostMapping("/submitXcfhxApply-manual/{id}") | |||
public String submitXcfhxApplyManual(@PathVariable Long id) { | |||
return constructionManage.submitXcfhxApplyManual(id); | |||
} | |||
} |
@@ -2,11 +2,9 @@ package com.hz.pm.api.projectdeclared.manage; | |||
import cn.hutool.core.bean.BeanUtil; | |||
import cn.hutool.core.collection.CollUtil; | |||
import cn.hutool.core.io.FileUtil; | |||
import cn.hutool.core.io.IoUtil; | |||
import cn.hutool.json.JSONUtil; | |||
import com.alibaba.excel.EasyExcel; | |||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |||
import com.baomidou.mybatisplus.core.toolkit.StringUtils; | |||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | |||
import com.google.common.collect.Lists; | |||
@@ -20,7 +18,6 @@ import com.hz.pm.api.common.util.DecimalUtil; | |||
import com.hz.pm.api.common.util.ExcelDownUtil; | |||
import com.hz.pm.api.common.util.ExcelExportStyle; | |||
import com.hz.pm.api.common.util.StrUtils; | |||
import com.hz.pm.api.external.MhFileClient; | |||
import com.hz.pm.api.projectdeclared.helper.MhXchxFileHelper; | |||
import com.hz.pm.api.projectdeclared.model.dto.DeclaredProjectExportDTO; | |||
import com.hz.pm.api.projectdeclared.model.dto.PaymentPlanSupplementDTO; | |||
@@ -53,30 +50,22 @@ import com.hz.pm.api.user.security.model.UserInfoDetails; | |||
import com.hz.pm.api.user.util.LoginUserUtil; | |||
import com.ningdatech.basic.exception.BizException; | |||
import com.ningdatech.basic.function.VUtils; | |||
import com.ningdatech.basic.model.ApiResponse; | |||
import com.ningdatech.basic.model.PageVo; | |||
import com.ningdatech.basic.util.CollUtils; | |||
import com.ningdatech.basic.util.NdDateUtils; | |||
import com.ningdatech.file.controller.FileController; | |||
import com.ningdatech.file.entity.vo.result.FileResultVO; | |||
import com.ningdatech.file.service.FileService; | |||
import com.wflow.bean.entity.WflowModels; | |||
import com.wflow.workflow.bean.dto.OrgInfoDTO; | |||
import com.wflow.workflow.bean.vo.ProcessStartParamsVo; | |||
import com.wflow.workflow.service.ProcessInstanceService; | |||
import lombok.RequiredArgsConstructor; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.apache.commons.io.IOUtils; | |||
import org.flowable.engine.TaskService; | |||
import org.flowable.task.api.Task; | |||
import org.springframework.beans.BeanUtils; | |||
import org.springframework.mock.web.MockMultipartFile; | |||
import org.springframework.stereotype.Component; | |||
import org.springframework.transaction.annotation.Transactional; | |||
import javax.servlet.http.HttpServletResponse; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.math.BigDecimal; | |||
import java.time.LocalDateTime; | |||
import java.time.format.DateTimeFormatter; | |||
@@ -110,11 +99,12 @@ public class ConstructionManage { | |||
private final IProjectAnnualPaymentPlanService projectPaymentPlanService; | |||
private final TenderStateMachineUtil tenderStateMachineUtil; | |||
private final XcfhxStateMachineUtil xcfhxStateMachineUtil; | |||
private final FileController fileController; | |||
private final MhFileClient mhFileClient; | |||
private final MhXchxFileHelper mhXchxFileHelper; | |||
private final IXinchuangService xinchuangService; | |||
private final TaskService taskService; | |||
/** | |||
* 待采购的-项目列表 | |||
* | |||
@@ -623,6 +613,35 @@ public class ConstructionManage { | |||
purchaseInstService.save(purchaseInst); | |||
} | |||
@Transactional(rollbackFor = Exception.class) | |||
public synchronized String submitXcfhxApplyManual(Long id) { | |||
Xinchuang xinhcuang = xinchuangService.getById(id); | |||
VUtils.isTrue(Objects.isNull(xinhcuang)).throwMessage("信创符合性申请不存在"); | |||
if(StringUtils.isNotBlank(xinhcuang.getInstCode())){ | |||
List<Task> tasks = taskService.createTaskQuery().active() | |||
.processInstanceId(xinhcuang.getInstCode()) | |||
.list(); | |||
VUtils.isTrue(CollUtil.isNotEmpty(tasks)).throwMessage("此信创符合性已经发起过审核 并且还没审核完!"); | |||
} | |||
UserInfoDetails user = LoginUserUtil.loginUserDetail(); | |||
WflowModels model = processModelManage.getWflowModelsNoNull(ProjectProcessType.XC_APPROVAL_PROCESS, | |||
user.getMhUnitId()); | |||
ProcessStartParamsVo processParam = new ProcessStartParamsVo(); | |||
processParam.setUser(declaredProjectHelper.buildUser(user)); | |||
processParam.setProcessUsers(Collections.emptyMap()); | |||
processParam.setFormData(Collections.emptyMap()); | |||
// 获取发起单位 | |||
Map<String, OrgInfoDTO> orgMap = declaredProjectHelper.buildOrgModelMap(user); | |||
String instanceId = processInstanceService.startProcessLs(model, processParam, orgMap); | |||
//保存实例code | |||
xinhcuang.setInstCode(instanceId); | |||
xinhcuang.setStatus(TenderXcfhxApplyStatus.ON_XCFHX_APPLY.getCode()); | |||
xinchuangService.updateById(xinhcuang); | |||
return instanceId; | |||
} | |||
/** | |||
* 补充项目 合同 实际支付信息 | |||
* | |||
@@ -206,6 +206,54 @@ public class DeclaredProjectHelper { | |||
return orgMap; | |||
} | |||
public Map<String, OrgInfoDTO> buildOrgModelMap(UserInfoDetails user) { | |||
Map<String, OrgInfoDTO> orgMap = new HashMap<>(); | |||
// 查出所有的单位流程配置 | |||
List<WflowOrgModels> orgModelsList = orgProcdefService.list(); | |||
String startOrgCode = user.getMhUnitIdStr(); | |||
String startOrgName = user.getMhUnitName(); | |||
String startOrgParentCode = user.getMhUnitIdStr(); | |||
String startOrgParentName = user.getMhUnitName(); | |||
// 如果申报时 上级主管单位,由该单位自己审核 | |||
//查询 当前发起人及主管单位所在区域的 单位流程配置 | |||
OrgInfoDTO startOrgInfoDto = new OrgInfoDTO(); | |||
startOrgInfoDto.setOrganizationCode(startOrgCode); | |||
startOrgInfoDto.setOrganizationName(startOrgName); | |||
startOrgInfoDto.setOrgModelMap(orgModelsList.stream() | |||
.filter(v -> v.getOrgCode().equals(startOrgCode) | |||
&& Boolean.FALSE.equals(v.getIsDelete()) | |||
&& (ProcessDefTypeEnum.SEAL.name().equals(v.getType()) || | |||
ProcessDefTypeEnum.JOINT_REVIEW.name().equals(v.getType()) || | |||
ProcessDefTypeEnum.DEFAULT.name().equals(v.getType()))) | |||
.collect(Collectors.toMap(WflowOrgModels::getType, v -> v))); | |||
OrgInfoDTO parentOrgInfoDto = new OrgInfoDTO(); | |||
parentOrgInfoDto.setOrganizationCode(startOrgParentCode); | |||
parentOrgInfoDto.setOrganizationName(startOrgParentName); | |||
parentOrgInfoDto.setOrgModelMap(orgModelsList.stream() | |||
.filter(v -> v.getOrgCode().equals(startOrgParentCode) | |||
&& Boolean.FALSE.equals(v.getIsDelete()) | |||
&& (ProcessDefTypeEnum.SEAL.name().equals(v.getType()) || | |||
ProcessDefTypeEnum.JOINT_REVIEW.name().equals(v.getType()) || | |||
ProcessDefTypeEnum.DEFAULT.name().equals(v.getType()))) | |||
.collect(Collectors.toMap(WflowOrgModels::getType, v -> v))); | |||
orgMap.put(OrgTypeEnum.TARGET_OWNER.name(), startOrgInfoDto); | |||
orgMap.put(OrgTypeEnum.TARGET_MANAGEMENT.name(), parentOrgInfoDto); | |||
// 如果是指定单位,直接根据流程定义ID放入map | |||
OrgInfoDTO orgInfoDTO = new OrgInfoDTO(); | |||
orgInfoDTO.setOrgModelMap(orgModelsList.stream() | |||
.collect(Collectors.toMap(WflowOrgModels::getProcessDefId, v -> v))); | |||
orgMap.put(OrgTypeEnum.TARGET_LABEL.name(), orgInfoDTO); | |||
orgMap.put(OrgTypeEnum.TARGET_LINE_MANAGEMENT.name(), parentOrgInfoDto); | |||
return orgMap; | |||
} | |||
public Map<String, OrgInfoDTO> buildOrgModelMapUserOrgCode(Project project) { | |||
Map<String, OrgInfoDTO> orgMap = new HashMap<>(); | |||
@@ -68,4 +68,6 @@ public class Xinchuang { | |||
@ApiModelProperty("项目名称") | |||
private String projectName; | |||
@ApiModelProperty("实例code") | |||
private String instCode; | |||
} |
@@ -68,6 +68,9 @@ public class XinchuangVO { | |||
@ApiModelProperty("项目名称") | |||
private String projectName; | |||
@ApiModelProperty("实例code") | |||
private String instCode; | |||
public String getSourceTypeName() { | |||
return PurchaseSourceTypeEnum.desc(this.sourceType); | |||
} | |||
@@ -23,7 +23,7 @@ public enum TenderXcfhxApplyStatus implements IStatus<Integer, String> { | |||
TO_BE_SUBMIT_XCFHX_APPLY(301, "待信创符合性申请"), | |||
ON_XCFHX_APPLY(302, "信创符合性申请中"), | |||
XCFHX_APPLY_FAILED(303, "信创符合性申请不通过"), | |||
XCFHX_APPLY_PASSED(304, "信创符合性申请不通过"); | |||
XCFHX_APPLY_PASSED(304, "信创符合性申请通过"); | |||
private final Integer code; | |||
private final String desc; | |||
@@ -58,6 +58,11 @@ public class TodoCenterController { | |||
return todoCenterManage.todoProjectList(param); | |||
} | |||
@GetMapping("/todo-list-xinchuang") | |||
public PageVo<ResToBeProcessedVO> todoListXinchuang(@Valid @ModelAttribute ToBeProcessedReq param) { | |||
return todoCenterManage.todoXinchuangList(param); | |||
} | |||
/** | |||
* 待办中心-待我处理项目列表导出 | |||
* | |||
@@ -83,6 +88,11 @@ public class TodoCenterController { | |||
return todoCenterManage.getProcessDetail(request); | |||
} | |||
@GetMapping("/progress/xinchuang-detail") | |||
public ProcessProgressDetailVO getProcessXinchuangDetail(@Valid @ModelAttribute ProcessDetailReq request) { | |||
return todoCenterManage.getProcessXinchuangDetail(request); | |||
} | |||
/** | |||
* 审核通过,盖章并通过、退回、撤回、驳回等操作 | |||
* | |||
@@ -95,6 +105,12 @@ public class TodoCenterController { | |||
return todoCenterManage.handler(param); | |||
} | |||
@PostMapping("/handler-xinchuang") | |||
@WebLog("信创审核通过,盖章并通过、退回、撤回、驳回等操作") | |||
public Object handlerXinchuang(@Valid @RequestBody ReqProcessHandlerDTO param) { | |||
return todoCenterManage.handlerXinchuang(param); | |||
} | |||
/** | |||
* 保存盖章审核提交的审核意见 | |||
* | |||
@@ -118,6 +134,11 @@ public class TodoCenterController { | |||
return todoCenterManage.idoList(param); | |||
} | |||
@GetMapping("/ido-list-xinchuang") | |||
public PageVo<ResToBeProcessedVO> idoListXinchuang(@ModelAttribute ToBeProcessedReq param) { | |||
return todoCenterManage.idoListXinchuang(param); | |||
} | |||
/** | |||
* 待办中心-我已处理项目列表导出 | |||
* | |||
@@ -141,6 +162,11 @@ public class TodoCenterController { | |||
return todoCenterManage.mySubmittedList(param); | |||
} | |||
@GetMapping("/my-submitted-xinchuang") | |||
public PageVo<ResToBeProcessedVO> mySubmittedXinchuang(@ModelAttribute ToBeProcessedReq param) { | |||
return todoCenterManage.mySubmittedXinchuang(param); | |||
} | |||
/** | |||
* 待办中心-我发起的项目列表导出 | |||
* | |||
@@ -22,10 +22,12 @@ import com.hz.pm.api.projectdeclared.model.dto.ProjectDraftSaveDTO; | |||
import com.hz.pm.api.projectdeclared.model.entity.ProjectConstructionSuggestions; | |||
import com.hz.pm.api.projectdeclared.model.entity.Purchase; | |||
import com.hz.pm.api.projectdeclared.model.entity.PurchaseInst; | |||
import com.hz.pm.api.projectdeclared.model.entity.Xinchuang; | |||
import com.hz.pm.api.projectdeclared.model.enumerization.ProjectDraftTypeEnum; | |||
import com.hz.pm.api.projectdeclared.service.IConstructionSuggestionsService; | |||
import com.hz.pm.api.projectdeclared.service.IPurchaseInstService; | |||
import com.hz.pm.api.projectdeclared.service.IPurchaseService; | |||
import com.hz.pm.api.projectdeclared.service.IXinchuangService; | |||
import com.hz.pm.api.projectlib.model.dto.ProjectApplicationDTO; | |||
import com.hz.pm.api.projectlib.model.dto.ProjectDTO; | |||
import com.hz.pm.api.projectlib.model.entity.Project; | |||
@@ -34,6 +36,7 @@ import com.hz.pm.api.projectlib.model.entity.ProjectDelayApply; | |||
import com.hz.pm.api.projectlib.model.entity.ProjectInst; | |||
import com.hz.pm.api.projectlib.model.enumeration.InstTypeEnum; | |||
import com.hz.pm.api.projectlib.model.enumeration.status.ProjectStatus; | |||
import com.hz.pm.api.projectlib.model.enumeration.status.TenderXcfhxApplyStatus; | |||
import com.hz.pm.api.projectlib.service.INdProjectDelayApplyService; | |||
import com.hz.pm.api.projectlib.service.IProjectApplicationService; | |||
import com.hz.pm.api.projectlib.service.IProjectInstService; | |||
@@ -104,6 +107,8 @@ public class HandlerManage { | |||
private final XcfhxStateMachineUtil xcfhxStateMachineUtil; | |||
private final WflowHelper wflowHelper; | |||
private final IXinchuangService xinchuangService; | |||
@Value("${spring.profiles.active}") | |||
private String active; | |||
@@ -220,6 +225,54 @@ public class HandlerManage { | |||
} | |||
} | |||
public void afterPassTodo(Xinchuang xinchuang, HistoricProcessInstance instance) { | |||
Long userId = LoginUserUtil.getUserId(); | |||
// 获取流程通过后的流程实例 | |||
HistoricProcessInstance newInstance = historyService.createHistoricProcessInstanceQuery() | |||
.processInstanceId(instance.getId()) | |||
.singleResult(); | |||
// 获取当前流程实例类型 | |||
String instanceId = newInstance.getId(); | |||
// 获取流程通过后当前流程详情 | |||
ProcessProgressVo newInstDetail = processInstanceService.getProgressInstanceDetail(null, instance.getId()); | |||
// 获取流程通过后当前审核人信息,向其发送工作通知 | |||
// 会签/或签会有多个审核人 | |||
Set<String> currUserIdList = Sets.newHashSet(); | |||
List<ProgressNode> newProgressInfo = newInstDetail.getProgressInfo(); | |||
ProgressNode currNode = newProgressInfo.get(newProgressInfo.size() - 1); | |||
// 说明当前节点是子流程节点 | |||
if (currNode.getNodeType().name().equals(NodeTypeEnum.SUB.name())) { | |||
List<ProgressNode> children = currNode.getChildren(); | |||
// 获取子流程当前审核人节点 | |||
ProgressNode subCurrNode = CollUtil.isEmpty(children) ? new ProgressNode() : children.get(children.size() - 1); | |||
// 获取节点ID相同地审核节点 | |||
children.forEach(c -> { | |||
if (subCurrNode.getNodeId().equals(c.getNodeId())) { | |||
currUserIdList.add(c.getUserId()); | |||
} | |||
}); | |||
} else { | |||
newProgressInfo.forEach(w -> { | |||
if (currNode.getNodeId().equals(w.getNodeId())) { | |||
currUserIdList.add(w.getUserId()); | |||
} | |||
}); | |||
} | |||
// 流程通过后,判断当前登录用户是不是最后一个审核人 | |||
// 若当前登录用户是最后一个审批人,需更新流程状态为审核完成,项目状态到下个状态 | |||
// 并向流程发起人发送浙政钉工作通知:【项目名称】已通过【流程名称】,请及时开始下一步操作。 | |||
if (HisProInsEndActId.END.equals(newInstance.getEndActivityId())) { | |||
xinchuangPassedCallback(xinchuang); | |||
} | |||
} | |||
private void xinchuangPassedCallback(Xinchuang xinchuang) { | |||
xinchuang.setStatus(TenderXcfhxApplyStatus.XCFHX_APPLY_PASSED.getCode()); | |||
xinchuangService.updateById(xinchuang); | |||
} | |||
private void purchaseOperationPassedCallback(Long projectId, String instanceId, InstTypeEnum instType) { | |||
PurchaseInst purchaseInst = purchaseInstService.getByProjectIdAndInstCode(projectId, instanceId); | |||
Purchase purchase = purchaseService.getById(purchaseInst.getBidId()); | |||
@@ -401,6 +454,11 @@ public class HandlerManage { | |||
REJECT_MSG_TEMPLATE, MsgTypeEnum.PROJECT_REVIEW_REJECT); | |||
} | |||
public void afterRejectTodo(Xinchuang xinchuang, HistoricProcessInstance hiInst) { | |||
xinchuang.setStatus(TenderXcfhxApplyStatus.XCFHX_APPLY_FAILED.getCode()); | |||
xinchuangService.updateById(xinchuang); | |||
} | |||
/** | |||
* 发起人 撤回逻辑 | |||
*/ | |||
@@ -489,7 +547,6 @@ public class HandlerManage { | |||
BACK_MSG_TEMPLATE, MsgTypeEnum.PROJECT_REVIEW_BACK); | |||
} | |||
/** | |||
* 当为通过操作时,更新项目表中项目状态 | |||
* | |||
@@ -23,7 +23,9 @@ import com.hz.pm.api.common.util.ExcelDownUtil; | |||
import com.hz.pm.api.irs.sign.IRSAPIRequest; | |||
import com.hz.pm.api.projectdeclared.manage.DeclaredProjectHelper; | |||
import com.hz.pm.api.projectdeclared.model.entity.PurchaseInst; | |||
import com.hz.pm.api.projectdeclared.model.entity.Xinchuang; | |||
import com.hz.pm.api.projectdeclared.service.IPurchaseInstService; | |||
import com.hz.pm.api.projectdeclared.service.IXinchuangService; | |||
import com.hz.pm.api.projectlib.manage.ProjectLibManage; | |||
import com.hz.pm.api.projectlib.model.dto.ProjectApplicationDTO; | |||
import com.hz.pm.api.projectlib.model.dto.ProjectDTO; | |||
@@ -144,6 +146,8 @@ public class TodoCenterManage { | |||
private final ITodoService todoService; | |||
private final IPurchaseInstService purchaseInstService; | |||
private final IXinchuangService xinchuangService; | |||
/** | |||
* 待办中心待我处理项目列表查询 | |||
* | |||
@@ -233,6 +237,75 @@ public class TodoCenterManage { | |||
return PageVo.of(resVos, list.size()); | |||
} | |||
public PageVo<ResToBeProcessedVO> todoXinchuangList(ToBeProcessedReq param) { | |||
Long userId = Optional.ofNullable(param.getUserId()).orElseGet(LoginUserUtil::getUserId); | |||
String userIdStr = String.valueOf(userId); | |||
UserFullInfoDTO userFullInfo = userInfoHelper.getUserFullInfo(userId); | |||
// 查出信创信息 | |||
List<Xinchuang> xinchuangs = xinchuangService.list(Wrappers.lambdaQuery(Xinchuang.class) | |||
.isNotNull(Xinchuang::getInstCode)); | |||
if (CollUtil.isEmpty(xinchuangs)) { | |||
return PageVo.empty(); | |||
} | |||
Map<String, Xinchuang> xinchuangMap = CollUtils.listToMap(xinchuangs, Xinchuang::getInstCode); | |||
List<String> instCodes = CollUtils.fieldList(xinchuangs, Xinchuang::getInstCode); | |||
// 查出用户工作流 | |||
TodoCenterListReqDTO req = new TodoCenterListReqDTO(); | |||
req.setInstCodes(instCodes); | |||
Integer pageNumber = param.getPageNumber(); | |||
Integer pageSize = param.getPageSize(); | |||
req.setProcessDefId(param.getProcessDefId()); | |||
req.setEmployeeCode(userIdStr); | |||
//有待办节点的(不包含退回) | |||
List<ProcessTaskVo> todoList = processTaskService.getUserTodoList(req); | |||
//有退回待办的 | |||
List<ProcessTaskVo> backList = processTaskService.getBackTodoList(req); | |||
//合并 并且排序 | |||
List<ProcessTaskVo> list = Stream.concat(todoList.stream(), backList.stream()) | |||
.filter(Objects::nonNull) | |||
.sorted(Comparator.comparing(ProcessTaskVo::getTaskCreateTime).reversed()) | |||
.collect(Collectors.toList()); | |||
if (CollUtil.isEmpty(list)) { | |||
return PageVo.empty(); | |||
} | |||
List<ProcessTaskVo> userTodoList = list.stream() | |||
.skip((long) (pageNumber - 1) * pageSize) | |||
.limit(pageSize) | |||
.collect(Collectors.toList()); | |||
Set<String> processSet = Sets.newHashSet(); | |||
Map<String, ProcessTaskVo> taskMap = userTodoList.stream() | |||
.sorted((t1, t2) -> t2.getTaskCreateTime().compareTo(t1.getTaskCreateTime())) | |||
.collect(Collectors.toList()).stream() | |||
.filter(v -> processSet.add(v.getNodeId())) | |||
.collect(Collectors.toMap(ProcessTaskVo::getNodeId, v -> v)); | |||
List<String> instanceIds = CollUtils.fieldList(userTodoList, ProcessTaskVo::getInstanceId); | |||
List<ResToBeProcessedVO> resVos = userTodoList.stream().map(d -> { | |||
Xinchuang xinchuang = xinchuangMap.get(d.getInstanceId()); | |||
ResToBeProcessedVO res = new ResToBeProcessedVO(); | |||
if(Objects.nonNull(xinchuang)){ | |||
res.setXinchuangId(xinchuang.getId()); | |||
res.setProjectName(xinchuang.getProjectName()); | |||
} | |||
res.setInstCode(d.getInstanceId()); | |||
res.setBuildOrg(userFullInfo.getMhUnitName()); | |||
ProcessTaskVo taskVo = taskMap.get(d.getNodeId()); | |||
res.setNodeId(d.getNodeId()); | |||
res.setProcessStatusName(taskVo.getStatus()); | |||
res.setProcessLaunchTime(d.getTaskCreateTime()); | |||
res.setProcessDefName(d.getProcessDefName()); | |||
res.setTaskId(d.getTaskId()); | |||
res.setNodeName(findSubProcessName(d)); | |||
return res; | |||
}).collect(Collectors.toList()); | |||
return PageVo.of(resVos, list.size()); | |||
} | |||
private String findSubProcessName(ProcessTaskVo d) { | |||
if (StringUtils.isBlank(d.getProcessDefId())) { | |||
return null; | |||
@@ -434,6 +507,113 @@ public class TodoCenterManage { | |||
return "操作成功"; | |||
} | |||
@Transactional(rollbackFor = Exception.class) | |||
public synchronized String handlerXinchuang(ReqProcessHandlerDTO param) { | |||
// 获取登录用户ID | |||
UserInfoDetails user = LoginUserUtil.loginUserDetail(); | |||
// 获取登录用户浙政钉code | |||
String userIdStr = user.getUserIdStr(); | |||
// 获取入参 | |||
String processInstanceId = param.getInstanceId(); | |||
Long xinchuangId = param.getProjectId(); | |||
VUtils.isTrue(Objects.isNull(processInstanceId)).throwMessage("获取流程实例ID失败!"); | |||
VUtils.isTrue(Objects.isNull(xinchuangId)).throwMessage("获取信创ID失败!"); | |||
// 获取当前信创 | |||
Xinchuang xinchuang = xinchuangService.getById(xinchuangId); | |||
VUtils.isTrue(Objects.isNull(xinchuang)).throwMessage("获取信创信息失败!"); | |||
// 获取当前未处理流程详情 | |||
ProcessProgressVo currentInstanceDetail = processInstanceService.getProgressInstanceDetail(null, processInstanceId); | |||
// 获取当前要处理的流程实例 | |||
HistoricProcessInstance instance = historyService.createHistoricProcessInstanceQuery() | |||
.processInstanceId(processInstanceId) | |||
.singleResult(); | |||
//提前判断下 是不是 已经被退回了 | |||
checkIsBack(instance); | |||
//进入处理逻辑 | |||
switch (param.getAction()) { | |||
// 通过 | |||
case PASS: | |||
// 盖章并通过 | |||
case SEAL_PASS: { | |||
//前置判断前端传的taskId是否存在不存在的情况 有可能是 或签被别人审批掉了 | |||
Task task = taskService.createTaskQuery().taskId(param.getTaskId()).active().singleResult(); | |||
if (ObjectUtil.isNull(task)) { | |||
return TodoCenterConst.Handler.TASKID_ERROR; | |||
} | |||
String nodeId = task.getTaskDefinitionKey(); | |||
// 通过该任务,流程到下一审核人处 | |||
processTaskService.handleTask(param, userIdStr); | |||
//通过审核后 所处理的逻辑 | |||
handlerManage.afterPassTodo(xinchuang, instance); | |||
return findNextTaskId(instance, userIdStr, nodeId, param.getTaskId()); | |||
} | |||
// 驳回 | |||
case REJECT: { | |||
//前置判断前端传的taskId是否存在不存在的情况 有可能是 或签被别人审批掉了 | |||
Task task = taskService.createTaskQuery().taskId(param.getTaskId()).active().singleResult(); | |||
if (ObjectUtil.isNull(task)) { | |||
return TodoCenterConst.Handler.TASKID_ERROR; | |||
} | |||
// 驳回该任务,中止流程并使项目进入对应状态,给项目创建人、流程发起人发送浙政钉工作通知: | |||
// 【项目名称】的【流程名称】被驳回,请及时处理。 | |||
processTaskService.handleTask(param, userIdStr); | |||
//驳回审核后 所处理的逻辑 | |||
handlerManage.afterRejectTodo(xinchuang, instance); | |||
} | |||
break; | |||
// 退回 | |||
case BACK: { | |||
//前置判断前端传的taskId是否存在不存在的情况 有可能是 或签被别人审批掉了 | |||
Task task = taskService.createTaskQuery().taskId(param.getTaskId()).active().singleResult(); | |||
if (ObjectUtil.isNull(task)) { | |||
return TodoCenterConst.Handler.TASKID_ERROR; | |||
} | |||
// 退回该任务 | |||
processTaskService.handleTaskLs(param, userIdStr); | |||
} | |||
break; | |||
// 撤回(流程发起人和当前流程审核人的前一个审核人操作) | |||
case WITHDRAW: { | |||
/* | |||
* 新逻辑 | |||
* 不判断前端传的taskId | |||
* 1.先判断 用户是否是ROOT 发起人 并且流程没有开始审批 | |||
*/ | |||
if (withDrawHandle.canRootWithDraw(instance, userIdStr)) { | |||
// 登录用户是流程发起人,且是流程发起人撤回 | |||
processTaskService.rootWithdrawTask(param, userIdStr); | |||
//发起人撤回 | |||
} else { | |||
// 2.如果用户不是ROOT发起人 或者 不满足root撤回 那么必定要判断 他是不是上个节点审批人 或者 当前会签已审批的审批人 | |||
// 这里有个小操作 check的同时 把对应的操作人的taskId 也塞入 | |||
VUtils.isTrue(!withDrawHandle.checkUserIsBefore(currentInstanceDetail.getProgressInfo(), param)) | |||
.throwMessage("当前登录用户不是发起人,也不是上一个节点审批人或者当前会签已批审批人 无法进行撤回操作!"); | |||
//前置判断前端传的taskId是否存在不存在的情况 有可能是 或签被别人审批掉了 | |||
HistoricTaskInstance taskInst = historyService.createHistoricTaskInstanceQuery().taskId(param.getTaskId()).finished().singleResult(); | |||
if (ObjectUtil.isNull(taskInst)) { | |||
return TodoCenterConst.Handler.TASKID_ERROR; | |||
} | |||
String nodeId = taskInst.getTaskDefinitionKey(); | |||
//上个审批人处理逻辑 | |||
processTaskService.lastWithdrawTask(param); | |||
return findNextTaskId(instance, userIdStr, nodeId, param.getTaskId()); | |||
} | |||
} | |||
break; | |||
default: | |||
throw new IllegalStateException("Unexpected value: " + param.getAction()); | |||
} | |||
return "操作成功"; | |||
} | |||
private void checkIsBack(HistoricProcessInstance instance) { | |||
VUtils.isTrue(Objects.nonNull(instance.getBusinessStatus()) && | |||
HisProInsEndActId.BACK.equals(instance.getBusinessStatus())) | |||
@@ -573,6 +753,38 @@ public class TodoCenterManage { | |||
return res; | |||
} | |||
public ProcessProgressDetailVO getProcessXinchuangDetail(ProcessDetailReq request) { | |||
String employeeCode = LoginUserUtil.loginUserDetail().getEmployeeCode(); | |||
String instanceId = request.getInstanceId(); | |||
String nodeId = request.getNodeId(); | |||
Long xinchuangId = request.getXinchuangId(); | |||
String taskId = request.getTaskId(); | |||
ProcessProgressVo progressInstanceDetail = processInstanceService.getProgressInstanceDetail(nodeId, instanceId, taskId); | |||
Xinchuang xinchuang = xinchuangService.getById(xinchuangId); | |||
if (Objects.isNull(xinchuang)) { | |||
return null; | |||
} | |||
List<ProgressNode> progressInfo = progressInstanceDetail.getProgressInfo(); | |||
Boolean isHighLine = Boolean.FALSE; | |||
if (CollUtil.isNotEmpty(progressInfo)) { | |||
buildUserUtils.buildUserByProcessInfo(progressInfo); | |||
isHighLine = checkHighLine(progressInfo, taskId, LoginUserUtil.loginUserDetail()); | |||
} | |||
ProcessProgressDetailVO res = new ProcessProgressDetailVO(); | |||
res.setProcessProgressVo(progressInstanceDetail); | |||
res.setStatus(progressInstanceDetail.getStatus()); | |||
res.setCanWithdraw(withDrawHandle.checkCanWithdraw(instanceId, progressInstanceDetail, request.getTaskId())); | |||
res.setIsHighLine(isHighLine); | |||
res.setConstructionSuggestions(checkConstructionSuggestionsByNodeId(taskId)); | |||
res.setXinchuangId(xinchuang.getId()); | |||
passHandle.checkCanPassOrSeal(request.getInstanceId(), request.getTaskId(), employeeCode, res); | |||
//是不是被 驳回|退回 | |||
res.setIsChange(todoService.isChangeRecordXinchuang(xinchuangId)); | |||
return res; | |||
} | |||
private Boolean checkConstructionSuggestionsByNodeId(String taskId) { | |||
if (StringUtils.isNotBlank(taskId)) { | |||
List<Task> tasks = taskService.createTaskQuery() | |||
@@ -702,6 +914,60 @@ public class TodoCenterManage { | |||
return PageVo.of(resVos, iDoList.size()); | |||
} | |||
public PageVo<ResToBeProcessedVO> idoListXinchuang(ToBeProcessedReq param) { | |||
// 获取登录用户ID | |||
Long userId = LoginUserUtil.getUserId(); | |||
// 获取登录用户浙政钉code | |||
String userIdStr = String.valueOf(userId); | |||
UserFullInfoDTO userFullInfo = userInfoHelper.getUserFullInfo(userId); | |||
// 查出信创信息 | |||
List<Xinchuang> xinchuangs = xinchuangService.list(Wrappers.lambdaQuery(Xinchuang.class) | |||
.isNotNull(Xinchuang::getInstCode)); | |||
if (xinchuangs.isEmpty()) { | |||
return PageVo.empty(); | |||
} | |||
Map<String, Xinchuang> xinchuangMap = CollUtils.listToMap(xinchuangs, Xinchuang::getInstCode, v -> v); | |||
List<String> instCodes = CollUtils.fieldList(xinchuangs, Xinchuang::getInstCode); | |||
// 查出用户工作流 | |||
TodoCenterListReqDTO req = new TodoCenterListReqDTO(); | |||
Integer pageNumber = param.getPageNumber(); | |||
Integer pageSize = param.getPageSize(); | |||
req.setProcessDefId(param.getProcessDefId()); | |||
req.setUserId(userIdStr); | |||
req.setEmployeeCode(userIdStr); | |||
req.setInstCodes(instCodes); | |||
List<ProcessTaskVo> iDoList = processTaskService.getUserIdoList(req); | |||
if (CollUtil.isEmpty(iDoList)) { | |||
return PageVo.empty(); | |||
} | |||
List<ProcessTaskVo> userIdoList = iDoList.stream() | |||
.skip((long) (pageNumber - 1) * pageSize) | |||
.limit(pageSize) | |||
.collect(Collectors.toList()); | |||
List<ResToBeProcessedVO> resVos = userIdoList.stream().map(d -> { | |||
ResToBeProcessedVO res = new ResToBeProcessedVO(); | |||
Xinchuang xinchuang = xinchuangMap.get(d.getInstanceId()); | |||
if(Objects.nonNull(xinchuang)){ | |||
res.setXinchuangId(xinchuang.getId()); | |||
res.setProjectName(xinchuang.getProjectName()); | |||
} | |||
res.setInstCode(d.getInstanceId()); | |||
res.setBuildOrg(userFullInfo.getMhUnitName()); | |||
res.setProcessStatusName(d.getStatus()); | |||
res.setProcessLaunchTime(d.getCreateTime()); | |||
res.setProcessHandleTime(d.getTaskEndTime()); | |||
res.setTaskId(d.getTaskId()); | |||
res.setNodeName(findSubProcessName(d)); | |||
return res; | |||
}).collect(Collectors.toList()); | |||
return PageVo.of(resVos, iDoList.size()); | |||
} | |||
/** | |||
* 导出我已处理项目列表 | |||
* | |||
@@ -844,6 +1110,58 @@ public class TodoCenterManage { | |||
return PageVo.of(resVos, submittedList.size()); | |||
} | |||
public PageVo<ResToBeProcessedVO> mySubmittedXinchuang(ToBeProcessedReq param) { | |||
// 获取登录用户ID | |||
Long userId = LoginUserUtil.getUserId(); | |||
// 获取登录用户浙政钉code | |||
String userIdStr = String.valueOf(userId); | |||
UserFullInfoDTO userFullInfo = userInfoHelper.getUserFullInfo(userId); | |||
// 查出信创 | |||
List<Xinchuang> xinchuangs = xinchuangService.list(Wrappers.lambdaQuery(Xinchuang.class) | |||
.isNotNull(Xinchuang::getInstCode)); | |||
if (CollUtil.isEmpty(xinchuangs)) { | |||
return PageVo.empty(); | |||
} | |||
Map<String, Xinchuang> xinchuangMap = CollUtils.listToMap(xinchuangs, Xinchuang::getInstCode, v -> v); | |||
List<String> instCodes = CollUtils.fieldList(xinchuangs,Xinchuang::getInstCode); | |||
// 查出用户工作流 | |||
TodoCenterListReqDTO req = new TodoCenterListReqDTO(); | |||
Integer pageNumber = param.getPageNumber(); | |||
Integer pageSize = param.getPageSize(); | |||
req.setProcessDefId(param.getProcessDefId()); | |||
req.setUserId(userIdStr); | |||
req.setEmployeeCode(userIdStr); | |||
req.setInstCodes(instCodes); | |||
List<ProcessInstanceVo> submittedList = processInstanceService.getUserSubmittedList(req); | |||
if (CollUtil.isEmpty(submittedList)) { | |||
return PageVo.empty(); | |||
} | |||
List<ProcessInstanceVo> userSubmittedList = submittedList.stream() | |||
.skip((long) (pageNumber - 1) * pageSize) | |||
.limit(pageSize) | |||
.collect(Collectors.toList()); | |||
List<ResToBeProcessedVO> resVos = userSubmittedList.stream().map(d -> { | |||
ResToBeProcessedVO res = new ResToBeProcessedVO(); | |||
Xinchuang xinchuang = xinchuangMap.get(d.getInstanceId()); | |||
if(Objects.nonNull(xinchuang)){ | |||
res.setXinchuangId(xinchuang.getId()); | |||
res.setProjectName(xinchuang.getProjectName()); | |||
} | |||
res.setInstCode(d.getInstanceId()); | |||
res.setBuildOrg(userFullInfo.getMhUnitName()); | |||
res.setProcessStatusName(d.getStatus()); | |||
res.setProcessLaunchTime(d.getStartTime()); | |||
return res; | |||
}).collect(Collectors.toList()); | |||
return PageVo.of(resVos, submittedList.size()); | |||
} | |||
/** | |||
* 待办中心-我发起的项目列表导出 | |||
* | |||
@@ -28,6 +28,9 @@ public class ProcessDetailReq { | |||
@ApiModelProperty("项目ID") | |||
private Long projectId; | |||
@ApiModelProperty("信创id") | |||
private Long xinchuangId; | |||
@ApiModelProperty("任务ID") | |||
private String taskId; | |||
} |
@@ -36,6 +36,16 @@ public class ProcessProgressDetailVO { | |||
private String projectCode; | |||
/** | |||
* 信创ID | |||
*/ | |||
private Long xinchuangId; | |||
/** | |||
* 信创系统名 | |||
*/ | |||
private String bidName; | |||
/** | |||
* 能否撤回 | |||
*/ | |||
private Boolean canWithdraw = Boolean.FALSE; | |||
@@ -36,6 +36,9 @@ public class ResToBeProcessedVO implements Serializable { | |||
@ApiModelProperty("任务ID") | |||
private String taskId; | |||
@ApiModelProperty("信创ID") | |||
private Long xinchuangId; | |||
@ApiModelProperty("项目名称") | |||
private String projectName; | |||
@@ -18,4 +18,6 @@ public interface ITodoService { | |||
ProcessProgressDetailVO getProcessDetail(ProcessDetailReq request) ; | |||
boolean isChangeRecord(Long projectId) ; | |||
boolean isChangeRecordXinchuang(Long xinchuangId) ; | |||
} |
@@ -3,6 +3,8 @@ package com.hz.pm.api.todocenter.service.impl; | |||
import cn.hutool.core.collection.CollUtil; | |||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
import com.hz.pm.api.common.helper.UserInfoHelper; | |||
import com.hz.pm.api.projectdeclared.model.entity.Xinchuang; | |||
import com.hz.pm.api.projectdeclared.service.IXinchuangService; | |||
import com.hz.pm.api.projectlib.model.entity.Project; | |||
import com.hz.pm.api.projectlib.model.entity.ProjectInst; | |||
import com.hz.pm.api.projectlib.service.IProjectInstService; | |||
@@ -25,6 +27,8 @@ import com.wflow.workflow.service.ProcessInstanceService; | |||
import lombok.AllArgsConstructor; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.apache.commons.lang3.StringUtils; | |||
import org.flowable.engine.HistoryService; | |||
import org.flowable.engine.history.HistoricProcessInstance; | |||
import org.springframework.stereotype.Service; | |||
import java.util.List; | |||
@@ -51,6 +55,10 @@ public class TodoServiceImpl implements ITodoService { | |||
private final IProjectService projectService; | |||
private final IProjectInstService projectInstService; | |||
private final IXinchuangService xinchuangService; | |||
private final HistoryService historyService; | |||
/** | |||
* 查询流程表单数据及审批的进度步骤 | |||
* | |||
@@ -159,4 +167,24 @@ public class TodoServiceImpl implements ITodoService { | |||
return Boolean.TRUE; | |||
} | |||
@Override | |||
public boolean isChangeRecordXinchuang(Long xinchuangId) { | |||
//1.先判断下 信创存不存在 | |||
Xinchuang xinchuang = xinchuangService.getById(xinchuangId); | |||
if (Objects.isNull(xinchuang) || StringUtils.isBlank(xinchuang.getInstCode())) { | |||
return Boolean.FALSE; | |||
} | |||
String instCode = xinchuang.getInstCode(); | |||
HistoricProcessInstance instance = historyService.createHistoricProcessInstanceQuery() | |||
.processInstanceId(instCode) | |||
.singleResult(); | |||
if(StringUtils.isNotBlank(instance.getEndActivityId()) && | |||
"refuse-end".equals(instance.getEndActivityId())){ | |||
return Boolean.TRUE; | |||
} | |||
return Boolean.FALSE; | |||
} | |||
} |