Browse Source

modify:

1. 项目重新申请修改;
tags/24080901
WendyYang 3 months ago
parent
commit
38832bbe4b
49 changed files with 2061 additions and 63 deletions
  1. +7
    -1
      hz-pm-api/src/main/java/com/hz/pm/api/common/enumeration/ProjectProcessType.java
  2. +27
    -1
      hz-pm-api/src/main/java/com/hz/pm/api/common/statemachine/event/ProjectStateChangeEvent.java
  3. +23
    -1
      hz-pm-api/src/main/java/com/hz/pm/api/common/statemachine/event/TenderStateChangeEvent.java
  4. +38
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/common/util/MethodReferenceUtil.java
  5. +46
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/entity/ProjectChangeHistory.java
  6. +16
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/mapper/ProjectChangeHistoryMapper.java
  7. +5
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/mapper/ProjectChangeHistoryMapper.xml
  8. +77
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/model/dto/ContractDTO.java
  9. +96
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/model/dto/OperationDTO.java
  10. +29
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/model/dto/PreInsAcceptancePersonDTO.java
  11. +28
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/model/dto/ProjectEditDTO.java
  12. +177
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/model/dto/PurchaseDTO.java
  13. +35
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/model/dto/PurchaseEditDTO.java
  14. +2
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/model/dto/PurchaseSaveDTO.java
  15. +16
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/service/IProjectChangeHistoryService.java
  16. +20
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/service/impl/ProjectChangeHistoryServiceImpl.java
  17. +126
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/utils/BeanDiffUtil.java
  18. +36
    -9
      hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/utils/ProjectIdCodeCacheUtil.java
  19. +88
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/controller/ProjectStoppedChangeController.java
  20. +8
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/entity/PurchaseStatusChange.java
  21. +291
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/helper/ProjectChangeStopHelper.java
  22. +218
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/manage/ProjectChangeManage.java
  23. +14
    -12
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/manage/ProjectLibManage.java
  24. +153
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/manage/ProjectStoppedManage.java
  25. +7
    -1
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/mapper/ProjectMapper.java
  26. +21
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/mapper/ProjectMapper.xml
  27. +20
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/dto/GovSystemReplaceInfoDTO.java
  28. +1
    -1
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/dto/ProjectApplicationDTO.java
  29. +59
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/dto/ProjectChangeListDTO.java
  30. +2
    -2
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/dto/ProjectDTO.java
  31. +27
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/dto/ProjectPaymentPlanDTO.java
  32. +9
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/entity/Project.java
  33. +8
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/entity/ProjectInst.java
  34. +3
    -1
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/enumeration/InstTypeEnum.java
  35. +28
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/enumeration/status/ProjectChangeStatus.java
  36. +13
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/enumeration/status/ProjectStatus.java
  37. +28
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/enumeration/status/ProjectStoppedStatus.java
  38. +4
    -1
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/enumeration/status/TenderStatus.java
  39. +24
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/req/SubmitProjectChangeApplyReq.java
  40. +26
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/req/SubmitProjectStoppedApplyReq.java
  41. +29
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/vo/ProjectChangeDetailVO.java
  42. +62
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/vo/ProjectChangeListVO.java
  43. +6
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/vo/ProjectDetailVO.java
  44. +6
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/vo/ProjectLibListItemVO.java
  45. +4
    -1
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/service/IProjectService.java
  46. +8
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/projectlib/service/impl/ProjectServiceImpl.java
  47. +37
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/todocenter/manage/HandlerManage.java
  48. +52
    -31
      hz-pm-api/src/main/java/com/hz/pm/api/todocenter/manage/TodoCenterManage.java
  49. +1
    -1
      hz-pm-gen/src/main/java/com/hz/pm/gen/config/CodeGen.java

+ 7
- 1
hz-pm-api/src/main/java/com/hz/pm/api/common/enumeration/ProjectProcessType.java View File

@@ -36,11 +36,17 @@ public enum ProjectProcessType {
ADAPTION(11, "适配改造审批流程"),
TEST_VALID(12, "测试验证审批流程"),
COMPLIANCE_REVIEW(13, "合规性审查流程"),
PROJECT_REVIEW(14, "项目评审流程");
PROJECT_REVIEW(14, "项目评审流程"),
PROJECT_STOPPED(15, "项目终止流程"),
PROJECT_CHANGE(16, "项目变更流程");

private final Integer code;
private final String desc;

public boolean eq(Integer code) {
return this.code.equals(code);
}

public static String getDesc(Integer code) {
if (Objects.isNull(code)) {
return StringUtils.EMPTY;


+ 27
- 1
hz-pm-api/src/main/java/com/hz/pm/api/common/statemachine/event/ProjectStateChangeEvent.java View File

@@ -79,12 +79,14 @@ public enum ProjectStateChangeEvent implements AbstractStateChangeEvent {

/**
* 立项备案通过
*
* @see ProjectStateChangeAction#DECLARED_RECORD_PASS(Message)
*/
DECLARED_RECORD_PASS(ProjectStatus.DECLARED_APPROVED_RECORD_AUDITING.getCode(), null, null),

/**
* 立项备案不通过
*
* @see ProjectStateChangeAction#DECLARED_RECORD_FAILED(Message)
*/
DECLARED_RECORD_FAILED(null, ProjectStatus.DECLARED_APPROVED_RECORD_AUDITING.getCode(), null),
@@ -93,33 +95,39 @@ public enum ProjectStateChangeEvent implements AbstractStateChangeEvent {

/**
* 发布采购公告
*
* @see ProjectStateChangeAction#SUBMIT_PURCHASE_NOTICE(Message)
*/
SUBMIT_PURCHASE_NOTICE(ProjectStatus.TO_BE_PURCHASED.getCode(), null, null),

/**
* 填写实施计划
*
* @see ProjectStateChangeAction#SUBMIT_OPERATION_PLAN(Message)
*/
SUBMIT_OPERATION_PLAN(ProjectStatus.ON_PURCHASING.getCode(), null, null),

/**
* 上传初验材料
*
* @see ProjectStateChangeAction#SUBMIT_FIRST_INSPECTED_FILES(Message)
*/
SUBMIT_FIRST_INSPECTED_FILES(ProjectStatus.TO_BE_FIRST_INSPECTED.getCode(), null, null),
/**
* 终验申请(项目状态变为:终验审核中)
*
* @see ProjectStateChangeAction#FINAL_ACCEPTANCE_APPLICATION(Message)
*/
FINAL_ACCEPTANCE_APPLICATION(ProjectStatus.ON_PILOT_RUNNING.getCode(), null, null),
/**
* 终验审核不通过(项目状态变为:终验审核不通过)
*
* @see ProjectStateChangeAction#FINAL_ACCEPTANCE_REJECT(Message)
*/
FINAL_ACCEPTANCE_REJECT(null, ProjectStatus.ON_FINALLY_INSPECTED.getCode(), null),
/**
* 终验审核通过(项目状态变为:已归档)
*
* @see ProjectStateChangeAction#FINAL_ACCEPTANCE_PASS(Message)
*/
FINAL_ACCEPTANCE_PASS(ProjectStatus.ON_FINALLY_INSPECTED.getCode(), null, null),
@@ -128,9 +136,27 @@ public enum ProjectStateChangeEvent implements AbstractStateChangeEvent {

/**
* 重新提交 终验
*
* @see ProjectStateChangeAction#FINAL_RE_ACCEPTANCE_APPLICATION(Message)
*/
FINAL_RE_ACCEPTANCE_APPLICATION(ProjectStatus.FINALLY_INSPECTED_FAILED.getCode(), null, null);
FINAL_RE_ACCEPTANCE_APPLICATION(ProjectStatus.FINALLY_INSPECTED_FAILED.getCode(), null, null),

/**
* 项目终止申请提交
*/
STOPPED_APPLY_SUBMIT(null, null, null),

/**
* 项目终止申请通过
*/
STOPPED_APPLY_PASS(null, null, null),
STOPPED_APPLY_AUTO_PASS(null, null, null),

STOPPED_APPLY_FAILED(null, null, null),

CHANGE_APPLY_SUBMIT(null, null, null),
CHANGE_APPLY_PASS(null, null, null),
CHANGE_APPLY_FAILED(null, null, null);


private final Integer passStatusCode;


+ 23
- 1
hz-pm-api/src/main/java/com/hz/pm/api/common/statemachine/event/TenderStateChangeEvent.java View File

@@ -42,8 +42,30 @@ public enum TenderStateChangeEvent implements AbstractStateChangeEvent {
/**
* 终验申报拒绝
*/
FINALLY_INSPECTED_FAILED(null, 501, null);
FINALLY_INSPECTED_FAILED(null, 501, null),

CHANGE_APPLY_SUBMIT(null, null, null),

CHANGE_APPLY_PASS(null, null, null),

CHANGE_APPLY_FAILED(null, null, null),

/**
* 项目终止申请提交
*/
STOPPED_APPLY_SUBMIT(null, null, null),

/**
* 项目终止申请通过
*/
STOPPED_APPLY_PASS(null, null, null),

STOPPED_APPLY_AUTO_PASS(null, null, null),

/**
* 项目终止申请拒绝
*/
STOPPED_APPLY_FAILED(null, null, null);

private final Integer passStatusCode;
private final Integer rejectStatusCode;


+ 38
- 0
hz-pm-api/src/main/java/com/hz/pm/api/common/util/MethodReferenceUtil.java View File

@@ -0,0 +1,38 @@
package com.hz.pm.api.common.util;

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;

import java.lang.reflect.Method;
import java.util.function.Function;

/**
* <p>
* MethodReferenceUtil
* </p>
*
* @author WendyYang
* @since 16:24 2024/8/6
*/
public class MethodReferenceUtil {

private MethodReferenceUtil() {
}

/**
* 根据属性名获取方法引用。
*
* @param field 属性名
* @return 方法引用
*/
public static <T> Function<T, Object> getReference(Class<T> clazz, String field) {
// 将属性名首字母大写
String methodName = StrUtil.upperFirst(field);
Method method = ReflectUtil.getMethod(clazz, "get" + methodName);
if (method == null) {
return null;
}
return obj -> ReflectUtil.invoke(obj, method);
}

}

+ 46
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/entity/ProjectChangeHistory.java View File

@@ -0,0 +1,46 @@
package com.hz.pm.api.projectdeclared.entity;

import com.baomidou.mybatisplus.annotation.*;
import io.swagger.annotations.ApiModel;
import lombok.Data;

import java.io.Serializable;
import java.time.LocalDateTime;

/**
* <p>
* 项目变更记录
* </p>
*
* @author WendyYang
* @since 2024-08-06
*/
@Data
@TableName("ND_PROJECT_CHANGE_HISTORY")
@ApiModel(value = "NdProjectChangeHistory对象")
public class ProjectChangeHistory implements Serializable {

private static final long serialVersionUID = 1L;

@TableId(value = "ID", type = IdType.AUTO)
private Long id;

private Long projectId;

private String instCode;

private String projectCode;

private String changeReason;

private String changeContent;

@TableField(fill = FieldFill.INSERT)
private Long createBy;

@TableField(fill = FieldFill.INSERT)
private LocalDateTime createOn;

private Integer status;

}

+ 16
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/mapper/ProjectChangeHistoryMapper.java View File

@@ -0,0 +1,16 @@
package com.hz.pm.api.projectdeclared.mapper;

import com.hz.pm.api.projectdeclared.entity.ProjectChangeHistory;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

/**
* <p>
* Mapper 接口
* </p>
*
* @author WendyYang
* @since 2024-08-06
*/
public interface ProjectChangeHistoryMapper extends BaseMapper<ProjectChangeHistory> {

}

+ 5
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/mapper/ProjectChangeHistoryMapper.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.hz.pm.api.projectdeclared.mapper.ProjectChangeHistoryMapper">

</mapper>

+ 77
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/model/dto/ContractDTO.java View File

@@ -0,0 +1,77 @@
package com.hz.pm.api.projectdeclared.model.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
* @Classname Contract
* @Description
* @Date 2023/5/30 15:35
* @Author PoffyZhang
*/
@Data
@ApiModel(value = "ContractVO")
public class ContractDTO {

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

@ApiModelProperty("创建时间")
private LocalDateTime createOn;

@ApiModelProperty("修改时间")
private LocalDateTime updateOn;

@ApiModelProperty("合同名称")
private String name;

@ApiModelProperty("合同总金额")
private BigDecimal totalAmount;

@ApiModelProperty("供应商开户行")
private String supplierBank;

@ApiModelProperty("供应商开户行帐号")
private String supplierAccount;

@ApiModelProperty("质保期 年")
private Integer warrantyPeriod;

@ApiModelProperty("质保金")
private BigDecimal retentionMoney;

@ApiModelProperty("合同完成时间")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDateTime contractTime;

@ApiModelProperty("交货日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDateTime deliveryTime;

@ApiModelProperty("附件")
private String attachment;

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

@ApiModelProperty("项目编号")
private String projectCode;

@ApiModelProperty("供应商联系人")
private String supplierContact;

@ApiModelProperty("供应商联系方式")
private String supplierContactInfo;

@ApiModelProperty("标段ID")
private Long bidId;

@ApiModelProperty("合同编号")
private String constructionNo;

}

+ 96
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/model/dto/OperationDTO.java View File

@@ -0,0 +1,96 @@
package com.hz.pm.api.projectdeclared.model.dto;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.time.LocalDateTime;

/**
* <p>
* OperationVO
* </p>
*
* @author WendyYang
* @since 09:28 2024/2/23
*/
@Data
@ApiModel("实施对象")
public class OperationDTO {

@ApiModelProperty("id")
private Long id;

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

@ApiModelProperty("项目Code")
private String projectCode;

@ApiModelProperty("创建时间")
private LocalDateTime createOn;

@ApiModelProperty("修改时间")
private LocalDateTime updateOn;

@ApiModelProperty("创建人 工号")
private String createBy;

@ApiModelProperty("修改人 工号")
private String updateBy;

@ApiModelProperty("项目开工时间")
private LocalDateTime projectStartDate;

@ApiModelProperty("初验时间")
private LocalDateTime initialInspectionDate;

@ApiModelProperty("终验时间")
private LocalDateTime finalInspectionDate;

@ApiModelProperty("标段ID")
private Long bidId;

@ApiModelProperty("试运行开始时间")
private LocalDateTime pilotRunStartDate;

@ApiModelProperty("开始实施时间")
private LocalDateTime startTrialOperationDate;

@ApiModelProperty("适配改造时间")
private LocalDateTime adaptationTime;

@ApiModelProperty("系统自测时间")
private LocalDateTime selfTestTime;

@ApiModelProperty("测试验证时间")
private LocalDateTime testValidTime;

@ApiModelProperty("实际完成适配改造时间")
private LocalDateTime actualAdaptionTime;

@ApiModelProperty("适配改造备注")
private String adaptionRemark;

@ApiModelProperty("适配改造附件")
private String adaptionFiles;

@ApiModelProperty("系统自测备注")
private String selfTestRemark;

@ApiModelProperty("系统自测附件")
private String selfTestFiles;

@ApiModelProperty("实际完成系统自测时间")
private LocalDateTime actualSelfTestTime;

@ApiModelProperty("实际完成测试验证时间")
private LocalDateTime actualTestValidTime;

@ApiModelProperty("测试验证备注")
private String testValidRemark;

@ApiModelProperty("测试验证附件")
private String testValidFiles;

}

+ 29
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/model/dto/PreInsAcceptancePersonDTO.java View File

@@ -0,0 +1,29 @@
package com.hz.pm.api.projectdeclared.model.dto;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
* <p>
* PreInsAcceptancePersonVO
* </p>
*
* @author WendyYang
* @since 14:34 2024/2/26
*/
@Data
public class PreInsAcceptancePersonDTO {

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

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

@ApiModelProperty("人员名称")
private String personName;

@ApiModelProperty("单位")
private String unit;

}

+ 28
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/model/dto/ProjectEditDTO.java View File

@@ -0,0 +1,28 @@
package com.hz.pm.api.projectdeclared.model.dto;

import com.hz.pm.api.projectdeclared.utils.BeanDiffUtil.FieldDiff;
import com.hz.pm.api.projectlib.model.dto.ProjectDTO;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.util.List;

/**
* <p>
* ProjectDetailDTO
* </p>
*
* @author WendyYang
* @since 19:53 2024/8/5
*/
@Data
public class ProjectEditDTO {

@ApiModelProperty("项目信息")
private ProjectDTO project;

private List<FieldDiff> projectDiffs;

private List<PurchaseEditDTO> purchases;

}

+ 177
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/model/dto/PurchaseDTO.java View File

@@ -0,0 +1,177 @@
package com.hz.pm.api.projectdeclared.model.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;

import javax.validation.constraints.NotBlank;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;

/**
* @Classname Purchase
* @Description
* @Date 2023/5/29 10:00
* @Author PoffyZhang
*/
@Data
@ApiModel(value = "采购对象")
@AllArgsConstructor
public class PurchaseDTO {

@ApiModelProperty("id")
private Long id;

@ApiModelProperty("标段状态")
private Integer status;

@ApiModelProperty("标段状态名称")
private String statusName;

@ApiModelProperty("标段预算")
private BigDecimal bidBudget;

@ApiModelProperty("标段名称")
private String bidName;

@ApiModelProperty("标段类型")
private Integer bidType;

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

@ApiModelProperty("创建时间")
private LocalDateTime createOn;

@ApiModelProperty("修改时间")
private LocalDateTime updateOn;

@ApiModelProperty("创建人 工号")
private String createBy;

@ApiModelProperty("修改人 工号")
private String updateBy;

@ApiModelProperty("供应商")
private String supplier;

@ApiModelProperty("供应商联系人")
private String supplierContact;

@ApiModelProperty("供应商联系方式")
private String supplierContactInfo;

@ApiModelProperty("供应商社会信用代码")
private String supplierSocialCreditCode;

@ApiModelProperty("采购方式 1公开招标 2自行采购")
private String purchaseMethod;

@ApiModelProperty("成交金额")
private BigDecimal transactionAmount;

@ApiModelProperty("成交时间")
private LocalDateTime transactionTime;

@ApiModelProperty("代理机构")
private String agency;

@ApiModelProperty("投标地址(政府采购网地址)")
private String bidAddress;

@ApiModelProperty("开标时间")
private LocalDateTime bidStartTime;

@ApiModelProperty("投标截止时间")
private LocalDateTime bidEndTime;

@ApiModelProperty("代理机构社会统一信用代码")
private String purchaseSocialCreditCode;

@ApiModelProperty("投标文件")
private String biddingDoc;

@ApiModelProperty("招标文件")
private String bidDoc;

@ApiModelProperty("中标通知书")
private String acceptanceLetter;

@ApiModelProperty("预算执行确认书编号")
private String budgetExecConfirmNo;

@ApiModelProperty("标段建设内容")
private String bidBuildContent;

@ApiModelProperty("采购范围:1 公开采购、2 非公开采购")
private Integer purchaseScope;

@ApiModelProperty("采购单位")
private String purchaseUnit;

@ApiModelProperty("采购联系人")
private String purchaseContact;

@ApiModelProperty("采购联系电话")
private String purchasePhone;

@ApiModelProperty("采购联系地址")
private String purchaseConnectAddress;

@ApiModelProperty("采购说明")
private String purchaseRemark;

@ApiModelProperty("是否符合信创符合性要求")
private Boolean matchXcfhx;

@ApiModelProperty("备注")
private String xcfhxApplyRemark;

@ApiModelProperty("其他附件")
private String xcfhxApplyFiles;

@ApiModelProperty("信创报告")
private String xcfhxReportFiles;

@ApiModelProperty("信创符合性测评报告文件")
@NotBlank(message = "信创符合性测评报告文件不能为空")
private String mhXcfhxReportFile;

@ApiModelProperty("信创符合性测评记录ID")
@NotBlank(message = "信创符合性测评记录ID不能为空")
private String mhXcfhxReportRecordId;

@ApiModelProperty("初验材料")
@NotBlank(message = "请提交初验材料")
private String preliminaryInspectionMaterials;

@ApiModelProperty("初验 是否完成日志数据归集")
private Boolean isCompletedLogCollection;

@ApiModelProperty("初验 实际成效指标")
private String actualPerformanceIndicators;

@ApiModelProperty("终验申报材料")
private String finalInspectionMaterials;

@ApiModelProperty("资源类型 1手动新增 2系统生成 3大数据局")
private Integer sourceType;

@ApiModelProperty("项目名称")
private String projectName;

@ApiModelProperty("标项支付金额")
private BigDecimal bidPayAmount;

@ApiModelProperty("采购时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private LocalDate purchaseDate;

@ApiModelProperty("是否发布信创云图")
public Boolean publishMhNotice;


}

+ 35
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/model/dto/PurchaseEditDTO.java View File

@@ -0,0 +1,35 @@
package com.hz.pm.api.projectdeclared.model.dto;

import com.hz.pm.api.projectdeclared.utils.BeanDiffUtil.FieldDiff;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.util.List;

/**
* <p>
* PurchaseEditDTO
* </p>
*
* @author WendyYang
* @since 11:12 2024/8/6
*/
@Data
public class PurchaseEditDTO {

@ApiModelProperty("采购信息")
private PurchaseDTO purchase;

private List<FieldDiff> purchaseDiffs;

@ApiModelProperty("合同信息")
private ContractDTO contract;

private List<FieldDiff> contractDiffs;

@ApiModelProperty("实施信息")
private OperationDTO operation;

private List<FieldDiff> operationDiffs;

}

+ 2
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/model/dto/PurchaseSaveDTO.java View File

@@ -86,4 +86,6 @@ public class PurchaseSaveDTO {
@ApiModelProperty("资源类型 1手动新增 2系统生成 3大数据局")
private Integer sourceType = PurchaseSourceTypeEnum.SYSTEM_AUTO.getCode();
}


}

+ 16
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/service/IProjectChangeHistoryService.java View File

@@ -0,0 +1,16 @@
package com.hz.pm.api.projectdeclared.service;

import com.hz.pm.api.projectdeclared.entity.ProjectChangeHistory;
import com.baomidou.mybatisplus.extension.service.IService;

/**
* <p>
* 服务类
* </p>
*
* @author WendyYang
* @since 2024-08-06
*/
public interface IProjectChangeHistoryService extends IService<ProjectChangeHistory> {

}

+ 20
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/service/impl/ProjectChangeHistoryServiceImpl.java View File

@@ -0,0 +1,20 @@
package com.hz.pm.api.projectdeclared.service.impl;

import com.hz.pm.api.projectdeclared.entity.ProjectChangeHistory;
import com.hz.pm.api.projectdeclared.mapper.ProjectChangeHistoryMapper;
import com.hz.pm.api.projectdeclared.service.IProjectChangeHistoryService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

/**
* <p>
* 服务实现类
* </p>
*
* @author WendyYang
* @since 2024-08-06
*/
@Service
public class ProjectChangeHistoryServiceImpl extends ServiceImpl<ProjectChangeHistoryMapper, ProjectChangeHistory> implements IProjectChangeHistoryService {

}

+ 126
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/utils/BeanDiffUtil.java View File

@@ -0,0 +1,126 @@
package com.hz.pm.api.projectdeclared.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjUtil;
import lombok.Builder;
import lombok.Data;

import java.util.*;

/**
* <p>
* BeanDiffUtil
* </p>
*
* @author WendyYang
* @since 10:27 2024/8/6
*/
public class BeanDiffUtil {

private BeanDiffUtil() {
}

@Data
@Builder
public static class FieldDiff {

private String fieldName;

private String fileType;

private Object oldValue;

private Object newValue;

}

/**
* 比较两个对象的不同属性值,包括嵌套的对象属性。
*
* @param obj1 第一个对象
* @param obj2 第二个对象
* @return 返回一个 Map,其中 key 是不同属性的名称,value 是一个包含两个值的数组,第一个值来自 obj1,第二个值来自 obj2
*/
private static List<FieldDiff> diff(Object obj1, Object obj2, boolean diffSameField, String... ignoreFields) {
Map<String, Object> map1 = BeanUtil.beanToMap(obj1);
Map<String, Object> map2 = BeanUtil.beanToMap(obj2);
if (ArrayUtil.isNotEmpty(ignoreFields)) {
for (String ignoreField : ignoreFields) {
map2.remove(ignoreField);
map1.remove(ignoreField);
}
}
// 创建结果 Map
List<FieldDiff> result = new ArrayList<>();

// 获取两个 Map 的 keySet
Set<String> keys1 = map1.keySet();
Set<String> keys2 = map2.keySet();

// 计算不同的属性
Collection<String> diffKeys = CollUtil.disjunction(keys1, keys2);

if (!diffSameField) {
// 输出不同的属性及其值
for (String key : diffKeys) {
Object oldValue = map1.getOrDefault(key, null);
Object newValue = map2.getOrDefault(key, null);
result.add(FieldDiff.builder()
.fieldName(key)
.fileType((oldValue == null ? newValue.getClass() : oldValue.getClass()).getTypeName())
.oldValue(oldValue)
.newValue(newValue)
.build());
}

}

// 输出相同的属性,但是值不同
Collection<String> commonKeys = CollUtil.intersection(keys1, keys2);
for (String key : commonKeys) {
Object value1 = map1.get(key);
Object value2 = map2.get(key);
if (value1 == null && value2 == null) {
continue;
}
Class<?> valueClass = value1 == null ? value2.getClass() : value1.getClass();
// 如果是嵌套对象,则递归比较
if (!BeanUtil.isBean(valueClass) && !ObjUtil.equals(value1, value2)) {
Object oldValue = map1.getOrDefault(key, null);
Object newValue = map2.getOrDefault(key, null);
result.add(FieldDiff.builder()
.fieldName(key)
.fileType((oldValue == null ? newValue.getClass() : oldValue.getClass()).getTypeName())
.oldValue(oldValue)
.newValue(newValue)
.build());
}
}

return result;
}

/**
* 比较两个对象的不同属性值,包括嵌套的对象属性。
*
* @param obj1 第一个对象
* @param obj2 第二个对象
* @return 返回一个 Map,其中 key 是不同属性的名称,value 是一个包含两个值的数组,第一个值来自 obj1,第二个值来自 obj2
*/
public static List<FieldDiff> diffSameField(Object obj1, Object obj2, String... ignoreFields) {
return diff(obj1, obj2, true, ignoreFields);
}

/**
* 比较两个对象的不同属性值,包括嵌套的对象属性。
*
* @param obj1 第一个对象
* @param obj2 第二个对象
* @return 返回一个 Map,其中 key 是不同属性的名称,value 是一个包含两个值的数组,第一个值来自 obj1,第二个值来自 obj2
*/
public static List<FieldDiff> diff(Object obj1, Object obj2, String... ignoreFields) {
return diff(obj1, obj2, false, ignoreFields);
}
}

+ 36
- 9
hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/utils/ProjectIdCodeCacheUtil.java View File

@@ -6,13 +6,16 @@ import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hz.pm.api.projectlib.model.entity.Project;
import com.hz.pm.api.projectlib.service.IProjectService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@@ -29,40 +32,64 @@ import java.util.stream.Collectors;
@RequiredArgsConstructor
public class ProjectIdCodeCacheUtil {

@Data
private static class IdCodeCacheDTO {

private Long projectId;

private String projectCode;

private LocalDateTime createOn;

private Boolean newest;

}

private final IProjectService projectService;

@PostConstruct
public void initProjectIdCodeCache() {
Wrapper<Project> query = Wrappers.lambdaQuery(Project.class)
.select(Project::getProjectCode, Project::getId);
.select(Project::getProjectCode, Project::getId, Project::getCreateOn, Project::getNewest);
for (Project project : projectService.list(query)) {
put(project.getId(), project.getProjectCode());
put(project.getId(), project);
}
log.info("初始化项目ID编码缓存:{}", CACHE.size());
}

//==================================================================================================================

private static final Map<Long, String> CACHE = new ConcurrentHashMap<>();
private static final Map<Long, IdCodeCacheDTO> CACHE = new ConcurrentHashMap<>();

public static String get(Long projectId) {
return CACHE.get(projectId);
return Optional.ofNullable(CACHE.get(projectId))
.flatMap(w -> Optional.of(w.getProjectCode()))
.orElse(null);
}

public static List<Long> get(String projectCode) {
return CACHE.entrySet()
.stream()
.filter(w -> w.getValue().equals(projectCode))
.filter(w -> w.getValue().getProjectCode().equals(projectCode))
.map(Map.Entry::getKey)
.collect(Collectors.toList());
}

public static void put(Long projectId, String projectCode) {
CACHE.put(projectId, projectCode);
public static void put(Long projectId, Project project) {
IdCodeCacheDTO idCodeCache = new IdCodeCacheDTO();
idCodeCache.setProjectId(project.getId());
idCodeCache.setProjectCode(project.getProjectCode());
idCodeCache.setCreateOn(project.getCreateOn());
idCodeCache.setNewest(project.getNewest());
CACHE.put(projectId, idCodeCache);
}

public static Long newest(String projectCode) {
return CollUtil.max(get(projectCode));
return get(projectCode).stream().map(CACHE::get)
.filter(IdCodeCacheDTO::getNewest)
.findFirst()
.flatMap(w -> Optional.of(w.getProjectId()))
.orElse(null);
}

public static Long newest(Long projectId) {
@@ -70,7 +97,7 @@ public class ProjectIdCodeCacheUtil {
if (StrUtil.isBlank(projectCode)) {
return projectId;
}
return CollUtil.max(get(projectCode));
return newest(projectCode);
}

}

+ 88
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/controller/ProjectStoppedChangeController.java View File

@@ -0,0 +1,88 @@
package com.hz.pm.api.projectlib.controller;

import com.hz.pm.api.projectlib.manage.ProjectChangeManage;
import com.hz.pm.api.projectlib.manage.ProjectStoppedManage;
import com.hz.pm.api.projectlib.model.req.ProjectListReq;
import com.hz.pm.api.projectlib.model.req.SubmitProjectChangeApplyReq;
import com.hz.pm.api.projectlib.model.req.SubmitProjectStoppedApplyReq;
import com.hz.pm.api.projectlib.model.vo.ProjectChangeDetailVO;
import com.hz.pm.api.projectlib.model.vo.ProjectChangeListVO;
import com.hz.pm.api.projectlib.model.vo.ProjectLibListItemVO;
import com.ningdatech.basic.model.PageVo;
import com.ningdatech.log.annotation.WebLog;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;

/**
* <p>
* ProjectStoppedController
* </p>
*
* @author WendyYang
* @since 11:03 2024/8/5
*/
@RestController
@Api(tags = "项目终止控制器")
@RequestMapping("/api/v1/project")
@RequiredArgsConstructor
public class ProjectStoppedChangeController {

private final ProjectStoppedManage projectStoppedManage;
private final ProjectChangeManage projectChangeManage;

@PostMapping("/stopped/submitApply")
@ApiOperation("提交项目终止申请")
@WebLog("提交项目终止申请")
public void submitProjectStoppedApply(@RequestBody @Valid SubmitProjectStoppedApplyReq req) {
projectStoppedManage.submitProjectStoppedApply(req);
}

@PostMapping("/change/submitApply")
@ApiOperation("提交项目变更申请")
@WebLog("提交项目变更申请")
public void submitProjectChangeApply(@RequestBody @Valid SubmitProjectChangeApplyReq req) {
projectChangeManage.submitProjectChangeApply(req);
}

@GetMapping("/stopped/page")
@ApiOperation("项目终止列表")
@WebLog("项目终止列表")
public PageVo<ProjectLibListItemVO> pageStopped(ProjectListReq req) {
return projectStoppedManage.page(req);
}

@GetMapping("/stopped/options")
@ApiOperation("项目终止下拉筛选")
@WebLog("项目终止下拉筛选")
public List<ProjectLibListItemVO> stoppedOptions() {
return projectStoppedManage.options();
}

@GetMapping("/change/page")
@ApiOperation("项目变更列表")
@WebLog("项目变更列表")
public PageVo<ProjectChangeListVO> pageChange(ProjectListReq req) {
return projectChangeManage.page(req);
}

@GetMapping("/change/detail/{projectCode}/{instCode}")
@ApiOperation("项目变更详情")
@WebLog("项目变更详情")
public ProjectChangeDetailVO changeDetail(@PathVariable("projectCode") String projectCode,
@PathVariable("instCode") String instCode) {
return projectChangeManage.changeDetail(projectCode, instCode);
}

@GetMapping("/change/options")
@ApiOperation("项目变更下拉筛选")
@WebLog("项目变更下拉筛选")
public List<ProjectLibListItemVO> changeOptions() {
return projectChangeManage.options();
}

}

+ 8
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/entity/PurchaseStatusChange.java View File

@@ -3,7 +3,9 @@ package com.hz.pm.api.projectlib.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Builder;
import lombok.Data;
import lombok.experimental.Tolerate;

import java.io.Serializable;
import java.time.LocalDateTime;
@@ -17,11 +19,17 @@ import java.time.LocalDateTime;
* @since 2024-04-01
*/
@Data
@Builder
@TableName("ND_PURCHASE_STATUS_CHANGE")
public class PurchaseStatusChange implements Serializable {

private static final long serialVersionUID = 1L;

@Tolerate
public PurchaseStatusChange() {
// no-args constructor
}

@TableId(value = "ID", type = IdType.AUTO)
private Long id;



+ 291
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/helper/ProjectChangeStopHelper.java View File

@@ -0,0 +1,291 @@
package com.hz.pm.api.projectlib.helper;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.hz.pm.api.common.model.constant.BizConst;
import com.hz.pm.api.common.statemachine.event.ProjectStateChangeEvent;
import com.hz.pm.api.common.statemachine.event.TenderStateChangeEvent;
import com.hz.pm.api.common.util.MethodReferenceUtil;
import com.hz.pm.api.projectdeclared.entity.ProjectChangeHistory;
import com.hz.pm.api.projectdeclared.model.dto.*;
import com.hz.pm.api.projectdeclared.model.entity.Contract;
import com.hz.pm.api.projectdeclared.model.entity.Operation;
import com.hz.pm.api.projectdeclared.model.entity.Purchase;
import com.hz.pm.api.projectdeclared.service.IContractService;
import com.hz.pm.api.projectdeclared.service.IOperationService;
import com.hz.pm.api.projectdeclared.service.IProjectChangeHistoryService;
import com.hz.pm.api.projectdeclared.service.IPurchaseService;
import com.hz.pm.api.projectdeclared.utils.BeanDiffUtil.FieldDiff;
import com.hz.pm.api.projectlib.entity.PurchaseStatusChange;
import com.hz.pm.api.projectlib.manage.ProjectGovSystemReplaceInfoManage;
import com.hz.pm.api.projectlib.manage.ProjectLibManage;
import com.hz.pm.api.projectlib.model.dto.ProjectDTO;
import com.hz.pm.api.projectlib.model.entity.Project;
import com.hz.pm.api.projectlib.model.entity.ProjectStatusChange;
import com.hz.pm.api.projectlib.model.enumeration.status.*;
import com.hz.pm.api.projectlib.service.IProjectService;
import com.hz.pm.api.projectlib.service.IProjectStatusChangeService;
import com.hz.pm.api.projectlib.service.IPurchaseStatusChangeService;
import com.ningdatech.basic.exception.BizException;
import com.ningdatech.basic.util.CollUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

/**
* <p>
* ProjectChangeStopHelper
* </p>
*
* @author WendyYang
* @since 14:37 2024/8/5
*/
@Component
@RequiredArgsConstructor
public class ProjectChangeStopHelper {

private final IProjectChangeHistoryService projectChangeHistoryService;
private final IPurchaseStatusChangeService purchaseStatusChangeService;
private final IProjectStatusChangeService projectStatusChangeService;
private final IPurchaseService purchaseService;
private final IOperationService operationService;
private final IContractService contractService;
private final IProjectService projectService;
private final ProjectGovSystemReplaceInfoManage projectGovSystemReplaceInfoManage;
private final ProjectLibManage projectLibManage;

/**
* 根据状态变更记录重置项目、标段状态
*
* @param project 项目
* @param event event
*/
public void changeProjectPurchaseStatus(Project project, ProjectStateChangeEvent event) {
TenderStateChangeEvent tenderEvent = TenderStateChangeEvent.valueOf(event.name());
ProjectStateChangeEvent beforeEvent;
TenderStateChangeEvent tenderBeforeEvent;
if (event.equals(ProjectStateChangeEvent.STOPPED_APPLY_FAILED)) {
beforeEvent = ProjectStateChangeEvent.STOPPED_APPLY_SUBMIT;
tenderBeforeEvent = TenderStateChangeEvent.STOPPED_APPLY_SUBMIT;
} else if (event.equals(ProjectStateChangeEvent.CHANGE_APPLY_FAILED)
|| event.equals(ProjectStateChangeEvent.CHANGE_APPLY_PASS)) {
beforeEvent = ProjectStateChangeEvent.CHANGE_APPLY_SUBMIT;
tenderBeforeEvent = TenderStateChangeEvent.CHANGE_APPLY_SUBMIT;
} else if (event.equals(ProjectStateChangeEvent.STOPPED_APPLY_SUBMIT)
|| event.equals(ProjectStateChangeEvent.CHANGE_APPLY_SUBMIT)
|| event.equals(ProjectStateChangeEvent.STOPPED_APPLY_PASS)
|| event.equals(ProjectStateChangeEvent.STOPPED_APPLY_AUTO_PASS)) {
// 提交的时候不重置项目、标项状态
beforeEvent = null;
tenderBeforeEvent = null;
ProjectStatus status;
TenderStatus tenderStatus;
if (event.equals(ProjectStateChangeEvent.STOPPED_APPLY_SUBMIT)) {
status = ProjectStatus.ON_STOPPED_APPLY;
tenderStatus = TenderStatus.ON_STOPPED_APPLY;
} else if (event.equals(ProjectStateChangeEvent.CHANGE_APPLY_SUBMIT)) {
status = ProjectStatus.ON_CHANGE_APPLY;
tenderStatus = TenderStatus.ON_CHANGE_APPLY;
} else {
project.setStoppedStatus(buildBizStatus(event).getCode());
status = ProjectStatus.STOPPED_PASSED;
tenderStatus = TenderStatus.STOPPED_PASSED;
}
ProjectStatusChange projectStatusChange = ProjectStatusChange.builder()
.event(event.name())
.projectId(project.getId())
.event(event.name())
.projectCode(project.getProjectCode())
.beforeStatus(project.getStatus())
.afterStatus(status.getCode())
.build();
projectStatusChangeService.save(projectStatusChange);
project.setStage(project.getStatus() - project.getStatus() % 10000);
projectService.updateById(project);
List<Purchase> purchases = purchaseService.listByProjectId(project.getId());
List<PurchaseStatusChange> purchaseStatusChanges = CollUtils.convert(purchases,
purchase -> PurchaseStatusChange.builder()
.bidId(purchase.getId())
.event(tenderEvent.name())
.projectId(project.getId())
.projectCode(project.getProjectCode())
.beforeStatus(purchase.getStatus())
.afterStatus(tenderStatus.getCode())
.build());
purchaseStatusChangeService.saveBatch(purchaseStatusChanges);
} else {
throw new BizException("不支持的状态转换");
}
resetProjectPurchaseStatus(project, event, beforeEvent, tenderBeforeEvent, tenderEvent);
}

private void resetProjectPurchaseStatus(Project project,
ProjectStateChangeEvent projEvent,
ProjectStateChangeEvent projBeforeEvent,
TenderStateChangeEvent tenderBeforeEvent,
TenderStateChangeEvent tenderEvent) {
if (projBeforeEvent != null) {
if (projEvent.equals(ProjectStateChangeEvent.STOPPED_APPLY_FAILED)) {
project.setStoppedStatus(buildBizStatus(projBeforeEvent).getCode());
} else {
Wrapper<ProjectChangeHistory> changeHistoryWrapper = Wrappers.lambdaQuery(ProjectChangeHistory.class)
.eq(ProjectChangeHistory::getProjectCode, project.getProjectCode())
.orderByDesc(ProjectChangeHistory::getCreateOn)
.last(BizConst.LIMIT_1);
ProjectChangeHistory changeHistory = projectChangeHistoryService.getOne(changeHistoryWrapper);
changeHistory.setStatus(buildBizStatus(projEvent).getCode());
projectChangeHistoryService.updateById(changeHistory);
if (projEvent.equals(ProjectStateChangeEvent.CHANGE_APPLY_PASS)) {
projectEditRewrite(JSONUtil.toBean(changeHistory.getChangeContent(), ProjectEditDTO.class));
}
}
ProjectStatusChange change = projectStatusChangeService.getLastOne(projBeforeEvent, project.getId());
projectStatusChangeService.save(ProjectStatusChange.builder()
.event(projEvent.name())
.projectId(project.getId())
.event(projEvent.name())
.projectCode(project.getProjectCode())
.beforeStatus(change.getAfterStatus())
.afterStatus(change.getBeforeStatus())
.createOn(project.getCreateOn())
.build());
project.setStatus(change.getBeforeStatus());
project.setStage(project.getStatus() - project.getStatus() % 10000);
projectService.updateById(project);
List<Purchase> purchases = purchaseService.listByProjectId(project.getId());
if (!purchases.isEmpty()) {
Wrapper<PurchaseStatusChange> purchaseStatusChangeQuery = Wrappers.lambdaQuery(PurchaseStatusChange.class)
.eq(PurchaseStatusChange::getProjectId, project.getId())
.eq(PurchaseStatusChange::getEvent, tenderBeforeEvent);
List<PurchaseStatusChange> purchaseStatusChanges = purchaseStatusChangeService.list(purchaseStatusChangeQuery);
Map<Long, PurchaseStatusChange> purchaseStatusChangeMap = CollUtils.listToMap(purchaseStatusChanges, PurchaseStatusChange::getBidId);
List<PurchaseStatusChange> changeArrayList = new ArrayList<>();
purchases.forEach(purchase -> {
PurchaseStatusChange currChange = purchaseStatusChangeMap.get(purchase.getId());
purchase.setStatus(currChange.getBeforeStatus());
changeArrayList.add(PurchaseStatusChange.builder()
.afterStatus(currChange.getBeforeStatus())
.beforeStatus(currChange.getAfterStatus())
.bidId(purchase.getId())
.event(tenderEvent.name())
.projectId(project.getId())
.projectCode(project.getProjectCode())
.build());
});
purchaseService.updateBatchById(purchases);
purchaseStatusChangeService.saveBatch(changeArrayList);
}
}
}

private IStatus<Integer, String> buildBizStatus(ProjectStateChangeEvent event) {
IStatus<Integer, String> bizStatus;
switch (event) {
case STOPPED_APPLY_PASS:
case STOPPED_APPLY_AUTO_PASS:
bizStatus = ProjectStoppedStatus.STOPPED_PASSED;
break;
case STOPPED_APPLY_SUBMIT:
bizStatus = ProjectStoppedStatus.ON_STOPPED_APPLY;
break;
case STOPPED_APPLY_FAILED:
bizStatus = ProjectStoppedStatus.STOPPED_FAILED;
break;
case CHANGE_APPLY_SUBMIT:
bizStatus = ProjectChangeStatus.ON_CHANGE_APPLY;
break;
case CHANGE_APPLY_PASS:
bizStatus = ProjectChangeStatus.CHANGE_PASSED;
break;
case CHANGE_APPLY_FAILED:
bizStatus = ProjectChangeStatus.CHANGE_FAILED;
break;
default:
bizStatus = null;
break;
}
return bizStatus;
}

private void projectEditRewrite(ProjectEditDTO projectEdit) {
List<FieldDiff> projectDiffs = projectEdit.getProjectDiffs();
if (projectDiffs != null && !projectDiffs.isEmpty()) {
ProjectDTO projectDetail = projectEdit.getProject();
LambdaUpdateWrapper<Project> wrapper = Wrappers.lambdaUpdate(Project.class);
projectDiffs.forEach(fieldDiff -> {
String fieldName = fieldDiff.getFieldName();
Object newValue = fieldDiff.getNewValue();
Function<Project, Object> reference = MethodReferenceUtil.getReference(Project.class, fieldName);
if (reference != null) {
wrapper.set((SFunction<Project, Object>) reference, newValue);
}
if (ProjectDTO.SYSTEM_REPLACE_INFOS.equals(fieldName)) {
projectLibManage.saveGovSystemReplaceInfos(projectDetail.getId(),
projectDetail.getProjectCode(),
projectDetail.getSystemReplaceInfos());
}
});
wrapper.eq(Project::getId, projectDetail.getId());
projectService.update(wrapper);
}
List<PurchaseEditDTO> purchases = projectEdit.getPurchases();
if (CollUtil.isNotEmpty(purchases)) {
for (PurchaseEditDTO purchaseEdit : purchases) {
List<FieldDiff> purchaseDiffs = purchaseEdit.getPurchaseDiffs();
if (CollUtil.isNotEmpty(purchaseDiffs)) {
PurchaseDTO purchaseDetail = purchaseEdit.getPurchase();
LambdaUpdateWrapper<Purchase> wrapper = Wrappers.lambdaUpdate(Purchase.class);
purchaseDiffs.forEach(fieldDiff -> {
String fieldName = fieldDiff.getFieldName();
Object newValue = fieldDiff.getNewValue();
Function<Purchase, Object> reference = MethodReferenceUtil.getReference(Purchase.class, fieldName);
if (reference != null) {
wrapper.set((SFunction<Purchase, Object>) reference, newValue);
}
});
wrapper.eq(Purchase::getId, purchaseDetail.getId());
purchaseService.update(wrapper);
}
List<FieldDiff> contractDiffs = purchaseEdit.getContractDiffs();
if (CollUtil.isNotEmpty(contractDiffs)) {
ContractDTO contractDetail = purchaseEdit.getContract();
LambdaUpdateWrapper<Contract> wrapper = Wrappers.lambdaUpdate(Contract.class);
contractDiffs.forEach(fieldDiff -> {
String fieldName = fieldDiff.getFieldName();
Object newValue = fieldDiff.getNewValue();
Function<Contract, Object> reference = MethodReferenceUtil.getReference(Contract.class, fieldName);
if (reference != null) {
wrapper.set((SFunction<Contract, Object>) reference, newValue);
}
});
wrapper.eq(Contract::getId, contractDetail.getId());
contractService.update(wrapper);
}
List<FieldDiff> operationDiffs = purchaseEdit.getOperationDiffs();
if (CollUtil.isNotEmpty(operationDiffs)) {
OperationDTO operationDetail = purchaseEdit.getOperation();
LambdaUpdateWrapper<Operation> wrapper = Wrappers.lambdaUpdate(Operation.class);
operationDiffs.forEach(fieldDiff -> {
String fieldName = fieldDiff.getFieldName();
Object newValue = fieldDiff.getNewValue();
Function<Operation, Object> reference = MethodReferenceUtil.getReference(Operation.class, fieldName);
if (reference != null) {
wrapper.set((SFunction<Operation, Object>) reference, newValue);
}
});
wrapper.eq(Operation::getId, operationDetail.getId());
operationService.update(wrapper);
}
}
}
}

}

+ 218
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/manage/ProjectChangeManage.java View File

@@ -0,0 +1,218 @@
package com.hz.pm.api.projectlib.manage;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hz.pm.api.common.enumeration.ProjectProcessType;
import com.hz.pm.api.external.model.enumeration.MhUnitStripEnum;
import com.hz.pm.api.projectdeclared.entity.ProjectChangeHistory;
import com.hz.pm.api.projectdeclared.manage.DeclaredProjectHelper;
import com.hz.pm.api.projectdeclared.model.dto.*;
import com.hz.pm.api.projectdeclared.model.vo.ContractVO;
import com.hz.pm.api.projectdeclared.model.vo.OperationVO;
import com.hz.pm.api.projectdeclared.model.vo.PurchaseFullInfoVO;
import com.hz.pm.api.projectdeclared.model.vo.PurchaseVO;
import com.hz.pm.api.projectdeclared.service.IProjectChangeHistoryService;
import com.hz.pm.api.projectdeclared.utils.BeanDiffUtil;
import com.hz.pm.api.projectdeclared.utils.BeanDiffUtil.FieldDiff;
import com.hz.pm.api.projectlib.helper.ProjectChangeStopHelper;
import com.hz.pm.api.projectlib.helper.ProjectManageUtil;
import com.hz.pm.api.projectlib.model.dto.GovSystemReplaceInfoDTO;
import com.hz.pm.api.projectlib.model.dto.ProjectChangeListDTO;
import com.hz.pm.api.projectlib.model.dto.ProjectDTO;
import com.hz.pm.api.projectlib.model.entity.Project;
import com.hz.pm.api.projectlib.model.entity.ProjectInst;
import com.hz.pm.api.projectlib.model.enumeration.status.ProjectChangeStatus;
import com.hz.pm.api.projectlib.model.enumeration.status.ProjectStatus;
import com.hz.pm.api.projectlib.model.req.ProjectListReq;
import com.hz.pm.api.projectlib.model.req.SubmitProjectChangeApplyReq;
import com.hz.pm.api.projectlib.model.vo.ProjectChangeDetailVO;
import com.hz.pm.api.projectlib.model.vo.ProjectChangeListVO;
import com.hz.pm.api.projectlib.model.vo.ProjectDetailVO;
import com.hz.pm.api.projectlib.model.vo.ProjectLibListItemVO;
import com.hz.pm.api.projectlib.service.IProjectInstService;
import com.hz.pm.api.projectlib.service.IProjectService;
import com.hz.pm.api.sys.manage.ProcessModelManage;
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.model.ITree;
import com.ningdatech.basic.model.PageVo;
import com.ningdatech.basic.util.CollUtils;
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.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.hz.pm.api.common.statemachine.event.ProjectStateChangeEvent.CHANGE_APPLY_SUBMIT;

/**
* <p>
* ProjectStoppedManage
* </p>
*
* @author WendyYang
* @since 11:04 2024/8/5
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class ProjectChangeManage {

private final IProjectService projectService;
private final IProjectInstService projectInstService;
private final ProcessInstanceService processInstanceService;
private final ProcessModelManage processModelManage;
private final DeclaredProjectHelper declaredProjectHelper;
private final ProjectChangeStopHelper projectChangeStopHelper;
private final ProjectLibManage projectLibManage;
private final IProjectChangeHistoryService projectChangeHistoryService;

@Transactional(rollbackFor = Exception.class)
public synchronized void submitProjectChangeApply(SubmitProjectChangeApplyReq req) {
ProjectEditDTO projectEdit = req.getProjectEditDetail();
ProjectDTO reqProject = projectEdit.getProject();
Project project = projectService.getNewProject(reqProject.getId());
if (ProjectStatus.ON_CHANGE_APPLY.eq(project.getStatus()) ||
ProjectStatus.STOPPED_PASSED.eq(project.getStatus())) {
throw BizException.wrap("暂无法提交变更申请");
}
ProjectDetailVO projDetailOld = projectLibManage.getProjectDetail(project);

List<FieldDiff> projDiffs = BeanDiffUtil.diffSameField(projDetailOld, reqProject,
ProjectDTO.SYSTEM_REPLACE_INFOS);
List<GovSystemReplaceInfoDTO> systemReplaceInfos = reqProject.getSystemReplaceInfos();
List<GovSystemReplaceInfoDTO> systemReplaceInfosOld = projDetailOld.getSystemReplaceInfos();
if (!CollUtil.isEqualList(systemReplaceInfos, systemReplaceInfosOld)) {
projDiffs.add(FieldDiff.builder()
.fieldName("systemReplaceInfos")
.fileType(List.class.getTypeName())
.oldValue(systemReplaceInfosOld)
.newValue(systemReplaceInfos)
.build());
}
projectEdit.setProjectDiffs(projDiffs);
List<PurchaseFullInfoVO> purchaseDetails = projDetailOld.getPurchaseDetails();
if (purchaseDetails != null && !purchaseDetails.isEmpty()) {
Map<Long, PurchaseEditDTO> reqPurchaseMap = CollUtils.listToMap(projectEdit.getPurchases(),
w -> w.getPurchase().getId());
for (PurchaseFullInfoVO purchaseDetail : purchaseDetails) {
PurchaseVO purchase = purchaseDetail.getPurchase();
ContractVO contract = purchaseDetail.getConstruction();
OperationVO operation = purchaseDetail.getOperation();

PurchaseEditDTO reqPurchaseDetail = reqPurchaseMap.get(purchase.getId());
PurchaseDTO reqPurchase = reqPurchaseDetail.getPurchase();
OperationDTO reqOperation = reqPurchaseDetail.getOperation();
ContractDTO reqContract = reqPurchaseDetail.getContract();

List<FieldDiff> purchaseDiffs = BeanDiffUtil.diffSameField(purchase, reqPurchase);
List<FieldDiff> operationDiffs = BeanDiffUtil.diffSameField(operation, reqOperation);
List<FieldDiff> contractDiffs = BeanDiffUtil.diffSameField(contract, reqContract);
reqPurchaseDetail.setPurchaseDiffs(purchaseDiffs);
reqPurchaseDetail.setContractDiffs(contractDiffs);
reqPurchaseDetail.setOperationDiffs(operationDiffs);
}
}

UserInfoDetails userDetail = LoginUserUtil.loginUserDetail();

WflowModels wflowModels = processModelManage.getWflowModelsNoNull(ProjectProcessType.PROJECT_CHANGE, userDetail.getMhUnitId());

ProcessStartParamsVo params = new ProcessStartParamsVo();
params.setUser(declaredProjectHelper.buildUser(userDetail));
params.setProcessUsers(Collections.emptyMap());
params.setFormData(Collections.emptyMap());

// 获取发起单位、发起单位主管单位、发起单位上级主管条线单位信息
Map<String, OrgInfoDTO> orgModelMap = declaredProjectHelper.buildOrgModelMap(userDetail, project);
String instId = processInstanceService.startProcessLs(wflowModels, params, orgModelMap);
ProjectInst projectInst = new ProjectInst();
projectInst.setInstCode(instId);
projectInst.setProjectId(project.getId());
projectInst.setInstType(ProjectProcessType.PROJECT_CHANGE);
projectInstService.save(projectInst);
projectChangeStopHelper.changeProjectPurchaseStatus(project, CHANGE_APPLY_SUBMIT);

// 保存变更历史
ProjectChangeHistory projectChangeHistory = new ProjectChangeHistory();
projectChangeHistory.setChangeContent(JSONUtil.toJsonStr(projectEdit));
projectChangeHistory.setChangeReason(req.getChangeReason());
projectChangeHistory.setProjectId(project.getId());
projectChangeHistory.setProjectCode(project.getProjectCode());
projectChangeHistory.setStatus(ProjectChangeStatus.ON_CHANGE_APPLY.getCode());
projectChangeHistory.setInstCode(instId);
projectChangeHistoryService.save(projectChangeHistory);
}

public PageVo<ProjectChangeListVO> page(ProjectListReq req) {
LambdaQueryWrapper<Project> wrapper = ProjectManageUtil.projectQuery(req)
.eq(Project::getNewest, Boolean.TRUE);
UserInfoDetails userDetail = LoginUserUtil.loginUserDetail();
if (!userDetail.getSuperAdmin()) {
wrapper.eq(Project::getBuildOrgCode, userDetail.getMhUnitIdStr());
}
Page<ProjectChangeListDTO> page = projectService.pageChangeList(wrapper, req.page());
if (page.getTotal() == 0) {
return PageVo.empty();
}
List<ProjectChangeListDTO> records = page.getRecords();
List<ProjectChangeListVO> data = records.stream().map(w -> {
ProjectChangeListVO item = new ProjectChangeListVO();
BeanUtil.copyProperties(w, item);
item.setUnitStripName(MhUnitStripEnum.getVal(w.getUnitStrip()));
return item;
}).collect(Collectors.toList());
return PageVo.of(data, page.getTotal());
}

public ProjectChangeDetailVO changeDetail(String projectCode, String instCode) {
LambdaQueryWrapper<ProjectChangeHistory> wrapper = Wrappers.lambdaQuery(ProjectChangeHistory.class)
.eq(ProjectChangeHistory::getProjectCode, projectCode)
.eq(ProjectChangeHistory::getInstCode, instCode);
ProjectChangeHistory changeHistory = projectChangeHistoryService.getOne(wrapper);
if (changeHistory == null) {
return null;
}
ProjectChangeDetailVO result = new ProjectChangeDetailVO();
result.setProjectEditDetail(JSONUtil.toBean(changeHistory.getChangeContent(), ProjectEditDTO.class));
result.setChangeReason(changeHistory.getChangeReason());
result.setCreateOn(changeHistory.getCreateOn());
return result;
}

public List<ProjectLibListItemVO> options() {
LambdaQueryWrapper<Project> query = Wrappers.lambdaQuery(Project.class)
.select(Project::getId, Project::getProjectCode, Project::getProjectName)
.eq(Project::getNewest, Boolean.TRUE)
.orderByDesc(Project::getCreateOn)
.notIn(Project::getStatus, ProjectStatus.STOPPED.getCode(),
ProjectStatus.ON_STOPPED_APPLY.getCode(),
ProjectStatus.ON_CHANGE_APPLY);
UserInfoDetails userDetail = LoginUserUtil.loginUserDetail();
if (!userDetail.getSuperAdmin()) {
query.eq(Project::getBuildOrgCode, userDetail.getMhUnitIdStr());
}
List<Project> projects = projectService.list(query);
return CollUtils.convert(projects, w -> {
ProjectLibListItemVO item = new ProjectLibListItemVO();
item.setProjectName(w.getProjectName());
item.setProjectCode(w.getProjectCode());
item.setId(w.getId());
return item;
});
}

}

+ 14
- 12
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/manage/ProjectLibManage.java View File

@@ -793,7 +793,7 @@ public class ProjectLibManage {
/**
* 申报新项目时 保存项目信息和其它相关联的信息
*
* @param proj \
* @param proj \
* @param instCode \
* @return \
*/
@@ -813,7 +813,7 @@ public class ProjectLibManage {
/**
* 申报新项目时 保存项目信息和其它相关联的信息
*
* @param proj \
* @param proj \
* @param instCode \
* @return \
*/
@@ -838,7 +838,7 @@ public class ProjectLibManage {
* @return \
*/
private Project saveProjectNewVersion(ProjectDTO projectDto, String instanceId,
Long userId, Boolean isContruct) {
Long userId, Boolean isContruct) {
//流程启动之后 入库项目 重要业务信息 用于列表查询 展示
return saveProjectNewVersion(projectDto, instanceId, userId, isContruct, ProjectStatus.NOT_APPROVED, ProjectStatus.TO_BE_DECLARED);
}
@@ -866,7 +866,7 @@ public class ProjectLibManage {
if (projectService.save(project)) {
saveApplication(projectDto, project, null);
savePaymentPlans(project, projectDto.getPaymentPlanList());
saveGovSystemReplaceInfos(project, projectDto.getSystemReplaceInfos());
saveGovSystemReplaceInfos(project.getId(), project.getProjectCode(), projectDto.getSystemReplaceInfos());
}
} else {
//否则是重新提交的 新生成一个新版本的项目
@@ -939,24 +939,26 @@ public class ProjectLibManage {
projectService.reverseNewest(newProj.getProjectCode(), newProj.getId());
saveApplication(reqProj, newProj, isConstruct);
savePaymentPlans(newProj, reqProj.getPaymentPlanList());
saveGovSystemReplaceInfos(newProj, reqProj.getSystemReplaceInfos());
saveGovSystemReplaceInfos(newProj.getId(), newProj.getProjectCode(), reqProj.getSystemReplaceInfos());
return newProj;
}

private void saveGovSystemReplaceInfos(Project project, List<GovSystemReplaceInfoDTO> govSystemReplaceInfos) {
public void saveGovSystemReplaceInfos(Long projectId,
String projectCode,
List<GovSystemReplaceInfoDTO> systemReplaceInfos) {
Wrapper<ProjectGovSystemReplaceInfos> delQuery = Wrappers.lambdaQuery(ProjectGovSystemReplaceInfos.class)
.eq(ProjectGovSystemReplaceInfos::getProjectCode, project.getProjectCode());
.eq(ProjectGovSystemReplaceInfos::getProjectCode, projectCode);
projectGovSystemReplaceInfosService.remove(delQuery);
if (CollUtil.isEmpty(govSystemReplaceInfos)) {
if (CollUtil.isEmpty(systemReplaceInfos)) {
return;
}
List<ProjectGovSystemReplaceInfos> replaceInfos = new ArrayList<>();
for (int i = 0; i < govSystemReplaceInfos.size(); i++) {
GovSystemReplaceInfoDTO curr = govSystemReplaceInfos.get(i);
for (int i = 0; i < systemReplaceInfos.size(); i++) {
GovSystemReplaceInfoDTO curr = systemReplaceInfos.get(i);
for (String systemName : curr.getSourceSystemNames()) {
ProjectGovSystemReplaceInfos replaceInfo = new ProjectGovSystemReplaceInfos();
replaceInfo.setProjectId(project.getId());
replaceInfo.setProjectCode(project.getProjectCode());
replaceInfo.setProjectId(projectId);
replaceInfo.setProjectCode(projectCode);
replaceInfo.setReplaceType(curr.getReplaceType());
replaceInfo.setSourceSystem(systemName);
replaceInfo.setTargetSystem(curr.getTargetSystemName());


+ 153
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/manage/ProjectStoppedManage.java View File

@@ -0,0 +1,153 @@
package com.hz.pm.api.projectlib.manage;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hz.pm.api.common.enumeration.ProjectProcessType;
import com.hz.pm.api.common.statemachine.event.ProjectStateChangeEvent;
import com.hz.pm.api.external.model.enumeration.MhUnitStripEnum;
import com.hz.pm.api.projectdeclared.manage.DeclaredProjectHelper;
import com.hz.pm.api.projectlib.helper.ProjectChangeStopHelper;
import com.hz.pm.api.projectlib.helper.ProjectManageUtil;
import com.hz.pm.api.projectlib.model.entity.Project;
import com.hz.pm.api.projectlib.model.entity.ProjectInst;
import com.hz.pm.api.projectlib.model.entity.ProjectStatusChange;
import com.hz.pm.api.projectlib.model.enumeration.status.ProjectStatus;
import com.hz.pm.api.projectlib.model.req.ProjectListReq;
import com.hz.pm.api.projectlib.model.req.SubmitProjectStoppedApplyReq;
import com.hz.pm.api.projectlib.model.vo.ProjectLibListItemVO;
import com.hz.pm.api.projectlib.service.IProjectInstService;
import com.hz.pm.api.projectlib.service.IProjectService;
import com.hz.pm.api.projectlib.service.IProjectStatusChangeService;
import com.hz.pm.api.sys.manage.ProcessModelManage;
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.model.PageVo;
import com.ningdatech.basic.util.CollUtils;
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.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.hz.pm.api.common.statemachine.event.ProjectStateChangeEvent.STOPPED_APPLY_AUTO_PASS;
import static com.hz.pm.api.common.statemachine.event.ProjectStateChangeEvent.STOPPED_APPLY_SUBMIT;

/**
* <p>
* ProjectStoppedManage
* </p>
*
* @author WendyYang
* @since 11:04 2024/8/5
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class ProjectStoppedManage {

private final IProjectService projectService;
private final IProjectStatusChangeService projectStatusChangeService;
private final IProjectInstService projectInstService;
private final ProcessInstanceService processInstanceService;
private final ProcessModelManage processModelManage;
private final DeclaredProjectHelper declaredProjectHelper;
private final ProjectChangeStopHelper projectChangeStopHelper;

@Transactional(rollbackFor = Exception.class)
public synchronized void submitProjectStoppedApply(SubmitProjectStoppedApplyReq req) {
Project project = projectService.getNewProject(req.getProjectId());
if (ProjectStatus.STOPPED_PASSED.eq(project.getStatus()) ||
ProjectStatus.ON_STOPPED_APPLY.eq(project.getStatus())) {
throw BizException.wrap("暂无法提交终止申请");
}
long hasDeclared = projectStatusChangeService.count(Wrappers.lambdaQuery(ProjectStatusChange.class)
.eq(ProjectStatusChange::getProjectId, project.getProjectCode())
.eq(ProjectStatusChange::getEvent, ProjectStateChangeEvent.DECLARED_RECORD_PASS));

project.setStoppedFiles(req.getStoppedFiles());
project.setStoppedReason(req.getStoppedReason());
if (hasDeclared == 0) {
projectChangeStopHelper.changeProjectPurchaseStatus(project, STOPPED_APPLY_AUTO_PASS);
return;
}

UserInfoDetails userDetail = LoginUserUtil.loginUserDetail();

WflowModels wflowModels = processModelManage.getWflowModelsNoNull(ProjectProcessType.PROJECT_STOPPED, userDetail.getMhUnitId());

ProcessStartParamsVo params = new ProcessStartParamsVo();
params.setUser(declaredProjectHelper.buildUser(userDetail));
params.setProcessUsers(Collections.emptyMap());
params.setFormData(Collections.emptyMap());

// 获取发起单位、发起单位主管单位、发起单位上级主管条线单位信息
Map<String, OrgInfoDTO> orgModelMap = declaredProjectHelper.buildOrgModelMap(userDetail, project);
String instId = processInstanceService.startProcessLs(wflowModels, params, orgModelMap);
ProjectInst projectInst = new ProjectInst();
projectInst.setInstCode(instId);
projectInst.setProjectId(project.getId());
projectInst.setInstType(ProjectProcessType.PROJECT_STOPPED);
projectInstService.save(projectInst);
// 修改项目状态、标项状态
projectChangeStopHelper.changeProjectPurchaseStatus(project, STOPPED_APPLY_SUBMIT);
}

public PageVo<ProjectLibListItemVO> page(ProjectListReq req) {
LambdaQueryWrapper<Project> query = ProjectManageUtil.projectQuery(req);
query.eq(Project::getNewest, Boolean.TRUE)
.orderByDesc(Project::getUpdateOn)
.isNotNull(Project::getStoppedStatus);
Page<Project> page = req.page();
projectService.page(page, query);
if (page.getTotal() == 0) {
return PageVo.empty();
}
List<Project> records = page.getRecords();
List<ProjectLibListItemVO> data = records.stream().map(w -> {
ProjectLibListItemVO project = new ProjectLibListItemVO();
project.setProjectName(w.getProjectName());
project.setProjectCode(w.getProjectCode());
project.setStoppedStatus(w.getStoppedStatus());
project.setId(w.getId());
project.setStage(w.getStage());
project.setStatus(w.getStatus());
project.setCreateOn(w.getCreateOn());
project.setBuildOrgName(w.getBuildOrgName());
project.setUnitStripName(MhUnitStripEnum.getVal(w.getUnitStrip()));
return project;
}).collect(Collectors.toList());
return PageVo.of(data, page.getTotal());
}

public List<ProjectLibListItemVO> options() {
LambdaQueryWrapper<Project> query = Wrappers.lambdaQuery(Project.class)
.select(Project::getId, Project::getProjectCode, Project::getProjectName)
.eq(Project::getNewest, Boolean.TRUE)
.orderByDesc(Project::getCreateOn)
.notIn(Project::getStatus, ProjectStatus.STOPPED.getCode(),
ProjectStatus.ON_STOPPED_APPLY.getCode());
UserInfoDetails userDetail = LoginUserUtil.loginUserDetail();
if (!userDetail.getSuperAdmin()) {
query.eq(Project::getBuildOrgCode, userDetail.getMhUnitIdStr());
}
List<Project> projects = projectService.list(query);
return CollUtils.convert(projects, w -> {
ProjectLibListItemVO item = new ProjectLibListItemVO();
item.setProjectName(w.getProjectName());
item.setProjectCode(w.getProjectCode());
item.setId(w.getId());
return item;
});
}

}

+ 7
- 1
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/mapper/ProjectMapper.java View File

@@ -1,6 +1,9 @@
package com.hz.pm.api.projectlib.mapper;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hz.pm.api.projectlib.model.dto.ProjectChangeListDTO;
import com.hz.pm.api.projectlib.model.entity.Project;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hz.pm.api.projectlib.model.po.ProjectPO;
@@ -9,7 +12,7 @@ import org.apache.ibatis.annotations.Param;

/**
* <p>
* Mapper 接口
* Mapper 接口
* </p>
*
* @author WendyYang
@@ -20,4 +23,7 @@ public interface ProjectMapper extends BaseMapper<Project> {
Page<ProjectPO> pageAllWithPermission(Page<ProjectPO> page, @Param("req") ProjectListReq req);

Page<ProjectPO> pageLibWithPermission(Page<ProjectPO> page, @Param("req") ProjectListReq req);

Page<ProjectChangeListDTO> pageChangeList(Page<ProjectChangeListDTO> page, @Param(Constants.WRAPPER) Wrapper<Project> req);

}

+ 21
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/mapper/ProjectMapper.xml View File

@@ -470,4 +470,25 @@
</if>)
) ORDER BY topped desc, update_on DESC
</select>

<select id="pageChangeList" resultType="com.hz.pm.api.projectlib.model.dto.ProjectChangeListDTO">
select np.id as projectId,
np.project_code,
np.project_name,
np.build_org_code,
np.build_org_name,
np.review_amount,
np.stage,
np.status,
np.create_on,
np.unit_strip,
npch.status as changeStatus,
npch.craete_on as change_apply_time,
npch.id as changeId
from (select * from nd_project ${ew.customSqlSegment}) np
inner join nd_project_change_history npch
on np.id = npch.project_id
order by npch.create_on desc
</select>

</mapper>

+ 20
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/dto/GovSystemReplaceInfoDTO.java View File

@@ -1,9 +1,11 @@
package com.hz.pm.api.projectlib.model.dto;

import cn.hutool.core.collection.CollUtil;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

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

/**
* <p>
@@ -25,4 +27,22 @@ public class GovSystemReplaceInfoDTO {
@ApiModelProperty("替代方式")
private String replaceType;

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
GovSystemReplaceInfoDTO that = (GovSystemReplaceInfoDTO) o;
return CollUtil.isEqualList(sourceSystemNames, that.sourceSystemNames)
&& Objects.equals(targetSystemName, that.targetSystemName)
&& Objects.equals(replaceType, that.replaceType);
}

@Override
public int hashCode() {
return Objects.hash(sourceSystemNames, targetSystemName, replaceType);
}
}

+ 1
- 1
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/dto/ProjectApplicationDTO.java View File

@@ -17,7 +17,7 @@ import java.util.List;
* @author WendyYang
* @since 2023-02-05
*/
@ApiModel(value = "NdProjectApplication对象", description = "")
@ApiModel(value = "NdProjectApplication对象")
@Data
public class ProjectApplicationDTO implements Serializable {



+ 59
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/dto/ProjectChangeListDTO.java View File

@@ -0,0 +1,59 @@
package com.hz.pm.api.projectlib.model.dto;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
* <p>
* ProjectChangeListDTO
* </p>
*
* @author WendyYang
* @since 14:12 2024/8/6
*/
@Data
public class ProjectChangeListDTO {

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

@ApiModelProperty("项目状态")
private Integer status;

@ApiModelProperty("项目阶段")
private String stage;

@ApiModelProperty("项目编码")
private String projectCode;

@ApiModelProperty("所属领域")
private Integer unitStrip;

@ApiModelProperty("建设单位")
private String buildOrgCode;

@ApiModelProperty("建设单位")
private String buildOrgName;

@ApiModelProperty("项目名称")
private String projectName;

@ApiModelProperty("创建时间")
private LocalDateTime createOn;

@ApiModelProperty("变更申请时间")
private String changeApplyTime;

@ApiModelProperty("变更状态")
private Integer changeStatus;

@ApiModelProperty("评审金额")
private BigDecimal reviewAmount;

@ApiModelProperty("变更ID")
private Long changeId;

}

+ 2
- 2
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/dto/ProjectDTO.java View File

@@ -2,7 +2,6 @@ package com.hz.pm.api.projectlib.model.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.hz.pm.api.common.compare.Compare;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@@ -20,9 +19,10 @@ import java.util.Map;
* @since 2023-02-03
*/
@Data
@ApiModel(value = "NdProjectDto")
public class ProjectDTO {

public static final String SYSTEM_REPLACE_INFOS = "systemReplaceInfos";

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



+ 27
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/dto/ProjectPaymentPlanDTO.java View File

@@ -5,6 +5,7 @@ import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.math.BigDecimal;
import java.util.Objects;

/**
* <p>
@@ -33,4 +34,30 @@ public class ProjectPaymentPlanDTO {
@ApiModelProperty("年度支付计划-政府投资-上级补助资金(万元)")
private BigDecimal annualPlanGovSuperiorFinanceAmount;


@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ProjectPaymentPlanDTO that = (ProjectPaymentPlanDTO) o;
return Objects.equals(paymentYear, that.paymentYear)
&& Objects.equals(annualPlanAmount, that.annualPlanAmount)
&& Objects.equals(annualPlanHaveAmount, that.annualPlanHaveAmount)
&& Objects.equals(annualPlanGovOwnFinanceAmount, that.annualPlanGovOwnFinanceAmount)
&& Objects.equals(annualPlanGovSuperiorFinanceAmount, that.annualPlanGovSuperiorFinanceAmount);
}

@Override
public int hashCode() {
return Objects.hash(paymentYear,
annualPlanAmount,
annualPlanHaveAmount,
annualPlanGovOwnFinanceAmount,
annualPlanGovSuperiorFinanceAmount);
}

}

+ 9
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/entity/Project.java View File

@@ -583,4 +583,13 @@ public class Project implements Serializable {
@ApiModelProperty("是否已开启年度计划")
private Boolean annualPlanOpened;

@ApiModelProperty("项目终止原因")
private String stoppedReason;

@ApiModelProperty("项目终止附件")
private String stoppedFiles;

@ApiModelProperty("项目终止状态")
private Integer stoppedStatus;

}

+ 8
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/entity/ProjectInst.java View File

@@ -9,7 +9,9 @@ import com.hz.pm.api.common.enumeration.ProjectProcessType;
import com.hz.pm.api.projectlib.model.enumeration.InstTypeEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
import lombok.experimental.Tolerate;

/**
* <p>
@@ -19,6 +21,7 @@ import lombok.Data;
* @author Poffy
* @since 2023-02-13
*/
@Builder
@TableName("nd_project_inst")
@Data
@ApiModel(value = "NdProjectInst对象")
@@ -26,6 +29,11 @@ public class ProjectInst implements Serializable {

private static final long serialVersionUID = 1L;

@Tolerate
public ProjectInst() {
// no-op
}

@ApiModelProperty("主键")
@TableId(type = IdType.AUTO)
private Long id;


+ 3
- 1
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/enumeration/InstTypeEnum.java View File

@@ -38,7 +38,9 @@ public enum InstTypeEnum {
ADAPTION(11, "适配改造审批流程"),
TEST_VALID(12, "测试验证审批流程"),
COMPLIANCE_REVIEW(13, "合规性审查流程"),
PROJECT_REVIEW(14, "项目评审流程");
PROJECT_REVIEW(14, "项目评审流程"),
PROJECT_STOPPED(15, "项目终止流程"),
PROJECT_CHANGE(16, "项目变更流程");

private Integer code;
private String desc;


+ 28
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/enumeration/status/ProjectChangeStatus.java View File

@@ -0,0 +1,28 @@
package com.hz.pm.api.projectlib.model.enumeration.status;

import lombok.AllArgsConstructor;
import lombok.Getter;

/**
* <p>
* ProjectStoppedStatus
* </p>
*
* @author WendyYang
* @since 16:53 2024/8/5
*/
@Getter
@AllArgsConstructor
public enum ProjectChangeStatus implements IStatus<Integer, String> {

/**
* 项目终止
*/
ON_CHANGE_APPLY(50001, "项目变更审核中"),
CHANGE_PASSED(50002, "项目变更审核通过"),
CHANGE_FAILED(50003, "项目变更审核不通过");

private final Integer code;
private final String desc;

}

+ 13
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/enumeration/status/ProjectStatus.java View File

@@ -62,6 +62,19 @@ public enum ProjectStatus implements IStatus<Integer, String> {
FINALLY_INSPECTED_FAILED(20005, "终验审核不通过"),

/**
* 项目终止
*/
STOPPED(40000, "项目终止"),
ON_STOPPED_APPLY(40001, "项目终止中"),
STOPPED_PASSED(40002, "项目终止"),

/**
* 项目变更
*/
CHANGE(50000, "项目变更"),
ON_CHANGE_APPLY(50001, "项目变更中"),

/**
* 项目阶段:已归档
*/
ARCHIVED(30000, "已归档"),


+ 28
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/enumeration/status/ProjectStoppedStatus.java View File

@@ -0,0 +1,28 @@
package com.hz.pm.api.projectlib.model.enumeration.status;

import lombok.AllArgsConstructor;
import lombok.Getter;

/**
* <p>
* ProjectStoppedStatus
* </p>
*
* @author WendyYang
* @since 16:53 2024/8/5
*/
@Getter
@AllArgsConstructor
public enum ProjectStoppedStatus implements IStatus<Integer, String> {

/**
* 项目终止
*/
ON_STOPPED_APPLY(40001, "项目终止审核中"),
STOPPED_PASSED(40002, "项目终止"),
STOPPED_FAILED(40003, "项目终止审核不通过");

private final Integer code;
private final String desc;

}

+ 4
- 1
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/enumeration/status/TenderStatus.java View File

@@ -26,7 +26,10 @@ public enum TenderStatus implements IStatus<Integer, String> {
TO_BE_SUBMIT_FINALLY_INSPECTED_APPLY(ProjectStatus.ON_PILOT_RUNNING, 401, "待终验申报"),
ON_FINALLY_INSPECTED_APPLY(ProjectStatus.ON_FINALLY_INSPECTED, 501, "终验申报中"),
FINALLY_INSPECTED_FAILED(ProjectStatus.ON_FINALLY_INSPECTED, 502, "终验申报不通过"),
FINALLY_INSPECTED_PASSED(ProjectStatus.ACCEPTED, 601, "终验完成");
FINALLY_INSPECTED_PASSED(ProjectStatus.ACCEPTED, 601, "终验完成"),
ON_CHANGE_APPLY(ProjectStatus.ON_CHANGE_APPLY, 701, "项目变更中"),
ON_STOPPED_APPLY(ProjectStatus.ON_STOPPED_APPLY, 901, "项目终止审核中"),
STOPPED_PASSED(ProjectStatus.STOPPED, 902, "项目终止");

private final ProjectStatus projectStatus;
private final Integer code;


+ 24
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/req/SubmitProjectChangeApplyReq.java View File

@@ -0,0 +1,24 @@
package com.hz.pm.api.projectlib.model.req;

import com.hz.pm.api.projectdeclared.model.dto.ProjectEditDTO;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
* <p>
* SubmitProjectChangeApplyReq
* </p>
*
* @author WendyYang
* @since 11:07 2024/8/5
*/
@Data
public class SubmitProjectChangeApplyReq {

@ApiModelProperty("变更原因")
private String changeReason;

@ApiModelProperty("项目信息")
private ProjectEditDTO projectEditDetail;

}

+ 26
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/req/SubmitProjectStoppedApplyReq.java View File

@@ -0,0 +1,26 @@
package com.hz.pm.api.projectlib.model.req;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
* <p>
* SubmitProjectStoppedApplyReq
* </p>
*
* @author WendyYang
* @since 11:07 2024/8/5
*/
@Data
public class SubmitProjectStoppedApplyReq {

@ApiModelProperty(value = "项目id")
private Long projectId;

@ApiModelProperty(value = "项目终止原因")
private String stoppedReason;

@ApiModelProperty(value = "项目终止附件")
private String stoppedFiles;

}

+ 29
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/vo/ProjectChangeDetailVO.java View File

@@ -0,0 +1,29 @@
package com.hz.pm.api.projectlib.model.vo;

import com.hz.pm.api.projectdeclared.model.dto.ProjectEditDTO;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.time.LocalDateTime;

/**
* <p>
* ProjectChangeDetailVO
* </p>
*
* @author WendyYang
* @since 14:48 2024/8/6
*/
@Data
public class ProjectChangeDetailVO {

@ApiModelProperty("变更原因")
private String changeReason;

@ApiModelProperty("变更内容")
private ProjectEditDTO projectEditDetail;

@ApiModelProperty("变更申请时间")
private LocalDateTime createOn;

}

+ 62
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/vo/ProjectChangeListVO.java View File

@@ -0,0 +1,62 @@
package com.hz.pm.api.projectlib.model.vo;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
* <p>
* ProjectChangeListDTO
* </p>
*
* @author WendyYang
* @since 14:12 2024/8/6
*/
@Data
public class ProjectChangeListVO {

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

@ApiModelProperty("项目状态")
private Integer status;

@ApiModelProperty("项目阶段")
private String stage;

@ApiModelProperty("项目编码")
private String projectCode;

@ApiModelProperty("所属领域")
private Integer unitStrip;

@ApiModelProperty("所属领域")
private String unitStripName;

@ApiModelProperty("建设单位")
private String buildOrgCode;

@ApiModelProperty("建设单位")
private String buildOrgName;

@ApiModelProperty("项目名称")
private String projectName;

@ApiModelProperty("创建时间")
private LocalDateTime createOn;

@ApiModelProperty("变更申请时间")
private String changeApplyTime;

@ApiModelProperty("变更状态")
private Integer changeStatus;

@ApiModelProperty("评审金额")
private BigDecimal reviewAmount;

@ApiModelProperty("变更ID")
private Long changeId;

}

+ 6
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/vo/ProjectDetailVO.java View File

@@ -592,4 +592,10 @@ public class ProjectDetailVO {
@ApiModelProperty("建设方案详情")
private ConstructionDetailVO construction;

@ApiModelProperty("项目终止附件")
private String stoppedFiles;

@ApiModelProperty("项目终止状态")
private Integer stoppedStatus;

}

+ 6
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/model/vo/ProjectLibListItemVO.java View File

@@ -98,6 +98,9 @@ public class ProjectLibListItemVO {
@ApiModelProperty("建设单位统一社会信用代码")
private String buildOrgCode;

@ApiModelProperty("所属领域")
private String unitStripName;

private String projectTypeName;

@ApiModelProperty("成交金额")
@@ -172,4 +175,7 @@ public class ProjectLibListItemVO {
@ApiModelProperty("标段信息")
private List<TenderListInfoVO> tenders;

@ApiModelProperty("项目终止状态")
private Integer stoppedStatus;

}

+ 4
- 1
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/service/IProjectService.java View File

@@ -10,6 +10,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.hz.pm.api.common.model.constant.BizConst;
import com.hz.pm.api.projectdeclared.utils.ProjectIdCodeCacheUtil;
import com.hz.pm.api.projectlib.model.dto.ProjectChangeListDTO;
import com.hz.pm.api.projectlib.model.entity.Project;
import com.hz.pm.api.projectlib.model.po.ProjectPO;
import com.hz.pm.api.projectlib.model.req.ProjectListReq;
@@ -43,7 +44,7 @@ public interface IProjectService extends IService<Project> {
default boolean save(Project entity) {
boolean state = IService.super.save(entity);
// 将项目ID与编码的对应关系保存下来
ProjectIdCodeCacheUtil.put(entity.getId(), entity.getProjectCode());
ProjectIdCodeCacheUtil.put(entity.getId(), entity);
return state;
}

@@ -99,4 +100,6 @@ public interface IProjectService extends IService<Project> {
return getOne(query);
}

Page<ProjectChangeListDTO> pageChangeList(Wrapper<Project> wrapper, Page<ProjectChangeListDTO> page);

}

+ 8
- 0
hz-pm-api/src/main/java/com/hz/pm/api/projectlib/service/impl/ProjectServiceImpl.java View File

@@ -1,5 +1,6 @@
package com.hz.pm.api.projectlib.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -7,6 +8,7 @@ import com.hz.pm.api.common.model.constant.BizConst;
import com.hz.pm.api.common.model.constant.BooleanBit;
import com.hz.pm.api.projectdeclared.utils.ProjectIdCodeCacheUtil;
import com.hz.pm.api.projectlib.mapper.ProjectMapper;
import com.hz.pm.api.projectlib.model.dto.ProjectChangeListDTO;
import com.hz.pm.api.projectlib.model.entity.Project;
import com.hz.pm.api.projectlib.model.po.ProjectPO;
import com.hz.pm.api.projectlib.model.req.ProjectListReq;
@@ -60,4 +62,10 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
public Page<ProjectPO> pageLibWithPermission(Page<ProjectPO> page, ProjectListReq req) {
return baseMapper.pageLibWithPermission(page, req);
}

@Override
public Page<ProjectChangeListDTO> pageChangeList(Wrapper<Project> wrapper, Page<ProjectChangeListDTO> page) {
return baseMapper.pageChangeList(page, wrapper);
}

}

+ 37
- 0
hz-pm-api/src/main/java/com/hz/pm/api/todocenter/manage/HandlerManage.java View File

@@ -13,6 +13,7 @@ import com.hz.pm.api.common.enumeration.ProjectProcessType;
import com.hz.pm.api.common.helper.WflowHelper;
import com.hz.pm.api.common.model.constant.BizConst;
import com.hz.pm.api.common.model.constant.TypeReferenceConst;
import com.hz.pm.api.common.statemachine.event.ProjectStateChangeEvent;
import com.hz.pm.api.common.statemachine.util.*;
import com.hz.pm.api.common.util.BizUtils;
import com.hz.pm.api.filemanage.model.entity.ProjectApplyBorrow;
@@ -28,6 +29,7 @@ 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.helper.ProjectChangeStopHelper;
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;
@@ -106,6 +108,7 @@ public class HandlerManage {
private final TestValidStateMachineUtil testValidStateMachineUtil;
private final XcfhxStateMachineUtil xcfhxStateMachineUtil;
private final WflowHelper wflowHelper;
private final ProjectChangeStopHelper projectChangeStopHelper;

private final IXinchuangService xinchuangService;

@@ -202,6 +205,10 @@ public class HandlerManage {
ProjectProcessType processStage = ProjectProcessType.getNoNull(instTypeEnum.getCode());
purchasePassedCallback(project, instanceId, processStage);
break;
case ON_CHANGE_APPLY:
case ON_STOPPED_APPLY:
stoppedChaneCallbackAfterPass(project, instTypeEnum);
break;
default:
throw BizException.wrap("传入项目状态错误: %s", project.getStatus());
}
@@ -444,6 +451,10 @@ public class HandlerManage {
case ADAPTION:
purchaseOperationRejectedCallback(project.getId(), instanceId, instTypeEnum);
break;
case PROJECT_CHANGE:
case PROJECT_STOPPED:
stoppedChaneCallbackAfterReject(project, instTypeEnum);
break;
default:
updateRejectProjectStatus(userId, project, instType);
break;
@@ -454,6 +465,32 @@ public class HandlerManage {
REJECT_MSG_TEMPLATE, MsgTypeEnum.PROJECT_REVIEW_REJECT);
}

public void stoppedChaneCallbackAfterPass(Project project,
InstTypeEnum instType) {
ProjectStateChangeEvent event;
if (InstTypeEnum.PROJECT_STOPPED.equals(instType)) {
event = ProjectStateChangeEvent.STOPPED_APPLY_PASS;
} else if (InstTypeEnum.PROJECT_CHANGE.equals(instType)) {
event = ProjectStateChangeEvent.CHANGE_APPLY_PASS;
} else {
throw BizException.wrap("不支持的流程类型");
}
projectChangeStopHelper.changeProjectPurchaseStatus(project, event);
}

public void stoppedChaneCallbackAfterReject(Project project,
InstTypeEnum instType) {
ProjectStateChangeEvent event;
if (InstTypeEnum.PROJECT_STOPPED.equals(instType)) {
event = ProjectStateChangeEvent.STOPPED_APPLY_FAILED;
} else if (InstTypeEnum.PROJECT_CHANGE.equals(instType)) {
event = ProjectStateChangeEvent.CHANGE_APPLY_FAILED;
} else {
throw BizException.wrap("不支持的流程类型");
}
projectChangeStopHelper.changeProjectPurchaseStatus(project, event);
}

public void afterRejectTodo(Xinchuang xinchuang, HistoricProcessInstance hiInst) {
xinchuang.setStatus(TenderXcfhxApplyStatus.XCFHX_APPLY_FAILED.getCode());
xinchuangService.updateById(xinchuang);


+ 52
- 31
hz-pm-api/src/main/java/com/hz/pm/api/todocenter/manage/TodoCenterManage.java View File

@@ -14,6 +14,7 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.hz.pm.api.common.enumeration.CommonEnum;
import com.hz.pm.api.common.enumeration.ProjectProcessType;
import com.hz.pm.api.common.helper.UserInfoHelper;
import com.hz.pm.api.common.model.constant.BizConst;
import com.hz.pm.api.common.model.constant.RegionConst;
@@ -35,6 +36,7 @@ import com.hz.pm.api.projectlib.model.entity.Project;
import com.hz.pm.api.projectlib.model.entity.ProjectApplication;
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.req.ProjectListReq;
import com.hz.pm.api.projectlib.service.IProjectApplicationService;
import com.hz.pm.api.projectlib.service.IProjectInstService;
@@ -44,6 +46,7 @@ import com.hz.pm.api.signature.service.ICompanySignatureService;
import com.hz.pm.api.sys.model.entity.Region;
import com.hz.pm.api.sys.service.IRegionService;
import com.hz.pm.api.todocenter.constant.TodoCenterConst;
import com.hz.pm.api.todocenter.constant.TodoCenterConst.Declared;
import com.hz.pm.api.todocenter.constant.TodoCenterConst.SealTemplate;
import com.hz.pm.api.todocenter.enumeration.IsAppendProjectEnum;
import com.hz.pm.api.todocenter.handle.PassHandle;
@@ -75,6 +78,7 @@ import com.ningdatech.basic.util.StrPool;
import com.ningdatech.file.entity.File;
import com.ningdatech.file.entity.vo.result.FileResultVO;
import com.ningdatech.file.service.FileService;
import com.sun.org.apache.xpath.internal.operations.Bool;
import com.wflow.contants.HisProInsEndActId;
import com.wflow.contants.ProcessConstant;
import com.wflow.exception.BusinessException;
@@ -168,18 +172,35 @@ public class TodoCenterManage {
ProjectListReq projectListReq = new ProjectListReq();
BeanUtils.copyProperties(param, projectListReq);
List<Project> projects = projectLibManage.projectList(projectListReq);
projects.removeIf(w -> ProjectStatus.STOPPED_PASSED.eq(w.getStatus()));
if (CollUtil.isEmpty(projects)) {
return PageVo.empty();
}

List<Long> changeOrStoppedProjectIds = projects.stream()
.filter(w -> ProjectStatus.ON_CHANGE_APPLY.eq(w.getStatus())
|| ProjectStatus.ON_STOPPED_APPLY.eq(w.getStatus()))
.map(Project::getId)
.collect(Collectors.toList());

Map<Long, Project> projectsMap = CollUtils.listToMap(projects, Project::getId);

List<ProjectInst> projectInstList = projectInstService.listByProjectIds(projectsMap.keySet());
Map<String, Project> projectInfoMap = projectInstList.stream()
.filter(p -> StringUtils.isNotBlank(p.getInstCode()) &&
!TodoCenterConst.Declared.NULL_INST_CODE.equals(p.getInstCode()))
.collect(Collectors.toMap(ProjectInst::getInstCode, p -> projectsMap.get(p.getProjectId())));
.filter(p -> StrUtil.isNotBlank(p.getInstCode()) &&
!Declared.NULL_INST_CODE.equals(p.getInstCode()))
.filter(p -> {
if (changeOrStoppedProjectIds.contains(p.getProjectId())) {
if (ProjectProcessType.PROJECT_STOPPED.eq(p.getInstType())
|| ProjectProcessType.PROJECT_CHANGE.eq(p.getInstType())) {
return Boolean.TRUE;
}
return Boolean.FALSE;
}
return Boolean.TRUE;
}).collect(Collectors.toMap(ProjectInst::getInstCode, p -> projectsMap.get(p.getProjectId())));

List<String> instCodes = projectInstList.stream().map(ProjectInst::getInstCode).collect(Collectors.toList());
List<String> instCodes = CollUtils.fieldList(projectInstList,ProjectInst::getInstCode);
if (CollUtil.isEmpty(instCodes)) {
return PageVo.empty();
}
@@ -248,8 +269,8 @@ public class TodoCenterManage {

// 查出信创
List<Xinchuang> xinchuangs = xinchuangService.list(Wrappers.lambdaQuery(Xinchuang.class)
.like(StringUtils.isNotBlank(param.getProjectName()),Xinchuang::getProjectName, param.getProjectName())
.like(StringUtils.isNotBlank(param.getBuildOrgName()),Xinchuang::getBuildOrgName, param.getBuildOrgName())
.like(StringUtils.isNotBlank(param.getProjectName()), Xinchuang::getProjectName, param.getProjectName())
.like(StringUtils.isNotBlank(param.getBuildOrgName()), Xinchuang::getBuildOrgName, param.getBuildOrgName())
.isNotNull(Xinchuang::getInstCode));

if (CollUtil.isEmpty(xinchuangs)) {
@@ -271,10 +292,10 @@ public class TodoCenterManage {
Integer pageNumber = param.getPageNumber();
Integer pageSize = param.getPageSize();
req.setProcessDefId(param.getProcessDefId());
if(Objects.nonNull(param.getCreateOnMin())){
if (Objects.nonNull(param.getCreateOnMin())) {
req.setStartTime(NdDateUtils.localDateTime2Date(param.getCreateOnMin()));
}
if(Objects.nonNull(param.getCreateOnMax())){
if (Objects.nonNull(param.getCreateOnMax())) {
req.setEndTime(NdDateUtils.localDateTime2Date(param.getCreateOnMax()));
}
req.setEmployeeCode(userIdStr);
@@ -309,7 +330,7 @@ public class TodoCenterManage {
List<ResToBeProcessedVO> resVos = userTodoList.stream().map(d -> {
XinchuangInst xinchuangInst = xinchuangInstMap.get(d.getInstanceId());
ResToBeProcessedVO res = new ResToBeProcessedVO();
if(Objects.nonNull(xinchuangInst) && xinchuangMap.containsKey(xinchuangInst.getXinchuangId())){
if (Objects.nonNull(xinchuangInst) && xinchuangMap.containsKey(xinchuangInst.getXinchuangId())) {
Xinchuang xinchuang = xinchuangMap.get(xinchuangInst.getXinchuangId());
res.setXinchuangId(xinchuang.getId());
res.setProjectName(xinchuang.getProjectName());
@@ -894,7 +915,7 @@ public class TodoCenterManage {
}
Map<String, Project> projectInfoMap = projectInstList.stream()
.filter(p -> StringUtils.isNotBlank(p.getInstCode()) &&
!TodoCenterConst.Declared.NULL_INST_CODE.equals(p.getInstCode()))
!Declared.NULL_INST_CODE.equals(p.getInstCode()))
.collect(Collectors.toMap(ProjectInst::getInstCode, p -> projectsMap.get(p.getProjectId())));
List<String> instCodes = projectInstList.stream().map(ProjectInst::getInstCode).collect(Collectors.toList());

@@ -946,8 +967,8 @@ public class TodoCenterManage {

// 查出信创
List<Xinchuang> xinchuangs = xinchuangService.list(Wrappers.lambdaQuery(Xinchuang.class)
.like(StringUtils.isNotBlank(param.getProjectName()),Xinchuang::getProjectName, param.getProjectName())
.like(StringUtils.isNotBlank(param.getBuildOrgName()),Xinchuang::getBuildOrgName, param.getBuildOrgName())
.like(StringUtils.isNotBlank(param.getProjectName()), Xinchuang::getProjectName, param.getProjectName())
.like(StringUtils.isNotBlank(param.getBuildOrgName()), Xinchuang::getBuildOrgName, param.getBuildOrgName())
.isNotNull(Xinchuang::getInstCode));

if (CollUtil.isEmpty(xinchuangs)) {
@@ -971,10 +992,10 @@ public class TodoCenterManage {
req.setUserId(userIdStr);
req.setEmployeeCode(userIdStr);
req.setInstCodes(instCodes);
if(Objects.nonNull(param.getCreateOnMin())){
if (Objects.nonNull(param.getCreateOnMin())) {
req.setStartTime(NdDateUtils.localDateTime2Date(param.getCreateOnMin()));
}
if(Objects.nonNull(param.getCreateOnMax())){
if (Objects.nonNull(param.getCreateOnMax())) {
req.setEndTime(NdDateUtils.localDateTime2Date(param.getCreateOnMax()));
}
List<ProcessTaskVo> iDoList = processTaskService.getUserIdoList(req);
@@ -988,7 +1009,7 @@ public class TodoCenterManage {
List<ResToBeProcessedVO> resVos = userIdoList.stream().map(d -> {
ResToBeProcessedVO res = new ResToBeProcessedVO();
XinchuangInst xinchuangInst = xinchuangInstMap.get(d.getInstanceId());
if(Objects.nonNull(xinchuangInst) && xinchuangMap.containsKey(xinchuangInst.getXinchuangId())){
if (Objects.nonNull(xinchuangInst) && xinchuangMap.containsKey(xinchuangInst.getXinchuangId())) {
Xinchuang xinchuang = xinchuangMap.get(xinchuangInst.getXinchuangId());
res.setXinchuangId(xinchuang.getId());
res.setProjectName(xinchuang.getProjectName());
@@ -1037,7 +1058,7 @@ public class TodoCenterManage {
.orderByDesc(ProjectInst::getProjectId));
projectInfoMap = projectInstList.stream()
.filter(p -> StringUtils.isNotBlank(p.getInstCode()) &&
!TodoCenterConst.Declared.NULL_INST_CODE.equals(p.getInstCode()))
!Declared.NULL_INST_CODE.equals(p.getInstCode()))
.collect(Collectors.toMap(ProjectInst::getInstCode, p -> projectsMap.get(p.getProjectId())));
List<String> instCodes = projectInstList.stream().map(ProjectInst::getInstCode).collect(Collectors.toList());

@@ -1110,7 +1131,7 @@ public class TodoCenterManage {
}
Map<String, Project> projectInfoMap = projectInstList.stream()
.filter(p -> StringUtils.isNotBlank(p.getInstCode()) &&
!TodoCenterConst.Declared.NULL_INST_CODE.equals(p.getInstCode()))
!Declared.NULL_INST_CODE.equals(p.getInstCode()))
.collect(Collectors.toMap(ProjectInst::getInstCode, p -> projectsMap.get(p.getProjectId())));
List<String> instCodes = projectInstList.stream().map(ProjectInst::getInstCode).collect(Collectors.toList());

@@ -1156,8 +1177,8 @@ public class TodoCenterManage {

// 查出信创
List<Xinchuang> xinchuangs = xinchuangService.list(Wrappers.lambdaQuery(Xinchuang.class)
.like(StringUtils.isNotBlank(param.getProjectName()),Xinchuang::getProjectName, param.getProjectName())
.like(StringUtils.isNotBlank(param.getBuildOrgName()),Xinchuang::getBuildOrgName, param.getBuildOrgName())
.like(StringUtils.isNotBlank(param.getProjectName()), Xinchuang::getProjectName, param.getProjectName())
.like(StringUtils.isNotBlank(param.getBuildOrgName()), Xinchuang::getBuildOrgName, param.getBuildOrgName())
.isNotNull(Xinchuang::getInstCode));

if (CollUtil.isEmpty(xinchuangs)) {
@@ -1181,10 +1202,10 @@ public class TodoCenterManage {
req.setUserId(userIdStr);
req.setEmployeeCode(userIdStr);
req.setInstCodes(instCodes);
if(Objects.nonNull(param.getCreateOnMin())){
if (Objects.nonNull(param.getCreateOnMin())) {
req.setStartTime(NdDateUtils.localDateTime2Date(param.getCreateOnMin()));
}
if(Objects.nonNull(param.getCreateOnMax())){
if (Objects.nonNull(param.getCreateOnMax())) {
req.setEndTime(NdDateUtils.localDateTime2Date(param.getCreateOnMax()));
}
List<ProcessInstanceVo> submittedList = processInstanceService.getUserSubmittedList(req);
@@ -1201,7 +1222,7 @@ public class TodoCenterManage {
List<ResToBeProcessedVO> resVos = userSubmittedList.stream().map(d -> {
ResToBeProcessedVO res = new ResToBeProcessedVO();
XinchuangInst xinchuangInst = xinchuangInstMap.get(d.getInstanceId());
if(Objects.nonNull(xinchuangInst) && xinchuangMap.containsKey(xinchuangInst.getXinchuangId())){
if (Objects.nonNull(xinchuangInst) && xinchuangMap.containsKey(xinchuangInst.getXinchuangId())) {
Xinchuang xinchuang = xinchuangMap.get(xinchuangInst.getXinchuangId());
res.setXinchuangId(xinchuang.getId());
res.setProjectName(xinchuang.getProjectName());
@@ -1249,7 +1270,7 @@ public class TodoCenterManage {
.orderByDesc(ProjectInst::getProjectId));
projectInfoMap = projectInstList.stream()
.filter(p -> StringUtils.isNotBlank(p.getInstCode()) &&
!TodoCenterConst.Declared.NULL_INST_CODE.equals(p.getInstCode()))
!Declared.NULL_INST_CODE.equals(p.getInstCode()))
.collect(Collectors.toMap(ProjectInst::getInstCode, p -> projectsMap.get(p.getProjectId())));
List<String> instCodes = projectInstList.stream().map(ProjectInst::getInstCode).collect(Collectors.toList());

@@ -1318,7 +1339,7 @@ public class TodoCenterManage {
.orderByDesc(ProjectInst::getProjectId));
Map<String, Project> projectInfoMap = projectInstList.stream()
.filter(p -> StringUtils.isNotBlank(p.getInstCode()) &&
!TodoCenterConst.Declared.NULL_INST_CODE.equals(p.getInstCode()))
!Declared.NULL_INST_CODE.equals(p.getInstCode()))
.collect(Collectors.toMap(ProjectInst::getInstCode, p -> projectsMap.get(p.getProjectId())));
List<String> instCodes = projectInstList.stream().map(ProjectInst::getInstCode).collect(Collectors.toList());

@@ -1365,8 +1386,8 @@ public class TodoCenterManage {
String userIdStr = String.valueOf(userId);
// 查出信创
List<Xinchuang> xinchuangs = xinchuangService.list(Wrappers.lambdaQuery(Xinchuang.class)
.like(StringUtils.isNotBlank(param.getProjectName()),Xinchuang::getProjectName, param.getProjectName())
.like(StringUtils.isNotBlank(param.getBuildOrgName()),Xinchuang::getBuildOrgName, param.getBuildOrgName())
.like(StringUtils.isNotBlank(param.getProjectName()), Xinchuang::getProjectName, param.getProjectName())
.like(StringUtils.isNotBlank(param.getBuildOrgName()), Xinchuang::getBuildOrgName, param.getBuildOrgName())
.isNotNull(Xinchuang::getInstCode));

if (CollUtil.isEmpty(xinchuangs)) {
@@ -1389,10 +1410,10 @@ public class TodoCenterManage {
req.setUserId(userIdStr);
req.setEmployeeCode(userIdStr);
req.setInstCodes(instCodes);
if(Objects.nonNull(param.getCreateOnMin())){
if (Objects.nonNull(param.getCreateOnMin())) {
req.setStartTime(NdDateUtils.localDateTime2Date(param.getCreateOnMin()));
}
if(Objects.nonNull(param.getCreateOnMax())){
if (Objects.nonNull(param.getCreateOnMax())) {
req.setEndTime(NdDateUtils.localDateTime2Date(param.getCreateOnMax()));
}
List<ProcessInstanceVo> ccMeList = processInstanceService.getCcMeList(req);
@@ -1409,7 +1430,7 @@ public class TodoCenterManage {
List<ResToBeProcessedVO> resVos = ccMeInstList.stream().map(d -> {
ResToBeProcessedVO res = new ResToBeProcessedVO();
XinchuangInst xinchuangInst = xinchuangInstMap.get(d.getInstanceId());
if(Objects.nonNull(xinchuangInst) && xinchuangMap.containsKey(xinchuangInst.getXinchuangId())){
if (Objects.nonNull(xinchuangInst) && xinchuangMap.containsKey(xinchuangInst.getXinchuangId())) {
Xinchuang xinchuang = xinchuangMap.get(xinchuangInst.getXinchuangId());
BeanUtils.copyProperties(xinchuang, res);
res.setXinchuangId(xinchuang.getId());
@@ -1456,7 +1477,7 @@ public class TodoCenterManage {
.orderByDesc(ProjectInst::getProjectId));
projectInfoMap = projectInstList.stream()
.filter(p -> StringUtils.isNotBlank(p.getInstCode()) &&
!TodoCenterConst.Declared.NULL_INST_CODE.equals(p.getInstCode()))
!Declared.NULL_INST_CODE.equals(p.getInstCode()))
.collect(Collectors.toMap(ProjectInst::getInstCode, p -> projectsMap.get(p.getProjectId())));
List<String> instCodes = projectInstList.stream().map(ProjectInst::getInstCode).collect(Collectors.toList());

@@ -1708,7 +1729,7 @@ public class TodoCenterManage {
Map<Long, Project> projectsMap = projects.stream().collect(Collectors.toMap(Project::getId, v -> v));
Map<String, Project> projectInfoMap = projectInstList.stream()
.filter(p -> StringUtils.isNotBlank(p.getInstCode()) &&
!TodoCenterConst.Declared.NULL_INST_CODE.equals(p.getInstCode()))
!Declared.NULL_INST_CODE.equals(p.getInstCode()))
.collect(Collectors.toMap(ProjectInst::getInstCode, p -> projectsMap.get(p.getProjectId())));
// 关联项目信息
List<Project> projectList = list.stream()


+ 1
- 1
hz-pm-gen/src/main/java/com/hz/pm/gen/config/CodeGen.java View File

@@ -55,7 +55,7 @@ public class CodeGen {
}

public static void main(String[] args) {
generate("WendyYang", "sys", PATH_YYD, "nd_msg_call_record");
generate("WendyYang", "projectdeclared", PATH_YYD, "nd_project_change_history");
}

}

Loading…
Cancel
Save