@@ -1,5 +1,6 @@ | |||
package com.hz.pm.api.common.model.constant; | |||
import cn.hutool.json.JSONConfig; | |||
import com.ningdatech.basic.model.ApiResponse; | |||
import java.math.BigDecimal; | |||
@@ -111,4 +112,10 @@ public class BizConst { | |||
public static final String OP_SUCCESS = "操作成功"; | |||
public static final String OP_FAIL = "操作失败"; | |||
public static final String SAVE_FAIL = "保存失败"; | |||
public static final JSONConfig JSON_NOT_IGNORE_NULL_VALUE; | |||
static { | |||
JSON_NOT_IGNORE_NULL_VALUE = JSONConfig.create().setIgnoreNullValue(false); | |||
} | |||
} |
@@ -1,38 +0,0 @@ | |||
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); | |||
} | |||
} |
@@ -5,6 +5,7 @@ import com.hz.pm.api.projectlib.model.dto.ProjectDTO; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.Data; | |||
import java.io.Serializable; | |||
import java.util.List; | |||
/** | |||
@@ -16,7 +17,9 @@ import java.util.List; | |||
* @since 19:53 2024/8/5 | |||
*/ | |||
@Data | |||
public class ProjectEditDTO { | |||
public class ProjectEditDTO implements Serializable { | |||
private static final long serialVersionUID = 7066112975653039072L; | |||
@ApiModelProperty("项目信息") | |||
private ProjectDTO project; | |||
@@ -7,6 +7,7 @@ import cn.hutool.core.util.ObjUtil; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
import java.io.Serializable; | |||
import java.util.*; | |||
/** | |||
@@ -24,7 +25,9 @@ public class BeanDiffUtil { | |||
@Data | |||
@Builder | |||
public static class FieldDiff { | |||
public static class FieldDiff implements Serializable { | |||
private static final long serialVersionUID = -9003132377177378460L; | |||
private String fieldName; | |||
@@ -28,7 +28,7 @@ import java.util.List; | |||
* @since 11:03 2024/8/5 | |||
*/ | |||
@RestController | |||
@Api(tags = "项目终止控制器") | |||
@Api(tags = "项目终止变更控制器") | |||
@RequestMapping("/api/v1/project") | |||
@RequiredArgsConstructor | |||
public class ProjectStoppedChangeController { | |||
@@ -1,8 +1,6 @@ | |||
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 com.baomidou.mybatisplus.annotation.*; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
import lombok.experimental.Tolerate; | |||
@@ -41,6 +39,7 @@ public class PurchaseStatusChange implements Serializable { | |||
private String event; | |||
@TableField(fill = FieldFill.INSERT) | |||
private LocalDateTime createOn; | |||
private String projectCode; | |||
@@ -1,15 +1,17 @@ | |||
package com.hz.pm.api.projectlib.helper; | |||
import cn.hutool.core.collection.CollUtil; | |||
import cn.hutool.core.util.ClassUtil; | |||
import cn.hutool.core.util.StrUtil; | |||
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.conditions.update.UpdateWrapper; | |||
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.common.util.BizUtils; | |||
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; | |||
@@ -35,9 +37,9 @@ import lombok.RequiredArgsConstructor; | |||
import org.springframework.stereotype.Component; | |||
import org.springframework.transaction.annotation.Transactional; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.lang.reflect.Field; | |||
import java.util.*; | |||
import java.util.stream.Collectors; | |||
/** | |||
* <p> | |||
@@ -124,20 +126,22 @@ public class ProjectChangeStopHelper { | |||
} else { | |||
throw new BizException("不支持的状态转换"); | |||
} | |||
resetProjectPurchaseStatus(project, event, beforeEvent, tenderBeforeEvent, tenderEvent); | |||
resetProjectPurchaseStatus(project.getId(), project.getProjectCode(), event, beforeEvent, tenderBeforeEvent, tenderEvent); | |||
} | |||
private void resetProjectPurchaseStatus(Project project, | |||
private void resetProjectPurchaseStatus(Long projectId, String projectCode, | |||
ProjectStateChangeEvent projEvent, | |||
ProjectStateChangeEvent projBeforeEvent, | |||
TenderStateChangeEvent tenderBeforeEvent, | |||
TenderStateChangeEvent tenderEvent) { | |||
LambdaUpdateWrapper<Project> projectWrapper = Wrappers.lambdaUpdate(Project.class) | |||
.eq(Project::getId, projectId); | |||
if (projBeforeEvent != null) { | |||
if (projEvent.equals(ProjectStateChangeEvent.STOPPED_APPLY_FAILED)) { | |||
project.setStoppedStatus(buildBizStatus(projEvent).getCode()); | |||
projectWrapper.set(Project::getStoppedStatus, buildBizStatus(projEvent).getCode()); | |||
} else { | |||
Wrapper<ProjectChangeHistory> changeHistoryWrapper = Wrappers.lambdaQuery(ProjectChangeHistory.class) | |||
.eq(ProjectChangeHistory::getProjectCode, project.getProjectCode()) | |||
.eq(ProjectChangeHistory::getProjectCode, projectCode) | |||
.orderByDesc(ProjectChangeHistory::getCreateOn) | |||
.last(BizConst.LIMIT_1); | |||
ProjectChangeHistory changeHistory = projectChangeHistoryService.getOne(changeHistoryWrapper); | |||
@@ -147,26 +151,27 @@ public class ProjectChangeStopHelper { | |||
projectEditRewrite(JSONUtil.toBean(changeHistory.getChangeContent(), ProjectEditDTO.class)); | |||
} | |||
} | |||
ProjectStatusChange change = projectStatusChangeService.getLastOne(projBeforeEvent, project.getId()); | |||
ProjectStatusChange change = projectStatusChangeService.getLastOne(projBeforeEvent, projectId); | |||
projectStatusChangeService.save(ProjectStatusChange.builder() | |||
.event(projEvent.name()) | |||
.projectId(project.getId()) | |||
.projectId(projectId) | |||
.event(projEvent.name()) | |||
.projectCode(project.getProjectCode()) | |||
.projectCode(projectCode) | |||
.beforeStatus(change.getAfterStatus()) | |||
.afterStatus(change.getBeforeStatus()) | |||
.createOn(project.getCreateOn()) | |||
.build()); | |||
project.setStatus(change.getBeforeStatus()); | |||
project.setStage(ProjectStatus.getNoNull(project.getStatus()).getStage().getCode()); | |||
projectService.updateById(project); | |||
List<Purchase> purchases = purchaseService.listByProjectId(project.getId()); | |||
Integer currStatus = change.getBeforeStatus(); | |||
projectWrapper.set(Project::getStatus, currStatus); | |||
projectWrapper.set(Project::getStage, ProjectStatus.getNoNull(currStatus).getStage().getCode()); | |||
projectService.update(projectWrapper); | |||
List<Purchase> purchases = purchaseService.listByProjectId(projectId); | |||
if (!purchases.isEmpty()) { | |||
Wrapper<PurchaseStatusChange> purchaseStatusChangeQuery = Wrappers.lambdaQuery(PurchaseStatusChange.class) | |||
.eq(PurchaseStatusChange::getProjectId, project.getId()) | |||
.eq(PurchaseStatusChange::getProjectId, projectId) | |||
.eq(PurchaseStatusChange::getEvent, tenderBeforeEvent); | |||
List<PurchaseStatusChange> purchaseStatusChanges = purchaseStatusChangeService.list(purchaseStatusChangeQuery); | |||
Map<Long, PurchaseStatusChange> purchaseStatusChangeMap = CollUtils.listToMap(purchaseStatusChanges, PurchaseStatusChange::getBidId); | |||
Map<Long, PurchaseStatusChange> purchaseStatusChangeMap = BizUtils.groupFirstMap(purchaseStatusChanges, | |||
PurchaseStatusChange::getBidId, Comparator.comparing(PurchaseStatusChange::getCreateOn).reversed()); | |||
List<PurchaseStatusChange> changeArrayList = new ArrayList<>(); | |||
purchases.forEach(purchase -> { | |||
PurchaseStatusChange currChange = purchaseStatusChangeMap.get(purchase.getId()); | |||
@@ -176,8 +181,8 @@ public class ProjectChangeStopHelper { | |||
.beforeStatus(currChange.getAfterStatus()) | |||
.bidId(purchase.getId()) | |||
.event(tenderEvent.name()) | |||
.projectId(project.getId()) | |||
.projectCode(project.getProjectCode()) | |||
.projectId(projectId) | |||
.projectCode(projectCode) | |||
.build()); | |||
}); | |||
purchaseService.updateBatchById(purchases); | |||
@@ -227,9 +232,9 @@ public class ProjectChangeStopHelper { | |||
projectLibManage.saveGovSystemReplaceInfos(projectDetail.getId(), | |||
projectDetail.getProjectCode(), projectDetail.getSystemReplaceInfos()); | |||
} | |||
LambdaUpdateWrapper<Project> wrapper = buildWrapper(projectDiffs, Project.class); | |||
UpdateWrapper<Project> wrapper = buildWrapper(projectDiffs, Project.class); | |||
if (wrapper != null) { | |||
wrapper.eq(Project::getId, projectDetail.getId()); | |||
wrapper.eq("id", projectDetail.getId()); | |||
projectService.update(wrapper); | |||
} | |||
} | |||
@@ -239,27 +244,27 @@ public class ProjectChangeStopHelper { | |||
List<FieldDiff> purchaseDiffs = purchaseEdit.getPurchaseDiffs(); | |||
if (CollUtil.isNotEmpty(purchaseDiffs)) { | |||
PurchaseDTO purchaseDetail = purchaseEdit.getPurchase(); | |||
LambdaUpdateWrapper<Purchase> wrapper = buildWrapper(purchaseDiffs, Purchase.class); | |||
UpdateWrapper<Purchase> wrapper = buildWrapper(purchaseDiffs, Purchase.class); | |||
if (wrapper != null) { | |||
wrapper.eq(Purchase::getId, purchaseDetail.getId()); | |||
wrapper.eq("id", purchaseDetail.getId()); | |||
purchaseService.update(wrapper); | |||
} | |||
} | |||
List<FieldDiff> contractDiffs = purchaseEdit.getContractDiffs(); | |||
if (CollUtil.isNotEmpty(contractDiffs)) { | |||
ContractDTO contractDetail = purchaseEdit.getContract(); | |||
LambdaUpdateWrapper<Contract> wrapper = buildWrapper(contractDiffs, Contract.class); | |||
UpdateWrapper<Contract> wrapper = buildWrapper(contractDiffs, Contract.class); | |||
if (wrapper != null) { | |||
wrapper.eq(Contract::getId, contractDetail.getId()); | |||
wrapper.eq("id", contractDetail.getId()); | |||
contractService.update(wrapper); | |||
} | |||
} | |||
List<FieldDiff> operationDiffs = purchaseEdit.getOperationDiffs(); | |||
if (CollUtil.isNotEmpty(operationDiffs)) { | |||
OperationDTO operationDetail = purchaseEdit.getOperation(); | |||
LambdaUpdateWrapper<Operation> wrapper = buildWrapper(operationDiffs, Operation.class); | |||
UpdateWrapper<Operation> wrapper = buildWrapper(operationDiffs, Operation.class); | |||
if (wrapper != null) { | |||
wrapper.eq(Operation::getId, operationDetail.getId()); | |||
wrapper.eq("id", operationDetail.getId()); | |||
operationService.update(wrapper); | |||
} | |||
} | |||
@@ -267,25 +272,21 @@ public class ProjectChangeStopHelper { | |||
} | |||
} | |||
private <T> LambdaUpdateWrapper<T> buildWrapper(List<FieldDiff> diffs, | |||
Class<T> clazz) { | |||
LambdaUpdateWrapper<T> wrapper = Wrappers.lambdaUpdate(clazz); | |||
private <T> UpdateWrapper<T> buildWrapper(List<FieldDiff> diffs, Class<T> clazz) { | |||
List<String> fields = Arrays.stream(ClassUtil.getDeclaredFields(clazz)) | |||
.map(Field::getName) | |||
.collect(Collectors.toList()); | |||
UpdateWrapper<T> wrapper = Wrappers.update(); | |||
boolean hasFieldChanged = false; | |||
for (FieldDiff fieldDiff : diffs) { | |||
String fieldName = fieldDiff.getFieldName(); | |||
Object newValue = fieldDiff.getNewValue(); | |||
SFunction<T, Object> reference = getReference(clazz, fieldName); | |||
if (reference != null) { | |||
if (fields.contains(fieldName)) { | |||
hasFieldChanged = true; | |||
wrapper.set(reference, newValue); | |||
wrapper.set(StrUtil.toUnderlineCase(fieldName), newValue); | |||
} | |||
} | |||
return hasFieldChanged ? wrapper : null; | |||
} | |||
private <T> SFunction<T, Object> getReference(Class<T> clazz, String fieldName) { | |||
return (SFunction<T, Object>) MethodReferenceUtil.getReference(clazz, fieldName); | |||
} | |||
} |
@@ -2,11 +2,13 @@ package com.hz.pm.api.projectlib.manage; | |||
import cn.hutool.core.bean.BeanUtil; | |||
import cn.hutool.core.collection.CollUtil; | |||
import cn.hutool.json.JSONConfig; | |||
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.common.model.constant.BizConst; | |||
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; | |||
@@ -103,26 +105,28 @@ public class ProjectChangeManage { | |||
.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); | |||
if (CollUtil.isNotEmpty(projectEdit.getPurchases())) { | |||
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); | |||
} | |||
} | |||
} | |||
@@ -147,7 +151,7 @@ public class ProjectChangeManage { | |||
// 保存变更历史 | |||
ProjectChangeHistory projectChangeHistory = new ProjectChangeHistory(); | |||
projectChangeHistory.setChangeContent(JSONUtil.toJsonStr(projectEdit)); | |||
projectChangeHistory.setChangeContent(JSONUtil.toJsonStr(projectEdit, BizConst.JSON_NOT_IGNORE_NULL_VALUE)); | |||
projectChangeHistory.setChangeReason(req.getChangeReason()); | |||
projectChangeHistory.setProjectId(project.getId()); | |||
projectChangeHistory.setProjectCode(project.getProjectCode()); | |||
@@ -483,8 +483,9 @@ | |||
np.create_on, | |||
np.unit_strip, | |||
npch.status as changeStatus, | |||
npch.craete_on as change_apply_time, | |||
npch.id as changeId | |||
npch.create_on as change_apply_time, | |||
npch.id as changeId, | |||
npch.inst_code as instCode | |||
from (select * from nd_project ${ew.customSqlSegment}) np | |||
inner join nd_project_change_history npch | |||
on np.id = npch.project_id | |||
@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.Data; | |||
import java.io.Serializable; | |||
import java.util.List; | |||
import java.util.Objects; | |||
@@ -16,7 +17,9 @@ import java.util.Objects; | |||
* @since 11:49 2024/2/29 | |||
*/ | |||
@Data | |||
public class GovSystemReplaceInfoDTO { | |||
public class GovSystemReplaceInfoDTO implements Serializable { | |||
private static final long serialVersionUID = -1054216204216816787L; | |||
@ApiModelProperty("替代前系统名称") | |||
private List<String> sourceSystemNames; | |||
@@ -5,6 +5,7 @@ import com.hz.pm.api.common.compare.Compare; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.Data; | |||
import java.io.Serializable; | |||
import java.math.BigDecimal; | |||
import java.time.LocalDateTime; | |||
import java.util.List; | |||
@@ -19,7 +20,9 @@ import java.util.Map; | |||
* @since 2023-02-03 | |||
*/ | |||
@Data | |||
public class ProjectDTO { | |||
public class ProjectDTO implements Serializable { | |||
private static final long serialVersionUID = 632385496811481979L; | |||
public static final String SYSTEM_REPLACE_INFOS = "systemReplaceInfos"; | |||
@@ -59,4 +59,7 @@ public class ProjectChangeListVO { | |||
@ApiModelProperty("变更ID") | |||
private Long changeId; | |||
@ApiModelProperty("流程实例ID") | |||
private String instCode; | |||
} |