diff --git a/backend/framework/sdk/src/main/resources/i18n/plan_en_US.properties b/backend/framework/sdk/src/main/resources/i18n/plan_en_US.properties index 064857ddf8..f4c96edae1 100644 --- a/backend/framework/sdk/src/main/resources/i18n/plan_en_US.properties +++ b/backend/framework/sdk/src/main/resources/i18n/plan_en_US.properties @@ -94,4 +94,5 @@ log.test_plan.update=Update resources log.test_plan.functional_case=Functional case log.test_plan.api_case=Api case log.test_plan.api_scenario=Api scenario -test_plan.type.not_blank=Test plan type cannot be empty \ No newline at end of file +test_plan.type.not_blank=Test plan type cannot be empty +test_plan.group.not_plan=There are no archived plans in the current testing plan group \ No newline at end of file diff --git a/backend/framework/sdk/src/main/resources/i18n/plan_zh_CN.properties b/backend/framework/sdk/src/main/resources/i18n/plan_zh_CN.properties index cffddb9777..96bab37f49 100644 --- a/backend/framework/sdk/src/main/resources/i18n/plan_zh_CN.properties +++ b/backend/framework/sdk/src/main/resources/i18n/plan_zh_CN.properties @@ -94,4 +94,5 @@ log.test_plan.update=修改了资源 log.test_plan.functional_case=功能用例 log.test_plan.api_case=接口用例 log.test_plan.api_scenario=接口场景 -test_plan.type.not_blank=测试计划类型不能为空 \ No newline at end of file +test_plan.type.not_blank=测试计划类型不能为空 +test_plan.group.not_plan=当前测试计划组没有可归档计划 \ No newline at end of file diff --git a/backend/framework/sdk/src/main/resources/i18n/plan_zh_TW.properties b/backend/framework/sdk/src/main/resources/i18n/plan_zh_TW.properties index 81a20ee468..71a02658f9 100644 --- a/backend/framework/sdk/src/main/resources/i18n/plan_zh_TW.properties +++ b/backend/framework/sdk/src/main/resources/i18n/plan_zh_TW.properties @@ -94,4 +94,5 @@ log.test_plan.update=修改了資源 log.test_plan.functional_case=功能用例 log.test_plan.api_case=接口用例 log.test_plan.api_scenario=接口場景 -test_plan.type.not_blank=測試計劃類型不能為空 \ No newline at end of file +test_plan.type.not_blank=測試計劃類型不能為空 +test_plan.group.not_plan=當前測試計劃組沒有可歸檔計劃 \ No newline at end of file diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanController.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanController.java index aabdf28d15..384f15f322 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanController.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanController.java @@ -4,10 +4,13 @@ import io.metersphere.plan.constants.TestPlanResourceConfig; import io.metersphere.plan.dto.request.*; import io.metersphere.plan.dto.response.TestPlanCountResponse; import io.metersphere.plan.dto.response.TestPlanResponse; +import io.metersphere.plan.service.TestPlanLogService; import io.metersphere.plan.service.TestPlanManagementService; import io.metersphere.plan.service.TestPlanService; import io.metersphere.sdk.constants.HttpMethodConstants; import io.metersphere.sdk.constants.PermissionConstants; +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.Pager; import io.metersphere.system.utils.SessionUtils; @@ -111,4 +114,14 @@ public class TestPlanController { } + @GetMapping("/archived/{id}") + @Operation(summary = "测试计划-归档") + @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_UPDATE) + @CheckOwner(resourceId = "#id", resourceType = "test_plan") + @Log(type = OperationLogType.ARCHIVED, expression = "#msClass.archivedLog(#id)", msClass = TestPlanLogService.class) + public void archived(@NotBlank @PathVariable String id) { + String userId = SessionUtils.getUserId(); + testPlanService.archived(id, userId); + } + } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanMapper.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanMapper.java index 9b58c925a1..4f9cb66102 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanMapper.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanMapper.java @@ -28,4 +28,6 @@ public interface ExtTestPlanMapper { long updateDefaultGroupId(@Param("list") List groupIds); String selectProjectIdByTestPlanId(String testPlanId); + + void batchUpdateStatus(@Param("status") String status, @Param("userId") String userId, @Param("updateTime") Long updateTime, @Param("ids") List ids); } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanMapper.xml b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanMapper.xml index fc1ab1b273..eff004c919 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanMapper.xml +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanMapper.xml @@ -359,4 +359,14 @@ + + + UPDATE test_plan + SET status = #{status}, update_user = #{userId}, update_time = #{updateTime} + WHERE id IN + + #{id} + + + \ No newline at end of file diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanLogService.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanLogService.java index e9d7472f44..89b7c5e8b9 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanLogService.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanLogService.java @@ -1,8 +1,10 @@ package io.metersphere.plan.service; import io.metersphere.plan.domain.TestPlan; +import io.metersphere.plan.mapper.TestPlanMapper; import io.metersphere.project.domain.Project; import io.metersphere.project.mapper.ProjectMapper; +import io.metersphere.sdk.constants.HttpMethodConstants; import io.metersphere.sdk.constants.TestPlanConstants; import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.Translator; @@ -29,6 +31,8 @@ public class TestPlanLogService { private ProjectMapper projectMapper; @Resource private OperationLogService operationLogService; + @Resource + private TestPlanMapper testPlanMapper; public void saveAddLog(TestPlan module, String operator, String requestUrl, String requestMethod) { Project project = projectMapper.selectByPrimaryKey(module.getProjectId()); @@ -115,7 +119,7 @@ public class TestPlanLogService { private String generateTestPlanDeleteContent(TestPlan deleteTestPlan) { StringBuilder content = new StringBuilder(); - if(StringUtils.equals(deleteTestPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)){ + if (StringUtils.equals(deleteTestPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) { content.append(Translator.get("log.delete.test_plan_group")).append(":").append(deleteTestPlan.getName()).append(StringUtils.SPACE); } else { content.append(Translator.get("log.delete.test_plan")).append(":").append(deleteTestPlan.getName()).append(StringUtils.SPACE); @@ -123,4 +127,25 @@ public class TestPlanLogService { return content.toString(); } + /** + * 归档日志 + * + * @param id + * @return + */ + public LogDTO archivedLog(String id) { + TestPlan testPlan = testPlanMapper.selectByPrimaryKey(id); + LogDTO dto = new LogDTO( + testPlan.getProjectId(), + null, + testPlan.getId(), + null, + OperationLogType.ARCHIVED.name(), + logModule, + testPlan.getName()); + dto.setPath("/test-plan/archived"); + dto.setMethod(HttpMethodConstants.GET.name()); + dto.setOriginalValue(JSON.toJSONBytes(testPlan)); + return dto; + } } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanService.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanService.java index 56a3f34411..0366e3d4c7 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanService.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanService.java @@ -34,6 +34,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; @Service @Transactional(rollbackFor = Exception.class) @@ -360,4 +361,46 @@ public class TestPlanService { testPlanFollowerMapper.insert(testPlanFollower); } } + + + /** + * 测试计划归档 + * + * @param id + * @param userId + */ + public void archived(String id, String userId) { + TestPlan testPlan = testPlanMapper.selectByPrimaryKey(id); + if (StringUtils.equalsAnyIgnoreCase(testPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) { + //测试计划组归档 + updateGroupStatus(testPlan.getId(), userId); + } else { + //测试计划 + testPlan.setStatus(TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED); + testPlan.setUpdateUser(userId); + testPlan.setUpdateTime(System.currentTimeMillis()); + testPlanMapper.updateByPrimaryKeySelective(testPlan); + } + + } + + /** + * 测试计划组归档 + * + * @param id + * @param userId + */ + private void updateGroupStatus(String id, String userId) { + TestPlanExample example = new TestPlanExample(); + example.createCriteria().andGroupIdEqualTo(id); + List testPlanList = testPlanMapper.selectByExample(example); + if (CollectionUtils.isEmpty(testPlanList)) { + throw new MSException(Translator.get("test_plan.group.not_plan")); + } + List ids = testPlanList.stream().filter(item -> StringUtils.equalsIgnoreCase(item.getStatus(), TestPlanConstants.TEST_PLAN_STATUS_COMPLETED)).map(TestPlan::getId).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(ids)) { + throw new MSException(Translator.get("test_plan.group.not_plan")); + } + extTestPlanMapper.batchUpdateStatus(TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED, userId, System.currentTimeMillis(), ids); + } } diff --git a/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanTests.java b/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanTests.java index 3b910ec52c..28391e12ae 100644 --- a/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanTests.java +++ b/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanTests.java @@ -120,6 +120,7 @@ public class TestPlanTests extends BaseTest { private static final String URL_POST_RESOURCE_API_SCENARIO_SORT = "/test-plan/api/scenario/sort"; private static final String URL_TEST_PLAN_EDIT_FOLLOWER = "/test-plan/edit/follower"; + private static final String URL_TEST_PLAN_ARCHIVED = "/test-plan/archived/%s"; private static String groupTestPlanId7 = null; private static String groupTestPlanId15 = null; @@ -2081,4 +2082,16 @@ public class TestPlanTests extends BaseTest { Assertions.assertNotNull(returnId); } + @Test + @Order(302) + public void testArchived() throws Exception { + //计划 + this.requestGetWithOk(String.format(URL_TEST_PLAN_ARCHIVED, "wx_test_plan_id_1")); + //计划组 + this.requestGet(String.format(URL_TEST_PLAN_ARCHIVED, "wx_test_plan_id_2")); + this.requestGet(String.format(URL_TEST_PLAN_ARCHIVED, "wx_test_plan_id_3")); + this.requestGetWithOk(String.format(URL_TEST_PLAN_ARCHIVED, "wx_test_plan_id_5")); + + } + } diff --git a/backend/services/test-plan/src/test/resources/dml/init_test_plan_test.sql b/backend/services/test-plan/src/test/resources/dml/init_test_plan_test.sql index e698805c17..a1d126ad0a 100644 --- a/backend/services/test-plan/src/test/resources/dml/init_test_plan_test.sql +++ b/backend/services/test-plan/src/test/resources/dml/init_test_plan_test.sql @@ -1,3 +1,8 @@ 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 - ('wx_test_plan_id_1', 5000, 'wx', 'NONE', '1', '测试一下计划', 'PREPARED', 'TEST_PLAN', NULL, 1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000, 1714980158000, '11'); + ('wx_test_plan_id_1', 5000, 'wx', 'NONE', '1', '测试一下计划', 'PREPARED', 'TEST_PLAN', NULL, 1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000, 1714980158000, '11'), + ('wx_test_plan_id_2', 10000, 'wx', 'NONE', '1', '测试一下组', 'PREPARED', 'GROUP', NULL, 1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000, 1714980158000, '11'), + ('wx_test_plan_id_3', 15000, 'wx', 'NONE', '1', '测试一下组2', 'PREPARED', 'GROUP', NULL, 1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000, 1714980158000, '11'), + ('wx_test_plan_id_4', 20000, 'wx', 'wx_test_plan_id_3', '1', '测试一下计划2', 'PREPARED', 'TEST_PLAN', NULL, 1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000, 1714980158000, '11'), + ('wx_test_plan_id_5', 25000, 'wx', 'NONE', '1', '测试一下组3', 'PREPARED', 'GROUP', NULL, 1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000, 1714980158000, '11'), + ('wx_test_plan_id_6', 30000, 'wx', 'wx_test_plan_id_5', '1', '测试组3下计划', 'COMPLETED', 'TEST_PLAN', NULL, 1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000, 1714980158000, '11'); \ No newline at end of file