diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanApiCaseController.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanApiCaseController.java index 716fb1557d..90ee77269f 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanApiCaseController.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanApiCaseController.java @@ -4,15 +4,19 @@ import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; import io.metersphere.plan.dto.request.BasePlanCaseBatchRequest; import io.metersphere.plan.dto.request.TestPlanApiCaseRequest; +import io.metersphere.plan.dto.request.TestPlanApiCaseUpdateRequest; import io.metersphere.plan.dto.request.TestPlanDisassociationRequest; import io.metersphere.plan.dto.response.TestPlanApiCasePageResponse; import io.metersphere.plan.dto.response.TestPlanAssociationResponse; +import io.metersphere.plan.service.TestPlanApiCaseLogService; import io.metersphere.plan.service.TestPlanApiCaseService; import io.metersphere.plan.service.TestPlanService; import io.metersphere.sdk.constants.HttpMethodConstants; import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.system.dto.LogInsertModule; import io.metersphere.system.dto.sdk.BaseTreeNode; +import io.metersphere.system.log.annotation.Log; +import io.metersphere.system.log.constants.OperationLogType; import io.metersphere.system.security.CheckOwner; import io.metersphere.system.utils.PageUtils; import io.metersphere.system.utils.Pager; @@ -79,6 +83,15 @@ public class TestPlanApiCaseController { return response; } + @PostMapping("/batch/update/executor") + @Operation(summary = "测试计划-计划详情-功能用例-批量更新执行人") + @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_UPDATE) + @CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan") + @Log(type = OperationLogType.DISASSOCIATE, expression = "#msClass.batchUpdateExecutor(#request)", msClass = TestPlanApiCaseLogService.class) + public void batchUpdateExecutor(@Validated @RequestBody TestPlanApiCaseUpdateRequest request) { + testPlanApiCaseService.batchUpdateExecutor(request); + } + //TODO 计划集 type } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanFunctionalCaseController.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanFunctionalCaseController.java index 9ed35c65cb..36e4d25099 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanFunctionalCaseController.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanFunctionalCaseController.java @@ -163,7 +163,7 @@ public class TestPlanFunctionalCaseController { @Operation(summary = "测试计划-计划详情-功能用例-批量更新执行人") @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_UPDATE) @CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan") - @Log(type = OperationLogType.DISASSOCIATE, expression = "#msClass.batchUpdateExecutor(#request)", msClass = TestPlanCaseLogService.class) + @Log(type = OperationLogType.UPDATE, expression = "#msClass.batchUpdateExecutor(#request)", msClass = TestPlanCaseLogService.class) public void batchUpdateExecutor(@Validated @RequestBody TestPlanCaseUpdateRequest request) { testPlanFunctionalCaseService.batchUpdateExecutor(request); } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanApiCaseUpdateRequest.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanApiCaseUpdateRequest.java new file mode 100644 index 0000000000..08daca3ae3 --- /dev/null +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanApiCaseUpdateRequest.java @@ -0,0 +1,24 @@ +package io.metersphere.plan.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; + +import java.util.List; + + +/** + * @author wx + */ +@Data +public class TestPlanApiCaseUpdateRequest extends BasePlanCaseBatchRequest { + + @Schema(description = "执行人id", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{test_plan.user_id.not_blank}") + private String userId; + + @Schema(description = "接口协议", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "{api_definition.protocol.not_blank}") + private List protocols; +} diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanApiCaseMapper.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanApiCaseMapper.java index cfe85e9c6e..8785e7b59e 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanApiCaseMapper.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanApiCaseMapper.java @@ -49,5 +49,7 @@ public interface ExtTestPlanApiCaseMapper { List selectBaseByProjectIdAndTestPlanId(@Param("testPlanId") String testPlanId); - List getIds(@Param("request") BasePlanCaseBatchRequest request, @Param("deleted") boolean deleted); + List getIds(@Param("request") BasePlanCaseBatchRequest request, @Param("deleted") boolean deleted, @Param("protocols") List protocols); + + void batchUpdateExecutor(@Param("ids") List ids, @Param("userId") String userId); } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanApiCaseMapper.xml b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanApiCaseMapper.xml index b9dddeb9d5..7d072f7ca6 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanApiCaseMapper.xml +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanApiCaseMapper.xml @@ -599,11 +599,11 @@ - - and a.protocol = #{request.protocol} - - - and atc.api_definition_id = #{request.apiDefinitionId} + + and a.protocol in + + #{protocol} + and ( @@ -630,4 +630,14 @@ + + update test_plan_api_case + set execute_user = #{userId} + where id in + + #{id} + + + + \ No newline at end of file diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanApiCaseLogService.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanApiCaseLogService.java new file mode 100644 index 0000000000..d345eb4c4c --- /dev/null +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanApiCaseLogService.java @@ -0,0 +1,71 @@ +package io.metersphere.plan.service; + +import io.metersphere.api.domain.ApiTestCase; +import io.metersphere.api.domain.ApiTestCaseExample; +import io.metersphere.api.mapper.ApiTestCaseMapper; +import io.metersphere.plan.domain.TestPlanApiCase; +import io.metersphere.plan.domain.TestPlanApiCaseExample; +import io.metersphere.plan.dto.request.TestPlanApiCaseUpdateRequest; +import io.metersphere.plan.mapper.TestPlanApiCaseMapper; +import io.metersphere.sdk.constants.HttpMethodConstants; +import io.metersphere.sdk.util.JSON; +import io.metersphere.system.log.constants.OperationLogModule; +import io.metersphere.system.log.constants.OperationLogType; +import io.metersphere.system.log.dto.LogDTO; +import jakarta.annotation.Resource; +import org.apache.commons.collections.CollectionUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Service +@Transactional(rollbackFor = Exception.class) +public class TestPlanApiCaseLogService { + + @Resource + private TestPlanApiCaseService testPlanApiCaseService; + @Resource + private TestPlanApiCaseMapper testPlanApiCaseMapper; + @Resource + private ApiTestCaseMapper apiTestCaseMapper; + + public void batchUpdateExecutor(TestPlanApiCaseUpdateRequest request) { + List ids = testPlanApiCaseService.doSelectIds(request, request.getProtocols()); + if (CollectionUtils.isNotEmpty(ids)) { + TestPlanApiCaseExample example = new TestPlanApiCaseExample(); + example.createCriteria().andIdIn(ids); + List planCaseList = testPlanApiCaseMapper.selectByExample(example); + Map userMap = planCaseList.stream().collect(Collectors.toMap(TestPlanApiCase::getId, TestPlanApiCase::getExecuteUser)); + Map idsMap = planCaseList.stream().collect(Collectors.toMap(TestPlanApiCase::getId, TestPlanApiCase::getApiCaseId)); + List caseIds = planCaseList.stream().map(TestPlanApiCase::getApiCaseId).collect(Collectors.toList()); + ApiTestCaseExample caseExample = new ApiTestCaseExample(); + caseExample.createCriteria().andIdIn(caseIds); + List functionalCases = apiTestCaseMapper.selectByExample(caseExample); + Map caseMap = functionalCases.stream().collect(Collectors.toMap(ApiTestCase::getId, ApiTestCase::getName)); + List dtoList = new ArrayList<>(); + idsMap.forEach((k, v) -> { + LogDTO dto = new LogDTO( + null, + null, + k, + null, + OperationLogType.UPDATE.name(), + OperationLogModule.TEST_PLAN, + caseMap.get(v)); + dto.setPath("/test-plan/api/case/batch/update/executor"); + dto.setMethod(HttpMethodConstants.POST.name()); + dto.setOriginalValue(JSON.toJSONBytes(userMap.get(k))); + dto.setModifiedValue(JSON.toJSONBytes(request.getUserId())); + dtoList.add(dto); + }); + } + } + +} + + + diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanApiCaseService.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanApiCaseService.java index 5eb4d72b9c..13e521a4fa 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanApiCaseService.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanApiCaseService.java @@ -14,6 +14,7 @@ import io.metersphere.plan.dto.TestPlanCaseRunResultCount; import io.metersphere.plan.dto.TestPlanResourceAssociationParam; import io.metersphere.plan.dto.request.BasePlanCaseBatchRequest; import io.metersphere.plan.dto.request.TestPlanApiCaseRequest; +import io.metersphere.plan.dto.request.TestPlanApiCaseUpdateRequest; import io.metersphere.plan.dto.request.TestPlanApiRequest; import io.metersphere.plan.dto.response.TestPlanApiCasePageResponse; import io.metersphere.plan.dto.response.TestPlanAssociationResponse; @@ -324,12 +325,11 @@ public class TestPlanApiCaseService extends TestPlanResourceService { * @return */ public TestPlanAssociationResponse disassociate(BasePlanCaseBatchRequest request, LogInsertModule logInsertModule) { - List selectIds = doSelectIds(request); return super.disassociate( TestPlanResourceConstants.RESOURCE_API_CASE, request, logInsertModule, - selectIds, + request.getSelectIds(), this::deleteTestPlanResource); } @@ -341,9 +341,9 @@ public class TestPlanApiCaseService extends TestPlanResourceService { } - public List doSelectIds(BasePlanCaseBatchRequest request) { + public List doSelectIds(BasePlanCaseBatchRequest request, List protocols) { if (request.isSelectAll()) { - List ids = extTestPlanApiCaseMapper.getIds(request, false); + List ids = extTestPlanApiCaseMapper.getIds(request, false, protocols); if (CollectionUtils.isNotEmpty(request.getExcludeIds())) { ids.removeAll(request.getExcludeIds()); } @@ -352,4 +352,17 @@ public class TestPlanApiCaseService extends TestPlanResourceService { return request.getSelectIds(); } } + + + /** + * 批量更新执行人 + * + * @param request + */ + public void batchUpdateExecutor(TestPlanApiCaseUpdateRequest request) { + List ids = doSelectIds(request, request.getProtocols()); + if (CollectionUtils.isNotEmpty(ids)) { + extTestPlanApiCaseMapper.batchUpdateExecutor(ids, request.getUserId()); + } + } } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanCaseLogService.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanCaseLogService.java index d4e6801ec6..80f6f1320f 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanCaseLogService.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanCaseLogService.java @@ -56,7 +56,7 @@ public class TestPlanCaseLogService { OperationLogType.UPDATE.name(), OperationLogModule.TEST_PLAN, caseMap.get(v)); - dto.setPath("/test-plan/functional/case/batch/update/executer"); + dto.setPath("/test-plan/functional/case/batch/update/executor"); dto.setMethod(HttpMethodConstants.POST.name()); dto.setOriginalValue(JSON.toJSONBytes(userMap.get(k))); dto.setModifiedValue(JSON.toJSONBytes(request.getUserId())); diff --git a/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanApiCaseControllerTests.java b/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanApiCaseControllerTests.java index 2a9dc77f32..4fdc7981d1 100644 --- a/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanApiCaseControllerTests.java +++ b/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanApiCaseControllerTests.java @@ -1,6 +1,7 @@ package io.metersphere.plan.controller; import io.metersphere.plan.dto.request.TestPlanApiCaseRequest; +import io.metersphere.plan.dto.request.TestPlanApiCaseUpdateRequest; import io.metersphere.plan.dto.request.TestPlanDisassociationRequest; import io.metersphere.sdk.util.JSON; import io.metersphere.system.base.BaseTest; @@ -14,6 +15,7 @@ import org.springframework.test.web.servlet.MvcResult; import java.nio.charset.StandardCharsets; import java.util.HashMap; +import java.util.List; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @AutoConfigureMockMvc @@ -24,6 +26,7 @@ public class TestPlanApiCaseControllerTests extends BaseTest { public static final String API_CASE_TREE_COUNT = "/test-plan/api/case/module/count"; public static final String API_CASE_TREE_MODULE_TREE = "/test-plan/api/case/tree/"; public static final String API_CASE_DISASSOCIATE = "/test-plan/api/case/disassociate"; + public static final String API_CASE_BATCH_UPDATE_EXECUTOR_URL = "/test-plan/api/case/batch/update/executor"; @Test @Order(1) @@ -86,4 +89,19 @@ public class TestPlanApiCaseControllerTests extends BaseTest { Assertions.assertNotNull(resultHolder); } + + @Test + @Order(5) + public void testBatchUpdateExecutor() throws Exception { + TestPlanApiCaseUpdateRequest request = new TestPlanApiCaseUpdateRequest(); + request.setUserId("test_user"); + request.setTestPlanId("wxxx_2"); + request.setSelectAll(true); + request.setProtocols(List.of("HTTP")); + this.requestPostWithOk(API_CASE_BATCH_UPDATE_EXECUTOR_URL, request); + request.setTestPlanId("wxxx_1"); + request.setSelectAll(false); + request.setSelectIds(List.of("wxxx_1")); + this.requestPostWithOk(API_CASE_BATCH_UPDATE_EXECUTOR_URL, request); + } }