feat(用例评审): 关联用例弹窗&评审详情展示关联用例列表接口
This commit is contained in:
parent
f933967063
commit
faa17a3843
|
@ -0,0 +1,50 @@
|
||||||
|
package io.metersphere.functional.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import com.alibaba.excel.util.StringUtils;
|
||||||
|
import com.github.pagehelper.Page;
|
||||||
|
import com.github.pagehelper.PageHelper;
|
||||||
|
import io.metersphere.functional.dto.ReviewFunctionalCaseDTO;
|
||||||
|
import io.metersphere.functional.request.ReviewFunctionalCasePageRequest;
|
||||||
|
import io.metersphere.functional.service.CaseReviewFunctionalCaseService;
|
||||||
|
import io.metersphere.system.utils.PageUtils;
|
||||||
|
import io.metersphere.system.utils.Pager;
|
||||||
|
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.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author wx
|
||||||
|
*/
|
||||||
|
@Tag(name = "用例管理-用例评审-评审列表-评审详情")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/case/review/detail")
|
||||||
|
public class CaseReviewFunctionalCaseController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CaseReviewFunctionalCaseService caseReviewFunctionalCaseService;
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("/get-ids/{reviewId}")
|
||||||
|
@Operation(summary = "用例管理-功能用例-评审列表-评审详情-获取已关联用例id集合(关联用例弹窗前调用)")
|
||||||
|
public List<String> getCaseIds(@PathVariable String reviewId) {
|
||||||
|
return caseReviewFunctionalCaseService.getCaseIdsByReviewId(reviewId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping("/page")
|
||||||
|
@Operation(summary = "用例管理-功能用例-评审列表-评审详情-已关联用例列表")
|
||||||
|
public Pager<List<ReviewFunctionalCaseDTO>> page(@Validated @RequestBody ReviewFunctionalCasePageRequest request) {
|
||||||
|
String userId = StringUtils.EMPTY;
|
||||||
|
if (request.getViewFlag()) {
|
||||||
|
userId = SessionUtils.getUserId();
|
||||||
|
}
|
||||||
|
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize());
|
||||||
|
return PageUtils.setPageInfo(page, caseReviewFunctionalCaseService.page(request, false, userId));
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,10 +11,12 @@ import io.metersphere.project.dto.filemanagement.request.FileMetadataTableReques
|
||||||
import io.metersphere.project.dto.filemanagement.response.FileInformationResponse;
|
import io.metersphere.project.dto.filemanagement.response.FileInformationResponse;
|
||||||
import io.metersphere.project.service.FileAssociationService;
|
import io.metersphere.project.service.FileAssociationService;
|
||||||
import io.metersphere.project.service.FileMetadataService;
|
import io.metersphere.project.service.FileMetadataService;
|
||||||
|
import io.metersphere.project.service.FileModuleService;
|
||||||
import io.metersphere.sdk.constants.PermissionConstants;
|
import io.metersphere.sdk.constants.PermissionConstants;
|
||||||
import io.metersphere.sdk.exception.MSException;
|
import io.metersphere.sdk.exception.MSException;
|
||||||
import io.metersphere.sdk.util.FileAssociationSourceUtil;
|
import io.metersphere.sdk.util.FileAssociationSourceUtil;
|
||||||
import io.metersphere.sdk.util.Translator;
|
import io.metersphere.sdk.util.Translator;
|
||||||
|
import io.metersphere.system.dto.sdk.BaseTreeNode;
|
||||||
import io.metersphere.system.log.constants.OperationLogModule;
|
import io.metersphere.system.log.constants.OperationLogModule;
|
||||||
import io.metersphere.system.utils.Pager;
|
import io.metersphere.system.utils.Pager;
|
||||||
import io.metersphere.system.utils.SessionUtils;
|
import io.metersphere.system.utils.SessionUtils;
|
||||||
|
@ -46,6 +48,8 @@ public class FunctionalCaseAttachmentController {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private FileAssociationService fileAssociationService;
|
private FileAssociationService fileAssociationService;
|
||||||
|
@Resource
|
||||||
|
private FileModuleService fileModuleService;
|
||||||
|
|
||||||
|
|
||||||
@PostMapping("/page")
|
@PostMapping("/page")
|
||||||
|
@ -120,6 +124,7 @@ public class FunctionalCaseAttachmentController {
|
||||||
String fileId = null;
|
String fileId = null;
|
||||||
try {
|
try {
|
||||||
FileAssociationDTO fileAssociationDTO = new FileAssociationDTO(attachment.getFileName(), fileByte, attachment.getCaseId(), FileAssociationSourceUtil.SOURCE_TYPE_FUNCTIONAL_CASE, fileLogRecord);
|
FileAssociationDTO fileAssociationDTO = new FileAssociationDTO(attachment.getFileName(), fileByte, attachment.getCaseId(), FileAssociationSourceUtil.SOURCE_TYPE_FUNCTIONAL_CASE, fileLogRecord);
|
||||||
|
fileAssociationDTO.setModuleId(request.getModuleId());
|
||||||
fileId = fileAssociationService.transferAndAssociation(fileAssociationDTO);
|
fileId = fileAssociationService.transferAndAssociation(fileAssociationDTO);
|
||||||
functionalCaseAttachmentService.deleteCaseAttachment(Arrays.asList(request.getFileId()), request.getCaseId(), request.getProjectId());
|
functionalCaseAttachmentService.deleteCaseAttachment(Arrays.asList(request.getFileId()), request.getCaseId(), request.getProjectId());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -146,4 +151,13 @@ public class FunctionalCaseAttachmentController {
|
||||||
functionalCaseAttachmentService.deleteFile(request, userId);
|
functionalCaseAttachmentService.deleteFile(request, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("/options/{projectId}")
|
||||||
|
@Operation(summary = "用例管理-功能用例-附件-转存目录下拉框")
|
||||||
|
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ)
|
||||||
|
public List<BaseTreeNode> options(@PathVariable String projectId) {
|
||||||
|
return fileModuleService.getTree(projectId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
package io.metersphere.functional.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author wx
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ReviewFunctionalCaseDTO implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "用例id")
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@Schema(description = "用例名称")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Schema(description = "版本id")
|
||||||
|
private String versionId;
|
||||||
|
|
||||||
|
@Schema(description = "版本名称")
|
||||||
|
private String versionName;
|
||||||
|
|
||||||
|
@Schema(description = "评审人")
|
||||||
|
private List<String> reviewers;
|
||||||
|
|
||||||
|
@Schema(description = "评审人名称")
|
||||||
|
private List<String> reviewNames;
|
||||||
|
|
||||||
|
@Schema(description = "评审状态")
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
@Schema(description = "所属模块")
|
||||||
|
private String moduleId;
|
||||||
|
|
||||||
|
@Schema(description = "模块名称")
|
||||||
|
private String moduleName;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package io.metersphere.functional.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author wx
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ReviewsDTO implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "用例id")
|
||||||
|
private String caseId;
|
||||||
|
|
||||||
|
@Schema(description = "用例评审人id字符串集合")
|
||||||
|
private String userIds;
|
||||||
|
|
||||||
|
@Schema(description = "用例评审人名称字符集合")
|
||||||
|
private String userNames;
|
||||||
|
|
||||||
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
package io.metersphere.functional.mapper;
|
package io.metersphere.functional.mapper;
|
||||||
|
|
||||||
import io.metersphere.functional.dto.FunctionalCaseReviewDTO;
|
import io.metersphere.functional.dto.FunctionalCaseReviewDTO;
|
||||||
|
import io.metersphere.functional.dto.ReviewFunctionalCaseDTO;
|
||||||
import io.metersphere.functional.request.FunctionalCaseReviewListRequest;
|
import io.metersphere.functional.request.FunctionalCaseReviewListRequest;
|
||||||
|
import io.metersphere.functional.request.ReviewFunctionalCasePageRequest;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -16,4 +18,8 @@ public interface ExtCaseReviewFunctionalCaseMapper {
|
||||||
void updateStatus(@Param("caseId") String caseId, @Param("reviewId") String reviewId, @Param("status") String status);
|
void updateStatus(@Param("caseId") String caseId, @Param("reviewId") String reviewId, @Param("status") String status);
|
||||||
|
|
||||||
Long getUnCompletedCaseCount(@Param("reviewId") String reviewId, @Param("statusList") List<String> statusList);
|
Long getUnCompletedCaseCount(@Param("reviewId") String reviewId, @Param("statusList") List<String> statusList);
|
||||||
|
|
||||||
|
List<String> getCaseIdsByReviewId(@Param("reviewId") String reviewId);
|
||||||
|
|
||||||
|
List<ReviewFunctionalCaseDTO> page(@Param("request") ReviewFunctionalCasePageRequest request, @Param("deleted") boolean deleted, @Param("userId") String userId, @Param("sort") String sort);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,4 +35,189 @@
|
||||||
where review_id = #{reviewId} and case_id = #{caseId}
|
where review_id = #{reviewId} and case_id = #{caseId}
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
|
|
||||||
|
<select id="getCaseIdsByReviewId" parameterType="java.lang.String" resultType="java.lang.String">
|
||||||
|
select case_id from case_review_functional_case where review_id = #{reviewId}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="page" resultType="io.metersphere.functional.dto.ReviewFunctionalCaseDTO">
|
||||||
|
SELECT
|
||||||
|
crfc.id as id,
|
||||||
|
crfc.review_id as reviewId,
|
||||||
|
crfc.case_id as caseId,
|
||||||
|
crfc.`status` as status,
|
||||||
|
crfc.create_time as createTime,
|
||||||
|
functional_case.version_id as versionId,
|
||||||
|
functional_case.module_id as moduleId,
|
||||||
|
functional_case.name as name
|
||||||
|
FROM
|
||||||
|
case_review_functional_case crfc
|
||||||
|
LEFT JOIN functional_case ON crfc.case_id = functional_case.id
|
||||||
|
WHERE
|
||||||
|
review_id = #{request.reviewId}
|
||||||
|
AND functional_case.deleted = #{deleted}
|
||||||
|
<if test="userId != null and userId != ''">
|
||||||
|
AND crfc.case_id in (select case_id from case_review_functional_case_user crfcu where crfcu.review_id = #{request.reviewId} and crfcu.user_id = #{userId})
|
||||||
|
</if>
|
||||||
|
<choose>
|
||||||
|
<when test='request.searchMode == "AND"'>
|
||||||
|
AND <include refid="queryWhereCondition"/>
|
||||||
|
</when>
|
||||||
|
<when test='request.searchMode == "OR"'>
|
||||||
|
and (
|
||||||
|
<include refid="queryWhereCondition"/>
|
||||||
|
)
|
||||||
|
</when>
|
||||||
|
</choose>
|
||||||
|
order by
|
||||||
|
<if test="sort != null and sort != ''">
|
||||||
|
crfc.${sort}
|
||||||
|
</if>
|
||||||
|
<if test="sort == null or sort == ''">
|
||||||
|
crfc.pos desc
|
||||||
|
</if>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<sql id="queryWhereCondition">
|
||||||
|
<if test="request.keyword != null">
|
||||||
|
(
|
||||||
|
functional_case.name like concat('%', #{request.keyword},'%')
|
||||||
|
or functional_case.num like concat('%', #{request.keyword},'%')
|
||||||
|
or JSON_CONTAINS(tags, concat('["',#{request.keyword},'"]'))
|
||||||
|
)
|
||||||
|
<include refid="queryType">
|
||||||
|
<property name="searchMode" value="request.searchMode"/>
|
||||||
|
</include>
|
||||||
|
</if>
|
||||||
|
<include refid="filters">
|
||||||
|
<property name="filter" value="request.filter"/>
|
||||||
|
</include>
|
||||||
|
<include refid="combine">
|
||||||
|
<property name="condition" value="request.combine"/>
|
||||||
|
</include>
|
||||||
|
1=1
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
|
||||||
|
<sql id="filters">
|
||||||
|
<if test="${filter} != null and ${filter}.size() > 0">
|
||||||
|
<foreach collection="${filter}.entrySet()" index="key" item="values">
|
||||||
|
<if test="values != null and values.size() > 0">
|
||||||
|
<choose>
|
||||||
|
<when test="key=='review_status'">
|
||||||
|
case_review_functional_case.review_status in
|
||||||
|
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
|
||||||
|
<include refid="queryType">
|
||||||
|
<property name="searchMode" value="request.searchMode"/>
|
||||||
|
</include>
|
||||||
|
</when>
|
||||||
|
<when test="key=='last_execute_result'">
|
||||||
|
functional_case.last_execute_result in
|
||||||
|
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
|
||||||
|
<include refid="queryType">
|
||||||
|
<property name="searchMode" value="request.searchMode"/>
|
||||||
|
</include>
|
||||||
|
</when>
|
||||||
|
<when test="key=='version_id'">
|
||||||
|
functional_case.version_id in
|
||||||
|
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
|
||||||
|
<include refid="queryType">
|
||||||
|
<property name="searchMode" value="request.searchMode"/>
|
||||||
|
</include>
|
||||||
|
</when>
|
||||||
|
<when test="key.startsWith('custom_single')">
|
||||||
|
test_case.id in (
|
||||||
|
select resource_id from custom_field_test_case where concat('custom_single-',field_id) =
|
||||||
|
#{key}
|
||||||
|
and trim(both '"' from `value`) in
|
||||||
|
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
|
||||||
|
)
|
||||||
|
<include refid="queryType">
|
||||||
|
<property name="searchMode" value="request.searchMode"/>
|
||||||
|
</include>
|
||||||
|
</when>
|
||||||
|
<when test="key.startsWith('custom_multiple')">
|
||||||
|
test_case.id in (
|
||||||
|
select resource_id from custom_field_test_case where concat('custom_multiple-',field_id) =
|
||||||
|
#{key}
|
||||||
|
and JSON_CONTAINS(`value`, json_array(#{value}))
|
||||||
|
<include refid="queryType">
|
||||||
|
<property name="searchMode" value="request.searchMode"/>
|
||||||
|
</include>
|
||||||
|
</when>
|
||||||
|
<when test="key=='create_user'">
|
||||||
|
functional_case.create_user in
|
||||||
|
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
|
||||||
|
<include refid="queryType">
|
||||||
|
<property name="searchMode" value="request.searchMode"/>
|
||||||
|
</include>
|
||||||
|
</when>
|
||||||
|
</choose>
|
||||||
|
</if>
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<sql id="combine">
|
||||||
|
<if test="request.combine != null">
|
||||||
|
<if test='${condition}.name != null'>
|
||||||
|
functional_case.name
|
||||||
|
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
|
||||||
|
<property name="object" value="${condition}.name"/>
|
||||||
|
</include>
|
||||||
|
<include refid="queryType">
|
||||||
|
<property name="searchMode" value="request.searchMode"/>
|
||||||
|
</include>
|
||||||
|
</if>
|
||||||
|
<if test='${condition}.id != null'>
|
||||||
|
functional_case.num
|
||||||
|
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
|
||||||
|
<property name="object" value="${condition}.id"/>
|
||||||
|
</include>
|
||||||
|
<include refid="queryType">
|
||||||
|
<property name="searchMode" value="request.searchMode"/>
|
||||||
|
</include>
|
||||||
|
</if>
|
||||||
|
<if test="${condition}.customs != null and ${condition}.customs.size() > 0">
|
||||||
|
<foreach collection="${condition}.customs" item="custom" separator="" open="" close="">
|
||||||
|
functional_case.id ${custom.operator} (
|
||||||
|
select case_id from functional_case_custom_field where field_id = #{custom.id}
|
||||||
|
<choose>
|
||||||
|
<when test="custom.type == 'List'">
|
||||||
|
and JSON_CONTAINS(`value`, json_array(#{custom.value}))
|
||||||
|
</when>
|
||||||
|
<when test="custom.type == 'date' or custom.type == 'datetime'">
|
||||||
|
and `value`
|
||||||
|
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
|
||||||
|
<property name="object" value="custom"/>
|
||||||
|
</include>
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
and trim(both '"' from `value`)
|
||||||
|
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
|
||||||
|
<property name="object" value="custom"/>
|
||||||
|
</include>
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
)
|
||||||
|
<include refid="queryType">
|
||||||
|
<property name="searchMode" value="request.searchMode"/>
|
||||||
|
</include>
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
|
</if>
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<sql id="queryType">
|
||||||
|
<choose>
|
||||||
|
<when test='${searchMode} == "AND"'>
|
||||||
|
AND
|
||||||
|
</when>
|
||||||
|
<when test='${searchMode} == "OR"'>
|
||||||
|
OR
|
||||||
|
</when>
|
||||||
|
</choose>
|
||||||
|
</sql>
|
||||||
</mapper>
|
</mapper>
|
|
@ -0,0 +1,13 @@
|
||||||
|
package io.metersphere.functional.mapper;
|
||||||
|
|
||||||
|
import io.metersphere.functional.dto.ReviewsDTO;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author wx
|
||||||
|
*/
|
||||||
|
public interface ExtCaseReviewFunctionalCaseUserMapper {
|
||||||
|
List<ReviewsDTO> selectReviewers(@Param("ids") List<String> ids, @Param("reviewId") String reviewId);
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="io.metersphere.functional.mapper.ExtCaseReviewFunctionalCaseUserMapper">
|
||||||
|
|
||||||
|
<select id="selectReviewers" resultType="io.metersphere.functional.dto.ReviewsDTO">
|
||||||
|
SELECT
|
||||||
|
case_id,
|
||||||
|
GROUP_CONCAT( user_id ),
|
||||||
|
GROUP_CONCAT( `user`.NAME )
|
||||||
|
FROM
|
||||||
|
case_review_functional_case_user crfcu
|
||||||
|
LEFT JOIN `user` ON crfcu.user_id = `user`.id
|
||||||
|
WHERE
|
||||||
|
crfcu.review_id = #{reviewId}
|
||||||
|
AND crfcu.case_id IN
|
||||||
|
<foreach collection="ids" item="id" open="(" separator="," close=")">
|
||||||
|
#{id}
|
||||||
|
</foreach>
|
||||||
|
GROUP BY
|
||||||
|
crfcu.case_id
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
|
@ -95,7 +95,12 @@
|
||||||
)
|
)
|
||||||
</when>
|
</when>
|
||||||
</choose>
|
</choose>
|
||||||
|
<if test="request.excludeIds != null and request.excludeIds.size() > 0">
|
||||||
|
AND functional_case.id not in
|
||||||
|
<foreach collection="request.excludeIds" item="excludeId" separator="," open="(" close=")">
|
||||||
|
#{excludeId}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<update id="recoverCase">
|
<update id="recoverCase">
|
||||||
|
|
|
@ -27,4 +27,7 @@ public class FunctionalCaseFileRequest implements Serializable {
|
||||||
@Schema(description = "是否本地",requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "是否本地",requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private Boolean local;
|
private Boolean local;
|
||||||
|
|
||||||
|
@Schema(description = "转存的模块id",requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private String moduleId;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,4 +41,7 @@ public class FunctionalCasePageRequest extends BasePageRequest implements Serial
|
||||||
@Schema(description = "关联缺陷")
|
@Schema(description = "关联缺陷")
|
||||||
private AssociationDTO associationBug;
|
private AssociationDTO associationBug;
|
||||||
|
|
||||||
|
@Schema(description = "排除ids")
|
||||||
|
private List<String> excludeIds;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package io.metersphere.functional.request;
|
||||||
|
|
||||||
|
import io.metersphere.system.dto.sdk.BasePageRequest;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author wx
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ReviewFunctionalCasePageRequest extends BasePageRequest implements Serializable {
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "评审id", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private String reviewId;
|
||||||
|
|
||||||
|
|
||||||
|
@Schema(description = "是否只看我的", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private Boolean viewFlag;
|
||||||
|
}
|
|
@ -1,7 +1,24 @@
|
||||||
package io.metersphere.functional.service;
|
package io.metersphere.functional.service;
|
||||||
|
|
||||||
|
|
||||||
|
import io.metersphere.functional.dto.ReviewFunctionalCaseDTO;
|
||||||
|
import io.metersphere.functional.dto.ReviewsDTO;
|
||||||
|
import io.metersphere.functional.mapper.ExtCaseReviewFunctionalCaseMapper;
|
||||||
|
import io.metersphere.functional.mapper.ExtCaseReviewFunctionalCaseUserMapper;
|
||||||
|
import io.metersphere.functional.mapper.ExtFunctionalCaseModuleMapper;
|
||||||
|
import io.metersphere.functional.request.ReviewFunctionalCasePageRequest;
|
||||||
|
import io.metersphere.project.domain.ProjectVersion;
|
||||||
|
import io.metersphere.project.mapper.ExtBaseProjectVersionMapper;
|
||||||
|
import io.metersphere.system.dto.sdk.BaseTreeNode;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用例评审和功能用例的中间表服务实现类
|
* 用例评审和功能用例的中间表服务实现类
|
||||||
|
@ -9,6 +26,63 @@ import org.springframework.stereotype.Service;
|
||||||
* @date : 2023-5-17
|
* @date : 2023-5-17
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public class CaseReviewFunctionalCaseService {
|
public class CaseReviewFunctionalCaseService {
|
||||||
|
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ExtCaseReviewFunctionalCaseMapper extCaseReviewFunctionalCaseMapper;
|
||||||
|
@Resource
|
||||||
|
private ExtFunctionalCaseModuleMapper extFunctionalCaseModuleMapper;
|
||||||
|
@Resource
|
||||||
|
private ExtBaseProjectVersionMapper extBaseProjectVersionMapper;
|
||||||
|
@Resource
|
||||||
|
private ExtCaseReviewFunctionalCaseUserMapper extCaseReviewFunctionalCaseUserMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过评审id获取关联的用例id集合
|
||||||
|
*
|
||||||
|
* @param reviewId reviewId
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public List<String> getCaseIdsByReviewId(String reviewId) {
|
||||||
|
return extCaseReviewFunctionalCaseMapper.getCaseIdsByReviewId(reviewId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 评审详情分页列表查询
|
||||||
|
*
|
||||||
|
* @param request request
|
||||||
|
* @param deleted deleted
|
||||||
|
* @return ReviewFunctionalCaseDTO
|
||||||
|
*/
|
||||||
|
public List<ReviewFunctionalCaseDTO> page(ReviewFunctionalCasePageRequest request, boolean deleted, String userId) {
|
||||||
|
List<ReviewFunctionalCaseDTO> list = extCaseReviewFunctionalCaseMapper.page(request, deleted, userId, request.getSortString());
|
||||||
|
return doHandleDTO(list, request.getReviewId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ReviewFunctionalCaseDTO> doHandleDTO(List<ReviewFunctionalCaseDTO> list, String reviewId) {
|
||||||
|
if (CollectionUtils.isNotEmpty(list)) {
|
||||||
|
List<String> ids = list.stream().map(ReviewFunctionalCaseDTO::getId).toList();
|
||||||
|
List<BaseTreeNode> modules = extFunctionalCaseModuleMapper.selectBaseByIds(ids);
|
||||||
|
Map<String, String> moduleMap = modules.stream().collect(Collectors.toMap(BaseTreeNode::getId, BaseTreeNode::getName));
|
||||||
|
|
||||||
|
List<String> versionIds = list.stream().map(ReviewFunctionalCaseDTO::getVersionId).toList();
|
||||||
|
List<ProjectVersion> versions = extBaseProjectVersionMapper.getVersionByIds(versionIds);
|
||||||
|
Map<String, String> versionMap = versions.stream().collect(Collectors.toMap(ProjectVersion::getId, ProjectVersion::getName));
|
||||||
|
|
||||||
|
List<ReviewsDTO> reviewers = extCaseReviewFunctionalCaseUserMapper.selectReviewers(ids, reviewId);
|
||||||
|
Map<String, String> userIdMap = reviewers.stream().collect(Collectors.toMap(ReviewsDTO::getCaseId, ReviewsDTO::getUserIds));
|
||||||
|
Map<String, String> userNameMap = reviewers.stream().collect(Collectors.toMap(ReviewsDTO::getCaseId, ReviewsDTO::getUserNames));
|
||||||
|
|
||||||
|
list.forEach(item -> {
|
||||||
|
item.setModuleName(moduleMap.get(item.getModuleId()));
|
||||||
|
item.setVersionName(versionMap.get(item.getVersionId()));
|
||||||
|
item.setReviewers(Arrays.asList(userIdMap.get(item.getId())));
|
||||||
|
item.setReviewNames(Arrays.asList(userNameMap.get(item.getId())));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
package io.metersphere.functional.controller;
|
||||||
|
|
||||||
|
import io.metersphere.functional.request.FunctionalCasePageRequest;
|
||||||
|
import io.metersphere.functional.request.ReviewFunctionalCasePageRequest;
|
||||||
|
import io.metersphere.system.base.BaseTest;
|
||||||
|
import org.junit.jupiter.api.MethodOrderer;
|
||||||
|
import org.junit.jupiter.api.Order;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.TestMethodOrder;
|
||||||
|
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.context.jdbc.Sql;
|
||||||
|
import org.springframework.test.context.jdbc.SqlConfig;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||||
|
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||||
|
@AutoConfigureMockMvc
|
||||||
|
public class CaseReviewFunctionalCaseControllerTests extends BaseTest {
|
||||||
|
|
||||||
|
public static final String GET_CASE_IDS = "/case/review/detail/get-ids/";
|
||||||
|
public static final String FUNCTIONAL_CASE_LIST_URL = "/functional/case/page";
|
||||||
|
|
||||||
|
public static final String REVIEW_CASE_PAGE = "/case/review/detail/page";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(1)
|
||||||
|
public void testGetCaseIds() throws Exception {
|
||||||
|
this.requestGet(GET_CASE_IDS + "test_review_id");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(2)
|
||||||
|
public void testPage() throws Exception {
|
||||||
|
FunctionalCasePageRequest request = new FunctionalCasePageRequest();
|
||||||
|
request.setProjectId("100001100001");
|
||||||
|
request.setCurrent(1);
|
||||||
|
request.setPageSize(10);
|
||||||
|
request.setExcludeIds(Arrays.asList("TEST_FUNCTIONAL_CASE_ID_1"));
|
||||||
|
Map<String, Object> map = new HashMap<>();
|
||||||
|
map.put("customs", Arrays.asList(new LinkedHashMap() {{
|
||||||
|
put("id", "TEST_FIELD_ID");
|
||||||
|
put("operator", "in");
|
||||||
|
put("value", "222");
|
||||||
|
put("type", "List");
|
||||||
|
}}));
|
||||||
|
request.setCombine(map);
|
||||||
|
this.requestPost(FUNCTIONAL_CASE_LIST_URL, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(3)
|
||||||
|
@Sql(scripts = {"/dml/init_review_functional_case_test.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED))
|
||||||
|
public void testReviewCasePage() throws Exception {
|
||||||
|
ReviewFunctionalCasePageRequest request = new ReviewFunctionalCasePageRequest();
|
||||||
|
request.setReviewId("wx_review_id_1");
|
||||||
|
request.setCurrent(1);
|
||||||
|
request.setPageSize(10);
|
||||||
|
Map<String, Object> map = new HashMap<>();
|
||||||
|
map.put("customs", Arrays.asList(new LinkedHashMap() {{
|
||||||
|
put("id", "TEST_FIELD_ID");
|
||||||
|
put("operator", "in");
|
||||||
|
put("value", "222");
|
||||||
|
put("type", "List");
|
||||||
|
}}));
|
||||||
|
request.setCombine(map);
|
||||||
|
request.setViewFlag(false);
|
||||||
|
this.requestPostWithOkAndReturn(REVIEW_CASE_PAGE, request);
|
||||||
|
|
||||||
|
request.setSort(new HashMap<>() {{
|
||||||
|
put("createTime", "desc");
|
||||||
|
}});
|
||||||
|
this.requestPostWithOkAndReturn(REVIEW_CASE_PAGE, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -14,7 +14,7 @@ import org.springframework.test.context.jdbc.SqlConfig;
|
||||||
@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
|
@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||||
@AutoConfigureMockMvc
|
@AutoConfigureMockMvc
|
||||||
public class CleanupFunctionalCaseResourceTest {
|
public class CleanupFunctionalCaseResourceTests {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private CleanupFunctionalCaseResourceService cleanupFunctionalCaseResourceService;
|
private CleanupFunctionalCaseResourceService cleanupFunctionalCaseResourceService;
|
|
@ -55,6 +55,7 @@ public class FunctionalCaseAttachmentControllerTests extends BaseTest {
|
||||||
public static final String ATTACHMENT_TRANSFER_URL = "/attachment/transfer";
|
public static final String ATTACHMENT_TRANSFER_URL = "/attachment/transfer";
|
||||||
public static final String UPLOAD_FILE_URL = "/attachment/upload/file";
|
public static final String UPLOAD_FILE_URL = "/attachment/upload/file";
|
||||||
public static final String DELETE_FILE_URL = "/attachment/delete/file";
|
public static final String DELETE_FILE_URL = "/attachment/delete/file";
|
||||||
|
public static final String OPTIONS_URL = "/attachment/options/";
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -216,4 +217,11 @@ public class FunctionalCaseAttachmentControllerTests extends BaseTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(9)
|
||||||
|
public void testOptions() throws Exception {
|
||||||
|
//覆盖controller方法
|
||||||
|
this.requestGet(OPTIONS_URL + DEFAULT_PROJECT_ID);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
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 ('wx_case_id_1', 100, 'TEST_MODULE_ID', 'wx_test_project', '100001', '测试', 'UN_REVIEWED', NULL, 'STEP', 0, 'v1.0.0', 'v1.0.0', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 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 ('wx_case_id_2', 101, 'TEST_MODULE_ID', 'wx_test_project', '100001', '测试多版本', 'UN_REVIEWED', '["测试标签_1"]', 'STEP', 0, 'v1.0.0', 'TEST_REF_ID', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL);
|
||||||
|
|
||||||
|
INSERT INTO functional_case_blob(id, steps, text_description, expected_result, prerequisite, description) VALUES ('wx_case_id_1', 'STEP', '1111', '', '', 'TEST');
|
||||||
|
INSERT INTO functional_case_blob(id, steps, text_description, expected_result, prerequisite, description) VALUES ('wx_case_id_2', 'STEP', '1111', '', '', '1111');
|
||||||
|
|
||||||
|
|
||||||
|
INSERT INTO functional_case_custom_field(case_id, field_id, value) VALUES ('wx_case_id_1', '100548878725546079', '22');
|
||||||
|
INSERT INTO functional_case_custom_field(case_id, field_id, value) VALUES ('wx_case_id_1', 'TEST_FIELD_ID', '["222","333"]');
|
||||||
|
INSERT INTO functional_case_custom_field(case_id, field_id, value) VALUES ('wx_case_id_2', 'TEST_FIELD_ID_1', '["222","333"]');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
INSERT INTO case_review(id, num, name, module_id, project_id, status, review_pass_rule, pos, start_time, end_time, case_count, pass_rate, tags, description, create_time, create_user, update_time, update_user)
|
||||||
|
VALUES ('wx_review_id_1',10001,'wx1', 'wx_module_1', 'wx_test_project', 'COMPLETED', 'SINGLE', 001, null, null, 1,100.00,null,null,1698058347559,'admin',1698058347559,'admin'),
|
||||||
|
('wx_review_id_2',10002,'wx2', 'wx_module_2', 'wx_test_project', 'COMPLETED', 'SINGLE', 001, null, null, 1,100.00,null,null,1698058347559,'admin',1698058347559,'admin');
|
||||||
|
|
||||||
|
INSERT INTO case_review_functional_case(id, review_id, case_id, status, create_time, create_user, update_time)
|
||||||
|
VALUES ('wx_test_1', 'wx_review_id_1', 'wx_case_id_1', 'PASS', 1698058347559,'admin',1698058347559),
|
||||||
|
('wx_test_2', 'wx_review_id_2', 'wx_case_id_2', 'PASS', 1698058347559,'admin',1698058347559);
|
||||||
|
|
||||||
|
|
||||||
|
INSERT INTO functional_case_module(id, project_id, name, parent_id, pos, create_time, update_time, create_user, update_user) VALUES ('wx_module_1', 'wx_test_project', '测试所属模块', 'NONE', 0, 1669174143999, 1669174143999, 'admin', 'admin');
|
|
@ -1,8 +1,14 @@
|
||||||
package io.metersphere.project.mapper;
|
package io.metersphere.project.mapper;
|
||||||
|
|
||||||
|
import io.metersphere.project.domain.ProjectVersion;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface ExtBaseProjectVersionMapper {
|
public interface ExtBaseProjectVersionMapper {
|
||||||
|
|
||||||
String getDefaultVersion(@Param("projectId") String projectId);
|
String getDefaultVersion(@Param("projectId") String projectId);
|
||||||
|
|
||||||
|
|
||||||
|
List<ProjectVersion> getVersionByIds(@Param("ids") List<String> ids);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,4 +6,10 @@
|
||||||
select id from project_version where project_id = #{projectId} and status = 'open' and latest = TRUE LIMIT 1
|
select id from project_version where project_id = #{projectId} and status = 'open' and latest = TRUE LIMIT 1
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="getVersionByIds" resultType="io.metersphere.project.domain.ProjectVersion">
|
||||||
|
select id, name from project_version where id in
|
||||||
|
<foreach collection="ids" item="id" open="(" separator="," close=")">
|
||||||
|
#{id}
|
||||||
|
</foreach>
|
||||||
|
</select>
|
||||||
</mapper>
|
</mapper>
|
Loading…
Reference in New Issue