refactor(测试计划): 优化测试计划组生成明细和明细查询的逻辑

--bug=1048250 --user=宋昌昌 【测试计划】计划组-执行历史-查看停止执行结果-报告未展示用例明细 https://www.tapd.cn/55049933/s/1611441
This commit is contained in:
song-cc-rock 2024-11-18 17:09:49 +08:00 committed by Craftsman
parent 4e4a68b11a
commit 54269d69b4
22 changed files with 397 additions and 314 deletions

View File

@ -25,6 +25,7 @@ api_management.unPassCount=未通过
bug_management.retentionRate=遗留率 bug_management.retentionRate=遗留率
bug_management.totalCount=缺陷总数 bug_management.totalCount=缺陷总数
bug_management.retentionCount=遗留缺陷数 bug_management.retentionCount=遗留缺陷数
get_platform_end_status_error=获取平台结束状态失败

View File

@ -25,3 +25,4 @@ api_management.unPassCount=Un pass
bug_management.retentionRate=Retention rate bug_management.retentionRate=Retention rate
bug_management.totalCount=Bug total count bug_management.totalCount=Bug total count
bug_management.retentionCount=Retention count bug_management.retentionCount=Retention count
get_platform_end_status_error=Failed to get the end status of the platform

View File

@ -26,3 +26,4 @@ api_management.unPassCount=未通过
bug_management.retentionRate=遗留率 bug_management.retentionRate=遗留率
bug_management.totalCount=缺陷总数 bug_management.totalCount=缺陷总数
bug_management.retentionCount=遗留缺陷数 bug_management.retentionCount=遗留缺陷数
get_platform_end_status_error=获取平台结束状态失败

View File

@ -136,5 +136,5 @@ public interface ExtBugMapper {
*/ */
List<ProjectUserStatusCountDTO> projectUserBugStatusCount(@Param("projectId") String projectId, @Param("startTime") Long startTime, @Param("endTime") Long endTime, @Param("userIds") List<String> userIds, @Param("platforms") Set<String> platforms); List<ProjectUserStatusCountDTO> projectUserBugStatusCount(@Param("projectId") String projectId, @Param("startTime") Long startTime, @Param("endTime") Long endTime, @Param("userIds") List<String> userIds, @Param("platforms") Set<String> platforms);
List<Bug>getSimpleList(@Param("projectId") String projectId, @Param("startTime") Long startTime, @Param("endTime") Long endTime,@Param("handleUser") String handleUser,@Param("createUser") String createUser, @Param("platforms") Set<String> platforms); List<Bug>getSimpleList(@Param("projectId") String projectId, @Param("startTime") Long startTime, @Param("endTime") Long endTime,@Param("handleUser") String handleUser,@Param("createUser") String createUser, @Param("platforms") Set<String> platforms, @Param("currentUser") String currentUser);
} }

View File

@ -457,8 +457,16 @@
<if test="startTime != null and endTime != null"> <if test="startTime != null and endTime != null">
AND bug.create_time BETWEEN #{startTime} AND #{endTime} AND bug.create_time BETWEEN #{startTime} AND #{endTime}
</if> </if>
<if test="handleUser != null or currentUser != null">
AND (
FALSE
<if test="handleUser != null and handleUser != ''"> <if test="handleUser != null and handleUser != ''">
AND bug.handle_user = #{handleUser} OR bug.handle_user = #{handleUser}
</if>
<if test="currentUser != null and currentUser != ''">
OR bug.handle_user = #{currentUser}
</if>
)
</if> </if>
<if test="createUser != null and createUser != ''"> <if test="createUser != null and createUser != ''">
AND bug.create_user = #{createUser} AND bug.create_user = #{createUser}

View File

@ -25,6 +25,7 @@ import io.metersphere.system.domain.ServiceIntegration;
import io.metersphere.system.service.FileService; import io.metersphere.system.service.FileService;
import io.metersphere.system.service.PlatformPluginService; import io.metersphere.system.service.PlatformPluginService;
import io.metersphere.system.service.PluginLoadService; import io.metersphere.system.service.PluginLoadService;
import io.metersphere.system.service.UserPlatformAccountService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.commons.collections4.ListUtils; import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -34,6 +35,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Service @Service
@ -68,6 +70,8 @@ public class BugCommonService {
private BugLocalAttachmentMapper bugLocalAttachmentMapper; private BugLocalAttachmentMapper bugLocalAttachmentMapper;
@Resource @Resource
private ProjectApplicationService projectApplicationService; private ProjectApplicationService projectApplicationService;
@Resource
private UserPlatformAccountService userPlatformAccountService;
/** /**
* 获取表头处理人选项 * 获取表头处理人选项
@ -211,4 +215,26 @@ public class BugCommonService {
List<SelectOption> platformLastSteps = platform.getStatusTransitionsLastSteps(projectApplicationService.getProjectBugThirdPartConfig(projectId)); List<SelectOption> platformLastSteps = platform.getStatusTransitionsLastSteps(projectApplicationService.getProjectBugThirdPartConfig(projectId));
return platformLastSteps.stream().map(SelectOption::getValue).toList(); return platformLastSteps.stream().map(SelectOption::getValue).toList();
} }
/**
* 获取登录用户平台处理人
* @param projectId 项目ID
* @param currentUserId 当前用户ID
* @param currentOrgId 当前组织ID
* @return 平台处理人
*/
public String getPlatformHandlerUser(String projectId, String currentUserId, String currentOrgId) {
ServiceIntegration serviceIntegration = projectApplicationService.getPlatformServiceIntegrationWithSyncOrDemand(projectId, true);
String platformUserName = userPlatformAccountService.getPlatformUserName(currentUserId, currentOrgId, serviceIntegration.getPluginId());
List<SelectOption> headerHandlerOption = getHeaderHandlerOption(projectId);
if (StringUtils.isNotBlank(platformUserName)) {
Optional<SelectOption> handleOption = headerHandlerOption.stream().filter(option -> StringUtils.containsAnyIgnoreCase(option.getText(), platformUserName))
.findFirst();
if (handleOption.isPresent()) {
return handleOption.get().getValue();
}
return platformUserName;
}
return null;
}
} }

View File

@ -3,6 +3,7 @@ package io.metersphere.dashboard.controller;
import com.github.pagehelper.Page; import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageHelper;
import io.metersphere.api.dto.definition.ApiDefinitionUpdateDTO; import io.metersphere.api.dto.definition.ApiDefinitionUpdateDTO;
import io.metersphere.bug.service.BugCommonService;
import io.metersphere.dashboard.dto.LayoutDTO; import io.metersphere.dashboard.dto.LayoutDTO;
import io.metersphere.dashboard.request.DashboardFrontPageRequest; import io.metersphere.dashboard.request.DashboardFrontPageRequest;
import io.metersphere.dashboard.response.OverViewCountDTO; import io.metersphere.dashboard.response.OverViewCountDTO;
@ -35,6 +36,8 @@ public class DashboardController {
@Resource @Resource
private DashboardService dashboardService; private DashboardService dashboardService;
@Resource @Resource
private BugCommonService bugCommonService;
@Resource
private PermissionCheckService permissionCheckService; private PermissionCheckService permissionCheckService;
@PostMapping("/layout/edit/{organizationId}") @PostMapping("/layout/edit/{organizationId}")
@ -133,21 +136,22 @@ public class DashboardController {
@Operation(summary = "缺陷数量统计") @Operation(summary = "缺陷数量统计")
@CheckOwner(resourceId = "#request.getOrganizationId()", resourceType = "organization") @CheckOwner(resourceId = "#request.getOrganizationId()", resourceType = "organization")
public StatisticsDTO projectBugCount(@Validated @RequestBody DashboardFrontPageRequest request) { public StatisticsDTO projectBugCount(@Validated @RequestBody DashboardFrontPageRequest request) {
return dashboardService.projectBugCount(request, SessionUtils.getUserId()); return dashboardService.projectBugCount(request, SessionUtils.getUserId(), null);
} }
@PostMapping("/create_bug_by_me") @PostMapping("/create_bug_by_me")
@Operation(summary = "我创建的缺陷") @Operation(summary = "我创建的缺陷")
@CheckOwner(resourceId = "#request.getOrganizationId()", resourceType = "organization") @CheckOwner(resourceId = "#request.getOrganizationId()", resourceType = "organization")
public StatisticsDTO projectBugCountCreateByMe(@Validated @RequestBody DashboardFrontPageRequest request) { public StatisticsDTO projectBugCountCreateByMe(@Validated @RequestBody DashboardFrontPageRequest request) {
return dashboardService.projectBugCountCreateByMe(request, SessionUtils.getUserId()); return dashboardService.projectBugCountCreateByMe(request, SessionUtils.getUserId(), null);
} }
@PostMapping("/handle_bug_by_me") @PostMapping("/handle_bug_by_me")
@Operation(summary = "待我处理的缺陷") @Operation(summary = "待我处理的缺陷")
@CheckOwner(resourceId = "#request.getOrganizationId()", resourceType = "organization") @CheckOwner(resourceId = "#request.getOrganizationId()", resourceType = "organization")
public StatisticsDTO projectBugCountHandleByMe(@Validated @RequestBody DashboardFrontPageRequest request) { public StatisticsDTO projectBugCountHandleByMe(@Validated @RequestBody DashboardFrontPageRequest request) {
return dashboardService.projectBugCountHandleByMe(request, SessionUtils.getUserId()); String platformHandlerUser = bugCommonService.getPlatformHandlerUser(request.getProjectIds().getFirst(), SessionUtils.getUserId(), SessionUtils.getCurrentOrganizationId());
return dashboardService.projectBugCountHandleByMe(request, SessionUtils.getUserId(), platformHandlerUser);
} }
@PostMapping("/plan_legacy_bug") @PostMapping("/plan_legacy_bug")

View File

@ -16,10 +16,8 @@ import io.metersphere.plan.dto.response.TestPlanResponse;
import io.metersphere.plan.dto.response.TestPlanStatisticsResponse; import io.metersphere.plan.dto.response.TestPlanStatisticsResponse;
import io.metersphere.plan.service.TestPlanManagementService; import io.metersphere.plan.service.TestPlanManagementService;
import io.metersphere.plan.service.TestPlanStatisticsService; import io.metersphere.plan.service.TestPlanStatisticsService;
import io.metersphere.plugin.platform.dto.SelectOption;
import io.metersphere.project.service.ProjectApplicationService; import io.metersphere.project.service.ProjectApplicationService;
import io.metersphere.sdk.util.LogUtils; import io.metersphere.sdk.util.LogUtils;
import io.metersphere.system.domain.ServiceIntegration;
import io.metersphere.system.security.CheckOwner; import io.metersphere.system.security.CheckOwner;
import io.metersphere.system.service.UserPlatformAccountService; import io.metersphere.system.service.UserPlatformAccountService;
import io.metersphere.system.utils.PageUtils; import io.metersphere.system.utils.PageUtils;
@ -118,15 +116,8 @@ public class ToDoController {
return todoParam; return todoParam;
} }
todoParam.setCurrentPlatform(platformName); todoParam.setCurrentPlatform(platformName);
List<String> platformLastStepStatus = bugCommonService.getPlatformLastStepStatus(request.getProjectId()); todoParam.setPlatformLastStatus(bugCommonService.getPlatformLastStepStatus(request.getProjectId()));
todoParam.setPlatformLastStatus(platformLastStepStatus); todoParam.setPlatformUser(bugCommonService.getPlatformHandlerUser(request.getProjectId(), currentUserId, currentOrgId));
ServiceIntegration serviceIntegration = projectApplicationService.getPlatformServiceIntegrationWithSyncOrDemand(request.getProjectId(), true);
String platformUserName = userPlatformAccountService.getPlatformUserName(currentUserId, currentOrgId, serviceIntegration.getPluginId());
List<SelectOption> headerHandlerOption = bugCommonService.getHeaderHandlerOption(request.getProjectId());
if (StringUtils.isNotBlank(platformUserName)) {
headerHandlerOption.stream().filter(option -> StringUtils.containsAnyIgnoreCase(option.getText(), platformUserName))
.findFirst().ifPresent(option -> todoParam.setPlatformUser(option.getValue()));
}
} catch (Exception e) { } catch (Exception e) {
// 设置平台参数异常时, 无法正常过滤平台非结束的缺陷 // 设置平台参数异常时, 无法正常过滤平台非结束的缺陷
LogUtils.error(e.getMessage()); LogUtils.error(e.getMessage());

View File

@ -52,6 +52,7 @@ import io.metersphere.sdk.constants.TestPlanConstants;
import io.metersphere.sdk.dto.CombineCondition; import io.metersphere.sdk.dto.CombineCondition;
import io.metersphere.sdk.dto.CombineSearch; import io.metersphere.sdk.dto.CombineSearch;
import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.LogUtils;
import io.metersphere.sdk.util.Translator; import io.metersphere.sdk.util.Translator;
import io.metersphere.system.domain.UserLayout; import io.metersphere.system.domain.UserLayout;
import io.metersphere.system.domain.UserLayoutExample; import io.metersphere.system.domain.UserLayoutExample;
@ -1234,17 +1235,18 @@ public class DashboardService {
return statisticsDTO; return statisticsDTO;
} }
public StatisticsDTO baseProjectBugCount(DashboardFrontPageRequest request, String userId, Boolean hasHandleUser, Boolean hasCreateUser) { public StatisticsDTO baseProjectBugCount(DashboardFrontPageRequest request, String userId, String handleUserId, Boolean hasHandleUser, Boolean hasCreateUser) {
String projectId = request.getProjectIds().getFirst(); String projectId = request.getProjectIds().getFirst();
StatisticsDTO statisticsDTO = new StatisticsDTO(); StatisticsDTO statisticsDTO = new StatisticsDTO();
if (Boolean.FALSE.equals(permissionCheckService.checkModule(projectId, BUG_MODULE, userId, PermissionConstants.PROJECT_BUG_READ))) { if (Boolean.FALSE.equals(permissionCheckService.checkModule(projectId, BUG_MODULE, userId, PermissionConstants.PROJECT_BUG_READ))) {
statisticsDTO.setErrorCode(NO_PROJECT_PERMISSION.getCode()); statisticsDTO.setErrorCode(NO_PROJECT_PERMISSION.getCode());
return statisticsDTO; return statisticsDTO;
} }
String handleUser = hasHandleUser ? userId : null; String localHandleUser = hasHandleUser ? userId : null;
String handleUser = hasHandleUser ? handleUserId : null;
String createUser = hasCreateUser ? userId : null; String createUser = hasCreateUser ? userId : null;
Set<String> platforms = getPlatforms(projectId); Set<String> platforms = getPlatforms(projectId);
List<Bug> allSimpleList = extBugMapper.getSimpleList(projectId, null, null, handleUser, createUser, platforms); List<Bug> allSimpleList = extBugMapper.getSimpleList(projectId, null, null, handleUser, createUser, platforms, localHandleUser);
List<String> localLastStepStatus = getBugEndStatus(projectId); List<String> localLastStepStatus = getBugEndStatus(projectId);
List<Bug> statusList = allSimpleList.stream().filter(t -> !localLastStepStatus.contains(t.getStatus())).toList(); List<Bug> statusList = allSimpleList.stream().filter(t -> !localLastStepStatus.contains(t.getStatus())).toList();
int statusSize = CollectionUtils.isEmpty(statusList) ? 0 : statusList.size(); int statusSize = CollectionUtils.isEmpty(statusList) ? 0 : statusList.size();
@ -1263,11 +1265,17 @@ public class DashboardService {
@NotNull @NotNull
private List<String> getBugEndStatus(String projectId) { private List<String> getBugEndStatus(String projectId) {
List<String> localLastStepStatus = bugCommonService.getLocalLastStepStatus(projectId); List<String> localLastStepStatus = bugCommonService.getLocalLastStepStatus(projectId);
String platformName = projectApplicationService.getPlatformName(projectId);
if (StringUtils.equalsIgnoreCase(platformName, BugPlatform.LOCAL.getName())) {
return localLastStepStatus;
}
// 项目对接三方平台
List<String> platformLastStepStatus = new ArrayList<>(); List<String> platformLastStepStatus = new ArrayList<>();
try { try {
platformLastStepStatus = bugCommonService.getPlatformLastStepStatus(projectId); platformLastStepStatus = bugCommonService.getPlatformLastStepStatus(projectId);
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); // 获取三方平台结束状态失败, 只过滤本地结束状态
LogUtils.error(Translator.get("get_platform_end_status_error"));
} }
localLastStepStatus.addAll(platformLastStepStatus); localLastStepStatus.addAll(platformLastStepStatus);
return localLastStepStatus; return localLastStepStatus;
@ -1312,16 +1320,16 @@ public class DashboardService {
return statusPercentList; return statusPercentList;
} }
public StatisticsDTO projectBugCount(DashboardFrontPageRequest request, String userId) { public StatisticsDTO projectBugCount(DashboardFrontPageRequest request, String userId, String handlerUser) {
return baseProjectBugCount(request, userId, false, false); return baseProjectBugCount(request, userId, handlerUser, false, false);
} }
public StatisticsDTO projectBugCountCreateByMe(DashboardFrontPageRequest request, String userId) { public StatisticsDTO projectBugCountCreateByMe(DashboardFrontPageRequest request, String userId, String handlerUser) {
return baseProjectBugCount(request, userId, false, true); return baseProjectBugCount(request, userId, handlerUser, false, true);
} }
public StatisticsDTO projectBugCountHandleByMe(DashboardFrontPageRequest request, String userId) { public StatisticsDTO projectBugCountHandleByMe(DashboardFrontPageRequest request, String userId, String handlerUser) {
return baseProjectBugCount(request, userId, true, false); return baseProjectBugCount(request, userId, handlerUser, true, false);
} }
public StatisticsDTO projectPlanLegacyBug(DashboardFrontPageRequest request, String userId) { public StatisticsDTO projectPlanLegacyBug(DashboardFrontPageRequest request, String userId) {

View File

@ -163,6 +163,7 @@ public class TestPlanReportController {
@RequiresPermissions(value = {PermissionConstants.TEST_PLAN_REPORT_READ, PermissionConstants.TEST_PLAN_READ_EXECUTE}, logical = Logical.OR) @RequiresPermissions(value = {PermissionConstants.TEST_PLAN_REPORT_READ, PermissionConstants.TEST_PLAN_READ_EXECUTE}, logical = Logical.OR)
@CheckOwner(resourceId = "#request.getReportId()", resourceType = "test_plan_report") @CheckOwner(resourceId = "#request.getReportId()", resourceType = "test_plan_report")
public Pager<List<BugDTO>> pageBug(@Validated @RequestBody TestPlanReportDetailPageRequest request) { public Pager<List<BugDTO>> pageBug(@Validated @RequestBody TestPlanReportDetailPageRequest request) {
request.setDetailReportIds(testPlanReportService.getActualReportIds(request.getReportId()));
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(), Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "tprb.bug_num, tprb.id desc"); StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "tprb.bug_num, tprb.id desc");
if (!request.getStartPager()) { if (!request.getStartPager()) {
@ -177,6 +178,7 @@ public class TestPlanReportController {
@RequiresPermissions(value = {PermissionConstants.TEST_PLAN_REPORT_READ, PermissionConstants.TEST_PLAN_READ_EXECUTE}, logical = Logical.OR) @RequiresPermissions(value = {PermissionConstants.TEST_PLAN_REPORT_READ, PermissionConstants.TEST_PLAN_READ_EXECUTE}, logical = Logical.OR)
@CheckOwner(resourceId = "#request.getReportId()", resourceType = "test_plan_report") @CheckOwner(resourceId = "#request.getReportId()", resourceType = "test_plan_report")
public Pager<List<ReportDetailCasePageDTO>> pageFunctionalCase(@Validated @RequestBody TestPlanReportDetailPageRequest request) { public Pager<List<ReportDetailCasePageDTO>> pageFunctionalCase(@Validated @RequestBody TestPlanReportDetailPageRequest request) {
request.setDetailReportIds(testPlanReportService.getActualReportIds(request.getReportId()));
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(), Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "tprfc.pos desc"); StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "tprfc.pos desc");
if (!request.getStartPager()) { if (!request.getStartPager()) {
@ -201,6 +203,7 @@ public class TestPlanReportController {
@RequiresPermissions(value = {PermissionConstants.TEST_PLAN_REPORT_READ, PermissionConstants.TEST_PLAN_READ_EXECUTE}, logical = Logical.OR) @RequiresPermissions(value = {PermissionConstants.TEST_PLAN_REPORT_READ, PermissionConstants.TEST_PLAN_READ_EXECUTE}, logical = Logical.OR)
@CheckOwner(resourceId = "#request.getReportId()", resourceType = "test_plan_report") @CheckOwner(resourceId = "#request.getReportId()", resourceType = "test_plan_report")
public Pager<List<ReportDetailCasePageDTO>> pageApiCase(@Validated @RequestBody TestPlanReportDetailPageRequest request) { public Pager<List<ReportDetailCasePageDTO>> pageApiCase(@Validated @RequestBody TestPlanReportDetailPageRequest request) {
request.setDetailReportIds(testPlanReportService.getActualReportIds(request.getReportId()));
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(), Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "tprac.pos desc"); StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "tprac.pos desc");
if (!request.getStartPager()) { if (!request.getStartPager()) {
@ -218,6 +221,7 @@ public class TestPlanReportController {
@RequiresPermissions(value = {PermissionConstants.TEST_PLAN_REPORT_READ, PermissionConstants.TEST_PLAN_READ_EXECUTE}, logical = Logical.OR) @RequiresPermissions(value = {PermissionConstants.TEST_PLAN_REPORT_READ, PermissionConstants.TEST_PLAN_READ_EXECUTE}, logical = Logical.OR)
@CheckOwner(resourceId = "#request.getReportId()", resourceType = "test_plan_report") @CheckOwner(resourceId = "#request.getReportId()", resourceType = "test_plan_report")
public Pager<List<ReportDetailCasePageDTO>> pageScenarioCase(@Validated @RequestBody TestPlanReportDetailPageRequest request) { public Pager<List<ReportDetailCasePageDTO>> pageScenarioCase(@Validated @RequestBody TestPlanReportDetailPageRequest request) {
request.setDetailReportIds(testPlanReportService.getActualReportIds(request.getReportId()));
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(), Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "tpras.pos desc"); StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "tpras.pos desc");
if (!request.getStartPager()) { if (!request.getStartPager()) {
@ -249,7 +253,6 @@ public class TestPlanReportController {
return testPlanReportService.previewMd(projectId, fileId, compressed); return testPlanReportService.previewMd(projectId, fileId, compressed);
} }
@PostMapping("/export/{reportId}") @PostMapping("/export/{reportId}")
@Operation(summary = "测试计划-报告-导出日志") @Operation(summary = "测试计划-报告-导出日志")
@RequiresPermissions(PermissionConstants.TEST_PLAN_REPORT_READ_EXPORT) @RequiresPermissions(PermissionConstants.TEST_PLAN_REPORT_READ_EXPORT)
@ -264,13 +267,13 @@ public class TestPlanReportController {
testPlanReportService.batchExportLog(request, SessionUtils.getUserId(), SessionUtils.getCurrentProjectId()); testPlanReportService.batchExportLog(request, SessionUtils.getUserId(), SessionUtils.getCurrentProjectId());
} }
@PostMapping("/detail/{type}/collection/page") @PostMapping("/detail/{type}/collection/page")
@Operation(summary = "测试计划-报告-详情-测试集分页查询(不同用例类型)") @Operation(summary = "测试计划-报告-详情-测试集分页查询(不同用例类型)")
@RequiresPermissions(value = {PermissionConstants.TEST_PLAN_REPORT_READ, PermissionConstants.TEST_PLAN_READ_EXECUTE}, logical = Logical.OR) @RequiresPermissions(value = {PermissionConstants.TEST_PLAN_REPORT_READ, PermissionConstants.TEST_PLAN_READ_EXECUTE}, logical = Logical.OR)
@CheckOwner(resourceId = "#request.getReportId()", resourceType = "test_plan_report") @CheckOwner(resourceId = "#request.getReportId()", resourceType = "test_plan_report")
@Parameter(name = "type", description = "用例类型", schema = @Schema(requiredMode = Schema.RequiredMode.REQUIRED), example = "functional, api, scenario") @Parameter(name = "type", description = "用例类型", schema = @Schema(requiredMode = Schema.RequiredMode.REQUIRED), example = "functional, api, scenario")
public Pager<List<TestPlanReportDetailCollectionResponse>> collectionPage(@PathVariable String type, @Validated @RequestBody TestPlanReportDetailPageRequest request) { public Pager<List<TestPlanReportDetailCollectionResponse>> collectionPage(@PathVariable String type, @Validated @RequestBody TestPlanReportDetailPageRequest request) {
request.setDetailReportIds(testPlanReportService.getActualReportIds(request.getReportId()));
// 默认按照测试集的位序升序 // 默认按照测试集的位序升序
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(), "tpc.pos asc"); Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(), "tpc.pos asc");
return PageUtils.setPageInfo(page, testPlanReportService.listReportCollection(request, type)); return PageUtils.setPageInfo(page, testPlanReportService.listReportCollection(request, type));

View File

@ -94,6 +94,7 @@ public class TestPlanReportShareController {
@PostMapping("/detail/bug/page") @PostMapping("/detail/bug/page")
@Operation(summary = "测试计划-报告-详情-缺陷分页查询") @Operation(summary = "测试计划-报告-详情-缺陷分页查询")
public Pager<List<BugDTO>> pageBug(@Validated @RequestBody TestPlanShareReportDetailRequest request) { public Pager<List<BugDTO>> pageBug(@Validated @RequestBody TestPlanShareReportDetailRequest request) {
request.setDetailReportIds(testPlanReportService.getActualReportIds(request.getReportId()));
ShareInfo shareInfo = testPlanReportShareService.checkResource(request.getShareId()); ShareInfo shareInfo = testPlanReportShareService.checkResource(request.getShareId());
testPlanReportShareService.validateExpired(shareInfo); testPlanReportShareService.validateExpired(shareInfo);
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(), Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
@ -104,6 +105,7 @@ public class TestPlanReportShareController {
@PostMapping("/detail/functional/case/page") @PostMapping("/detail/functional/case/page")
@Operation(summary = "测试计划-报告-详情-功能用例分页查询") @Operation(summary = "测试计划-报告-详情-功能用例分页查询")
public Pager<List<ReportDetailCasePageDTO>> pageFunctionalCase(@Validated @RequestBody TestPlanShareReportDetailRequest request) { public Pager<List<ReportDetailCasePageDTO>> pageFunctionalCase(@Validated @RequestBody TestPlanShareReportDetailRequest request) {
request.setDetailReportIds(testPlanReportService.getActualReportIds(request.getReportId()));
ShareInfo shareInfo = testPlanReportShareService.checkResource(request.getShareId()); ShareInfo shareInfo = testPlanReportShareService.checkResource(request.getShareId());
testPlanReportShareService.validateExpired(shareInfo); testPlanReportShareService.validateExpired(shareInfo);
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(), Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
@ -114,6 +116,7 @@ public class TestPlanReportShareController {
@PostMapping("/detail/api/case/page") @PostMapping("/detail/api/case/page")
@Operation(summary = "测试计划-报告-详情-接口用例分页查询") @Operation(summary = "测试计划-报告-详情-接口用例分页查询")
public Pager<List<ReportDetailCasePageDTO>> pageApiCase(@Validated @RequestBody TestPlanShareReportDetailRequest request) { public Pager<List<ReportDetailCasePageDTO>> pageApiCase(@Validated @RequestBody TestPlanShareReportDetailRequest request) {
request.setDetailReportIds(testPlanReportService.getActualReportIds(request.getReportId()));
ShareInfo shareInfo = testPlanReportShareService.checkResource(request.getShareId()); ShareInfo shareInfo = testPlanReportShareService.checkResource(request.getShareId());
testPlanReportShareService.validateExpired(shareInfo); testPlanReportShareService.validateExpired(shareInfo);
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(), Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
@ -124,6 +127,7 @@ public class TestPlanReportShareController {
@PostMapping("/detail/scenario/case/page") @PostMapping("/detail/scenario/case/page")
@Operation(summary = "测试计划-报告-详情-场景用例分页查询") @Operation(summary = "测试计划-报告-详情-场景用例分页查询")
public Pager<List<ReportDetailCasePageDTO>> pageScenarioCase(@Validated @RequestBody TestPlanShareReportDetailRequest request) { public Pager<List<ReportDetailCasePageDTO>> pageScenarioCase(@Validated @RequestBody TestPlanShareReportDetailRequest request) {
request.setDetailReportIds(testPlanReportService.getActualReportIds(request.getReportId()));
ShareInfo shareInfo = testPlanReportShareService.checkResource(request.getShareId()); ShareInfo shareInfo = testPlanReportShareService.checkResource(request.getShareId());
testPlanReportShareService.validateExpired(shareInfo); testPlanReportShareService.validateExpired(shareInfo);
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(), Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
@ -189,6 +193,7 @@ public class TestPlanReportShareController {
@Operation(summary = "测试计划-报告-详情-测试集分页查询(不同用例类型)") @Operation(summary = "测试计划-报告-详情-测试集分页查询(不同用例类型)")
@Parameter(name = "type", description = "用例类型", schema = @Schema(requiredMode = Schema.RequiredMode.REQUIRED), example = "functional, api, scenario") @Parameter(name = "type", description = "用例类型", schema = @Schema(requiredMode = Schema.RequiredMode.REQUIRED), example = "functional, api, scenario")
public Pager<List<TestPlanReportDetailCollectionResponse>> collectionPage(@PathVariable String type, @Validated @RequestBody TestPlanShareReportDetailRequest request) { public Pager<List<TestPlanReportDetailCollectionResponse>> collectionPage(@PathVariable String type, @Validated @RequestBody TestPlanShareReportDetailRequest request) {
request.setDetailReportIds(testPlanReportService.getActualReportIds(request.getReportId()));
ShareInfo shareInfo = testPlanReportShareService.checkResource(request.getShareId()); ShareInfo shareInfo = testPlanReportShareService.checkResource(request.getShareId());
testPlanReportShareService.validateExpired(shareInfo); testPlanReportShareService.validateExpired(shareInfo);
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(), Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),

View File

@ -6,6 +6,11 @@ import jakarta.validation.constraints.NotBlank;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import java.util.List;
/**
* @author song-cc-rock
*/
@Data @Data
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
public class TestPlanReportDetailPageRequest extends BasePageRequest { public class TestPlanReportDetailPageRequest extends BasePageRequest {
@ -19,4 +24,7 @@ public class TestPlanReportDetailPageRequest extends BasePageRequest {
@Schema(description = "测试集ID") @Schema(description = "测试集ID")
private String collectionId; private String collectionId;
@Schema(description = "报告ID集合")
private List<String> detailReportIds;
} }

View File

@ -14,10 +14,10 @@ public interface ExtTestPlanReportApiCaseMapper {
/** /**
* 统计报告中接口用例执行情况 * 统计报告中接口用例执行情况
* @param reportId 报告ID * @param reportIds 报告ID集合
* @return 用例数量 * @return 用例数量
*/ */
List<CaseStatusCountMap> countExecuteResult(@Param("id") String reportId); List<CaseStatusCountMap> countExecuteResult(@Param("ids") List<String> reportIds);
/** /**
* 获取计划关联的接口用例 * 获取计划关联的接口用例

View File

@ -3,7 +3,10 @@
<mapper namespace="io.metersphere.plan.mapper.ExtTestPlanReportApiCaseMapper"> <mapper namespace="io.metersphere.plan.mapper.ExtTestPlanReportApiCaseMapper">
<select id="countExecuteResult" resultType="io.metersphere.plan.dto.CaseStatusCountMap"> <select id="countExecuteResult" resultType="io.metersphere.plan.dto.CaseStatusCountMap">
select ifnull(tprac.api_case_execute_result, 'PENDING') as status, count(id) as count from test_plan_report_api_case tprac select ifnull(tprac.api_case_execute_result, 'PENDING') as status, count(id) as count from test_plan_report_api_case tprac
where tprac.test_plan_report_id = #{id} where tprac.test_plan_report_id in
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
group by tprac.api_case_execute_result group by tprac.api_case_execute_result
</select> </select>
@ -38,7 +41,10 @@
ifnull(tprac.api_case_execute_result, 'PENDING') as executeResult, tprac.api_case_execute_user as executeUser, atc.project_id projectId ifnull(tprac.api_case_execute_result, 'PENDING') as executeResult, tprac.api_case_execute_user as executeUser, atc.project_id projectId
from test_plan_report_api_case tprac left join api_test_case atc on tprac.api_case_id = atc.id from test_plan_report_api_case tprac left join api_test_case atc on tprac.api_case_id = atc.id
left join test_plan_collection tpc on tprac.test_plan_collection_id = tpc.id left join test_plan_collection tpc on tprac.test_plan_collection_id = tpc.id
where tprac.test_plan_report_id = #{request.reportId} where tprac.test_plan_report_id in
<foreach collection="request.detailReportIds" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
<if test="request.keyword != null and request.keyword != ''"> <if test="request.keyword != null and request.keyword != ''">
and (tprac.api_case_num like concat('%', #{request.keyword}, '%') and (tprac.api_case_num like concat('%', #{request.keyword}, '%')
or tprac.api_case_name like concat('%', #{request.keyword}, '%') or tprac.api_case_name like concat('%', #{request.keyword}, '%')
@ -55,7 +61,10 @@
from test_plan_report_api_case tprac from test_plan_report_api_case tprac
right join test_plan_collection tpc on tprac.test_plan_collection_id = tpc.id and tpc.type = 'API' right join test_plan_collection tpc on tprac.test_plan_collection_id = tpc.id and tpc.type = 'API'
join test_plan tp on tpc.test_plan_id = tp.id join test_plan tp on tpc.test_plan_id = tp.id
where tprac.test_plan_report_id = #{request.reportId} where tprac.test_plan_report_id in
<foreach collection="request.detailReportIds" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
<if test="request.keyword != null and request.keyword != ''"> <if test="request.keyword != null and request.keyword != ''">
and (tprac.api_case_name like concat('%', #{request.keyword}, '%') and (tprac.api_case_name like concat('%', #{request.keyword}, '%')
or tprac.api_case_num like concat('%', #{request.keyword}, '%') or tprac.api_case_num like concat('%', #{request.keyword}, '%')

View File

@ -14,10 +14,10 @@ public interface ExtTestPlanReportApiScenarioMapper {
/** /**
* 统计报告中场景用例执行情况 * 统计报告中场景用例执行情况
* @param reportId 报告ID * @param reportIds 报告ID集合
* @return 用例数量 * @return 用例数量
*/ */
List<CaseStatusCountMap> countExecuteResult(@Param("id") String reportId); List<CaseStatusCountMap> countExecuteResult(@Param("ids") List<String> reportIds);
/** /**
* 获取计划关联的场景用例 * 获取计划关联的场景用例

View File

@ -3,7 +3,10 @@
<mapper namespace="io.metersphere.plan.mapper.ExtTestPlanReportApiScenarioMapper"> <mapper namespace="io.metersphere.plan.mapper.ExtTestPlanReportApiScenarioMapper">
<select id="countExecuteResult" resultType="io.metersphere.plan.dto.CaseStatusCountMap"> <select id="countExecuteResult" resultType="io.metersphere.plan.dto.CaseStatusCountMap">
select ifnull(tpras.api_scenario_execute_result, 'PENDING') as status, count(id) as count from test_plan_report_api_scenario tpras select ifnull(tpras.api_scenario_execute_result, 'PENDING') as status, count(id) as count from test_plan_report_api_scenario tpras
where tpras.test_plan_report_id = #{id} where tpras.test_plan_report_id in
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
group by tpras.api_scenario_execute_result group by tpras.api_scenario_execute_result
</select> </select>
@ -37,7 +40,10 @@
ifnull(tpras.api_scenario_execute_result, 'PENDING') as executeResult, tpras.api_scenario_execute_user as executeUser, aso.project_id projectId ifnull(tpras.api_scenario_execute_result, 'PENDING') as executeResult, tpras.api_scenario_execute_user as executeUser, aso.project_id projectId
from test_plan_report_api_scenario tpras left join api_scenario aso on tpras.api_scenario_id = aso.id from test_plan_report_api_scenario tpras left join api_scenario aso on tpras.api_scenario_id = aso.id
left join test_plan_collection tpc on tpras.test_plan_collection_id = tpc.id left join test_plan_collection tpc on tpras.test_plan_collection_id = tpc.id
where tpras.test_plan_report_id = #{request.reportId} where tpras.test_plan_report_id in
<foreach collection="request.detailReportIds" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
<if test="request.keyword != null and request.keyword != ''"> <if test="request.keyword != null and request.keyword != ''">
and (tpras.api_scenario_num like concat('%', #{request.keyword}, '%') and (tpras.api_scenario_num like concat('%', #{request.keyword}, '%')
or tpras.api_scenario_name like concat('%', #{request.keyword}, '%') or tpras.api_scenario_name like concat('%', #{request.keyword}, '%')
@ -54,7 +60,10 @@
from test_plan_report_api_scenario tpras from test_plan_report_api_scenario tpras
right join test_plan_collection tpc on tpras.test_plan_collection_id = tpc.id and tpc.type = 'SCENARIO' right join test_plan_collection tpc on tpras.test_plan_collection_id = tpc.id and tpc.type = 'SCENARIO'
join test_plan tp on tpc.test_plan_id = tp.id join test_plan tp on tpc.test_plan_id = tp.id
where tpras.test_plan_report_id = #{request.reportId} where tpras.test_plan_report_id in
<foreach collection="request.detailReportIds" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
<if test="request.keyword != null and request.keyword != ''"> <if test="request.keyword != null and request.keyword != ''">
and (tpras.api_scenario_name like concat('%', #{request.keyword}, '%') and (tpras.api_scenario_name like concat('%', #{request.keyword}, '%')
or tpras.api_scenario_num like concat('%', #{request.keyword}, '%') or tpras.api_scenario_num like concat('%', #{request.keyword}, '%')

View File

@ -26,7 +26,10 @@
select distinct tprb.bug_id as id, tprb.bug_num as num, tprb.bug_title as title, tprb.bug_status as status, tprb.bug_status as statusName, tprb.bug_handle_user as handleUserName, select distinct tprb.bug_id as id, tprb.bug_num as num, tprb.bug_title as title, tprb.bug_status as status, tprb.bug_status as statusName, tprb.bug_handle_user as handleUserName,
ifnull(tprb.bug_case_count, 0) as relationCaseCount ifnull(tprb.bug_case_count, 0) as relationCaseCount
from test_plan_report_bug tprb from test_plan_report_bug tprb
where tprb.test_plan_report_id = #{request.reportId} where tprb.test_plan_report_id in
<foreach collection="request.detailReportIds" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
<if test="request.keyword != null and request.keyword != ''"> <if test="request.keyword != null and request.keyword != ''">
and (tprb.bug_num like concat('%', #{request.keyword}, '%') or tprb.bug_title like concat('%', #{request.keyword}, '%')) and (tprb.bug_num like concat('%', #{request.keyword}, '%') or tprb.bug_title like concat('%', #{request.keyword}, '%'))
</if> </if>

View File

@ -43,10 +43,10 @@ public interface ExtTestPlanReportFunctionalCaseMapper {
/** /**
* 统计报告中功能用例执行情况 * 统计报告中功能用例执行情况
* @param reportId 报告ID * @param reportIds 报告ID集合
* @return 用例数量 * @return 用例数量
*/ */
List<CaseStatusCountMap> countExecuteResult(@Param("id") String reportId); List<CaseStatusCountMap> countExecuteResult(@Param("ids") List<String> reportIds);
/** /**
* 分页查询报告关联的用例 * 分页查询报告关联的用例

View File

@ -45,7 +45,10 @@
<select id="countExecuteResult" resultType="io.metersphere.plan.dto.CaseStatusCountMap"> <select id="countExecuteResult" resultType="io.metersphere.plan.dto.CaseStatusCountMap">
select ifnull(tprfc.function_case_execute_result, 'PENDING') as status, count(id) as count from test_plan_report_function_case tprfc select ifnull(tprfc.function_case_execute_result, 'PENDING') as status, count(id) as count from test_plan_report_function_case tprfc
where tprfc.test_plan_report_id = #{id} where tprfc.test_plan_report_id in
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
group by tprfc.function_case_execute_result group by tprfc.function_case_execute_result
</select> </select>
@ -58,7 +61,10 @@
from test_plan_report_function_case tprfc from test_plan_report_function_case tprfc
left join functional_case fc on fc.id = tprfc.function_case_id left join functional_case fc on fc.id = tprfc.function_case_id
left join test_plan_collection tpc on tpc.id = tprfc.test_plan_collection_id left join test_plan_collection tpc on tpc.id = tprfc.test_plan_collection_id
where tprfc.test_plan_report_id = #{request.reportId} where tprfc.test_plan_report_id in
<foreach collection="request.detailReportIds" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
<if test="request.keyword != null and request.keyword != ''"> <if test="request.keyword != null and request.keyword != ''">
and (tprfc.function_case_num like concat('%', #{request.keyword}, '%') and (tprfc.function_case_num like concat('%', #{request.keyword}, '%')
or tprfc.function_case_name like concat('%', #{request.keyword}, '%') or tprfc.function_case_name like concat('%', #{request.keyword}, '%')
@ -75,7 +81,10 @@
from test_plan_report_function_case tprfc from test_plan_report_function_case tprfc
right join test_plan_collection tpc on tprfc.test_plan_collection_id = tpc.id and tpc.type = 'FUNCTIONAL' right join test_plan_collection tpc on tprfc.test_plan_collection_id = tpc.id and tpc.type = 'FUNCTIONAL'
join test_plan tp on tpc.test_plan_id = tp.id join test_plan tp on tpc.test_plan_id = tp.id
where tprfc.test_plan_report_id = #{request.reportId} where tprfc.test_plan_report_id in
<foreach collection="request.detailReportIds" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
<if test="request.keyword != null and request.keyword != ''"> <if test="request.keyword != null and request.keyword != ''">
and (tprfc.function_case_num like concat('%', #{request.keyword}, '%') and (tprfc.function_case_num like concat('%', #{request.keyword}, '%')
or tprfc.function_case_name like concat('%', #{request.keyword}, '%') or tprfc.function_case_name like concat('%', #{request.keyword}, '%')

View File

@ -75,4 +75,6 @@ public interface ExtTestPlanReportMapper {
List<TestPlanReport> getChildrenReport(@Param("reportId") String reportId); List<TestPlanReport> getChildrenReport(@Param("reportId") String reportId);
void resetRerunReport(@Param("reportId") String reportId); void resetRerunReport(@Param("reportId") String reportId);
List<TestPlanReport> getPlanChildrenTask(@Param("reportId") String reportId);
} }

View File

@ -550,7 +550,12 @@
<select id="getChildrenReport" resultType="io.metersphere.plan.domain.TestPlanReport"> <select id="getChildrenReport" resultType="io.metersphere.plan.domain.TestPlanReport">
select id from test_plan_report where parent_id = #{reportId} and id != #{reportId} select id from test_plan_report where parent_id = #{reportId} and id != #{reportId} order by test_plan_report.create_time desc
</select>
<select id="getPlanChildrenTask" resultType="io.metersphere.plan.domain.TestPlanReport">
select test_plan_report.id, test_plan.name from test_plan_report left join test_plan on test_plan_report.test_plan_id = test_plan.id
where parent_id = #{reportId} and integrated = false order by test_plan_report.create_time desc
</select> </select>
<update id="resetRerunReport"> <update id="resetRerunReport">

View File

@ -60,6 +60,9 @@ import java.util.*;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/**
* @author song-cc-rock
*/
@Service @Service
public class TestPlanReportService { public class TestPlanReportService {
@ -126,8 +129,6 @@ public class TestPlanReportService {
@Resource @Resource
private ApiReportRelateTaskMapper apiReportRelateTaskMapper; private ApiReportRelateTaskMapper apiReportRelateTaskMapper;
@Resource @Resource
private TestPlanCollectionMapper testPlanCollectionMapper;
@Resource
private ExecTaskMapper execTaskMapper; private ExecTaskMapper execTaskMapper;
private static final int MAX_REPORT_NAME_LENGTH = 300; private static final int MAX_REPORT_NAME_LENGTH = 300;
@ -337,7 +338,6 @@ public class TestPlanReportService {
return genReport(prepareReportId, taskId, request, false, currentUser, null); return genReport(prepareReportId, taskId, request, false, currentUser, null);
} }
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public Map<String, String> genReport(String prepareReportId, TestPlanReportGenRequest request, boolean manual, String currentUser, String manualReportName) { public Map<String, String> genReport(String prepareReportId, TestPlanReportGenRequest request, boolean manual, String currentUser, String manualReportName) {
return genReport(prepareReportId, null, request, manual, currentUser, manualReportName); return genReport(prepareReportId, null, request, manual, currentUser, manualReportName);
} }
@ -464,18 +464,28 @@ public class TestPlanReportService {
*/ */
private TestPlanReportDetailCaseDTO genReportDetail(TestPlanReportGenPreParam genParam, TestPlanReport report) { private TestPlanReportDetailCaseDTO genReportDetail(TestPlanReportGenPreParam genParam, TestPlanReport report) {
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
// 缺陷数
List<ReportBugCountDTO> bugCountList = extTestPlanReportBugMapper.countPlanBug(genParam.getTestPlanId()); List<ReportBugCountDTO> bugCountList = extTestPlanReportBugMapper.countPlanBug(genParam.getTestPlanId());
Map<String, Long> bugCountMap = bugCountList.stream().collect(Collectors.toMap(ReportBugCountDTO::getRefCaseId, ReportBugCountDTO::getBugCount)); Map<String, Long> bugCountMap = bugCountList.stream().collect(Collectors.toMap(ReportBugCountDTO::getRefCaseId, ReportBugCountDTO::getBugCount));
Project project = projectMapper.selectByPrimaryKey(genParam.getProjectId()); Project project = projectMapper.selectByPrimaryKey(genParam.getProjectId());
long funcCount = initReportFunctionCase(sqlSession, genParam, report, bugCountMap);
long apiCount = initReportApiCase(sqlSession, genParam, report, project, bugCountMap);
long scenarioCount = initReportApiScenario(sqlSession, genParam, report, project, bugCountMap);
long bugCount = initReportBug(sqlSession, genParam, report);
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
return TestPlanReportDetailCaseDTO.builder()
.functionCaseCount(funcCount).apiCaseCount(apiCount).apiScenarioCount(scenarioCount).bugCount(bugCount).build();
}
/**
* 批量初始化报告关联功能用例数据
* @param sqlSession sql操作对象
* @param genParam 报告生成参数
* @param report 报告
* @param bugCountMap 缺陷-用例 统计Map
* @return 执行条数
*/
private long initReportFunctionCase(SqlSession sqlSession, TestPlanReportGenPreParam genParam, TestPlanReport report, Map<String, Long> bugCountMap) {
AtomicLong funcCaseCount = new AtomicLong(); AtomicLong funcCaseCount = new AtomicLong();
AtomicLong apiCaseCount = new AtomicLong();
AtomicLong apiScenarioCount = new AtomicLong();
AtomicLong bugCount = new AtomicLong();
// 功能用例
{
List<String> funcCaseIdList = extTestPlanReportFunctionalCaseMapper.getPlanExecuteCasesId(genParam.getTestPlanId()); List<String> funcCaseIdList = extTestPlanReportFunctionalCaseMapper.getPlanExecuteCasesId(genParam.getTestPlanId());
if (CollectionUtils.isNotEmpty(funcCaseIdList)) { if (CollectionUtils.isNotEmpty(funcCaseIdList)) {
SubListUtils.dealForSubList(funcCaseIdList, 200, (subList) -> { SubListUtils.dealForSubList(funcCaseIdList, 200, (subList) -> {
@ -519,13 +529,23 @@ public class TestPlanReportService {
// 插入计划功能用例关联数据 -> 报告内容 // 插入计划功能用例关联数据 -> 报告内容
TestPlanReportFunctionCaseMapper batchMapper = sqlSession.getMapper(TestPlanReportFunctionCaseMapper.class); TestPlanReportFunctionCaseMapper batchMapper = sqlSession.getMapper(TestPlanReportFunctionCaseMapper.class);
batchMapper.batchInsert(reportFunctionCases); batchMapper.batchInsert(reportFunctionCases);
sqlSession.flushStatements();
}); });
} }
funcCaseIdList = null; return funcCaseCount.get();
} }
// 接口用例 /**
{ * 批量初始化报告关联接口用例数据
* @param sqlSession sql操作对象
* @param genParam 报告生成参数
* @param report 报告
* @param project 项目
* @param bugCountMap 缺陷-用例 统计Map
* @return 执行条数
*/
private long initReportApiCase(SqlSession sqlSession, TestPlanReportGenPreParam genParam, TestPlanReport report, Project project, Map<String, Long> bugCountMap) {
AtomicLong apiCaseCount = new AtomicLong();
List<String> testPlanReportApiCaseIdList = extTestPlanReportApiCaseMapper.getPlanExecuteCasesId(genParam.getTestPlanId()); List<String> testPlanReportApiCaseIdList = extTestPlanReportApiCaseMapper.getPlanExecuteCasesId(genParam.getTestPlanId());
if (CollectionUtils.isNotEmpty(testPlanReportApiCaseIdList)) { if (CollectionUtils.isNotEmpty(testPlanReportApiCaseIdList)) {
SubListUtils.dealForSubList(testPlanReportApiCaseIdList, 200, (subList) -> { SubListUtils.dealForSubList(testPlanReportApiCaseIdList, 200, (subList) -> {
@ -536,7 +556,6 @@ public class TestPlanReportService {
apiCaseCount.addAndGet(reportApiCases.size()); apiCaseCount.addAndGet(reportApiCases.size());
List<String> moduleIds = reportApiCases.stream().map(TestPlanReportApiCase::getApiCaseModule).filter(Objects::nonNull).distinct().toList(); List<String> moduleIds = reportApiCases.stream().map(TestPlanReportApiCase::getApiCaseModule).filter(Objects::nonNull).distinct().toList();
Map<String, String> moduleMap = getModuleMapByIds(moduleIds, CaseType.API_CASE.getKey()); Map<String, String> moduleMap = getModuleMapByIds(moduleIds, CaseType.API_CASE.getKey());
for (TestPlanReportApiCase reportApiCase : reportApiCases) { for (TestPlanReportApiCase reportApiCase : reportApiCases) {
reportApiCase.setId(IDGenerator.nextStr()); reportApiCase.setId(IDGenerator.nextStr());
reportApiCase.setTestPlanReportId(report.getId()); reportApiCase.setTestPlanReportId(report.getId());
@ -564,11 +583,20 @@ public class TestPlanReportService {
} }
}); });
} }
testPlanReportApiCaseIdList = null; return apiCaseCount.get();
} }
// 场景用例 /**
{ * 批量初始化报告关联场景用例数据
* @param sqlSession sql操作对象
* @param genParam 报告生成参数
* @param report 报告
* @param project 项目
* @param bugCountMap 缺陷-用例 统计Map
* @return 执行条数
*/
private long initReportApiScenario(SqlSession sqlSession, TestPlanReportGenPreParam genParam, TestPlanReport report, Project project, Map<String, Long> bugCountMap) {
AtomicLong apiScenarioCount = new AtomicLong();
List<String> reportApiScenarioIdList = extTestPlanReportApiScenarioMapper.getPlanExecuteCasesId(genParam.getTestPlanId()); List<String> reportApiScenarioIdList = extTestPlanReportApiScenarioMapper.getPlanExecuteCasesId(genParam.getTestPlanId());
if (CollectionUtils.isNotEmpty(reportApiScenarioIdList)) { if (CollectionUtils.isNotEmpty(reportApiScenarioIdList)) {
SubListUtils.dealForSubList(reportApiScenarioIdList, 200, (subList) -> { SubListUtils.dealForSubList(reportApiScenarioIdList, 200, (subList) -> {
@ -606,11 +634,18 @@ public class TestPlanReportService {
} }
}); });
} }
reportApiScenarioIdList = null; return apiScenarioCount.get();
} }
// 计划报告缺陷内容 /**
{ * 批量初始化报告关联缺陷数据
* @param sqlSession sql操作对象
* @param genParam 报告生成参数
* @param report 报告
* @return 执行条数
*/
private long initReportBug(SqlSession sqlSession, TestPlanReportGenPreParam genParam, TestPlanReport report) {
AtomicLong bugCount = new AtomicLong();
List<String> reportBugIdList = extTestPlanReportBugMapper.getPlanBugsId(genParam.getTestPlanId()); List<String> reportBugIdList = extTestPlanReportBugMapper.getPlanBugsId(genParam.getTestPlanId());
if (CollectionUtils.isNotEmpty(reportBugIdList)) { if (CollectionUtils.isNotEmpty(reportBugIdList)) {
SubListUtils.dealForSubList(reportBugIdList, 200, (subList) -> { SubListUtils.dealForSubList(reportBugIdList, 200, (subList) -> {
@ -638,14 +673,7 @@ public class TestPlanReportService {
sqlSession.flushStatements(); sqlSession.flushStatements();
}); });
} }
} return bugCount.get();
long beforeFlush = System.currentTimeMillis();
sqlSession.flushStatements();
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
return TestPlanReportDetailCaseDTO.builder()
.functionCaseCount(funcCaseCount.get()).apiCaseCount(apiCaseCount.get()).apiScenarioCount(apiScenarioCount.get()).bugCount(bugCount.get()).build();
} }
private void initApiCaseExecTaskItem(String taskId, String testPlanId, List<TestPlanReportApiCase> apiTestCases, String userId, Project project) { private void initApiCaseExecTaskItem(String taskId, String testPlanId, List<TestPlanReportApiCase> apiTestCases, String userId, Project project) {
@ -793,20 +821,15 @@ public class TestPlanReportService {
return planReportDetail; return planReportDetail;
} }
/**
* 获取计划任务执行结果
* @param taskId 任务ID
* @return 计划执行结果
*/
public TestPlanTaskReportResponse getTaskDetail(String taskId) { public TestPlanTaskReportResponse getTaskDetail(String taskId) {
TestPlanTaskReportResponse testPlanTaskReportResponse = new TestPlanTaskReportResponse(); TestPlanTaskReportResponse testPlanTaskReportResponse = new TestPlanTaskReportResponse();
ExecTask task = execTaskMapper.selectByPrimaryKey(taskId); ExecTask task = execTaskMapper.selectByPrimaryKey(taskId);
BeanUtils.copyBean(testPlanTaskReportResponse, task); BeanUtils.copyBean(testPlanTaskReportResponse, task);
TestPlanExample planExample = new TestPlanExample();
planExample.createCriteria().andGroupIdEqualTo(task.getResourceId());
List<TestPlan> testPlans = testPlanMapper.selectByExample(planExample);
List<TestPlanTaskReportResponse.ChildPlan> childPlans = testPlans.stream().map(plan -> {
TestPlanTaskReportResponse.ChildPlan childPlan = new TestPlanTaskReportResponse.ChildPlan();
childPlan.setId(plan.getId());
childPlan.setName(plan.getName());
return childPlan;
}).toList();
testPlanTaskReportResponse.setChildPlans(childPlans);
ApiReportRelateTaskExample example = new ApiReportRelateTaskExample(); ApiReportRelateTaskExample example = new ApiReportRelateTaskExample();
example.createCriteria().andTaskResourceIdEqualTo(taskId); example.createCriteria().andTaskResourceIdEqualTo(taskId);
List<ApiReportRelateTask> taskReports = apiReportRelateTaskMapper.selectByExample(example); List<ApiReportRelateTask> taskReports = apiReportRelateTaskMapper.selectByExample(example);
@ -815,6 +838,14 @@ public class TestPlanReportService {
return testPlanTaskReportResponse; return testPlanTaskReportResponse;
} }
String reportId = taskReports.getFirst().getReportId(); String reportId = taskReports.getFirst().getReportId();
List<TestPlanReport> planChildrenTask = extTestPlanReportMapper.getPlanChildrenTask(reportId);
List<TestPlanTaskReportResponse.ChildPlan> childPlans = planChildrenTask.stream().map(childTask -> {
TestPlanTaskReportResponse.ChildPlan childPlan = new TestPlanTaskReportResponse.ChildPlan();
childPlan.setId(childTask.getId());
childPlan.setName(childTask.getName());
return childPlan;
}).toList();
testPlanTaskReportResponse.setChildPlans(childPlans);
return calcTaskExecActual(reportId, testPlanTaskReportResponse); return calcTaskExecActual(reportId, testPlanTaskReportResponse);
} }
@ -878,9 +909,7 @@ public class TestPlanReportService {
List<String> distinctUserIds = detailCases.stream().map(ReportDetailCasePageDTO::getExecuteUser).distinct().collect(Collectors.toList()); List<String> distinctUserIds = detailCases.stream().map(ReportDetailCasePageDTO::getExecuteUser).distinct().collect(Collectors.toList());
distinctUserIds.removeIf(StringUtils::isEmpty); distinctUserIds.removeIf(StringUtils::isEmpty);
Map<String, String> userMap = getUserMap(distinctUserIds); Map<String, String> userMap = getUserMap(distinctUserIds);
detailCases.forEach(detailCase -> { detailCases.forEach(detailCase -> detailCase.setExecuteUser(userMap.getOrDefault(detailCase.getExecuteUser(), detailCase.getExecuteUser())));
detailCase.setExecuteUser(userMap.getOrDefault(detailCase.getExecuteUser(), detailCase.getExecuteUser()));
});
return detailCases; return detailCases;
} }
@ -915,13 +944,13 @@ public class TestPlanReportService {
return; return;
} }
// 功能用例 // 功能用例
List<CaseStatusCountMap> functionalCountMapList = extTestPlanReportFunctionalCaseMapper.countExecuteResult(reportId); List<CaseStatusCountMap> functionalCountMapList = extTestPlanReportFunctionalCaseMapper.countExecuteResult(List.of(reportId));
CaseCount functionalCaseCount = countMap(functionalCountMapList); CaseCount functionalCaseCount = countMap(functionalCountMapList);
// 接口用例 // 接口用例
List<CaseStatusCountMap> apiCountMapList = extTestPlanReportApiCaseMapper.countExecuteResult(reportId); List<CaseStatusCountMap> apiCountMapList = extTestPlanReportApiCaseMapper.countExecuteResult(List.of(reportId));
CaseCount apiCaseCount = countMap(apiCountMapList); CaseCount apiCaseCount = countMap(apiCountMapList);
// 场景用例 // 场景用例
List<CaseStatusCountMap> scenarioCountMapList = extTestPlanReportApiScenarioMapper.countExecuteResult(reportId); List<CaseStatusCountMap> scenarioCountMapList = extTestPlanReportApiScenarioMapper.countExecuteResult(List.of(reportId));
CaseCount scenarioCaseCount = countMap(scenarioCountMapList); CaseCount scenarioCaseCount = countMap(scenarioCountMapList);
// 规划整体的汇总数据 // 规划整体的汇总数据
@ -950,7 +979,7 @@ public class TestPlanReportService {
summaryExample.createCriteria().andTestPlanReportIdEqualTo(reportId); summaryExample.createCriteria().andTestPlanReportIdEqualTo(reportId);
List<TestPlanReportSummary> testPlanReportSummaries = testPlanReportSummaryMapper.selectByExample(summaryExample); List<TestPlanReportSummary> testPlanReportSummaries = testPlanReportSummaryMapper.selectByExample(summaryExample);
if (CollectionUtils.isEmpty(testPlanReportSummaries)) { if (CollectionUtils.isEmpty(testPlanReportSummaries)) {
// 报告详情不存在 // 计划组报告详情不存在
return; return;
} }
TestPlanReportSummary groupSummary = testPlanReportSummaries.getFirst(); TestPlanReportSummary groupSummary = testPlanReportSummaries.getFirst();
@ -963,69 +992,27 @@ public class TestPlanReportService {
return; return;
} }
// 汇总子报告关联的数据并入库 // 汇总子报告关联的数据 (计划组的用例明细不入库)
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
List<String> ids = testPlanReports.stream().map(TestPlanReport::getId).toList(); List<String> ids = testPlanReports.stream().map(TestPlanReport::getId).toList();
// 功能用例 // 汇总功能用例
TestPlanReportFunctionCaseExample functionCaseExample = new TestPlanReportFunctionCaseExample(); TestPlanReportFunctionCaseExample functionCaseExample = new TestPlanReportFunctionCaseExample();
functionCaseExample.createCriteria().andTestPlanReportIdIn(ids); functionCaseExample.createCriteria().andTestPlanReportIdIn(ids);
List<TestPlanReportFunctionCase> reportFunctionCases = testPlanReportFunctionCaseMapper.selectByExample(functionCaseExample); groupSummary.setFunctionalCaseCount(testPlanReportFunctionCaseMapper.countByExample(functionCaseExample));
if (CollectionUtils.isNotEmpty(reportFunctionCases)) { // 汇总接口用例
groupSummary.setFunctionalCaseCount((long) reportFunctionCases.size());
reportFunctionCases.forEach(reportFunctionCase -> {
reportFunctionCase.setId(IDGenerator.nextStr());
reportFunctionCase.setTestPlanReportId(reportId);
});
// 插入计划组报告, 功能用例关联数据
TestPlanReportFunctionCaseMapper batchMapper = sqlSession.getMapper(TestPlanReportFunctionCaseMapper.class);
batchMapper.batchInsert(reportFunctionCases);
}
// 接口用例
TestPlanReportApiCaseExample apiCaseExample = new TestPlanReportApiCaseExample(); TestPlanReportApiCaseExample apiCaseExample = new TestPlanReportApiCaseExample();
apiCaseExample.createCriteria().andTestPlanReportIdIn(ids); apiCaseExample.createCriteria().andTestPlanReportIdIn(ids);
List<TestPlanReportApiCase> reportApiCases = testPlanReportApiCaseMapper.selectByExample(apiCaseExample); groupSummary.setApiCaseCount(testPlanReportApiCaseMapper.countByExample(apiCaseExample));
if (CollectionUtils.isNotEmpty(reportApiCases)) { // 汇总场景用例
groupSummary.setApiCaseCount((long) reportApiCases.size());
reportApiCases.forEach(reportApiCase -> {
reportApiCase.setId(IDGenerator.nextStr());
reportApiCase.setTestPlanReportId(reportId);
});
// 插入计划组报告, 接口用例关联数据
TestPlanReportApiCaseMapper batchMapper = sqlSession.getMapper(TestPlanReportApiCaseMapper.class);
batchMapper.batchInsert(reportApiCases);
}
// 场景用例
TestPlanReportApiScenarioExample scenarioExample = new TestPlanReportApiScenarioExample(); TestPlanReportApiScenarioExample scenarioExample = new TestPlanReportApiScenarioExample();
scenarioExample.createCriteria().andTestPlanReportIdIn(ids); scenarioExample.createCriteria().andTestPlanReportIdIn(ids);
List<TestPlanReportApiScenario> reportApiScenarios = testPlanReportApiScenarioMapper.selectByExample(scenarioExample); groupSummary.setApiScenarioCount(testPlanReportApiScenarioMapper.countByExample(scenarioExample));
if (CollectionUtils.isNotEmpty(reportApiScenarios)) { // 汇总缺陷明细 (子计划同一缺陷去重)
groupSummary.setApiScenarioCount((long) reportApiScenarios.size());
reportApiScenarios.forEach(reportApiScenario -> {
reportApiScenario.setId(IDGenerator.nextStr());
reportApiScenario.setTestPlanReportId(reportId);
});
// 插入计划组报告, 场景用例关联数据
TestPlanReportApiScenarioMapper batchMapper = sqlSession.getMapper(TestPlanReportApiScenarioMapper.class);
batchMapper.batchInsert(reportApiScenarios);
}
// 缺陷明细
TestPlanReportBugExample bugExample = new TestPlanReportBugExample(); TestPlanReportBugExample bugExample = new TestPlanReportBugExample();
bugExample.createCriteria().andTestPlanReportIdIn(ids); bugExample.createCriteria().andTestPlanReportIdIn(ids);
List<TestPlanReportBug> reportBugs = testPlanReportBugMapper.selectByExample(bugExample); List<TestPlanReportBug> reportBugs = testPlanReportBugMapper.selectByExample(bugExample);
if (CollectionUtils.isNotEmpty(reportBugs)) { groupSummary.setBugCount(reportBugs.stream().map(TestPlanReportBug::getBugId).distinct().count());
groupSummary.setBugCount((long) reportBugs.size());
reportBugs.forEach(reportBug -> {
reportBug.setId(IDGenerator.nextStr());
reportBug.setTestPlanReportId(reportId);
});
// 插入计划组关联用例缺陷数据
TestPlanReportBugMapper batchMapper = sqlSession.getMapper(TestPlanReportBugMapper.class);
batchMapper.batchInsert(reportBugs);
}
sqlSession.flushStatements();
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
// 汇总并计算子报告执行的数据 // 汇总并计算子报告执行的用例数据
summaryExample.clear(); summaryExample.clear();
summaryExample.createCriteria().andTestPlanReportIdIn(ids); summaryExample.createCriteria().andTestPlanReportIdIn(ids);
List<TestPlanReportSummary> summaryList = testPlanReportSummaryMapper.selectByExampleWithBLOBs(summaryExample); List<TestPlanReportSummary> summaryList = testPlanReportSummaryMapper.selectByExampleWithBLOBs(summaryExample);
@ -1281,22 +1268,6 @@ public class TestPlanReportService {
return userOptions.stream().collect(Collectors.toMap(OptionDTO::getId, OptionDTO::getName)); return userOptions.stream().collect(Collectors.toMap(OptionDTO::getId, OptionDTO::getName));
} }
/**
* 获取测试点集合
*
* @param collectionIds 测试点ID集合
* @return 测试点集合
*/
private Map<String, String> getCollectionMap(List<String> collectionIds) {
if (CollectionUtils.isEmpty(collectionIds)) {
return new HashMap<>(16);
}
TestPlanCollectionExample example = new TestPlanCollectionExample();
example.createCriteria().andIdIn(collectionIds);
List<TestPlanCollection> collections = testPlanCollectionMapper.selectByExample(example);
return collections.stream().collect(Collectors.toMap(TestPlanCollection::getId, TestPlanCollection::getName));
}
/** /**
* 计划报告列表 * 计划报告列表
* *
@ -1430,11 +1401,12 @@ public class TestPlanReportService {
*/ */
private TestPlanTaskReportResponse calcTaskExecActual(String reportId, TestPlanTaskReportResponse testPlanTaskReportResponse) { private TestPlanTaskReportResponse calcTaskExecActual(String reportId, TestPlanTaskReportResponse testPlanTaskReportResponse) {
testPlanTaskReportResponse.setReportId(reportId); testPlanTaskReportResponse.setReportId(reportId);
List<String> calcReportIds = getActualReportIds(reportId);
// 计算接口用例 // 计算接口用例
List<CaseStatusCountMap> apiCountMapList = extTestPlanReportApiCaseMapper.countExecuteResult(reportId); List<CaseStatusCountMap> apiCountMapList = extTestPlanReportApiCaseMapper.countExecuteResult(calcReportIds);
CaseCount apiCaseCount = countMap(apiCountMapList); CaseCount apiCaseCount = countMap(apiCountMapList);
// 计算场景用例 // 计算场景用例
List<CaseStatusCountMap> scenarioCountMapList = extTestPlanReportApiScenarioMapper.countExecuteResult(reportId); List<CaseStatusCountMap> scenarioCountMapList = extTestPlanReportApiScenarioMapper.countExecuteResult(calcReportIds);
CaseCount scenarioCaseCount = countMap(scenarioCountMapList); CaseCount scenarioCaseCount = countMap(scenarioCountMapList);
// 汇总接口&&场景用例的执行情况 // 汇总接口&&场景用例的执行情况
CaseCount caseCount = CountUtils.summarizeProperties(List.of(apiCaseCount, scenarioCaseCount)); CaseCount caseCount = CountUtils.summarizeProperties(List.of(apiCaseCount, scenarioCaseCount));
@ -1444,4 +1416,22 @@ public class TestPlanReportService {
0 : RateCalculateUtils.divWithPrecision(caseCount.sum() - caseCount.getPending(), caseCount.sum(), 2)); 0 : RateCalculateUtils.divWithPrecision(caseCount.sum() - caseCount.getPending(), caseCount.sum(), 2));
return testPlanTaskReportResponse; return testPlanTaskReportResponse;
} }
/**
* 获取实际的报告ID集合 (计划组报告则会返回多个)
* @param reportId 报告ID
* @return 报告ID集合
*/
public List<String> getActualReportIds(String reportId) {
// 计划组任务结果, 取多个子计划的结果计算完成率
TestPlanReport report = testPlanReportMapper.selectByPrimaryKey(reportId);
if (report.getIntegrated()) {
TestPlanReportExample example = new TestPlanReportExample();
example.createCriteria().andParentIdEqualTo(reportId).andIntegratedEqualTo(false);
List<TestPlanReport> testPlanReports = testPlanReportMapper.selectByExample(example);
return testPlanReports.stream().map(TestPlanReport::getId).toList();
} else {
return List.of(reportId);
}
}
} }