From b4bf910a063d80939740551aa564c7bc550aae8a Mon Sep 17 00:00:00 2001 From: WangXu10 Date: Wed, 1 Nov 2023 16:17:53 +0800 Subject: [PATCH] =?UTF-8?q?refactor(=E5=8A=9F=E8=83=BD=E7=94=A8=E4=BE=8B):?= =?UTF-8?q?=20=E5=88=A0=E9=99=A4=E9=A1=B9=E7=9B=AE=E6=B8=85=E7=90=86?= =?UTF-8?q?=E7=94=A8=E4=BE=8B=E8=B5=84=E6=BA=90&=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E9=80=9A=E7=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../functional/domain/FunctionalCaseTest.java | 16 +-- .../domain/FunctionalCaseTestExample.java | 112 +++++++++--------- .../mapper/FunctionalCaseTestMapper.xml | 68 +++++------ .../3.0.0/ddl/V3.0.0_10__functional_case.sql | 8 +- .../main/resources/i18n/case_en_US.properties | 8 +- .../main/resources/i18n/case_zh_CN.properties | 8 +- .../main/resources/i18n/case_zh_TW.properties | 8 +- .../controller/FunctionalCaseController.java | 4 +- .../dto/FunctionalCaseVersionDTO.java | 2 + .../mapper/ExtFunctionalCaseMapper.java | 1 + .../mapper/ExtFunctionalCaseMapper.xml | 12 +- .../request/FunctionalCaseDeleteRequest.java | 4 + .../CleanupFunctionalCaseResourceService.java | 38 ++++++ .../service/DeleteFunctionalCaseService.java | 55 +++++++++ .../FunctionalCaseAttachmentService.java | 71 ++++++++++- .../service/FunctionalCaseLogService.java | 27 +++-- .../service/FunctionalCaseNoticeService.java | 51 ++++---- .../service/FunctionalCaseService.java | 83 +++---------- .../CleanupFunctionalCaseResourceTest.java | 30 +++++ .../FunctionalCaseControllerTests.java | 3 +- .../dml/init_clean_up_resource_test.sql | 15 +++ .../resources/dml/init_file_metadata_test.sql | 2 + .../CleanupApplicationResourceService.java | 7 ++ 23 files changed, 412 insertions(+), 221 deletions(-) create mode 100644 backend/services/case-management/src/main/java/io/metersphere/functional/service/CleanupFunctionalCaseResourceService.java create mode 100644 backend/services/case-management/src/main/java/io/metersphere/functional/service/DeleteFunctionalCaseService.java create mode 100644 backend/services/case-management/src/test/java/io/metersphere/functional/controller/CleanupFunctionalCaseResourceTest.java create mode 100644 backend/services/case-management/src/test/resources/dml/init_clean_up_resource_test.sql diff --git a/backend/framework/domain/src/main/java/io/metersphere/functional/domain/FunctionalCaseTest.java b/backend/framework/domain/src/main/java/io/metersphere/functional/domain/FunctionalCaseTest.java index 0897191d85..541f41f851 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/functional/domain/FunctionalCaseTest.java +++ b/backend/framework/domain/src/main/java/io/metersphere/functional/domain/FunctionalCaseTest.java @@ -23,14 +23,14 @@ public class FunctionalCaseTest implements Serializable { private String caseId; @Schema(description = "其他类型用例ID", requiredMode = Schema.RequiredMode.REQUIRED) - @NotBlank(message = "{functional_case_test.test_id.not_blank}", groups = {Created.class}) - @Size(min = 1, max = 50, message = "{functional_case_test.test_id.length_range}", groups = {Created.class, Updated.class}) - private String testId; + @NotBlank(message = "{functional_case_test.source_id.not_blank}", groups = {Created.class}) + @Size(min = 1, max = 50, message = "{functional_case_test.source_id.length_range}", groups = {Created.class, Updated.class}) + private String sourceId; @Schema(description = "用例类型:接口用例/场景用例/性能用例/UI用例", requiredMode = Schema.RequiredMode.REQUIRED) - @NotBlank(message = "{functional_case_test.test_type.not_blank}", groups = {Created.class}) - @Size(min = 1, max = 64, message = "{functional_case_test.test_type.length_range}", groups = {Created.class, Updated.class}) - private String testType; + @NotBlank(message = "{functional_case_test.source_type.not_blank}", groups = {Created.class}) + @Size(min = 1, max = 64, message = "{functional_case_test.source_type.length_range}", groups = {Created.class, Updated.class}) + private String sourceType; @Schema(description = "创建时间") private Long createTime; @@ -43,8 +43,8 @@ public class FunctionalCaseTest implements Serializable { public enum Column { id("id", "id", "VARCHAR", false), caseId("case_id", "caseId", "VARCHAR", false), - testId("test_id", "testId", "VARCHAR", false), - testType("test_type", "testType", "VARCHAR", false), + sourceId("source_id", "sourceId", "VARCHAR", false), + sourceType("source_type", "sourceType", "VARCHAR", false), createTime("create_time", "createTime", "BIGINT", false), updateTime("update_time", "updateTime", "BIGINT", false); diff --git a/backend/framework/domain/src/main/java/io/metersphere/functional/domain/FunctionalCaseTestExample.java b/backend/framework/domain/src/main/java/io/metersphere/functional/domain/FunctionalCaseTestExample.java index eca291a2bb..a6facaf1a5 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/functional/domain/FunctionalCaseTestExample.java +++ b/backend/framework/domain/src/main/java/io/metersphere/functional/domain/FunctionalCaseTestExample.java @@ -244,143 +244,143 @@ public class FunctionalCaseTestExample { return (Criteria) this; } - public Criteria andTestIdIsNull() { - addCriterion("test_id is null"); + public Criteria andSourceIdIsNull() { + addCriterion("source_id is null"); return (Criteria) this; } - public Criteria andTestIdIsNotNull() { - addCriterion("test_id is not null"); + public Criteria andSourceIdIsNotNull() { + addCriterion("source_id is not null"); return (Criteria) this; } - public Criteria andTestIdEqualTo(String value) { - addCriterion("test_id =", value, "testId"); + public Criteria andSourceIdEqualTo(String value) { + addCriterion("source_id =", value, "sourceId"); return (Criteria) this; } - public Criteria andTestIdNotEqualTo(String value) { - addCriterion("test_id <>", value, "testId"); + public Criteria andSourceIdNotEqualTo(String value) { + addCriterion("source_id <>", value, "sourceId"); return (Criteria) this; } - public Criteria andTestIdGreaterThan(String value) { - addCriterion("test_id >", value, "testId"); + public Criteria andSourceIdGreaterThan(String value) { + addCriterion("source_id >", value, "sourceId"); return (Criteria) this; } - public Criteria andTestIdGreaterThanOrEqualTo(String value) { - addCriterion("test_id >=", value, "testId"); + public Criteria andSourceIdGreaterThanOrEqualTo(String value) { + addCriterion("source_id >=", value, "sourceId"); return (Criteria) this; } - public Criteria andTestIdLessThan(String value) { - addCriterion("test_id <", value, "testId"); + public Criteria andSourceIdLessThan(String value) { + addCriterion("source_id <", value, "sourceId"); return (Criteria) this; } - public Criteria andTestIdLessThanOrEqualTo(String value) { - addCriterion("test_id <=", value, "testId"); + public Criteria andSourceIdLessThanOrEqualTo(String value) { + addCriterion("source_id <=", value, "sourceId"); return (Criteria) this; } - public Criteria andTestIdLike(String value) { - addCriterion("test_id like", value, "testId"); + public Criteria andSourceIdLike(String value) { + addCriterion("source_id like", value, "sourceId"); return (Criteria) this; } - public Criteria andTestIdNotLike(String value) { - addCriterion("test_id not like", value, "testId"); + public Criteria andSourceIdNotLike(String value) { + addCriterion("source_id not like", value, "sourceId"); return (Criteria) this; } - public Criteria andTestIdIn(List values) { - addCriterion("test_id in", values, "testId"); + public Criteria andSourceIdIn(List values) { + addCriterion("source_id in", values, "sourceId"); return (Criteria) this; } - public Criteria andTestIdNotIn(List values) { - addCriterion("test_id not in", values, "testId"); + public Criteria andSourceIdNotIn(List values) { + addCriterion("source_id not in", values, "sourceId"); return (Criteria) this; } - public Criteria andTestIdBetween(String value1, String value2) { - addCriterion("test_id between", value1, value2, "testId"); + public Criteria andSourceIdBetween(String value1, String value2) { + addCriterion("source_id between", value1, value2, "sourceId"); return (Criteria) this; } - public Criteria andTestIdNotBetween(String value1, String value2) { - addCriterion("test_id not between", value1, value2, "testId"); + public Criteria andSourceIdNotBetween(String value1, String value2) { + addCriterion("source_id not between", value1, value2, "sourceId"); return (Criteria) this; } - public Criteria andTestTypeIsNull() { - addCriterion("test_type is null"); + public Criteria andSourceTypeIsNull() { + addCriterion("source_type is null"); return (Criteria) this; } - public Criteria andTestTypeIsNotNull() { - addCriterion("test_type is not null"); + public Criteria andSourceTypeIsNotNull() { + addCriterion("source_type is not null"); return (Criteria) this; } - public Criteria andTestTypeEqualTo(String value) { - addCriterion("test_type =", value, "testType"); + public Criteria andSourceTypeEqualTo(String value) { + addCriterion("source_type =", value, "sourceType"); return (Criteria) this; } - public Criteria andTestTypeNotEqualTo(String value) { - addCriterion("test_type <>", value, "testType"); + public Criteria andSourceTypeNotEqualTo(String value) { + addCriterion("source_type <>", value, "sourceType"); return (Criteria) this; } - public Criteria andTestTypeGreaterThan(String value) { - addCriterion("test_type >", value, "testType"); + public Criteria andSourceTypeGreaterThan(String value) { + addCriterion("source_type >", value, "sourceType"); return (Criteria) this; } - public Criteria andTestTypeGreaterThanOrEqualTo(String value) { - addCriterion("test_type >=", value, "testType"); + public Criteria andSourceTypeGreaterThanOrEqualTo(String value) { + addCriterion("source_type >=", value, "sourceType"); return (Criteria) this; } - public Criteria andTestTypeLessThan(String value) { - addCriterion("test_type <", value, "testType"); + public Criteria andSourceTypeLessThan(String value) { + addCriterion("source_type <", value, "sourceType"); return (Criteria) this; } - public Criteria andTestTypeLessThanOrEqualTo(String value) { - addCriterion("test_type <=", value, "testType"); + public Criteria andSourceTypeLessThanOrEqualTo(String value) { + addCriterion("source_type <=", value, "sourceType"); return (Criteria) this; } - public Criteria andTestTypeLike(String value) { - addCriterion("test_type like", value, "testType"); + public Criteria andSourceTypeLike(String value) { + addCriterion("source_type like", value, "sourceType"); return (Criteria) this; } - public Criteria andTestTypeNotLike(String value) { - addCriterion("test_type not like", value, "testType"); + public Criteria andSourceTypeNotLike(String value) { + addCriterion("source_type not like", value, "sourceType"); return (Criteria) this; } - public Criteria andTestTypeIn(List values) { - addCriterion("test_type in", values, "testType"); + public Criteria andSourceTypeIn(List values) { + addCriterion("source_type in", values, "sourceType"); return (Criteria) this; } - public Criteria andTestTypeNotIn(List values) { - addCriterion("test_type not in", values, "testType"); + public Criteria andSourceTypeNotIn(List values) { + addCriterion("source_type not in", values, "sourceType"); return (Criteria) this; } - public Criteria andTestTypeBetween(String value1, String value2) { - addCriterion("test_type between", value1, value2, "testType"); + public Criteria andSourceTypeBetween(String value1, String value2) { + addCriterion("source_type between", value1, value2, "sourceType"); return (Criteria) this; } - public Criteria andTestTypeNotBetween(String value1, String value2) { - addCriterion("test_type not between", value1, value2, "testType"); + public Criteria andSourceTypeNotBetween(String value1, String value2) { + addCriterion("source_type not between", value1, value2, "sourceType"); return (Criteria) this; } diff --git a/backend/framework/domain/src/main/java/io/metersphere/functional/mapper/FunctionalCaseTestMapper.xml b/backend/framework/domain/src/main/java/io/metersphere/functional/mapper/FunctionalCaseTestMapper.xml index 970274ca83..83169d062e 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/functional/mapper/FunctionalCaseTestMapper.xml +++ b/backend/framework/domain/src/main/java/io/metersphere/functional/mapper/FunctionalCaseTestMapper.xml @@ -4,8 +4,8 @@ - - + + @@ -68,7 +68,7 @@ - id, case_id, test_id, test_type, create_time, update_time + id, case_id, source_id, source_type, create_time, update_time + + \ No newline at end of file diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/request/FunctionalCaseDeleteRequest.java b/backend/services/case-management/src/main/java/io/metersphere/functional/request/FunctionalCaseDeleteRequest.java index 9881d97cfe..9971c2a6ce 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/request/FunctionalCaseDeleteRequest.java +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/request/FunctionalCaseDeleteRequest.java @@ -22,4 +22,8 @@ public class FunctionalCaseDeleteRequest implements Serializable { @Schema(description = "删除列表版本/删除全部版本") private Boolean deleteAll; + @Schema(description = "项目id") + @NotBlank(message = "{functional_case.project_id.not_blank}") + private String projectId; + } diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/service/CleanupFunctionalCaseResourceService.java b/backend/services/case-management/src/main/java/io/metersphere/functional/service/CleanupFunctionalCaseResourceService.java new file mode 100644 index 0000000000..7aa5732eba --- /dev/null +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/service/CleanupFunctionalCaseResourceService.java @@ -0,0 +1,38 @@ +package io.metersphere.functional.service; + +import io.metersphere.functional.mapper.ExtFunctionalCaseMapper; +import io.metersphere.sdk.util.LogUtils; +import io.metersphere.system.service.CleanupProjectResourceService; +import jakarta.annotation.Resource; +import org.apache.commons.collections.CollectionUtils; +import org.springframework.stereotype.Component; + +import java.util.List; + + +/** + * @author wx + */ +@Component +public class CleanupFunctionalCaseResourceService implements CleanupProjectResourceService { + + @Resource + private ExtFunctionalCaseMapper extFunctionalCaseMapper; + + @Resource + private DeleteFunctionalCaseService deleteFunctionalCaseService; + + + @Override + public void deleteResources(String projectId) { + List ids = extFunctionalCaseMapper.getFunctionalCaseIds(projectId); + if (CollectionUtils.isNotEmpty(ids)) { + deleteFunctionalCaseService.deleteFunctionalCaseResource(ids, projectId); + } + } + + @Override + public void cleanReportResources(String projectId) { + LogUtils.info("清理当前项目[" + projectId + "]相关报告资源"); + } +} diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/service/DeleteFunctionalCaseService.java b/backend/services/case-management/src/main/java/io/metersphere/functional/service/DeleteFunctionalCaseService.java new file mode 100644 index 0000000000..3e753deb81 --- /dev/null +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/service/DeleteFunctionalCaseService.java @@ -0,0 +1,55 @@ +package io.metersphere.functional.service; + +import io.metersphere.functional.domain.*; +import io.metersphere.functional.mapper.FunctionalCaseBlobMapper; +import io.metersphere.functional.mapper.FunctionalCaseCustomFieldMapper; +import io.metersphere.functional.mapper.FunctionalCaseMapper; +import io.metersphere.functional.mapper.FunctionalCaseTestMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * @author wx + */ +@Service +@Transactional(rollbackFor = Exception.class) +public class DeleteFunctionalCaseService { + + @Resource + private FunctionalCaseTestMapper functionalCaseTestMapper; + @Resource + private FunctionalCaseAttachmentService functionalCaseAttachmentService; + @Resource + private FunctionalCaseCustomFieldMapper functionalCaseCustomFieldMapper; + @Resource + private FunctionalCaseBlobMapper functionalCaseBlobMapper; + @Resource + private FunctionalCaseMapper functionalCaseMapper; + + + public void deleteFunctionalCaseResource(List ids, String projectId) { + //TODO 删除各种关联关系? 1.测试用例(接口/场景/ui/性能)? 2.关联缺陷(是否需要同步?) 3.关联需求(是否需要同步?) 4.依赖关系? 5.关联评审? 6.操作记录? 7.关联测试计划? 8.评论? 9.附件? 10.自定义字段? 11.用例基本信息(主表、附属表)?12.模块? 13...? + //1.刪除用例与其他用例关联关系 + FunctionalCaseTestExample caseTestExample = new FunctionalCaseTestExample(); + caseTestExample.createCriteria().andCaseIdIn(ids); + functionalCaseTestMapper.deleteByExample(caseTestExample); + //9.附件 + functionalCaseAttachmentService.deleteAttachmentResource(ids, projectId); + //10.自定义字段 + FunctionalCaseCustomFieldExample fieldExample = new FunctionalCaseCustomFieldExample(); + fieldExample.createCriteria().andCaseIdIn(ids); + functionalCaseCustomFieldMapper.deleteByExample(fieldExample); + //11.用例基本信息 + FunctionalCaseBlobExample blobExample = new FunctionalCaseBlobExample(); + blobExample.createCriteria().andIdIn(ids); + functionalCaseBlobMapper.deleteByExample(blobExample); + FunctionalCaseExample caseExample = new FunctionalCaseExample(); + caseExample.createCriteria().andIdIn(ids).andProjectIdEqualTo(projectId); + functionalCaseMapper.deleteByExample(caseExample); + + + } +} diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseAttachmentService.java b/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseAttachmentService.java index 07ca259772..d642970e34 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseAttachmentService.java +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseAttachmentService.java @@ -7,9 +7,15 @@ import io.metersphere.functional.domain.FunctionalCaseAttachmentExample; import io.metersphere.functional.dto.FunctionalCaseAttachmentDTO; import io.metersphere.functional.dto.FunctionalCaseDetailDTO; import io.metersphere.functional.mapper.FunctionalCaseAttachmentMapper; +import io.metersphere.functional.request.FunctionalCaseAddRequest; import io.metersphere.project.domain.FileMetadata; import io.metersphere.project.mapper.FileMetadataMapper; +import io.metersphere.sdk.constants.StorageType; +import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.util.BeanUtils; +import io.metersphere.sdk.util.MsFileUtils; +import io.metersphere.system.file.FileRequest; +import io.metersphere.system.file.MinioRepository; import io.metersphere.system.uid.IDGenerator; import jakarta.annotation.Resource; import org.apache.commons.collections.CollectionUtils; @@ -40,6 +46,9 @@ public class FunctionalCaseAttachmentService { @Resource private FileMetadataMapper fileMetadataMapper; + @Resource + private MinioRepository minioRepository; + /** * 保存本地上传文件和用例关联关系 * @@ -55,6 +64,31 @@ public class FunctionalCaseAttachmentService { } + /** + * 功能用例上传附件 + * + * @param request + * @param files + */ + public void uploadFile(FunctionalCaseAddRequest request, String caseId, List files, Boolean isLocal, String userId) { + if (CollectionUtils.isNotEmpty(files)) { + files.forEach(file -> { + String fileId = IDGenerator.nextStr(); + FileRequest fileRequest = new FileRequest(); + fileRequest.setFileName(file.getName()); + fileRequest.setResourceId(MsFileUtils.FUNCTIONAL_CASE_DIR_NAME + "/" + request.getProjectId() + fileId); + fileRequest.setStorage(StorageType.MINIO.name()); + try { + minioRepository.saveFile(file, fileRequest); + } catch (Exception e) { + throw new MSException("save file error"); + } + saveCaseAttachment(fileId, file, caseId, isLocal, userId); + }); + } + } + + /** * 保存文件库文件与用例关联关系 * @@ -121,13 +155,46 @@ public class FunctionalCaseAttachmentService { * * @param deleteFileMetaIds */ - public List deleteCaseAttachment(List deleteFileMetaIds, String caseId) { + public void deleteCaseAttachment(List deleteFileMetaIds, String caseId, String projectId) { FunctionalCaseAttachmentExample example = new FunctionalCaseAttachmentExample(); example.createCriteria().andFileIdIn(deleteFileMetaIds).andCaseIdEqualTo(caseId).andLocalEqualTo(true); List delAttachment = functionalCaseAttachmentMapper.selectByExample(example); example.clear(); example.createCriteria().andFileIdIn(deleteFileMetaIds).andCaseIdEqualTo(caseId); functionalCaseAttachmentMapper.deleteByExample(example); - return delAttachment; + this.deleteMinioFile(delAttachment, projectId); + } + + + private void deleteMinioFile(List files, String projectId) { + if (CollectionUtils.isNotEmpty(files)) { + files.forEach(file -> { + FileRequest fileRequest = new FileRequest(); + fileRequest.setFileName(file.getFileName()); + fileRequest.setResourceId(MsFileUtils.FUNCTIONAL_CASE_DIR_NAME + "/" + projectId + file.getFileId()); + fileRequest.setStorage(StorageType.MINIO.name()); + try { + minioRepository.delete(fileRequest); + } catch (Exception e) { + throw new MSException("delete file error"); + } + }); + } + } + + + /** + * 清理附件资源 + * + * @param ids + */ + public void deleteAttachmentResource(List ids, String projectId) { + FunctionalCaseAttachmentExample example = new FunctionalCaseAttachmentExample(); + example.createCriteria().andCaseIdIn(ids).andLocalEqualTo(true); + List localAttachment = functionalCaseAttachmentMapper.selectByExample(example); + example.clear(); + example.createCriteria().andCaseIdIn(ids); + functionalCaseAttachmentMapper.deleteByExample(example); + deleteMinioFile(localAttachment, projectId); } } \ No newline at end of file diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseLogService.java b/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseLogService.java index d8723db098..0660026b79 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseLogService.java +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseLogService.java @@ -87,18 +87,21 @@ public class FunctionalCaseLogService { */ public LogDTO deleteFunctionalCaseLog(FunctionalCaseDeleteRequest request) { FunctionalCase functionalCase = functionalCaseMapper.selectByPrimaryKey(request.getId()); - LogDTO dto = new LogDTO( - functionalCase.getProjectId(), - null, - functionalCase.getId(), - null, - OperationLogType.DELETE.name(), - OperationLogModule.FUNCTIONAL_CASE, - functionalCase.getName()); + if (functionalCase != null) { + LogDTO dto = new LogDTO( + functionalCase.getProjectId(), + null, + functionalCase.getId(), + null, + OperationLogType.DELETE.name(), + OperationLogModule.FUNCTIONAL_CASE, + functionalCase.getName()); - dto.setPath("/functional/case/delete"); - dto.setMethod(HttpMethodConstants.POST.name()); - dto.setOriginalValue(JSON.toJSONBytes(functionalCase)); - return dto; + dto.setPath("/functional/case/delete"); + dto.setMethod(HttpMethodConstants.POST.name()); + dto.setOriginalValue(JSON.toJSONBytes(functionalCase)); + return dto; + } + return null; } } diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseNoticeService.java b/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseNoticeService.java index c689fe27c7..d23c4c9fca 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseNoticeService.java +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseNoticeService.java @@ -7,7 +7,6 @@ import io.metersphere.functional.dto.CaseCustomsFieldDTO; import io.metersphere.functional.dto.FunctionalCaseDTO; import io.metersphere.functional.mapper.FunctionalCaseCustomFieldMapper; import io.metersphere.functional.mapper.FunctionalCaseMapper; -import io.metersphere.functional.request.FunctionalCaseAddRequest; import io.metersphere.functional.request.FunctionalCaseCommentRequest; import io.metersphere.sdk.util.BeanUtils; import io.metersphere.system.domain.CustomField; @@ -21,10 +20,7 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; @Service @@ -39,10 +35,10 @@ public class FunctionalCaseNoticeService { @Resource private CustomFieldMapper customFieldMapper; - public FunctionalCaseDTO getFunctionalCaseDTO(FunctionalCaseCommentRequest functionalCaseCommentRequest){ + public FunctionalCaseDTO getFunctionalCaseDTO(FunctionalCaseCommentRequest functionalCaseCommentRequest) { FunctionalCase functionalCase = functionalCaseMapper.selectByPrimaryKey(functionalCaseCommentRequest.getCaseId()); FunctionalCaseDTO functionalCaseDTO = new FunctionalCaseDTO(); - BeanUtils.copyBean(functionalCaseDTO,functionalCase); + BeanUtils.copyBean(functionalCaseDTO, functionalCase); setNotifier(functionalCaseCommentRequest, functionalCaseDTO); List customFields = getCustomFields(functionalCaseCommentRequest.getCaseId()); functionalCaseDTO.setFields(customFields); @@ -50,11 +46,11 @@ public class FunctionalCaseNoticeService { } /** - * * 如果是REPLAY事件,需要判断有无@的人,如果有@的人且当前被回复的人不是同一人,这里只要被回复的人,如果是同一人,这里通知人为空,走AT事件 * 如果不是REPLAY事件,需要判断有无被回复的人,如果被回复的人不在被@人里,则用页面参数传递的通知人,如果在,则排除这个人,如果没有被回复的人,用页面数据 + * * @param functionalCaseCommentRequest 页面参数 - * @param functionalCaseDTO 发通知需要解析字段集合 + * @param functionalCaseDTO 发通知需要解析字段集合 */ private void setNotifier(FunctionalCaseCommentRequest functionalCaseCommentRequest, FunctionalCaseDTO functionalCaseDTO) { String notifier = functionalCaseCommentRequest.getNotifier(); @@ -70,7 +66,7 @@ public class FunctionalCaseNoticeService { } } else { if (StringUtils.isNotBlank(replyUser)) { - StringBuilder notifierStr = new StringBuilder(); + StringBuilder notifierStr = new StringBuilder(); if (StringUtils.isNotBlank(notifier)) { List notifierList = Arrays.asList(notifier.split(";")); if (notifierList.contains(replyUser)) { @@ -79,8 +75,7 @@ public class FunctionalCaseNoticeService { notifierStr.append(notifierId).append(";"); } } - } - else { + } else { notifierStr = new StringBuilder(notifier); } functionalCaseDTO.setRelatedUsers(notifierStr.toString()); @@ -94,21 +89,21 @@ public class FunctionalCaseNoticeService { /** * 根据用例id获取当前用例在使用的自定义的字段及其值 * - * @param caseId 用例Id + * @param caseId 用例Id * @return 返回 字段以及字段值的组合 */ private List getCustomFields(String caseId) { FunctionalCaseCustomFieldExample functionalCaseCustomFieldExample = new FunctionalCaseCustomFieldExample(); functionalCaseCustomFieldExample.createCriteria().andCaseIdEqualTo(caseId); List functionalCaseCustomFields = functionalCaseCustomFieldMapper.selectByExample(functionalCaseCustomFieldExample); - ListoptionDTOList = new ArrayList<>(); + List optionDTOList = new ArrayList<>(); if (CollectionUtils.isNotEmpty(functionalCaseCustomFields)) { Map fieldValueMap = functionalCaseCustomFields.stream().collect(Collectors.toMap(FunctionalCaseCustomField::getFieldId, FunctionalCaseCustomField::getValue)); List fieldIds = functionalCaseCustomFields.stream().map(FunctionalCaseCustomField::getFieldId).distinct().toList(); CustomFieldExample customFieldExample = new CustomFieldExample(); customFieldExample.createCriteria().andIdIn(fieldIds); List customFields = customFieldMapper.selectByExample(customFieldExample); - customFields.forEach(t->{ + customFields.forEach(t -> { OptionDTO optionDTO = new OptionDTO(); optionDTO.setId(t.getName()); optionDTO.setName(fieldValueMap.get(t.getId())); @@ -118,15 +113,15 @@ public class FunctionalCaseNoticeService { return optionDTOList; } - public FunctionalCaseDTO getMainFunctionalCaseDTO(FunctionalCaseAddRequest request) { + public FunctionalCaseDTO getMainFunctionalCaseDTO(String name, String caseEditType, List customsFields) { String userId = SessionUtils.getUserId(); FunctionalCaseDTO functionalCaseDTO = new FunctionalCaseDTO(); - functionalCaseDTO.setName(request.getName()); - functionalCaseDTO.setCaseEditType(request.getCaseEditType()); + functionalCaseDTO.setName(name); + functionalCaseDTO.setCaseEditType(caseEditType); functionalCaseDTO.setCreateUser(userId); - Listfields = new ArrayList<>(); - if (CollectionUtils.isNotEmpty(request.getCustomsFields())){ - for (CaseCustomsFieldDTO customsFieldDTO : request.getCustomsFields()) { + List fields = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(customsFields)) { + for (CaseCustomsFieldDTO customsFieldDTO : customsFields) { OptionDTO optionDTO = new OptionDTO(); CustomField customField = customFieldMapper.selectByPrimaryKey(customsFieldDTO.getFieldId()); if (customField == null) { @@ -142,5 +137,19 @@ public class FunctionalCaseNoticeService { } + public FunctionalCaseDTO getDeleteFunctionalCaseDTO(String id){ + String userId = SessionUtils.getUserId(); + FunctionalCase functionalCase = functionalCaseMapper.selectByPrimaryKey(id); + FunctionalCaseDTO functionalCaseDTO = new FunctionalCaseDTO(); + Optional.ofNullable(functionalCase).ifPresent(functional -> { + functionalCaseDTO.setName(functionalCase.getName()); + functionalCaseDTO.setCaseEditType(functionalCase.getCaseEditType()); + functionalCaseDTO.setCreateUser(userId); + List customFields = getCustomFields(id); + functionalCaseDTO.setFields(customFields); + + }); + return functionalCaseDTO; + } } diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseService.java b/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseService.java index 1929c0b759..c2aaf5430d 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseService.java +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseService.java @@ -13,14 +13,14 @@ import io.metersphere.functional.request.FunctionalCaseDeleteRequest; import io.metersphere.functional.request.FunctionalCaseEditRequest; import io.metersphere.functional.result.FunctionalCaseResultCode; import io.metersphere.project.service.ProjectTemplateService; -import io.metersphere.sdk.constants.*; +import io.metersphere.sdk.constants.ApplicationNumScope; +import io.metersphere.sdk.constants.FunctionalCaseExecuteResult; +import io.metersphere.sdk.constants.FunctionalCaseReviewStatus; +import io.metersphere.sdk.constants.TemplateScene; import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.util.BeanUtils; -import io.metersphere.sdk.util.MsFileUtils; import io.metersphere.system.dto.sdk.TemplateCustomFieldDTO; import io.metersphere.system.dto.sdk.TemplateDTO; -import io.metersphere.system.file.FileRequest; -import io.metersphere.system.file.MinioRepository; import io.metersphere.system.uid.IDGenerator; import io.metersphere.system.uid.NumGenerator; import jakarta.annotation.Resource; @@ -32,6 +32,7 @@ import org.springframework.web.multipart.MultipartFile; import java.math.BigDecimal; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -45,9 +46,6 @@ public class FunctionalCaseService { public static final int ORDER_STEP = 5000; - @Resource - private MinioRepository minioRepository; - @Resource private ExtFunctionalCaseMapper extFunctionalCaseMapper; @@ -70,7 +68,7 @@ public class FunctionalCaseService { private FunctionalCaseFollowerMapper functionalCaseFollowerMapper; @Resource - private FunctionalCaseCommentService functionalCaseCommentService; + private DeleteFunctionalCaseService deleteFunctionalCaseService; public FunctionalCase addFunctionalCase(FunctionalCaseAddRequest request, List files, String userId) { String caseId = IDGenerator.nextStr(); @@ -78,7 +76,7 @@ public class FunctionalCaseService { FunctionalCase functionalCase = addCase(caseId, request, userId); //上传文件 - uploadFile(request, caseId, files, true, userId); + functionalCaseAttachmentService.uploadFile(request, caseId, files, true, userId); //关联附件 functionalCaseAttachmentService.relateFileMeta(request.getRelateFileMetaIds(), caseId, userId); @@ -133,30 +131,6 @@ public class FunctionalCaseService { return bigDecimal.intValue(); } - /** - * 功能用例上传附件 - * - * @param request - * @param files - */ - public void uploadFile(FunctionalCaseAddRequest request, String caseId, List files, Boolean isLocal, String userId) { - if (CollectionUtils.isNotEmpty(files)) { - files.forEach(file -> { - String fileId = IDGenerator.nextStr(); - FileRequest fileRequest = new FileRequest(); - fileRequest.setFileName(file.getName()); - fileRequest.setResourceId(MsFileUtils.FUNCTIONAL_CASE_DIR_NAME + "/" + request.getProjectId() + fileId); - fileRequest.setStorage(StorageType.MINIO.name()); - try { - minioRepository.saveFile(file, fileRequest); - } catch (Exception e) { - throw new MSException("save file error"); - } - functionalCaseAttachmentService.saveCaseAttachment(fileId, file, caseId, isLocal, userId); - }); - } - } - /** * 查看用例获取详情 @@ -243,11 +217,11 @@ public class FunctionalCaseService { //处理删除文件id if (CollectionUtils.isNotEmpty(request.getDeleteFileMetaIds())) { - this.deleteFile(request.getDeleteFileMetaIds(), request); + functionalCaseAttachmentService.deleteCaseAttachment(request.getDeleteFileMetaIds(), request.getId(), request.getProjectId()); } //上传新文件 - uploadFile(request, request.getId(), files, true, userId); + functionalCaseAttachmentService.uploadFile(request, request.getId(), files, true, userId); //关联新附件 functionalCaseAttachmentService.relateFileMeta(request.getRelateFileMetaIds(), request.getId(), userId); @@ -269,27 +243,6 @@ public class FunctionalCaseService { extFunctionalCaseMapper.updateFunctionalCaseModule(refId, moduleId); } - private void deleteFile(List deleteFileMetaIds, FunctionalCaseEditRequest request) { - List caseAttachments = functionalCaseAttachmentService.deleteCaseAttachment(deleteFileMetaIds, request.getId()); - if (CollectionUtils.isNotEmpty(caseAttachments)) { - //删除本地上传的minio文件 - deleteMinioFile(caseAttachments, request.getProjectId()); - } - } - - private void deleteMinioFile(List files, String projectId) { - files.forEach(file -> { - FileRequest fileRequest = new FileRequest(); - fileRequest.setFileName(file.getFileName()); - fileRequest.setResourceId(MsFileUtils.FUNCTIONAL_CASE_DIR_NAME + "/" + projectId + file.getFileId()); - fileRequest.setStorage(StorageType.MINIO.name()); - try { - minioRepository.delete(fileRequest); - } catch (Exception e) { - throw new MSException("delete file error"); - } - }); - } private void updateCase(FunctionalCaseEditRequest request, String userId, FunctionalCase functionalCase) { functionalCase.setUpdateUser(userId); @@ -357,7 +310,8 @@ public class FunctionalCaseService { if (versionDTOList.size() > 1) { //存在多个版本 List ids = versionDTOList.stream().map(FunctionalCaseVersionDTO::getId).collect(Collectors.toList()); - handleFunctionalCaseByVersions(request, ids, userId); + String projectId = versionDTOList.get(0).getProjectId(); + handleFunctionalCaseByVersions(request, projectId, ids, userId); } else { //只有一个版本 直接放入回收站 doDelete(request.getId(), userId); @@ -373,27 +327,18 @@ public class FunctionalCaseService { * @param ids * @param userId */ - private void handleFunctionalCaseByVersions(FunctionalCaseDeleteRequest request, List ids, String userId) { + private void handleFunctionalCaseByVersions(FunctionalCaseDeleteRequest request, String projectId, List ids, String userId) { if (request.getDeleteAll()) { //删除所有版本 ids.forEach(id -> { doDelete(id, userId); }); } else { - //删除指定版本 - deleteFunctionalCaseSingle(request.getId()); + //删除指定版本(用例多版本情况下 删除单个版本用例) + deleteFunctionalCaseService.deleteFunctionalCaseResource(Arrays.asList(request.getId()), projectId); } } - /** - * 用例多版本情况下 删除单个版本用例 - * - * @param functionalCaseId - */ - private void deleteFunctionalCaseSingle(String functionalCaseId) { - //TODO 删除各种关联关系? 1.测试用例(接口/场景/ui/性能)? 2.关联缺陷(是否需要同步?) 3.关联需求(是否需要同步?) 4.依赖关系? 5.关联评审? 6.操作记录? 7.关联测试计划? 8.评论? 9.附件? 10.自定义字段? 11.用例基本信息(主表、附属表)? - } - private void doDelete(String id, String userId) { FunctionalCase functionalCase = new FunctionalCase(); diff --git a/backend/services/case-management/src/test/java/io/metersphere/functional/controller/CleanupFunctionalCaseResourceTest.java b/backend/services/case-management/src/test/java/io/metersphere/functional/controller/CleanupFunctionalCaseResourceTest.java new file mode 100644 index 0000000000..771f1b5c40 --- /dev/null +++ b/backend/services/case-management/src/test/java/io/metersphere/functional/controller/CleanupFunctionalCaseResourceTest.java @@ -0,0 +1,30 @@ +package io.metersphere.functional.controller; + +import io.metersphere.functional.service.CleanupFunctionalCaseResourceService; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.test.context.jdbc.SqlConfig; + +@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT) +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +@AutoConfigureMockMvc +public class CleanupFunctionalCaseResourceTest { + + @Resource + private CleanupFunctionalCaseResourceService cleanupFunctionalCaseResourceService; + + @Test + @Order(1) + @Sql(scripts = {"/dml/init_clean_up_resource_test.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED)) + public void testCleanupResource() throws Exception { + cleanupFunctionalCaseResourceService.deleteResources("test_project_id"); + cleanupFunctionalCaseResourceService.deleteResources("TEST_CLEAN_UP_PROJECT_ID"); + } + +} diff --git a/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalCaseControllerTests.java b/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalCaseControllerTests.java index 624fcb6d01..f6fb1b45de 100644 --- a/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalCaseControllerTests.java +++ b/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalCaseControllerTests.java @@ -259,6 +259,7 @@ public class FunctionalCaseControllerTests extends BaseTest { FunctionalCaseDeleteRequest request = new FunctionalCaseDeleteRequest(); request.setId("TEST_FUNCTIONAL_CASE_ID"); request.setDeleteAll(false); + request.setProjectId(DEFAULT_PROJECT_ID); MvcResult mvcResult = this.requestPostWithOkAndReturn(FUNCTIONAL_CASE_DELETE_URL, request); String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8); ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class); @@ -267,7 +268,7 @@ public class FunctionalCaseControllerTests extends BaseTest { request.setId("TEST_FUNCTIONAL_CASE_ID_1"); request.setDeleteAll(false); this.requestPostWithOkAndReturn(FUNCTIONAL_CASE_DELETE_URL, request); - request.setId("TEST_FUNCTIONAL_CASE_ID_1"); + request.setId("TEST_FUNCTIONAL_CASE_ID_3"); request.setDeleteAll(true); this.requestPostWithOkAndReturn(FUNCTIONAL_CASE_DELETE_URL, request); } diff --git a/backend/services/case-management/src/test/resources/dml/init_clean_up_resource_test.sql b/backend/services/case-management/src/test/resources/dml/init_clean_up_resource_test.sql new file mode 100644 index 0000000000..fe70320805 --- /dev/null +++ b/backend/services/case-management/src/test/resources/dml/init_clean_up_resource_test.sql @@ -0,0 +1,15 @@ + +INSERT INTO functional_case(id, num, module_id, project_id, template_id, name, review_status, tags, case_edit_type, pos, version_id, ref_id, last_execute_result, deleted, public_case, latest, create_user, update_user, delete_user, create_time, update_time, delete_time) +VALUES ('CLEAN_UP_FUNCTIONAL_CASE_ID', 1, 'TEST_MOUDLE_ID', 'TEST_CLEAN_UP_PROJECT_ID', '100001', '测试', 'UN_REVIEWED', NULL, 'STEP', 0, 'v1.0.0', 'v1.0.0', 'UN_EXECUTED', b'0', b'0', b'0', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL); + +INSERT INTO functional_case(id, num, module_id, project_id, template_id, name, review_status, tags, case_edit_type, pos, version_id, ref_id, last_execute_result, deleted, public_case, latest, create_user, update_user, delete_user, create_time, update_time, delete_time) +VALUES ('CLEAN_UP_FUNCTIONAL_CASE_ID_1', 2, 'TEST_MOUDLE_ID', 'TEST_CLEAN_UP_PROJECT_ID', '100001', '测试多版本', 'UN_REVIEWED', NULL, 'STEP', 0, 'v1.0.0', 'TEST_REF_ID', 'UN_EXECUTED', b'0', b'0', b'0', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL); + + + + + + + + + diff --git a/backend/services/case-management/src/test/resources/dml/init_file_metadata_test.sql b/backend/services/case-management/src/test/resources/dml/init_file_metadata_test.sql index 38341d308f..cfe28d05ec 100644 --- a/backend/services/case-management/src/test/resources/dml/init_file_metadata_test.sql +++ b/backend/services/case-management/src/test/resources/dml/init_file_metadata_test.sql @@ -13,6 +13,8 @@ VALUES ('TEST_FUNCTIONAL_CASE_ID_2', 3, 'TEST_MOUDLE_ID', '100001100001', '10000 INSERT INTO functional_case(id, num, module_id, project_id, template_id, name, review_status, tags, case_edit_type, pos, version_id, ref_id, last_execute_result, deleted, public_case, latest, create_user, update_user, delete_user, create_time, update_time, delete_time) VALUES ('TEST_FUNCTIONAL_CASE_ID_3', 3, 'TEST_MOUDLE_ID', '100001100001', '100001', 'copy_测试多版本', 'UN_REVIEWED', NULL, 'STEP', 0, 'v3.0.0', 'TEST_REF_ID', 'UN_EXECUTED', b'0', b'0', b'0', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL); +INSERT INTO functional_case(id, num, module_id, project_id, template_id, name, review_status, tags, case_edit_type, pos, version_id, ref_id, last_execute_result, deleted, public_case, latest, create_user, update_user, delete_user, create_time, update_time, delete_time) +VALUES ('TEST_FUNCTIONAL_CASE_ID_4', 4, 'TEST_MOUDLE_ID', '100001100001', '100001', 'copy_测试多版本', 'UN_REVIEWED', NULL, 'STEP', 0, 'v3.0.0', 'TEST_REF_ID', 'UN_EXECUTED', b'0', b'0', b'0', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL); INSERT INTO functional_case_blob(id, steps, text_description, expected_result, prerequisite, description) VALUES ('TEST_FUNCTIONAL_CASE_ID', 'STEP', '1111', NULL, NULL, 'TEST'); diff --git a/backend/services/project-management/src/main/java/io/metersphere/project/service/CleanupApplicationResourceService.java b/backend/services/project-management/src/main/java/io/metersphere/project/service/CleanupApplicationResourceService.java index 48e064a94c..e2bd7fd0c3 100644 --- a/backend/services/project-management/src/main/java/io/metersphere/project/service/CleanupApplicationResourceService.java +++ b/backend/services/project-management/src/main/java/io/metersphere/project/service/CleanupApplicationResourceService.java @@ -1,5 +1,7 @@ package io.metersphere.project.service; +import io.metersphere.project.domain.ProjectApplicationExample; +import io.metersphere.project.mapper.ProjectApplicationMapper; import io.metersphere.sdk.util.LogUtils; import io.metersphere.system.sechedule.ScheduleService; import io.metersphere.system.service.CleanupProjectResourceService; @@ -14,10 +16,15 @@ public class CleanupApplicationResourceService implements CleanupProjectResource @Resource private ScheduleService scheduleService; + @Resource + private ProjectApplicationMapper projectApplicationMapper; @Override public void deleteResources(String projectId) { scheduleService.deleteByProjectId(projectId); + ProjectApplicationExample example = new ProjectApplicationExample(); + example.createCriteria().andProjectIdEqualTo(projectId); + projectApplicationMapper.deleteByExample(example); } @Override