Browse Source

Merge remote-tracking branch 'origin/master'

tags/24080901
PoffyZhang 1 year ago
parent
commit
123521dc79
34 changed files with 1149 additions and 429 deletions
  1. +1
    -1
      ningda-generator/src/main/java/com/ningdatech/generator/config/GeneratorCodeKingbaseConfig.java
  2. +14
    -10
      pmapi/src/main/java/com/ningdatech/pmapi/common/constant/CommonConstant.java
  3. +8
    -1
      pmapi/src/main/java/com/ningdatech/pmapi/common/enumeration/ExportOptionEnum.java
  4. +14
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/common/statemachine/util/StateMachineUtils.java
  5. +1
    -3
      pmapi/src/main/java/com/ningdatech/pmapi/common/util/ExcelDownUtil.java
  6. +7
    -7
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/controller/AnnualPlanController.java
  7. +14
    -4
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/controller/ProjectLibController.java
  8. +11
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/enumeration/StepStatusEnum.java
  9. +30
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handle/AbstractProcessBusinessHandle.java
  10. +100
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handle/AnnualPlanHandle.java
  11. +59
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handle/ArchivedHandle.java
  12. +82
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handle/ConstructionPlanReviewHandle.java
  13. +27
    -17
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handle/DeptUnitedReviewHandle.java
  14. +79
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handle/PreliminaryPreviewHandle.java
  15. +43
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handle/ProcessExecuteChainHandle.java
  16. +114
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handle/ProjectApprovalHandle.java
  17. +13
    -14
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handle/ProjectDeclareHandle.java
  18. +82
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handle/ProjectFinalInspectionHandle.java
  19. +82
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handle/ProjectPreliminaryInspectionHandle.java
  20. +86
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handle/TenderPurchaseHandle.java
  21. +25
    -15
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handle/UnitInnerAuditHandle.java
  22. +0
    -43
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handler/AbstractProcessBusinessHandler.java
  23. +51
    -5
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/manage/AnnualPlanLibManage.java
  24. +38
    -8
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/manage/ProjectLibManage.java
  25. +16
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/mapper/NdProjectStatusChangeMapper.java
  26. +5
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/mapper/NdProjectStatusChangeMapper.xml
  27. +95
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/model/entity/NdProjectStatusChange.java
  28. +8
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/model/req/ProjectListReq.java
  29. +3
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/model/vo/ProcessDetailVO.java
  30. +16
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/service/INdProjectStatusChangeService.java
  31. +20
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/service/impl/NdProjectStatusChangeServiceImpl.java
  32. +0
    -191
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/extension/cmd/BackToHisApprovalNodeCmd.java
  33. +0
    -105
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/extension/cmd/SaveCommentCmd.java
  34. +5
    -5
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/manage/TodoCenterManage.java

+ 1
- 1
ningda-generator/src/main/java/com/ningdatech/generator/config/GeneratorCodeKingbaseConfig.java View File

@@ -17,7 +17,7 @@ public class GeneratorCodeKingbaseConfig {
private static final String PATH_YYD = "/Users/wendy/code project/java/project-management/pmapi/src/main/java";
private static final String PATH_LS = "";
private static final String PATH_ZPF = "D:\\ningda\\project-management\\pmapi\\src\\main\\java";
private static final String PATH_CMM = "";
private static final String PATH_CMM = "D:\\work\\project-management\\project-management\\pmapi\\src\\main\\java";

private static final String URL = "jdbc:kingbase8://120.26.44.207:54321/nd_project_management?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8";
private static final String USER_NAME = "SYSTEM";


+ 14
- 10
pmapi/src/main/java/com/ningdatech/pmapi/common/constant/CommonConstant.java View File

@@ -18,15 +18,19 @@ public class CommonConstant {
public static final Integer SUB_COMMENT_SIZE_MIN = 0;
public static final Integer SUB_COMMENT_SIZE_MAX = 160;

public static final String PROJECT_DECLARE_PREFIX = "projectDeclare";
public static final String UNIT_INNER_AUDIT_PREFIX = "unitInnerAudit";
public static final String PRELIMINARY_PREVIEW_PREFIX = "preliminaryPreview";
public static final String DEPT_UNITED_REVIEW_PREFIX = "deptUnitedReview";
public static final String ANNUAL_PLAN_PREFIX = "annualPlan";
public static final String CONSTRUCTION_PLAN_REVIEW_PREFIX = "constructionPlanReview";
public static final String PROJECT_APPROVAL_PREFIX = "projectApproval";
public static final String TENDER_PURCHASE_PREFIX = "tenderPurchase";
public static final String PROJECT_PRELIMINARY_INSPECTION_PREFIX = "projectPreliminaryInspection";
public static final String PROJECT_FINAL_INSPECTION_PREFIX = "projectFinalInspection";
public static final String PROJECT_DECLARE = "项目申报";
public static final String UNIT_INNER_AUDIT = "单位内部审核";
public static final String PRELIMINARY_PREVIEW = "项目预审";
public static final String DEPT_UNITED_REVIEW = "部门联审";
public static final String ANNUAL_PLAN = "年度计划";
public static final String CONSTRUCTION_PLAN_REVIEW = "建设方案评审";
public static final String PROJECT_APPROVAL = "立项批复";
public static final String TENDER_PURCHASE = "招标采购";
public static final String PROJECT_PRELIMINARY_INSPECTION = "项目初验";
public static final String PROJECT_FINAL_INSPECTION = "项目终验";

public static final String ARCHIVED = "归档";



}

+ 8
- 1
pmapi/src/main/java/com/ningdatech/pmapi/common/enumeration/ExportOptionEnum.java View File

@@ -143,7 +143,14 @@ public enum ExportOptionEnum {
projectRemarks(59, "备注"),
processStatusName(60, "流程状态名称"),
processLaunchTime(61,"流程发起时间"),
processHandleTime(62,"流程处理时间");
processHandleTime(62,"流程处理时间"),

projectStatusName(63,"项目状态名称"),

createOn(64,"创建时间"),

updateOn(65,"更新时间");


private Integer code;
private String desc;


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

@@ -6,7 +6,9 @@ import com.ningdatech.pmapi.common.constant.StateMachineConstants;
import com.ningdatech.pmapi.common.statemachine.builder.ProjectDeclareStateMachineBuilder;
import com.ningdatech.pmapi.common.statemachine.event.ProjectStatusChangeEvent;
import com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum;
import com.ningdatech.pmapi.projectlib.model.entity.NdProjectStatusChange;
import com.ningdatech.pmapi.projectlib.model.entity.Project;
import com.ningdatech.pmapi.projectlib.service.INdProjectStatusChangeService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.messaging.Message;
@@ -16,6 +18,7 @@ import org.springframework.statemachine.persist.StateMachinePersister;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Objects;

/**
@@ -33,17 +36,28 @@ public class StateMachineUtils {

private final ProjectDeclareStateMachineBuilder projectDeclareStateMachineBuilder;

private final INdProjectStatusChangeService projectStatusChangeService;

@Resource(name = "projectDeclareStateMachinePersister")
private StateMachinePersister projectDeclareStateMachinePersister;

public void execute(Project project, ProjectStatusChangeEvent event) throws Exception {
log.info("调用状态机前的项目状态为>>>>>>>>>>{}" + project.getStatus());
// 将状态变更记录保存到项目状态变更表中
NdProjectStatusChange projectStatusChange = new NdProjectStatusChange();
projectStatusChange.setBeforeStatus(project.getStatus());
//获取TO状态机
StateMachine<ProjectStatusEnum, ProjectStatusChangeEvent> stateMachine = projectDeclareStateMachineBuilder.build();
Message message = MessageBuilder.withPayload(event).setHeader(PROJECT_DECLARE, project).build();
//初始化状态机
projectDeclareStateMachinePersister.restore(stateMachine, project);
stateMachine.sendEvent(message);
projectStatusChange.setProjectId(project.getId());
projectStatusChange.setAfterStatus(project.getStatus());
projectStatusChange.setEvent(event.name());
projectStatusChange.setCreateOn(LocalDateTime.now());
// 插入项目状态变更表中
projectStatusChangeService.save(projectStatusChange);
log.info("调用状态机后的项目状态为>>>>>>>>>>{}" + project.getStatus());
}



+ 1
- 3
pmapi/src/main/java/com/ningdatech/pmapi/common/util/ExcelDownUtil.java View File

@@ -140,12 +140,10 @@ public class ExcelDownUtil {
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encodeName(fileName) + ".xls");
}

public static List<List<String>> getExportDatas(ToBeProcessedExportReq param, List<Project> projects) {
public static List<List<String>> getExportDatas(List<ExportOptionEnum> columnList, List<Project> projects) {

// 表体行数据集合
List<List<String>> rowList = Lists.newArrayList();
// 表体列数据集合
List<ExportOptionEnum> columnList = param.getExportOptionList();
for (ExportOptionEnum column : columnList) {
List<String> columnValues = Lists.newArrayList();
columnValues.add(column.getDesc());


+ 7
- 7
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/controller/AnnualPlanController.java View File

@@ -12,6 +12,7 @@ import com.ningdatech.pmapi.projectlib.model.vo.AnnualPlanListItemVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

@@ -27,7 +28,7 @@ import javax.validation.Valid;
* @since 14:07 2023/2/11
*/
@RestController
@AllArgsConstructor
@RequiredArgsConstructor
@Api(tags = "年度计划库")
@RequestMapping("/api/v1/annualPlan")
public class AnnualPlanController {
@@ -68,17 +69,16 @@ public class AnnualPlanController {
annualPlanLibManage.importAnnualPlan(file);
}

@GetMapping("/exportAnnualPlanEditTable")
@ApiOperation("导出年度计划编辑表")
public void exportAnnualPlanEditTable(HttpServletResponse response) {
annualPlanLibManage.exportAnnualPlanEditTable(response);
}

@GetMapping("/modify")
@ApiOperation("年度计划编辑")
@WebLog("年度计划编辑")
public void modify(@RequestBody ProjectDTO req) {
annualPlanLibManage.updateAnnualPlan(req);
}
@PostMapping("/exportList")
@ApiOperation("项目库【列表|编辑表】导出")
public void exportList(@Valid @RequestBody ProjectListReq param, HttpServletResponse response){
annualPlanLibManage.exportList(param,response);
}

}

+ 14
- 4
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/controller/ProjectLibController.java View File

@@ -8,11 +8,16 @@ import com.ningdatech.pmapi.projectlib.model.req.ProjectListReq;
import com.ningdatech.pmapi.projectlib.model.vo.ProcessDetailVO;
import com.ningdatech.pmapi.projectlib.model.vo.ProjectDetailVO;
import com.ningdatech.pmapi.projectlib.model.vo.ProjectLibListItemVO;
import com.ningdatech.pmapi.todocenter.model.dto.req.ToBeProcessedExportReq;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.List;

/**
* <p>
* ProjectLibController
@@ -41,10 +46,15 @@ public class ProjectLibController {
return projectLibManage.getProjectDetail(id);
}

@GetMapping("/totalProcessDetail/{projectId}")
@ApiOperation("获取流程当前进度")
private ProcessDetailVO totalProcessDetail(@PathVariable Long projectId){
return projectLibManage.totalProcessDetail(projectId);
@GetMapping("/processSchedule/{projectId}")
@ApiOperation("项目库申报项目当前进度详情")
private List<ProcessDetailVO> processScheduleDetail(@PathVariable("projectId") Long projectId){
return projectLibManage.processScheduleDetail(projectId);
}

@PostMapping("/exportList")
@ApiOperation("项目库列表导出")
private void exportList(@Valid @RequestBody ProjectListReq param, HttpServletResponse response){
projectLibManage.exportList(param,response);
}
}

+ 11
- 0
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/enumeration/StepStatusEnum.java View File

@@ -1,10 +1,13 @@
package com.ningdatech.pmapi.projectlib.enumeration;

import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Getter
@@ -38,4 +41,12 @@ public enum StepStatusEnum {
}
return StringUtils.EMPTY;
}

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

public static boolean contains (StepStatusEnum e, List<StepStatusEnum> enums){
return enums.contains(e);
}
}

+ 30
- 0
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handle/AbstractProcessBusinessHandle.java View File

@@ -0,0 +1,30 @@
package com.ningdatech.pmapi.projectlib.handle;

import com.ningdatech.pmapi.projectlib.model.vo.ProcessDetailVO;

import java.util.List;

/**
* 流程业务抽象处理类
*
* @author CMM
* @since 2023/02/24 14:22
*/

public abstract class AbstractProcessBusinessHandle {
/**
* 构造,子类必须实现
*/
public AbstractProcessBusinessHandle(){}

/**
* 抽象的,所有具体处理者应该实现的处理逻辑
* @param projectId
* @param processSchedule
* @return void
* @author CMM
* @since 2023/02/27 9:01
*/
abstract void businessHandle(Long projectId, List<ProcessDetailVO> processSchedule);

}

+ 100
- 0
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handle/AnnualPlanHandle.java View File

@@ -0,0 +1,100 @@
package com.ningdatech.pmapi.projectlib.handle;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ningdatech.basic.model.PageVo;
import com.ningdatech.pmapi.common.statemachine.event.ProjectStatusChangeEvent;
import com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum;
import com.ningdatech.pmapi.projectlib.manage.AnnualPlanLibManage;
import com.ningdatech.pmapi.projectlib.model.entity.NdProjectStatusChange;
import com.ningdatech.pmapi.projectlib.model.entity.Project;
import com.ningdatech.pmapi.projectlib.model.req.ProjectListReq;
import com.ningdatech.pmapi.projectlib.model.vo.AnnualPlanListItemVO;
import com.ningdatech.pmapi.projectlib.service.INdProjectStatusChangeService;
import com.ningdatech.pmapi.projectlib.service.IProjectService;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import com.ningdatech.pmapi.common.constant.CommonConstant;
import com.ningdatech.pmapi.projectlib.enumeration.StepStatusEnum;
import com.ningdatech.pmapi.projectlib.model.vo.ProcessDetailVO;

/**
* 年度计划处理
*
* @author CMM
* @since 2023/02/24 14:35
*/
@Order(5)
@Component
public class AnnualPlanHandle extends AbstractProcessBusinessHandle {
private final AnnualPlanLibManage annualPlanLibManage;
private final INdProjectStatusChangeService projectStatusChangeService;

public AnnualPlanHandle(AnnualPlanLibManage annualPlanLibManage, INdProjectStatusChangeService projectStatusChangeService){
this.annualPlanLibManage = annualPlanLibManage;
this.projectStatusChangeService = projectStatusChangeService;
}

@Override
void businessHandle(Long projectId, List<ProcessDetailVO> processSchedule) {
ProcessDetailVO processDetailVO = new ProcessDetailVO();
// 根据年度计划库列表是否包含该项目以及是否开启方案申报判断年度计划是否开始
ProjectListReq req = new ProjectListReq();
PageVo<AnnualPlanListItemVO> planLibList = annualPlanLibManage.annulPlanLibList(req);
Collection<AnnualPlanListItemVO> records = planLibList.getRecords();
Map<Long, AnnualPlanListItemVO> itemVOMap = records.stream()
.collect(Collectors.toMap(AnnualPlanListItemVO::getProjectId, v -> v));
AnnualPlanListItemVO itemVO = itemVOMap.get(projectId);
// 年度计划库中不包含当前项目
if (Objects.isNull(itemVO)){
processDetailVO.setStepStatus(StepStatusEnum.NOT_START);
processDetailVO.setProcessName(CommonConstant.ANNUAL_PLAN);
processSchedule.add(processDetailVO);
return;
}
Boolean isStartDeclaredProject = itemVO.getIsStartDeclaredProject();
// 年度计划库中包含当前项目但未开启方案申报
if (Boolean.FALSE.equals(isStartDeclaredProject)) {
processDetailVO.setStepStatus(StepStatusEnum.NOT_START);
processDetailVO.setProcessName(CommonConstant.ANNUAL_PLAN);
processSchedule.add(processDetailVO);
return;
}
// 年度计划库包含当前项目且开启了方案申报
Integer status = itemVO.getStatus();
if (ProjectStatusEnum.IN_THE_ANNUAL_PLAN.getCode().equals(status)){
// 根据部门联审通过的时间获取
NdProjectStatusChange projectStatusChange = projectStatusChangeService.getOne(Wrappers.lambdaQuery(NdProjectStatusChange.class)
.eq(NdProjectStatusChange::getProjectId, projectId)
.eq(NdProjectStatusChange::getEvent, ProjectStatusChangeEvent.DEPARTMENT_UNITED_REVIEW_PASS.name())
.last("limit 1"));
processDetailVO.setFinishTime(projectStatusChange.getCreateOn());
processDetailVO.setStepStatus(StepStatusEnum.ON_GOING);

} else if (ProjectStatusEnum.BE_SUSPENDED.getCode().equals(status)) {
// 根据年度计划暂缓的时间获取
NdProjectStatusChange projectStatusChange = projectStatusChangeService.getOne(Wrappers.lambdaQuery(NdProjectStatusChange.class)
.eq(NdProjectStatusChange::getProjectId, projectId)
.eq(NdProjectStatusChange::getEvent, ProjectStatusChangeEvent.ANNUAL_PLAN_SUSPEND.name())
.last("limit 1"));
processDetailVO.setFinishTime(projectStatusChange.getCreateOn());
processDetailVO.setStepStatus(StepStatusEnum.REJECTED);
} else {
// 根据开启方案申报的时间获取
NdProjectStatusChange projectStatusChange = projectStatusChangeService.getOne(Wrappers.lambdaQuery(NdProjectStatusChange.class)
.eq(NdProjectStatusChange::getProjectId, projectId)
.eq(NdProjectStatusChange::getEvent, ProjectStatusChangeEvent.ANNUAL_PLAN_PROJECT_OPEN_PLAN_DECLARE.name())
.last("limit 1"));
processDetailVO.setFinishTime(projectStatusChange.getCreateOn());
processDetailVO.setStepStatus(StepStatusEnum.COMPLETED);
}
processDetailVO.setProcessName(CommonConstant.ANNUAL_PLAN);
processSchedule.add(processDetailVO);
}
}

+ 59
- 0
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handle/ArchivedHandle.java View File

@@ -0,0 +1,59 @@
package com.ningdatech.pmapi.projectlib.handle;


import java.util.List;
import com.ningdatech.pmapi.projectlib.model.entity.Project;
import com.ningdatech.pmapi.projectlib.service.IProjectService;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ningdatech.pmapi.common.constant.CommonConstant;
import com.ningdatech.pmapi.common.statemachine.event.ProjectStatusChangeEvent;
import com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum;
import com.ningdatech.pmapi.projectlib.enumeration.StepStatusEnum;
import com.ningdatech.pmapi.projectlib.model.entity.NdProjectStatusChange;
import com.ningdatech.pmapi.projectlib.model.vo.ProcessDetailVO;
import com.ningdatech.pmapi.projectlib.service.INdProjectStatusChangeService;

/**
* 归档处理
*
* @author CMM
* @since 2023/02/24 14:35
*/
@Order(11)
@Component
public class ArchivedHandle extends AbstractProcessBusinessHandle {
private final IProjectService projectService;
private final INdProjectStatusChangeService projectStatusChangeService;

public ArchivedHandle( IProjectService projectService, INdProjectStatusChangeService projectStatusChangeService){
this.projectService = projectService;
this.projectStatusChangeService = projectStatusChangeService;
}

@Override
void businessHandle(Long projectId, List<ProcessDetailVO> processSchedule) {
ProcessDetailVO processDetailVO = new ProcessDetailVO();
Project project = projectService.getById(projectId);
Integer status = project.getStage();
// 根据项目阶段判断是否已归档
// 项目阶段不为已归档
if (!ProjectStatusEnum.ARCHIVED.getCode().equals(status)){
processDetailVO.setStepStatus(StepStatusEnum.NOT_START);
processDetailVO.setProcessName(CommonConstant.ARCHIVED);
processSchedule.add(processDetailVO);
return;
}
// 项目阶段为已归档
processDetailVO.setStepStatus(StepStatusEnum.COMPLETED);
// 根据项目终验获取归档时间
NdProjectStatusChange projectStatusChange = projectStatusChangeService.getOne(Wrappers.lambdaQuery(NdProjectStatusChange.class)
.eq(NdProjectStatusChange::getProjectId, projectId)
.eq(NdProjectStatusChange::getEvent, ProjectStatusChangeEvent.FINAL_ACCEPTANCE_PASS.name())
.last("limit 1"));
processDetailVO.setFinishTime(projectStatusChange.getCreateOn());
processDetailVO.setProcessName(CommonConstant.ARCHIVED);
processSchedule.add(processDetailVO);
}
}

+ 82
- 0
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handle/ConstructionPlanReviewHandle.java View File

@@ -0,0 +1,82 @@
package com.ningdatech.pmapi.projectlib.handle;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

import com.google.common.collect.Lists;
import com.ningdatech.basic.util.NdDateUtils;
import com.wflow.workflow.bean.process.ProgressNode;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ningdatech.pmapi.common.constant.CommonConstant;
import com.ningdatech.pmapi.projectlib.enumeration.InstTypeEnum;
import com.ningdatech.pmapi.projectlib.enumeration.StepStatusEnum;
import com.ningdatech.pmapi.projectlib.model.entity.ProjectInst;
import com.ningdatech.pmapi.projectlib.model.vo.ProcessDetailVO;
import com.ningdatech.pmapi.projectlib.service.IProjectInstService;
import com.wflow.workflow.bean.vo.ProcessProgressVo;
import com.wflow.workflow.enums.ProcessStatusEnum;
import com.wflow.workflow.service.ProcessInstanceService;

/**
* 建设方案评审处理
*
* @author CMM
* @since 2023/02/24 14:35
*/
@Order(6)
@Component
public class ConstructionPlanReviewHandle extends AbstractProcessBusinessHandle {

private final IProjectInstService projectInstService;
private final ProcessInstanceService processInstanceService;

public ConstructionPlanReviewHandle(IProjectInstService projectInstService, ProcessInstanceService processInstanceService){
this.projectInstService = projectInstService;
this.processInstanceService = processInstanceService;
}

@Override
void businessHandle(Long projectId, List<ProcessDetailVO> processSchedule) {
ProcessDetailVO processDetailVO = new ProcessDetailVO();
// 根据项目ID查询出建设方案评审流程的流程状态
ProjectInst projectInst = projectInstService.getOne(Wrappers.lambdaQuery(ProjectInst.class)
.eq(ProjectInst::getProjectId, projectId)
.eq(ProjectInst::getInstType, InstTypeEnum.CONSTRUCTION_PLAN_REVIEW.getCode())
.orderByDesc(ProjectInst::getCreatOn)
.last("limit 1"));

if (Objects.isNull(projectInst)){
processDetailVO.setStepStatus(StepStatusEnum.NOT_START);
processDetailVO.setProcessName(CommonConstant.CONSTRUCTION_PLAN_REVIEW);
processSchedule.add(processDetailVO);
return;
}

String instCode = projectInst.getInstCode();
ProcessProgressVo instanceDetail = processInstanceService.getProgressInstanceDetail(null, instCode);
String status = instanceDetail.getStatus();
if (ProcessStatusEnum.UNDER_REVIEW.getDesc().equals(status)){
processDetailVO.setStepStatus(StepStatusEnum.ON_GOING);
} else if (ProcessStatusEnum.BE_REJECTED.getDesc().equals(status)) {
processDetailVO.setStepStatus(StepStatusEnum.REJECTED);
} else if (ProcessStatusEnum.APPROVED.getDesc().equals(status)) {
processDetailVO.setStepStatus(StepStatusEnum.COMPLETED);
}
// 根据流程处理详情获取流程完成时间
if(StepStatusEnum.contains(processDetailVO.getStepStatus(),
Lists.newArrayList(StepStatusEnum.REJECTED,
StepStatusEnum.COMPLETED))){
List<ProgressNode> progressInfo = instanceDetail.getProgressInfo();
ProgressNode progressNode = progressInfo.get(progressInfo.size() - 1);
LocalDateTime finishTime = NdDateUtils.date2LocalDateTime(progressNode.getFinishTime());
processDetailVO.setFinishTime(finishTime);
}
processDetailVO.setProcessProgressVo(instanceDetail);
processDetailVO.setProcessName(CommonConstant.CONSTRUCTION_PLAN_REVIEW);
processSchedule.add(processDetailVO);
}
}

pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handler/DeptUnitedReviewHandle.java → pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handle/DeptUnitedReviewHandle.java View File

@@ -1,8 +1,13 @@
package com.ningdatech.pmapi.projectlib.handler;
package com.ningdatech.pmapi.projectlib.handle;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

import com.google.common.collect.Lists;
import com.ningdatech.basic.util.NdDateUtils;
import com.wflow.workflow.bean.process.ProgressNode;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -22,35 +27,32 @@ import com.wflow.workflow.service.ProcessInstanceService;
* @author CMM
* @since 2023/02/24 14:35
*/
@Order(4)
@Component
public class DeptUnitedReviewHandle extends AbstractProcessBusinessHandler{
public class DeptUnitedReviewHandle extends AbstractProcessBusinessHandle {

private final IProjectInstService projectInstService;

private final ProcessInstanceService processInstanceService;

/**
* 设置该业务前缀
*/
private static final String PREFIX = CommonConstant.DEPT_UNITED_REVIEW_PREFIX;

public DeptUnitedReviewHandle(IProjectInstService projectInstService, ProcessInstanceService processInstanceService){
setPrefix(PREFIX);
this.projectInstService = projectInstService;
this.processInstanceService = processInstanceService;
}

@Override
ProcessDetailVO businessHandle(Long projectId) {
void businessHandle(Long projectId, List<ProcessDetailVO> processSchedule) {
ProcessDetailVO processDetailVO = new ProcessDetailVO();
// 根据项目ID查询出单位内部审核流程的流程状态
// 注意:已经在项目库中的项目,一定是已经开始的项目
// 根据项目ID查询出部门联审流程的流程状态
ProjectInst projectInst = projectInstService.getOne(Wrappers.lambdaQuery(ProjectInst.class)
.eq(ProjectInst::getProjectId, projectId)
.eq(ProjectInst::getInstType, InstTypeEnum.DEPT_UNITED_REVIEW.getCode()));
.eq(ProjectInst::getInstType, InstTypeEnum.DEPT_UNITED_REVIEW.getCode())
.orderByDesc(ProjectInst::getCreatOn)
.last("limit 1"));
if (Objects.isNull(projectInst)){
processDetailVO.setStepStatus(StepStatusEnum.NOT_START);
return processDetailVO;
processDetailVO.setProcessName(CommonConstant.DEPT_UNITED_REVIEW);
processSchedule.add(processDetailVO);
return;
}
String instCode = projectInst.getInstCode();
ProcessProgressVo instanceDetail = processInstanceService.getProgressInstanceDetail(null, instCode);
@@ -63,8 +65,16 @@ public class DeptUnitedReviewHandle extends AbstractProcessBusinessHandler{
processDetailVO.setStepStatus(StepStatusEnum.COMPLETED);
}
// 根据流程处理详情获取流程完成时间
LocalDateTime finishTime = processDetailVO.getFinishTime();
processDetailVO.setFinishTime(finishTime);
return processDetailVO;
if(StepStatusEnum.contains(processDetailVO.getStepStatus(),
Lists.newArrayList(StepStatusEnum.REJECTED,
StepStatusEnum.COMPLETED))){
List<ProgressNode> progressInfo = instanceDetail.getProgressInfo();
ProgressNode progressNode = progressInfo.get(progressInfo.size() - 1);
LocalDateTime finishTime = NdDateUtils.date2LocalDateTime(progressNode.getFinishTime());
processDetailVO.setFinishTime(finishTime);
}
processDetailVO.setProcessProgressVo(instanceDetail);
processDetailVO.setProcessName(CommonConstant.DEPT_UNITED_REVIEW);
processSchedule.add(processDetailVO);
}
}

+ 79
- 0
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handle/PreliminaryPreviewHandle.java View File

@@ -0,0 +1,79 @@
package com.ningdatech.pmapi.projectlib.handle;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.ningdatech.basic.util.NdDateUtils;
import com.ningdatech.pmapi.common.constant.CommonConstant;
import com.ningdatech.pmapi.projectlib.enumeration.InstTypeEnum;
import com.ningdatech.pmapi.projectlib.enumeration.StepStatusEnum;
import com.ningdatech.pmapi.projectlib.model.entity.ProjectInst;
import com.ningdatech.pmapi.projectlib.model.vo.ProcessDetailVO;
import com.ningdatech.pmapi.projectlib.service.IProjectInstService;
import com.wflow.workflow.bean.process.ProgressNode;
import com.wflow.workflow.bean.vo.ProcessProgressVo;
import com.wflow.workflow.enums.ProcessStatusEnum;
import com.wflow.workflow.service.ProcessInstanceService;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
* 项目预审处理
*
* @author CMM
* @since 2023/02/27 10:09
*/
@Order(3)
@Component
public class PreliminaryPreviewHandle extends AbstractProcessBusinessHandle {

private final IProjectInstService projectInstService;
private final ProcessInstanceService processInstanceService;

public PreliminaryPreviewHandle(IProjectInstService projectInstService, ProcessInstanceService processInstanceService) {
this.projectInstService = projectInstService;
this.processInstanceService = processInstanceService;
}

@Override
void businessHandle(Long projectId, List<ProcessDetailVO> processSchedule) {
ProcessDetailVO processDetailVO = new ProcessDetailVO();
// 根据项目ID查询项目预审流程的流程状态
ProjectInst projectInst = projectInstService.getOne(Wrappers.lambdaQuery(ProjectInst.class)
.eq(ProjectInst::getProjectId, projectId)
.eq(ProjectInst::getInstType, InstTypeEnum.DEPT_UNITED_REVIEW.getCode())
.orderByDesc(ProjectInst::getCreatOn)
.last("limit 1"));
if (Objects.isNull(projectInst)){
processDetailVO.setStepStatus(StepStatusEnum.NOT_START);
processDetailVO.setProcessName(CommonConstant.PRELIMINARY_PREVIEW);
processSchedule.add(processDetailVO);
return;
}
String instCode = projectInst.getInstCode();
ProcessProgressVo instanceDetail = processInstanceService.getProgressInstanceDetail(null, instCode);
String status = instanceDetail.getStatus();
if (ProcessStatusEnum.UNDER_REVIEW.getDesc().equals(status)){
processDetailVO.setStepStatus(StepStatusEnum.ON_GOING);
} else if (ProcessStatusEnum.BE_REJECTED.getDesc().equals(status)) {
processDetailVO.setStepStatus(StepStatusEnum.REJECTED);
} else if (ProcessStatusEnum.APPROVED.getDesc().equals(status)) {
processDetailVO.setStepStatus(StepStatusEnum.COMPLETED);
}
// 根据流程处理详情获取流程完成时间
if(StepStatusEnum.contains(processDetailVO.getStepStatus(),
Lists.newArrayList(StepStatusEnum.REJECTED,
StepStatusEnum.COMPLETED))){
List<ProgressNode> progressInfo = instanceDetail.getProgressInfo();
ProgressNode progressNode = progressInfo.get(progressInfo.size() - 1);
LocalDateTime finishTime = NdDateUtils.date2LocalDateTime(progressNode.getFinishTime());
processDetailVO.setFinishTime(finishTime);
}
processDetailVO.setProcessProgressVo(instanceDetail);
processDetailVO.setProcessName(CommonConstant.PRELIMINARY_PREVIEW);
processSchedule.add(processDetailVO);
}
}

+ 43
- 0
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handle/ProcessExecuteChainHandle.java View File

@@ -0,0 +1,43 @@
package com.ningdatech.pmapi.projectlib.handle;

import com.ningdatech.pmapi.projectlib.model.vo.ProcessDetailVO;
import org.springframework.stereotype.Component;

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

/**
* 流程执行链
*
* @author CMM
* @since 2023/02/26 21:36
*/
@Component
public class ProcessExecuteChainHandle {

/**
* 具体处理者的集合
*/
private final List<AbstractProcessBusinessHandle> processBusinessHandles;

public ProcessExecuteChainHandle(List<AbstractProcessBusinessHandle> processBusinessHandles) {
this.processBusinessHandles = processBusinessHandles;
}

/**
* 遍历处理链,通过前缀判断能否处理逻辑,如果不能继续遍历
* @param projectId
* @return void
* @author CMM
* @since 2023/02/26
*/
public List<ProcessDetailVO> handle(Long projectId, List<ProcessDetailVO> processSchedule){
if (processBusinessHandles.size() > 0) {
for (AbstractProcessBusinessHandle processBusinessHandle : processBusinessHandles) {
processBusinessHandle.businessHandle(projectId, processSchedule);
}
return processSchedule;
}
return Collections.emptyList();
}
}

+ 114
- 0
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handle/ProjectApprovalHandle.java View File

@@ -0,0 +1,114 @@
package com.ningdatech.pmapi.projectlib.handle;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import com.ningdatech.basic.util.CollUtils;
import com.ningdatech.basic.util.NdDateUtils;
import com.ningdatech.pmapi.projectlib.model.entity.Project;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ningdatech.basic.model.PageVo;
import com.ningdatech.pmapi.common.constant.CommonConstant;
import com.ningdatech.pmapi.common.statemachine.event.ProjectStatusChangeEvent;
import com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum;
import com.ningdatech.pmapi.projectlib.enumeration.StepStatusEnum;
import com.ningdatech.pmapi.projectlib.manage.AnnualPlanLibManage;
import com.ningdatech.pmapi.projectlib.model.entity.NdProjectStatusChange;
import com.ningdatech.pmapi.projectlib.model.req.ProjectListReq;
import com.ningdatech.pmapi.projectlib.model.vo.AnnualPlanListItemVO;
import com.ningdatech.pmapi.projectlib.model.vo.ProcessDetailVO;
import com.ningdatech.pmapi.projectlib.service.INdProjectStatusChangeService;
import com.ningdatech.pmapi.projectlib.service.IProjectService;

import static com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum.*;

/**
* 立项批复处理
*
* @author CMM
* @since 2023/02/24 14:35
*/
@Order(7)
@Component
public class ProjectApprovalHandle extends AbstractProcessBusinessHandle {

private final AnnualPlanLibManage annualPlanLibManage;
private final INdProjectStatusChangeService projectStatusChangeService;
private final IProjectService projectService;

/**
* 项目状态为:待立项批复及之后的状态
*/
private static final List<ProjectStatusEnum> ANNUAL_PLAN_LIST_STATUS = Arrays.asList(
TO_BE_APPROVED,
PROJECT_APPROVED,
TO_BE_PURCHASED,
UNDER_CONSTRUCTION,
TO_BE_FINALLY_INSPECTED,
FINAL_ACCEPTANCE_IS_UNDER_REVIEW,
FINAL_ACCEPTANCE_REVIEW_FAILED,
ARCHIVED
);

public ProjectApprovalHandle(AnnualPlanLibManage annualPlanLibManage, INdProjectStatusChangeService projectStatusChangeService, IProjectService projectService){
this.annualPlanLibManage = annualPlanLibManage;
this.projectStatusChangeService = projectStatusChangeService;
this.projectService = projectService;
}

@Override
void businessHandle(Long projectId, List<ProcessDetailVO> processSchedule) {
ProcessDetailVO processDetailVO = new ProcessDetailVO();
// 根据年度计划库列表是否包含该项目以及建设方案评审流程是否通过来判断立项批复是否开始
ProjectListReq req = new ProjectListReq();
PageVo<AnnualPlanListItemVO> planLibList = annualPlanLibManage.annulPlanLibList(req);
Collection<AnnualPlanListItemVO> records = planLibList.getRecords();
Map<Long, AnnualPlanListItemVO> itemVOMap = records.stream()
.collect(Collectors.toMap(AnnualPlanListItemVO::getProjectId, v -> v));
AnnualPlanListItemVO itemVO = itemVOMap.get(projectId);
// 年度计划库中不包含当前项目
if (Objects.isNull(itemVO)){
processDetailVO.setStepStatus(StepStatusEnum.NOT_START);
processDetailVO.setProcessName(CommonConstant.PROJECT_APPROVAL);
processSchedule.add(processDetailVO);
return;
}
Integer projectStatus = itemVO.getStatus();
List<Integer> fieldList = CollUtils.fieldList(ANNUAL_PLAN_LIST_STATUS, ProjectStatusEnum::getCode);

// 年度计划库中包含当前项目,但当前项目状态在待立项批复之前
if (!fieldList.contains(projectStatus)) {
processDetailVO.setStepStatus(StepStatusEnum.NOT_START);
processDetailVO.setProcessName(CommonConstant.ANNUAL_PLAN);
processSchedule.add(processDetailVO);
return;
}
// 年度计划库包含当前项目且当前项目状态为待立项批复
Integer status = itemVO.getStatus();
if (ProjectStatusEnum.TO_BE_APPROVED.getCode().equals(status)){
// 根据建设方案评审通过的时间获取
NdProjectStatusChange projectStatusChange = projectStatusChangeService.getOne(Wrappers.lambdaQuery(NdProjectStatusChange.class)
.eq(NdProjectStatusChange::getProjectId, projectId)
.eq(NdProjectStatusChange::getEvent, ProjectStatusChangeEvent.PLAN_REVIEW_PASS.name())
.last("limit 1"));
processDetailVO.setFinishTime(projectStatusChange.getCreateOn());
processDetailVO.setStepStatus(StepStatusEnum.ON_GOING);

} else {
// 年度计划库包含当前项目且当前项目状态为待立项批复之后的状态
// 根据立项批复的时间获取
Project project = projectService.getById(projectId);
LocalDate approvalDate = project.getApprovalDate();
LocalDateTime approvalDateTime = approvalDate.atStartOfDay();
processDetailVO.setFinishTime(approvalDateTime);
processDetailVO.setStepStatus(StepStatusEnum.COMPLETED);
}
processDetailVO.setProcessName(CommonConstant.PROJECT_APPROVAL);
processSchedule.add(processDetailVO);
}
}

pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handler/ProjectDeclareHandle.java → pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handle/ProjectDeclareHandle.java View File

@@ -1,13 +1,15 @@
package com.ningdatech.pmapi.projectlib.handler;
package com.ningdatech.pmapi.projectlib.handle;

import com.ningdatech.pmapi.common.constant.CommonConstant;
import com.ningdatech.pmapi.projectlib.enumeration.StepStatusEnum;
import com.ningdatech.pmapi.projectlib.model.entity.Project;
import com.ningdatech.pmapi.projectlib.model.vo.ProcessDetailVO;
import com.ningdatech.pmapi.projectlib.service.IProjectService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

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

/**
* 项目申报处理
@@ -16,22 +18,18 @@ import java.time.LocalDateTime;
* @since 2023/02/24 14:35
*/

public class ProjectDeclareHandle extends AbstractProcessBusinessHandler{
@Order(1)
@Component
public class ProjectDeclareHandle extends AbstractProcessBusinessHandle {

@Autowired
private IProjectService projectService;
private final IProjectService projectService;

/**
* 设置该业务前缀
*/
private static final String PREFIX = CommonConstant.PROJECT_DECLARE_PREFIX;

public ProjectDeclareHandle(){
setPrefix(PREFIX);
public ProjectDeclareHandle(IProjectService projectService){
this.projectService = projectService;
}

@Override
ProcessDetailVO businessHandle(Long projectId) {
void businessHandle(Long projectId, List<ProcessDetailVO> processSchedule) {
// 因为此时在项目库中的项目,都是已经申报过的项目,所以直接设置环节状态为已完成
ProcessDetailVO processDetailVO = new ProcessDetailVO();
processDetailVO.setStepStatus(StepStatusEnum.COMPLETED);
@@ -39,6 +37,7 @@ public class ProjectDeclareHandle extends AbstractProcessBusinessHandler{
Project project = projectService.getById(projectId);
LocalDateTime createOn = project.getCreateOn();
processDetailVO.setFinishTime(createOn);
return processDetailVO;
processDetailVO.setProcessName(CommonConstant.PROJECT_DECLARE);
processSchedule.add(processDetailVO);
}
}

+ 82
- 0
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handle/ProjectFinalInspectionHandle.java View File

@@ -0,0 +1,82 @@
package com.ningdatech.pmapi.projectlib.handle;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import com.google.common.collect.Lists;
import com.ningdatech.basic.util.NdDateUtils;
import com.ningdatech.pmapi.projectlib.enumeration.InstTypeEnum;
import com.ningdatech.pmapi.projectlib.model.entity.ProjectInst;
import com.ningdatech.pmapi.projectlib.service.IProjectInstService;
import com.wflow.workflow.bean.process.ProgressNode;
import com.wflow.workflow.bean.vo.ProcessProgressVo;
import com.wflow.workflow.enums.ProcessStatusEnum;
import com.wflow.workflow.service.ProcessInstanceService;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ningdatech.pmapi.common.constant.CommonConstant;
import com.ningdatech.pmapi.projectlib.enumeration.StepStatusEnum;
import com.ningdatech.pmapi.projectlib.model.vo.ProcessDetailVO;


/**
* 项目终验处理
*
* @author CMM
* @since 2023/02/24 14:35
*/
@Order(10)
@Component
public class ProjectFinalInspectionHandle extends AbstractProcessBusinessHandle {
private final IProjectInstService projectInstService;
private final ProcessInstanceService processInstanceService;

public ProjectFinalInspectionHandle(IProjectInstService projectInstService, ProcessInstanceService processInstanceService){
this.projectInstService = projectInstService;
this.processInstanceService = processInstanceService;
}

@Override
void businessHandle(Long projectId, List<ProcessDetailVO> processSchedule) {
ProcessDetailVO processDetailVO = new ProcessDetailVO();

// 根据项目ID查询出项目终验流程的流程状态
ProjectInst projectInst = projectInstService.getOne(Wrappers.lambdaQuery(ProjectInst.class)
.eq(ProjectInst::getProjectId, projectId)
.eq(ProjectInst::getInstType, InstTypeEnum.PROJECT_FINAL_INSPECTION.getCode())
.orderByDesc(ProjectInst::getCreatOn)
.last("limit 1"));

if (Objects.isNull(projectInst)){
processDetailVO.setStepStatus(StepStatusEnum.NOT_START);
processDetailVO.setProcessName(CommonConstant.PROJECT_FINAL_INSPECTION);
processSchedule.add(processDetailVO);
return;
}

String instCode = projectInst.getInstCode();
ProcessProgressVo instanceDetail = processInstanceService.getProgressInstanceDetail(null, instCode);
String status = instanceDetail.getStatus();
// 项目状态不在待终验之后的状态
if (ProcessStatusEnum.UNDER_REVIEW.getDesc().equals(status)){
processDetailVO.setStepStatus(StepStatusEnum.ON_GOING);
} else if (ProcessStatusEnum.BE_REJECTED.getDesc().equals(status)) {
processDetailVO.setStepStatus(StepStatusEnum.REJECTED);
} else if (ProcessStatusEnum.APPROVED.getDesc().equals(status)) {
processDetailVO.setStepStatus(StepStatusEnum.COMPLETED);
}
// 根据流程处理详情获取流程完成时间
if(StepStatusEnum.contains(processDetailVO.getStepStatus(),
Lists.newArrayList(StepStatusEnum.REJECTED,
StepStatusEnum.COMPLETED))){
List<ProgressNode> progressInfo = instanceDetail.getProgressInfo();
ProgressNode progressNode = progressInfo.get(progressInfo.size() - 1);
LocalDateTime finishTime = NdDateUtils.date2LocalDateTime(progressNode.getFinishTime());
processDetailVO.setFinishTime(finishTime);
}
processDetailVO.setProcessProgressVo(instanceDetail);
processDetailVO.setProcessName(CommonConstant.PRELIMINARY_PREVIEW);
processSchedule.add(processDetailVO);
}
}

+ 82
- 0
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handle/ProjectPreliminaryInspectionHandle.java View File

@@ -0,0 +1,82 @@
package com.ningdatech.pmapi.projectlib.handle;

import static com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum.*;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;

import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ningdatech.basic.util.CollUtils;
import com.ningdatech.pmapi.common.constant.CommonConstant;
import com.ningdatech.pmapi.common.statemachine.event.ProjectStatusChangeEvent;
import com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum;
import com.ningdatech.pmapi.projectlib.enumeration.StepStatusEnum;
import com.ningdatech.pmapi.projectlib.manage.AnnualPlanLibManage;
import com.ningdatech.pmapi.projectlib.model.entity.NdProjectStatusChange;
import com.ningdatech.pmapi.projectlib.model.entity.Project;
import com.ningdatech.pmapi.projectlib.model.vo.ProcessDetailVO;
import com.ningdatech.pmapi.projectlib.service.INdProjectStatusChangeService;
import com.ningdatech.pmapi.projectlib.service.IProjectService;

/**
* 项目初验处理
*
* @author CMM
* @since 2023/02/24 14:35
*/
@Order(9)
@Component
public class ProjectPreliminaryInspectionHandle extends AbstractProcessBusinessHandle {
private final INdProjectStatusChangeService projectStatusChangeService;
private final IProjectService projectService;

/**
* 项目状态为:建设中及之后的状态
*/
private static final List<ProjectStatusEnum> ANNUAL_PLAN_LIST_STATUS = Arrays.asList(
UNDER_CONSTRUCTION,
TO_BE_FINALLY_INSPECTED,
FINAL_ACCEPTANCE_IS_UNDER_REVIEW,
FINAL_ACCEPTANCE_REVIEW_FAILED,
ARCHIVED
);

public ProjectPreliminaryInspectionHandle(INdProjectStatusChangeService projectStatusChangeService, IProjectService projectService){
this.projectStatusChangeService = projectStatusChangeService;
this.projectService = projectService;
}

@Override
void businessHandle(Long projectId, List<ProcessDetailVO> processSchedule) {
ProcessDetailVO processDetailVO = new ProcessDetailVO();
// 根据项目状态是否在建设中及之后的状态判断项目初验是否开始
List<Integer> fieldList = CollUtils.fieldList(ANNUAL_PLAN_LIST_STATUS, ProjectStatusEnum::getCode);
Project project = projectService.getById(projectId);
Integer status = project.getStatus();
// 项目状态不在建设中及之后的状态
if (!fieldList.contains(status)){
processDetailVO.setStepStatus(StepStatusEnum.NOT_START);
processDetailVO.setProcessName(CommonConstant.PROJECT_PRELIMINARY_INSPECTION);
processSchedule.add(processDetailVO);
return;
}
// 项目状态为建设中或之后的状态
if (ProjectStatusEnum.UNDER_CONSTRUCTION.getCode().equals(project.getStatus())){
processDetailVO.setStepStatus(StepStatusEnum.ON_GOING);
}else {
processDetailVO.setStepStatus(StepStatusEnum.COMPLETED);
// 根据初验备案的时间获取
NdProjectStatusChange projectStatusChange = projectStatusChangeService.getOne(Wrappers.lambdaQuery(NdProjectStatusChange.class)
.eq(NdProjectStatusChange::getProjectId, projectId)
.eq(NdProjectStatusChange::getEvent, ProjectStatusChangeEvent.PRELIMINARY_ACCEPTANCE_PUT_ON_RECORD.name())
.last("limit 1"));
processDetailVO.setFinishTime(projectStatusChange.getCreateOn());
}
processDetailVO.setProcessName(CommonConstant.TENDER_PURCHASE);
processSchedule.add(processDetailVO);
}
}

+ 86
- 0
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handle/TenderPurchaseHandle.java View File

@@ -0,0 +1,86 @@
package com.ningdatech.pmapi.projectlib.handle;

import static com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum.*;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ningdatech.basic.model.PageVo;
import com.ningdatech.basic.util.CollUtils;
import com.ningdatech.pmapi.common.constant.CommonConstant;
import com.ningdatech.pmapi.common.statemachine.event.ProjectStatusChangeEvent;
import com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum;
import com.ningdatech.pmapi.projectlib.enumeration.StepStatusEnum;
import com.ningdatech.pmapi.projectlib.manage.AnnualPlanLibManage;
import com.ningdatech.pmapi.projectlib.model.entity.NdProjectStatusChange;
import com.ningdatech.pmapi.projectlib.model.entity.Project;
import com.ningdatech.pmapi.projectlib.model.req.ProjectListReq;
import com.ningdatech.pmapi.projectlib.model.vo.AnnualPlanListItemVO;
import com.ningdatech.pmapi.projectlib.model.vo.ProcessDetailVO;
import com.ningdatech.pmapi.projectlib.service.INdProjectStatusChangeService;
import com.ningdatech.pmapi.projectlib.service.IProjectService;

/**
* 招标采购处理
*
* @author CMM
* @since 2023/02/24 14:35
*/
@Order(8)
@Component
public class TenderPurchaseHandle extends AbstractProcessBusinessHandle {
private final INdProjectStatusChangeService projectStatusChangeService;
private final IProjectService projectService;

/**
* 项目状态为:建设中及之后的状态
*/
private static final List<ProjectStatusEnum> ANNUAL_PLAN_LIST_STATUS = Arrays.asList(
UNDER_CONSTRUCTION,
TO_BE_FINALLY_INSPECTED,
FINAL_ACCEPTANCE_IS_UNDER_REVIEW,
FINAL_ACCEPTANCE_REVIEW_FAILED,
ARCHIVED
);

public TenderPurchaseHandle(INdProjectStatusChangeService projectStatusChangeService, IProjectService projectService){
this.projectStatusChangeService = projectStatusChangeService;
this.projectService = projectService;
}

@Override
void businessHandle(Long projectId, List<ProcessDetailVO> processSchedule) {
ProcessDetailVO processDetailVO = new ProcessDetailVO();
// 根据项目是否通过立项批复(立项批复时间)来判断招标采购是否开始
Project project = projectService.getById(projectId);
Integer status = project.getStatus();
// 未进行立项批复
if (Objects.isNull(project.getApprovalDate())){
processDetailVO.setStepStatus(StepStatusEnum.NOT_START);
processDetailVO.setProcessName(CommonConstant.TENDER_PURCHASE);
processSchedule.add(processDetailVO);
return;
}
List<Integer> fieldList = CollUtils.fieldList(ANNUAL_PLAN_LIST_STATUS, ProjectStatusEnum::getCode);
// 进行了立项批复且项目状态是待采购
if (ProjectStatusEnum.TO_BE_PURCHASED.getCode().equals(project.getStatus())){
processDetailVO.setStepStatus(StepStatusEnum.ON_GOING);
}else if (fieldList.contains(status)){
processDetailVO.setStepStatus(StepStatusEnum.COMPLETED);
// 根据采购备案的时间获取
NdProjectStatusChange projectStatusChange = projectStatusChangeService.getOne(Wrappers.lambdaQuery(NdProjectStatusChange.class)
.eq(NdProjectStatusChange::getProjectId, projectId)
.eq(NdProjectStatusChange::getEvent, ProjectStatusChangeEvent.PURCHASE_PUT_ON_RECORD.name())
.last("limit 1"));
processDetailVO.setFinishTime(projectStatusChange.getCreateOn());
}
processDetailVO.setProcessName(CommonConstant.TENDER_PURCHASE);
processSchedule.add(processDetailVO);
}
}

pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handler/UnitInnerAuditHandle.java → pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handle/UnitInnerAuditHandle.java View File

@@ -1,8 +1,11 @@
package com.ningdatech.pmapi.projectlib.handler;
package com.ningdatech.pmapi.projectlib.handle;

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

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.ningdatech.basic.util.NdDateUtils;
import com.ningdatech.pmapi.projectlib.enumeration.InstTypeEnum;
import com.ningdatech.pmapi.projectlib.model.entity.ProjectInst;
import com.ningdatech.pmapi.projectlib.service.IProjectInstService;
@@ -10,9 +13,11 @@ import com.ningdatech.pmapi.projectlib.service.IProjectInstService;
import com.ningdatech.pmapi.common.constant.CommonConstant;
import com.ningdatech.pmapi.projectlib.enumeration.StepStatusEnum;
import com.ningdatech.pmapi.projectlib.model.vo.ProcessDetailVO;
import com.wflow.workflow.bean.process.ProgressNode;
import com.wflow.workflow.bean.vo.ProcessProgressVo;
import com.wflow.workflow.enums.ProcessStatusEnum;
import com.wflow.workflow.service.ProcessInstanceService;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
@@ -21,32 +26,29 @@ import org.springframework.stereotype.Component;
* @author CMM
* @since 2023/02/24 14:35
*/
@Order(2)
@Component
public class UnitInnerAuditHandle extends AbstractProcessBusinessHandler{
public class UnitInnerAuditHandle extends AbstractProcessBusinessHandle {

private final IProjectInstService projectInstService;

private final ProcessInstanceService processInstanceService;

/**
* 设置该业务前缀
*/
private static final String PREFIX = CommonConstant.UNIT_INNER_AUDIT_PREFIX;

public UnitInnerAuditHandle(IProjectInstService projectInstService, ProcessInstanceService processInstanceService){
setPrefix(PREFIX);
this.projectInstService = projectInstService;
this.processInstanceService = processInstanceService;
}

@Override
ProcessDetailVO businessHandle(Long projectId) {
void businessHandle(Long projectId, List<ProcessDetailVO> processSchedule) {
ProcessDetailVO processDetailVO = new ProcessDetailVO();
// 根据项目ID查询出单位内部审核流程的流程状态
// 注意:已经在项目库中的项目,一定是已经开始的项目
// 注意:已经在项目库中的项目,一定是单位内部审核已经开始的项目
ProjectInst projectInst = projectInstService.getOne(Wrappers.lambdaQuery(ProjectInst.class)
.eq(ProjectInst::getProjectId, projectId)
.eq(ProjectInst::getInstType, InstTypeEnum.UNIT_INNER_AUDIT.getCode()));
.eq(ProjectInst::getInstType, InstTypeEnum.UNIT_INNER_AUDIT.getCode())
.orderByDesc(ProjectInst::getCreatOn)
.last("limit 1"));
String instCode = projectInst.getInstCode();
ProcessProgressVo instanceDetail = processInstanceService.getProgressInstanceDetail(null, instCode);
String status = instanceDetail.getStatus();
@@ -57,9 +59,17 @@ public class UnitInnerAuditHandle extends AbstractProcessBusinessHandler{
} else if (ProcessStatusEnum.APPROVED.getDesc().equals(status)) {
processDetailVO.setStepStatus(StepStatusEnum.COMPLETED);
}
// 项目库中查出申报完成时间
LocalDateTime finishTime = processDetailVO.getFinishTime();
processDetailVO.setFinishTime(finishTime);
return processDetailVO;
// 根据流程处理详情获取流程完成时间
if(StepStatusEnum.contains(processDetailVO.getStepStatus(),
Lists.newArrayList(StepStatusEnum.REJECTED,
StepStatusEnum.COMPLETED))){
List<ProgressNode> progressInfo = instanceDetail.getProgressInfo();
ProgressNode progressNode = progressInfo.get(progressInfo.size() - 1);
LocalDateTime finishTime = NdDateUtils.date2LocalDateTime(progressNode.getFinishTime());
processDetailVO.setFinishTime(finishTime);
}
processDetailVO.setProcessProgressVo(instanceDetail);
processDetailVO.setProcessName(CommonConstant.UNIT_INNER_AUDIT);
processSchedule.add(processDetailVO);
}
}

+ 0
- 43
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/handler/AbstractProcessBusinessHandler.java View File

@@ -1,43 +0,0 @@
package com.ningdatech.pmapi.projectlib.handler;

import com.ningdatech.pmapi.projectlib.model.vo.ProcessDetailVO;

/**
* 流程业务抽象处理类
*
* @author CMM
* @since 2023/02/24 14:22
*/

public abstract class AbstractProcessBusinessHandler {
/**
* 前缀,用于区分是什么业务
*/
private String prefix;

/**
* 构造,子类必须实现
*/
public AbstractProcessBusinessHandler(){}

/**
* 操作前缀属性的公开方法
*/
public String getPrefix(){
return prefix;
}

public void setPrefix(String prefix){
this.prefix = prefix;
}

/**
* 抽象的,所有具体处理者应该实现的处理逻辑
* @param projectId 项目ID
* @return void
* @author CMM
* @since 2023/02/24 14:33
*/
abstract ProcessDetailVO businessHandle(Long projectId);

}

+ 51
- 5
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/manage/AnnualPlanLibManage.java View File

@@ -12,8 +12,11 @@ import com.ningdatech.basic.exception.BizException;
import com.ningdatech.basic.model.PageVo;
import com.ningdatech.basic.util.CollUtils;
import com.ningdatech.basic.util.ValidUtil;
import com.ningdatech.pmapi.common.constant.CommonConstant;
import com.ningdatech.pmapi.common.model.entity.ExcelExportWriter;
import com.ningdatech.pmapi.common.statemachine.event.ProjectStatusChangeEvent;
import com.ningdatech.pmapi.common.statemachine.util.StateMachineUtils;
import com.ningdatech.pmapi.common.util.ExcelDownUtil;
import com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum;
import com.ningdatech.pmapi.projectlib.helper.ProjectHelper;
import com.ningdatech.pmapi.projectlib.model.dto.AnnualLibImportDTO;
@@ -36,6 +39,7 @@ import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

import static com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum.*;

@@ -77,7 +81,11 @@ public class AnnualPlanLibManage {

public PageVo<AnnualPlanListItemVO> annulPlanLibList(ProjectListReq req) {
LambdaQueryWrapper<Project> query = ProjectHelper.projectQuery(req);
query.eq(Project::getIsTemporaryAugment, 0);
Integer isTemporaryAugment = req.getIsTemporaryAugment();
if (Objects.isNull(isTemporaryAugment)){
throw new BizException("请传入是否临时增补标志!");
}
query.eq(Project::getIsTemporaryAugment, isTemporaryAugment);
query.orderByDesc(Project::getAnnualPlanAddTime);
query.in(Project::getStatus, CollUtils.fieldList(ANNUAL_PLAN_LIST_STATUS, ProjectStatusEnum::getCode));
Page<Project> page = projectService.page(req.page(), query);
@@ -89,6 +97,7 @@ public class AnnualPlanLibManage {
page.getRecords().forEach(w -> {
AnnualPlanListItemVO item = new AnnualPlanListItemVO();
item.setProjectId(w.getId());
item.setProjectId(w.getId());
item.setProjectName(w.getProjectName());
item.setStage(w.getStage());
item.setStatus(w.getStatus());
@@ -202,13 +211,50 @@ public class AnnualPlanLibManage {
}
}

public void exportAnnualPlanEditTable(HttpServletResponse response) {
// TODO
}

public void updateAnnualPlan(ProjectDTO req) {
Project project = BeanUtil.copyProperties(req, Project.class);
projectService.updateById(project);
}

public void exportList(ProjectListReq param, HttpServletResponse response) {
param.setPageNumber(CommonConstant.EXPORT_PAGE_NUMBER);
param.setPageSize(CommonConstant.EXPORT_PAGE_SIZE);
LambdaQueryWrapper<Project> query = ProjectHelper.projectQuery(param);
Integer isTemporaryAugment = param.getIsTemporaryAugment();
if (Objects.isNull(isTemporaryAugment)){
throw new BizException("请传入是否临时增补标志!");
}
query.eq(Project::getIsTemporaryAugment, isTemporaryAugment);
query.eq(Project::getIsTemporaryAugment, 0);
query.orderByDesc(Project::getAnnualPlanAddTime);
query.in(Project::getStatus, CollUtils.fieldList(ANNUAL_PLAN_LIST_STATUS, ProjectStatusEnum::getCode));
List<Project> projects = projectService.list(query);

ExcelExportWriter excelExportWriter = new ExcelExportWriter();

Integer tableFlag = param.getTableFlag();
if (Objects.isNull(tableFlag)){
throw new BizException("请传入要导出的表格类型!");
}
String fileName = null;
if (tableFlag == 0){
fileName = "年度计划库编辑表";
} else if (tableFlag == 1) {
fileName = "年度计划库列表";
}
excelExportWriter.setFileName(fileName);
List<String> sheetsNames = new ArrayList<>();
sheetsNames.add(fileName);
// 表体行数据集合
List<List<String>> exportDatas = ExcelDownUtil.getExportDatas(param.getExportOptionList(), projects);
// sheet列表集合
List<List<List<String>>> sheets = new ArrayList<>();
sheets.add(exportDatas);
excelExportWriter.setHeads(sheets);
excelExportWriter.setDatas(exportDatas);
excelExportWriter.setSheets(sheetsNames);
excelExportWriter.setHeadPropertyClass(List.class);
excelExportWriter.setHeadPropertyFlag(Boolean.FALSE);
ExcelDownUtil.excelExportFile(response, excelExportWriter);
}
}

+ 38
- 8
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/manage/ProjectLibManage.java View File

@@ -6,7 +6,11 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.ningdatech.basic.model.PageVo;
import com.ningdatech.basic.util.CollUtils;
import com.ningdatech.pmapi.common.constant.CommonConstant;
import com.ningdatech.pmapi.common.model.entity.ExcelExportWriter;
import com.ningdatech.pmapi.common.util.ExcelDownUtil;
import com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum;
import com.ningdatech.pmapi.projectlib.handle.ProcessExecuteChainHandle;
import com.ningdatech.pmapi.projectlib.helper.ProjectHelper;
import com.ningdatech.pmapi.projectlib.model.entity.Project;
import com.ningdatech.pmapi.projectlib.model.entity.ProjectApplication;
@@ -19,14 +23,13 @@ import com.ningdatech.pmapi.projectlib.model.vo.ProjectLibListItemVO;
import com.ningdatech.pmapi.projectlib.service.IProjectApplicationService;
import com.ningdatech.pmapi.projectlib.service.IProjectRenewalFundDeclarationService;
import com.ningdatech.pmapi.projectlib.service.IProjectService;
import com.ningdatech.pmapi.todocenter.enumeration.IsAppendProjectEnum;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
* <p>
@@ -41,10 +44,9 @@ import java.util.Optional;
public class ProjectLibManage {

private final IProjectService projectService;

private final IProjectApplicationService applicationService;

private final IProjectRenewalFundDeclarationService renewalFundDeclarationService;
private final ProcessExecuteChainHandle processExecuteHandle;

public PageVo<ProjectLibListItemVO> projectLibList(ProjectListReq req) {
LambdaQueryWrapper<Project> query = ProjectHelper.projectQuery(req);
@@ -126,7 +128,35 @@ public class ProjectLibManage {
return vo;
}

public ProcessDetailVO totalProcessDetail(Long projectId) {
return null;
public List<ProcessDetailVO> processScheduleDetail(Long projectId) {
List<ProcessDetailVO> processDetailVOS = new ArrayList<>();
return processExecuteHandle.handle(projectId, processDetailVOS);
}

public void exportList(ProjectListReq param, HttpServletResponse response) {

param.setPageNumber(CommonConstant.EXPORT_PAGE_NUMBER);
param.setPageSize(CommonConstant.EXPORT_PAGE_SIZE);
LambdaQueryWrapper<Project> query = ProjectHelper.projectQuery(param);
List<Project> projects = projectService.list(query);

ExcelExportWriter excelExportWriter = new ExcelExportWriter();

String fileName = "项目库列表";
excelExportWriter.setFileName(fileName);

List<String> sheetsNames = new ArrayList<>();
sheetsNames.add(fileName);
// 表体行数据集合
List<List<String>> exportDatas = ExcelDownUtil.getExportDatas(param.getExportOptionList(), projects);
// sheet列表集合
List<List<List<String>>> sheets = new ArrayList<>();
sheets.add(exportDatas);
excelExportWriter.setHeads(sheets);
excelExportWriter.setDatas(exportDatas);
excelExportWriter.setSheets(sheetsNames);
excelExportWriter.setHeadPropertyClass(List.class);
excelExportWriter.setHeadPropertyFlag(Boolean.FALSE);
ExcelDownUtil.excelExportFile(response, excelExportWriter);
}
}

+ 16
- 0
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/mapper/NdProjectStatusChangeMapper.java View File

@@ -0,0 +1,16 @@
package com.ningdatech.pmapi.projectlib.mapper;

import com.ningdatech.pmapi.projectlib.model.entity.NdProjectStatusChange;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

/**
* <p>
* Mapper 接口
* </p>
*
* @author CMM
* @since 2023-02-27
*/
public interface NdProjectStatusChangeMapper extends BaseMapper<NdProjectStatusChange> {

}

+ 5
- 0
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/mapper/NdProjectStatusChangeMapper.xml View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ningdatech.pmapi.projectlib.mapper.NdProjectStatusChangeMapper">

</mapper>

+ 95
- 0
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/model/entity/NdProjectStatusChange.java View File

@@ -0,0 +1,95 @@
package com.ningdatech.pmapi.projectlib.model.entity;

import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

/**
* <p>
*
* </p>
*
* @author CMM
* @since 2023-02-27
*/
@TableName("nd_project_status_change")
@ApiModel(value = "NdProjectStatusChange对象", description = "")
public class NdProjectStatusChange implements Serializable {

private static final long serialVersionUID = 1L;

@ApiModelProperty("主键")
private Long id;

@ApiModelProperty("项目ID")
private Long projectId;

@ApiModelProperty("状态机执行前的项目状态")
private Integer beforeStatus;

@ApiModelProperty("状态机执行后的项目状态")
private Integer afterStatus;

@ApiModelProperty("状态变更对应的事件")
private String event;

@ApiModelProperty("状态变更发生的时间")
private LocalDateTime createOn;

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}
public Long getProjectId() {
return projectId;
}

public void setProjectId(Long projectId) {
this.projectId = projectId;
}
public Integer getBeforeStatus() {
return beforeStatus;
}

public void setBeforeStatus(Integer beforeStatus) {
this.beforeStatus = beforeStatus;
}
public Integer getAfterStatus() {
return afterStatus;
}

public void setAfterStatus(Integer afterStatus) {
this.afterStatus = afterStatus;
}
public String getEvent() {
return event;
}

public void setEvent(String event) {
this.event = event;
}
public LocalDateTime getCreateOn() {
return createOn;
}

public void setCreateOn(LocalDateTime createOn) {
this.createOn = createOn;
}

@Override
public String toString() {
return "NdProjectStatusChange{" +
"id=" + id +
", projectId=" + projectId +
", beforeStatus=" + beforeStatus +
", afterStatus=" + afterStatus +
", event=" + event +
", createOn=" + createOn +
"}";
}
}

+ 8
- 0
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/model/req/ProjectListReq.java View File

@@ -1,11 +1,13 @@
package com.ningdatech.pmapi.projectlib.model.req;

import com.ningdatech.basic.model.PagePo;
import com.ningdatech.pmapi.common.enumeration.ExportOptionEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import org.springframework.format.annotation.DateTimeFormat;

import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
@@ -83,4 +85,10 @@ public class ProjectListReq extends PagePo {

@ApiModelProperty("实例code 多个")
private List<String> instCodes;

@ApiModelProperty("导出选项")
private List<ExportOptionEnum> exportOptionList;

@ApiModelProperty(value = "表格类型",allowableValues = "0,1")
private Integer tableFlag;
}

+ 3
- 0
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/model/vo/ProcessDetailVO.java View File

@@ -26,6 +26,9 @@ public class ProcessDetailVO implements Serializable {
@ApiModelProperty("环节状态")
private StepStatusEnum stepStatus;

@ApiModelProperty("流程名称")
private String processName;

@ApiModelProperty("完成时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private LocalDateTime finishTime;


+ 16
- 0
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/service/INdProjectStatusChangeService.java View File

@@ -0,0 +1,16 @@
package com.ningdatech.pmapi.projectlib.service;

import com.ningdatech.pmapi.projectlib.model.entity.NdProjectStatusChange;
import com.baomidou.mybatisplus.extension.service.IService;

/**
* <p>
* 服务类
* </p>
*
* @author CMM
* @since 2023-02-27
*/
public interface INdProjectStatusChangeService extends IService<NdProjectStatusChange> {

}

+ 20
- 0
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/service/impl/NdProjectStatusChangeServiceImpl.java View File

@@ -0,0 +1,20 @@
package com.ningdatech.pmapi.projectlib.service.impl;

import com.ningdatech.pmapi.projectlib.model.entity.NdProjectStatusChange;
import com.ningdatech.pmapi.projectlib.mapper.NdProjectStatusChangeMapper;
import com.ningdatech.pmapi.projectlib.service.INdProjectStatusChangeService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

/**
* <p>
* 服务实现类
* </p>
*
* @author CMM
* @since 2023-02-27
*/
@Service
public class NdProjectStatusChangeServiceImpl extends ServiceImpl<NdProjectStatusChangeMapper, NdProjectStatusChange> implements INdProjectStatusChangeService {

}

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

@@ -1,191 +0,0 @@
package com.ningdatech.pmapi.todocenter.extension.cmd;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.assertj.core.util.Sets;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowNode;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.UserTask;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.common.engine.api.FlowableObjectNotFoundException;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.impl.delegate.ActivityBehavior;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.engine.impl.util.ExecutionGraphUtil;
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
import org.flowable.task.api.Task;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;

import com.wflow.workflow.utils.FlowableUtils;

/**
* @author : willian fu
* @date : 2022/10/14
*/
@RequiredArgsConstructor
@AllArgsConstructor
public class BackToHisApprovalNodeCmd implements Command<String>, Serializable {

private static final long serialVersionUID = -80075781855060928L;
protected RuntimeService runtimeService;
protected BpmnModel bpmnModel;
protected String taskId;
protected String targetNodeId;

@Override
public String execute(CommandContext commandContext) {

if (targetNodeId == null || targetNodeId.length() == 0) {
throw new FlowableException("退回的目标节点不能为空");
}
TaskEntity task = CommandContextUtil.getProcessEngineConfiguration().getTaskServiceConfiguration().getTaskService().getTask(taskId);
if (task == null) {
throw new FlowableObjectNotFoundException(taskId + " 任务不能为空", Task.class);
}
String sourceNodeId = task.getTaskDefinitionKey();
String processInstanceId = task.getProcessInstanceId();
String processDefinitionId = task.getProcessDefinitionId();

//获取流程定义
Process process = ProcessDefinitionUtil.getProcess(processDefinitionId);

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

// 只支持从用户任务退回
if (!(sourceFlowElement instanceof UserTask)) {
throw new FlowableException("只能从审批节点进行回退");
}
FlowNode targetFlowElement = (FlowNode) bpmnModel.getFlowElement(targetNodeId);
// 退回节点到当前节点不可达到,不允许退回
if (!ExecutionGraphUtil.isReachable(processDefinitionId, targetNodeId, sourceNodeId)) {
throw new FlowableException("无法回退到目标节点");
}

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

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

Map<String, Set<String>> specialGatewayNodes = FlowableUtils.getSpecialGatewayElements(process);
// 当前节点处在的并行网关list
List<String> sourceInSpecialGatewayList = new ArrayList<>();
// 目标节点处在的并行网关list
List<String> targetInSpecialGatewayList = new ArrayList<>();
setSpecialGatewayList(sourceRealActivityId, targetRealActivityId, specialGatewayNodes, sourceInSpecialGatewayList, targetInSpecialGatewayList);
// 实际应筛选的节点ID
Set<String> sourceRealAcitivtyIds = null;
// 若退回目标节点相对当前节点在并行网关中,则要找到相对当前节点最近的这个并行网关,后续做特殊处理
String targetRealSpecialGateway = null;

// 1.目标节点和当前节点都不在并行网关中
if (targetInSpecialGatewayList.isEmpty() && sourceInSpecialGatewayList.isEmpty()) {
sourceRealAcitivtyIds = Sets.newLinkedHashSet(sourceRealActivityId);
}
// 2.目标节点不在并行网关中、当前节点在并行网关中
else if (targetInSpecialGatewayList.isEmpty()) {
sourceRealAcitivtyIds = specialGatewayNodes.get(sourceInSpecialGatewayList.get(0));
}
// 3.目标节点在并行网关中、当前节点不在并行网关中
else if (sourceInSpecialGatewayList.isEmpty()) {
sourceRealAcitivtyIds = Sets.newLinkedHashSet(sourceRealActivityId);
targetRealSpecialGateway = targetInSpecialGatewayList.get(0);
}
// 4.目标节点和当前节点都在并行网关中
else {
int diffSpecialGatewayLevel = FlowableUtils.getDiffLevel(sourceInSpecialGatewayList, targetInSpecialGatewayList);
// 在并行网关同一层且在同一分支
if (diffSpecialGatewayLevel == -1) {
sourceRealAcitivtyIds = Sets.newLinkedHashSet(sourceRealActivityId);
} else {
// 当前节点最内层并行网关不被目标节点最内层并行网关包含
// 或理解为当前节点相对目标节点在并行网关外
// 只筛选当前节点的execution
if (sourceInSpecialGatewayList.size() == diffSpecialGatewayLevel) {
sourceRealAcitivtyIds = Sets.newLinkedHashSet(sourceRealActivityId);
}
// 当前节点相对目标节点在并行网关内,应筛选相对目标节点最近的并行网关的所有节点的execution
else {
sourceRealAcitivtyIds = specialGatewayNodes.get(sourceInSpecialGatewayList.get(diffSpecialGatewayLevel));
}
// 目标节点最内层并行网关包含当前节点最内层并行网关
// 或理解为目标节点相对当前节点在并行网关外
// 不做处理
if (targetInSpecialGatewayList.size() == diffSpecialGatewayLevel) {
}
// 目标节点相对当前节点在并行网关内
else {
targetRealSpecialGateway = targetInSpecialGatewayList.get(diffSpecialGatewayLevel);
}
}
}

// 筛选需要处理的execution
List<ExecutionEntity> realExecutions = this.getRealExecutions(commandContext, processInstanceId,
task.getExecutionId(), sourceRealActivityId, sourceRealAcitivtyIds);
// 执行退回,直接跳转到实际的 targetRealActivityId
List<String> realExecutionIds = realExecutions.stream().map(ExecutionEntity::getId).collect(Collectors.toList());
runtimeService.createChangeActivityStateBuilder().processInstanceId(processInstanceId).moveExecutionsToSingleActivityId(realExecutionIds, targetRealActivityId).changeState();
// 目标节点相对当前节点处于并行网关内,需要特殊处理,需要手动生成并行网关汇聚节点(_end)的execution数据
if (targetRealSpecialGateway != null) {
createTargetInSpecialGatewayEndExecutions(commandContext, realExecutions, process, targetInSpecialGatewayList, targetRealSpecialGateway);
}
return targetRealActivityId;
}

private void setSpecialGatewayList(String sourceNodeId, String targetNodeId, Map<String, Set<String>> specialGatewayNodes,
List<String> sourceInSpecialGatewayList, List<String> targetInSpecialGatewayList) {
for (Map.Entry<String, Set<String>> entry : specialGatewayNodes.entrySet()) {
if (entry.getValue().contains(sourceNodeId)) {
sourceInSpecialGatewayList.add(entry.getKey());
}
if (entry.getValue().contains(targetNodeId)) {
targetInSpecialGatewayList.add(entry.getKey());
}
}
}

private void createTargetInSpecialGatewayEndExecutions(CommandContext commandContext, List<ExecutionEntity> excutionEntitys, Process process,
List<String> targetInSpecialGatewayList, String targetRealSpecialGateway) {
// 目标节点相对当前节点处于并行网关,需要手动生成并行网关汇聚节点(_end)的execution数据
String parentExecutionId = excutionEntitys.iterator().next().getParentId();
ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(commandContext);
ExecutionEntity parentExecutionEntity = executionEntityManager.findById(parentExecutionId);

int index = targetInSpecialGatewayList.indexOf(targetRealSpecialGateway);
for (; index < targetInSpecialGatewayList.size(); index++) {
String targetInSpecialGateway = targetInSpecialGatewayList.get(index);
FlowNode targetInSpecialGatewayEnd = (FlowNode) process.getFlowElement(targetInSpecialGateway + "_end", true);
int nbrOfExecutionsToJoin = targetInSpecialGatewayEnd.getIncomingFlows().size();
// 处理目标节点所处的分支以外的分支,即 总分枝数-1 = nbrOfExecutionsToJoin - 1
for (int i = 0; i < nbrOfExecutionsToJoin - 1; i++) {
ExecutionEntity childExecution = executionEntityManager.createChildExecution(parentExecutionEntity);
childExecution.setCurrentFlowElement(targetInSpecialGatewayEnd);
ActivityBehavior activityBehavior = (ActivityBehavior) targetInSpecialGatewayEnd.getBehavior();
activityBehavior.execute(childExecution);
}
}
}

private List<ExecutionEntity> getRealExecutions(CommandContext commandContext, String processInstanceId,
String taskExecutionId, String sourceRealActivityId, Set<String> activityIds) {
ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(commandContext);
ExecutionEntity taskExecution = executionEntityManager.findById(taskExecutionId);
List<ExecutionEntity> executions = executionEntityManager.findChildExecutionsByProcessInstanceId(processInstanceId);
Set<String> parentExecutionIds = FlowableUtils.getParentExecutionIdsByActivityId(executions, sourceRealActivityId);
String realParentExecutionId = FlowableUtils.getParentExecutionIdFromParentIds(taskExecution, parentExecutionIds);
return executionEntityManager.findExecutionsByParentExecutionAndActivityIds(realParentExecutionId, activityIds);
}
}

+ 0
- 105
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/extension/cmd/SaveCommentCmd.java View File

@@ -1,105 +0,0 @@
package com.ningdatech.pmapi.todocenter.extension.cmd;

import com.ningdatech.pmapi.common.constant.CommonConstant;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.common.engine.api.FlowableObjectNotFoundException;
import org.flowable.common.engine.impl.identity.Authentication;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.compatibility.Flowable5CompatibilityHandler;
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.flowable.engine.impl.persistence.entity.CommentEntity;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.engine.impl.util.Flowable5Util;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.task.Comment;
import org.flowable.task.api.Task;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;

/**
* 保存评论
*
* @author CMM
* @since 2023/02/09 11:43
*/

public class SaveCommentCmd implements Command<Comment> {

protected String taskId;
protected String processInstanceId;
protected String userId;
protected String message;
protected String type;


public SaveCommentCmd(String taskId, String processInstanceId, String userId , String message) {
this.taskId = taskId;
this.processInstanceId = processInstanceId;
this.userId = userId;
this.message = message;
}

@Override
public Comment execute(CommandContext commandContext) {
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
TaskEntity task = null;
if (this.taskId != null) {
task = processEngineConfiguration.getTaskServiceConfiguration().getTaskService().getTask(this.taskId);
if (task == null) {
throw new FlowableObjectNotFoundException("Cannot find task with id " + this.taskId, Task.class);
}

if (task.isSuspended()) {
throw new FlowableException(this.getSuspendedTaskException());
}
}

ExecutionEntity execution = null;
if (this.processInstanceId != null) {
execution = (ExecutionEntity)processEngineConfiguration.getExecutionEntityManager().findById(this.processInstanceId);
if (execution == null) {
throw new FlowableObjectNotFoundException("execution " + this.processInstanceId + " doesn't exist", Execution.class);
}

if (execution.isSuspended()) {
throw new FlowableException(this.getSuspendedExceptionMessage());
}
}

String processDefinitionId = null;
if (execution != null) {
processDefinitionId = execution.getProcessDefinitionId();
} else if (task != null) {
processDefinitionId = task.getProcessDefinitionId();
}

if (Flowable5Util.isFlowable5ProcessDefinitionId(commandContext, processDefinitionId)) {
Flowable5CompatibilityHandler compatibilityHandler = Flowable5Util.getFlowable5CompatibilityHandler();
return compatibilityHandler.addComment(this.taskId, this.processInstanceId, this.type, this.message);
} else {
CommentEntity comment = (CommentEntity)processEngineConfiguration.getCommentEntityManager().create();
comment.setUserId(userId);
comment.setType(this.type == null ? "comment" : this.type);
comment.setTime(processEngineConfiguration.getClock().getCurrentTime());
comment.setTaskId(this.taskId);
comment.setProcessInstanceId(this.processInstanceId);
comment.setAction("AddComment");
String eventMessage = this.message.replaceAll("\\s+", " ");
if (eventMessage.length() > CommonConstant.COMMENT_MAX_SIZE) {
eventMessage = eventMessage.substring(CommonConstant.SUB_COMMENT_SIZE_MIN, CommonConstant.SUB_COMMENT_SIZE_MAX) + "...";
}

comment.setMessage(eventMessage);
comment.setFullMessage(this.message);
processEngineConfiguration.getCommentEntityManager().insert(comment);
return comment;
}
}
protected String getSuspendedTaskException() {
return "Cannot add a comment to a suspended task";
}
protected String getSuspendedExceptionMessage() {
return "Cannot add a comment to a suspended execution";
}
}

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

@@ -174,7 +174,7 @@ public class TodoCenterManage {
}
excelExportWriter.setFileName(fileName);
List<String> sheetsNames = Lists.newArrayList(fileName);
List<List<String>> exportDatas = ExcelDownUtil.getExportDatas(param, projects);
List<List<String>> exportDatas = ExcelDownUtil.getExportDatas(param.getExportOptionList(), projects);
// sheet列表集合
List<List<List<String>>> sheets = Lists.newArrayList();
sheets.add(exportDatas);
@@ -252,7 +252,7 @@ public class TodoCenterManage {

// 如果流程状态是被退回状态,流程通过后,进入下一个审核人,
// 当前通过审核人一定不是最后一个审核人(下一个审核人至多是最后一个),更新流程状态为审核中
if (ProcessStatusEnum.BE_BACKED.getCode().equals(currentProcessStatus)) {
if (ProcessStatusEnum.BE_BACKED.getDesc().equals(currentProcessStatus)) {
// 更新流程状态为审核中
declaredProject.setProcessStatus(ProcessStatusEnum.UNDER_REVIEW.getCode());
declaredProject.setUpdateOn(LocalDateTime.now());
@@ -690,7 +690,7 @@ public class TodoCenterManage {
List<String> sheetsNames = new ArrayList<>();
sheetsNames.add(fileName);

List<List<String>> exportDatas = ExcelDownUtil.getExportDatas(param, projects);
List<List<String>> exportDatas = ExcelDownUtil.getExportDatas(param.getExportOptionList(), projects);
// sheet列表集合
List<List<List<String>>> sheets = new ArrayList<>();
sheets.add(exportDatas);
@@ -783,7 +783,7 @@ public class TodoCenterManage {
List<String> sheetsNames = new ArrayList<>();
sheetsNames.add(fileName);
// 表体行数据集合
List<List<String>> exportDatas = ExcelDownUtil.getExportDatas(param, projects);
List<List<String>> exportDatas = ExcelDownUtil.getExportDatas(param.getExportOptionList(), projects);
// sheet列表集合
List<List<List<String>>> sheets = new ArrayList<>();
sheets.add(exportDatas);
@@ -880,7 +880,7 @@ public class TodoCenterManage {
List<String> sheetsNames = new ArrayList<>();
sheetsNames.add(fileName);
// 表体行数据集合
List<List<String>> exportDatas = ExcelDownUtil.getExportDatas(param, projects);
List<List<String>> exportDatas = ExcelDownUtil.getExportDatas(param.getExportOptionList(), projects);
// sheet列表集合
List<List<List<String>>> sheets = new ArrayList<>();
sheets.add(exportDatas);


Loading…
Cancel
Save