diff --git a/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanFollower.java b/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanFollower.java index e753867db1..59d4f42046 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanFollower.java +++ b/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanFollower.java @@ -1,24 +1,96 @@ package io.metersphere.plan.domain; -import io.metersphere.validation.groups.Created; -import io.metersphere.validation.groups.Updated; +import io.metersphere.validation.groups.*; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.Size; +import jakarta.validation.constraints.*; import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; import lombok.Data; @Data public class TestPlanFollower implements Serializable { - @Schema(description = "测试计划ID;联合主键", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "测试计划ID;联合主键", requiredMode = Schema.RequiredMode.REQUIRED) @NotBlank(message = "{test_plan_follower.test_plan_id.not_blank}", groups = {Created.class}) @Size(min = 1, max = 50, message = "{test_plan_follower.test_plan_id.length_range}", groups = {Created.class, Updated.class}) private String testPlanId; - @Schema(description = "用户ID;联合主键", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "用户ID;联合主键", requiredMode = Schema.RequiredMode.REQUIRED) @NotBlank(message = "{test_plan_follower.user_id.not_blank}", groups = {Created.class}) @Size(min = 1, max = 50, message = "{test_plan_follower.user_id.length_range}", groups = {Created.class, Updated.class}) private String userId; private static final long serialVersionUID = 1L; + + public enum Column { + testPlanId("test_plan_id", "testPlanId", "VARCHAR", false), + userId("user_id", "userId", "VARCHAR", false); + + private static final String BEGINNING_DELIMITER = "`"; + + private static final String ENDING_DELIMITER = "`"; + + private final String column; + + private final boolean isColumnNameDelimited; + + private final String javaProperty; + + private final String jdbcType; + + public String value() { + return this.column; + } + + public String getValue() { + return this.column; + } + + public String getJavaProperty() { + return this.javaProperty; + } + + public String getJdbcType() { + return this.jdbcType; + } + + Column(String column, String javaProperty, String jdbcType, boolean isColumnNameDelimited) { + this.column = column; + this.javaProperty = javaProperty; + this.jdbcType = jdbcType; + this.isColumnNameDelimited = isColumnNameDelimited; + } + + public String desc() { + return this.getEscapedColumnName() + " DESC"; + } + + public String asc() { + return this.getEscapedColumnName() + " ASC"; + } + + public static Column[] excludes(Column ... excludes) { + ArrayList columns = new ArrayList<>(Arrays.asList(Column.values())); + if (excludes != null && excludes.length > 0) { + columns.removeAll(new ArrayList<>(Arrays.asList(excludes))); + } + return columns.toArray(new Column[]{}); + } + + public static Column[] all() { + return Column.values(); + } + + public String getEscapedColumnName() { + if (this.isColumnNameDelimited) { + return new StringBuilder().append(BEGINNING_DELIMITER).append(this.column).append(ENDING_DELIMITER).toString(); + } else { + return this.column; + } + } + + public String getAliasedEscapedColumnName() { + return this.getEscapedColumnName(); + } + } } \ No newline at end of file diff --git a/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanFollowerMapper.java b/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanFollowerMapper.java index 3099d4ef0b..29ac691ecd 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanFollowerMapper.java +++ b/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanFollowerMapper.java @@ -21,4 +21,8 @@ public interface TestPlanFollowerMapper { int updateByExampleSelective(@Param("record") TestPlanFollower record, @Param("example") TestPlanFollowerExample example); int updateByExample(@Param("record") TestPlanFollower record, @Param("example") TestPlanFollowerExample example); + + int batchInsert(@Param("list") List list); + + int batchInsertSelective(@Param("list") List list, @Param("selective") TestPlanFollower.Column ... selective); } \ No newline at end of file diff --git a/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanFollowerMapper.xml b/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanFollowerMapper.xml index 808700173f..7ef023acc5 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanFollowerMapper.xml +++ b/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanFollowerMapper.xml @@ -142,4 +142,32 @@ + + insert into test_plan_follower + (test_plan_id, user_id) + values + + (#{item.testPlanId,jdbcType=VARCHAR}, #{item.userId,jdbcType=VARCHAR}) + + + + insert into test_plan_follower ( + + ${column.escapedColumnName} + + ) + values + + ( + + + #{item.testPlanId,jdbcType=VARCHAR} + + + #{item.userId,jdbcType=VARCHAR} + + + ) + + \ No newline at end of file diff --git a/backend/framework/domain/src/main/resources/migration/3.0.0/ddl/V3.0.0_3__test_plan.sql b/backend/framework/domain/src/main/resources/migration/3.0.0/ddl/V3.0.0_3__test_plan.sql index e8e2464f86..da0049f441 100644 --- a/backend/framework/domain/src/main/resources/migration/3.0.0/ddl/V3.0.0_3__test_plan.sql +++ b/backend/framework/domain/src/main/resources/migration/3.0.0/ddl/V3.0.0_3__test_plan.sql @@ -13,7 +13,9 @@ CREATE TABLE IF NOT EXISTS test_plan_module `create_user` VARCHAR(100) COMMENT '创建人', `update_user` VARCHAR(100) COMMENT '更新人', PRIMARY KEY (id) -) COMMENT = '测试计划模块'; +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 + COLLATE = utf8mb4_general_ci COMMENT = '测试计划模块'; CREATE INDEX idx_project_id ON test_plan_module (project_id); @@ -42,7 +44,9 @@ CREATE TABLE IF NOT EXISTS test_plan `actual_end_time` BIGINT COMMENT '实际结束时间', `description` VARCHAR(2000) COMMENT '描述', PRIMARY KEY (id) -) COMMENT = '测试计划'; +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 + COLLATE = utf8mb4_general_ci COMMENT = '测试计划'; CREATE INDEX idx_group_id ON test_plan (group_id); CREATE INDEX idx_project_id ON test_plan (project_id); @@ -60,14 +64,18 @@ CREATE TABLE IF NOT EXISTS test_plan_config `repeat_case` BIT NOT NULL DEFAULT 0 COMMENT '是否允许重复添加用例', `pass_threshold` DOUBLE NOT NULL DEFAULT 100 COMMENT '测试计划通过阈值;0-100', PRIMARY KEY (test_plan_id) -) COMMENT = '测试计划配置'; +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 + COLLATE = utf8mb4_general_ci COMMENT = '测试计划配置'; CREATE TABLE IF NOT EXISTS test_plan_follower ( `test_plan_id` VARCHAR(50) NOT NULL COMMENT '测试计划ID;联合主键', `user_id` VARCHAR(50) NOT NULL COMMENT '用户ID;联合主键', PRIMARY KEY (test_plan_id, user_id) -) COMMENT = '测试计划关注人'; +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 + COLLATE = utf8mb4_general_ci COMMENT = '测试计划关注人'; CREATE TABLE IF NOT EXISTS test_plan_functional_case ( @@ -81,7 +89,9 @@ CREATE TABLE IF NOT EXISTS test_plan_functional_case `last_exec_result` VARCHAR(50) COMMENT '最后执行结果', `pos` BIGINT NOT NULL COMMENT '自定义排序,间隔5000', PRIMARY KEY (id) -) COMMENT = '测试计划关联功能用例'; +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 + COLLATE = utf8mb4_general_ci COMMENT = '测试计划关联功能用例'; CREATE INDEX idx_functional_case_id ON test_plan_functional_case (functional_case_id); CREATE INDEX idx_test_plan_id ON test_plan_functional_case (test_plan_id); @@ -100,7 +110,9 @@ CREATE TABLE IF NOT EXISTS test_plan_api_case `create_user` VARCHAR(50) NOT NULL COMMENT '创建人', `pos` BIGINT NOT NULL COMMENT '自定义排序,间隔5000', PRIMARY KEY (id) -) COMMENT = '测试计划关联接口用例'; +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 + COLLATE = utf8mb4_general_ci COMMENT = '测试计划关联接口用例'; CREATE INDEX idx_api_case_id ON test_plan_api_case (api_case_id); @@ -120,12 +132,23 @@ CREATE TABLE IF NOT EXISTS test_plan_api_scenario `create_user` VARCHAR(40) NOT NULL COMMENT '创建人', `pos` BIGINT NOT NULL COMMENT '自定义排序,间隔5000', PRIMARY KEY (id) -) COMMENT = '测试计划关联场景用例'; +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 + COLLATE = utf8mb4_general_ci COMMENT = '测试计划关联场景用例'; CREATE INDEX idx_api_scenario_id ON test_plan_api_scenario (api_scenario_id); CREATE INDEX idx_test_plan_id ON test_plan_api_scenario (test_plan_id); CREATE INDEX idx_create_user ON test_plan_api_scenario (create_user); +CREATE TABLE IF NOT EXISTS test_plan_follower +( + `test_plan_id` VARCHAR(50) NOT NULL COMMENT '测试计划ID;联合主键', + `user_id` VARCHAR(50) NOT NULL COMMENT '用户ID;联合主键', + PRIMARY KEY (test_plan_id, user_id) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 + COLLATE = utf8mb4_general_ci COMMENT = '测试计划关注人'; + -- set innodb lock wait timeout to default SET SESSION innodb_lock_wait_timeout = DEFAULT; \ No newline at end of file diff --git a/backend/framework/sdk/src/main/java/io/metersphere/sdk/constants/TestPlanConstants.java b/backend/framework/sdk/src/main/java/io/metersphere/sdk/constants/TestPlanConstants.java index 8fe940ec3e..18bb9af47a 100644 --- a/backend/framework/sdk/src/main/java/io/metersphere/sdk/constants/TestPlanConstants.java +++ b/backend/framework/sdk/src/main/java/io/metersphere/sdk/constants/TestPlanConstants.java @@ -6,7 +6,7 @@ public class TestPlanConstants { //测试计划类型-测试计划组 public static final String TEST_PLAN_TYPE_GROUP = "GROUP"; //测试计划组默认ID - public static final String TEST_PLAN_DEFAULT_GROUP_ID = "none"; + public static final String TEST_PLAN_DEFAULT_GROUP_ID = "NONE"; //测试计划状态-未开始 public static final String TEST_PLAN_STATUS_PREPARED = "PREPARED"; diff --git a/backend/framework/sdk/src/main/resources/i18n/plan.properties b/backend/framework/sdk/src/main/resources/i18n/plan.properties index 6c35c7e32f..e70c17ac3a 100644 --- a/backend/framework/sdk/src/main/resources/i18n/plan.properties +++ b/backend/framework/sdk/src/main/resources/i18n/plan.properties @@ -1,3 +1,5 @@ +test_plan.test_plan=测试计划 +test_plan.test_plan_group=测试计划组 test_plan.id.not_blank=测试计划id不能为空 test_plan.project_id.length_range=测试计划所属项目id长度过长 test_plan.project_id.not_blank=测试计划所属项目id不能为空 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 6539b81592..afb1076fe5 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 @@ -1,3 +1,5 @@ +test_plan.test_plan=Test plan +test_plan.test_plan_group=Test plan group test_plan.id.not_blank=Test plan id cannot be empty test_plan.project_id.length_range=Test plan project id length too long test_plan.project_id.not_blank=Test plan project id cannot be empty 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 6c35c7e32f..e70c17ac3a 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 @@ -1,3 +1,5 @@ +test_plan.test_plan=测试计划 +test_plan.test_plan_group=测试计划组 test_plan.id.not_blank=测试计划id不能为空 test_plan.project_id.length_range=测试计划所属项目id长度过长 test_plan.project_id.not_blank=测试计划所属项目id不能为空 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 8d4371ffbe..1751fcf346 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 @@ -1,3 +1,5 @@ +test_plan.test_plan=測試計劃 +test_plan.test_plan_group=測試計劃組 test_plan.id.not_blank=測試計劃id不能為空 test_plan.project_id.length_range=測試計劃所屬項目id長度過長 test_plan.project_id.not_blank=測試計劃所屬項目id不能為空 diff --git a/backend/services/project-management/src/main/java/io/metersphere/project/service/ModuleTreeService.java b/backend/services/project-management/src/main/java/io/metersphere/project/service/ModuleTreeService.java index f0f5abb2bc..4a4b2e06e7 100644 --- a/backend/services/project-management/src/main/java/io/metersphere/project/service/ModuleTreeService.java +++ b/backend/services/project-management/src/main/java/io/metersphere/project/service/ModuleTreeService.java @@ -63,6 +63,7 @@ public abstract class ModuleTreeService { * @param haveVirtualRootNode 是否包含虚拟跟节点 */ public List buildTreeAndCountResource(List traverseList, boolean haveVirtualRootNode, String virtualRootName) { + List baseTreeNodeList = new ArrayList<>(); if (haveVirtualRootNode) { BaseTreeNode defaultNode = this.getDefaultModule(virtualRootName); diff --git a/backend/services/system-setting/src/test/java/io/metersphere/system/controller/LicenseControllerTests.java b/backend/services/system-setting/src/test/java/io/metersphere/system/controller/LicenseControllerTests.java index 188fb12165..56ef48aaae 100644 --- a/backend/services/system-setting/src/test/java/io/metersphere/system/controller/LicenseControllerTests.java +++ b/backend/services/system-setting/src/test/java/io/metersphere/system/controller/LicenseControllerTests.java @@ -1,10 +1,10 @@ package io.metersphere.system.controller; import io.metersphere.sdk.constants.SessionConstants; -import io.metersphere.system.dto.sdk.LicenseDTO; import io.metersphere.sdk.util.JSON; import io.metersphere.system.base.BaseTest; import io.metersphere.system.controller.handler.ResultHolder; +import io.metersphere.system.dto.sdk.LicenseDTO; import jakarta.annotation.Resource; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.MethodOrderer; @@ -72,7 +72,7 @@ public class LicenseControllerTests extends BaseTest { Assertions.assertEquals(200, mvcResult.getResponse().getStatus()); LicenseDTO licenseDTO = parseObjectFromMvcResult(mvcResult, LicenseDTO.class); Assertions.assertNotNull(licenseDTO); - Assertions.assertEquals("OK", licenseDTO.getStatus()); + Assertions.assertEquals("valid", licenseDTO.getStatus()); } @Test @@ -81,7 +81,7 @@ public class LicenseControllerTests extends BaseTest { Assertions.assertEquals(200, mvcResult.getResponse().getStatus()); LicenseDTO licenseDTO = parseObjectFromMvcResult(mvcResult, LicenseDTO.class); Assertions.assertNotNull(licenseDTO); - Assertions.assertEquals("OK", licenseDTO.getStatus()); + Assertions.assertEquals("valid", licenseDTO.getStatus()); } diff --git a/backend/services/system-setting/src/test/java/io/metersphere/system/mock/LicenseServiceMockImpl.java b/backend/services/system-setting/src/test/java/io/metersphere/system/mock/LicenseServiceMockImpl.java index d1ef43cce7..24142f7181 100644 --- a/backend/services/system-setting/src/test/java/io/metersphere/system/mock/LicenseServiceMockImpl.java +++ b/backend/services/system-setting/src/test/java/io/metersphere/system/mock/LicenseServiceMockImpl.java @@ -10,21 +10,21 @@ public class LicenseServiceMockImpl implements LicenseService { @Override public LicenseDTO refreshLicense() { LicenseDTO licenseDTO = new LicenseDTO(); - licenseDTO.setStatus("OK"); + licenseDTO.setStatus("valid"); return licenseDTO; } @Override public LicenseDTO validate() { LicenseDTO licenseDTO = new LicenseDTO(); - licenseDTO.setStatus("OK"); + licenseDTO.setStatus("valid"); return licenseDTO; } @Override public LicenseDTO addLicense(String licenseCode, String userId) { LicenseDTO licenseDTO = new LicenseDTO(); - licenseDTO.setStatus("OK"); + licenseDTO.setStatus("valid"); return licenseDTO; } 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 4a150baa6d..baf9abd6d3 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 @@ -3,6 +3,8 @@ package io.metersphere.plan.controller; import io.metersphere.plan.dto.request.TestPlanBatchProcessRequest; import io.metersphere.plan.dto.request.TestPlanCreateRequest; import io.metersphere.plan.dto.request.TestPlanTableRequest; +import io.metersphere.plan.dto.request.TestPlanUpdateRequest; +import io.metersphere.plan.dto.response.TestPlanCountResponse; import io.metersphere.plan.dto.response.TestPlanResponse; import io.metersphere.plan.service.TestPlanManagementService; import io.metersphere.plan.service.TestPlanService; @@ -43,7 +45,7 @@ public class TestPlanController { @Operation(summary = "测试计划-获取统计数据") @RequiresPermissions(PermissionConstants.TEST_PLAN_READ) @CheckOwner(resourceId = "#id", resourceType = "test_plan") - public TestPlanResponse getCount(@PathVariable String id) { + public TestPlanCountResponse getCount(@PathVariable String id) { return testPlanService.getCount(id); } @@ -52,7 +54,8 @@ public class TestPlanController { @Operation(summary = "测试计划-模块统计") @RequiresPermissions(PermissionConstants.TEST_PLAN_READ) @CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project") - public Map moduleCount(@Validated @RequestBody TestPlanTableRequest request) { + public Map moduleCount(@Validated @RequestBody TestPlanTableRequest + request) { return testPlanManagementService.moduleCount(request); } @@ -61,8 +64,16 @@ public class TestPlanController { @Operation(summary = "测试计划-创建测试计划") @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_ADD) @CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project") - public String add(@Validated @RequestBody TestPlanCreateRequest testPlan) { - return testPlanService.add(testPlan, SessionUtils.getUserId(), "/test-plan/add", HttpMethodConstants.POST.name()); + public String add(@Validated @RequestBody TestPlanCreateRequest request) { + return testPlanService.add(request, SessionUtils.getUserId(), "/test-plan/add", HttpMethodConstants.POST.name()); + } + + @PostMapping("/update") + @Operation(summary = "测试计划-创建测试计划") + @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_UPDATE) + @CheckOwner(resourceId = "#request.getId()", resourceType = "test_plan") + public String add(@Validated @RequestBody TestPlanUpdateRequest request) { + return testPlanService.update(request, SessionUtils.getUserId(), "/test-plan/update", HttpMethodConstants.POST.name()); } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/TestPlanQueryConditions.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/TestPlanQueryConditions.java index 933c084bae..15ad3aae69 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/TestPlanQueryConditions.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/TestPlanQueryConditions.java @@ -21,7 +21,7 @@ public class TestPlanQueryConditions { private String projectId; //测试计划所属GroupId - private String groupId = TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID; + private String groupId; //查询条件 private BaseCondition condition = new BaseCondition(); @@ -29,7 +29,11 @@ public class TestPlanQueryConditions { //隐藏的测试计划ID public List hiddenIds = new ArrayList<>(); + //需要包含的ID + public List includeIds = new ArrayList<>(); + public TestPlanQueryConditions(List moduleIds,String projectId,BaseCondition condition){ + this.groupId = TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID; this.moduleIds = moduleIds; this.projectId = projectId; this.condition = condition; diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanCreateRequest.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanCreateRequest.java index 3697317701..d85c8be3a4 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanCreateRequest.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanCreateRequest.java @@ -7,6 +7,7 @@ import jakarta.validation.constraints.Max; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Size; import lombok.Data; +import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; import java.util.LinkedHashSet; @@ -58,8 +59,14 @@ public class TestPlanCreateRequest { @Schema(description = "测试计划通过阈值;0-100", requiredMode = Schema.RequiredMode.REQUIRED) @Max(value = 100, message = "{test_plan.pass_threshold.max}") private double passThreshold = 100; + @Schema(description = "测试计划类型") + private String type = TestPlanConstants.TEST_PLAN_TYPE_PLAN; public List getTags() { return tags == null ? null : new ArrayList<>(tags); } + + public boolean isGroupOption() { + return StringUtils.equals(this.type, TestPlanConstants.TEST_PLAN_TYPE_GROUP) || !StringUtils.equals(this.groupId, TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID); + } } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanTableRequest.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanTableRequest.java index 2337b21f88..8b73de685a 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanTableRequest.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanTableRequest.java @@ -5,6 +5,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import lombok.Data; import lombok.EqualsAndHashCode; +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; import java.util.List; @@ -22,4 +24,9 @@ public class TestPlanTableRequest extends BasePageRequest { this.setCurrent(1); this.setPageSize(5); } + + //没有查询条件 + public boolean conditionIsEmpty() { + return StringUtils.isEmpty(this.getKeyword()) && MapUtils.isEmpty(this.getFilter()) && MapUtils.isEmpty(this.getCombine()); + } } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanUpdateRequest.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanUpdateRequest.java new file mode 100644 index 0000000000..d2a28de401 --- /dev/null +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanUpdateRequest.java @@ -0,0 +1,49 @@ +package io.metersphere.plan.dto.request; + +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 java.util.LinkedHashSet; + +@Data +public class TestPlanUpdateRequest { + @Schema(description = "测试计划ID") + @NotBlank(message = "{test_plan.id.not_blank}") + private String id; + + @Schema(description = "测试计划名称") + private String name; + + @Schema(description = "模块ID") + private String moduleId; + + @Schema(description = "标签") + private LinkedHashSet tags; + + @Schema(description = "计划开始时间") + private Long plannedStartTime; + + @Schema(description = "计划结束时间") + private Long plannedEndTime; + + @Schema(description = "描述") + private String description; + + @Schema(description = "是否自定更新功能用例状态") + private Boolean automaticStatusUpdate; + + @Schema(description = "是否允许重复添加用例") + private Boolean repeatCase; + + @Schema(description = "测试计划通过阈值;0-100", requiredMode = Schema.RequiredMode.REQUIRED) + @Max(value = 100) + @Min(value = 0) + private Double passThreshold; + + @Schema(description = "测试计划组Id") + private String testPlanGroupId; + +} diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/response/TestPlanCountResponse.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/response/TestPlanCountResponse.java new file mode 100644 index 0000000000..d0091c9326 --- /dev/null +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/response/TestPlanCountResponse.java @@ -0,0 +1,22 @@ +package io.metersphere.plan.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class TestPlanCountResponse { + @Schema(description = "测试计划ID") + private String id; + @Schema(description = "通过率") + private String passRate; + @Schema(description = "功能用例数") + private long functionalCaseCount = -1; + @Schema(description = "接口用例数") + private long apiCaseCount = -1; + @Schema(description = "接口场景数") + private long apiScenarioCount = -1; + @Schema(description = "Bug数量") + private long bugCount = -1; + @Schema(description = "测试进度") + private String testProgress; +} diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/response/TestPlanResponse.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/response/TestPlanResponse.java index 81b12ad496..d29eb8a436 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/response/TestPlanResponse.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/response/TestPlanResponse.java @@ -3,29 +3,22 @@ package io.metersphere.plan.dto.response; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import java.util.List; + @Data public class TestPlanResponse { - //:ID、计划名称、计划状态、测试进度、通过率、用例数、定时任务、bug数、创建人、创建时间、模块 @Schema(description = "测试计划ID") private String id; + @Schema(description = "项目ID") + private String projectId; @Schema(description = "测试计划编号") private long num; @Schema(description = "名称") private String name; @Schema(description = "状态") private String status; - @Schema(description = "测试进度") - private String testProgress; - @Schema(description = "通过率") - private String passRate; - @Schema(description = "功能用例数") - private long functionalCaseCount = -1; - @Schema(description = "接口用例数") - private long apiCaseCount = -1; - @Schema(description = "接口场景数") - private long apiScenarioCount = -1; - @Schema(description = "Bug数量") - private long bugCount = -1; + @Schema(description = "标签") + private List tags; @Schema(description = "定时任务") private String schedule; @Schema(description = "创建人") @@ -36,6 +29,9 @@ public class TestPlanResponse { private String moduleName; @Schema(description = "模块Id") private String moduleId; - @Schema(description = "类型(测试计划组/测试计划)") - private String type; + @Schema(description = "测试计划组内的测试计划") + List testPlanItem; + + @Schema(description = "测试计划组Id") + private String testPlanGroupId; } 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 20656dd91c..86a35f8edd 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 @@ -17,7 +17,9 @@ public interface ExtTestPlanMapper { List selectIdByConditions(TestPlanQueryConditions testPlanQueryConditions); - List countModuleIdByKeywordAndFileType(TestPlanQueryConditions testPlanQueryConditions); + List selectGroupIdByConditions(TestPlanQueryConditions testPlanQueryConditions); + + List countModuleIdByConditions(TestPlanQueryConditions testPlanQueryConditions); List selectBaseInfoByIds(@Param("list") List deleteIdList); 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 3855af8714..2287e2cc09 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 @@ -1,9 +1,21 @@ + + + + + + + + + + + + UPDATE test_plan - SET group_id = 'none' + SET group_id = 'NONE' WHERE group_id IN #{item} @@ -22,7 +34,7 @@ - + + + - - t.group_id = #{groupId} - - AND t.project_id = #{projectId} + WHERE t.project_id = #{projectId} + + AND t.group_id = #{groupId} AND t.name like concat('%', #{condition.keyword}, '%') @@ -83,6 +107,13 @@ #{item} - + + OR + t.id IN + + #{item} + + + \ No newline at end of file diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanGroupService.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanGroupService.java new file mode 100644 index 0000000000..4895606cfe --- /dev/null +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanGroupService.java @@ -0,0 +1,8 @@ +package io.metersphere.plan.service; + +import io.metersphere.plan.domain.TestPlan; +import io.metersphere.plan.domain.TestPlanConfig; + +public interface TestPlanGroupService { + boolean validateGroup(TestPlan testPlan, TestPlanConfig testPlanConfig); +} 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 62f2584c2c..e9d7472f44 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 @@ -40,7 +40,7 @@ public class TestPlanLogService { .method(requestMethod) .path(requestUrl) .sourceId(module.getId()) - .content(module.getName()) + .content(generateTestPlanSimpleContent(module)) .originalValue(JSON.toJSONBytes(module)) .createUser(operator) .build().getLogDTO(); @@ -103,6 +103,16 @@ public class TestPlanLogService { operationLogService.batchAdd(list); } + private String generateTestPlanSimpleContent(TestPlan testPlan) { + StringBuilder content = new StringBuilder(); + if (StringUtils.equals(testPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) { + content.append(Translator.get("test_plan.test_plan_group")).append(StringUtils.SPACE).append(testPlan.getName()).append(StringUtils.SPACE); + } else { + content.append(Translator.get("test_plan.test_plan")).append(StringUtils.SPACE).append(testPlan.getName()).append(StringUtils.SPACE); + } + return content.toString(); + } + private String generateTestPlanDeleteContent(TestPlan deleteTestPlan) { StringBuilder content = new StringBuilder(); if(StringUtils.equals(deleteTestPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)){ diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanManagementService.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanManagementService.java index 5cad541976..4d83d52412 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanManagementService.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanManagementService.java @@ -28,20 +28,37 @@ public class TestPlanManagementService { public Map moduleCount(TestPlanTableRequest request) { //查出每个模块节点下的资源数量。 不需要按照模块进行筛选 TestPlanQueryConditions testPlanQueryConditions = new TestPlanQueryConditions(null, request.getProjectId(), request); - List moduleCountDTOList = extTestPlanMapper.countModuleIdByKeywordAndFileType(testPlanQueryConditions); + List moduleCountDTOList = extTestPlanMapper.countModuleIdByConditions(testPlanQueryConditions); Map moduleCountMap = testPlanModuleService.getModuleCountMap(request.getProjectId(), moduleCountDTOList); - return moduleCountMap; } public Pager> page(TestPlanTableRequest request) { + TestPlanQueryConditions queryConditions = this.generateTestPlanConditions(request); Page page = PageHelper.startPage(request.getCurrent(), request.getPageSize(), StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "t.update_time desc"); - return PageUtils.setPageInfo(page, this.getTableList(request)); + return PageUtils.setPageInfo(page, this.getTableList(queryConditions)); } - private List getTableList(TestPlanTableRequest request) { - List testPlanResponses = extTestPlanMapper.selectByConditions(new TestPlanQueryConditions(request.getModuleIds(), request.getProjectId(), request)); + /** + * 生成查询条件 + * + * @param request 前端传来的筛选条件 + * @return + */ + private TestPlanQueryConditions generateTestPlanConditions(TestPlanTableRequest request) { + TestPlanQueryConditions conditions = new TestPlanQueryConditions(request.getModuleIds(), request.getProjectId(), request); + if (!request.conditionIsEmpty()) { + //查询符合匹配的子节点时不需要传入groupId + conditions.setGroupId(null); + List includeGroupIds = extTestPlanMapper.selectGroupIdByConditions(conditions); + conditions.setIncludeIds(includeGroupIds); + } + return conditions; + } + + private List getTableList(TestPlanQueryConditions request) { + List testPlanResponses = extTestPlanMapper.selectByConditions(request); testPlanResponses.forEach(item -> { item.setModuleName(testPlanModuleService.getNameById(item.getModuleId())); //todo 定时任务相关信息处理 diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanModuleService.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanModuleService.java index 78ebd9c3ac..fddff03bc0 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanModuleService.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanModuleService.java @@ -150,13 +150,13 @@ public class TestPlanModuleService extends ModuleTreeService implements CleanupP public void deleteModule(String deleteId, String operator, String requestUrl, String requestMethod) { TestPlanModule deleteModule = testPlanModuleMapper.selectByPrimaryKey(deleteId); if (deleteModule != null) { - this.deleteModule(Collections.singletonList(deleteId), operator, requestUrl, requestMethod); + this.deleteModule(Collections.singletonList(deleteId), deleteModule.getProjectId(), operator, requestUrl, requestMethod); //记录日志 testPlanModuleLogService.saveDeleteLog(deleteModule, operator, requestUrl, requestMethod); } } - public void deleteModule(List deleteIds, String operator, String requestUrl, String requestMethod) { + public void deleteModule(List deleteIds, String projectId, String operator, String requestUrl, String requestMethod) { if (CollectionUtils.isEmpty(deleteIds)) { return; } @@ -165,11 +165,12 @@ public class TestPlanModuleService extends ModuleTreeService implements CleanupP TestPlanBatchProcessRequest request = new TestPlanBatchProcessRequest(); request.setModuleIds(deleteIds); request.setSelectAll(true); + request.setProjectId(projectId); testPlanService.batchDelete(request, operator, requestUrl, requestMethod); List childrenIds = extTestPlanModuleMapper.selectChildrenIdsByParentIds(deleteIds); if (CollectionUtils.isNotEmpty(childrenIds)) { - deleteModule(childrenIds, operator, requestUrl, requestMethod); + deleteModule(childrenIds, projectId, operator, requestUrl, requestMethod); } } @@ -234,7 +235,7 @@ public class TestPlanModuleService extends ModuleTreeService implements CleanupP public void deleteResources(String projectId) { List fileModuleIdList = extTestPlanModuleMapper.selectIdsByProjectId(projectId); if (CollectionUtils.isNotEmpty(fileModuleIdList)) { - this.deleteModule(fileModuleIdList, "SCHEDULE", "none", "none"); + this.deleteModule(fileModuleIdList, projectId, "SCHEDULE", "none", "none"); } } 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 edfcb70a3a..33019992c6 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 @@ -1,16 +1,16 @@ package io.metersphere.plan.service; -import io.metersphere.plan.domain.TestPlan; -import io.metersphere.plan.domain.TestPlanConfig; -import io.metersphere.plan.domain.TestPlanConfigExample; -import io.metersphere.plan.domain.TestPlanExample; +import io.metersphere.plan.domain.*; import io.metersphere.plan.dto.TestPlanQueryConditions; import io.metersphere.plan.dto.request.TestPlanBatchProcessRequest; import io.metersphere.plan.dto.request.TestPlanCreateRequest; -import io.metersphere.plan.dto.response.TestPlanResponse; +import io.metersphere.plan.dto.request.TestPlanUpdateRequest; +import io.metersphere.plan.dto.response.TestPlanCountResponse; import io.metersphere.plan.mapper.ExtTestPlanMapper; import io.metersphere.plan.mapper.TestPlanConfigMapper; +import io.metersphere.plan.mapper.TestPlanFollowerMapper; import io.metersphere.plan.mapper.TestPlanMapper; +import io.metersphere.plan.utils.TestPlanXPackFactory; import io.metersphere.sdk.constants.ApplicationNumScope; import io.metersphere.sdk.constants.ModuleConstants; import io.metersphere.sdk.constants.TestPlanConstants; @@ -26,6 +26,7 @@ import io.metersphere.system.uid.NumGenerator; import io.metersphere.system.utils.BatchProcessUtils; import jakarta.annotation.Resource; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -50,10 +51,10 @@ public class TestPlanService { @Resource private TestPlanModuleMapper testPlanModuleMapper; @Resource - private TestPlanConfigService testPlanConfigService; - + private TestPlanFollowerMapper testPlanFollowerMapper; @Resource - private TestPlanFollowerService testPlanFollowerService; + private TestPlanXPackFactory testPlanXPackFactory; + @Resource private TestPlanApiCaseService testPlanApiCaseService; @Resource @@ -87,18 +88,20 @@ public class TestPlanService { createTestPlan.setCreateTime(operateTime); createTestPlan.setUpdateTime(operateTime); createTestPlan.setStatus(TestPlanConstants.TEST_PLAN_STATUS_PREPARED); - createTestPlan.setType(TestPlanConstants.TEST_PLAN_TYPE_PLAN); - testPlanMapper.insert(createTestPlan); TestPlanConfig testPlanConfig = new TestPlanConfig(); testPlanConfig.setTestPlanId(createTestPlan.getId()); testPlanConfig.setAutomaticStatusUpdate(testPlanCreateRequest.isAutomaticStatusUpdate()); testPlanConfig.setRepeatCase(testPlanCreateRequest.isRepeatCase()); testPlanConfig.setPassThreshold(testPlanCreateRequest.getPassThreshold()); + + if (testPlanCreateRequest.isGroupOption()) { + testPlanXPackFactory.getTestPlanGroupService().validateGroup(createTestPlan, testPlanConfig); + } + + testPlanMapper.insert(createTestPlan); testPlanConfigMapper.insert(testPlanConfig); - testPlanLogService.saveAddLog(createTestPlan, operator, requestUrl, requestMethod); - return createTestPlan.getId(); } @@ -107,26 +110,23 @@ public class TestPlanService { if (StringUtils.isBlank(testPlan.getId())) { TestPlanExample.Criteria criteria = example.createCriteria(); //测试计划第一层的数据还不能超过1000个 - criteria.andGroupIdEqualTo(TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID); - if (testPlanMapper.countByExample(example) >= MAX_TEST_PLAN_SIZE) { - throw new MSException(Translator.getWithArgs("test_plan.too_many", MAX_TEST_PLAN_SIZE)); + if (StringUtils.equals(testPlan.getGroupId(), TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) { + criteria.andGroupIdEqualTo(TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID); + if (testPlanMapper.countByExample(example) >= MAX_TEST_PLAN_SIZE) { + throw new MSException(Translator.getWithArgs("test_plan.too_many", MAX_TEST_PLAN_SIZE)); + } } example.clear(); example.createCriteria().andNameEqualTo(testPlan.getName()).andProjectIdEqualTo(testPlan.getProjectId()); if (testPlanMapper.countByExample(example) > 0) { throw new MSException(Translator.get("test_plan.name.exist") + ":" + testPlan.getName()); } - } - - /* - //todo 重名校验-写到测试计划修改的时候再增加 - else { + } else { example.createCriteria().andNameEqualTo(testPlan.getName()).andProjectIdEqualTo(testPlan.getProjectId()).andIdNotEqualTo(testPlan.getId()); if (testPlanMapper.countByExample(example) > 0) { throw new MSException(Translator.get("test_plan.name.exist") + ":" + testPlan.getName()); } } - */ } public void delete(String id, String operator, String requestUrl, String requestMethod) { @@ -212,23 +212,26 @@ public class TestPlanService { TestPlanConfigExample configExample = new TestPlanConfigExample(); configExample.createCriteria().andTestPlanIdIn(testPlanIds); testPlanConfigMapper.deleteByExample(configExample); + + TestPlanFollowerExample testPlanFollowerExample = new TestPlanFollowerExample(); + testPlanFollowerExample.createCriteria().andTestPlanIdIn(testPlanIds); + testPlanFollowerMapper.deleteByExample(testPlanFollowerExample); /* todo - 删除计划的关注者 - 删除计划报告 删除计划定时任务 */ } - public TestPlanResponse getCount(String id) { - TestPlanResponse response = new TestPlanResponse(); + public TestPlanCountResponse getCount(String id) { + TestPlanCountResponse response = new TestPlanCountResponse(); response.setId(id); /* todo 统计:测试进度、通过率、用例数、Bug数量(这些比较慢的查询,是否需要另开接口查询) Q:测试计划组需要查询这些数据吗? */ + response.setFunctionalCaseCount(0); response.setApiCaseCount(0); response.setApiScenarioCount(0); @@ -236,4 +239,51 @@ public class TestPlanService { response.setTestProgress("15.92%"); return response; } + + public String update(TestPlanUpdateRequest request, String userId, String requestUrl, String requestMethod) { + TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getId()); + if (testPlan == null) { + throw new MSException("test_plan.not.exist"); + } + if (!ObjectUtils.allNull(request.getName(), request.getModuleId(), request.getTags(), request.getPlannedEndTime(), request.getPlannedStartTime(), request.getDescription(), request.getTestPlanGroupId())) { + TestPlan updateTestPlan = new TestPlan(); + updateTestPlan.setId(request.getId()); + if (StringUtils.isNotBlank(request.getName())) { + updateTestPlan.setName(request.getName()); + updateTestPlan.setProjectId(testPlan.getProjectId()); + this.validateTestPlan(updateTestPlan); + } + if (StringUtils.isNotBlank(request.getModuleId())) { + //检查模块的合法性 + this.checkModule(request.getModuleId()); + updateTestPlan.setModuleId(request.getModuleId()); + } + if (CollectionUtils.isNotEmpty(request.getTags())) { + updateTestPlan.setTags(new ArrayList<>(request.getTags())); + } + updateTestPlan.setPlannedStartTime(request.getPlannedStartTime()); + updateTestPlan.setPlannedEndTime(request.getPlannedEndTime()); + updateTestPlan.setDescription(request.getDescription()); + updateTestPlan.setGroupId(request.getTestPlanGroupId()); + updateTestPlan.setType(testPlan.getType()); + + if (StringUtils.equals(testPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP) || StringUtils.isNotEmpty(request.getTestPlanGroupId())) { + //修改组、移动测试计划进组出组,需要特殊的处理方式 + testPlanXPackFactory.getTestPlanGroupService().validateGroup(testPlan, null); + } + testPlanMapper.updateByPrimaryKeySelective(updateTestPlan); + } + + if (!ObjectUtils.allNull(request.getAutomaticStatusUpdate(), request.getRepeatCase(), request.getPassThreshold())) { + TestPlanConfig testPlanConfig = new TestPlanConfig(); + testPlanConfig.setTestPlanId(request.getId()); + testPlanConfig.setAutomaticStatusUpdate(request.getAutomaticStatusUpdate()); + testPlanConfig.setRepeatCase(request.getRepeatCase()); + testPlanConfig.setPassThreshold(request.getPassThreshold()); + testPlanConfigMapper.updateByPrimaryKeySelective(testPlanConfig); + } + testPlanLogService.saveUpdateLog(testPlan, testPlanMapper.selectByPrimaryKey(request.getId()), testPlan.getProjectId(), userId, requestUrl, requestMethod); + return request.getId(); + } + } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/utils/TestPlanXPackFactory.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/utils/TestPlanXPackFactory.java new file mode 100644 index 0000000000..40251df147 --- /dev/null +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/utils/TestPlanXPackFactory.java @@ -0,0 +1,38 @@ +package io.metersphere.plan.utils; + +import io.metersphere.plan.service.TestPlanGroupService; +import io.metersphere.sdk.util.CommonBeanFactory; +import io.metersphere.system.dto.sdk.LicenseDTO; +import io.metersphere.system.service.LicenseService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +@Component +public class TestPlanXPackFactory { + + private TestPlanGroupService testPlanGroupService; + private LicenseService licenseService; + + public TestPlanGroupService getTestPlanGroupService() { + this.checkService(); + if (licenseValidate()) { + return testPlanGroupService; + } else { + return null; + } + } + + private void checkService() { + if (licenseService == null) { + licenseService = CommonBeanFactory.getBean(LicenseService.class); + } + if (testPlanGroupService == null) { + testPlanGroupService = CommonBeanFactory.getBean(TestPlanGroupService.class); + } + } + + private boolean licenseValidate() { + LicenseDTO licenseDTO = licenseService.validate(); + return (licenseDTO != null && StringUtils.equals(licenseDTO.getStatus(), "valid")); + } +} diff --git a/backend/services/test-plan/src/main/resources/testPlanGeneratorConfig.xml b/backend/services/test-plan/src/main/resources/testPlanGeneratorConfig.xml index 5634b02ebc..d97e354d7b 100644 --- a/backend/services/test-plan/src/main/resources/testPlanGeneratorConfig.xml +++ b/backend/services/test-plan/src/main/resources/testPlanGeneratorConfig.xml @@ -77,9 +77,10 @@ - -
-
+ + + +