feat(项目管理产品需求重构): 完善产品中的需求规格功能开发

需规修改接口拆分为修改接口和变更接口:
1. 限制已评审或计划中的需求规格请通过需求变更调整需求内容(标题、正文、附件)
2. 限制变更需求规格时,变更内容不能为空
3. 已评审或已计划的需规需要进行变更:调整原需规状态、创建变更后的需规、更新需求唯一标识、原需求评论需迁移至变更后的需求、记录变更评审记录

Signed-off-by: OTTO <731554297@qq.com>
This commit is contained in:
OTTO 2024-12-02 15:17:37 +08:00
parent 1e222677d2
commit f50d4ef1a8
7 changed files with 137 additions and 78 deletions

View File

@ -77,6 +77,17 @@ public class ProductReqSpecsController extends BaseController {
return toAjax(pmsProductRequirementService.updateReqSpecs(productReqSpecsUpdateVo));
}
/**
* 变更需求规格
*/
@RequiresPermissions("pms:pmsProductRequirement:edit")
@Log(title = "需求规格", businessType = BusinessType.UPDATE)
@PutMapping
@ApiOperation(value = "变更需求规格")
public AjaxResult change(@RequestBody @Validated ProductReqSpecsChangeVo productReqSpecsChangeVo) {
return toAjax(pmsProductRequirementService.changeReqSpecs(productReqSpecsChangeVo));
}
/**
* 删除需求规格
*/

View File

@ -7,8 +7,8 @@ import com.microservices.common.core.utils.bean.BeanUtils;
import com.microservices.common.core.web.domain.BaseEntity;
import com.microservices.pms.product.domain.enums.ProductReqStatus;
import com.microservices.pms.product.domain.vo.PmsProductRequirementDataVo;
import com.microservices.pms.product.domain.vo.ProductReqSpecsChangeVo;
import com.microservices.pms.product.domain.vo.ProductReqSpecsDataVo;
import com.microservices.pms.product.domain.vo.ProductReqSpecsUpdateVo;
import com.microservices.pms.product.domain.vo.ProductUserReqDataVo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ -178,29 +178,20 @@ public class PmsProductRequirement extends BaseEntity
return target;
}
public PmsProductRequirement toChangeReqSpecs(ProductReqSpecsUpdateVo productReqSpecsUpdateVo) {
public PmsProductRequirement toChangeReqSpecs(ProductReqSpecsChangeVo productReqSpecsChangeVo) {
PmsProductRequirement target = new PmsProductRequirement();
BeanUtils.copyProperties(this, target);
target.setId(null);
target.setFromId(this.id);
target.setStatus(ProductReqStatus.CHANGING_REQ_SPECS.getKey());
if (StringUtils.isNotEmpty(productReqSpecsUpdateVo.getTitle())) {
target.setTitle(productReqSpecsUpdateVo.getTitle());
if (StringUtils.isNotEmpty(productReqSpecsChangeVo.getTitle())) {
target.setTitle(productReqSpecsChangeVo.getTitle());
}
if (productReqSpecsUpdateVo.getPmsProductModuleId() != null) {
target.setPmsProductModuleId(productReqSpecsUpdateVo.getPmsProductModuleId());
if (StringUtils.isNotEmpty(productReqSpecsChangeVo.getContent())) {
target.setContent(productReqSpecsChangeVo.getContent());
}
if (StringUtils.isNotEmpty(productReqSpecsUpdateVo.getContent())) {
target.setContent(productReqSpecsUpdateVo.getContent());
}
if (StringUtils.isNotEmpty(productReqSpecsUpdateVo.getFileIdentifiers())) {
target.setFileIdentifiers(productReqSpecsUpdateVo.getFileIdentifiers());
}
if (StringUtils.isNotEmpty(productReqSpecsUpdateVo.getType())) {
target.setType(productReqSpecsUpdateVo.getType());
}
if (productReqSpecsUpdateVo.getPmsProductPlanId() != null) {
target.setPmsProductPlanId(productReqSpecsUpdateVo.getPmsProductPlanId());
if (StringUtils.isNotEmpty(productReqSpecsChangeVo.getFileIdentifiers())) {
target.setFileIdentifiers(productReqSpecsChangeVo.getFileIdentifiers());
}
return target;
}

View File

@ -62,4 +62,16 @@ public enum ProductReqStatus {
throw new ServiceException("获取需求规格的来源状态失败");
}
}
// 获取将改成的状态
public static ProductReqStatus getToStatus(String status) {
ProductReqStatus productReqStatus = getByKey(status);
if (REVIEWED_REQ_SPECS == productReqStatus) {
return REVIEWED_REQ_SPECS_CHANGING;
} else if (PLANNED_REQ_SPECS == productReqStatus) {
return PLANNED_REQ_SPECS_CHANGING;
} else {
throw new ServiceException("获取需求规格的更新状态失败");
}
}
}

View File

@ -0,0 +1,57 @@
package com.microservices.pms.product.domain.vo;
import com.microservices.common.core.utils.StringUtils;
import com.microservices.pms.product.domain.PmsProductReqOperationRecord;
import com.microservices.pms.product.domain.PmsProductRequirement;
import com.microservices.pms.product.domain.enums.ProductContentModifyOperation;
import com.microservices.pms.product.domain.enums.ProductReqOperationType;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/**
* 产品需求对象 pms_product_requirement
*
* @author otto
* @date 2023-10-10
*/
@Data
@ApiModel("变更需求规格变更对象")
public class ProductReqSpecsChangeVo {
@ApiModelProperty(value = "需求Id", required = true)
@NotNull
private Long id;
@ApiModelProperty(value = "标题")
@Size(max = 50, message = "长度需要小于50")
private String title;
@ApiModelProperty(value = "正文")
private String content;
@ApiModelProperty(value = "附件标识列表")
private String fileIdentifiers;
// 需求变更记录应记录在原需求下
public PmsProductReqOperationRecord toReqSpecsChangeRecord(Long oldReqSpecsId, PmsProductRequirement changeReqSpecs) {
PmsProductReqOperationRecord record = new PmsProductReqOperationRecord();
record.setProductRequirementId(oldReqSpecsId);
record.setType(ProductReqOperationType.CONTENT_MODIFY.getKey());
record.setOperation(ProductContentModifyOperation.CHANGING_REQ.getKey());
record.setOperator(changeReqSpecs.getUpdateBy());
record.setOperatingTime(changeReqSpecs.getUpdateTime());
return record;
}
public boolean isReqChange(PmsProductRequirement oldPmsProductRequirement) {
if (StringUtils.isNotEmpty(this.getContent()) || StringUtils.isNotEmpty(this.getFileIdentifiers()) || StringUtils.isNotEmpty(this.getTitle())) {
return !oldPmsProductRequirement.getTitle().equals(this.title)
|| !oldPmsProductRequirement.getContent().equals(this.content)
|| !oldPmsProductRequirement.getFileIdentifiers().equals(this.fileIdentifiers);
}
return false;
}
}

View File

@ -9,9 +9,6 @@ import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/**
* 产品需求对象 pms_product_requirement
*
@ -20,24 +17,11 @@ import javax.validation.constraints.Size;
*/
@Data
@ApiModel("需求规格更新对象")
public class ProductReqSpecsUpdateVo {
@ApiModelProperty(value = "需求Id", required = true)
@NotNull
private Long id;
@ApiModelProperty(value = "标题")
@Size(max = 50, message = "长度需要小于50")
private String title;
public class ProductReqSpecsUpdateVo extends ProductReqSpecsChangeVo {
@ApiModelProperty(value = "关联产品模块ID")
private Long pmsProductModuleId;
@ApiModelProperty(value = "正文")
private String content;
@ApiModelProperty(value = "附件标识列表")
private String fileIdentifiers;
@ApiModelProperty(value = "产品需求类型")
private String type;

View File

@ -160,4 +160,6 @@ public interface IPmsProductRequirementService
int deleteReqSpecsByIds(Long[] ids);
int reviewReqSpecs(ProductReqReviewVo productReqReviewVo);
int changeReqSpecs(ProductReqSpecsChangeVo productReqSpecsChangeVo);
}

View File

@ -509,52 +509,54 @@ public class PmsProductRequirementServiceImpl implements IPmsProductRequirementS
int success = 0;
PmsProductReqOperationRecord pmsProductReqOperationRecord;
PmsProduct pmsProduct = pmsProductService.selectPmsProductByIdentifier(oldPmsProductRequirement.getPmsProductIdentifier());
checkUserReqParameter(pmsProductRequirement, pmsProduct);
String reqIdentifier = oldPmsProductRequirement.getIdentifier();
if (StringUtils.isNotEmpty(productReqSpecsUpdateVo.getTitle())) {
checkReqSpecsParameter(pmsProductRequirement, pmsProduct, oldPmsProductRequirement);
if (ProductReqStatus.REVIEWED_REQ_SPECS.getKey().equals(oldPmsProductRequirement.getStatus()) || ProductReqStatus.PLANNED_REQ_SPECS.getKey().equals(oldPmsProductRequirement.getStatus())) {
if (productReqSpecsUpdateVo.isReqChange(oldPmsProductRequirement)) {
throw new ServiceException("已评审或计划中的需求规格请通过需求变更调整需求内容(标题、正文、附件)");
}
} else if (ProductReqStatus.PENDING_REVIEW_REQ_SPECS.getKey().equals(oldPmsProductRequirement.getStatus()) || ProductReqStatus.CHANGING_REQ_SPECS.getKey().equals(oldPmsProductRequirement.getStatus())) {
// 待审核和变更中的需求可随意更改
if (StringUtils.isNotEmpty(productReqSpecsUpdateVo.getTitle())) {
// 更新需求唯一标识
pmsProductRequirement.setIdentifier(genReqSpecsIdentifier(pmsProduct.getProductIdentifier(), productReqSpecsUpdateVo.getTitle()));
}
} else {
throw new ServiceException("当前状态下的需求规格不允许修改");
}
success = updateRequirement(pmsProductRequirement, oldPmsProductRequirement.getPmsProductIdentifier());
pmsProductReqOperationRecordService.insertPmsProductReqOperationRecord(productReqSpecsUpdateVo.toPmsProductReqOperationRecord(pmsProductRequirement));
return success;
}
@Override
public int changeReqSpecs(ProductReqSpecsChangeVo productReqSpecsChangeVo) {
// 通过id检查需修改的产品需求是否存在
PmsProductRequirement oldPmsProductRequirement = selectPmsProductRequirementById(productReqSpecsChangeVo.getId(), true);
if (!ProductReqStatus.REVIEWED_REQ_SPECS.getKey().equals(oldPmsProductRequirement.getStatus()) && !ProductReqStatus.PLANNED_REQ_SPECS.getKey().equals(oldPmsProductRequirement.getStatus())) {
throw new ServiceException("仅已评审和计划中的需求规格才能发起需求变更");
}
if (!productReqSpecsChangeVo.isReqChange(oldPmsProductRequirement)) {
throw new ServiceException("变更需求规格时,变更内容不能为空");
}
// 已评审或已计划的需规需要进行变更创建一条对应的需规
// 调整原需规状态
oldPmsProductRequirement.setStatus(ProductReqStatus.getToStatus(oldPmsProductRequirement.getStatus()).getKey());
updateRequirement(oldPmsProductRequirement, oldPmsProductRequirement.getPmsProductIdentifier());
// 创建变更后的需规
PmsProductRequirement changingReqSpecs = oldPmsProductRequirement.toChangeReqSpecs(productReqSpecsChangeVo);
if (StringUtils.isNotEmpty(productReqSpecsChangeVo.getTitle())) {
// 更新需求唯一标识
reqIdentifier = genReqSpecsIdentifier(pmsProduct.getProductIdentifier(), productReqSpecsUpdateVo.getTitle());
changingReqSpecs.setIdentifier(genReqSpecsIdentifier(oldPmsProductRequirement.getPmsProductIdentifier(), productReqSpecsChangeVo.getTitle()));
}
switch (ProductReqStatus.getByKey(oldPmsProductRequirement.getStatus())) {
case PENDING_REVIEW_REQ_SPECS:
case CHANGING_REQ_SPECS: {
// 待审核和变更中的需求可随意更改
pmsProductRequirement.setIdentifier(reqIdentifier);
success = updateRequirement(pmsProductRequirement, oldPmsProductRequirement.getPmsProductIdentifier());
pmsProductReqOperationRecord =
productReqSpecsUpdateVo.toPmsProductReqOperationRecord(pmsProductRequirement);
break;
}
case REVIEWED_REQ_SPECS:
case PLANNED_REQ_SPECS: {
// 已评审或已计划的需规需要进行变更创建一条对应的需规
if (ProductReqStatus.REVIEWED_REQ_SPECS.getKey().equals(oldPmsProductRequirement.getStatus())) {
oldPmsProductRequirement.setStatus(ProductReqStatus.REVIEWED_REQ_SPECS_CHANGING.getKey());
} else {
oldPmsProductRequirement.setStatus(ProductReqStatus.PLANNED_REQ_SPECS_CHANGING.getKey());
}
success = updateRequirement(oldPmsProductRequirement, oldPmsProductRequirement.getPmsProductIdentifier());
PmsProductRequirement changingReqSpecs = oldPmsProductRequirement.toChangeReqSpecs(productReqSpecsUpdateVo);
changingReqSpecs.setIdentifier(reqIdentifier);
changingReqSpecs.setUpdateBy(SecurityUtils.getUsername());
changingReqSpecs.setUpdateTime(DateUtils.getNowDate());
pmsProductRequirementMapper.insertPmsProductRequirement(changingReqSpecs);
// 原需求评论需迁移至变更后的需求
pmsJournalsService.updateJournalsIdByTypeAndOldId(
PmsConstants.JOURNAL_TYPE_PRODUCT_REQUIREMENT, oldPmsProductRequirement.getId(), changingReqSpecs.getId());
pmsProductReqOperationRecord =
productReqSpecsUpdateVo.toPmsProductReqOperationRecord(changingReqSpecs);
pmsProductReqOperationRecord.setOperation(ProductContentModifyOperation.CHANGING_REQ.getKey());
break;
}
default: {
throw new ServiceException("当前状态下的需求规格不允许修改");
}
}
pmsProductReqOperationRecordService.insertPmsProductReqOperationRecord(pmsProductReqOperationRecord);
changingReqSpecs.setUpdateBy(SecurityUtils.getUsername());
changingReqSpecs.setUpdateTime(DateUtils.getNowDate());
int success = pmsProductRequirementMapper.insertPmsProductRequirement(changingReqSpecs);
// 原需求评论需迁移至变更后的需求
pmsJournalsService.updateJournalsIdByTypeAndOldId(PmsConstants.JOURNAL_TYPE_PRODUCT_REQUIREMENT, oldPmsProductRequirement.getId(), changingReqSpecs.getId());
// 插入变更记录
pmsProductReqOperationRecordService.insertPmsProductReqOperationRecord(productReqSpecsChangeVo.toReqSpecsChangeRecord(oldPmsProductRequirement.getId(), changingReqSpecs));
return success;
}