fix(产品需求、项目需求): 按照会议所说进行修改。
This commit is contained in:
@@ -19,4 +19,7 @@ public class DictDataRespDTO {
|
||||
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer status; // 参见 CommonStatusEnum 枚举
|
||||
|
||||
@Schema(description = "标识", example = "system")
|
||||
private String sign;
|
||||
|
||||
}
|
||||
|
||||
@@ -59,11 +59,12 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode REQUIREMENT_MODULE_HAS_NON_TERMINAL_REQUIREMENTS = new ErrorCode(1_008_002_012, "模块下存在非终态需求,不可删除");
|
||||
ErrorCode REQUIREMENT_MODULE_HAS_CHILDREN = new ErrorCode(1_008_002_015, "存在子模块,请先删除子模块");
|
||||
ErrorCode REQUIREMENT_MODULE_HAS_REQUIREMENTS = new ErrorCode(1_008_002_016, "模块下存在需求,请先删除需求");
|
||||
ErrorCode PROJECT_REQUIREMENT_MODULE_ROOT_NOT_EXISTS = new ErrorCode(1_008_002_018, "实现项目下不存在根模块,请先创建项目模块");
|
||||
ErrorCode PROJECT_REQUIREMENT_MODULE_ROOT_NOT_EXISTS = new ErrorCode(1_008_002_018, "关联项目下不存在根模块,请先创建项目模块");
|
||||
ErrorCode REQUIREMENT_DISPATCHED_NOT_ALLOW_SPLIT = new ErrorCode(1_008_002_019, "产品需求已分流生成项目需求,不允许再在产品端拆分");
|
||||
ErrorCode REQUIREMENT_NOT_DISPATCHED = new ErrorCode(1_008_002_020, "该产品需求尚未分流到实现项目");
|
||||
ErrorCode REQUIREMENT_NOT_DISPATCHED = new ErrorCode(1_008_002_020, "该产品需求尚未分流到关联项目");
|
||||
ErrorCode REQUIREMENT_DISPATCHED_PROJECT_REQUIREMENT_NOT_FOUND = new ErrorCode(1_008_002_021, "未找到该产品需求对应的项目需求");
|
||||
ErrorCode REQUIREMENT_NOT_PROJECT_MEMBER = new ErrorCode(1_008_002_022, "您不是该项目的成员,无权访问");
|
||||
ErrorCode REQUIREMENT_HANDLER_NOT_PROJECT_MEMBER = new ErrorCode(1_008_002_023, "当前需求负责人不是所选分流项目的成员,请重新选择");
|
||||
|
||||
// ========== 项目管理 1-008-002-000 ==========
|
||||
ErrorCode PROJECT_NOT_EXISTS = new ErrorCode(1_008_002_000, "项目不存在");
|
||||
@@ -189,4 +190,5 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode PROJECT_REQUIREMENT_MODULE_HAS_CHILDREN = new ErrorCode(1_008_007_015, "存在子模块,请先删除子模块");
|
||||
ErrorCode PROJECT_REQUIREMENT_MODULE_HAS_REQUIREMENTS = new ErrorCode(1_008_007_016, "模块下存在项目需求,请先删除需求");
|
||||
ErrorCode PROJECT_REQUIREMENT_CHILD_NOT_ALLOW_CANCEL = new ErrorCode(1_008_007_017, "只有不存在子需求,或子需求都处于已取消和已拒绝状态时,父需求才允许取消");
|
||||
ErrorCode PROJECT_REQUIREMENT_SYNCED_FROM_PRODUCT_NOT_ALLOW_CANCEL = new ErrorCode(1_008_007_019, "\u7531\u4ea7\u54c1\u9700\u6c42\u6d41\u8f6c\u751f\u6210\u7684\u9879\u76ee\u9700\u6c42\u4e0d\u5141\u8bb8\u53d6\u6d88");
|
||||
}
|
||||
|
||||
@@ -101,6 +101,13 @@ public class ProductRequirementController {
|
||||
return success(requirementService.getAllowedTransitions(requirementId, productId));
|
||||
}
|
||||
|
||||
@PostMapping("/allowed-transitions/batch")
|
||||
@Operation(summary = "批量获取需求可执行的状态动作列表")
|
||||
public CommonResult<List<ProductRequirementAllowedTransitionBatchRespVO>> getAllowedTransitionsBatch(
|
||||
@Valid @RequestBody ProductRequirementBatchReqVO reqVO) {
|
||||
return success(requirementService.getAllowedTransitionsBatch(reqVO));
|
||||
}
|
||||
|
||||
@GetMapping("/has-dispatched")
|
||||
@Operation(summary = "判断产品需求是否已分流生成项目需求")
|
||||
@Parameter(name = "requirementId", description = "需求编号", required = true, example = "1024")
|
||||
@@ -111,6 +118,13 @@ public class ProductRequirementController {
|
||||
return success(requirementService.hasDispatchedProjectRequirement(requirementId, productId));
|
||||
}
|
||||
|
||||
@PostMapping("/has-dispatched/batch")
|
||||
@Operation(summary = "批量判断产品需求是否已分流生成项目需求")
|
||||
public CommonResult<List<ProductRequirementHasDispatchedBatchRespVO>> hasDispatchedProjectRequirementBatch(
|
||||
@Valid @RequestBody ProductRequirementBatchReqVO reqVO) {
|
||||
return success(requirementService.hasDispatchedProjectRequirementBatch(reqVO));
|
||||
}
|
||||
|
||||
@GetMapping("/lifecycle")
|
||||
@Operation(summary = "获取需求生命周期信息")
|
||||
@Parameter(name = "requirementId", description = "需求编号", required = true, example = "1024")
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.njcn.rdms.module.project.controller.admin.product.vo.requirement;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 产品需求批量可执行动作 Response VO")
|
||||
@Data
|
||||
public class ProductRequirementAllowedTransitionBatchRespVO {
|
||||
|
||||
@Schema(description = "需求编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long requirementId;
|
||||
|
||||
@Schema(description = "可执行动作列表", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private List<ProductRequirementStatusTransitionRespVO> transitions;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.njcn.rdms.module.project.controller.admin.product.vo.requirement;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 产品需求批量查询 Request VO")
|
||||
@Data
|
||||
public class ProductRequirementBatchReqVO {
|
||||
|
||||
@Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@NotNull(message = "产品编号不能为空")
|
||||
private Long productId;
|
||||
|
||||
@Schema(description = "需求编号列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1, 2, 3]")
|
||||
@NotEmpty(message = "需求编号列表不能为空")
|
||||
private List<Long> requirementIds;
|
||||
|
||||
}
|
||||
@@ -13,7 +13,7 @@ public class ProductRequirementDispatchedProjectLinkRespVO {
|
||||
@Schema(description = "项目需求ID", example = "10086")
|
||||
private Long projectRequirementId;
|
||||
|
||||
@Schema(description = "实现项目ID", example = "8888")
|
||||
@Schema(description = "关联项目ID", example = "8888")
|
||||
private Long projectId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.njcn.rdms.module.project.controller.admin.product.vo.requirement;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - 产品需求批量分流状态 Response VO")
|
||||
@Data
|
||||
public class ProductRequirementHasDispatchedBatchRespVO {
|
||||
|
||||
@Schema(description = "需求编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long requirementId;
|
||||
|
||||
@Schema(description = "是否已分流生成项目需求", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
private Boolean hasDispatched;
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import com.njcn.rdms.module.project.dal.dataobject.attachment.AttachmentItem;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@@ -65,8 +66,8 @@ public class ProductRequirementRespVO {
|
||||
@Schema(description = "提出人用户姓名", example = "张三")
|
||||
private String proposerNickname;
|
||||
|
||||
@Schema(description = "所需工时", example = "8")
|
||||
private Double workHours;
|
||||
@Schema(description = "预期完成时间", example = "2026-05-31")
|
||||
private LocalDate expectedTime;
|
||||
|
||||
@Schema(description = "当前处理人用户ID", example = "1024")
|
||||
private Long currentHandlerUserId;
|
||||
|
||||
@@ -8,6 +8,7 @@ import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -55,9 +56,8 @@ public class ProductRequirementSaveReqVO {
|
||||
@Schema(description = "提出人姓名", example = "张三")
|
||||
private String proposerNickname;
|
||||
|
||||
@Schema(description = "所需工时", example = "8")
|
||||
@NotNull(message = "所需工时不能为空")
|
||||
private Double workHours;
|
||||
@Schema(description = "预期完成时间", example = "2026-05-31")
|
||||
private LocalDate expectedTime;
|
||||
|
||||
@Schema(description = "当前处理人用户ID", example = "1024")
|
||||
private Long currentHandlerUserId;
|
||||
|
||||
@@ -8,6 +8,7 @@ import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -56,9 +57,8 @@ public class ProductRequirementSplitReqVO {
|
||||
@Schema(description = "提出人姓名", example = "张三")
|
||||
private String proposerNickname;
|
||||
|
||||
@Schema(description = "所需工时", example = "8")
|
||||
@NotNull(message = "所需工时不能为空")
|
||||
private Double workHours;
|
||||
@Schema(description = "预期完成时间", example = "2026-05-31")
|
||||
private LocalDate expectedTime;
|
||||
|
||||
@Schema(description = "当前处理人用户ID", example = "1024")
|
||||
private Long currentHandlerUserId;
|
||||
|
||||
@@ -30,6 +30,6 @@ public class ProductRequirementStatusActionReqVO {
|
||||
@Schema(description = "状态变更原因", example = "评审通过,进入分流阶段")
|
||||
private String reason;
|
||||
|
||||
@Schema(description = "实现项目编号(dispatch动作时可选)", example = "1024")
|
||||
@Schema(description = "关联项目编号(dispatch动作时可选)", example = "1024")
|
||||
private Long implementProjectId;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -56,9 +57,8 @@ public class ProductRequirementUpdateReqVO {
|
||||
@Schema(description = "提出人姓名", example = "张三")
|
||||
private String proposerNickname;
|
||||
|
||||
@Schema(description = "所需工时", example = "8")
|
||||
@NotNull(message = "所需工时不能为空")
|
||||
private Double workHours;
|
||||
@Schema(description = "预期完成时间", example = "2026-05-31")
|
||||
private LocalDate expectedTime;
|
||||
|
||||
@Schema(description = "当前处理人用户ID", example = "1024")
|
||||
private Long currentHandlerUserId;
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.njcn.rdms.module.project.controller.admin.project;
|
||||
|
||||
import com.njcn.rdms.framework.common.pojo.CommonResult;
|
||||
import com.njcn.rdms.framework.common.pojo.PageResult;
|
||||
import com.njcn.rdms.module.project.controller.admin.project.vo.requirement.ProjectRequirementAllowedTransitionBatchRespVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.project.vo.requirement.ProjectRequirementBatchReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.project.vo.requirement.ProjectRequirementCloseReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.project.vo.requirement.ProjectRequirementDeleteReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.project.vo.requirement.ProjectRequirementLifecycleRespVO;
|
||||
@@ -112,6 +114,13 @@ public class ProjectRequirementController {
|
||||
return success(requirementService.getAllowedTransitions(requirementId, projectId));
|
||||
}
|
||||
|
||||
@PostMapping("/allowed-transitions/batch")
|
||||
@Operation(summary = "批量获取需求可执行的状态动作列表")
|
||||
public CommonResult<List<ProjectRequirementAllowedTransitionBatchRespVO>> getAllowedTransitionsBatch(
|
||||
@Valid @RequestBody ProjectRequirementBatchReqVO reqVO) {
|
||||
return success(requirementService.getAllowedTransitionsBatch(reqVO));
|
||||
}
|
||||
|
||||
@GetMapping("/lifecycle")
|
||||
@Operation(summary = "获取需求生命周期信息")
|
||||
@Parameter(name = "requirementId", description = "需求编号", required = true, example = "1024")
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.njcn.rdms.module.project.controller.admin.project.vo.requirement;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 项目需求批量可执行动作 Response VO")
|
||||
@Data
|
||||
public class ProjectRequirementAllowedTransitionBatchRespVO {
|
||||
|
||||
@Schema(description = "需求编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long requirementId;
|
||||
|
||||
@Schema(description = "可执行动作列表", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private List<ProjectRequirementStatusTransitionRespVO> transitions;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.njcn.rdms.module.project.controller.admin.project.vo.requirement;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 项目需求批量查询 Request VO")
|
||||
@Data
|
||||
public class ProjectRequirementBatchReqVO {
|
||||
|
||||
@Schema(description = "项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@NotNull(message = "项目编号不能为空")
|
||||
private Long projectId;
|
||||
|
||||
@Schema(description = "需求编号列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1, 2, 3]")
|
||||
@NotEmpty(message = "需求编号列表不能为空")
|
||||
private List<Long> requirementIds;
|
||||
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import com.njcn.rdms.module.project.dal.dataobject.attachment.AttachmentItem;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@@ -68,8 +69,8 @@ public class ProjectRequirementRespVO {
|
||||
@Schema(description = "提出人姓名", example = "张三")
|
||||
private String proposerNickname;
|
||||
|
||||
@Schema(description = "所需工时", example = "8")
|
||||
private Double workHours;
|
||||
@Schema(description = "预期完成时间", example = "2026-05-31")
|
||||
private LocalDate expectedTime;
|
||||
|
||||
@Schema(description = "当前处理人用户ID", example = "1024")
|
||||
private Long currentHandlerUserId;
|
||||
|
||||
@@ -8,6 +8,7 @@ import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -55,9 +56,8 @@ public class ProjectRequirementSaveReqVO {
|
||||
@Schema(description = "提出人姓名", example = "张三")
|
||||
private String proposerNickname;
|
||||
|
||||
@Schema(description = "所需工时", example = "8")
|
||||
@NotNull(message = "所需工时不能为空")
|
||||
private Double workHours;
|
||||
@Schema(description = "预期完成时间", example = "2026-05-31")
|
||||
private LocalDate expectedTime;
|
||||
|
||||
@Schema(description = "当前处理人用户ID", example = "1024")
|
||||
private Long currentHandlerUserId;
|
||||
|
||||
@@ -8,6 +8,7 @@ import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -56,9 +57,8 @@ public class ProjectRequirementSplitReqVO {
|
||||
@Schema(description = "提出人姓名", example = "张三")
|
||||
private String proposerNickname;
|
||||
|
||||
@Schema(description = "所需工时", example = "8")
|
||||
@NotNull(message = "所需工时不能为空")
|
||||
private Double workHours;
|
||||
@Schema(description = "预期完成时间", example = "2026-05-31")
|
||||
private LocalDate expectedTime;
|
||||
|
||||
@Schema(description = "当前处理人用户ID", example = "1024")
|
||||
private Long currentHandlerUserId;
|
||||
|
||||
@@ -8,6 +8,7 @@ import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -56,9 +57,8 @@ public class ProjectRequirementUpdateReqVO {
|
||||
@Schema(description = "提出人姓名", example = "张三")
|
||||
private String proposerNickname;
|
||||
|
||||
@Schema(description = "所需工时", example = "8")
|
||||
@NotNull(message = "所需工时不能为空")
|
||||
private Double workHours;
|
||||
@Schema(description = "预期完成时间", example = "2026-05-31")
|
||||
private LocalDate expectedTime;
|
||||
|
||||
@Schema(description = "当前处理人用户ID", example = "1024")
|
||||
private Long currentHandlerUserId;
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.njcn.rdms.module.project.dal.dataobject.attachment.AttachmentItem;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -81,9 +82,9 @@ public class ProductRequirementDO extends BaseDO {
|
||||
*/
|
||||
private String proposerNickname;
|
||||
/**
|
||||
* 所需工时
|
||||
* 预期完成时间
|
||||
*/
|
||||
private Double workHours;
|
||||
private LocalDate expectedTime;
|
||||
/**
|
||||
* 当前处理人用户ID
|
||||
*/
|
||||
@@ -101,7 +102,7 @@ public class ProductRequirementDO extends BaseDO {
|
||||
*/
|
||||
private Integer sort;
|
||||
/**
|
||||
* 闄勪欢鍒楄〃锛圝SON锛夈€傚厓绱?{@link AttachmentItem}锛歩d / url / name / size / contentType銆?
|
||||
* 附件列表
|
||||
*/
|
||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
private List<AttachmentItem> attachments;
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.njcn.rdms.module.project.dal.dataobject.attachment.AttachmentItem;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -93,15 +94,15 @@ public class ProjectRequirementDO extends BaseDO {
|
||||
*/
|
||||
private String currentHandlerUserNickname;
|
||||
/**
|
||||
* 预估工时
|
||||
* 预期完成时间
|
||||
*/
|
||||
private Double workHours;
|
||||
private LocalDate expectedTime;
|
||||
/**
|
||||
* 排序值
|
||||
*/
|
||||
private Integer sort;
|
||||
/**
|
||||
* 闄勪欢鍒楄〃锛圝SON锛夈€傚厓绱?{@link AttachmentItem}锛歩d / url / name / size / contentType銆?
|
||||
* 附件项列表
|
||||
*/
|
||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
private List<AttachmentItem> attachments;
|
||||
|
||||
@@ -112,7 +112,7 @@ public interface ProductRequirementMapper extends BaseMapperX<ProductRequirement
|
||||
}
|
||||
|
||||
/**
|
||||
* 带并发控制的状态更新(支持同时更新实现项目ID)
|
||||
* 带并发控制的状态更新(支持同时更新关联项目ID)
|
||||
*/
|
||||
default int updateStatusByIdAndStatusWithProject(Long id, String fromStatus, String toStatus, String lastStatusReason, Long implementProjectId) {
|
||||
ProductRequirementDO update = new ProductRequirementDO();
|
||||
|
||||
@@ -61,6 +61,13 @@ public interface ObjectStatusTransitionMapper extends BaseMapperX<ObjectStatusTr
|
||||
.eq(ObjectStatusTransitionDO::getStatus, 0));
|
||||
}
|
||||
|
||||
default List<ObjectStatusTransitionDO> selectListByObjectTypeAndFromStatuses(String objectType, List<String> fromStatusCodes) {
|
||||
return selectList(new LambdaQueryWrapperX<ObjectStatusTransitionDO>()
|
||||
.eq(ObjectStatusTransitionDO::getObjectType, objectType)
|
||||
.in(ObjectStatusTransitionDO::getFromStatusCode, fromStatusCodes)
|
||||
.eq(ObjectStatusTransitionDO::getStatus, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* 统计某状态编码在流转配置中的引用次数。
|
||||
*/
|
||||
|
||||
@@ -88,6 +88,14 @@ public interface ProductRequirementService {
|
||||
*/
|
||||
List<ProductRequirementStatusTransitionRespVO> getAllowedTransitions(Long requirementId, Long productId);
|
||||
|
||||
/**
|
||||
* 批量获取需求当前可执行的状态动作列表
|
||||
*
|
||||
* @param reqVO 批量查询请求
|
||||
* @return 按需求编号标识的可执行动作列表
|
||||
*/
|
||||
List<ProductRequirementAllowedTransitionBatchRespVO> getAllowedTransitionsBatch(ProductRequirementBatchReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 判断需求是否已分流并生成项目需求
|
||||
*
|
||||
@@ -97,6 +105,14 @@ public interface ProductRequirementService {
|
||||
*/
|
||||
boolean hasDispatchedProjectRequirement(Long requirementId, Long productId);
|
||||
|
||||
/**
|
||||
* 批量判断需求是否已分流并生成项目需求
|
||||
*
|
||||
* @param reqVO 批量查询请求
|
||||
* @return 按需求编号标识的分流状态
|
||||
*/
|
||||
List<ProductRequirementHasDispatchedBatchRespVO> hasDispatchedProjectRequirementBatch(ProductRequirementBatchReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 获取需求生命周期信息(当前状态 + 可执行动作)
|
||||
*
|
||||
@@ -157,7 +173,7 @@ public interface ProductRequirementService {
|
||||
* 获取产品需求分流后对应的项目需求跳转链接
|
||||
*
|
||||
* @param productRequirementId 产品需求编号
|
||||
* @return 项目需求ID和实现项目ID
|
||||
* @return 项目需求ID和关联项目ID
|
||||
*/
|
||||
ProductRequirementDispatchedProjectLinkRespVO getDispatchedProjectLink(Long productRequirementId);
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.njcn.rdms.framework.security.core.util.SecurityFrameworkUtils;
|
||||
import com.njcn.rdms.module.project.controller.admin.product.vo.requirement.*;
|
||||
import com.njcn.rdms.module.project.constant.ProjectObjectConstants;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.audit.BizAuditLogDO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.member.UserObjectRoleDO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.product.ProductRequirementDO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.product.ProductRequirementModuleDO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.product.ProductRequirementStatusLogDO;
|
||||
@@ -143,11 +144,11 @@ public class ProductRequirementServiceImpl implements ProductRequirementService
|
||||
requirement.setStatusCode(initialStatus);
|
||||
requirement.setProposerId(createReqVO.getProposerId());
|
||||
requirement.setProposerNickname(normalizeNullableText(createReqVO.getProposerNickname()));
|
||||
requirement.setWorkHours(createReqVO.getWorkHours());
|
||||
requirement.setExpectedTime(createReqVO.getExpectedTime());
|
||||
requirement.setCurrentHandlerUserId(createReqVO.getCurrentHandlerUserId());
|
||||
requirement.setCurrentHandlerUserNickname(normalizeNullableText(createReqVO.getCurrentHandlerUserNickname()));
|
||||
requirement.setImplementProjectId(createReqVO.getImplementProjectId());
|
||||
requirement.setSort(createReqVO.getSort() != null ? createReqVO.getSort() : 0);
|
||||
requirement.setSort(createReqVO.getSort());
|
||||
requirement.setAttachments(createReqVO.getAttachments());
|
||||
requirementMapper.insert(requirement);
|
||||
|
||||
@@ -182,11 +183,11 @@ public class ProductRequirementServiceImpl implements ProductRequirementService
|
||||
requirement.setPriority(updateReqVO.getPriority());
|
||||
requirement.setProposerId(updateReqVO.getProposerId());
|
||||
requirement.setProposerNickname(normalizeNullableText(updateReqVO.getProposerNickname()));
|
||||
requirement.setWorkHours(updateReqVO.getWorkHours());
|
||||
requirement.setExpectedTime(updateReqVO.getExpectedTime());
|
||||
requirement.setCurrentHandlerUserId(updateReqVO.getCurrentHandlerUserId());
|
||||
requirement.setCurrentHandlerUserNickname(normalizeNullableText(updateReqVO.getCurrentHandlerUserNickname()));
|
||||
requirement.setImplementProjectId(updateReqVO.getImplementProjectId());
|
||||
requirement.setSort(updateReqVO.getSort() != null ? updateReqVO.getSort() : 0);
|
||||
requirement.setSort(updateReqVO.getSort());
|
||||
requirement.setAttachments(updateReqVO.getAttachments());
|
||||
requirementMapper.updateById(requirement);
|
||||
|
||||
@@ -262,7 +263,7 @@ public class ProductRequirementServiceImpl implements ProductRequirementService
|
||||
// 第三步:查询根需求详情并按排序值升序、创建时间倒排
|
||||
List<ProductRequirementDO> rootRequirements = requirementMapper.selectBatchIds(rootIds);
|
||||
rootRequirements.sort((a, b) -> {
|
||||
int sortCompare = Integer.compare(a.getSort() != null ? a.getSort() : 0, b.getSort() != null ? b.getSort() : 0);
|
||||
int sortCompare = Comparator.nullsLast(Integer::compareTo).compare(a.getSort(), b.getSort());
|
||||
if (sortCompare != 0) {
|
||||
return sortCompare;
|
||||
}
|
||||
@@ -496,11 +497,19 @@ public class ProductRequirementServiceImpl implements ProductRequirementService
|
||||
if (ACTION_CLOSE.equals(actionCode)) {
|
||||
closeAllAcceptedChildren(reqVO.getId(), reason);
|
||||
}
|
||||
// dispatch动作且选择了实现项目时,自动创建对应的项目需求
|
||||
// dispatch动作且选择了关联项目时,校验负责人是否在项目中,然后自动创建对应的项目需求
|
||||
if (ACTION_DISPATCH.equals(actionCode) && implementProjectId != null) {
|
||||
// 校验负责人是否为目标项目的成员
|
||||
if (requirement.getCurrentHandlerUserId() != null) {
|
||||
List<UserObjectRoleDO> userObjectRoleDOS = userObjectRoleMapper.selectActiveListByObjectAndUserId(
|
||||
ProjectObjectConstants.OBJECT_TYPE, implementProjectId, requirement.getCurrentHandlerUserId());
|
||||
if (userObjectRoleDOS.isEmpty()) {
|
||||
throw exception(ErrorCodeConstants.REQUIREMENT_HANDLER_NOT_PROJECT_MEMBER);
|
||||
}
|
||||
}
|
||||
createProjectRequirementFromProduct(requirement, implementProjectId);
|
||||
}
|
||||
// 带并发控制的状态更新(支持同时更新实现项目ID)
|
||||
// 带并发控制的状态更新(支持同时更新关联项目ID)
|
||||
int updateCount = requirementMapper.updateStatusByIdAndStatusWithProject(requirement.getId(), fromStatus, toStatus, reason, implementProjectId);
|
||||
if (updateCount != 1) {
|
||||
throw exception(ErrorCodeConstants.REQUIREMENT_STATUS_CONCURRENT_MODIFIED);
|
||||
@@ -613,11 +622,11 @@ public class ProductRequirementServiceImpl implements ProductRequirementService
|
||||
childRequirement.setStatusCode(initialStatus);
|
||||
childRequirement.setProposerId(reqVO.getProposerId());
|
||||
childRequirement.setProposerNickname(normalizeNullableText(reqVO.getProposerNickname()));
|
||||
childRequirement.setWorkHours(reqVO.getWorkHours());
|
||||
childRequirement.setExpectedTime(reqVO.getExpectedTime());
|
||||
childRequirement.setCurrentHandlerUserId(reqVO.getCurrentHandlerUserId());
|
||||
childRequirement.setCurrentHandlerUserNickname(normalizeNullableText(reqVO.getCurrentHandlerUserNickname()));
|
||||
childRequirement.setImplementProjectId(reqVO.getImplementProjectId());
|
||||
childRequirement.setSort(reqVO.getSort() != null ? reqVO.getSort() : 0);
|
||||
childRequirement.setSort(reqVO.getSort());
|
||||
childRequirement.setAttachments(reqVO.getAttachments());
|
||||
requirementMapper.insert(childRequirement);
|
||||
|
||||
@@ -721,16 +730,38 @@ public class ProductRequirementServiceImpl implements ProductRequirementService
|
||||
// 取消动作不满足前置条件时,不再返回给前端展示按钮
|
||||
.filter(transition -> shouldExposeTransition(requirement, transition))
|
||||
.map(transition -> {
|
||||
ProductRequirementStatusTransitionRespVO vo = new ProductRequirementStatusTransitionRespVO();
|
||||
vo.setActionCode(transition.getActionCode());
|
||||
vo.setActionName(transition.getActionName());
|
||||
vo.setToStatusCode(transition.getToStatusCode());
|
||||
// 查询目标状态名称
|
||||
ObjectStatusModelDO statusModel = statusModelMapper
|
||||
.selectByObjectTypeAndStatusCode(REQUIREMENT_OBJECT_TYPE, transition.getToStatusCode());
|
||||
vo.setToStatusName(statusModel != null ? statusModel.getStatusName() : transition.getToStatusCode());
|
||||
vo.setNeedReason(transition.getNeedReason());
|
||||
return vo;
|
||||
ProductRequirementStatusTransitionRespVO vo = new ProductRequirementStatusTransitionRespVO();
|
||||
vo.setActionCode(transition.getActionCode());
|
||||
vo.setActionName(transition.getActionName());
|
||||
vo.setToStatusCode(transition.getToStatusCode());
|
||||
// 查询目标状态名称
|
||||
ObjectStatusModelDO statusModel = statusModelMapper
|
||||
.selectByObjectTypeAndStatusCode(REQUIREMENT_OBJECT_TYPE, transition.getToStatusCode());
|
||||
vo.setToStatusName(statusModel != null ? statusModel.getStatusName() : transition.getToStatusCode());
|
||||
vo.setNeedReason(transition.getNeedReason());
|
||||
return vo;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@CheckObjectPermission(objectType = PRODUCT_OBJECT_TYPE, objectId = "#reqVO.productId",
|
||||
permission = PRODUCT_QUERY_PERMISSION)
|
||||
public List<ProductRequirementAllowedTransitionBatchRespVO> getAllowedTransitionsBatch(ProductRequirementBatchReqVO reqVO) {
|
||||
List<ProductRequirementDO> requirements = getBatchRequirements(reqVO.getRequirementIds(), reqVO.getProductId());
|
||||
Set<Long> dispatchedRequirementIds = getDispatchedProductRequirementIds(requirements);
|
||||
Map<String, List<ObjectStatusTransitionDO>> transitionsByStatus = getTransitionsByStatus(requirements);
|
||||
Map<String, ObjectStatusModelDO> statusModelMap = getStatusModelMap();
|
||||
|
||||
return requirements.stream().map(requirement -> {
|
||||
ProductRequirementAllowedTransitionBatchRespVO respVO = new ProductRequirementAllowedTransitionBatchRespVO();
|
||||
respVO.setRequirementId(requirement.getId());
|
||||
if (dispatchedRequirementIds.contains(requirement.getId())) {
|
||||
respVO.setTransitions(Collections.emptyList());
|
||||
} else {
|
||||
respVO.setTransitions(buildAllowedTransitions(requirement,
|
||||
transitionsByStatus.getOrDefault(requirement.getStatusCode(), Collections.emptyList()), statusModelMap));
|
||||
}
|
||||
return respVO;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@@ -742,13 +773,27 @@ public class ProductRequirementServiceImpl implements ProductRequirementService
|
||||
return hasDispatchedProjectRequirement(requirement);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CheckObjectPermission(objectType = PRODUCT_OBJECT_TYPE, objectId = "#reqVO.productId",
|
||||
permission = PRODUCT_QUERY_PERMISSION)
|
||||
public List<ProductRequirementHasDispatchedBatchRespVO> hasDispatchedProjectRequirementBatch(ProductRequirementBatchReqVO reqVO) {
|
||||
List<ProductRequirementDO> requirements = getBatchRequirements(reqVO.getRequirementIds(), reqVO.getProductId());
|
||||
Set<Long> dispatchedRequirementIds = getDispatchedProductRequirementIds(requirements);
|
||||
return requirements.stream().map(requirement -> {
|
||||
ProductRequirementHasDispatchedBatchRespVO respVO = new ProductRequirementHasDispatchedBatchRespVO();
|
||||
respVO.setRequirementId(requirement.getId());
|
||||
respVO.setHasDispatched(dispatchedRequirementIds.contains(requirement.getId()));
|
||||
return respVO;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 该方法作用和getAllowedTransitions()类似,是用来获取当前状态下可以进行的动作
|
||||
* @deprecated 产品需求页面最开始用来下拉框改状态时使用的,已经弃用
|
||||
*
|
||||
* @param requirementId 需求编号
|
||||
* @param productId 产品编号
|
||||
* @return ProductRequirementLifecycleRespVO
|
||||
* @deprecated 产品需求页面最开始用来下拉框改状态时使用的,已经弃用
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
@@ -778,7 +823,7 @@ public class ProductRequirementServiceImpl implements ProductRequirementService
|
||||
|
||||
@Override
|
||||
public ProductRequirementDispatchedProjectLinkRespVO getDispatchedProjectLink(Long productRequirementId) {
|
||||
// 校验产品需求是否存在,以及是否已分流到具体的实现项目
|
||||
// 校验产品需求是否存在,以及是否已分流到具体的关联项目
|
||||
ProductRequirementDO requirement = validateRequirementExists(productRequirementId);
|
||||
if (requirement.getImplementProjectId() == null) {
|
||||
throw exception(ErrorCodeConstants.REQUIREMENT_NOT_DISPATCHED);
|
||||
@@ -823,6 +868,78 @@ public class ProductRequirementServiceImpl implements ProductRequirementService
|
||||
return !projectRequirements.isEmpty();
|
||||
}
|
||||
|
||||
private List<ProductRequirementDO> getBatchRequirements(List<Long> requirementIds, Long productId) {
|
||||
if (requirementIds == null || requirementIds.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
if (requirementIds.stream().anyMatch(Objects::isNull)) {
|
||||
throw invalidParamException("需求编号不能为空");
|
||||
}
|
||||
List<Long> distinctIds = requirementIds.stream().distinct().collect(Collectors.toList());
|
||||
Map<Long, ProductRequirementDO> requirementMap = requirementMapper.selectByIds(distinctIds).stream()
|
||||
.collect(Collectors.toMap(ProductRequirementDO::getId, Function.identity()));
|
||||
if (requirementMap.size() != distinctIds.size()) {
|
||||
throw exception(ErrorCodeConstants.REQUIREMENT_NOT_EXISTS);
|
||||
}
|
||||
List<ProductRequirementDO> requirements = distinctIds.stream()
|
||||
.map(requirementMap::get)
|
||||
.collect(Collectors.toList());
|
||||
for (ProductRequirementDO requirement : requirements) {
|
||||
if (!Objects.equals(requirement.getProductId(), productId)) {
|
||||
throw invalidParamException("需求不属于当前产品");
|
||||
}
|
||||
}
|
||||
return requirements;
|
||||
}
|
||||
|
||||
private Set<Long> getDispatchedProductRequirementIds(List<ProductRequirementDO> requirements) {
|
||||
List<Long> candidateIds = requirements.stream()
|
||||
.filter(requirement -> requirement.getImplementProjectId() != null)
|
||||
.map(ProductRequirementDO::getId)
|
||||
.collect(Collectors.toList());
|
||||
if (candidateIds.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
return projectRequirementMapper.selectList(new LambdaQueryWrapperX<ProjectRequirementDO>()
|
||||
.eq(ProjectRequirementDO::getSourceType, "product_requirement")
|
||||
.in(ProjectRequirementDO::getProductRequirementId, candidateIds))
|
||||
.stream()
|
||||
.map(ProjectRequirementDO::getProductRequirementId)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private Map<String, List<ObjectStatusTransitionDO>> getTransitionsByStatus(List<ProductRequirementDO> requirements) {
|
||||
List<String> statusCodes = requirements.stream()
|
||||
.map(ProductRequirementDO::getStatusCode)
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
if (statusCodes.isEmpty()) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
return statusTransitionMapper.selectListByObjectTypeAndFromStatuses(REQUIREMENT_OBJECT_TYPE, statusCodes)
|
||||
.stream()
|
||||
.collect(Collectors.groupingBy(ObjectStatusTransitionDO::getFromStatusCode));
|
||||
}
|
||||
|
||||
private List<ProductRequirementStatusTransitionRespVO> buildAllowedTransitions(
|
||||
ProductRequirementDO requirement,
|
||||
List<ObjectStatusTransitionDO> transitions,
|
||||
Map<String, ObjectStatusModelDO> statusModelMap) {
|
||||
return transitions.stream()
|
||||
.filter(transition -> shouldExposeTransition(requirement, transition))
|
||||
.map(transition -> {
|
||||
ProductRequirementStatusTransitionRespVO vo = new ProductRequirementStatusTransitionRespVO();
|
||||
vo.setActionCode(transition.getActionCode());
|
||||
vo.setActionName(transition.getActionName());
|
||||
vo.setToStatusCode(transition.getToStatusCode());
|
||||
ObjectStatusModelDO statusModel = statusModelMap.get(transition.getToStatusCode());
|
||||
vo.setToStatusName(statusModel != null ? statusModel.getStatusName() : transition.getToStatusCode());
|
||||
vo.setNeedReason(transition.getNeedReason());
|
||||
return vo;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 已分流并生成项目需求后,产品需求端不再允许继续拆分。
|
||||
*/
|
||||
@@ -1265,7 +1382,7 @@ public class ProductRequirementServiceImpl implements ProductRequirementService
|
||||
target.setLastStatusReason(source.getLastStatusReason());
|
||||
target.setProposerId(source.getProposerId());
|
||||
target.setProposerNickname(source.getProposerNickname());
|
||||
target.setWorkHours(source.getWorkHours());
|
||||
target.setExpectedTime(source.getExpectedTime());
|
||||
target.setCurrentHandlerUserId(source.getCurrentHandlerUserId());
|
||||
target.setCurrentHandlerUserNickname(source.getCurrentHandlerUserNickname());
|
||||
target.setImplementProjectId(source.getImplementProjectId());
|
||||
@@ -1307,8 +1424,8 @@ public class ProductRequirementServiceImpl implements ProductRequirementService
|
||||
valueOf(after, ProductRequirementDO::getProposerId));
|
||||
appendFieldChange(fieldChanges, "proposerNickname", valueOf(before, ProductRequirementDO::getProposerNickname),
|
||||
valueOf(after, ProductRequirementDO::getProposerNickname));
|
||||
appendFieldChange(fieldChanges, "workHours", valueOf(before, ProductRequirementDO::getWorkHours),
|
||||
valueOf(after, ProductRequirementDO::getWorkHours));
|
||||
appendFieldChange(fieldChanges, "expectedTime", valueOf(before, ProductRequirementDO::getExpectedTime),
|
||||
valueOf(after, ProductRequirementDO::getExpectedTime));
|
||||
appendFieldChange(fieldChanges, "currentHandlerUserId", valueOf(before, ProductRequirementDO::getCurrentHandlerUserId),
|
||||
valueOf(after, ProductRequirementDO::getCurrentHandlerUserId));
|
||||
appendFieldChange(fieldChanges, "currentHandlerUserNickname",
|
||||
@@ -1358,10 +1475,10 @@ public class ProductRequirementServiceImpl implements ProductRequirementService
|
||||
}
|
||||
|
||||
/**
|
||||
* dispatch动作且已选择实现项目时,自动将产品需求转化为项目需求
|
||||
* dispatch动作且已选择关联项目时,自动将产品需求转化为项目需求
|
||||
*
|
||||
* @param productRequirement 产品需求
|
||||
* @param implementProjectId 实现项目ID
|
||||
* @param implementProjectId 关联项目ID
|
||||
*/
|
||||
@VisibleForTesting
|
||||
void createProjectRequirementFromProduct(ProductRequirementDO productRequirement, Long implementProjectId) {
|
||||
@@ -1374,7 +1491,7 @@ public class ProductRequirementServiceImpl implements ProductRequirementService
|
||||
return;
|
||||
}
|
||||
|
||||
// 查询实现项目下的根模块(parentId = 0)
|
||||
// 查询关联项目下的根模块(parentId = 0)
|
||||
ProjectRequirementModuleDO rootModule = projectRequirementModuleMapper.selectByProjectIdAndParentId(implementProjectId, 0L);
|
||||
if (rootModule == null) {
|
||||
throw exception(ErrorCodeConstants.PROJECT_REQUIREMENT_MODULE_ROOT_NOT_EXISTS);
|
||||
@@ -1397,9 +1514,9 @@ public class ProductRequirementServiceImpl implements ProductRequirementService
|
||||
newRequirement.setPriority(productRequirement.getPriority());
|
||||
newRequirement.setProposerId(productRequirement.getProposerId());
|
||||
newRequirement.setProposerNickname(productRequirement.getProposerNickname());
|
||||
newRequirement.setExpectedTime(productRequirement.getExpectedTime());
|
||||
newRequirement.setCurrentHandlerUserId(productRequirement.getCurrentHandlerUserId());
|
||||
newRequirement.setCurrentHandlerUserNickname(productRequirement.getCurrentHandlerUserNickname());
|
||||
newRequirement.setWorkHours(productRequirement.getWorkHours());
|
||||
newRequirement.setAttachments(productRequirement.getAttachments());
|
||||
newRequirement.setCreator(productRequirement.getCreator());
|
||||
newRequirement.setCreateTime(productRequirement.getCreateTime());
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.njcn.rdms.module.project.service.project;
|
||||
|
||||
import com.njcn.rdms.framework.common.pojo.PageResult;
|
||||
import com.njcn.rdms.module.project.controller.admin.project.vo.requirement.ProjectRequirementAllowedTransitionBatchRespVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.project.vo.requirement.ProjectRequirementBatchReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.project.vo.requirement.ProjectRequirementCloseReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.project.vo.requirement.ProjectRequirementLifecycleRespVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.project.vo.requirement.ProjectRequirementModuleReqVO;
|
||||
@@ -71,6 +73,11 @@ public interface ProjectRequirementService {
|
||||
*/
|
||||
List<ProjectRequirementStatusTransitionRespVO> getAllowedTransitions(Long requirementId, Long projectId);
|
||||
|
||||
/**
|
||||
* 批量获取需求可执行动作列表
|
||||
*/
|
||||
List<ProjectRequirementAllowedTransitionBatchRespVO> getAllowedTransitionsBatch(ProjectRequirementBatchReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 获取需求生命周期信息
|
||||
*/
|
||||
|
||||
@@ -7,6 +7,8 @@ import com.njcn.rdms.framework.common.util.object.BeanUtils;
|
||||
import com.njcn.rdms.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import com.njcn.rdms.framework.security.core.util.SecurityFrameworkUtils;
|
||||
import com.njcn.rdms.module.project.constant.ProjectObjectConstants;
|
||||
import com.njcn.rdms.module.project.controller.admin.project.vo.requirement.ProjectRequirementAllowedTransitionBatchRespVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.project.vo.requirement.ProjectRequirementBatchReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.project.vo.requirement.ProjectRequirementCloseReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.project.vo.requirement.ProjectRequirementLifecycleRespVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.project.vo.requirement.ProjectRequirementModuleReqVO;
|
||||
@@ -44,15 +46,7 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -152,10 +146,10 @@ public class ProjectRequirementServiceImpl implements ProjectRequirementService
|
||||
requirement.setStatusCode(initialStatus);
|
||||
requirement.setProposerId(createReqVO.getProposerId());
|
||||
requirement.setProposerNickname(normalizeNullableText(createReqVO.getProposerNickname()));
|
||||
requirement.setWorkHours(createReqVO.getWorkHours());
|
||||
requirement.setExpectedTime(createReqVO.getExpectedTime());
|
||||
requirement.setCurrentHandlerUserId(createReqVO.getCurrentHandlerUserId());
|
||||
requirement.setCurrentHandlerUserNickname(normalizeNullableText(createReqVO.getCurrentHandlerUserNickname()));
|
||||
requirement.setSort(createReqVO.getSort() != null ? createReqVO.getSort() : 0);
|
||||
requirement.setSort(createReqVO.getSort());
|
||||
requirement.setAttachments(createReqVO.getAttachments());
|
||||
requirementMapper.insert(requirement);
|
||||
|
||||
@@ -188,10 +182,10 @@ public class ProjectRequirementServiceImpl implements ProjectRequirementService
|
||||
requirement.setPriority(updateReqVO.getPriority());
|
||||
requirement.setProposerId(updateReqVO.getProposerId());
|
||||
requirement.setProposerNickname(normalizeNullableText(updateReqVO.getProposerNickname()));
|
||||
requirement.setWorkHours(updateReqVO.getWorkHours());
|
||||
requirement.setExpectedTime(updateReqVO.getExpectedTime());
|
||||
requirement.setCurrentHandlerUserId(updateReqVO.getCurrentHandlerUserId());
|
||||
requirement.setCurrentHandlerUserNickname(normalizeNullableText(updateReqVO.getCurrentHandlerUserNickname()));
|
||||
requirement.setSort(updateReqVO.getSort() != null ? updateReqVO.getSort() : 0);
|
||||
requirement.setSort(updateReqVO.getSort());
|
||||
requirement.setAttachments(updateReqVO.getAttachments());
|
||||
requirementMapper.updateById(requirement);
|
||||
|
||||
@@ -259,8 +253,7 @@ public class ProjectRequirementServiceImpl implements ProjectRequirementService
|
||||
|
||||
List<ProjectRequirementDO> rootRequirements = requirementMapper.selectBatchIds(rootIds);
|
||||
rootRequirements.sort((a, b) -> {
|
||||
int sortCompare = Integer.compare(a.getSort() != null ? a.getSort() : 0,
|
||||
b.getSort() != null ? b.getSort() : 0);
|
||||
int sortCompare = Comparator.nullsLast(Integer::compareTo).compare(a.getSort(), b.getSort());
|
||||
if (sortCompare != 0) {
|
||||
return sortCompare;
|
||||
}
|
||||
@@ -303,6 +296,10 @@ public class ProjectRequirementServiceImpl implements ProjectRequirementService
|
||||
if (ACTION_ACCEPT.equals(actionCode) || ACTION_CLOSE.equals(actionCode)) {
|
||||
validateAllChildrenAllowCloseOrAccept(reqVO.getId());
|
||||
}
|
||||
// 产品需求流转生成的项目需求不允许在项目侧取消,避免与产品侧主状态冲突。
|
||||
if (ACTION_CANCEL.equals(actionCode) && isFromProductRequirement(requirement)) {
|
||||
throw exception(ErrorCodeConstants.PROJECT_REQUIREMENT_SYNCED_FROM_PRODUCT_NOT_ALLOW_CANCEL);
|
||||
}
|
||||
if (ACTION_CANCEL.equals(actionCode) && hasChildren(requirement.getId())) {
|
||||
validateParentCancelAllowed(reqVO.getId());
|
||||
}
|
||||
@@ -379,10 +376,10 @@ public class ProjectRequirementServiceImpl implements ProjectRequirementService
|
||||
childRequirement.setStatusCode(initialStatus);
|
||||
childRequirement.setProposerId(reqVO.getProposerId());
|
||||
childRequirement.setProposerNickname(normalizeNullableText(reqVO.getProposerNickname()));
|
||||
childRequirement.setWorkHours(reqVO.getWorkHours());
|
||||
childRequirement.setExpectedTime(reqVO.getExpectedTime());
|
||||
childRequirement.setCurrentHandlerUserId(reqVO.getCurrentHandlerUserId());
|
||||
childRequirement.setCurrentHandlerUserNickname(normalizeNullableText(reqVO.getCurrentHandlerUserNickname()));
|
||||
childRequirement.setSort(reqVO.getSort() != null ? reqVO.getSort() : 0);
|
||||
childRequirement.setSort(reqVO.getSort());
|
||||
childRequirement.setAttachments(reqVO.getAttachments());
|
||||
requirementMapper.insert(childRequirement);
|
||||
|
||||
@@ -451,6 +448,23 @@ public class ProjectRequirementServiceImpl implements ProjectRequirementService
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@CheckObjectPermission(objectType = PROJECT_OBJECT_TYPE, objectId = "#reqVO.projectId",
|
||||
permission = PROJECT_QUERY_PERMISSION)
|
||||
public List<ProjectRequirementAllowedTransitionBatchRespVO> getAllowedTransitionsBatch(ProjectRequirementBatchReqVO reqVO) {
|
||||
List<ProjectRequirementDO> requirements = getBatchRequirements(reqVO.getRequirementIds(), reqVO.getProjectId());
|
||||
Map<String, List<ObjectStatusTransitionDO>> transitionsByStatus = getTransitionsByStatus(requirements);
|
||||
Map<String, ObjectStatusModelDO> statusModelMap = getStatusModelMap();
|
||||
|
||||
return requirements.stream().map(requirement -> {
|
||||
ProjectRequirementAllowedTransitionBatchRespVO respVO = new ProjectRequirementAllowedTransitionBatchRespVO();
|
||||
respVO.setRequirementId(requirement.getId());
|
||||
respVO.setTransitions(buildAllowedTransitions(requirement,
|
||||
transitionsByStatus.getOrDefault(requirement.getStatusCode(), Collections.emptyList()), statusModelMap));
|
||||
return respVO;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@CheckObjectPermission(objectType = PROJECT_OBJECT_TYPE, objectId = "#projectId",
|
||||
permission = PROJECT_QUERY_PERMISSION)
|
||||
@@ -654,6 +668,60 @@ public class ProjectRequirementServiceImpl implements ProjectRequirementService
|
||||
(left, right) -> left, LinkedHashMap::new));
|
||||
}
|
||||
|
||||
private List<ProjectRequirementDO> getBatchRequirements(List<Long> requirementIds, Long projectId) {
|
||||
if (requirementIds == null || requirementIds.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
if (requirementIds.stream().anyMatch(Objects::isNull)) {
|
||||
throw invalidParamException("需求编号不能为空");
|
||||
}
|
||||
List<Long> distinctIds = requirementIds.stream().distinct().collect(Collectors.toList());
|
||||
Map<Long, ProjectRequirementDO> requirementMap = requirementMapper.selectByIds(distinctIds).stream()
|
||||
.collect(Collectors.toMap(ProjectRequirementDO::getId, Function.identity()));
|
||||
if (requirementMap.size() != distinctIds.size()) {
|
||||
throw exception(ErrorCodeConstants.PROJECT_REQUIREMENT_NOT_EXISTS);
|
||||
}
|
||||
List<ProjectRequirementDO> requirements = distinctIds.stream()
|
||||
.map(requirementMap::get)
|
||||
.collect(Collectors.toList());
|
||||
for (ProjectRequirementDO requirement : requirements) {
|
||||
validateRequirementBelongsToProject(requirement, projectId);
|
||||
}
|
||||
return requirements;
|
||||
}
|
||||
|
||||
private Map<String, List<ObjectStatusTransitionDO>> getTransitionsByStatus(List<ProjectRequirementDO> requirements) {
|
||||
List<String> statusCodes = requirements.stream()
|
||||
.map(ProjectRequirementDO::getStatusCode)
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
if (statusCodes.isEmpty()) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
return statusTransitionMapper.selectListByObjectTypeAndFromStatuses(REQUIREMENT_OBJECT_TYPE, statusCodes)
|
||||
.stream()
|
||||
.collect(Collectors.groupingBy(ObjectStatusTransitionDO::getFromStatusCode));
|
||||
}
|
||||
|
||||
private List<ProjectRequirementStatusTransitionRespVO> buildAllowedTransitions(
|
||||
ProjectRequirementDO requirement,
|
||||
List<ObjectStatusTransitionDO> transitions,
|
||||
Map<String, ObjectStatusModelDO> statusModelMap) {
|
||||
return transitions.stream()
|
||||
.filter(transition -> shouldExposeTransition(requirement, transition))
|
||||
.map(transition -> {
|
||||
ProjectRequirementStatusTransitionRespVO vo = new ProjectRequirementStatusTransitionRespVO();
|
||||
vo.setActionCode(transition.getActionCode());
|
||||
vo.setActionName(transition.getActionName());
|
||||
vo.setToStatusCode(transition.getToStatusCode());
|
||||
ObjectStatusModelDO statusModel = statusModelMap.get(transition.getToStatusCode());
|
||||
vo.setToStatusName(statusModel != null ? statusModel.getStatusName() : transition.getToStatusCode());
|
||||
vo.setNeedReason(transition.getNeedReason());
|
||||
return vo;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断指定模块是否为“全部需求”根模块。
|
||||
*/
|
||||
@@ -742,12 +810,23 @@ public class ProjectRequirementServiceImpl implements ProjectRequirementService
|
||||
if (!ACTION_CANCEL.equals(transition.getActionCode())) {
|
||||
return true;
|
||||
}
|
||||
if (isFromProductRequirement(requirement)) {
|
||||
return false;
|
||||
}
|
||||
if (!hasChildren(requirement.getId())) {
|
||||
return true;
|
||||
}
|
||||
return isParentCancelAllowed(requirement.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前项目需求是否由产品需求流转生成。
|
||||
*/
|
||||
private boolean isFromProductRequirement(ProjectRequirementDO requirement) {
|
||||
return Objects.equals(requirement.getSourceType(), SOURCE_TYPE_PRODUCT_REQUIREMENT)
|
||||
&& requirement.getProductRequirementId() != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 父需求存在子需求时,只有全部子需求都已取消或已拒绝,才允许展示取消动作。
|
||||
*/
|
||||
@@ -1119,7 +1198,7 @@ public class ProjectRequirementServiceImpl implements ProjectRequirementService
|
||||
target.setLastStatusReason(source.getLastStatusReason());
|
||||
target.setProposerId(source.getProposerId());
|
||||
target.setProposerNickname(source.getProposerNickname());
|
||||
target.setWorkHours(source.getWorkHours());
|
||||
target.setExpectedTime(source.getExpectedTime());
|
||||
target.setCurrentHandlerUserId(source.getCurrentHandlerUserId());
|
||||
target.setCurrentHandlerUserNickname(source.getCurrentHandlerUserNickname());
|
||||
target.setSort(source.getSort());
|
||||
@@ -1162,8 +1241,8 @@ public class ProjectRequirementServiceImpl implements ProjectRequirementService
|
||||
valueOf(after, ProjectRequirementDO::getProposerId));
|
||||
appendFieldChange(fieldChanges, "proposerNickname", valueOf(before, ProjectRequirementDO::getProposerNickname),
|
||||
valueOf(after, ProjectRequirementDO::getProposerNickname));
|
||||
appendFieldChange(fieldChanges, "workHours", valueOf(before, ProjectRequirementDO::getWorkHours),
|
||||
valueOf(after, ProjectRequirementDO::getWorkHours));
|
||||
appendFieldChange(fieldChanges, "expectedTime", valueOf(before, ProjectRequirementDO::getExpectedTime),
|
||||
valueOf(after, ProjectRequirementDO::getExpectedTime));
|
||||
appendFieldChange(fieldChanges, "currentHandlerUserId",
|
||||
valueOf(before, ProjectRequirementDO::getCurrentHandlerUserId),
|
||||
valueOf(after, ProjectRequirementDO::getCurrentHandlerUserId));
|
||||
@@ -1229,7 +1308,7 @@ public class ProjectRequirementServiceImpl implements ProjectRequirementService
|
||||
target.setLastStatusReason(source.getLastStatusReason());
|
||||
target.setProposerId(source.getProposerId());
|
||||
target.setProposerNickname(source.getProposerNickname());
|
||||
target.setWorkHours(source.getWorkHours());
|
||||
target.setExpectedTime(source.getExpectedTime());
|
||||
target.setCurrentHandlerUserId(source.getCurrentHandlerUserId());
|
||||
target.setCurrentHandlerUserNickname(source.getCurrentHandlerUserNickname());
|
||||
target.setImplementProjectId(source.getImplementProjectId());
|
||||
@@ -1268,8 +1347,8 @@ public class ProjectRequirementServiceImpl implements ProjectRequirementService
|
||||
valueOf(after, ProductRequirementDO::getProposerId));
|
||||
appendFieldChange(fieldChanges, "proposerNickname", valueOf(before, ProductRequirementDO::getProposerNickname),
|
||||
valueOf(after, ProductRequirementDO::getProposerNickname));
|
||||
appendFieldChange(fieldChanges, "workHours", valueOf(before, ProductRequirementDO::getWorkHours),
|
||||
valueOf(after, ProductRequirementDO::getWorkHours));
|
||||
appendFieldChange(fieldChanges, "expectedTime", valueOf(before, ProductRequirementDO::getExpectedTime),
|
||||
valueOf(after, ProductRequirementDO::getExpectedTime));
|
||||
appendFieldChange(fieldChanges, "currentHandlerUserId", valueOf(before, ProductRequirementDO::getCurrentHandlerUserId),
|
||||
valueOf(after, ProductRequirementDO::getCurrentHandlerUserId));
|
||||
appendFieldChange(fieldChanges, "currentHandlerUserNickname",
|
||||
@@ -1313,4 +1392,4 @@ public class ProjectRequirementServiceImpl implements ProjectRequirementService
|
||||
return StringUtils.hasText(value) ? value : "";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -221,6 +221,9 @@ class ProjectServiceImpl implements ProjectService {
|
||||
// 8) 项目创建审计
|
||||
writeBizAuditLog(project, ObjectActivityConstants.PROJECT_ACTION_CREATE, null, initialStatus,
|
||||
buildProjectFieldChanges(null, project), null);
|
||||
|
||||
// 9) 初始化项目需求的根模块
|
||||
initDefaultRequirementModule(project);
|
||||
return project.getId();
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,9 @@ public class AdminUserRespDTO implements VO {
|
||||
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小王")
|
||||
private String nickname;
|
||||
|
||||
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description = "所属公司", example = "灿能")
|
||||
private String company;
|
||||
|
||||
|
||||
@@ -43,6 +43,10 @@ public class DictDataRespVO {
|
||||
@Schema(description = "颜色类型,default、primary、success、info、warning、danger", example = "default")
|
||||
private String colorType;
|
||||
|
||||
@Schema(description = "标识", example = "system")
|
||||
@ExcelProperty("标识")
|
||||
private String sign;
|
||||
|
||||
@Schema(description = "css 样式", example = "btn-visible")
|
||||
private String cssClass;
|
||||
|
||||
|
||||
@@ -42,6 +42,10 @@ public class DictDataSaveReqVO {
|
||||
@Schema(description = "颜色类型,default、primary、success、info、warning、danger", example = "default")
|
||||
private String colorType;
|
||||
|
||||
@Schema(description = "标识", example = "system")
|
||||
@Size(max = 255, message = "标识长度不能超过255个字符")
|
||||
private String sign;
|
||||
|
||||
@Schema(description = "css 样式", example = "btn-visible")
|
||||
private String cssClass;
|
||||
|
||||
|
||||
@@ -22,6 +22,9 @@ public class DictDataSimpleRespVO {
|
||||
@Schema(description = "颜色类型,default、primary、success、info、warning、danger", example = "default")
|
||||
private String colorType;
|
||||
|
||||
@Schema(description = "标识", example = "system")
|
||||
private String sign;
|
||||
|
||||
@Schema(description = "css 样式", example = "btn-visible")
|
||||
private String cssClass;
|
||||
|
||||
|
||||
@@ -184,9 +184,9 @@ public class UserController {
|
||||
public void importTemplate(HttpServletResponse response) throws IOException {
|
||||
// 手动创建导出 demo
|
||||
List<UserImportExcelVO> list = Arrays.asList(
|
||||
UserImportExcelVO.builder().username("yunai").deptId(1L).positionId(1L).email("yunai@iocoder.cn").mobile("15601691300")
|
||||
UserImportExcelVO.builder().username("yunai").deptId(1L).positionId(1L).sort(10).email("yunai@iocoder.cn").mobile("15601691300")
|
||||
.nickname("灿能").status(CommonStatusEnum.ENABLE.getStatus()).sex(SexEnum.MALE.getSex()).build(),
|
||||
UserImportExcelVO.builder().username("yuanma").deptId(2L).positionId(2L).email("yuanma@iocoder.cn").mobile("15601701300")
|
||||
UserImportExcelVO.builder().username("yuanma").deptId(2L).positionId(2L).sort(20).email("yuanma@iocoder.cn").mobile("15601701300")
|
||||
.nickname("源码").status(CommonStatusEnum.DISABLE.getStatus()).sex(SexEnum.FEMALE.getSex()).build()
|
||||
);
|
||||
// 输出
|
||||
|
||||
@@ -33,6 +33,9 @@ public class UserImportExcelVO {
|
||||
@ExcelProperty("主岗位编号")
|
||||
private Long positionId;
|
||||
|
||||
@ExcelProperty("显示顺序")
|
||||
private Integer sort;
|
||||
|
||||
@ExcelProperty("用户邮箱")
|
||||
private String email;
|
||||
|
||||
|
||||
@@ -48,6 +48,10 @@ public class UserRespVO {
|
||||
@ExcelProperty("主岗位")
|
||||
private String positionName;
|
||||
|
||||
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||
@ExcelProperty("显示顺序")
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description = "用户邮箱", example = "rdms@iocoder.cn")
|
||||
@ExcelProperty("用户邮箱")
|
||||
private String email;
|
||||
|
||||
@@ -58,6 +58,11 @@ public class UserSaveReqVO {
|
||||
@DiffLogField(name = "主岗位", function = PostParseFunction.NAME)
|
||||
private Long positionId;
|
||||
|
||||
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||
@NotNull(message = "显示顺序不能为空")
|
||||
@DiffLogField(name = "显示顺序")
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description = "离职时间", example = "2026-03-19 00:00:00")
|
||||
@DiffLogField(name = "离职时间")
|
||||
private LocalDateTime resignedAt;
|
||||
|
||||
@@ -17,8 +17,12 @@ public class UserSimpleRespVO {
|
||||
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "灿能")
|
||||
private String nickname;
|
||||
|
||||
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description = "部门ID", example = "我是一个用户")
|
||||
private Long deptId;
|
||||
|
||||
@Schema(description = "部门名称", example = "IT 部")
|
||||
private String deptName;
|
||||
|
||||
|
||||
@@ -23,4 +23,7 @@ public class AppDictDataRespVO {
|
||||
@Schema(description = "字典类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "sys_common_sex")
|
||||
private String dictType;
|
||||
|
||||
@Schema(description = "标识", example = "system")
|
||||
private String sign;
|
||||
|
||||
}
|
||||
|
||||
@@ -52,6 +52,11 @@ public class DictDataDO extends BaseDO {
|
||||
* 对应到 element-ui 为 default、primary、success、info、warning、danger
|
||||
*/
|
||||
private String colorType;
|
||||
/**
|
||||
* 标识
|
||||
*/
|
||||
@TableField(updateStrategy = FieldStrategy.ALWAYS)
|
||||
private String sign;
|
||||
/**
|
||||
* css 样式
|
||||
*/
|
||||
|
||||
@@ -52,6 +52,11 @@ public class AdminUserDO extends BaseDO {
|
||||
*/
|
||||
private String nickname;
|
||||
|
||||
/**
|
||||
* 显示排序
|
||||
*/
|
||||
private Integer sort;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
|
||||
@@ -35,23 +35,36 @@ public interface AdminUserMapper extends BaseMapperX<AdminUserDO> {
|
||||
.betweenIfPresent(AdminUserDO::getCreateTime, reqVO.getCreateTime())
|
||||
.inIfPresent(AdminUserDO::getDeptId, deptIds)
|
||||
.inIfPresent(AdminUserDO::getId, userIds)
|
||||
.orderByAsc(AdminUserDO::getSort)
|
||||
.orderByDesc(AdminUserDO::getId));
|
||||
}
|
||||
|
||||
default List<AdminUserDO> selectListByNickname(String nickname) {
|
||||
return selectList(new LambdaQueryWrapperX<AdminUserDO>().like(AdminUserDO::getNickname, nickname));
|
||||
return selectList(new LambdaQueryWrapperX<AdminUserDO>()
|
||||
.like(AdminUserDO::getNickname, nickname)
|
||||
.orderByAsc(AdminUserDO::getSort)
|
||||
.orderByDesc(AdminUserDO::getId));
|
||||
}
|
||||
|
||||
default List<AdminUserDO> selectListByStatus(Integer status) {
|
||||
return selectList(AdminUserDO::getStatus, status);
|
||||
return selectList(new LambdaQueryWrapperX<AdminUserDO>()
|
||||
.eq(AdminUserDO::getStatus, status)
|
||||
.orderByAsc(AdminUserDO::getSort)
|
||||
.orderByDesc(AdminUserDO::getId));
|
||||
}
|
||||
|
||||
default List<AdminUserDO> selectListByDeptIds(Collection<Long> deptIds) {
|
||||
return selectList(AdminUserDO::getDeptId, deptIds);
|
||||
return selectList(new LambdaQueryWrapperX<AdminUserDO>()
|
||||
.in(AdminUserDO::getDeptId, deptIds)
|
||||
.orderByAsc(AdminUserDO::getSort)
|
||||
.orderByDesc(AdminUserDO::getId));
|
||||
}
|
||||
|
||||
default List<AdminUserDO> selectListByPositionIds(Collection<Long> positionIds) {
|
||||
return selectList(AdminUserDO::getPositionId, positionIds);
|
||||
return selectList(new LambdaQueryWrapperX<AdminUserDO>()
|
||||
.in(AdminUserDO::getPositionId, positionIds)
|
||||
.orderByAsc(AdminUserDO::getSort)
|
||||
.orderByDesc(AdminUserDO::getId));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
|
||||
static final String USER_INIT_PASSWORD_KEY = "system.user.init-password";
|
||||
static final String USER_REGISTER_ENABLED_KEY = "system.user.register-enabled";
|
||||
private static final Integer DEFAULT_REGISTER_USER_SORT = 999;
|
||||
|
||||
@Resource
|
||||
private AdminUserMapper userMapper;
|
||||
@@ -107,6 +108,7 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
// 2. 插入用户
|
||||
AdminUserDO user = BeanUtils.toBean(registerReqVO, AdminUserDO.class);
|
||||
user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
|
||||
user.setSort(DEFAULT_REGISTER_USER_SORT);
|
||||
user.setPassword(encodePassword(registerReqVO.getPassword())); // 加密密码
|
||||
userMapper.insert(user);
|
||||
return user.getId();
|
||||
|
||||
Reference in New Issue
Block a user