From 6be74d1ab01ff630cfad612015e32cc567f697f3 Mon Sep 17 00:00:00 2001 From: guoyuqi Date: Mon, 4 Dec 2023 15:15:55 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E7=94=A8=E4=BE=8B=E8=AF=84=E5=AE=A1):=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=A4=8D=E5=88=B6=E5=92=8C=E6=89=B9=E9=87=8F?= =?UTF-8?q?=E7=A7=BB=E5=8A=A8=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CaseReviewController.java | 44 +++++++++------ .../mapper/ExtCaseReviewMapper.java | 6 ++- .../functional/mapper/ExtCaseReviewMapper.xml | 54 +++++++++++++++++++ .../request/CaseReviewBatchRequest.java | 21 ++++++++ .../service/CaseReviewLogService.java | 22 ++++++++ .../functional/service/CaseReviewService.java | 32 ++++++++++- .../controller/CaseReviewControllerTests.java | 51 +++++++++++++++++- .../test/resources/dml/init_case_review.sql | 5 +- .../system/log/aspect/OperationLogAspect.java | 2 +- 9 files changed, 215 insertions(+), 22 deletions(-) create mode 100644 backend/services/case-management/src/main/java/io/metersphere/functional/request/CaseReviewBatchRequest.java diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/controller/CaseReviewController.java b/backend/services/case-management/src/main/java/io/metersphere/functional/controller/CaseReviewController.java index 5712bbe78b..3c32936aef 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/controller/CaseReviewController.java +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/controller/CaseReviewController.java @@ -4,10 +4,7 @@ import com.alibaba.excel.util.StringUtils; import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; import io.metersphere.functional.dto.CaseReviewDTO; -import io.metersphere.functional.request.CaseReviewAssociateRequest; -import io.metersphere.functional.request.CaseReviewFollowerRequest; -import io.metersphere.functional.request.CaseReviewPageRequest; -import io.metersphere.functional.request.CaseReviewRequest; +import io.metersphere.functional.request.*; import io.metersphere.functional.service.CaseReviewLogService; import io.metersphere.functional.service.CaseReviewNoticeService; import io.metersphere.functional.service.CaseReviewService; @@ -59,12 +56,13 @@ public class CaseReviewController { caseReviewService.addCaseReview(request, SessionUtils.getUserId()); } - @PostMapping("/associate") - @Operation(summary = "用例管理-用例评审-关联用例") - @Log(type = OperationLogType.ASSOCIATE, expression = "#msClass.associateCaseLog(#request)", msClass = CaseReviewLogService.class) - @RequiresPermissions(PermissionConstants.CASE_REVIEW_RELEVANCE) - public void associateCase(@Validated @RequestBody CaseReviewAssociateRequest request) { - caseReviewService.associateCase(request, SessionUtils.getUserId()); + @PostMapping("/copy") + @Operation(summary = "用例管理-用例评审-复制用例评审") + @Log(type = OperationLogType.COPY, expression = "#msClass.copyCaseReviewLog(#request)", msClass = CaseReviewLogService.class) + @SendNotice(taskType = NoticeConstants.TaskType.CASE_REVIEW_TASK, event = NoticeConstants.Event.CREATE, target = "#targetClass.getMainCaseReview(#request)", targetClass = CaseReviewNoticeService.class) + @RequiresPermissions(PermissionConstants.CASE_REVIEW_READ_ADD) + public void copyCaseReview(@Validated @RequestBody CaseReviewRequest request) { + caseReviewService.addCaseReview(request, SessionUtils.getUserId()); } @PostMapping("/edit") @@ -76,6 +74,14 @@ public class CaseReviewController { caseReviewService.editCaseReview(request, SessionUtils.getUserId()); } + @GetMapping("/user-option/{projectId}") + @Operation(summary = "用例管理-用例评审-获取具有评审权限的用户") + @RequiresPermissions(value = {PermissionConstants.CASE_REVIEW_READ_ADD,PermissionConstants.CASE_REVIEW_READ_UPDATE}, logical = Logical.OR) + public List getReviewUserList(@PathVariable String projectId, @Schema(description = "查询关键字,根据邮箱和用户名查询") + @RequestParam(value = "keyword", required = false) String keyword) { + return caseReviewService.getReviewUserList(projectId, keyword); + } + @PostMapping("/edit/follower") @Operation(summary = "用例管理-用例评审-关注/取消关注用例") @RequiresPermissions(PermissionConstants.CASE_REVIEW_READ_UPDATE) @@ -83,12 +89,12 @@ public class CaseReviewController { caseReviewService.editFollower(request.getCaseReviewId(), SessionUtils.getUserId()); } - @GetMapping("/user-option/{projectId}") - @Operation(summary = "用例管理-用例评审-获取具有评审权限的用户") - @RequiresPermissions(value = {PermissionConstants.CASE_REVIEW_READ_ADD,PermissionConstants.CASE_REVIEW_READ_UPDATE}, logical = Logical.OR) - public List getReviewUserList(@PathVariable String projectId, @Schema(description = "查询关键字,根据邮箱和用户名查询") - @RequestParam(value = "keyword", required = false) String keyword) { - return caseReviewService.getReviewUserList(projectId, keyword); + @PostMapping("/associate") + @Operation(summary = "用例管理-用例评审-关联用例") + @Log(type = OperationLogType.ASSOCIATE, expression = "#msClass.associateCaseLog(#request)", msClass = CaseReviewLogService.class) + @RequiresPermissions(PermissionConstants.CASE_REVIEW_RELEVANCE) + public void associateCase(@Validated @RequestBody CaseReviewAssociateRequest request) { + caseReviewService.associateCase(request, SessionUtils.getUserId()); } @PostMapping("/edit/pos") @@ -105,4 +111,10 @@ public class CaseReviewController { return caseReviewService.getCaseReviewDetail(id, SessionUtils.getUserId()); } + @PostMapping("batch/move") + @Operation(summary = "用例管理-用例评审-复制用例评审") + @RequiresPermissions(PermissionConstants.CASE_REVIEW_READ_UPDATE) + public void batchMoveCaseReview(@Validated @RequestBody CaseReviewBatchRequest request) { + caseReviewService.batchMoveCaseReview(request, SessionUtils.getUserId()); + } } \ No newline at end of file diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtCaseReviewMapper.java b/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtCaseReviewMapper.java index 4eedf9db4d..1409e71195 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtCaseReviewMapper.java +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtCaseReviewMapper.java @@ -2,13 +2,14 @@ package io.metersphere.functional.mapper; import io.metersphere.functional.domain.CaseReview; import io.metersphere.functional.dto.CaseReviewDTO; +import io.metersphere.functional.request.CaseReviewBatchRequest; import io.metersphere.functional.request.CaseReviewPageRequest; import org.apache.ibatis.annotations.Param; import java.util.List; /** - * @author wx + * @author guoyuqi */ public interface ExtCaseReviewMapper { @@ -22,4 +23,7 @@ public interface ExtCaseReviewMapper { Long getLastPos(@Param("projectId") String projectId, @Param("basePos") Long basePos); + List getIds(@Param("request") CaseReviewBatchRequest request, @Param("projectId") String projectId); + + void batchMoveModule(@Param("request") CaseReviewBatchRequest request, @Param("ids") List ids, @Param("userId") String userId); } diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtCaseReviewMapper.xml b/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtCaseReviewMapper.xml index 192e697e90..0e915fcc5a 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtCaseReviewMapper.xml +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtCaseReviewMapper.xml @@ -45,6 +45,49 @@ 1 = 1 + + + + + ( + case_review.name like concat('%', #{request.keyword},'%') + or case_review.num like concat('%', #{request.keyword},'%') + ) + + + + + + + + + + + + + + + + + + case_review.module_id in @@ -310,4 +353,15 @@ order by `pos` desc limit 1; + + update case_review + set module_id = #{request.moduleId}, + update_user = #{userId}, + update_time = UNIX_TIMESTAMP()*1000 + where id in + + #{id} + + + \ No newline at end of file diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/request/CaseReviewBatchRequest.java b/backend/services/case-management/src/main/java/io/metersphere/functional/request/CaseReviewBatchRequest.java new file mode 100644 index 0000000000..fe1986d363 --- /dev/null +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/request/CaseReviewBatchRequest.java @@ -0,0 +1,21 @@ +package io.metersphere.functional.request; + +import io.metersphere.system.dto.table.TableBatchProcessDTO; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author guoyuqi + */ +@Data +public class CaseReviewBatchRequest extends TableBatchProcessDTO implements Serializable { + + @Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED) + private String projectId; + + @Schema(description = "模块ID", requiredMode = Schema.RequiredMode.REQUIRED) + private String moduleId; + +} diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/service/CaseReviewLogService.java b/backend/services/case-management/src/main/java/io/metersphere/functional/service/CaseReviewLogService.java index 53ca5358a6..db197494ee 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/service/CaseReviewLogService.java +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/service/CaseReviewLogService.java @@ -55,6 +55,28 @@ public class CaseReviewLogService { return dto; } + /** + * 复制用例评审 日志 + * + * @param requests 页面参数 + * @return LogDTO + */ + public LogDTO copyCaseReviewLog(CaseReviewRequest requests) { + LogDTO dto = new LogDTO( + requests.getProjectId(), + null, + null, + null, + OperationLogType.COPY.name(), + OperationLogModule.CASE_REVIEW, + requests.getName()); + + dto.setPath("/case/review/copy"); + dto.setMethod(HttpMethodConstants.POST.name()); + dto.setOriginalValue(JSON.toJSONBytes(requests)); + return dto; + } + /** * 更新用例评审 日志 * diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/service/CaseReviewService.java b/backend/services/case-management/src/main/java/io/metersphere/functional/service/CaseReviewService.java index d9b0b1f76c..7eb3f2d79d 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/service/CaseReviewService.java +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/service/CaseReviewService.java @@ -8,6 +8,7 @@ import io.metersphere.functional.dto.CaseReviewDTO; import io.metersphere.functional.dto.CaseReviewUserDTO; import io.metersphere.functional.mapper.*; import io.metersphere.functional.request.CaseReviewAssociateRequest; +import io.metersphere.functional.request.CaseReviewBatchRequest; import io.metersphere.functional.request.CaseReviewPageRequest; import io.metersphere.functional.request.CaseReviewRequest; import io.metersphere.functional.result.CaseManagementResultCode; @@ -66,6 +67,8 @@ public class CaseReviewService { private CaseReviewFunctionalCaseMapper caseReviewFunctionalCaseMapper; @Resource private ExtCaseReviewUserMapper extCaseReviewUserMapper; + @Resource + private FunctionalCaseMapper functionalCaseMapper; /** @@ -418,6 +421,12 @@ public class CaseReviewService { public void associateCase(CaseReviewAssociateRequest request, String userId) { String caseReviewId = request.getReviewId(); CaseReview caseReviewExist = checkCaseReview(caseReviewId); + FunctionalCaseExample functionalCaseExample = new FunctionalCaseExample(); + functionalCaseExample.createCriteria().andIdIn(request.getCaseIds()); + List functionalCases = functionalCaseMapper.selectByExample(functionalCaseExample); + if (CollectionUtils.isEmpty(functionalCases)) { + return; + } CaseReviewFunctionalCaseExample caseReviewFunctionalCaseExample = new CaseReviewFunctionalCaseExample(); caseReviewFunctionalCaseExample.createCriteria().andReviewIdEqualTo(caseReviewId); List caseReviewFunctionalCases = caseReviewFunctionalCaseMapper.selectByExample(caseReviewFunctionalCaseExample); @@ -450,6 +459,7 @@ public class CaseReviewService { /** * 用例评审列表拖拽排序 + * * @param request request */ public void editPos(PosRequest request) { @@ -463,7 +473,8 @@ public class CaseReviewService { /** * 获取用例评审详情 - * @param id 用例评审id + * + * @param id 用例评审id * @param userId 当前操作人 * @return CaseReviewDTO */ @@ -481,7 +492,8 @@ public class CaseReviewService { /** * 检查当前操作人是否关注该用例评审 - * @param id 评审人名称 + * + * @param id 评审人名称 * @param userId 操作人 * @return Boolean */ @@ -490,4 +502,20 @@ public class CaseReviewService { caseReviewFollowerExample.createCriteria().andReviewIdEqualTo(id).andUserIdEqualTo(userId); return caseReviewFollowerMapper.countByExample(caseReviewFollowerExample) > 0; } + + public void batchMoveCaseReview(CaseReviewBatchRequest request, String userId) { + List ids; + if (request.isSelectAll()) { + ids = extCaseReviewMapper.getIds(request, request.getProjectId()); + if (CollectionUtils.isNotEmpty(request.getExcludeIds())) { + ids.removeAll(request.getExcludeIds()); + } + + } else { + ids = request.getSelectIds(); + } + if (CollectionUtils.isNotEmpty(ids)) { + extCaseReviewMapper.batchMoveModule(request, ids, userId); + } + } } \ No newline at end of file diff --git a/backend/services/case-management/src/test/java/io/metersphere/functional/controller/CaseReviewControllerTests.java b/backend/services/case-management/src/test/java/io/metersphere/functional/controller/CaseReviewControllerTests.java index 4f04a272b0..3c82148b1b 100644 --- a/backend/services/case-management/src/test/java/io/metersphere/functional/controller/CaseReviewControllerTests.java +++ b/backend/services/case-management/src/test/java/io/metersphere/functional/controller/CaseReviewControllerTests.java @@ -46,6 +46,8 @@ public class CaseReviewControllerTests extends BaseTest { private static final String projectId = "project-gyq-case-review-test"; private static final String ADD_CASE_REVIEW = "/case/review/add"; + private static final String COPY_CASE_REVIEW = "/case/review/copy"; + private static final String BATCH_MOVE_CASE_REVIEW = "/case/review/batch/move"; private static final String EDIT_CASE_REVIEW = "/case/review/edit"; private static final String PAGE_CASE_REVIEW = "/case/review/page"; private static final String ASSOCIATE_CASE_REVIEW = "/case/review/associate"; @@ -89,9 +91,15 @@ public class CaseReviewControllerTests extends BaseTest { NotificationExample notificationExample = new NotificationExample(); notificationExample.createCriteria().andResourceTypeEqualTo(NoticeConstants.TaskType.CASE_REVIEW_TASK); List notifications = notificationMapper.selectByExampleWithBLOBs(notificationExample); - System.out.println(JSON.toJSONString(notifications)); Assertions.assertEquals(1, notifications.size()); + caseReviewRequest = getCaseReviewAddRequest("创建评审1", CaseReviewPassRule.SINGLE.toString(), "CASE_REVIEW_TEST_GYQ_ID", false, true, null); + this.requestPostWithOk(COPY_CASE_REVIEW, caseReviewRequest); + caseReviews = getCaseReviews("创建评审1"); + Assertions.assertEquals(2, caseReviews.size()); + List list = caseReviews.stream().map(CaseReview::getId).distinct().toList(); + Assertions.assertEquals(2, list.size()); + } private List getCaseReviews(String name) { @@ -298,6 +306,18 @@ public class CaseReviewControllerTests extends BaseTest { userIds.add("gyq_review_test2"); caseReviewAssociateRequest.setReviewers(userIds); this.requestPost(ASSOCIATE_CASE_REVIEW, caseReviewAssociateRequest).andExpect(status().is5xxServerError()); + List caseReviews = getCaseReviews("创建评审更新1"); + caseReviewAssociateRequest = new CaseReviewAssociateRequest(); + caseReviewAssociateRequest.setProjectId(projectId); + caseReviewAssociateRequest.setReviewId(caseReviews.get(0).getId()); + caseIds = new ArrayList<>(); + caseIds.add("CASE_REVIEW_TEST_GYQ_XX"); + caseReviewAssociateRequest.setCaseIds(caseIds); + userIds = new ArrayList<>(); + userIds.add("gyq_review_test"); + userIds.add("gyq_review_test2"); + caseReviewAssociateRequest.setReviewers(userIds); + this.requestPostWithOk(ASSOCIATE_CASE_REVIEW, caseReviewAssociateRequest); } @Test @@ -444,6 +464,35 @@ public class CaseReviewControllerTests extends BaseTest { Assertions.assertNotNull(resultHolder); } + + @Test + @Order(15) + public void testBatchMove() throws Exception { + List caseReviews = getCaseReviews("创建评审更新1"); + String moduleId = caseReviews.get(0).getModuleId(); + CaseReviewBatchRequest request = new CaseReviewBatchRequest(); + request.setProjectId(projectId); + request.setModuleId("CASE_REVIEW_REAL_MODULE_ID2"); + request.setSelectAll(false); + this.requestPostWithOkAndReturn(BATCH_MOVE_CASE_REVIEW, request); + request.setSelectAll(true); + this.requestPostWithOkAndReturn(BATCH_MOVE_CASE_REVIEW, request); + caseReviews = getCaseReviews("创建评审更新1"); + String moduleIdNew = caseReviews.get(0).getModuleId(); + Assertions.assertFalse(StringUtils.equals(moduleId, moduleIdNew)); + request = new CaseReviewBatchRequest(); + request.setProjectId(projectId); + request.setModuleId("CASE_REVIEW_REAL_MODULE_ID2"); + request.setSelectAll(false); + request.setExcludeIds(List.of(caseReviews.get(0).getId())); + this.requestPostWithOkAndReturn(BATCH_MOVE_CASE_REVIEW, request); + caseReviews = getCaseReviews("创建评审更新1"); + String moduleIdNewOne = caseReviews.get(0).getModuleId(); + Assertions.assertTrue(StringUtils.equals(moduleIdNewOne, moduleIdNew)); + + + } + /** * 生成高级搜索参数 * diff --git a/backend/services/case-management/src/test/resources/dml/init_case_review.sql b/backend/services/case-management/src/test/resources/dml/init_case_review.sql index 4c16d9b6de..58ca072b4d 100644 --- a/backend/services/case-management/src/test/resources/dml/init_case_review.sql +++ b/backend/services/case-management/src/test/resources/dml/init_case_review.sql @@ -39,7 +39,10 @@ VALUES('gyq_custom_id_review2', 'level', 'FUNCTIONAL', 'SELECT', '', 1, 'ORGANIZ INSERT INTO functional_case_module(id, project_id, name, parent_id, pos, create_time, update_time, create_user, update_user) VALUES ('CASE_REVIEW_TEST_MODULE_ID', 'project-gyq-case-review-test', '测试用例评审所属模块', 'NONE', 0, 1669174143999, 1669174143999, 'admin', 'admin'); -INSERT INTO case_review_module(id, project_id, name, parent_id, pos, create_time, update_time, create_user, update_user) VALUES ('CASE_REVIEW_REAL_MODULE_ID', 'project-gyq-case-review-test', '用例评审所属模块', 'NONE', 0, 1669174143999, 1669174143999, 'admin', 'admin'); +INSERT INTO case_review_module(id, project_id, name, parent_id, pos, create_time, update_time, create_user, update_user) +VALUES ('CASE_REVIEW_REAL_MODULE_ID', 'project-gyq-case-review-test', '用例评审所属模块', 'NONE', 0, 1669174143999, 1669174143999, 'admin', 'admin'), + ('CASE_REVIEW_REAL_MODULE_ID2', 'project-gyq-case-review-test', '用例评审所属模块', 'NONE', 0, 1669174143999, 1669174143999, 'admin', 'admin'); + INSERT INTO user(id, name, email, password, create_time, update_time, language, last_organization_id, phone, source, last_project_id, create_user, update_user, deleted) 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 32037b6b47..c44134d59e 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.COPY , OperationLogType.RECOVER, OperationLogType.DISASSOCIATE,OperationLogType.ASSOCIATE, OperationLogType.ARCHIVED}; // 需要后置执行合并内容的 private final OperationLogType[] postMethodNames = new OperationLogType[]{OperationLogType.ADD, OperationLogType.UPDATE};