refactor(测试计划): 测试计划已关联功能用例模块树
This commit is contained in:
parent
254cbfa019
commit
43440db470
|
@ -71,7 +71,7 @@ public class CaseReviewController {
|
||||||
|
|
||||||
@PostMapping("/copy")
|
@PostMapping("/copy")
|
||||||
@Operation(summary = "用例管理-用例评审-复制用例评审")
|
@Operation(summary = "用例管理-用例评审-复制用例评审")
|
||||||
@Log(type = OperationLogType.COPY, expression = "#msClass.copyCaseReviewLog(#request)", msClass = CaseReviewLogService.class)
|
@Log(type = OperationLogType.ADD, 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)
|
@SendNotice(taskType = NoticeConstants.TaskType.CASE_REVIEW_TASK, event = NoticeConstants.Event.CREATE, target = "#targetClass.getMainCaseReview(#request)", targetClass = CaseReviewNoticeService.class)
|
||||||
@RequiresPermissions(PermissionConstants.CASE_REVIEW_READ_ADD)
|
@RequiresPermissions(PermissionConstants.CASE_REVIEW_READ_ADD)
|
||||||
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||||
|
|
|
@ -22,7 +22,6 @@ public class TestPlanCaseRequest extends BasePageRequest implements Serializable
|
||||||
private String testPlanId;
|
private String testPlanId;
|
||||||
|
|
||||||
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
@NotBlank(message = "{functional_case.project_id.not_blank}")
|
|
||||||
private String projectId;
|
private String projectId;
|
||||||
|
|
||||||
@Schema(description = "版本id")
|
@Schema(description = "版本id")
|
||||||
|
|
|
@ -135,8 +135,15 @@
|
||||||
<sql id="queryWhereCondition">
|
<sql id="queryWhereCondition">
|
||||||
<if test="request.moduleIds != null and request.moduleIds.size() > 0">
|
<if test="request.moduleIds != null and request.moduleIds.size() > 0">
|
||||||
and functional_case.module_id in
|
and functional_case.module_id in
|
||||||
<foreach collection="request.moduleIds" item="moduleId" separator="," open="(" close=")">
|
<foreach collection="request.moduleIds" item="nodeId" separator="," open="(" close=")">
|
||||||
#{moduleId}
|
<choose>
|
||||||
|
<when test="nodeId.contains('_root')">
|
||||||
|
'root'
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
#{nodeId}
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
</foreach>
|
</foreach>
|
||||||
</if>
|
</if>
|
||||||
<if test="request.keyword != null and request.keyword != ''">
|
<if test="request.keyword != null and request.keyword != ''">
|
||||||
|
@ -148,6 +155,9 @@
|
||||||
<if test="request.collectionId != null and request.collectionId != ''">
|
<if test="request.collectionId != null and request.collectionId != ''">
|
||||||
and test_plan_functional_case.test_plan_collection_id = #{request.collectionId}
|
and test_plan_functional_case.test_plan_collection_id = #{request.collectionId}
|
||||||
</if>
|
</if>
|
||||||
|
<if test="request.projectId != null and request.projectId!=''">
|
||||||
|
and functional_case.project_id = #{request.projectId}
|
||||||
|
</if>
|
||||||
<include refid="filters">
|
<include refid="filters">
|
||||||
<property name="filter" value="request.filter"/>
|
<property name="filter" value="request.filter"/>
|
||||||
</include>
|
</include>
|
||||||
|
@ -451,7 +461,7 @@
|
||||||
LEFT JOIN test_plan_functional_case tpfc ON tpfc.functional_case_id = fc.id
|
LEFT JOIN test_plan_functional_case tpfc ON tpfc.functional_case_id = fc.id
|
||||||
LEFT JOIN project p ON fc.project_id = p.id
|
LEFT JOIN project p ON fc.project_id = p.id
|
||||||
WHERE tpfc.test_plan_id = #{testPlanId}
|
WHERE tpfc.test_plan_id = #{testPlanId}
|
||||||
AND fc.deleted = false AND fc.module_id = 'root'
|
AND fc.deleted = false
|
||||||
ORDER BY fc.pos
|
ORDER BY fc.pos
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
@ -465,14 +475,15 @@
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="countModuleIdByRequest" resultType="io.metersphere.functional.dto.FunctionalCaseModuleCountDTO">
|
<select id="countModuleIdByRequest" resultType="io.metersphere.functional.dto.FunctionalCaseModuleCountDTO">
|
||||||
SELECT functional_case.module_id AS moduleId, count(functional_case.id) AS dataCount, functional_case.project_id AS projectId, project.name AS projectName
|
SELECT CASE WHEN functional_case.module_id = 'root' THEN concat(functional_case.project_id, '_', functional_case.module_id) ElSE functional_case.module_id END AS moduleId,
|
||||||
|
count(functional_case.id) As dataCount, functional_case.project_id As projectId, project.name As projectName
|
||||||
FROM test_plan_functional_case
|
FROM test_plan_functional_case
|
||||||
LEFT JOIN functional_case ON test_plan_functional_case.functional_case_id = functional_case.id
|
LEFT JOIN functional_case ON test_plan_functional_case.functional_case_id = functional_case.id
|
||||||
LEFT JOIN project ON functional_case.project_id = project.id
|
LEFT JOIN project ON functional_case.project_id = project.id
|
||||||
WHERE test_plan_functional_case.test_plan_id = #{request.testPlanId}
|
WHERE test_plan_functional_case.test_plan_id = #{request.testPlanId}
|
||||||
AND functional_case.deleted = #{deleted}
|
AND functional_case.deleted = #{deleted}
|
||||||
<include refid="queryWhereCondition"/>
|
<include refid="queryWhereCondition"/>
|
||||||
GROUP BY module_id
|
GROUP BY moduleId
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="caseCount"
|
<select id="caseCount"
|
||||||
|
|
|
@ -30,7 +30,6 @@ import io.metersphere.plan.dto.request.*;
|
||||||
import io.metersphere.plan.dto.response.*;
|
import io.metersphere.plan.dto.response.*;
|
||||||
import io.metersphere.plan.mapper.*;
|
import io.metersphere.plan.mapper.*;
|
||||||
import io.metersphere.plugin.platform.dto.SelectOption;
|
import io.metersphere.plugin.platform.dto.SelectOption;
|
||||||
import io.metersphere.project.domain.Project;
|
|
||||||
import io.metersphere.project.dto.ModuleCountDTO;
|
import io.metersphere.project.dto.ModuleCountDTO;
|
||||||
import io.metersphere.project.dto.MoveNodeSortDTO;
|
import io.metersphere.project.dto.MoveNodeSortDTO;
|
||||||
import io.metersphere.provider.BaseAssociateBugProvider;
|
import io.metersphere.provider.BaseAssociateBugProvider;
|
||||||
|
@ -130,7 +129,7 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
|
||||||
@Override
|
@Override
|
||||||
public long copyResource(String originalTestPlanId, String newTestPlanId, Map<String, String> oldCollectionIdToNewCollectionId, String operator, long operatorTime) {
|
public long copyResource(String originalTestPlanId, String newTestPlanId, Map<String, String> oldCollectionIdToNewCollectionId, String operator, long operatorTime) {
|
||||||
List<TestPlanFunctionalCase> copyList = new ArrayList<>();
|
List<TestPlanFunctionalCase> copyList = new ArrayList<>();
|
||||||
String defaultCollectionId = extTestPlanCollectionMapper.selectDefaultCollectionId(newTestPlanId,CaseType.SCENARIO_CASE.getKey());
|
String defaultCollectionId = extTestPlanCollectionMapper.selectDefaultCollectionId(newTestPlanId, CaseType.SCENARIO_CASE.getKey());
|
||||||
extTestPlanFunctionalCaseMapper.selectByTestPlanIdAndNotDeleted(originalTestPlanId).forEach(originalCase -> {
|
extTestPlanFunctionalCaseMapper.selectByTestPlanIdAndNotDeleted(originalTestPlanId).forEach(originalCase -> {
|
||||||
TestPlanFunctionalCase newCase = new TestPlanFunctionalCase();
|
TestPlanFunctionalCase newCase = new TestPlanFunctionalCase();
|
||||||
BeanUtils.copyBean(newCase, originalCase);
|
BeanUtils.copyBean(newCase, originalCase);
|
||||||
|
@ -323,27 +322,38 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
|
||||||
*/
|
*/
|
||||||
private List<BaseTreeNode> getModuleTree(String testPlanId) {
|
private List<BaseTreeNode> getModuleTree(String testPlanId) {
|
||||||
List<BaseTreeNode> returnList = new ArrayList<>();
|
List<BaseTreeNode> returnList = new ArrayList<>();
|
||||||
List<ProjectOptionDTO> rootIds = extTestPlanFunctionalCaseMapper.selectRootIdByTestPlanId(testPlanId);
|
List<ProjectOptionDTO> moduleLists = extTestPlanFunctionalCaseMapper.selectRootIdByTestPlanId(testPlanId);
|
||||||
Map<String, List<ProjectOptionDTO>> projectRootMap = rootIds.stream().collect(Collectors.groupingBy(ProjectOptionDTO::getName));
|
// 获取所有的项目id
|
||||||
|
List<String> projectIds = moduleLists.stream().map(ProjectOptionDTO::getName).distinct().toList();
|
||||||
|
// moduleLists中id=root的数据
|
||||||
|
List<ProjectOptionDTO> rootModuleList = moduleLists.stream().filter(item -> StringUtils.equals(item.getId(), ModuleConstants.DEFAULT_NODE_ID)).toList();
|
||||||
|
|
||||||
|
Map<String, List<ProjectOptionDTO>> projectRootMap = rootModuleList.stream().collect(Collectors.groupingBy(ProjectOptionDTO::getName));
|
||||||
List<FunctionalCaseModuleDTO> functionalModuleIds = extTestPlanFunctionalCaseMapper.selectBaseByProjectIdAndTestPlanId(testPlanId);
|
List<FunctionalCaseModuleDTO> functionalModuleIds = extTestPlanFunctionalCaseMapper.selectBaseByProjectIdAndTestPlanId(testPlanId);
|
||||||
Map<String, List<FunctionalCaseModuleDTO>> projectModuleMap = functionalModuleIds.stream().collect(Collectors.groupingBy(FunctionalCaseModule::getProjectId));
|
Map<String, List<FunctionalCaseModuleDTO>> projectModuleMap = functionalModuleIds.stream().collect(Collectors.groupingBy(FunctionalCaseModule::getProjectId));
|
||||||
if (MapUtils.isEmpty(projectModuleMap)) {
|
|
||||||
projectRootMap.forEach((projectId, projectOptionDTOList) -> {
|
projectIds.forEach(projectId -> {
|
||||||
BaseTreeNode projectNode = new BaseTreeNode(projectId, projectOptionDTOList.get(0).getProjectName(), Project.class.getName());
|
// 如果projectRootMap中没有projectId,说明该项目没有根节点 不需要创
|
||||||
returnList.add(projectNode);
|
// projectModuleMap中没有projectId,说明该项目没有模块 不需要创建
|
||||||
BaseTreeNode defaultNode = functionalCaseModuleService.getDefaultModule(Translator.get("functional_case.module.default.name"));
|
// 如果都有 需要创建完整的数结构
|
||||||
projectNode.addChild(defaultNode);
|
boolean needCreatRoot = MapUtils.isNotEmpty(projectRootMap) && projectRootMap.containsKey(projectId);
|
||||||
});
|
boolean needCreatModule = MapUtils.isNotEmpty(projectModuleMap) && projectModuleMap.containsKey(projectId);
|
||||||
return returnList;
|
// 项目名称是
|
||||||
}
|
String projectName = needCreatModule ? projectModuleMap.get(projectId).getFirst().getProjectName() : projectRootMap.get(projectId).getFirst().getProjectName();
|
||||||
projectModuleMap.forEach((projectId, moduleList) -> {
|
// 构建项目那一层级
|
||||||
BaseTreeNode projectNode = new BaseTreeNode(projectId, moduleList.get(0).getProjectName(), Project.class.getName());
|
BaseTreeNode projectNode = new BaseTreeNode(projectId, projectName, "PROJECT");
|
||||||
returnList.add(projectNode);
|
returnList.add(projectNode);
|
||||||
List<String> projectModuleIds = moduleList.stream().map(FunctionalCaseModule::getId).toList();
|
List<BaseTreeNode> nodeByNodeIds = new ArrayList<>();
|
||||||
List<BaseTreeNode> nodeByNodeIds = functionalCaseModuleService.getNodeByNodeIds(projectModuleIds);
|
if (needCreatModule) {
|
||||||
boolean haveVirtualRootNode = CollectionUtils.isEmpty(projectRootMap.get(projectId));
|
List<String> projectModuleIds = projectModuleMap.get(projectId).stream().map(FunctionalCaseModuleDTO::getId).toList();
|
||||||
List<BaseTreeNode> baseTreeNodes = functionalCaseModuleService.buildTreeAndCountResource(nodeByNodeIds, !haveVirtualRootNode, Translator.get("functional_case.module.default.name"));
|
nodeByNodeIds = functionalCaseModuleService.getNodeByNodeIds(projectModuleIds);
|
||||||
|
}
|
||||||
|
List<BaseTreeNode> baseTreeNodes = functionalCaseModuleService.buildTreeAndCountResource(nodeByNodeIds, needCreatRoot, Translator.get("functional_case.module.default.name"));
|
||||||
for (BaseTreeNode baseTreeNode : baseTreeNodes) {
|
for (BaseTreeNode baseTreeNode : baseTreeNodes) {
|
||||||
|
if (StringUtils.equals(baseTreeNode.getId(), ModuleConstants.DEFAULT_NODE_ID)) {
|
||||||
|
// 默认拼项目id
|
||||||
|
baseTreeNode.setId(projectId + "_" + ModuleConstants.DEFAULT_NODE_ID);
|
||||||
|
}
|
||||||
projectNode.addChild(baseTreeNode);
|
projectNode.addChild(baseTreeNode);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -391,7 +401,7 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
|
||||||
request.setModuleIds(null);
|
request.setModuleIds(null);
|
||||||
List<FunctionalCaseModuleCountDTO> projectModuleCountDTOList = extTestPlanFunctionalCaseMapper.countModuleIdByRequest(request, false);
|
List<FunctionalCaseModuleCountDTO> projectModuleCountDTOList = extTestPlanFunctionalCaseMapper.countModuleIdByRequest(request, false);
|
||||||
Map<String, List<FunctionalCaseModuleCountDTO>> projectCountMap = projectModuleCountDTOList.stream().collect(Collectors.groupingBy(FunctionalCaseModuleCountDTO::getProjectId));
|
Map<String, List<FunctionalCaseModuleCountDTO>> projectCountMap = projectModuleCountDTOList.stream().collect(Collectors.groupingBy(FunctionalCaseModuleCountDTO::getProjectId));
|
||||||
Map<String, Long> projectModuleCountMap = new HashMap<>();
|
Map<String, Long> projectModuleCountMap = projectModuleCountDTOList.stream().collect(Collectors.groupingBy(FunctionalCaseModuleCountDTO::getModuleId, Collectors.summingLong(FunctionalCaseModuleCountDTO::getDataCount)));
|
||||||
projectCountMap.forEach((projectId, moduleCountDTOList) -> {
|
projectCountMap.forEach((projectId, moduleCountDTOList) -> {
|
||||||
List<ModuleCountDTO> moduleCountDTOS = new ArrayList<>();
|
List<ModuleCountDTO> moduleCountDTOS = new ArrayList<>();
|
||||||
for (FunctionalCaseModuleCountDTO functionalCaseModuleCountDTO : moduleCountDTOList) {
|
for (FunctionalCaseModuleCountDTO functionalCaseModuleCountDTO : moduleCountDTOList) {
|
||||||
|
|
|
@ -27,7 +27,7 @@ VALUES
|
||||||
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)
|
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
|
VALUES
|
||||||
('fc_1', 1, 't_1', '123', '100001', '111', 'UN_REVIEWED', NULL, 'TEXT', 55000, 'v3.0.0', 'TEST_FUNCTIONAL_MINDER_CASE_ID_7', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL),
|
('fc_1', 1, 't_1', '123', '100001', '111', 'UN_REVIEWED', NULL, 'TEXT', 55000, 'v3.0.0', 'TEST_FUNCTIONAL_MINDER_CASE_ID_7', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL),
|
||||||
('fc_2', 2, 't_1', '123', '100001', '222', 'UN_REVIEWED', NULL, 'TEXT', 55000, 'v3.0.0', 'TEST_FUNCTIONAL_MINDER_CASE_ID_7', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL),
|
('fc_2', 2, 'root', '123', '100001', '222', 'UN_REVIEWED', NULL, 'TEXT', 55000, 'v3.0.0', 'TEST_FUNCTIONAL_MINDER_CASE_ID_7', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL),
|
||||||
('fc_3', 3, 'root', '123', '100001', '333', 'UN_REVIEWED', NULL, 'TEXT', 55000, 'v3.0.0', 'TEST_FUNCTIONAL_MINDER_CASE_ID_7', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL),
|
('fc_3', 3, 'root', '123', '100001', '333', 'UN_REVIEWED', NULL, 'TEXT', 55000, 'v3.0.0', 'TEST_FUNCTIONAL_MINDER_CASE_ID_7', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL),
|
||||||
('gyq_disassociate_fc_1', 4, 'root', 'gyq_disassociate', '100001', 'disassociate1', 'UN_REVIEWED', NULL, 'TEXT', 55000, 'v3.0.0', 'gyq_disassociate_fc_1', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL),
|
('gyq_disassociate_fc_1', 4, 'root', 'gyq_disassociate', '100001', 'disassociate1', 'UN_REVIEWED', NULL, 'TEXT', 55000, 'v3.0.0', 'gyq_disassociate_fc_1', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL),
|
||||||
('gyq_disassociate_fc_2', 5, 'root', 'gyq_disassociate', '100001', 'disassociate2', 'UN_REVIEWED', NULL, 'TEXT', 55000, 'v3.0.0', 'gyq_disassociate_fc_2', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL),
|
('gyq_disassociate_fc_2', 5, 'root', 'gyq_disassociate', '100001', 'disassociate2', 'UN_REVIEWED', NULL, 'TEXT', 55000, 'v3.0.0', 'gyq_disassociate_fc_2', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL),
|
||||||
|
|
Loading…
Reference in New Issue