refactor(用例管理): 补充批量操作用例相关附件处理逻辑&变更记录接口

This commit is contained in:
WangXu10 2023-11-24 15:13:03 +08:00 committed by Craftsman
parent 0eb16af5f0
commit 86ce86649a
17 changed files with 305 additions and 74 deletions

View File

@ -26,6 +26,12 @@ public class FunctionalCaseHistory implements Serializable {
@Schema(description = "变更记录批次号", requiredMode = Schema.RequiredMode.REQUIRED)
private Integer num;
@Schema(description = "变更类型;IMPORT/EDIT/ROLLBACK", requiredMode = Schema.RequiredMode.REQUIRED)
private String type;
@Schema(description = "回退来源")
private String rollbackSourceId;
@Schema(description = "操作人")
private String createUser;
@ -42,6 +48,8 @@ public class FunctionalCaseHistory implements Serializable {
id("id", "id", "VARCHAR", false),
caseId("case_id", "caseId", "VARCHAR", false),
num("num", "num", "INTEGER", false),
type("type", "type", "VARCHAR", true),
rollbackSourceId("rollback_source_id", "rollbackSourceId", "VARCHAR", false),
createUser("create_user", "createUser", "VARCHAR", false),
createTime("create_time", "createTime", "BIGINT", false),
content("content", "content", "LONGVARBINARY", false);

View File

@ -304,6 +304,146 @@ public class FunctionalCaseHistoryExample {
return (Criteria) this;
}
public Criteria andTypeIsNull() {
addCriterion("`type` is null");
return (Criteria) this;
}
public Criteria andTypeIsNotNull() {
addCriterion("`type` is not null");
return (Criteria) this;
}
public Criteria andTypeEqualTo(String value) {
addCriterion("`type` =", value, "type");
return (Criteria) this;
}
public Criteria andTypeNotEqualTo(String value) {
addCriterion("`type` <>", value, "type");
return (Criteria) this;
}
public Criteria andTypeGreaterThan(String value) {
addCriterion("`type` >", value, "type");
return (Criteria) this;
}
public Criteria andTypeGreaterThanOrEqualTo(String value) {
addCriterion("`type` >=", value, "type");
return (Criteria) this;
}
public Criteria andTypeLessThan(String value) {
addCriterion("`type` <", value, "type");
return (Criteria) this;
}
public Criteria andTypeLessThanOrEqualTo(String value) {
addCriterion("`type` <=", value, "type");
return (Criteria) this;
}
public Criteria andTypeLike(String value) {
addCriterion("`type` like", value, "type");
return (Criteria) this;
}
public Criteria andTypeNotLike(String value) {
addCriterion("`type` not like", value, "type");
return (Criteria) this;
}
public Criteria andTypeIn(List<String> values) {
addCriterion("`type` in", values, "type");
return (Criteria) this;
}
public Criteria andTypeNotIn(List<String> values) {
addCriterion("`type` not in", values, "type");
return (Criteria) this;
}
public Criteria andTypeBetween(String value1, String value2) {
addCriterion("`type` between", value1, value2, "type");
return (Criteria) this;
}
public Criteria andTypeNotBetween(String value1, String value2) {
addCriterion("`type` not between", value1, value2, "type");
return (Criteria) this;
}
public Criteria andRollbackSourceIdIsNull() {
addCriterion("rollback_source_id is null");
return (Criteria) this;
}
public Criteria andRollbackSourceIdIsNotNull() {
addCriterion("rollback_source_id is not null");
return (Criteria) this;
}
public Criteria andRollbackSourceIdEqualTo(String value) {
addCriterion("rollback_source_id =", value, "rollbackSourceId");
return (Criteria) this;
}
public Criteria andRollbackSourceIdNotEqualTo(String value) {
addCriterion("rollback_source_id <>", value, "rollbackSourceId");
return (Criteria) this;
}
public Criteria andRollbackSourceIdGreaterThan(String value) {
addCriterion("rollback_source_id >", value, "rollbackSourceId");
return (Criteria) this;
}
public Criteria andRollbackSourceIdGreaterThanOrEqualTo(String value) {
addCriterion("rollback_source_id >=", value, "rollbackSourceId");
return (Criteria) this;
}
public Criteria andRollbackSourceIdLessThan(String value) {
addCriterion("rollback_source_id <", value, "rollbackSourceId");
return (Criteria) this;
}
public Criteria andRollbackSourceIdLessThanOrEqualTo(String value) {
addCriterion("rollback_source_id <=", value, "rollbackSourceId");
return (Criteria) this;
}
public Criteria andRollbackSourceIdLike(String value) {
addCriterion("rollback_source_id like", value, "rollbackSourceId");
return (Criteria) this;
}
public Criteria andRollbackSourceIdNotLike(String value) {
addCriterion("rollback_source_id not like", value, "rollbackSourceId");
return (Criteria) this;
}
public Criteria andRollbackSourceIdIn(List<String> values) {
addCriterion("rollback_source_id in", values, "rollbackSourceId");
return (Criteria) this;
}
public Criteria andRollbackSourceIdNotIn(List<String> values) {
addCriterion("rollback_source_id not in", values, "rollbackSourceId");
return (Criteria) this;
}
public Criteria andRollbackSourceIdBetween(String value1, String value2) {
addCriterion("rollback_source_id between", value1, value2, "rollbackSourceId");
return (Criteria) this;
}
public Criteria andRollbackSourceIdNotBetween(String value1, String value2) {
addCriterion("rollback_source_id not between", value1, value2, "rollbackSourceId");
return (Criteria) this;
}
public Criteria andCreateUserIsNull() {
addCriterion("create_user is null");
return (Criteria) this;

View File

@ -5,6 +5,8 @@
<id column="id" jdbcType="VARCHAR" property="id" />
<result column="case_id" jdbcType="VARCHAR" property="caseId" />
<result column="num" jdbcType="INTEGER" property="num" />
<result column="type" jdbcType="VARCHAR" property="type" />
<result column="rollback_source_id" jdbcType="VARCHAR" property="rollbackSourceId" />
<result column="create_user" jdbcType="VARCHAR" property="createUser" />
<result column="create_time" jdbcType="BIGINT" property="createTime" />
</resultMap>
@ -70,7 +72,7 @@
</where>
</sql>
<sql id="Base_Column_List">
id, case_id, num, create_user, create_time
id, case_id, num, `type`, rollback_source_id, create_user, create_time
</sql>
<sql id="Blob_Column_List">
content
@ -125,11 +127,11 @@
</delete>
<insert id="insert" parameterType="io.metersphere.functional.domain.FunctionalCaseHistory">
insert into functional_case_history (id, case_id, num,
create_user, create_time, content
)
`type`, rollback_source_id, create_user,
create_time, content)
values (#{id,jdbcType=VARCHAR}, #{caseId,jdbcType=VARCHAR}, #{num,jdbcType=INTEGER},
#{createUser,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{content,jdbcType=LONGVARBINARY}
)
#{type,jdbcType=VARCHAR}, #{rollbackSourceId,jdbcType=VARCHAR}, #{createUser,jdbcType=VARCHAR},
#{createTime,jdbcType=BIGINT}, #{content,jdbcType=LONGVARBINARY})
</insert>
<insert id="insertSelective" parameterType="io.metersphere.functional.domain.FunctionalCaseHistory">
insert into functional_case_history
@ -143,6 +145,12 @@
<if test="num != null">
num,
</if>
<if test="type != null">
`type`,
</if>
<if test="rollbackSourceId != null">
rollback_source_id,
</if>
<if test="createUser != null">
create_user,
</if>
@ -163,6 +171,12 @@
<if test="num != null">
#{num,jdbcType=INTEGER},
</if>
<if test="type != null">
#{type,jdbcType=VARCHAR},
</if>
<if test="rollbackSourceId != null">
#{rollbackSourceId,jdbcType=VARCHAR},
</if>
<if test="createUser != null">
#{createUser,jdbcType=VARCHAR},
</if>
@ -192,6 +206,12 @@
<if test="record.num != null">
num = #{record.num,jdbcType=INTEGER},
</if>
<if test="record.type != null">
`type` = #{record.type,jdbcType=VARCHAR},
</if>
<if test="record.rollbackSourceId != null">
rollback_source_id = #{record.rollbackSourceId,jdbcType=VARCHAR},
</if>
<if test="record.createUser != null">
create_user = #{record.createUser,jdbcType=VARCHAR},
</if>
@ -211,6 +231,8 @@
set id = #{record.id,jdbcType=VARCHAR},
case_id = #{record.caseId,jdbcType=VARCHAR},
num = #{record.num,jdbcType=INTEGER},
`type` = #{record.type,jdbcType=VARCHAR},
rollback_source_id = #{record.rollbackSourceId,jdbcType=VARCHAR},
create_user = #{record.createUser,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=BIGINT},
content = #{record.content,jdbcType=LONGVARBINARY}
@ -223,6 +245,8 @@
set id = #{record.id,jdbcType=VARCHAR},
case_id = #{record.caseId,jdbcType=VARCHAR},
num = #{record.num,jdbcType=INTEGER},
`type` = #{record.type,jdbcType=VARCHAR},
rollback_source_id = #{record.rollbackSourceId,jdbcType=VARCHAR},
create_user = #{record.createUser,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=BIGINT}
<if test="_parameter != null">
@ -238,6 +262,12 @@
<if test="num != null">
num = #{num,jdbcType=INTEGER},
</if>
<if test="type != null">
`type` = #{type,jdbcType=VARCHAR},
</if>
<if test="rollbackSourceId != null">
rollback_source_id = #{rollbackSourceId,jdbcType=VARCHAR},
</if>
<if test="createUser != null">
create_user = #{createUser,jdbcType=VARCHAR},
</if>
@ -254,6 +284,8 @@
update functional_case_history
set case_id = #{caseId,jdbcType=VARCHAR},
num = #{num,jdbcType=INTEGER},
`type` = #{type,jdbcType=VARCHAR},
rollback_source_id = #{rollbackSourceId,jdbcType=VARCHAR},
create_user = #{createUser,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT},
content = #{content,jdbcType=LONGVARBINARY}
@ -263,18 +295,20 @@
update functional_case_history
set case_id = #{caseId,jdbcType=VARCHAR},
num = #{num,jdbcType=INTEGER},
`type` = #{type,jdbcType=VARCHAR},
rollback_source_id = #{rollbackSourceId,jdbcType=VARCHAR},
create_user = #{createUser,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT}
where id = #{id,jdbcType=VARCHAR}
</update>
<insert id="batchInsert" parameterType="map">
insert into functional_case_history
(id, case_id, num, create_user, create_time, content)
(id, case_id, num, `type`, rollback_source_id, create_user, create_time, content)
values
<foreach collection="list" item="item" separator=",">
(#{item.id,jdbcType=VARCHAR}, #{item.caseId,jdbcType=VARCHAR}, #{item.num,jdbcType=INTEGER},
#{item.createUser,jdbcType=VARCHAR}, #{item.createTime,jdbcType=BIGINT}, #{item.content,jdbcType=LONGVARBINARY}
)
#{item.type,jdbcType=VARCHAR}, #{item.rollbackSourceId,jdbcType=VARCHAR}, #{item.createUser,jdbcType=VARCHAR},
#{item.createTime,jdbcType=BIGINT}, #{item.content,jdbcType=LONGVARBINARY})
</foreach>
</insert>
<insert id="batchInsertSelective" parameterType="map">
@ -296,6 +330,12 @@
<if test="'num'.toString() == column.value">
#{item.num,jdbcType=INTEGER}
</if>
<if test="'type'.toString() == column.value">
#{item.type,jdbcType=VARCHAR}
</if>
<if test="'rollback_source_id'.toString() == column.value">
#{item.rollbackSourceId,jdbcType=VARCHAR}
</if>
<if test="'create_user'.toString() == column.value">
#{item.createUser,jdbcType=VARCHAR}
</if>

View File

@ -233,6 +233,8 @@ CREATE TABLE IF NOT EXISTS functional_case_history
`id` VARCHAR(50) NOT NULL COMMENT 'ID',
`case_id` VARCHAR(50) NOT NULL COMMENT '用例ID',
`num` INT NOT NULL COMMENT '变更记录批次号',
`type` VARCHAR(64) NOT NULL COMMENT '变更类型;IMPORT/EDIT/ROLLBACK',
`rollback_source_id` VARCHAR(50) COMMENT '回退来源',
`content` BLOB NOT NULL COMMENT '修改内容',
`create_user` VARCHAR(50) NOT NULL COMMENT '操作人',
`create_time` BIGINT NOT NULL COMMENT '操作时间',

View File

@ -45,8 +45,6 @@ public class FunctionalCaseAttachmentController {
private FileAssociationService fileAssociationService;
//TODO 附件操作文件删除/文件下载/文件预览/文件转存/文件更新
@PostMapping("/page")
@Operation(summary = "用例管理-功能用例-附件-关联文件列表分页接口")
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ)

View File

@ -2,11 +2,11 @@ package io.metersphere.functional.service;
import io.metersphere.functional.constants.CaseReviewStatus;
import io.metersphere.functional.constants.FunctionalCaseReviewStatus;
import io.metersphere.functional.domain.*;
import io.metersphere.functional.mapper.*;
import io.metersphere.functional.request.CaseReviewAddRequest;
import io.metersphere.functional.result.CaseManagementResultCode;
import io.metersphere.sdk.constants.FunctionalCaseReviewStatus;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.uid.IDGenerator;

View File

@ -9,6 +9,7 @@ import io.metersphere.functional.dto.FunctionalCaseDetailDTO;
import io.metersphere.functional.mapper.FunctionalCaseAttachmentMapper;
import io.metersphere.functional.request.FunctionalCaseAddRequest;
import io.metersphere.functional.request.FunctionalCaseFileRequest;
import io.metersphere.project.domain.FileAssociation;
import io.metersphere.project.dto.filemanagement.FileInfo;
import io.metersphere.project.dto.filemanagement.FileLogRecord;
import io.metersphere.project.service.FileAssociationService;
@ -140,10 +141,10 @@ public class FunctionalCaseAttachmentService {
*/
public void deleteCaseAttachment(List<String> deleteFileMetaIds, String caseId, String projectId) {
FunctionalCaseAttachmentExample example = new FunctionalCaseAttachmentExample();
example.createCriteria().andFileIdIn(deleteFileMetaIds).andCaseIdEqualTo(caseId).andLocalEqualTo(true);
example.createCriteria().andIdIn(deleteFileMetaIds).andCaseIdEqualTo(caseId).andLocalEqualTo(true);
List<FunctionalCaseAttachment> delAttachment = functionalCaseAttachmentMapper.selectByExample(example);
example.clear();
example.createCriteria().andFileIdIn(deleteFileMetaIds).andCaseIdEqualTo(caseId);
example.createCriteria().andIdIn(deleteFileMetaIds);
functionalCaseAttachmentMapper.deleteByExample(example);
this.deleteMinioFile(delAttachment, projectId, caseId);
}
@ -237,7 +238,7 @@ public class FunctionalCaseAttachmentService {
FunctionalCaseAttachment attachment = caseAttachments.get(0);
FileRequest fileRequest = new FileRequest();
fileRequest.setFileName(attachment.getFileName());
fileRequest.setFolder(DefaultRepositoryDir.getFunctionalCaseDir(request.getProjectId(), request.getCaseId()) + "/" + request.getFileId());
fileRequest.setFolder(DefaultRepositoryDir.getFunctionalCaseDir(request.getProjectId(), request.getCaseId()) + "/" + attachment.getFileId());
fileRequest.setStorage(StorageType.MINIO.name());
byte[] bytes = null;
try {
@ -275,11 +276,20 @@ public class FunctionalCaseAttachmentService {
public FunctionalCaseAttachment getAttachment(FunctionalCaseFileRequest request) {
FunctionalCaseAttachmentExample example = new FunctionalCaseAttachmentExample();
example.createCriteria().andFileIdEqualTo(request.getFileId()).andCaseIdEqualTo(request.getCaseId());
example.createCriteria().andIdEqualTo(request.getFileId()).andCaseIdEqualTo(request.getCaseId());
List<FunctionalCaseAttachment> caseAttachments = functionalCaseAttachmentMapper.selectByExample(example);
if (CollectionUtils.isNotEmpty(caseAttachments)) {
return caseAttachments.get(0);
}
return new FunctionalCaseAttachment();
}
public Map<String, List<FileAssociation>> getFileAssociationByCaseIds(List<String> ids) {
List<FileAssociation> fileAssociations = fileAssociationService.getFileAssociations(ids, FileAssociationSourceUtil.SOURCE_TYPE_FUNCTIONAL_CASE);
Map<String, List<FileAssociation>> fileAssociationMap = new HashMap<>();
if (CollectionUtils.isNotEmpty(fileAssociations)) {
fileAssociationMap = fileAssociations.stream().collect(Collectors.groupingBy(FileAssociation::getSourceId));
}
return fileAssociationMap;
}
}

View File

@ -0,0 +1,7 @@
package io.metersphere.functional.service;
import java.util.List;
public interface FunctionalCaseHistoryService {
void saveHistoryLog(List<String> caseIds);
}

View File

@ -1,19 +1,24 @@
package io.metersphere.functional.service;
import io.metersphere.functional.constants.FunctionalCaseReviewStatus;
import io.metersphere.functional.domain.*;
import io.metersphere.functional.dto.*;
import io.metersphere.functional.mapper.*;
import io.metersphere.functional.mapper.ExtFunctionalCaseMapper;
import io.metersphere.functional.mapper.FunctionalCaseBlobMapper;
import io.metersphere.functional.mapper.FunctionalCaseFollowerMapper;
import io.metersphere.functional.mapper.FunctionalCaseMapper;
import io.metersphere.functional.request.*;
import io.metersphere.functional.result.CaseManagementResultCode;
import io.metersphere.project.domain.FileAssociation;
import io.metersphere.project.dto.ModuleCountDTO;
import io.metersphere.project.mapper.ExtBaseProjectVersionMapper;
import io.metersphere.project.service.ProjectTemplateService;
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.CommonBeanFactory;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.dto.sdk.TemplateCustomFieldDTO;
import io.metersphere.system.dto.sdk.TemplateDTO;
@ -80,6 +85,7 @@ public class FunctionalCaseService {
private static final String ADD_FUNCTIONAL_CASE_FILE_LOG_URL = "/functional/case/add";
private static final String UPDATE_FUNCTIONAL_CASE_FILE_LOG_URL = "/functional/case/update";
private static final String FUNCTIONAL_CASE_BATCH_COPY_FILE_LOG_URL = "/functional/case/batch/copy";
public FunctionalCase addFunctionalCase(FunctionalCaseAddRequest request, List<MultipartFile> files, String userId) {
String caseId = IDGenerator.nextStr();
@ -94,11 +100,18 @@ public class FunctionalCaseService {
functionalCaseAttachmentService.association(request.getRelateFileMetaIds(), caseId, userId, ADD_FUNCTIONAL_CASE_FILE_LOG_URL, request.getProjectId());
}
//TODO 记录变更历史
saveHistory(Collections.singletonList(caseId));
return functionalCase;
}
private void saveHistory(List<String> ids) {
FunctionalCaseHistoryService functionalCaseHistoryService = CommonBeanFactory.getBean(FunctionalCaseHistoryService.class);
if (functionalCaseHistoryService != null) {
functionalCaseHistoryService.saveHistoryLog(ids);
}
}
/**
* 添加功能用例
*
@ -169,7 +182,7 @@ public class FunctionalCaseService {
BeanUtils.copyBean(functionalCaseDetailDTO, caseBlob);
//模板校验 获取自定义字段
functionalCaseDetailDTO = checkTemplateCustomField(functionalCaseDetailDTO, functionalCase);
checkTemplateCustomField(functionalCaseDetailDTO, functionalCase);
//是否关注用例
Boolean isFollow = checkIsFollowCase(functionalCase.getId(), userId);
@ -268,7 +281,7 @@ public class FunctionalCaseService {
functionalCaseAttachmentService.association(request.getRelateFileMetaIds(), request.getId(), userId, UPDATE_FUNCTIONAL_CASE_FILE_LOG_URL, request.getProjectId());
}
//TODO 记录变更历史 addFunctionalCaseHistory
saveHistory(Collections.singletonList(request.getId()));
return functionalCase;
@ -455,64 +468,61 @@ public class FunctionalCaseService {
Map<String, FunctionalCaseBlob> functionalCaseBlobMap = copyBlobInfo(ids);
//附件 本地附件
Map<String, List<FunctionalCaseAttachment>> attachmentMap = functionalCaseAttachmentService.getAttachmentByCaseIds(ids);
//TODO 文件库附件
//文件库附件
Map<String, List<FileAssociation>> fileAssociationMap = functionalCaseAttachmentService.getFileAssociationByCaseIds(ids);
//自定义字段
Map<String, List<FunctionalCaseCustomField>> customFieldMap = functionalCaseCustomFieldService.getCustomFieldMapByCaseIds(ids);
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
FunctionalCaseMapper mapper = sqlSession.getMapper(FunctionalCaseMapper.class);
Long nextOrder = getNextOrder(request.getProjectId());
try {
for (int i = 0; i < ids.size(); i++) {
String id = IDGenerator.nextStr();
FunctionalCase functionalCase = functionalCaseMap.get(ids.get(i));
FunctionalCaseBlob functionalCaseBlob = functionalCaseBlobMap.get(ids.get(i));
List<FunctionalCaseAttachment> caseAttachments = attachmentMap.get(ids.get(i));
List<FunctionalCaseCustomField> customFields = customFieldMap.get(ids.get(i));
for (int i = 0; i < ids.size(); i++) {
String id = IDGenerator.nextStr();
FunctionalCase functionalCase = functionalCaseMap.get(ids.get(i));
FunctionalCaseBlob functionalCaseBlob = functionalCaseBlobMap.get(ids.get(i));
List<FunctionalCaseAttachment> caseAttachments = attachmentMap.get(ids.get(i));
List<FileAssociation> fileAssociationList = fileAssociationMap.get(ids.get(i));
List<FunctionalCaseCustomField> customFields = customFieldMap.get(ids.get(i));
Optional.ofNullable(functionalCase).ifPresent(functional -> {
functional.setId(id);
functional.setRefId(id);
functional.setModuleId(request.getModuleId());
functional.setNum(getNextNum(request.getProjectId()));
functional.setName(getCopyName(functionalCase.getName()));
functional.setReviewStatus(FunctionalCaseReviewStatus.UN_REVIEWED.name());
functional.setPos(nextOrder + ORDER_STEP);
functional.setLastExecuteResult(FunctionalCaseExecuteResult.UN_EXECUTED.name());
functional.setCreateUser(userId);
functional.setCreateTime(System.currentTimeMillis());
functional.setUpdateTime(System.currentTimeMillis());
mapper.insert(functional);
Optional.ofNullable(functionalCase).ifPresent(functional -> {
functional.setId(id);
functional.setRefId(id);
functional.setModuleId(request.getModuleId());
functional.setNum(getNextNum(request.getProjectId()));
functional.setName(getCopyName(functionalCase.getName()));
functional.setReviewStatus(FunctionalCaseReviewStatus.UN_REVIEWED.name());
functional.setPos(nextOrder + ORDER_STEP);
functional.setLastExecuteResult(FunctionalCaseExecuteResult.UN_EXECUTED.name());
functional.setCreateUser(userId);
functional.setCreateTime(System.currentTimeMillis());
functional.setUpdateTime(System.currentTimeMillis());
functionalCaseMapper.insert(functional);
functionalCaseBlob.setId(id);
functionalCaseBlobMapper.insert(functionalCaseBlob);
functionalCaseBlob.setId(id);
functionalCaseBlobMapper.insert(functionalCaseBlob);
});
if (CollectionUtils.isNotEmpty(caseAttachments)) {
caseAttachments.forEach(attachment -> {
attachment.setId(IDGenerator.nextStr());
attachment.setCaseId(id);
attachment.setCreateUser(userId);
attachment.setCreateTime(System.currentTimeMillis());
});
if (CollectionUtils.isNotEmpty(caseAttachments)) {
caseAttachments.forEach(attachment -> {
attachment.setId(IDGenerator.nextStr());
attachment.setCaseId(id);
attachment.setCreateUser(userId);
attachment.setCreateTime(System.currentTimeMillis());
});
functionalCaseAttachmentService.batchSaveAttachment(caseAttachments);
}
if (CollectionUtils.isNotEmpty(customFields)) {
customFields.forEach(customField -> {
customField.setCaseId(id);
});
functionalCaseCustomFieldService.batchSaveCustomField(customFields);
}
if (i % 50 == 0) {
sqlSession.flushStatements();
}
functionalCaseAttachmentService.batchSaveAttachment(caseAttachments);
}
sqlSession.flushStatements();
} finally {
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
if (CollectionUtils.isNotEmpty(customFields)) {
customFields.forEach(customField -> {
customField.setCaseId(id);
});
functionalCaseCustomFieldService.batchSaveCustomField(customFields);
}
if (CollectionUtils.isNotEmpty(fileAssociationList)) {
List<String> fileIds = fileAssociationList.stream().map(FileAssociation::getFileId).collect(Collectors.toList());
functionalCaseAttachmentService.association(fileIds, id, userId, FUNCTIONAL_CASE_BATCH_COPY_FILE_LOG_URL, request.getProjectId());
}
}
}
}
@ -554,6 +564,7 @@ public class FunctionalCaseService {
handleTags(request, userId, ids);
//自定义字段处理
handleCustomFields(request, userId, ids);
saveHistory(ids);
}
}

View File

@ -181,7 +181,7 @@ public class FunctionalCaseControllerTests extends BaseTest {
Assertions.assertNotNull(resultHolder);
//设置删除文件id
request.setDeleteFileMetaIds(Arrays.asList("delete_file_meta_id_1"));
request.setDeleteFileMetaIds(Arrays.asList("TEST_CASE_ATTACHMENT_ID_2"));
request.setUnLinkFilesIds(Arrays.asList("relate_file_meta_id_1"));
request.setRelateFileMetaIds(Arrays.asList("relate_file_meta_id_1", "relate_file_meta_id_2"));
paramMap = new LinkedMultiValueMap<>();

View File

@ -1,5 +1,6 @@
package io.metersphere.functional.controller;
import io.metersphere.functional.constants.FunctionalCaseReviewStatus;
import io.metersphere.functional.domain.FunctionalCase;
import io.metersphere.functional.domain.FunctionalCaseModule;
import io.metersphere.functional.domain.FunctionalCaseModuleExample;
@ -11,7 +12,6 @@ import io.metersphere.functional.service.FunctionalCaseModuleService;
import io.metersphere.project.domain.Project;
import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.sdk.constants.FunctionalCaseExecuteResult;
import io.metersphere.sdk.constants.FunctionalCaseReviewStatus;
import io.metersphere.sdk.constants.ModuleConstants;
import io.metersphere.sdk.constants.SessionConstants;
import io.metersphere.sdk.util.JSON;

View File

@ -1,7 +1,7 @@
INSERT INTO file_metadata(id, name, type, size, create_time, update_time, project_id, storage, create_user, update_user, tags, description, module_id, path, latest, ref_id, file_version) VALUES ('relate_file_meta_id_1', 'formItem', 'ts', 2502, 1698058347559, 1698058347559, '100001100001', 'MINIO', 'admin', 'admin', NULL, NULL, 'root', '100001100001/1127016598347779', b'1', '1127016598347779', '1127016598347779');
INSERT INTO file_metadata(id, name, type, size, create_time, update_time, project_id, storage, create_user, update_user, tags, description, module_id, path, latest, ref_id, file_version) VALUES ('relate_file_meta_id_2', 'formItem', 'ts', 2502, 1698058347559, 1698058347559, '100001100001', 'MINIO', 'admin', 'admin', NULL, NULL, 'root', '100001100001/1127016598347779', b'1', '1127016598347779', '1127016598347779');
INSERT INTO file_association(id, source_type, source_id, file_id, file_ref_id, file_version, create_time, update_user, update_time, create_user) VALUES ('file_association_1', 'functional_case', 'TEST_FUNCTIONAL_CASE_ID', 'relate_file_meta_id_1', '1', '1', 1698983271536, 'admin', 1698983271536, 'admin');
INSERT INTO file_association(id, source_type, source_id, file_id, file_ref_id, file_version, create_time, update_user, update_time, create_user) VALUES ('file_association_1', 'FUNCTIONAL_CASE', 'TEST_FUNCTIONAL_CASE_ID', 'relate_file_meta_id_1', '1', '1', 1698983271536, 'admin', 1698983271536, 'admin');
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)

View File

@ -1,5 +1,6 @@
package io.metersphere.project.mapper;
import io.metersphere.project.domain.FileAssociation;
import io.metersphere.project.dto.filemanagement.FileAssociationSource;
import io.metersphere.project.dto.filemanagement.FileInfo;
import org.apache.ibatis.annotations.Param;
@ -15,4 +16,6 @@ public interface ExtFileAssociationMapper {
List<FileAssociationSource> selectAssociationSourceBySourceTableAndIdList(@Param("querySql") String querySql, @Param("idList") List<String> sourceIdList);
List<FileInfo> selectAssociationFileInfo(@Param("sourceId") String sourceId, @Param("sourceType") String sourceType);
List<FileAssociation> selectFileIdsBySourceId(@Param("sourceIds")List<String> sourceIds, @Param("sourceType")String sourceType);
}

View File

@ -19,7 +19,7 @@
SELECT
file_association.id AS id,
file_association.file_id AS fileId,
CONCAT( file_metadata.`name`, file_metadata.type ) AS fileName,
CONCAT( file_metadata.`name`, '.', file_metadata.type ) AS fileName,
file_metadata.size AS size,
'false' AS local,
file_association.create_user AS createUser,
@ -31,4 +31,11 @@
file_association.source_id = #{sourceId}
AND file_association.source_type = #{sourceType}
</select>
<select id="selectFileIdsBySourceId" resultType="io.metersphere.project.domain.FileAssociation">
select source_id, file_id from file_association where source_type = #{sourceType} and source_id in
<foreach collection="sourceIds" item="sourceId" open="(" separator="," close=")">
#{sourceId}
</foreach>
</select>
</mapper>

View File

@ -326,4 +326,8 @@ public class FileAssociationService {
public List<FileInfo> getFiles(String sourceId, String sourceType) {
return extFileAssociationMapper.selectAssociationFileInfo(sourceId, sourceType);
}
public List<FileAssociation> getFileAssociations(List<String> sourceIds, String sourceType) {
return extFileAssociationMapper.selectFileIdsBySourceId(sourceIds, sourceType);
}
}

View File

@ -2330,5 +2330,6 @@ public class FileManagementControllerTests extends BaseTest {
@Order(91)
public void testQuery() throws Exception {
fileAssociationService.getFiles("TEST", FileAssociationSourceUtil.SOURCE_TYPE_FUNCTIONAL_CASE);
fileAssociationService.getFileAssociations(Collections.singletonList("TEST"), FileAssociationSourceUtil.SOURCE_TYPE_FUNCTIONAL_CASE);
}
}