diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/controller/FunctionalTestCaseController.java b/backend/services/case-management/src/main/java/io/metersphere/functional/controller/FunctionalTestCaseController.java index c023ebbf09..1f412600c4 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/controller/FunctionalTestCaseController.java +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/controller/FunctionalTestCaseController.java @@ -5,7 +5,9 @@ import com.github.pagehelper.PageHelper; import io.metersphere.dto.BugProviderDTO; import io.metersphere.dto.TestCaseProviderDTO; import io.metersphere.functional.dto.FunctionalCaseTestDTO; +import io.metersphere.functional.dto.FunctionalCaseTestPlanDTO; import io.metersphere.functional.request.AssociateCaseModuleRequest; +import io.metersphere.functional.request.AssociatePlanPageRequest; import io.metersphere.functional.request.DisassociateOtherCaseRequest; import io.metersphere.functional.request.FunctionalCaseTestRequest; import io.metersphere.functional.service.FunctionalCaseLogService; @@ -51,7 +53,7 @@ public class FunctionalTestCaseController { @PostMapping("/associate/case/module/count") @Operation(summary = "用例管理-功能用例-关联其他用例-统计需要关联用例模块数量") - @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ) + @RequiresPermissions(value = {PermissionConstants.FUNCTIONAL_CASE_READ_ADD, PermissionConstants.FUNCTIONAL_CASE_READ_UPDATE, PermissionConstants.FUNCTIONAL_CASE_READ_DELETE}, logical = Logical.OR) @CheckOwner(resourceId = "#request.projectId", resourceType = "project") public Map moduleCount(@Validated @RequestBody TestCasePageProviderRequest request) { return functionalTestCaseService.moduleCount(request, false); @@ -59,7 +61,7 @@ public class FunctionalTestCaseController { @PostMapping("/associate/case/module/tree") @Operation(summary = "用例管理-功能用例-关联其他用例-获取需要关联的用例模块树") - @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ) + @RequiresPermissions(value = {PermissionConstants.FUNCTIONAL_CASE_READ_ADD, PermissionConstants.FUNCTIONAL_CASE_READ_UPDATE, PermissionConstants.FUNCTIONAL_CASE_READ_DELETE}, logical = Logical.OR) @CheckOwner(resourceId = "#request.projectId", resourceType = "project") public List getTree(@RequestBody @Validated AssociateCaseModuleRequest request) { return functionalTestCaseService.getTree(request); @@ -67,7 +69,7 @@ public class FunctionalTestCaseController { @PostMapping("/associate/case") @Operation(summary = "用例管理-功能用例-关联其他用例-关联用例") - @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ) + @RequiresPermissions(value = {PermissionConstants.FUNCTIONAL_CASE_READ_ADD, PermissionConstants.FUNCTIONAL_CASE_READ_UPDATE, PermissionConstants.FUNCTIONAL_CASE_READ_DELETE}, logical = Logical.OR) @CheckOwner(resourceId = "#request.sourceId", resourceType = "functional_case") public void associateCase(@Validated @RequestBody AssociateOtherCaseRequest request) { functionalTestCaseService.associateCase(request, false, SessionUtils.getUserId()); @@ -76,7 +78,7 @@ public class FunctionalTestCaseController { @PostMapping("/disassociate/case") @Operation(summary = "用例管理-功能用例-关联其他用例-取消关联用例") @Log(type = OperationLogType.DISASSOCIATE, expression = "#msClass.disassociateCaseLog(#request)", msClass = FunctionalCaseLogService.class) - @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ) + @RequiresPermissions(value = {PermissionConstants.FUNCTIONAL_CASE_READ_ADD, PermissionConstants.FUNCTIONAL_CASE_READ_UPDATE, PermissionConstants.FUNCTIONAL_CASE_READ_DELETE}, logical = Logical.OR) @CheckOwner(resourceId = "#request.projectId", resourceType = "project") public void disassociateCase(@Validated @RequestBody DisassociateOtherCaseRequest request) { functionalTestCaseService.disassociateCase(request); @@ -129,4 +131,14 @@ public class FunctionalTestCaseController { Page page = PageHelper.startPage(request.getCurrent(), request.getPageSize()); return PageUtils.setPageInfo(page, functionalTestCaseService.hasAssociateBugPage(request)); } + + + @PostMapping("/has/associate/plan/page") + @Operation(summary = "用例管理-功能用例-关联其他用例-获取已关联的测试计划列表") + @RequiresPermissions(value = {PermissionConstants.FUNCTIONAL_CASE_READ_ADD, PermissionConstants.FUNCTIONAL_CASE_READ_UPDATE, PermissionConstants.FUNCTIONAL_CASE_READ_DELETE}, logical = Logical.OR) + @CheckOwner(resourceId = "#request.caseId", resourceType = "functional_case") + public Pager> getAssociateOtherPlanList(@Validated @RequestBody AssociatePlanPageRequest request) { + Page page = PageHelper.startPage(request.getCurrent(), request.getPageSize()); + return PageUtils.setPageInfo(page, functionalTestCaseService.hasAssociatePlanPage(request)); + } } diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/dto/FunctionalCaseTestPlanDTO.java b/backend/services/case-management/src/main/java/io/metersphere/functional/dto/FunctionalCaseTestPlanDTO.java new file mode 100644 index 0000000000..b243a20dbe --- /dev/null +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/dto/FunctionalCaseTestPlanDTO.java @@ -0,0 +1,18 @@ +package io.metersphere.functional.dto; + +import io.metersphere.plan.domain.TestPlanFunctionalCase; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class FunctionalCaseTestPlanDTO extends TestPlanFunctionalCase { + + @Schema(description = "测试计划ID") + private String num; + + @Schema(description = "所属项目") + private String projectName; + + @Schema(description = "计划状态") + private String planStatus; +} diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseTestMapper.java b/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseTestMapper.java index acdae6fdcd..19b4d073aa 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseTestMapper.java +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseTestMapper.java @@ -1,6 +1,8 @@ package io.metersphere.functional.mapper; import io.metersphere.functional.dto.FunctionalCaseTestDTO; +import io.metersphere.functional.dto.FunctionalCaseTestPlanDTO; +import io.metersphere.functional.request.AssociatePlanPageRequest; import io.metersphere.functional.request.DisassociateOtherCaseRequest; import io.metersphere.functional.request.FunctionalCaseTestRequest; import org.apache.ibatis.annotations.Param; @@ -12,4 +14,7 @@ public interface ExtFunctionalCaseTestMapper { List getIds(@Param("request") DisassociateOtherCaseRequest request); List getList(@Param("request") FunctionalCaseTestRequest request); + + List getPlanList(@Param("request") AssociatePlanPageRequest request); + } diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseTestMapper.xml b/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseTestMapper.xml index 8cbca18d12..26d71e4841 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseTestMapper.xml +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/mapper/ExtFunctionalCaseTestMapper.xml @@ -56,6 +56,23 @@ order by fct.create_time desc + + functional_case_test.source_id not in diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/request/AssociatePlanPageRequest.java b/backend/services/case-management/src/main/java/io/metersphere/functional/request/AssociatePlanPageRequest.java new file mode 100644 index 0000000000..cf6c8beafb --- /dev/null +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/request/AssociatePlanPageRequest.java @@ -0,0 +1,29 @@ +package io.metersphere.functional.request; + +import io.metersphere.request.BaseProviderCondition; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = false) +public class AssociatePlanPageRequest extends BaseProviderCondition { + + + @Schema(description = "功能用例id", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{associate_plan_page_request.case_id.not_blank}") + private String caseId; + + + @Min(value = 1, message = "当前页码必须大于0") + @Schema(description = "当前页码") + private int current; + + @Min(value = 5, message = "每页显示条数必须不小于5") + @Max(value = 500, message = "每页显示条数不能大于500") + @Schema(description = "每页显示条数") + private int pageSize; +} diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalTestCaseService.java b/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalTestCaseService.java index d7cde35bd6..92a185a78f 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalTestCaseService.java +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalTestCaseService.java @@ -7,10 +7,12 @@ import io.metersphere.functional.constants.AssociateCaseType; import io.metersphere.functional.domain.FunctionalCaseTest; import io.metersphere.functional.domain.FunctionalCaseTestExample; import io.metersphere.functional.dto.FunctionalCaseTestDTO; +import io.metersphere.functional.dto.FunctionalCaseTestPlanDTO; import io.metersphere.functional.mapper.ExtFunctionalCaseModuleMapper; import io.metersphere.functional.mapper.ExtFunctionalCaseTestMapper; import io.metersphere.functional.mapper.FunctionalCaseTestMapper; import io.metersphere.functional.request.AssociateCaseModuleRequest; +import io.metersphere.functional.request.AssociatePlanPageRequest; import io.metersphere.functional.request.DisassociateOtherCaseRequest; import io.metersphere.functional.request.FunctionalCaseTestRequest; import io.metersphere.provider.BaseAssociateApiProvider; @@ -207,4 +209,13 @@ public class FunctionalTestCaseService { public List hasAssociateBugPage(AssociateBugPageRequest request) { return baseAssociateBugProvider.hasAssociateBugPage(request); } + + /** + * 查询已关联的测试计划列表 + * @param request request + * @return List + */ + public List hasAssociatePlanPage(AssociatePlanPageRequest request) { + return extFunctionalCaseTestMapper.getPlanList(request); + } } diff --git a/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalTestCaseControllerTests.java b/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalTestCaseControllerTests.java index e1a1773b42..b4ea05192c 100644 --- a/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalTestCaseControllerTests.java +++ b/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalTestCaseControllerTests.java @@ -3,7 +3,6 @@ package io.metersphere.functional.controller; import io.metersphere.api.domain.ApiDefinitionModule; import io.metersphere.api.domain.ApiTestCase; import io.metersphere.api.mapper.ApiDefinitionModuleMapper; -import io.metersphere.bug.mapper.BugRelationCaseMapper; import io.metersphere.dto.BugProviderDTO; import io.metersphere.dto.TestCaseProviderDTO; import io.metersphere.functional.constants.AssociateCaseType; @@ -11,11 +10,15 @@ import io.metersphere.functional.constants.FunctionalCaseReviewStatus; import io.metersphere.functional.domain.FunctionalCase; import io.metersphere.functional.domain.FunctionalCaseTest; import io.metersphere.functional.dto.FunctionalCaseTestDTO; +import io.metersphere.functional.dto.FunctionalCaseTestPlanDTO; import io.metersphere.functional.mapper.FunctionalCaseMapper; import io.metersphere.functional.mapper.FunctionalCaseTestMapper; import io.metersphere.functional.request.AssociateCaseModuleRequest; +import io.metersphere.functional.request.AssociatePlanPageRequest; import io.metersphere.functional.request.DisassociateOtherCaseRequest; import io.metersphere.functional.request.FunctionalCaseTestRequest; +import io.metersphere.plan.mapper.TestPlanFunctionalCaseMapper; +import io.metersphere.plan.mapper.TestPlanMapper; import io.metersphere.provider.BaseAssociateApiProvider; import io.metersphere.provider.BaseAssociateBugProvider; import io.metersphere.request.*; @@ -62,6 +65,9 @@ public class FunctionalTestCaseControllerTests extends BaseTest { private static final String URL_DISASSOCIATE_BUG = "/functional/case/test/disassociate/bug/"; private static final String URL_ASSOCIATE_BUG_PAGE = "/functional/case/test/has/associate/bug/page"; + private static final String URL_ASSOCIATE_TEST_PLAN_PAGE = "/functional/case/test/has/associate/plan/page"; + + @Resource BaseAssociateApiProvider provider; @@ -76,12 +82,15 @@ public class FunctionalTestCaseControllerTests extends BaseTest { private ApiDefinitionModuleMapper apiDefinitionModuleMapper; @Resource BaseAssociateBugProvider baseAssociateBugProvider; - @Resource - private BugRelationCaseMapper bugRelationCaseMapper; + @Resource + TestPlanFunctionalCaseMapper testPlanFunctionalCaseMapper; + @Resource + TestPlanMapper testPlanMapper; @Test @Order(1) + @Sql(scripts = {"/dml/init_test_plan_case.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED)) public void getPageSuccess() throws Exception { TestCasePageProviderRequest request = new TestCasePageProviderRequest(); request.setSourceType(AssociateCaseType.API); @@ -389,4 +398,21 @@ public class FunctionalTestCaseControllerTests extends BaseTest { }}); this.requestPostWithOkAndReturn(URL_ASSOCIATE_BUG_PAGE, request); } + + @Test + @Order(12) + public void testAssociatePlanPage() throws Exception { + AssociatePlanPageRequest request = new AssociatePlanPageRequest(); + request.setCurrent(1); + request.setPageSize(10); + request.setCaseId("gyq_associate_function_case"); + request.setKeyword("name"); + MvcResult mvcResult = this.requestPostWithOkAndReturn(URL_ASSOCIATE_TEST_PLAN_PAGE, request); + Pager> tableData = JSON.parseObject(JSON.toJSONString( + JSON.parseObject(mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class).getData()), + Pager.class); + Assertions.assertNotNull(tableData); + List list = tableData.getList(); + Assertions.assertEquals(2, list.size()); + } } diff --git a/backend/services/case-management/src/test/resources/dml/init_test_plan_case.sql b/backend/services/case-management/src/test/resources/dml/init_test_plan_case.sql new file mode 100644 index 0000000000..73576a7a6d --- /dev/null +++ b/backend/services/case-management/src/test/resources/dml/init_test_plan_case.sql @@ -0,0 +1,20 @@ +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 ('test_plan_associate_case_gyq_three', 500, 'test_plan_associate_case_project', 'NONE', 'case_plan_module', 'test_plan_associate_case_name_three', 'PREPARED', '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 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) +VALUES ('test_plan_associate_case_gyq_one', 500, 'test_plan_associate_case_project', 'NONE', 'case_plan_module', 'test_plan_associate_case_name_one', 'PREPARED', 'TEST_PLAN', null, UNIX_TIMESTAMP() * 1000,'admin', + UNIX_TIMESTAMP() * 1000,'admin',UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, null), + ('test_plan_associate_case_gyq_two', 500, 'test_plan_associate_case_project', 'NONE', 'case_plan_module', 'test_plan_associate_case_name_two', 'PREPARED', '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(id, num, organization_id, name, description, create_time, update_time, update_user, create_user, delete_time, deleted, delete_user, enable, module_setting) + VALUE ('test_plan_associate_case_project', null, 'organization_plan_associate_case_project', 'test_plan_associate_case_name', null, + UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', 'admin', null, false, null, true, null); + + +INSERT INTO test_plan_functional_case(id, test_plan_id, functional_case_id, create_time, create_user, last_exec_time, last_exec_result, pos) +VALUES ('associate_case_plan_gyq_one', 'test_plan_associate_case_gyq_one', 'gyq_associate_function_case', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 'SUCCESS', 200), + ('associate_case_plan_gyq_two', 'test_plan_associate_case_gyq_two', 'gyq_associate_function_case', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 'SUCCESS', 200); \ No newline at end of file