diff --git a/backend/framework/domain/src/main/resources/migration/3.5.0/ddl/V3.5.0_2__ga_ddl.sql b/backend/framework/domain/src/main/resources/migration/3.5.0/ddl/V3.5.0_2__ga_ddl.sql index 07cb3334c5..3af7f78c8e 100644 --- a/backend/framework/domain/src/main/resources/migration/3.5.0/ddl/V3.5.0_2__ga_ddl.sql +++ b/backend/framework/domain/src/main/resources/migration/3.5.0/ddl/V3.5.0_2__ga_ddl.sql @@ -72,6 +72,9 @@ CREATE INDEX idx_project_id_delete_create_time CREATE INDEX idx_project_id_delete_create_time_create_user ON bug (project_id, deleted, create_time, create_user); +create index idx_test_plan_id_bug_id + on bug_relation_case (test_plan_id, bug_id); + ALTER TABLE exec_task ADD COLUMN deleted bit(1) NOT NULL DEFAULT b'0' COMMENT '删除标识'; ALTER TABLE exec_task_item ADD COLUMN deleted bit(1) NOT NULL DEFAULT b'0' COMMENT '删除标识'; ALTER TABLE exec_task_item ADD COLUMN case_id VARCHAR(50) COMMENT '用例表id'; diff --git a/backend/services/dashboard/src/main/java/io/metersphere/dashboard/controller/DashboardController.java b/backend/services/dashboard/src/main/java/io/metersphere/dashboard/controller/DashboardController.java index 6094ec3255..6033165919 100644 --- a/backend/services/dashboard/src/main/java/io/metersphere/dashboard/controller/DashboardController.java +++ b/backend/services/dashboard/src/main/java/io/metersphere/dashboard/controller/DashboardController.java @@ -144,12 +144,19 @@ public class DashboardController { } @PostMapping("/handle_bug_by_me") - @Operation(summary = "我创建的缺陷") + @Operation(summary = "待我处理的缺陷") @CheckOwner(resourceId = "#request.getOrganizationId()", resourceType = "organization") public StatisticsDTO projectBugCountHandleByMe(@Validated @RequestBody DashboardFrontPageRequest request) { return dashboardService.projectBugCountHandleByMe(request, SessionUtils.getUserId()); } + @PostMapping("/plan_legacy_bug") + @Operation(summary = "计划遗留bug统计") + @CheckOwner(resourceId = "#request.getOrganizationId()", resourceType = "organization") + public StatisticsDTO projectPlanLegacyBug(@Validated @RequestBody DashboardFrontPageRequest request) { + return dashboardService.projectPlanLegacyBug(request, SessionUtils.getUserId()); + } + @PostMapping("/reviewing_by_me") @Operation(summary = "待我评审") diff --git a/backend/services/dashboard/src/main/java/io/metersphere/dashboard/service/DashboardService.java b/backend/services/dashboard/src/main/java/io/metersphere/dashboard/service/DashboardService.java index 64cf2f6098..b1d27d14b0 100644 --- a/backend/services/dashboard/src/main/java/io/metersphere/dashboard/service/DashboardService.java +++ b/backend/services/dashboard/src/main/java/io/metersphere/dashboard/service/DashboardService.java @@ -48,6 +48,7 @@ import io.metersphere.project.service.ProjectService; import io.metersphere.sdk.constants.ExecStatus; import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.sdk.constants.ResultStatus; +import io.metersphere.sdk.constants.TestPlanConstants; import io.metersphere.sdk.dto.CombineCondition; import io.metersphere.sdk.dto.CombineSearch; import io.metersphere.sdk.util.JSON; @@ -335,38 +336,89 @@ public class DashboardService { UserLayoutExample userLayoutExample = new UserLayoutExample(); userLayoutExample.createCriteria().andUserIdEqualTo(userId).andOrgIdEqualTo(organizationId); List userLayouts = userLayoutMapper.selectByExampleWithBLOBs(userLayoutExample); - if (CollectionUtils.isEmpty(userLayouts)) { - return getDefaultLayoutDTOS(organizationId); + List allPermissionProjects = extProjectMapper.getUserProjectIdName(organizationId, null, userId); + if (CollectionUtils.isEmpty(allPermissionProjects)) { + return new ArrayList<>(); + } + if (CollectionUtils.isEmpty(userLayouts)) { + return getDefaultLayoutDTOS(allPermissionProjects.getFirst().getId()); } - UserLayout userLayout = userLayouts.getFirst(); byte[] configuration = userLayout.getConfiguration(); String layoutDTOStr = new String(configuration); List layoutDTOS = JSON.parseArray(layoutDTOStr, LayoutDTO.class); + Map> permissionModuleProjectIdMap = dashboardProjectService.getPermissionModuleProjectIds(allPermissionProjects, userId); + List orgProjectMemberList = extProjectMemberMapper.getOrgProjectMemberList(organizationId, null); + rebuildLayouts(layoutDTOS, allPermissionProjects, orgProjectMemberList, permissionModuleProjectIdMap); + return layoutDTOS; + } - //重新查询排除项目禁用的或者用户已经移除某个项目的项目或者成员 - List oldAllProjectIds = new ArrayList<>(); - List oldHallHandleUsers = new ArrayList<>(); + /** + * 过滤用户在当前项目是否有移除或者项目是否被禁用以及用户是否被删除禁用 + * @param layoutDTOS 用户保存的布局 + * @param allPermissionProjects 用户有任意权限的所有在役项目 + * @param orgProjectMemberList 当前组织下所有有项目权限的成员 + * @param permissionModuleProjectIdMap 只读权限对应的开启模块的项目ids + */ + private void rebuildLayouts(List layoutDTOS, List allPermissionProjects, List orgProjectMemberList, Map> permissionModuleProjectIdMap) { for (LayoutDTO layoutDTO : layoutDTOS) { - oldAllProjectIds.addAll(layoutDTO.getProjectIds()); - oldHallHandleUsers.addAll(layoutDTO.getHandleUsers()); - } - List hasPermissionProjectList; - if (CollectionUtils.isEmpty(oldAllProjectIds)) { - hasPermissionProjectList = extProjectMapper.getUserProjectIdName(organizationId, null, userId); - } else { - List projectIds = oldAllProjectIds.stream().distinct().toList(); - hasPermissionProjectList = extProjectMapper.getUserProjectIdName(null, projectIds, userId); - if (CollectionUtils.isEmpty(hasPermissionProjectList)) { - hasPermissionProjectList = extProjectMapper.getUserProjectIdName(organizationId, null, userId); + if (StringUtils.equalsIgnoreCase(layoutDTO.getKey(), DashboardUserLayoutKeys.PROJECT_VIEW.toString()) || StringUtils.equalsIgnoreCase(layoutDTO.getKey(), DashboardUserLayoutKeys.CREATE_BY_ME.toString())) { + List list = allPermissionProjects.stream().filter(t -> layoutDTO.getProjectIds().contains(t.getId())).toList(); + if (CollectionUtils.isNotEmpty(list)) { + layoutDTO.setProjectIds(list.stream().map(Project::getId).toList()); + } else { + layoutDTO.setProjectIds(allPermissionProjects.stream().map(Project::getId).toList()); + } + } else if (StringUtils.equalsIgnoreCase(layoutDTO.getKey(), DashboardUserLayoutKeys.PROJECT_MEMBER_VIEW.toString())) { + List list = orgProjectMemberList.stream().filter(t -> layoutDTO.getHandleUsers().contains(t.getId())).toList(); + layoutDTO.setHandleUsers(list.stream().map(ProjectUserMemberDTO::getId).toList()); + List projectList = allPermissionProjects.stream().filter(t -> layoutDTO.getProjectIds().contains(t.getId())).toList(); + if (CollectionUtils.isEmpty(projectList)) { + layoutDTO.setProjectIds(List.of(allPermissionProjects.getFirst().getId())); + } else { + layoutDTO.setProjectIds(List.of(projectList.getFirst().getId())); + } + } else if(StringUtils.equalsIgnoreCase(layoutDTO.getKey(), DashboardUserLayoutKeys.CASE_COUNT.toString()) + || StringUtils.equalsIgnoreCase(layoutDTO.getKey(), DashboardUserLayoutKeys.ASSOCIATE_CASE_COUNT.toString()) + ||StringUtils.equalsIgnoreCase(layoutDTO.getKey(), DashboardUserLayoutKeys.REVIEW_CASE_COUNT.toString()) + || StringUtils.equalsIgnoreCase(layoutDTO.getKey(), DashboardUserLayoutKeys.REVIEWING_BY_ME.toString())) { + Set hasReadProjectIds = permissionModuleProjectIdMap.get(PermissionConstants.FUNCTIONAL_CASE_READ); + checkHasPermissionProject(layoutDTO, hasReadProjectIds); + } else if (StringUtils.equalsIgnoreCase(layoutDTO.getKey(), DashboardUserLayoutKeys.API_COUNT.toString()) + || StringUtils.equalsIgnoreCase(layoutDTO.getKey(), DashboardUserLayoutKeys.API_CHANGE.toString())) { + Set hasReadProjectIds = permissionModuleProjectIdMap.get(PermissionConstants.PROJECT_API_DEFINITION_READ); + checkHasPermissionProject(layoutDTO, hasReadProjectIds); + } else if (StringUtils.equalsIgnoreCase(layoutDTO.getKey(), DashboardUserLayoutKeys.API_CASE_COUNT.toString())){ + Set hasReadProjectIds = permissionModuleProjectIdMap.get(PermissionConstants.PROJECT_API_DEFINITION_CASE_READ); + checkHasPermissionProject(layoutDTO, hasReadProjectIds); + }else if (StringUtils.equalsIgnoreCase(layoutDTO.getKey(), DashboardUserLayoutKeys.SCENARIO_COUNT.toString())){ + Set hasReadProjectIds = permissionModuleProjectIdMap.get(PermissionConstants.PROJECT_API_SCENARIO_READ); + checkHasPermissionProject(layoutDTO, hasReadProjectIds); + } + else if (StringUtils.equalsIgnoreCase(layoutDTO.getKey(), DashboardUserLayoutKeys.TEST_PLAN_COUNT.toString()) + || StringUtils.equalsIgnoreCase(layoutDTO.getKey(), DashboardUserLayoutKeys.PLAN_LEGACY_BUG.toString())) { + Set hasReadProjectIds = permissionModuleProjectIdMap.get(PermissionConstants.TEST_PLAN_READ); + checkHasPermissionProject(layoutDTO, hasReadProjectIds); + }else if (StringUtils.equalsIgnoreCase(layoutDTO.getKey(), DashboardUserLayoutKeys.BUG_COUNT.toString()) + || StringUtils.equalsIgnoreCase(layoutDTO.getKey(), DashboardUserLayoutKeys.CREATE_BUG_BY_ME.toString()) + ||StringUtils.equalsIgnoreCase(layoutDTO.getKey(), DashboardUserLayoutKeys.HANDLE_BUG_BY_ME.toString()) + || StringUtils.equalsIgnoreCase(layoutDTO.getKey(), DashboardUserLayoutKeys.BUG_HANDLE_USER.toString())) { + Set hasReadProjectIds = permissionModuleProjectIdMap.get(PermissionConstants.PROJECT_BUG_READ); + checkHasPermissionProject(layoutDTO, hasReadProjectIds); } } - Map projectMap = hasPermissionProjectList.stream().collect(Collectors.toMap(Project::getId, t -> t)); - List handleUsers = oldHallHandleUsers.stream().distinct().toList(); - List orgProjectMemberList = extProjectMemberMapper.getOrgProjectMemberList(organizationId, handleUsers); - //重新填充填充返回的项目id 和 用户id - rebuildProjectOrUser(layoutDTOS, hasPermissionProjectList, projectMap, orgProjectMemberList); - return layoutDTOS; + } + + private void checkHasPermissionProject(LayoutDTO layoutDTO, Set hasReadProjectIds) { + if (CollectionUtils.isEmpty(hasReadProjectIds)) { + return; + } + List projectIds = hasReadProjectIds.stream().filter(t -> layoutDTO.getProjectIds().contains(t)).toList(); + if (CollectionUtils.isEmpty(projectIds)) { + layoutDTO.setProjectIds(List.of(new ArrayList<>(hasReadProjectIds).getFirst())); + } else { + layoutDTO.setProjectIds(List.of(projectIds.getFirst())); + } } /** @@ -379,9 +431,9 @@ public class DashboardService { List layoutDTOS = new ArrayList<>(); LayoutDTO projectLayoutDTO = buildDefaultLayoutDTO(DashboardUserLayoutKeys.PROJECT_VIEW, "workbench.homePage.projectOverview", 0, new ArrayList<>()); layoutDTOS.add(projectLayoutDTO); - LayoutDTO createByMeLayoutDTO = buildDefaultLayoutDTO(DashboardUserLayoutKeys.CREATE_BY_ME, "workbench,homePage.createdByMe", 1, new ArrayList<>()); + LayoutDTO createByMeLayoutDTO = buildDefaultLayoutDTO(DashboardUserLayoutKeys.CREATE_BY_ME, "workbench.homePage.createdByMe", 1, new ArrayList<>()); layoutDTOS.add(createByMeLayoutDTO); - LayoutDTO projectMemberLayoutDTO = buildDefaultLayoutDTO(DashboardUserLayoutKeys.PROJECT_MEMBER_VIEW, "workbench,homePage.staffOverview", 2, List.of(organizationId)); + LayoutDTO projectMemberLayoutDTO = buildDefaultLayoutDTO(DashboardUserLayoutKeys.PROJECT_MEMBER_VIEW, "workbench.homePage.staffOverview", 2, List.of(organizationId)); layoutDTOS.add(projectMemberLayoutDTO); return layoutDTOS; } @@ -407,30 +459,6 @@ public class DashboardService { return layoutDTO; } - /** - * 过滤用户在当前项目是否有移除或者项目是否被禁用以及用户是否被删除禁用 - * - * @param layoutDTOS 获取的所有布局卡片 - * @param hasPermissionProjectList 用户有任意权限的项目 - * @param projectMap 用户有任意权限的项目Map - * @param orgProjectMemberList 组织下所有的项目人员 - */ - private static void rebuildProjectOrUser(List layoutDTOS, List hasPermissionProjectList, Map projectMap, List orgProjectMemberList) { - for (LayoutDTO layoutDTO : layoutDTOS) { - if (StringUtils.equalsIgnoreCase(layoutDTO.getKey(), DashboardUserLayoutKeys.PROJECT_VIEW.toString()) || StringUtils.equalsIgnoreCase(layoutDTO.getKey(), DashboardUserLayoutKeys.CREATE_BY_ME.toString())) { - List list = hasPermissionProjectList.stream().filter(t -> layoutDTO.getProjectIds().contains(t.getId())).toList(); - layoutDTO.setProjectIds(list.stream().map(Project::getId).toList()); - } else if (StringUtils.equalsIgnoreCase(layoutDTO.getKey(), DashboardUserLayoutKeys.PROJECT_MEMBER_VIEW.toString())) { - List list = orgProjectMemberList.stream().filter(t -> layoutDTO.getHandleUsers().contains(t.getId())).toList(); - layoutDTO.setHandleUsers(list.stream().map(ProjectUserMemberDTO::getId).toList()); - } else { - if (CollectionUtils.isNotEmpty(layoutDTO.getProjectIds()) && projectMap.get(layoutDTO.getProjectIds().getFirst()) == null) { - layoutDTO.setProjectIds(List.of(hasPermissionProjectList.get(0).getId())); - } - } - } - } - public OverViewCountDTO projectMemberViewCount(DashboardFrontPageRequest request) { String projectId = request.getProjectIds().getFirst(); Project project = projectMapper.selectByPrimaryKey(projectId); @@ -577,13 +605,10 @@ public class DashboardService { statisticsDTO.setErrorCode(NO_PROJECT_PERMISSION.getCode()); return statisticsDTO; } - Long toStartTime = request.getToStartTime(); - Long toEndTime = request.getToEndTime(); - List statisticListByProjectId = extFunctionalCaseMapper.getStatisticListByProjectId(projectId, toStartTime, toEndTime); List statusPercentList = new ArrayList<>(); - buildStatusPercentList(statisticListByProjectId, statusPercentList); - statisticsDTO.setStatusPercentList(statusPercentList); List allStatisticListByProjectId = extFunctionalCaseMapper.getStatisticListByProjectId(projectId, null, null); + buildStatusPercentList(allStatisticListByProjectId, statusPercentList); + statisticsDTO.setStatusPercentList(statusPercentList); Map> reviewStatusMap = allStatisticListByProjectId.stream().collect(Collectors.groupingBy(FunctionalCaseStatisticDTO::getReviewStatus)); Map> statusStatisticsMap = new HashMap<>(); List reviewList = getReviewList(reviewStatusMap, allStatisticListByProjectId); @@ -836,8 +861,6 @@ public class DashboardService { statisticsDTO.setErrorCode(NO_PROJECT_PERMISSION.getCode()); return statisticsDTO; } - Long toStartTime = request.getToStartTime(); - Long toEndTime = request.getToEndTime(); List statisticListByProjectId = extFunctionalCaseMapper.getStatisticListByProjectId(projectId, null, null); List unReviewCaseList = statisticListByProjectId.stream().filter(t -> StringUtils.equalsIgnoreCase(t.getReviewStatus(), FunctionalCaseReviewStatus.UN_REVIEWED.toString())).toList(); int reviewCount = statisticListByProjectId.size() - unReviewCaseList.size(); @@ -845,7 +868,7 @@ public class DashboardService { Map> statusStatisticsMap = new HashMap<>(); statusStatisticsMap.put("cover", coverList); statisticsDTO.setStatusStatisticsMap(statusStatisticsMap); - List statusPercentList = getStatusPercentList(projectId, toStartTime, toEndTime); + List statusPercentList = getStatusPercentList(statisticListByProjectId); statisticsDTO.setStatusPercentList(statusPercentList); return statisticsDTO; } @@ -857,29 +880,28 @@ public class DashboardService { statisticsDTO.setErrorCode(NO_PROJECT_PERMISSION.getCode()); return statisticsDTO; } - Long toStartTime = request.getToStartTime(); - Long toEndTime = request.getToEndTime(); - List createApiList = extApiDefinitionMapper.getCreateApiList(projectId, toStartTime, toEndTime); - Map> protocolMap = createApiList.stream().collect(Collectors.groupingBy(ApiDefinition::getProtocol)); + List createAllApiList = extApiDefinitionMapper.getCreateApiList(projectId, null, null); + Map> protocolMap = createAllApiList.stream().collect(Collectors.groupingBy(ApiDefinition::getProtocol)); List statusPercentList = new ArrayList<>(); List protocols = apiTestService.getProtocols(request.getOrganizationId()); + int totalCount = CollectionUtils.isEmpty(createAllApiList) ? 0 : createAllApiList.size(); for (ProtocolDTO protocol : protocols) { String protocolName = protocol.getProtocol(); StatusPercentDTO statusPercentDTO = new StatusPercentDTO(); statusPercentDTO.setStatus(protocolName); List apiDefinitionList = protocolMap.get(protocolName); - if (CollectionUtils.isEmpty(apiDefinitionList)) { + int size = CollectionUtils.isEmpty(apiDefinitionList) ? 0 : apiDefinitionList.size(); + if (totalCount == 0) { statusPercentDTO.setCount(0); statusPercentDTO.setPercentValue("0%"); } else { - int size = apiDefinitionList.size(); statusPercentDTO.setCount(size); - BigDecimal divide = BigDecimal.valueOf(size).divide(BigDecimal.valueOf(createApiList.size()), 2, RoundingMode.HALF_UP); + BigDecimal divide = BigDecimal.valueOf(size).divide(BigDecimal.valueOf(totalCount), 2, RoundingMode.HALF_UP); statusPercentDTO.setPercentValue(divide.multiply(BigDecimal.valueOf(100)) + "%"); } statusPercentList.add(statusPercentDTO); } - List createAllApiList = extApiDefinitionMapper.getCreateApiList(projectId, null, null); + Map> statusMap = createAllApiList.stream().collect(Collectors.groupingBy(ApiDefinition::getStatus)); List doneList = statusMap.get(ApiDefinitionStatus.DONE.toString()); List processList = statusMap.get(ApiDefinitionStatus.PROCESSING.toString()); @@ -890,12 +912,14 @@ public class DashboardService { doneDTO.setName(Translator.get("api_definition.status.completed")); NameCountDTO completionRate = new NameCountDTO(); completionRate.setName(Translator.get("api_definition.completionRate")); - if (CollectionUtils.isEmpty(doneList)) { + + int doneSize = CollectionUtils.isEmpty(doneList) ? 0 : doneList.size(); + if (totalCount == 0) { completionRate.setCount(0); doneDTO.setCount(0); } else { - doneDTO.setCount(doneList.size()); - BigDecimal divide = BigDecimal.valueOf(doneList.size()).divide(BigDecimal.valueOf(createAllApiList.size()), 2, RoundingMode.HALF_UP); + doneDTO.setCount(doneSize); + BigDecimal divide = BigDecimal.valueOf(doneSize).divide(BigDecimal.valueOf(totalCount), 2, RoundingMode.HALF_UP); completionRate.setCount(getTurnCount(divide)); } NameCountDTO processDTO = getNameCountDTO(CollectionUtils.isEmpty(processList) ? 0 : processList.size(), Translator.get("api_definition.status.ongoing")); @@ -922,23 +946,19 @@ public class DashboardService { } @NotNull - private List getStatusPercentList(String projectId, Long toStartTime, Long toEndTime) { + private List getStatusPercentList(List statisticListByProjectId) { List statusPercentList = new ArrayList<>(); Map statusNameMap = buildStatusNameMap(); - List projectUserStatusCountDTOS = extCaseReviewMapper.statusReviewCount(projectId, toStartTime, toEndTime); - Map statusCountMap = projectUserStatusCountDTOS.stream().collect(Collectors.toMap(ProjectUserStatusCountDTO::getStatus, ProjectUserStatusCountDTO::getCount)); + int totalCount = CollectionUtils.isEmpty(statisticListByProjectId) ? 0 : statisticListByProjectId.size(); + Map> reviewStatusMap = statisticListByProjectId.stream().collect(Collectors.groupingBy(FunctionalCaseStatisticDTO::getReviewStatus)); statusNameMap.forEach((k, v) -> { StatusPercentDTO statusPercentDTO = new StatusPercentDTO(); - Integer count = statusCountMap.get(k); + List functionalCaseStatisticDTOS = reviewStatusMap.get(k); + int count = CollectionUtils.isEmpty(functionalCaseStatisticDTOS) ? 0 : functionalCaseStatisticDTOS.size(); statusPercentDTO.setStatus(v); - if (count != null) { - statusPercentDTO.setCount(count); - } else { - count = 0; - statusPercentDTO.setCount(0); - } - if (CollectionUtils.isNotEmpty(projectUserStatusCountDTOS)) { - BigDecimal divide = BigDecimal.valueOf(count).divide(BigDecimal.valueOf(projectUserStatusCountDTOS.size()), 2, RoundingMode.HALF_UP); + statusPercentDTO.setCount(count); + if (totalCount > 0) { + BigDecimal divide = BigDecimal.valueOf(count).divide(BigDecimal.valueOf(totalCount), 2, RoundingMode.HALF_UP); statusPercentDTO.setPercentValue(divide.multiply(BigDecimal.valueOf(100)) + "%"); } else { statusPercentDTO.setPercentValue("0%"); @@ -971,9 +991,11 @@ public class DashboardService { private static Map buildStatusNameMap() { Map statusNameMap = new HashMap<>(); - statusNameMap.put(CaseReviewStatus.PREPARED.toString(), Translator.get("case_review.prepared")); - statusNameMap.put(CaseReviewStatus.UNDERWAY.toString(), Translator.get("case_review.underway")); - statusNameMap.put(CaseReviewStatus.COMPLETED.toString(), Translator.get("case_review.completed")); + statusNameMap.put(FunctionalCaseReviewStatus.UN_REVIEWED.toString(), Translator.get("case.review.status.un_reviewed")); + statusNameMap.put(FunctionalCaseReviewStatus.UNDER_REVIEWED.toString(), Translator.get("case.review.status.under_reviewed")); + statusNameMap.put(FunctionalCaseReviewStatus.PASS.toString(), Translator.get("case.review.status.pass")); + statusNameMap.put(FunctionalCaseReviewStatus.UN_PASS.toString(), Translator.get("case.review.status.un_pass")); + statusNameMap.put(FunctionalCaseReviewStatus.RE_REVIEWED.toString(), Translator.get("case.review.status.re_reviewed")); return statusNameMap; } @@ -1068,10 +1090,8 @@ public class DashboardService { statisticsDTO.setErrorCode(NO_PROJECT_PERMISSION.getCode()); return statisticsDTO; } - Long toStartTime = request.getToStartTime(); - Long toEndTime = request.getToEndTime(); Map> statusStatisticsMap = new HashMap<>(); - long unDeleteCaseExecCount = extExecTaskItemMapper.getUnDeleteCaseExecCount(projectId, toStartTime, toEndTime, List.of("PLAN_RUN_API_CASE", "API_CASE")); + long unDeleteCaseExecCount = extExecTaskItemMapper.getUnDeleteCaseExecCount(projectId, null, null, List.of("PLAN_RUN_API_CASE", "API_CASE")); List simpleAllApiCaseList = extApiTestCaseMapper.getSimpleApiCaseList(projectId, null, null); int simpleAllApiCaseSize = 0; @@ -1086,9 +1106,7 @@ public class DashboardService { List errorList = simpleAllApiCaseList.stream().filter(t -> StringUtils.equalsIgnoreCase(t.getLastReportStatus(), ResultStatus.ERROR.name())).toList(); int errorSize = CollectionUtils.isNotEmpty(errorList) ? errorList.size() : 0; - List simpleApiCaseList = extApiTestCaseMapper.getSimpleApiCaseList(projectId, toStartTime, toEndTime); - List fakeList = simpleApiCaseList.stream().filter(t -> StringUtils.equalsIgnoreCase(t.getLastReportStatus(), ResultStatus.FAKE_ERROR.name())).toList(); - int simpleApiCaseSize = CollectionUtils.isNotEmpty(simpleApiCaseList) ? simpleApiCaseList.size() : 0; + List fakeList = simpleAllApiCaseList.stream().filter(t -> StringUtils.equalsIgnoreCase(t.getLastReportStatus(), ResultStatus.FAKE_ERROR.name())).toList(); int fakeSize = CollectionUtils.isNotEmpty(fakeList) ? fakeList.size() : 0; List execDTOS = getExecDTOS((int) unDeleteCaseExecCount); @@ -1097,7 +1115,7 @@ public class DashboardService { statusStatisticsMap.put("execRate", execRateDTOS); List passRateDTOS = getPassRateDTOS(successSize, errorSize, simpleAllApiCaseSize, Translator.get("api_management.apiCasePassRate")); statusStatisticsMap.put("passRate", passRateDTOS); - List apiCaseDTOS = getApiCaseDTOS(fakeSize, simpleApiCaseSize, Translator.get("api_management.apiCaseCount")); + List apiCaseDTOS = getApiCaseDTOS(fakeSize, simpleAllApiCaseSize, Translator.get("api_management.apiCaseCount")); statusStatisticsMap.put("apiCaseCount", apiCaseDTOS); statisticsDTO.setStatusStatisticsMap(statusStatisticsMap); return statisticsDTO; @@ -1169,10 +1187,9 @@ public class DashboardService { statisticsDTO.setErrorCode(NO_PROJECT_PERMISSION.getCode()); return statisticsDTO; } - Long toStartTime = request.getToStartTime(); - Long toEndTime = request.getToEndTime(); + Map> statusStatisticsMap = new HashMap<>(); - long unDeleteCaseExecCount = extExecTaskItemMapper.getUnDeleteScenarioExecCount(projectId, toStartTime, toEndTime, List.of("PLAN_RUN_API_SCENARIO", "API_SCENARIO")); + long unDeleteCaseExecCount = extExecTaskItemMapper.getUnDeleteScenarioExecCount(projectId, null, null, List.of("PLAN_RUN_API_SCENARIO", "API_SCENARIO")); List simpleAllApiScenarioList = extApiScenarioMapper.getSimpleApiScenarioList(projectId, null, null); int simpleAllApiScenarioSize = 0; @@ -1187,9 +1204,7 @@ public class DashboardService { List errorList = simpleAllApiScenarioList.stream().filter(t -> StringUtils.equalsIgnoreCase(t.getLastReportStatus(), ResultStatus.ERROR.name())).toList(); int errorSize = CollectionUtils.isNotEmpty(errorList) ? errorList.size() : 0; - List simpleApiScenarioList = extApiScenarioMapper.getSimpleApiScenarioList(projectId, toStartTime, toEndTime); - List fakeList = simpleApiScenarioList.stream().filter(t -> StringUtils.equalsIgnoreCase(t.getLastReportStatus(), ResultStatus.FAKE_ERROR.name())).toList(); - int simpleApiCaseSize = CollectionUtils.isNotEmpty(simpleApiScenarioList) ? simpleApiScenarioList.size() : 0; + List fakeList = simpleAllApiScenarioList.stream().filter(t -> StringUtils.equalsIgnoreCase(t.getLastReportStatus(), ResultStatus.FAKE_ERROR.name())).toList(); int fakeSize = CollectionUtils.isNotEmpty(fakeList) ? fakeList.size() : 0; List execDTOS = getExecDTOS((int) unDeleteCaseExecCount); @@ -1198,25 +1213,40 @@ public class DashboardService { statusStatisticsMap.put("execRate", execRateDTOS); List passRateDTOS = getPassRateDTOS(successSize, errorSize, simpleAllApiScenarioSize, Translator.get("api_management.scenarioPassRate")); statusStatisticsMap.put("passRate", passRateDTOS); - List apiCaseDTOS = getApiCaseDTOS(fakeSize, simpleApiCaseSize, Translator.get("api_management.apiScenarioCount")) ; + List apiCaseDTOS = getApiCaseDTOS(fakeSize, simpleAllApiScenarioSize, Translator.get("api_management.apiScenarioCount")); statusStatisticsMap.put("apiScenarioCount", apiCaseDTOS); statisticsDTO.setStatusStatisticsMap(statusStatisticsMap); return statisticsDTO; } - public StatisticsDTO baseProjectBugCount(DashboardFrontPageRequest request, String userId, Boolean hasHandleUser, Boolean hasCreateUser){ + public StatisticsDTO baseProjectBugCount(DashboardFrontPageRequest request, String userId, Boolean hasHandleUser, Boolean hasCreateUser) { String projectId = request.getProjectIds().getFirst(); StatisticsDTO statisticsDTO = new StatisticsDTO(); if (Boolean.FALSE.equals(permissionCheckService.checkModule(projectId, BUG_MODULE, userId, PermissionConstants.PROJECT_BUG_READ))) { statisticsDTO.setErrorCode(NO_PROJECT_PERMISSION.getCode()); return statisticsDTO; } - Long toStartTime = request.getToStartTime(); - Long toEndTime = request.getToEndTime(); String handleUser = hasHandleUser ? userId : null; - String createUser = hasCreateUser ? userId :null; + String createUser = hasCreateUser ? userId : null; Set platforms = getPlatforms(projectId); List allSimpleList = extBugMapper.getSimpleList(projectId, null, null, handleUser, createUser, platforms); + List localLastStepStatus = getBugEndStatus(projectId); + List statusList = allSimpleList.stream().filter(t -> !localLastStepStatus.contains(t.getStatus())).toList(); + int statusSize = CollectionUtils.isEmpty(statusList) ? 0 : statusList.size(); + int totalSize = CollectionUtils.isEmpty(allSimpleList) ? 0 : allSimpleList.size(); + List nameCountDTOS = buildBugRetentionRateList(totalSize, statusSize); + Map> statusStatisticsMap = new HashMap<>(); + statusStatisticsMap.put("retentionRate", nameCountDTOS); + List headerStatusOption = bugStatusService.getHeaderStatusOption(projectId); + Map> bugMap = allSimpleList.stream().collect(Collectors.groupingBy(Bug::getStatus)); + List bugPercentList = bulidBugPercentList(headerStatusOption, bugMap, totalSize); + statisticsDTO.setStatusStatisticsMap(statusStatisticsMap); + statisticsDTO.setStatusPercentList(bugPercentList); + return statisticsDTO; + } + + @NotNull + private List getBugEndStatus(String projectId) { List localLastStepStatus = bugCommonService.getLocalLastStepStatus(projectId); List platformLastStepStatus = new ArrayList<>(); try { @@ -1225,29 +1255,15 @@ public class DashboardService { throw new RuntimeException(e); } localLastStepStatus.addAll(platformLastStepStatus); - List statusList = allSimpleList.stream().filter(t -> !localLastStepStatus.contains(t.getStatus())).toList(); - int statusSize = CollectionUtils.isEmpty(statusList) ? 0 : statusList.size(); - int totalSize = CollectionUtils.isEmpty(allSimpleList) ? 0 : allSimpleList.size(); - List nameCountDTOS = buildBugRetentionRateList(totalSize, statusSize); - Map> statusStatisticsMap = new HashMap<>(); - statusStatisticsMap.put("retentionRate",nameCountDTOS); - List headerStatusOption = bugStatusService.getHeaderStatusOption(projectId); - List simpleList = extBugMapper.getSimpleList(projectId, toStartTime, toEndTime,handleUser, createUser, platforms); - Map> bugMap = simpleList.stream().collect(Collectors.groupingBy(Bug::getStatus)); - List bugPercentList = bulidBugPercentList(headerStatusOption, bugMap, simpleList); - statisticsDTO.setStatusStatisticsMap(statusStatisticsMap); - statisticsDTO.setStatusPercentList(bugPercentList); - return statisticsDTO; + return localLastStepStatus; } - - private static List buildBugRetentionRateList(int totalSize, int statusSize) { List retentionRates = new ArrayList<>(); NameCountDTO retentionRate = new NameCountDTO(); retentionRate.setName(Translator.get("bug_management.retentionRate")); - if (totalSize ==0) { + if (totalSize == 0) { retentionRate.setCount(0); } else { BigDecimal divide = BigDecimal.valueOf(statusSize).divide(BigDecimal.valueOf(totalSize), 2, RoundingMode.HALF_UP); @@ -1261,9 +1277,8 @@ public class DashboardService { return retentionRates; } - private static List bulidBugPercentList(List headerStatusOption, Map> bugMap, List simpleList) { - ListstatusPercentList = new ArrayList<>(); - int simpleSize = CollectionUtils.isEmpty(simpleList) ? 0 : simpleList.size(); + private static List bulidBugPercentList(List headerStatusOption, Map> bugMap, int simpleSize) { + List statusPercentList = new ArrayList<>(); for (SelectOption selectOption : headerStatusOption) { StatusPercentDTO statusPercentDTO = new StatusPercentDTO(); statusPercentDTO.setStatus(selectOption.getText()); @@ -1283,15 +1298,54 @@ public class DashboardService { } public StatisticsDTO projectBugCount(DashboardFrontPageRequest request, String userId) { - return baseProjectBugCount(request,userId,false,false); + return baseProjectBugCount(request, userId, false, false); } public StatisticsDTO projectBugCountCreateByMe(DashboardFrontPageRequest request, String userId) { - return baseProjectBugCount(request,userId,false,true); + return baseProjectBugCount(request, userId, false, true); } public StatisticsDTO projectBugCountHandleByMe(DashboardFrontPageRequest request, String userId) { - return baseProjectBugCount(request,userId,true,false); + return baseProjectBugCount(request, userId, true, false); + } + + public StatisticsDTO projectPlanLegacyBug(DashboardFrontPageRequest request, String userId) { + String projectId = request.getProjectIds().getFirst(); + StatisticsDTO statisticsDTO = new StatisticsDTO(); + if (Boolean.FALSE.equals(permissionCheckService.checkModule(projectId, TEST_PLAN_MODULE, userId, PermissionConstants.TEST_PLAN_READ))) { + statisticsDTO.setErrorCode(NO_PROJECT_PERMISSION.getCode()); + return statisticsDTO; + } + Set platforms = getPlatforms(projectId); + List planBugList = extTestPlanMapper.getPlanBugList(projectId, TestPlanConstants.TEST_PLAN_TYPE_PLAN, new ArrayList<>(platforms), null); + List localLastStepStatus = getBugEndStatus(projectId); + List legacyBugList = planBugList.stream().filter(t -> !localLastStepStatus.contains(t.getText())).toList(); + List headerStatusOption = bugStatusService.getHeaderStatusOption(projectId); + int statusSize = CollectionUtils.isEmpty(legacyBugList) ? 0 : legacyBugList.size(); + int totalSize = CollectionUtils.isEmpty(planBugList) ? 0 : planBugList.size(); + List nameCountDTOS = buildBugRetentionRateList(totalSize, statusSize); + Map> statusStatisticsMap = new HashMap<>(); + statusStatisticsMap.put("retentionRate", nameCountDTOS); + Map> bugMap = legacyBugList.stream().collect(Collectors.groupingBy(SelectOption::getValue)); + List statusPercentList = new ArrayList<>(); + for (SelectOption selectOption : headerStatusOption) { + StatusPercentDTO statusPercentDTO = new StatusPercentDTO(); + statusPercentDTO.setStatus(selectOption.getText()); + List bugs = bugMap.get(selectOption.getValue()); + int bugSize = CollectionUtils.isEmpty(bugs) ? 0 : bugs.size(); + if (statusSize == 0) { + statusPercentDTO.setPercentValue("0%"); + statusPercentDTO.setCount(0); + } else { + BigDecimal divide = BigDecimal.valueOf(bugSize).divide(BigDecimal.valueOf(statusSize), 2, RoundingMode.HALF_UP); + statusPercentDTO.setPercentValue(divide.multiply(BigDecimal.valueOf(100)) + "%"); + statusPercentDTO.setCount(bugSize); + } + statusPercentList.add(statusPercentDTO); + } + statisticsDTO.setStatusStatisticsMap(statusStatisticsMap); + statisticsDTO.setStatusPercentList(statusPercentList); + return statisticsDTO; } } diff --git a/backend/services/dashboard/src/test/java/io/metersphere/dashboard/controller/DashboardFrontPageControllerTests.java b/backend/services/dashboard/src/test/java/io/metersphere/dashboard/controller/DashboardFrontPageControllerTests.java index 5abc451dc4..39bee52cbd 100644 --- a/backend/services/dashboard/src/test/java/io/metersphere/dashboard/controller/DashboardFrontPageControllerTests.java +++ b/backend/services/dashboard/src/test/java/io/metersphere/dashboard/controller/DashboardFrontPageControllerTests.java @@ -93,6 +93,7 @@ public class DashboardFrontPageControllerTests extends BaseTest { private static final String BUG_COUNT = "/dashboard/bug_count"; private static final String CREATE_BUG_BY_ME = "/dashboard/create_bug_by_me"; private static final String HANDLE_BUG_BY_ME = "/dashboard/handle_bug_by_me"; + private static final String PLAN_LEGACY_BUG = "/dashboard/plan_legacy_bug"; @@ -195,7 +196,7 @@ public class DashboardFrontPageControllerTests extends BaseTest { String contentAsString = mvcResultGrt.getResponse().getContentAsString(StandardCharsets.UTF_8); ResultHolder resultHolder = JSON.parseObject(contentAsString, ResultHolder.class); List layoutDTOS = JSON.parseArray(JSON.toJSONString(resultHolder.getData()), LayoutDTO.class); - Assertions.assertEquals(3, layoutDTOS.size()); + Assertions.assertEquals(0, layoutDTOS.size()); ProjectExample projectExample = new ProjectExample(); projectExample.createCriteria().andOrganizationIdEqualTo(DEFAULT_ORGANIZATION_ID); @@ -304,8 +305,7 @@ public class DashboardFrontPageControllerTests extends BaseTest { dashboardFrontPageRequest.setCurrent(1); dashboardFrontPageRequest.setPageSize(5); dashboardFrontPageRequest.setProjectIds(List.of(DEFAULT_PROJECT_ID)); - List headerStatusOption = bugStatusService.getHeaderStatusOption(DEFAULT_PROJECT_ID); - buildBug(headerStatusOption); + MvcResult mvcResult = this.requestPostWithOkAndReturn(CASE_COUNT, dashboardFrontPageRequest); String contentAsString = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8); ResultHolder resultHolder = JSON.parseObject(contentAsString, ResultHolder.class); @@ -352,6 +352,11 @@ public class DashboardFrontPageControllerTests extends BaseTest { ResultHolder handleBugResultHolder = JSON.parseObject(handleBugContentAsString, ResultHolder.class); StatisticsDTO handleBugCount = JSON.parseObject(JSON.toJSONString(handleBugResultHolder.getData()), StatisticsDTO.class); Assertions.assertNotNull(handleBugCount); + MvcResult planBugMvcResult = this.requestPostWithOkAndReturn(PLAN_LEGACY_BUG, dashboardFrontPageRequest); + String planBugContentAsString = planBugMvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8); + ResultHolder planBugResultHolder = JSON.parseObject(planBugContentAsString, ResultHolder.class); + StatisticsDTO planBugCount = JSON.parseObject(JSON.toJSONString(planBugResultHolder.getData()), StatisticsDTO.class); + Assertions.assertNotNull(planBugCount); Project project = new Project(); project.setModuleSetting("[]"); @@ -406,6 +411,11 @@ public class DashboardFrontPageControllerTests extends BaseTest { handleBugCount = JSON.parseObject(JSON.toJSONString(handleBugResultHolder.getData()), StatisticsDTO.class); Assertions.assertNotNull(handleBugCount); + planBugMvcResult = this.requestPostWithOkAndReturn(PLAN_LEGACY_BUG, dashboardFrontPageRequest); + planBugContentAsString = planBugMvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8); + planBugResultHolder = JSON.parseObject(planBugContentAsString, ResultHolder.class); + planBugCount = JSON.parseObject(JSON.toJSONString(planBugResultHolder.getData()), StatisticsDTO.class); + Assertions.assertNotNull(planBugCount); project.setModuleSetting("[\"apiTest\",\"testPlan\",\"caseManagement\",\"bugManagement\"]"); project.setId(DEFAULT_PROJECT_ID); @@ -462,6 +472,12 @@ public class DashboardFrontPageControllerTests extends BaseTest { handleBugCount = JSON.parseObject(JSON.toJSONString(handleBugResultHolder.getData()), StatisticsDTO.class); Assertions.assertNotNull(handleBugCount); + planBugMvcResult = this.requestPostWithOkAndReturn(PLAN_LEGACY_BUG, dashboardFrontPageRequest); + planBugContentAsString = planBugMvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8); + planBugResultHolder = JSON.parseObject(planBugContentAsString, ResultHolder.class); + planBugCount = JSON.parseObject(JSON.toJSONString(planBugResultHolder.getData()), StatisticsDTO.class); + Assertions.assertNotNull(planBugCount); + } @Test diff --git a/backend/services/dashboard/src/test/resources/dml/init_dashboard.sql b/backend/services/dashboard/src/test/resources/dml/init_dashboard.sql index f97444abbf..77846b212d 100644 --- a/backend/services/dashboard/src/test/resources/dml/init_dashboard.sql +++ b/backend/services/dashboard/src/test/resources/dml/init_dashboard.sql @@ -110,6 +110,17 @@ VALUES ('dashboard_scenario_four', 'api_scenario', 'p1', 'test-api-status', 'ER INSERT INTO api_scenario_step(id, scenario_id, name, sort, enable, resource_id, resource_num, step_type, project_id, parent_id, version_id, ref_type, origin_project_id, config) VALUE ('dashboard_act_1', 'dashboard_sc_1', 'dd', 1, true, 'dashboard_api_definition_id_1', '1000', 'API', '100001100001', null, 'oasis_ac_version_id', 'REF', '100001100001', null); + +INSERT INTO bug_relation_case(id, case_id, bug_id, case_type, test_plan_id, test_plan_case_id, create_user, create_time, update_time) +VALUES ('dashboard_bug-relate-case-default-id', 'bug_relate_case', 'dashboard_bug1', 'FUNCTIONAL', 'dashboard_test-plan-id', null, 'admin', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000), + ('dashboard_bug-relate-case-default-id-1', 'bug_relate_case', 'dashboard_bug2', 'FUNCTIONAL', 'dashboard_test-plan-id', 'bug_relate_case', 'admin', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000), + ('dashboard_bug-relate-case-default-id-2', 'bug_relate_case-1', 'dashboard_bug3', 'FUNCTIONAL', 'dashboard_test-plan-id', 'bug_relate_case-1', 'admin', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000), + ('dashboard_bug-relate-case-default-id-3', null, 'dashboard_bug1', 'FUNCTIONAL', 'dashboard_test-plan-id', 'bug_relate_case-3', 'admin', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000); + +INSERT INTO test_plan(id, num, project_id, group_id, module_id, name, status, type, tags, create_time, create_user, update_time, update_user, planned_start_time, planned_end_time, actual_start_time, actual_end_time, description) + VALUE ('dashboard_test-plan-id', 500, '100001100001', 'NONE', 'case_plan_module', 'test_plan_associate_case_name_three', 'NOT_ARCHIVED', 'TEST_PLAN', null, UNIX_TIMESTAMP() * 1000,'admin', + UNIX_TIMESTAMP() * 1000,'admin',UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, null); + INSERT INTO project_application (project_id, type, type_value) VALUES ('100001100001', 'BUG_SYNC_BUG_PLATFORM_CONFIG', '{"jiraKey":"TES","jiraBugTypeId":"10009"}'), ('100001100001', 'BUG_SYNC_PLATFORM_KEY', 'jira'), diff --git a/backend/services/project-management/src/main/java/io/metersphere/project/mapper/ExtProjectMapper.xml b/backend/services/project-management/src/main/java/io/metersphere/project/mapper/ExtProjectMapper.xml index 9f0b991747..d96048f300 100644 --- a/backend/services/project-management/src/main/java/io/metersphere/project/mapper/ExtProjectMapper.xml +++ b/backend/services/project-management/src/main/java/io/metersphere/project/mapper/ExtProjectMapper.xml @@ -134,7 +134,7 @@ - - +