From 61ee9d8ab094074de418b96a8f67f9b7c255859b Mon Sep 17 00:00:00 2001 From: guoyuqi Date: Tue, 7 Nov 2023 18:17:55 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E5=8A=9F=E8=83=BD=E7=94=A8=E4=BE=8B):=20?= =?UTF-8?q?=E5=9B=9E=E6=94=B6=E7=AB=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FunctionalCaseTrashController.java | 41 +++ .../dto/FunctionalCaseCommentDTO.java | 3 + .../mapper/ExtFunctionalCaseMapper.java | 3 + .../mapper/ExtFunctionalCaseMapper.xml | 13 + .../FunctionalCaseModuleCreateRequest.java | 14 +- .../FunctionalCaseModuleUpdateRequest.java | 12 +- .../service/DeleteFunctionalCaseService.java | 2 +- .../service/FunctionalCaseCommentService.java | 50 ++-- .../service/FunctionalCaseLogService.java | 47 ++++ .../service/FunctionalCaseNoticeService.java | 32 ++- .../service/FunctionalCaseTrashService.java | 93 +++++++ .../FunctionalCaseCommentControllerTests.java | 2 + .../FunctionalCaseTrashControllerTests.java | 91 +++++++ .../test/resources/dml/init_case_trash.sql | 29 +++ .../system/log/aspect/OperationLogAspect.java | 2 +- .../notice/sender/AbstractNoticeSender.java | 16 +- .../AfterReturningNoticeSendServiceTests.java | 233 +++++++++++++++++- .../src/test/resources/dml/init_aspect.sql | 13 + 18 files changed, 633 insertions(+), 63 deletions(-) create mode 100644 backend/services/case-management/src/main/java/io/metersphere/functional/controller/FunctionalCaseTrashController.java create mode 100644 backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseTrashService.java create mode 100644 backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalCaseTrashControllerTests.java create mode 100644 backend/services/case-management/src/test/resources/dml/init_case_trash.sql diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/controller/FunctionalCaseTrashController.java b/backend/services/case-management/src/main/java/io/metersphere/functional/controller/FunctionalCaseTrashController.java new file mode 100644 index 0000000000..32caf27ce8 --- /dev/null +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/controller/FunctionalCaseTrashController.java @@ -0,0 +1,41 @@ +package io.metersphere.functional.controller; + +import io.metersphere.functional.service.FunctionalCaseLogService; +import io.metersphere.functional.service.FunctionalCaseTrashService; +import io.metersphere.sdk.constants.PermissionConstants; +import io.metersphere.system.log.annotation.Log; +import io.metersphere.system.log.constants.OperationLogType; +import io.metersphere.system.utils.SessionUtils; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Tag(name = "用例管理-功能用例-回收站") +@RestController +@RequestMapping("/functional/case/trash") +public class FunctionalCaseTrashController { + @Resource + private FunctionalCaseTrashService functionalCaseTrashService; + + @GetMapping("/recover/{id}") + @Operation(summary = "用例管理-功能用例-回收站-恢复用例") + @RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ_DELETE) + @Log(type = OperationLogType.RECOVER, expression = "#msClass.recoverLog(#id)", msClass = FunctionalCaseLogService.class) + public void recoverCase(@PathVariable String id) { + functionalCaseTrashService.recoverCase(id, SessionUtils.getUserId()); + } + + @GetMapping("/delete/{id}") + @Operation(summary = "用例管理-功能用例-回收站-彻底删除用例") + @RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ_DELETE) + @Log(type = OperationLogType.DELETE, expression = "#msClass.deleteTrashCaseLog(#id)", msClass = FunctionalCaseLogService.class) + public void deleteCase(@PathVariable String id) { + functionalCaseTrashService.deleteCase(id); + } + +} diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/dto/FunctionalCaseCommentDTO.java b/backend/services/case-management/src/main/java/io/metersphere/functional/dto/FunctionalCaseCommentDTO.java index bd4297ebd2..d7e867c1fd 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/dto/FunctionalCaseCommentDTO.java +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/dto/FunctionalCaseCommentDTO.java @@ -18,6 +18,9 @@ public class FunctionalCaseCommentDTO extends FunctionalCaseComment { @Schema(description = "被回复的人头像") private String replyUserLogo; + @Schema(description = "评论的人头像") + private String userLogo; + @Schema(description = "该条评论下的所有回复数据") private List replies; diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseMapper.java b/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseMapper.java index 1742298a9f..812ef8c896 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseMapper.java +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseMapper.java @@ -28,6 +28,9 @@ public interface ExtFunctionalCaseMapper { List list(@Param("request") FunctionalCasePageRequest request, @Param("deleted") boolean deleted); + void recoverCase(@Param("ids") List ids, @Param("userId") String userId, @Param("time") long time); + + List getIds(@Param("request") TableBatchProcessDTO request, @Param("projectId") String projectId, @Param("deleted") boolean deleted); void batchDelete(@Param("ids") List ids, @Param("userId") String userId); diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseMapper.xml b/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseMapper.xml index 2ff47fba55..0cac648845 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseMapper.xml +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseMapper.xml @@ -87,6 +87,19 @@ + + UPDATE functional_case + SET deleted = false, + update_user = #{userId}, + update_time = #{time}, + delete_user = null, + delete_time = null + WHERE id IN + + #{id} + + + and functional_case.project_id = #{request.projectId} diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/request/FunctionalCaseModuleCreateRequest.java b/backend/services/case-management/src/main/java/io/metersphere/functional/request/FunctionalCaseModuleCreateRequest.java index 07496af090..09fb3b120e 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/request/FunctionalCaseModuleCreateRequest.java +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/request/FunctionalCaseModuleCreateRequest.java @@ -6,12 +6,22 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotEmpty; import lombok.Data; +import java.io.Serial; +import java.io.Serializable; + +/** + * @author guoyuqi + */ @Data -public class FunctionalCaseModuleCreateRequest { +public class FunctionalCaseModuleCreateRequest implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + @Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED) @NotBlank(message = "{project.id.not_blank}") private String projectId; - + @Schema(description = "模块名称", requiredMode = Schema.RequiredMode.REQUIRED) @NotEmpty(message = "{file_module.name.not_blank}") private String name; diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/request/FunctionalCaseModuleUpdateRequest.java b/backend/services/case-management/src/main/java/io/metersphere/functional/request/FunctionalCaseModuleUpdateRequest.java index 3b189cdf1a..8908d13861 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/request/FunctionalCaseModuleUpdateRequest.java +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/request/FunctionalCaseModuleUpdateRequest.java @@ -5,8 +5,18 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotEmpty; import lombok.Data; +import java.io.Serial; +import java.io.Serializable; + +/** + * @author guoyuqi + */ @Data -public class FunctionalCaseModuleUpdateRequest { +public class FunctionalCaseModuleUpdateRequest implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + @Schema(description = "模块ID", requiredMode = Schema.RequiredMode.REQUIRED) @NotBlank(message = "{file_module.id.not_blank}") private String id; diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/service/DeleteFunctionalCaseService.java b/backend/services/case-management/src/main/java/io/metersphere/functional/service/DeleteFunctionalCaseService.java index 0ba300e418..670972e6b4 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/service/DeleteFunctionalCaseService.java +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/service/DeleteFunctionalCaseService.java @@ -30,7 +30,7 @@ public class DeleteFunctionalCaseService { public void deleteFunctionalCaseResource(List ids, String projectId) { - //TODO 删除各种关联关系? 1.测试用例(接口/场景/ui/性能)? 2.关联缺陷(是否需要同步?) 3.关联需求(是否需要同步?) 4.依赖关系? 5.关联评审? 6.操作记录? 7.关联测试计划? 8.评论? 9.附件? 10.自定义字段? 11.用例基本信息(主表、附属表)? 12...? + //TODO 删除各种关联关系? 1.测试用例(接口/场景/ui/性能)? 2.关联缺陷(是否需要同步?) 3.关联需求(是否需要同步?) 4.依赖关系? 5.关联评审? 6.关联测试计划? 7.操作记录? 8.评论? 9.附件? 10.自定义字段? 11.用例基本信息(主表、附属表)? 12...? //1.刪除用例与其他用例关联关系 FunctionalCaseTestExample caseTestExample = new FunctionalCaseTestExample(); caseTestExample.createCriteria().andCaseIdIn(ids); diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseCommentService.java b/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseCommentService.java index 499e7854e8..5b7f20a9f3 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseCommentService.java +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseCommentService.java @@ -26,9 +26,6 @@ import org.apache.commons.beanutils.BeanMap; import org.apache.commons.lang3.StringUtils; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; -import org.apache.commons.collections.CollectionUtils; - - import java.util.*; import java.util.stream.Collectors; @@ -69,7 +66,7 @@ public class FunctionalCaseCommentService { if (StringUtils.equals(functionalCaseCommentRequest.getEvent(), NoticeConstants.Event.REPLY)) { return saveCommentWidthReply(functionalCaseCommentRequest, functionalCaseComment, userId); } else { - return saveCommentWidthOther(functionalCaseCommentRequest, functionalCaseComment, userId); + return saveCommentOrAt(functionalCaseCommentRequest, functionalCaseComment, userId); } } @@ -107,13 +104,15 @@ public class FunctionalCaseCommentService { * @param functionalCaseComment 被组装的半份数据 * @return FunctionalCaseComment */ - public FunctionalCaseComment saveCommentWidthOther(FunctionalCaseCommentRequest functionalCaseCommentRequest, FunctionalCaseComment functionalCaseComment, String userId) { + public FunctionalCaseComment saveCommentOrAt(FunctionalCaseCommentRequest functionalCaseCommentRequest, FunctionalCaseComment functionalCaseComment, String userId) { if (StringUtils.isNotBlank(functionalCaseCommentRequest.getNotifier())) { functionalCaseComment.setNotifier(functionalCaseCommentRequest.getNotifier()); } functionalCaseCommentMapper.insert(functionalCaseComment); FunctionalCaseDTO functionalCaseDTO = functionalCaseNoticeService.getFunctionalCaseDTO(functionalCaseCommentRequest); + //发送@ 通知人 sendNotice(functionalCaseCommentRequest, userId, functionalCaseDTO); + //发送系统设置的评论通知 if (StringUtils.isBlank(functionalCaseCommentRequest.getParentId()) && !StringUtils.equals(functionalCaseCommentRequest.getEvent(),NoticeConstants.Event.COMMENT)) { functionalCaseCommentRequest.setEvent(NoticeConstants.Event.COMMENT); sendNotice(functionalCaseCommentRequest, userId, functionalCaseDTO); @@ -128,7 +127,7 @@ public class FunctionalCaseCommentService { * @return FunctionalCaseComment */ public FunctionalCaseComment saveCommentWidthReply(FunctionalCaseCommentRequest functionalCaseCommentRequest, FunctionalCaseComment functionalCaseComment, String userId) { - setOther(functionalCaseCommentRequest, functionalCaseComment); + setReplyAndNotifier(functionalCaseCommentRequest, functionalCaseComment); functionalCaseCommentMapper.insert(functionalCaseComment); FunctionalCaseDTO functionalCaseDTOReply = functionalCaseNoticeService.getFunctionalCaseDTO(functionalCaseCommentRequest); sendNotice(functionalCaseCommentRequest, userId, functionalCaseDTOReply); @@ -139,12 +138,12 @@ public class FunctionalCaseCommentService { return functionalCaseComment; } - private void setOther(FunctionalCaseCommentRequest functionalCaseCommentRequest, FunctionalCaseComment functionalCaseComment) { + private void setReplyAndNotifier(FunctionalCaseCommentRequest functionalCaseCommentRequest, FunctionalCaseComment functionalCaseComment) { checkParentId(functionalCaseCommentRequest, functionalCaseComment); if (StringUtils.isBlank(functionalCaseCommentRequest.getReplyUser())) { throw new MSException(Translator.get("case_comment.reply_user_is_null")); } - functionalCaseCommentRequest.setReplyUser(functionalCaseCommentRequest.getReplyUser()); + functionalCaseComment.setReplyUser(functionalCaseCommentRequest.getReplyUser()); if (StringUtils.isNotBlank(functionalCaseCommentRequest.getNotifier())) { functionalCaseComment.setNotifier(functionalCaseCommentRequest.getNotifier()); } else { @@ -236,37 +235,24 @@ public class FunctionalCaseCommentService { */ private List buildData(List functionalCaseComments, Map userMap) { Listlist = new ArrayList<>(); - List rootList = functionalCaseComments.stream().filter(t -> StringUtils.isBlank(t.getParentId())).toList(); - List replyList = functionalCaseComments.stream().filter(t -> StringUtils.isNotBlank(t.getParentId())).toList(); - Map> commentMap = replyList.stream().collect(Collectors.groupingBy(FunctionalCaseComment::getParentId)); - for (FunctionalCaseComment functionalCaseComment : rootList) { + for (FunctionalCaseComment functionalCaseComment : functionalCaseComments) { FunctionalCaseCommentDTO functionalCaseCommentDTO = new FunctionalCaseCommentDTO(); BeanUtils.copyBean(functionalCaseCommentDTO,functionalCaseComment); functionalCaseCommentDTO.setUserName(userMap.get(functionalCaseComment.getCreateUser()).getName()); - List replyComments = commentMap.get(functionalCaseComment.getId()); - if (CollectionUtils.isNotEmpty(replyComments)) { - List replies = getReplies(userMap, functionalCaseComment, replyComments); - functionalCaseCommentDTO.setReplies(replies); + if (StringUtils.isNotBlank(functionalCaseComment.getReplyUser())) { + functionalCaseCommentDTO.setReplyUserName(userMap.get(functionalCaseComment.getReplyUser()).getName()); } list.add(functionalCaseCommentDTO); } - return list; - } - private List getReplies(Map userMap, FunctionalCaseComment functionalCaseComment, List replyComments) { - List replies = new ArrayList<>(); - for (FunctionalCaseComment replyComment : replyComments) { - FunctionalCaseCommentDTO functionalCaseCommentDTOReply = new FunctionalCaseCommentDTO(); - BeanUtils.copyBean(functionalCaseCommentDTOReply,replyComment); - functionalCaseCommentDTOReply.setUserName(userMap.get(replyComment.getCreateUser()).getName()); - if (StringUtils.isBlank(replyComment.getReplyUser())) { - functionalCaseCommentDTOReply.setReplyUserName(userMap.get(functionalCaseComment.getCreateUser()).getName()); - } else { - functionalCaseCommentDTOReply.setReplyUserName(userMap.get(replyComment.getReplyUser()).getName()); - } - replies.add(functionalCaseCommentDTOReply); + List rootList = list.stream().filter(t -> StringUtils.isBlank(t.getParentId())).sorted(Comparator.comparing(FunctionalCaseComment::getCreateTime).reversed()).toList(); + List replyList = list.stream().filter(t -> StringUtils.isNotBlank(t.getParentId())).sorted(Comparator.comparing(FunctionalCaseComment::getCreateTime).reversed()).toList(); + Map> commentMap = replyList.stream().collect(Collectors.groupingBy(FunctionalCaseComment::getParentId)); + for (FunctionalCaseCommentDTO functionalCaseComment : rootList) { + List replyComments = commentMap.get(functionalCaseComment.getId()); + functionalCaseComment.setReplies(replyComments); } - return replies.stream().sorted(Comparator.comparing(FunctionalCaseComment::getCreateTime).reversed()).toList(); + return rootList; } /** @@ -322,7 +308,7 @@ public class FunctionalCaseCommentService { } private FunctionalCaseComment updateCommentWidthNotice(FunctionalCaseCommentRequest functionalCaseCommentRequest, FunctionalCaseComment functionalCaseComment, String userId) { - setOther(functionalCaseCommentRequest, functionalCaseComment); + setReplyAndNotifier(functionalCaseCommentRequest, functionalCaseComment); functionalCaseCommentMapper.updateByPrimaryKeySelective(functionalCaseComment); functionalCaseCommentRequest.setEvent(NoticeConstants.Event.AT); FunctionalCaseDTO functionalCaseDTO = functionalCaseNoticeService.getFunctionalCaseDTO(functionalCaseCommentRequest); diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseLogService.java b/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseLogService.java index eb21450d0a..b399380109 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseLogService.java +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseLogService.java @@ -161,4 +161,51 @@ public class FunctionalCaseLogService { } return dtoList; } + + /** + * 恢复项目 + * @param id 接口请求参数 + * @return 日志详情 + */ + public LogDTO recoverLog(String id) { + FunctionalCase functionalCase = functionalCaseMapper.selectByPrimaryKey(id); + if (functionalCase != null) { + LogDTO dto = new LogDTO( + functionalCase.getProjectId(), + "", + id, + functionalCase.getCreateUser(), + OperationLogType.RECOVER.name(), + OperationLogModule.FUNCTIONAL_CASE, + functionalCase.getName()); + dto.setOriginalValue(JSON.toJSONBytes(functionalCase)); + return dto; + } + return null; + } + + /** + * 彻底删除 + * @param id 接口请求参数 + * @return 日志详情 + */ + public LogDTO deleteTrashCaseLog(String id) { + FunctionalCase functionalCase = functionalCaseMapper.selectByPrimaryKey(id); + if (functionalCase != null) { + LogDTO dto = new LogDTO( + functionalCase.getProjectId(), + null, + functionalCase.getId(), + functionalCase.getCreateUser(), + OperationLogType.DELETE.name(), + OperationLogModule.FUNCTIONAL_CASE, + functionalCase.getName()); + + dto.setPath("/functional/case/trash/delete"); + dto.setMethod(HttpMethodConstants.GET.name()); + dto.setOriginalValue(JSON.toJSONBytes(functionalCase)); + return dto; + } + return null; + } } diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseNoticeService.java b/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseNoticeService.java index ad53dce419..c75621cd14 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseNoticeService.java +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseNoticeService.java @@ -58,33 +58,29 @@ public class FunctionalCaseNoticeService { String notifier = functionalCaseCommentRequest.getNotifier(); String replyUser = functionalCaseCommentRequest.getReplyUser(); if (StringUtils.equals(functionalCaseCommentRequest.getEvent(), NoticeConstants.Event.REPLY)) { - if (StringUtils.isNotBlank(replyUser)) { - if (StringUtils.isNotBlank(notifier)) { - List notifierList = Arrays.asList(notifier.split(";")); - if (!notifierList.contains(replyUser)) { - functionalCaseDTO.setRelatedUsers(replyUser); - } - } else { + if (StringUtils.isNotBlank(notifier)) { + List notifierList = Arrays.asList(notifier.split(";")); + if (!notifierList.contains(replyUser)) { functionalCaseDTO.setRelatedUsers(replyUser); } + } else { + functionalCaseDTO.setRelatedUsers(replyUser); } } else { - if (StringUtils.isNotBlank(replyUser)) { + if (StringUtils.isNotBlank(replyUser) && StringUtils.isNotBlank(notifier)) { + List notifierList = Arrays.asList(notifier.split(";")); StringBuilder notifierStr = new StringBuilder(); - if (StringUtils.isNotBlank(notifier)) { - List notifierList = Arrays.asList(notifier.split(";")); - if (notifierList.contains(replyUser)) { - for (String notifierId : notifierList) { - if (!StringUtils.equals(notifierId, replyUser)) { - notifierStr.append(notifierId).append(";"); - } + if (notifierList.contains(replyUser)) { + for (String notifierId : notifierList) { + if (!StringUtils.equals(notifierId, replyUser)) { + notifierStr.append(notifierId).append(";"); } - } else { - notifierStr = new StringBuilder(notifier); } - functionalCaseDTO.setRelatedUsers(notifierStr.toString()); + } else { + notifierStr = new StringBuilder(notifier); } + functionalCaseDTO.setRelatedUsers(notifierStr.toString()); } else { functionalCaseDTO.setRelatedUsers(notifier); } diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseTrashService.java b/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseTrashService.java new file mode 100644 index 0000000000..7400001e79 --- /dev/null +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseTrashService.java @@ -0,0 +1,93 @@ +package io.metersphere.functional.service; + +import io.metersphere.functional.domain.FunctionalCase; +import io.metersphere.functional.domain.FunctionalCaseCustomField; +import io.metersphere.functional.domain.FunctionalCaseCustomFieldExample; +import io.metersphere.functional.domain.FunctionalCaseExample; +import io.metersphere.functional.mapper.ExtFunctionalCaseMapper; +import io.metersphere.functional.mapper.FunctionalCaseCustomFieldMapper; +import io.metersphere.functional.mapper.FunctionalCaseMapper; +import io.metersphere.sdk.exception.MSException; +import io.metersphere.sdk.util.Translator; +import io.metersphere.system.domain.CustomField; +import io.metersphere.system.domain.CustomFieldExample; +import io.metersphere.system.mapper.CustomFieldMapper; +import jakarta.annotation.Resource; +import org.apache.commons.collections.CollectionUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author guoyuqi + * 功能用例回收站服务实现类 + */ +@Service +@Transactional(rollbackFor = Exception.class) +public class FunctionalCaseTrashService { + @Resource + private FunctionalCaseMapper functionalCaseMapper; + @Resource + private FunctionalCaseCustomFieldMapper functionalCaseCustomFieldMapper; + @Resource + private CustomFieldMapper customFieldMapper; + @Resource + private ExtFunctionalCaseMapper extFunctionalCaseMapper; + @Resource + private DeleteFunctionalCaseService deleteFunctionalCaseService; + + /** + * 从回收站恢复用例 + * @param id 用例ID + * @param userId 当前操作人 + */ + public void recoverCase(String id, String userId) { + //检查并恢复所有版本 + FunctionalCase functionalCase = functionalCaseMapper.selectByPrimaryKey(id); + if (functionalCase == null) { + throw new MSException(Translator.get("case_comment.case_is_null")); + } + List ids = getIdsByRefId(functionalCase.getRefId()); + //检查自定义字段是否还存在,不存在,删除关联关系 + FunctionalCaseCustomFieldExample functionalCaseCustomFieldExample = new FunctionalCaseCustomFieldExample(); + functionalCaseCustomFieldExample.createCriteria().andCaseIdIn(ids); + List functionalCaseCustomFields = functionalCaseCustomFieldMapper.selectByExample(functionalCaseCustomFieldExample); + List filedIds = functionalCaseCustomFields.stream().map(FunctionalCaseCustomField::getFieldId).distinct().toList(); + List customFields = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(filedIds)) { + CustomFieldExample customFieldExample = new CustomFieldExample(); + customFieldExample.createCriteria().andIdIn(filedIds); + customFields = customFieldMapper.selectByExample(customFieldExample); + } + List customFieldIds = customFields.stream().map(CustomField::getId).toList(); + List delIds = filedIds.stream().filter(t -> !customFieldIds.contains(t)).toList(); + if (CollectionUtils.isNotEmpty(delIds)) { + functionalCaseCustomFieldExample = new FunctionalCaseCustomFieldExample(); + functionalCaseCustomFieldExample.createCriteria().andFieldIdIn(delIds); + functionalCaseCustomFieldMapper.deleteByExample(functionalCaseCustomFieldExample); + } + extFunctionalCaseMapper.recoverCase(ids,userId,System.currentTimeMillis()); + } + + /** + * 从回收站彻底用例 + * @param id 用例ID + */ + public void deleteCase(String id) { + FunctionalCase functionalCase = functionalCaseMapper.selectByPrimaryKey(id); + if (functionalCase == null) { + return; + } + List ids = getIdsByRefId(functionalCase.getRefId()); + deleteFunctionalCaseService.deleteFunctionalCaseResource(ids, functionalCase.getProjectId()); + } + + private List getIdsByRefId(String refId) { + FunctionalCaseExample functionalCaseExample = new FunctionalCaseExample(); + functionalCaseExample.createCriteria().andRefIdEqualTo(refId); + List functionalCases = functionalCaseMapper.selectByExample(functionalCaseExample); + return functionalCases.stream().map(FunctionalCase::getId).toList(); + } +} diff --git a/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalCaseCommentControllerTests.java b/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalCaseCommentControllerTests.java index a42cc82979..0b3ea666d8 100644 --- a/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalCaseCommentControllerTests.java +++ b/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalCaseCommentControllerTests.java @@ -469,6 +469,8 @@ public class FunctionalCaseCommentControllerTests { Assertions.assertTrue(StringUtils.equals(functionalCaseComment.getCaseId(), "xiaomeinvGTest")); Assertions.assertTrue(StringUtils.equals(functionalCaseComment.getNotifier(), "default-project-member-user-guo;default-project-member-user-guo-4;")); Assertions.assertTrue(StringUtils.equals(functionalCaseComment.getContent(), "评论你好哇")); + Assertions.assertTrue(StringUtils.isBlank(functionalCaseComment.getReplyUser())); + } @Test diff --git a/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalCaseTrashControllerTests.java b/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalCaseTrashControllerTests.java new file mode 100644 index 0000000000..646f09d2e4 --- /dev/null +++ b/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalCaseTrashControllerTests.java @@ -0,0 +1,91 @@ +package io.metersphere.functional.controller; + +import io.metersphere.functional.domain.FunctionalCase; +import io.metersphere.functional.domain.FunctionalCaseComment; +import io.metersphere.functional.mapper.FunctionalCaseCommentMapper; +import io.metersphere.functional.mapper.FunctionalCaseMapper; +import io.metersphere.sdk.constants.SessionConstants; +import io.metersphere.system.base.BaseTest; +import io.metersphere.system.mapper.CustomFieldMapper; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.*; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.test.context.jdbc.SqlConfig; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +@AutoConfigureMockMvc +public class FunctionalCaseTrashControllerTests extends BaseTest { + + private static final String URL_CASE_RECOVER = "/functional/case/trash/recover/"; + private static final String URL_CASE_DELETE = "/functional/case/trash/delete/"; + + + @Resource + private FunctionalCaseMapper functionalCaseMapper; + @Resource + private CustomFieldMapper customFieldMapper; + @Resource + private FunctionalCaseCommentMapper functionalCaseCommentMapper; + + + @Test + @Order(1) + @Sql(scripts = {"/dml/init_case_trash.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED)) + public void recoverCaseSuccessWidthCustom() throws Exception { + customFieldMapper.deleteByPrimaryKey("gyq_custom_id2"); + this.requestGetWithOk(URL_CASE_RECOVER + "Trash_TEST_FUNCTIONAL_CASE_ID"); + FunctionalCase functionalCase = functionalCaseMapper.selectByPrimaryKey("Trash_TEST_FUNCTIONAL_CASE_ID"); + Assertions.assertFalse(functionalCase.getDeleted()); + System.out.println(functionalCase.getUpdateUser()); + FunctionalCase functionalCaseV = functionalCaseMapper.selectByPrimaryKey("Trash_TEST_FUNCTIONAL_CASE_ID_4"); + Assertions.assertFalse(functionalCaseV.getDeleted()); + } + + @Test + @Order(2) + public void recoverCaseSuccessWidthNoCustom() throws Exception { + this.requestGetWithOk(URL_CASE_RECOVER + "Trash_TEST_FUNCTIONAL_CASE_ID_1"); + FunctionalCase functionalCase = functionalCaseMapper.selectByPrimaryKey("Trash_TEST_FUNCTIONAL_CASE_ID_1"); + Assertions.assertFalse(functionalCase.getDeleted()); + FunctionalCase functionalCase2 = functionalCaseMapper.selectByPrimaryKey("Trash_TEST_FUNCTIONAL_CASE_ID_2"); + Assertions.assertFalse(functionalCase2.getDeleted()); + FunctionalCase functionalCase3 = functionalCaseMapper.selectByPrimaryKey("Trash_TEST_FUNCTIONAL_CASE_ID_3"); + Assertions.assertFalse(functionalCase3.getDeleted()); + } + + @Test + @Order(3) + public void recoverCaseFalse() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.get(URL_CASE_RECOVER + "Trash_TEST_FUNCTIONAL_CASE_ID_del").header(SessionConstants.HEADER_TOKEN, sessionId) + .header(SessionConstants.CSRF_TOKEN, csrfToken) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is5xxServerError()); + } + + @Test + @Order(4) + public void deleteCaseWidthNoExist() throws Exception { + this.requestGetWithOk(URL_CASE_DELETE + "Trash_TEST_FUNCTIONAL_CASE_ID_del"); + } + + @Test + @Order(5) + public void deleteCaseWidthSuccess() throws Exception { + this.requestGetWithOk(URL_CASE_DELETE + "Trash_TEST_FUNCTIONAL_CASE_ID"); + FunctionalCase functionalCase = functionalCaseMapper.selectByPrimaryKey("Trash_TEST_FUNCTIONAL_CASE_ID"); + Assertions.assertNull(functionalCase); + FunctionalCase functionalCase4 = functionalCaseMapper.selectByPrimaryKey("Trash_TEST_FUNCTIONAL_CASE_ID_4"); + Assertions.assertNull(functionalCase4); + FunctionalCaseComment functionalCaseComment = functionalCaseCommentMapper.selectByPrimaryKey("trash_comment_id"); + Assertions.assertNull(functionalCaseComment); + + } + +} diff --git a/backend/services/case-management/src/test/resources/dml/init_case_trash.sql b/backend/services/case-management/src/test/resources/dml/init_case_trash.sql new file mode 100644 index 0000000000..a2e76b3727 --- /dev/null +++ b/backend/services/case-management/src/test/resources/dml/init_case_trash.sql @@ -0,0 +1,29 @@ + +INSERT INTO functional_case(id, num, module_id, project_id, template_id, name, review_status, tags, case_edit_type, pos, version_id, ref_id, last_execute_result, deleted, public_case, latest, create_user, update_user, delete_user, create_time, update_time, delete_time) +VALUES ('Trash_TEST_FUNCTIONAL_CASE_ID', 1, 'Trash_TEST_MOUDLE_ID', '100001100001', '100001', '回收站测试', 'UN_REVIEWED', NULL, 'STEP', 0, 'v1.0.0', 'Trash_TEST_FUNCTIONAL_CASE_ID', 'UN_EXECUTED', true, b'0', b'0', 'gyq', 'gyq', '', 1698058347559, 1698058347559, NULL); + +INSERT INTO functional_case(id, num, module_id, project_id, template_id, name, review_status, tags, case_edit_type, pos, version_id, ref_id, last_execute_result, deleted, public_case, latest, create_user, update_user, delete_user, create_time, update_time, delete_time) +VALUES ('Trash_TEST_FUNCTIONAL_CASE_ID_1', 2, 'Trash_TEST_MOUDLE_ID', '100001100001', '100001', '测试多版本', 'UN_REVIEWED', NULL, 'STEP', 0, 'v1.0.0', 'Trash_TEST_FUNCTIONAL_CASE_ID_1', 'UN_EXECUTED', true, b'0', b'0', 'gyq', 'gyq', '', 1698058347559, 1698058347559, NULL); + +INSERT INTO functional_case(id, num, module_id, project_id, template_id, name, review_status, tags, case_edit_type, pos, version_id, ref_id, last_execute_result, deleted, public_case, latest, create_user, update_user, delete_user, create_time, update_time, delete_time) +VALUES ('Trash_TEST_FUNCTIONAL_CASE_ID_2', 3, 'Trash_TEST_MOUDLE_ID', '100001100001', '100001', 'copy_测试多版本', 'UN_REVIEWED', NULL, 'STEP', 0, 'v2.0.0', 'Trash_TEST_FUNCTIONAL_CASE_ID_1', 'UN_EXECUTED', true, b'0', b'0', 'gyq', 'gyq', '', 1698058347559, 1698058347559, NULL); + +INSERT INTO functional_case(id, num, module_id, project_id, template_id, name, review_status, tags, case_edit_type, pos, version_id, ref_id, last_execute_result, deleted, public_case, latest, create_user, update_user, delete_user, create_time, update_time, delete_time) +VALUES ('Trash_TEST_FUNCTIONAL_CASE_ID_3', 3, 'Trash_TEST_MOUDLE_ID', '100001100001', '100001', 'copy_测试多版本', 'UN_REVIEWED', NULL, 'STEP', 0, 'v3.0.0', 'Trash_TEST_FUNCTIONAL_CASE_ID_1', 'UN_EXECUTED', true, b'0', b'0', 'gyq', 'gyq', '', 1698058347559, 1698058347559, NULL); + +INSERT INTO functional_case(id, num, module_id, project_id, template_id, name, review_status, tags, case_edit_type, pos, version_id, ref_id, last_execute_result, deleted, public_case, latest, create_user, update_user, delete_user, create_time, update_time, delete_time) +VALUES ('Trash_TEST_FUNCTIONAL_CASE_ID_4', 4, 'Trash_TEST_MOUDLE_ID', '100001100001', '100001', 'copy_测试多版本', 'UN_REVIEWED', NULL, 'STEP', 0, 'v3.0.0', 'Trash_TEST_FUNCTIONAL_CASE_ID', 'UN_EXECUTED',true, b'0', b'0', 'gyq', 'gyq', '', 1698058347559, 1698058347559, NULL); + + +INSERT INTO functional_case_custom_field(case_id, field_id, value) VALUES ('Trash_TEST_FUNCTIONAL_CASE_ID', 'gyq_custom_id1', '22'); +INSERT INTO functional_case_custom_field(case_id, field_id, value) VALUES ('Trash_TEST_FUNCTIONAL_CASE_ID', 'gyq_custom_id2', '33'); + + +INSERT INTO custom_field(id, name, scene, `type`, remark, internal, scope_type, create_time, update_time, create_user, scope_id) +VALUES('gyq_custom_id1', 'functional_priority', 'FUNCTIONAL', 'SELECT', '', 1, 'ORGANIZATION', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', '100001'); + +INSERT INTO custom_field(id, name, scene, `type`, remark, internal, scope_type, create_time, update_time, create_user, scope_id) +VALUES('gyq_custom_id2', 'level', 'FUNCTIONAL', 'SELECT', '', 1, 'ORGANIZATION', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', '100001'); + +INSERT INTO functional_case_comment(id, case_id, create_user, status, parent_id, resource_id, notifier, content, reply_user, create_time, update_time) +VALUES ('trash_comment_id', 'Trash_TEST_FUNCTIONAL_CASE_ID', 'gyq', null, null, null, 'gyq','你好', null, UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000); \ No newline at end of file diff --git a/backend/services/system-setting/src/main/java/io/metersphere/system/log/aspect/OperationLogAspect.java b/backend/services/system-setting/src/main/java/io/metersphere/system/log/aspect/OperationLogAspect.java index 8b098d1e2f..320ac85571 100644 --- a/backend/services/system-setting/src/main/java/io/metersphere/system/log/aspect/OperationLogAspect.java +++ b/backend/services/system-setting/src/main/java/io/metersphere/system/log/aspect/OperationLogAspect.java @@ -64,7 +64,7 @@ public class OperationLogAspect { private final ThreadLocal localProjectId = new ThreadLocal<>(); // 此方法随时补充类型,需要在内容变更前执行的类型都可以加入 - private final OperationLogType[] beforeMethodNames = new OperationLogType[]{OperationLogType.UPDATE, OperationLogType.DELETE}; + private final OperationLogType[] beforeMethodNames = new OperationLogType[]{OperationLogType.UPDATE, OperationLogType.DELETE, OperationLogType.RECOVER}; // 需要后置执行合并内容的 private final OperationLogType[] postMethodNames = new OperationLogType[]{OperationLogType.ADD, OperationLogType.UPDATE}; diff --git a/backend/services/system-setting/src/main/java/io/metersphere/system/notice/sender/AbstractNoticeSender.java b/backend/services/system-setting/src/main/java/io/metersphere/system/notice/sender/AbstractNoticeSender.java index aaf87a1985..6bf9e3ab1c 100644 --- a/backend/services/system-setting/src/main/java/io/metersphere/system/notice/sender/AbstractNoticeSender.java +++ b/backend/services/system-setting/src/main/java/io/metersphere/system/notice/sender/AbstractNoticeSender.java @@ -23,7 +23,6 @@ import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.LogUtils; import io.metersphere.system.domain.User; import io.metersphere.system.domain.UserExample; -import io.metersphere.system.mapper.CustomFieldMapper; import io.metersphere.system.mapper.UserMapper; import io.metersphere.system.notice.MessageDetail; import io.metersphere.system.notice.NoticeModel; @@ -42,8 +41,6 @@ import java.util.stream.Collectors; public abstract class AbstractNoticeSender implements NoticeSender { - @Resource - private CustomFieldMapper customFieldMapper; @Resource private TestPlanFollowerMapper testPlanFollowerMapper; @Resource @@ -89,7 +86,7 @@ public abstract class AbstractNoticeSender implements NoticeSender { } if (CollectionUtils.isNotEmpty(fields)) { for (Object o : fields) { - String jsonFields = JSON.toJSONString(o); + String jsonFields = JSON.toJSONString(o); Map jsonObject = JSON.parseObject(jsonFields, Map.class); String customFieldName = (String) jsonObject.get("id"); Object value = jsonObject.get("name"); @@ -145,6 +142,7 @@ public abstract class AbstractNoticeSender implements NoticeSender { // 去重复 List userIds = toUsers.stream().map(Receiver::getUserId).distinct().toList(); + LogUtils.error("userIds: ", JSON.toJSONString(userIds)); List users = getUsers(userIds); List realUserIds = users.stream().map(User::getId).toList(); return toUsers.stream().filter(t -> realUserIds.contains(t.getUserId())).toList(); @@ -153,6 +151,9 @@ public abstract class AbstractNoticeSender implements NoticeSender { private List handleFollows(MessageDetail messageDetail, NoticeModel noticeModel) { List receivers = new ArrayList<>(); String id = (String) noticeModel.getParamMap().get("id"); + if (StringUtils.isBlank(id)) { + return receivers; + } String taskType = messageDetail.getTaskType(); switch (taskType) { case NoticeConstants.TaskType.TEST_PLAN_TASK -> { @@ -218,7 +219,10 @@ public abstract class AbstractNoticeSender implements NoticeSender { protected List getUsers(List userIds) { UserExample userExample = new UserExample(); - userExample.createCriteria().andIdIn(userIds); - return userMapper.selectByExample(userExample); + if (CollectionUtils.isNotEmpty(userIds)) { + userExample.createCriteria().andIdIn(userIds); + return userMapper.selectByExample(userExample); + } + return new ArrayList<>(); } } diff --git a/backend/services/system-setting/src/test/java/io/metersphere/system/controller/AfterReturningNoticeSendServiceTests.java b/backend/services/system-setting/src/test/java/io/metersphere/system/controller/AfterReturningNoticeSendServiceTests.java index 34e68acfbc..0b78319839 100644 --- a/backend/services/system-setting/src/test/java/io/metersphere/system/controller/AfterReturningNoticeSendServiceTests.java +++ b/backend/services/system-setting/src/test/java/io/metersphere/system/controller/AfterReturningNoticeSendServiceTests.java @@ -1,10 +1,19 @@ package io.metersphere.system.controller; +import io.metersphere.api.domain.ApiDefinition; +import io.metersphere.api.domain.ApiScenario; +import io.metersphere.api.mapper.ApiDefinitionMapper; +import io.metersphere.api.mapper.ApiScenarioMapper; +import io.metersphere.functional.domain.CaseReview; import io.metersphere.functional.domain.FunctionalCase; import io.metersphere.functional.domain.FunctionalCaseCustomField; import io.metersphere.functional.domain.FunctionalCaseCustomFieldExample; +import io.metersphere.functional.mapper.CaseReviewMapper; import io.metersphere.functional.mapper.FunctionalCaseCustomFieldMapper; import io.metersphere.functional.mapper.FunctionalCaseMapper; +import io.metersphere.load.domain.LoadTest; +import io.metersphere.plan.domain.TestPlan; +import io.metersphere.plan.mapper.TestPlanMapper; import io.metersphere.sdk.util.BeanUtils; import io.metersphere.sdk.util.JSON; import io.metersphere.system.base.BaseTest; @@ -46,6 +55,14 @@ public class AfterReturningNoticeSendServiceTests extends BaseTest { private CustomFieldMapper customFieldMapper; @Resource private FunctionalCaseCustomFieldMapper functionalCaseCustomFieldMapper; + @Resource + private ApiDefinitionMapper apiDefinitionMapper; + @Resource + private ApiScenarioMapper apiScenarioMapper; + @Resource + private TestPlanMapper testPlanMapper; + @Resource + private CaseReviewMapper caseReviewMapper; private ThreadLocal source = new ThreadLocal<>(); @@ -54,7 +71,8 @@ public class AfterReturningNoticeSendServiceTests extends BaseTest { @Order(1) @Sql(scripts = {"/dml/init_aspect.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED)) public void noticeSuccess() { - String taskType = NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK; + String functionalCaseTask = NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK; + ListeventList = new ArrayList<>(); getTypeList(eventList); FunctionalCase functionalCase = functionalCaseMapper.selectByPrimaryKey("aspect_gyq_one"); @@ -99,7 +117,218 @@ public class AfterReturningNoticeSendServiceTests extends BaseTest { SessionUser user = SessionUser.fromUser(userDTO, sessionId); for (String event : eventList) { - afterReturningNoticeSendService.sendNotice(taskType, event,resources, user, "100001100001"); + afterReturningNoticeSendService.sendNotice(functionalCaseTask, event,resources, user, "100001100001"); + } + + } + + @Test + @Order(2) + public void ApiNoticeSuccess() { + String apiDefinitionTask = NoticeConstants.TaskType.API_DEFINITION_TASK; + + ListeventList = new ArrayList<>(); + getTypeList(eventList); + ApiDefinition aspectGyqApiOne = apiDefinitionMapper.selectByPrimaryKey("aspect_gyq_api_one"); + + String jsonObject = JSON.toJSONString(aspectGyqApiOne); + if (!StringUtils.equals("{}", jsonObject) && !StringUtils.equals("[]", jsonObject)) { + source.set(JSON.toJSONString(aspectGyqApiOne)); + } + + List resources = new ArrayList<>(); + String v = source.get(); + if (StringUtils.isNotBlank(v)) { + // array + if (StringUtils.startsWith(v, "[")) { + resources.addAll(JSON.parseArray(v, Map.class)); + } + // map + else { + Map value = JSON.parseObject(v, Map.class); + resources.add(value); + } + } + + UserDTO userDTO = new UserDTO(); + userDTO.setId(sessionId); + userDTO.setName("admin"); + SessionUser user = SessionUser.fromUser(userDTO, sessionId); + + for (String event : eventList) { + afterReturningNoticeSendService.sendNotice(apiDefinitionTask, event,resources, user, "100001100001"); + } + + } + + @Test + @Order(3) + public void ApiScenarioNoticeSuccess() { + String apiScenarioTask = NoticeConstants.TaskType.API_SCENARIO_TASK; + String testPlanTask = NoticeConstants.TaskType.TEST_PLAN_TASK; + String caseReviewTask = NoticeConstants.TaskType.CASE_REVIEW_TASK; + String loadTestTask = NoticeConstants.TaskType.LOAD_TEST_TASK; + + ListeventList = new ArrayList<>(); + getTypeList(eventList); + ApiScenario aspectGyqApiScenarioOne = apiScenarioMapper.selectByPrimaryKey("aspect_gyq_api_scenario_one"); + + String jsonObject = JSON.toJSONString(aspectGyqApiScenarioOne); + if (!StringUtils.equals("{}", jsonObject) && !StringUtils.equals("[]", jsonObject)) { + source.set(JSON.toJSONString(aspectGyqApiScenarioOne)); + } + + List resources = new ArrayList<>(); + String v = source.get(); + if (StringUtils.isNotBlank(v)) { + // array + if (StringUtils.startsWith(v, "[")) { + resources.addAll(JSON.parseArray(v, Map.class)); + } + // map + else { + Map value = JSON.parseObject(v, Map.class); + resources.add(value); + } + } + + UserDTO userDTO = new UserDTO(); + userDTO.setId(sessionId); + userDTO.setName("admin"); + SessionUser user = SessionUser.fromUser(userDTO, sessionId); + + for (String event : eventList) { + afterReturningNoticeSendService.sendNotice(apiScenarioTask, event,resources, user, "100001100001"); + } + + } + + @Test + @Order(4) + public void TestPlanTaskNoticeSuccess() { + String testPlanTask = NoticeConstants.TaskType.TEST_PLAN_TASK; + + ListeventList = new ArrayList<>(); + getTypeList(eventList); + TestPlan aspectGyqTestPlanOne = testPlanMapper.selectByPrimaryKey("aspect_gyq_test_plan_one"); + + String jsonObject = JSON.toJSONString(aspectGyqTestPlanOne); + if (!StringUtils.equals("{}", jsonObject) && !StringUtils.equals("[]", jsonObject)) { + source.set(JSON.toJSONString(aspectGyqTestPlanOne)); + } + + List resources = new ArrayList<>(); + String v = source.get(); + if (StringUtils.isNotBlank(v)) { + // array + if (StringUtils.startsWith(v, "[")) { + resources.addAll(JSON.parseArray(v, Map.class)); + } + // map + else { + Map value = JSON.parseObject(v, Map.class); + resources.add(value); + } + } + + UserDTO userDTO = new UserDTO(); + userDTO.setId(sessionId); + userDTO.setName("admin"); + SessionUser user = SessionUser.fromUser(userDTO, sessionId); + + for (String event : eventList) { + afterReturningNoticeSendService.sendNotice(testPlanTask, event,resources, user, "100001100001"); + } + + } + + @Test + @Order(5) + public void CaseReviewTaskNoticeSuccess() { + String caseReviewTask = NoticeConstants.TaskType.CASE_REVIEW_TASK; + + ListeventList = new ArrayList<>(); + getTypeList(eventList); + CaseReview aspectGyqCaseReviewOne = caseReviewMapper.selectByPrimaryKey("aspect_gyq_case_review_one"); + + String jsonObject = JSON.toJSONString(aspectGyqCaseReviewOne); + if (!StringUtils.equals("{}", jsonObject) && !StringUtils.equals("[]", jsonObject)) { + source.set(JSON.toJSONString(aspectGyqCaseReviewOne)); + } + + List resources = new ArrayList<>(); + String v = source.get(); + if (StringUtils.isNotBlank(v)) { + // array + if (StringUtils.startsWith(v, "[")) { + resources.addAll(JSON.parseArray(v, Map.class)); + } + // map + else { + Map value = JSON.parseObject(v, Map.class); + resources.add(value); + } + } + + UserDTO userDTO = new UserDTO(); + userDTO.setId(sessionId); + userDTO.setName("admin"); + SessionUser user = SessionUser.fromUser(userDTO, sessionId); + + for (String event : eventList) { + afterReturningNoticeSendService.sendNotice(caseReviewTask, event,resources, user, "100001100001"); + } + + } + + @Test + @Order(6) + public void LoadTestTaskTaskNoticeSuccess() { + String loadTestTask = NoticeConstants.TaskType.LOAD_TEST_TASK; + + ListeventList = new ArrayList<>(); + getTypeList(eventList); + LoadTest loadTest = new LoadTest(); + loadTest.setId("aspect_gyq_load_test_one"); + loadTest.setProjectId("100001100001"); + loadTest.setName("load_test"); + loadTest.setCreateTime(System.currentTimeMillis()); + loadTest.setUpdateTime(System.currentTimeMillis()); + loadTest.setStatus("Starting"); + loadTest.setTestResourcePoolId("test_pool"); + loadTest.setNum(10001); + loadTest.setCreateUser("admin"); + loadTest.setPos(1L); + loadTest.setVersionId("v1.10"); + loadTest.setRefId("aspect_gyq_load_test_one"); + loadTest.setLatest(true); + + String jsonObject = JSON.toJSONString(loadTest); + if (!StringUtils.equals("{}", jsonObject) && !StringUtils.equals("[]", jsonObject)) { + source.set(JSON.toJSONString(loadTest)); + } + + List resources = new ArrayList<>(); + String v = source.get(); + if (StringUtils.isNotBlank(v)) { + // array + if (StringUtils.startsWith(v, "[")) { + resources.addAll(JSON.parseArray(v, Map.class)); + } + // map + else { + Map value = JSON.parseObject(v, Map.class); + resources.add(value); + } + } + + UserDTO userDTO = new UserDTO(); + userDTO.setId(sessionId); + userDTO.setName("admin"); + SessionUser user = SessionUser.fromUser(userDTO, sessionId); + + for (String event : eventList) { + afterReturningNoticeSendService.sendNotice(loadTestTask, event,resources, user, "100001100001"); } } diff --git a/backend/services/system-setting/src/test/resources/dml/init_aspect.sql b/backend/services/system-setting/src/test/resources/dml/init_aspect.sql index 4c79d121c4..4679776ca1 100644 --- a/backend/services/system-setting/src/test/resources/dml/init_aspect.sql +++ b/backend/services/system-setting/src/test/resources/dml/init_aspect.sql @@ -33,3 +33,16 @@ INSERT INTO custom_field(id, name, scene, type, remark, create_time, update_time values ('aspect_test_one','aspect_test','FUNCTIONAL', 'INPUT','aspect_test', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin' , 'aspect_test_one', '100001100001',false, false, 'PROJECT'); INSERT INTO functional_case_custom_field(case_id, field_id, value) VALUES ('aspect_gyq_one', 'aspect_test_one', 'hello'); + +INSERT INTO api_definition(id, name, protocol, method, path, status, num, tags, pos, project_id, module_id, latest, version_id, ref_id, description, create_time, create_user, update_time, update_user, delete_user, delete_time, deleted) +VALUES ('aspect_gyq_api_one', 'api_test','HTTP', 'POST','api/test','test-api-status', 1000001, null, 1, '100001100001' , 'test_module', true, 'v1.10','aspect_gyq_api_one', null, UNIX_TIMESTAMP() * 1000,'admin', UNIX_TIMESTAMP() * 1000,'admin', null,null,false); + +INSERT INTO api_scenario(id, name, level, status, principal, last_report_status, last_report_id, num, custom_num, pos, version_id, ref_id, project_id, api_scenario_module_id, description, tags, create_user, create_time, delete_time, delete_user, update_user, update_time) +VALUES ('aspect_gyq_api_scenario_one', 'api_scenario', 'p1', 'test-api-status', 'gyq', null, null,1000001, 1000001, 1,'v1.10', 'aspect_gyq_api_scenario_one','100001100001', 'test_module', null,null,'admin', UNIX_TIMESTAMP() * 1000,null,null,'admin', UNIX_TIMESTAMP() * 1000); + +INSERT INTO test_plan(id, project_id, parent_id, name, status, stage, tags, create_time, create_user, update_time, update_user, planned_start_time, planned_end_time, actual_start_time, actual_end_time, description) +VALUES ('aspect_gyq_test_plan_one','100001100001', 'NONE', 'test_plan', 'test-api-status', 'Smock', null, UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 2000, UNIX_TIMESTAMP() * 3000 ,UNIX_TIMESTAMP() * 2000, UNIX_TIMESTAMP() * 3000,null); + +INSERT INTO case_review(id, name, status, create_time, update_time, end_time, description, project_id, tags, create_user, review_pass_rule) +VALUES ('aspect_gyq_case_review_one','case_review','test-api-status',UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000,null, '100001100001',null,'admin','single'); +