From 0549a16d2b6e95c57a729acfdb1969a5723db99b Mon Sep 17 00:00:00 2001 From: guoyuqi Date: Fri, 1 Dec 2023 15:15:21 +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=E7=94=A8=E4=BE=8B=E8=AF=84=E5=AE=A1=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E6=8B=96=E6=8B=BD=E6=8E=92=E5=BA=8F=E5=92=8C=E6=9F=A5?= =?UTF-8?q?=E7=9C=8B=E8=AF=A6=E6=83=85=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CaseReviewController.java | 15 ++++ .../functional/dto/CaseReviewDTO.java | 3 + .../mapper/ExtCaseReviewMapper.java | 4 + .../functional/mapper/ExtCaseReviewMapper.xml | 17 ++++ .../functional/service/CaseReviewService.java | 69 +++++++++++++-- .../controller/CaseReviewControllerTests.java | 86 ++++++++++++++----- 6 files changed, 164 insertions(+), 30 deletions(-) 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 c2a25635bb..5712bbe78b 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 @@ -13,6 +13,7 @@ import io.metersphere.functional.service.CaseReviewNoticeService; import io.metersphere.functional.service.CaseReviewService; import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.system.domain.User; +import io.metersphere.system.dto.sdk.request.PosRequest; import io.metersphere.system.log.annotation.Log; import io.metersphere.system.log.constants.OperationLogType; import io.metersphere.system.notice.annotation.SendNotice; @@ -90,4 +91,18 @@ public class CaseReviewController { return caseReviewService.getReviewUserList(projectId, keyword); } + @PostMapping("/edit/pos") + @Operation(summary = "用例管理-用例评审-拖拽排序") + @RequiresPermissions(PermissionConstants.CASE_REVIEW_READ_UPDATE) + public void editPos(@Validated @RequestBody PosRequest request) { + caseReviewService.editPos(request); + } + + @GetMapping("/detail/{id}") + @Operation(summary = "用例管理-用例评审-查看评审详情") + @RequiresPermissions(PermissionConstants.CASE_REVIEW_READ) + public CaseReviewDTO getCaseReviewDetail(@PathVariable String id) { + return caseReviewService.getCaseReviewDetail(id, SessionUtils.getUserId()); + } + } \ No newline at end of file diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/dto/CaseReviewDTO.java b/backend/services/case-management/src/main/java/io/metersphere/functional/dto/CaseReviewDTO.java index 54313a87b8..18f47b5d99 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/dto/CaseReviewDTO.java +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/dto/CaseReviewDTO.java @@ -29,4 +29,7 @@ public class CaseReviewDTO extends CaseReview { @Schema(description = "评审状态名称") private String statusName; + + @Schema(description = "关注标识") + private Boolean followFlag; } 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 f838438461..4eedf9db4d 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 @@ -18,4 +18,8 @@ public interface ExtCaseReviewMapper { List list(@Param("request") CaseReviewPageRequest request); + Long getPrePos(@Param("projectId") String projectId, @Param("basePos") Long basePos); + + Long getLastPos(@Param("projectId") String projectId, @Param("basePos") Long basePos); + } 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 45e9390f55..192e697e90 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 @@ -293,4 +293,21 @@ + + + + + \ No newline at end of file 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 84b3d521e6..d9b0b1f76c 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 @@ -14,11 +14,14 @@ import io.metersphere.functional.result.CaseManagementResultCode; import io.metersphere.sdk.constants.ApplicationNumScope; import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.sdk.exception.MSException; +import io.metersphere.sdk.util.BeanUtils; import io.metersphere.sdk.util.JSON; import io.metersphere.system.domain.User; +import io.metersphere.system.dto.sdk.request.PosRequest; import io.metersphere.system.mapper.ExtUserMapper; import io.metersphere.system.uid.IDGenerator; import io.metersphere.system.uid.NumGenerator; +import io.metersphere.system.utils.ServiceUtils; import jakarta.annotation.Resource; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -94,7 +97,8 @@ public class CaseReviewService { * @param reviewUserMap 评审和评审人的关系map */ private static void buildCaseReviewDTO(CaseReviewDTO caseReviewDTO, Map> reviewCaseMap, Map> reviewUserMap) { - List caseReviewFunctionalCaseList = reviewCaseMap.get(caseReviewDTO.getId()); + String caseReviewId = caseReviewDTO.getId(); + List caseReviewFunctionalCaseList = reviewCaseMap.get(caseReviewId); if (CollectionUtils.isEmpty(caseReviewFunctionalCaseList)) { caseReviewDTO.setPassCount(0); caseReviewDTO.setUnPassCount(0); @@ -105,16 +109,21 @@ public class CaseReviewService { buildAboutCaseCount(caseReviewDTO, caseReviewFunctionalCaseList); } - List caseReviewUserDTOS = reviewUserMap.get(caseReviewDTO.getId()); - List userNames = caseReviewUserDTOS.stream().map(CaseReviewUserDTO::getUserName).toList(); - caseReviewDTO.setReviewers(userNames); + buildReviewers(caseReviewDTO, reviewUserMap); caseReviewDTO.setStatusName(CaseReviewStatus.valueOf(caseReviewDTO.getStatus()).getName()); } + private static void buildReviewers(CaseReviewDTO caseReviewDTO, Map> reviewUserMap) { + List caseReviewUserDTOS = reviewUserMap.get(caseReviewDTO.getId()); + List userNames = caseReviewUserDTOS.stream().map(CaseReviewUserDTO::getUserName).toList(); + caseReviewDTO.setReviewers(userNames); + } + /** * 构建用例相关的各种数量 - * @param caseReviewDTO 用例评审 + * + * @param caseReviewDTO 用例评审 * @param caseReviewFunctionalCaseList 用例和评审相关联的集合 */ private static void buildAboutCaseCount(CaseReviewDTO caseReviewDTO, List caseReviewFunctionalCaseList) { @@ -402,8 +411,9 @@ public class CaseReviewService { /** * 关联用例 + * * @param request 页面参数 - * @param userId 当前操作人 + * @param userId 当前操作人 */ public void associateCase(CaseReviewAssociateRequest request, String userId) { String caseReviewId = request.getReviewId(); @@ -429,12 +439,55 @@ public class CaseReviewService { CaseReview caseReview = new CaseReview(); caseReview.setId(caseReviewId); //更新用例数量 - caseReview.setCaseCount(caseReviewExist.getCaseCount()+caseRealIds.size()); + caseReview.setCaseCount(caseReviewExist.getCaseCount() + caseRealIds.size()); //通过率 BigDecimal passCount = BigDecimal.valueOf(passList.size()); BigDecimal totalCount = BigDecimal.valueOf(caseReview.getCaseCount()); - BigDecimal passRate = passCount.divide(totalCount,2, RoundingMode.HALF_UP); + BigDecimal passRate = passCount.divide(totalCount, 2, RoundingMode.HALF_UP); caseReview.setPassRate(passRate); caseReviewMapper.updateByPrimaryKeySelective(caseReview); } + + /** + * 用例评审列表拖拽排序 + * @param request request + */ + public void editPos(PosRequest request) { + ServiceUtils.updatePosField(request, + CaseReview.class, + caseReviewMapper::selectByPrimaryKey, + extCaseReviewMapper::getPrePos, + extCaseReviewMapper::getLastPos, + caseReviewMapper::updateByPrimaryKeySelective); + } + + /** + * 获取用例评审详情 + * @param id 用例评审id + * @param userId 当前操作人 + * @return CaseReviewDTO + */ + public CaseReviewDTO getCaseReviewDetail(String id, String userId) { + CaseReview caseReview = checkCaseReview(id); + CaseReviewDTO caseReviewDTO = new CaseReviewDTO(); + BeanUtils.copyBean(caseReviewDTO, caseReview); + Boolean isFollow = checkFollow(id, userId); + caseReviewDTO.setFollowFlag(isFollow); + Map> reviewCaseMap = getReviewCaseMap(List.of(id)); + Map> reviewUserMap = getReviewUserMap(List.of(id)); + buildCaseReviewDTO(caseReviewDTO, reviewCaseMap, reviewUserMap); + return caseReviewDTO; + } + + /** + * 检查当前操作人是否关注该用例评审 + * @param id 评审人名称 + * @param userId 操作人 + * @return Boolean + */ + private Boolean checkFollow(String id, String userId) { + CaseReviewFollowerExample caseReviewFollowerExample = new CaseReviewFollowerExample(); + caseReviewFollowerExample.createCriteria().andReviewIdEqualTo(id).andUserIdEqualTo(userId); + return caseReviewFollowerMapper.countByExample(caseReviewFollowerExample) > 0; + } } \ 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 3ba9848a69..4f04a272b0 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 @@ -5,10 +5,8 @@ import io.metersphere.functional.constants.FunctionalCaseReviewStatus; import io.metersphere.functional.domain.*; import io.metersphere.functional.dto.CaseReviewDTO; import io.metersphere.functional.mapper.*; -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.result.CaseManagementResultCode; import io.metersphere.project.domain.Notification; import io.metersphere.project.domain.NotificationExample; import io.metersphere.project.mapper.NotificationMapper; @@ -16,6 +14,7 @@ import io.metersphere.sdk.util.JSON; import io.metersphere.system.base.BaseTest; import io.metersphere.system.controller.handler.ResultHolder; import io.metersphere.system.domain.User; +import io.metersphere.system.dto.sdk.request.PosRequest; import io.metersphere.system.notice.constants.NoticeConstants; import io.metersphere.system.utils.Pager; import jakarta.annotation.Resource; @@ -36,7 +35,7 @@ import java.util.stream.Collectors; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @AutoConfigureMockMvc @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class CaseReviewControllerTests extends BaseTest { @@ -50,9 +49,10 @@ public class CaseReviewControllerTests extends BaseTest { 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"; - + private static final String EDIT_POS_CASE_REVIEW_URL = "/case/review/edit/pos"; private static final String FOLLOW_CASE_REVIEW = "/case/review/edit/follower"; private static final String CASE_REVIEWER_LIST = "/case/review/user-option/"; + private static final String DETAIL_CASE_REVIEW = "/case/review/detail/"; @Resource @@ -183,14 +183,14 @@ public class CaseReviewControllerTests extends BaseTest { CaseReviewFollowerRequest caseReviewFollowerRequest = new CaseReviewFollowerRequest(); caseReviewFollowerRequest.setCaseReviewId(caseReview.getId()); caseReviewFollowerRequest.setUserId("admin"); - this.requestPostWithOk(FOLLOW_CASE_REVIEW,caseReviewFollowerRequest); + this.requestPostWithOk(FOLLOW_CASE_REVIEW, caseReviewFollowerRequest); CaseReviewFollowerExample example = new CaseReviewFollowerExample(); example.createCriteria().andReviewIdEqualTo(caseReview.getId()).andUserIdEqualTo("admin"); Assertions.assertTrue(caseReviewFollowerMapper.countByExample(example) > 0); caseReviewFollowerRequest = new CaseReviewFollowerRequest(); caseReviewFollowerRequest.setCaseReviewId(caseReview.getId()); caseReviewFollowerRequest.setUserId("admin"); - this.requestPostWithOk(FOLLOW_CASE_REVIEW,caseReviewFollowerRequest); + this.requestPostWithOk(FOLLOW_CASE_REVIEW, caseReviewFollowerRequest); example = new CaseReviewFollowerExample(); example.createCriteria().andReviewIdEqualTo(caseReview.getId()).andUserIdEqualTo("admin"); Assertions.assertEquals(0, caseReviewFollowerMapper.countByExample(example)); @@ -227,7 +227,7 @@ public class CaseReviewControllerTests extends BaseTest { notificationExample.createCriteria().andResourceTypeEqualTo(NoticeConstants.TaskType.CASE_REVIEW_TASK).andReceiverEqualTo("gyq_review_test2"); List notifications = notificationMapper.selectByExampleWithBLOBs(notificationExample); System.out.println(JSON.toJSONString(notifications)); - Assertions.assertTrue(notifications.size()>0); + Assertions.assertTrue(notifications.size() > 0); } @@ -259,14 +259,14 @@ public class CaseReviewControllerTests extends BaseTest { CaseReviewAssociateRequest caseReviewAssociateRequest = new CaseReviewAssociateRequest(); caseReviewAssociateRequest.setProjectId(projectId); caseReviewAssociateRequest.setReviewId(caseReviewId); - ListcaseIds = new ArrayList<>(); + List caseIds = new ArrayList<>(); caseIds.add("CASE_REVIEW_TEST_GYQ_ID2"); caseIds.add("CASE_REVIEW_TEST_GYQ_ID3"); caseIds.add("CASE_REVIEW_TEST_GYQ_ID4"); caseIds.add("CASE_REVIEW_TEST_GYQ_ID5"); caseIds.add("CASE_REVIEW_TEST_GYQ_ID6"); caseReviewAssociateRequest.setCaseIds(caseIds); - ListuserIds = new ArrayList<>(); + List userIds = new ArrayList<>(); userIds.add("gyq_review_test"); userIds.add("gyq_review_test2"); caseReviewAssociateRequest.setReviewers(userIds); @@ -290,10 +290,10 @@ public class CaseReviewControllerTests extends BaseTest { CaseReviewAssociateRequest caseReviewAssociateRequest = new CaseReviewAssociateRequest(); caseReviewAssociateRequest.setProjectId(projectId); caseReviewAssociateRequest.setReviewId("caseReviewIdXXXX"); - ListcaseIds = new ArrayList<>(); + List caseIds = new ArrayList<>(); caseIds.add("CASE_REVIEW_TEST_GYQ_ID2"); caseReviewAssociateRequest.setCaseIds(caseIds); - ListuserIds = new ArrayList<>(); + List userIds = new ArrayList<>(); userIds.add("gyq_review_test"); userIds.add("gyq_review_test2"); caseReviewAssociateRequest.setReviewers(userIds); @@ -308,7 +308,7 @@ public class CaseReviewControllerTests extends BaseTest { Map caseReviewCombine = buildRequestCombine(); CaseReviewPageRequest request = new CaseReviewPageRequest(); Map> filters = new HashMap<>(); - filters.put("status", Arrays.asList("PREPARED", "UNDERWAY","COMPLETED", "ARCHIVED")); + filters.put("status", Arrays.asList("PREPARED", "UNDERWAY", "COMPLETED", "ARCHIVED")); request.setFilter(filters); request.setCombine(caseReviewCombine); request.setProjectId(projectId); @@ -333,7 +333,7 @@ public class CaseReviewControllerTests extends BaseTest { caseReviewFunctionalCaseExample.createCriteria().andReviewIdEqualTo(caseReviews.get(0).getId()); List caseReviewFunctionalCases = caseReviewFunctionalCaseMapper.selectByExample(caseReviewFunctionalCaseExample); Map caseReviewFunctionalCaseMap = caseReviewFunctionalCases.stream().collect(Collectors.toMap(CaseReviewFunctionalCase::getCaseId, t -> t)); - caseReviewFunctionalCaseMap.forEach((k,v)->{ + caseReviewFunctionalCaseMap.forEach((k, v) -> { switch (k) { case "CASE_REVIEW_TEST_GYQ_ID2" -> v.setStatus(FunctionalCaseReviewStatus.RE_REVIEWED.toString()); case "CASE_REVIEW_TEST_GYQ_ID3" -> v.setStatus(FunctionalCaseReviewStatus.UNDER_REVIEWED.toString()); @@ -346,7 +346,7 @@ public class CaseReviewControllerTests extends BaseTest { request = new CaseReviewPageRequest(); filters = new HashMap<>(); - filters.put("status", Arrays.asList("PREPARED", "UNDERWAY","COMPLETED", "ARCHIVED")); + filters.put("status", Arrays.asList("PREPARED", "UNDERWAY", "COMPLETED", "ARCHIVED")); request.setFilter(filters); request.setCombine(caseReviewCombine); request.setProjectId(projectId); @@ -368,15 +368,15 @@ public class CaseReviewControllerTests extends BaseTest { Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(pageData.getList())).size() <= request.getPageSize()); List caseReviewDTOS = JSON.parseArray(JSON.toJSONString(pageData.getList()), CaseReviewDTO.class); List caseReviewOne = caseReviewDTOS.stream().filter(t -> StringUtils.equals(t.getName(), "创建评审更新1")).toList(); - Assertions.assertTrue(caseReviewOne.get(0).getPassCount()>0); - Assertions.assertTrue(caseReviewOne.get(0).getUnPassCount()>0); - Assertions.assertTrue(caseReviewOne.get(0).getUnderReviewedCount()>0); - Assertions.assertTrue(caseReviewOne.get(0).getReReviewedCount()>0); - Assertions.assertTrue(caseReviewOne.get(0).getReviewedCount()>0); + Assertions.assertTrue(caseReviewOne.get(0).getPassCount() > 0); + Assertions.assertTrue(caseReviewOne.get(0).getUnPassCount() > 0); + Assertions.assertTrue(caseReviewOne.get(0).getUnderReviewedCount() > 0); + Assertions.assertTrue(caseReviewOne.get(0).getReReviewedCount() > 0); + Assertions.assertTrue(caseReviewOne.get(0).getReviewedCount() > 0); request = new CaseReviewPageRequest(); filters = new HashMap<>(); - filters.put("status", Arrays.asList("UNDERWAY","COMPLETED", "ARCHIVED")); + filters.put("status", Arrays.asList("UNDERWAY", "COMPLETED", "ARCHIVED")); request.setFilter(filters); request.setCombine(caseReviewCombine); request.setProjectId(projectId); @@ -401,10 +401,52 @@ public class CaseReviewControllerTests extends BaseTest { } + @Test + @Order(13) + public void testPos() throws Exception { + List caseReviews = getCaseReviews("创建评审更新1"); + List caseReviews2 = getCaseReviews("创建评审更新2"); + Long pos = caseReviews.get(0).getPos(); + Long pos2 = caseReviews2.get(0).getPos(); + PosRequest posRequest = new PosRequest(); + posRequest.setProjectId(projectId); + posRequest.setTargetId(caseReviews.get(0).getId()); + posRequest.setMoveId(caseReviews2.get(0).getId()); + posRequest.setMoveMode("AFTER"); + this.requestPostWithOkAndReturn(EDIT_POS_CASE_REVIEW_URL, posRequest); + caseReviews = getCaseReviews("创建评审更新1"); + caseReviews2 = getCaseReviews("创建评审更新2"); + Long pos3 = caseReviews.get(0).getPos(); + Long pos4 = caseReviews2.get(0).getPos(); + Assertions.assertTrue(Objects.equals(pos, pos3)); + Assertions.assertTrue(pos2 > pos4); + posRequest.setMoveMode("BEFORE"); + this.requestPostWithOkAndReturn(EDIT_POS_CASE_REVIEW_URL, posRequest); + caseReviews = getCaseReviews("创建评审更新1"); + caseReviews2 = getCaseReviews("创建评审更新2"); + Long pos5 = caseReviews.get(0).getPos(); + Long pos6 = caseReviews2.get(0).getPos(); + Assertions.assertTrue(Objects.equals(pos5, pos3)); + Assertions.assertTrue(pos6 > pos4); + } + @Test + @Order(14) + public void testFunctionalCaseDetail() throws Exception { + List caseReviews = getCaseReviews("创建评审更新1"); + String id = caseReviews.get(0).getId(); + assertErrorCode(this.requestGet(DETAIL_CASE_REVIEW + "ERROR_TEST_FUNCTIONAL_CASE_ID"), CaseManagementResultCode.CASE_REVIEW_NOT_FOUND); + MvcResult mvcResult = this.requestGetWithOkAndReturn(DETAIL_CASE_REVIEW + id); + // 获取返回值 + String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8); + ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class); + // 返回请求正常 + Assertions.assertNotNull(resultHolder); + } /** * 生成高级搜索参数 + * * @return combine param */ private Map buildRequestCombine() {