feat(用例评审): 新增用例评审列表拖拽排序和查看详情接口

This commit is contained in:
guoyuqi 2023-12-01 15:15:21 +08:00 committed by f2c-ci-robot[bot]
parent a554003902
commit 0549a16d2b
6 changed files with 164 additions and 30 deletions

View File

@ -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());
}
}

View File

@ -29,4 +29,7 @@ public class CaseReviewDTO extends CaseReview {
@Schema(description = "评审状态名称")
private String statusName;
@Schema(description = "关注标识")
private Boolean followFlag;
}

View File

@ -18,4 +18,8 @@ public interface ExtCaseReviewMapper {
List<CaseReviewDTO> 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);
}

View File

@ -293,4 +293,21 @@
</choose>
</sql>
<select id="getPrePos" resultType="java.lang.Long">
select `pos` from case_review where project_id = #{projectId}
<if test="basePos != null">
and `pos` &lt; #{basePos}
</if>
order by `pos` desc limit 1;
</select>
<select id="getLastPos" resultType="java.lang.Long">
select `pos` from case_review where project_id = #{projectId}
<if test="basePos != null">
and `pos` &gt; #{basePos}
</if>
order by `pos` desc limit 1;
</select>
</mapper>

View File

@ -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<String, List<CaseReviewFunctionalCase>> reviewCaseMap, Map<String, List<CaseReviewUserDTO>> reviewUserMap) {
List<CaseReviewFunctionalCase> caseReviewFunctionalCaseList = reviewCaseMap.get(caseReviewDTO.getId());
String caseReviewId = caseReviewDTO.getId();
List<CaseReviewFunctionalCase> 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<CaseReviewUserDTO> caseReviewUserDTOS = reviewUserMap.get(caseReviewDTO.getId());
List<String> 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<String, List<CaseReviewUserDTO>> reviewUserMap) {
List<CaseReviewUserDTO> caseReviewUserDTOS = reviewUserMap.get(caseReviewDTO.getId());
List<String> userNames = caseReviewUserDTOS.stream().map(CaseReviewUserDTO::getUserName).toList();
caseReviewDTO.setReviewers(userNames);
}
/**
* 构建用例相关的各种数量
* @param caseReviewDTO 用例评审
*
* @param caseReviewDTO 用例评审
* @param caseReviewFunctionalCaseList 用例和评审相关联的集合
*/
private static void buildAboutCaseCount(CaseReviewDTO caseReviewDTO, List<CaseReviewFunctionalCase> 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<String, List<CaseReviewFunctionalCase>> reviewCaseMap = getReviewCaseMap(List.of(id));
Map<String, List<CaseReviewUserDTO>> 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;
}
}

View File

@ -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<Notification> 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);
List<String>caseIds = new ArrayList<>();
List<String> 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);
List<String>userIds = new ArrayList<>();
List<String> 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");
List<String>caseIds = new ArrayList<>();
List<String> caseIds = new ArrayList<>();
caseIds.add("CASE_REVIEW_TEST_GYQ_ID2");
caseReviewAssociateRequest.setCaseIds(caseIds);
List<String>userIds = new ArrayList<>();
List<String> 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<String, Object> caseReviewCombine = buildRequestCombine();
CaseReviewPageRequest request = new CaseReviewPageRequest();
Map<String, List<String>> 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<CaseReviewFunctionalCase> caseReviewFunctionalCases = caseReviewFunctionalCaseMapper.selectByExample(caseReviewFunctionalCaseExample);
Map<String, CaseReviewFunctionalCase> 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<CaseReviewDTO> caseReviewDTOS = JSON.parseArray(JSON.toJSONString(pageData.getList()), CaseReviewDTO.class);
List<CaseReviewDTO> 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<CaseReview> caseReviews = getCaseReviews("创建评审更新1");
List<CaseReview> 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<CaseReview> 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<String, Object> buildRequestCombine() {