feat(功能用例): 查看用例详情&更新用例基本信息接口

This commit is contained in:
WangXu10 2023-10-30 11:52:46 +08:00 committed by Craftsman
parent 9f5b37b497
commit b1c627ef3f
16 changed files with 478 additions and 161 deletions

View File

@ -12,6 +12,11 @@ import lombok.Data;
@Data
public class FunctionalCaseAttachment implements Serializable {
@Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{functional_case_attachment.id.not_blank}", groups = {Updated.class})
@Size(min = 1, max = 50, message = "{functional_case_attachment.id.length_range}", groups = {Created.class, Updated.class})
private String id;
@Schema(description = "功能用例ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{functional_case_attachment.case_id.not_blank}", groups = {Created.class})
@Size(min = 1, max = 50, message = "{functional_case_attachment.case_id.length_range}", groups = {Created.class, Updated.class})
@ -22,11 +27,6 @@ public class FunctionalCaseAttachment implements Serializable {
@Size(min = 1, max = 50, message = "{functional_case_attachment.file_id.length_range}", groups = {Created.class, Updated.class})
private String fileId;
@Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{functional_case_attachment.id.not_blank}", groups = {Updated.class})
@Size(min = 1, max = 50, message = "{functional_case_attachment.id.length_range}", groups = {Created.class, Updated.class})
private String id;
@Schema(description = "文件名称", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{functional_case_attachment.file_name.not_blank}", groups = {Created.class})
@Size(min = 1, max = 255, message = "{functional_case_attachment.file_name.length_range}", groups = {Created.class, Updated.class})
@ -51,9 +51,9 @@ public class FunctionalCaseAttachment implements Serializable {
private static final long serialVersionUID = 1L;
public enum Column {
id("id", "id", "VARCHAR", false),
caseId("case_id", "caseId", "VARCHAR", false),
fileId("file_id", "fileId", "VARCHAR", false),
id("id", "id", "VARCHAR", false),
fileName("file_name", "fileName", "VARCHAR", false),
size("size", "size", "BIGINT", true),
local("local", "local", "BIT", true),

View File

@ -104,6 +104,76 @@ public class FunctionalCaseAttachmentExample {
criteria.add(new Criterion(condition, value1, value2));
}
public Criteria andIdIsNull() {
addCriterion("id is null");
return (Criteria) this;
}
public Criteria andIdIsNotNull() {
addCriterion("id is not null");
return (Criteria) this;
}
public Criteria andIdEqualTo(String value) {
addCriterion("id =", value, "id");
return (Criteria) this;
}
public Criteria andIdNotEqualTo(String value) {
addCriterion("id <>", value, "id");
return (Criteria) this;
}
public Criteria andIdGreaterThan(String value) {
addCriterion("id >", value, "id");
return (Criteria) this;
}
public Criteria andIdGreaterThanOrEqualTo(String value) {
addCriterion("id >=", value, "id");
return (Criteria) this;
}
public Criteria andIdLessThan(String value) {
addCriterion("id <", value, "id");
return (Criteria) this;
}
public Criteria andIdLessThanOrEqualTo(String value) {
addCriterion("id <=", value, "id");
return (Criteria) this;
}
public Criteria andIdLike(String value) {
addCriterion("id like", value, "id");
return (Criteria) this;
}
public Criteria andIdNotLike(String value) {
addCriterion("id not like", value, "id");
return (Criteria) this;
}
public Criteria andIdIn(List<String> values) {
addCriterion("id in", values, "id");
return (Criteria) this;
}
public Criteria andIdNotIn(List<String> values) {
addCriterion("id not in", values, "id");
return (Criteria) this;
}
public Criteria andIdBetween(String value1, String value2) {
addCriterion("id between", value1, value2, "id");
return (Criteria) this;
}
public Criteria andIdNotBetween(String value1, String value2) {
addCriterion("id not between", value1, value2, "id");
return (Criteria) this;
}
public Criteria andCaseIdIsNull() {
addCriterion("case_id is null");
return (Criteria) this;
@ -244,76 +314,6 @@ public class FunctionalCaseAttachmentExample {
return (Criteria) this;
}
public Criteria andIdIsNull() {
addCriterion("id is null");
return (Criteria) this;
}
public Criteria andIdIsNotNull() {
addCriterion("id is not null");
return (Criteria) this;
}
public Criteria andIdEqualTo(String value) {
addCriterion("id =", value, "id");
return (Criteria) this;
}
public Criteria andIdNotEqualTo(String value) {
addCriterion("id <>", value, "id");
return (Criteria) this;
}
public Criteria andIdGreaterThan(String value) {
addCriterion("id >", value, "id");
return (Criteria) this;
}
public Criteria andIdGreaterThanOrEqualTo(String value) {
addCriterion("id >=", value, "id");
return (Criteria) this;
}
public Criteria andIdLessThan(String value) {
addCriterion("id <", value, "id");
return (Criteria) this;
}
public Criteria andIdLessThanOrEqualTo(String value) {
addCriterion("id <=", value, "id");
return (Criteria) this;
}
public Criteria andIdLike(String value) {
addCriterion("id like", value, "id");
return (Criteria) this;
}
public Criteria andIdNotLike(String value) {
addCriterion("id not like", value, "id");
return (Criteria) this;
}
public Criteria andIdIn(List<String> values) {
addCriterion("id in", values, "id");
return (Criteria) this;
}
public Criteria andIdNotIn(List<String> values) {
addCriterion("id not in", values, "id");
return (Criteria) this;
}
public Criteria andIdBetween(String value1, String value2) {
addCriterion("id between", value1, value2, "id");
return (Criteria) this;
}
public Criteria andIdNotBetween(String value1, String value2) {
addCriterion("id not between", value1, value2, "id");
return (Criteria) this;
}
public Criteria andFileNameIsNull() {
addCriterion("file_name is null");
return (Criteria) this;

View File

@ -10,7 +10,7 @@ public interface FunctionalCaseAttachmentMapper {
int deleteByExample(FunctionalCaseAttachmentExample example);
int deleteByPrimaryKey(@Param("caseId") String caseId, @Param("fileId") String fileId);
int deleteByPrimaryKey(String id);
int insert(FunctionalCaseAttachment record);
@ -18,7 +18,7 @@ public interface FunctionalCaseAttachmentMapper {
List<FunctionalCaseAttachment> selectByExample(FunctionalCaseAttachmentExample example);
FunctionalCaseAttachment selectByPrimaryKey(@Param("caseId") String caseId, @Param("fileId") String fileId);
FunctionalCaseAttachment selectByPrimaryKey(String id);
int updateByExampleSelective(@Param("record") FunctionalCaseAttachment record, @Param("example") FunctionalCaseAttachmentExample example);

View File

@ -2,9 +2,9 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="io.metersphere.functional.mapper.FunctionalCaseAttachmentMapper">
<resultMap id="BaseResultMap" type="io.metersphere.functional.domain.FunctionalCaseAttachment">
<id column="case_id" jdbcType="VARCHAR" property="caseId" />
<id column="file_id" jdbcType="VARCHAR" property="fileId" />
<result column="id" jdbcType="VARCHAR" property="id" />
<id column="id" jdbcType="VARCHAR" property="id" />
<result column="case_id" jdbcType="VARCHAR" property="caseId" />
<result column="file_id" jdbcType="VARCHAR" property="fileId" />
<result column="file_name" jdbcType="VARCHAR" property="fileName" />
<result column="size" jdbcType="BIGINT" property="size" />
<result column="local" jdbcType="BIT" property="local" />
@ -70,7 +70,7 @@
</where>
</sql>
<sql id="Base_Column_List">
case_id, file_id, id, file_name, `size`, `local`, create_user, create_time
id, case_id, file_id, file_name, `size`, `local`, create_user, create_time
</sql>
<select id="selectByExample" parameterType="io.metersphere.functional.domain.FunctionalCaseAttachmentExample" resultMap="BaseResultMap">
select
@ -86,17 +86,15 @@
order by ${orderByClause}
</if>
</select>
<select id="selectByPrimaryKey" parameterType="map" resultMap="BaseResultMap">
<select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from functional_case_attachment
where case_id = #{caseId,jdbcType=VARCHAR}
and file_id = #{fileId,jdbcType=VARCHAR}
where id = #{id,jdbcType=VARCHAR}
</select>
<delete id="deleteByPrimaryKey" parameterType="map">
<delete id="deleteByPrimaryKey" parameterType="java.lang.String">
delete from functional_case_attachment
where case_id = #{caseId,jdbcType=VARCHAR}
and file_id = #{fileId,jdbcType=VARCHAR}
where id = #{id,jdbcType=VARCHAR}
</delete>
<delete id="deleteByExample" parameterType="io.metersphere.functional.domain.FunctionalCaseAttachmentExample">
delete from functional_case_attachment
@ -105,25 +103,25 @@
</if>
</delete>
<insert id="insert" parameterType="io.metersphere.functional.domain.FunctionalCaseAttachment">
insert into functional_case_attachment (case_id, file_id, id,
insert into functional_case_attachment (id, case_id, file_id,
file_name, `size`, `local`, create_user,
create_time)
values (#{caseId,jdbcType=VARCHAR}, #{fileId,jdbcType=VARCHAR}, #{id,jdbcType=VARCHAR},
values (#{id,jdbcType=VARCHAR}, #{caseId,jdbcType=VARCHAR}, #{fileId,jdbcType=VARCHAR},
#{fileName,jdbcType=VARCHAR}, #{size,jdbcType=BIGINT}, #{local,jdbcType=BIT}, #{createUser,jdbcType=VARCHAR},
#{createTime,jdbcType=BIGINT})
</insert>
<insert id="insertSelective" parameterType="io.metersphere.functional.domain.FunctionalCaseAttachment">
insert into functional_case_attachment
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
id,
</if>
<if test="caseId != null">
case_id,
</if>
<if test="fileId != null">
file_id,
</if>
<if test="id != null">
id,
</if>
<if test="fileName != null">
file_name,
</if>
@ -141,15 +139,15 @@
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=VARCHAR},
</if>
<if test="caseId != null">
#{caseId,jdbcType=VARCHAR},
</if>
<if test="fileId != null">
#{fileId,jdbcType=VARCHAR},
</if>
<if test="id != null">
#{id,jdbcType=VARCHAR},
</if>
<if test="fileName != null">
#{fileName,jdbcType=VARCHAR},
</if>
@ -176,15 +174,15 @@
<update id="updateByExampleSelective" parameterType="map">
update functional_case_attachment
<set>
<if test="record.id != null">
id = #{record.id,jdbcType=VARCHAR},
</if>
<if test="record.caseId != null">
case_id = #{record.caseId,jdbcType=VARCHAR},
</if>
<if test="record.fileId != null">
file_id = #{record.fileId,jdbcType=VARCHAR},
</if>
<if test="record.id != null">
id = #{record.id,jdbcType=VARCHAR},
</if>
<if test="record.fileName != null">
file_name = #{record.fileName,jdbcType=VARCHAR},
</if>
@ -207,9 +205,9 @@
</update>
<update id="updateByExample" parameterType="map">
update functional_case_attachment
set case_id = #{record.caseId,jdbcType=VARCHAR},
set id = #{record.id,jdbcType=VARCHAR},
case_id = #{record.caseId,jdbcType=VARCHAR},
file_id = #{record.fileId,jdbcType=VARCHAR},
id = #{record.id,jdbcType=VARCHAR},
file_name = #{record.fileName,jdbcType=VARCHAR},
`size` = #{record.size,jdbcType=BIGINT},
`local` = #{record.local,jdbcType=BIT},
@ -222,8 +220,11 @@
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.functional.domain.FunctionalCaseAttachment">
update functional_case_attachment
<set>
<if test="id != null">
id = #{id,jdbcType=VARCHAR},
<if test="caseId != null">
case_id = #{caseId,jdbcType=VARCHAR},
</if>
<if test="fileId != null">
file_id = #{fileId,jdbcType=VARCHAR},
</if>
<if test="fileName != null">
file_name = #{fileName,jdbcType=VARCHAR},
@ -241,26 +242,25 @@
create_time = #{createTime,jdbcType=BIGINT},
</if>
</set>
where case_id = #{caseId,jdbcType=VARCHAR}
and file_id = #{fileId,jdbcType=VARCHAR}
where id = #{id,jdbcType=VARCHAR}
</update>
<update id="updateByPrimaryKey" parameterType="io.metersphere.functional.domain.FunctionalCaseAttachment">
update functional_case_attachment
set id = #{id,jdbcType=VARCHAR},
set case_id = #{caseId,jdbcType=VARCHAR},
file_id = #{fileId,jdbcType=VARCHAR},
file_name = #{fileName,jdbcType=VARCHAR},
`size` = #{size,jdbcType=BIGINT},
`local` = #{local,jdbcType=BIT},
create_user = #{createUser,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT}
where case_id = #{caseId,jdbcType=VARCHAR}
and file_id = #{fileId,jdbcType=VARCHAR}
where id = #{id,jdbcType=VARCHAR}
</update>
<insert id="batchInsert" parameterType="map">
insert into functional_case_attachment
(case_id, file_id, id, file_name, `size`, `local`, create_user, create_time)
(id, case_id, file_id, file_name, `size`, `local`, create_user, create_time)
values
<foreach collection="list" item="item" separator=",">
(#{item.caseId,jdbcType=VARCHAR}, #{item.fileId,jdbcType=VARCHAR}, #{item.id,jdbcType=VARCHAR},
(#{item.id,jdbcType=VARCHAR}, #{item.caseId,jdbcType=VARCHAR}, #{item.fileId,jdbcType=VARCHAR},
#{item.fileName,jdbcType=VARCHAR}, #{item.size,jdbcType=BIGINT}, #{item.local,jdbcType=BIT},
#{item.createUser,jdbcType=VARCHAR}, #{item.createTime,jdbcType=BIGINT})
</foreach>
@ -275,15 +275,15 @@
<foreach collection="list" item="item" separator=",">
(
<foreach collection="selective" item="column" separator=",">
<if test="'id'.toString() == column.value">
#{item.id,jdbcType=VARCHAR}
</if>
<if test="'case_id'.toString() == column.value">
#{item.caseId,jdbcType=VARCHAR}
</if>
<if test="'file_id'.toString() == column.value">
#{item.fileId,jdbcType=VARCHAR}
</if>
<if test="'id'.toString() == column.value">
#{item.id,jdbcType=VARCHAR}
</if>
<if test="'file_name'.toString() == column.value">
#{item.fileName,jdbcType=VARCHAR}
</if>

View File

@ -108,7 +108,7 @@ CREATE TABLE IF NOT EXISTS functional_case_attachment(
`local` BIT(1) NOT NULL COMMENT '是否本地' ,
`create_user` VARCHAR(50) NOT NULL COMMENT '创建人' ,
`create_time` BIGINT NOT NULL COMMENT '创建时间' ,
PRIMARY KEY (case_id,file_id)
PRIMARY KEY (id)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci COMMENT = '功能用例和附件的中间表';

View File

@ -213,6 +213,7 @@ public class PermissionConstants {
/*------ start: FUNCTIONAL_CASE ------*/
public static final String FUNCTIONAL_CASE_READ = "FUNCTIONAL_CASE:READ";
public static final String FUNCTIONAL_CASE_READ_ADD = "FUNCTIONAL_CASE:READ+ADD";
public static final String FUNCTIONAL_CASE_READ_UPDATE = "FUNCTIONAL_CASE:READ+UPDATE";
public static final String FUNCTIONAL_CASE_COMMENT_READ_ADD = "FUNCTIONAL_CASE_COMMENT:READ+ADD";
/*------ end: FUNCTIONAL_CASE ------*/

View File

@ -3,6 +3,7 @@ package io.metersphere.functional.controller;
import io.metersphere.functional.domain.FunctionalCase;
import io.metersphere.functional.dto.FunctionalCaseDetailDTO;
import io.metersphere.functional.request.FunctionalCaseAddRequest;
import io.metersphere.functional.request.FunctionalCaseEditRequest;
import io.metersphere.functional.service.FunctionalCaseService;
import io.metersphere.project.service.ProjectTemplateService;
import io.metersphere.sdk.constants.PermissionConstants;
@ -62,4 +63,14 @@ public class FunctionalCaseController {
public FunctionalCaseDetailDTO getFunctionalCaseDetail(@PathVariable String functionalCaseId) {
return functionalCaseService.getFunctionalCaseDetail(functionalCaseId);
}
@PostMapping("/update")
@Operation(summary = "功能用例-更新用例")
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ_UPDATE)
@Log(type = OperationLogType.UPDATE, expression = "#msClass.updateFunctionalCaseLog(#request, #files)", msClass = FunctionalCaseService.class)
public FunctionalCase updateFunctionalCase(@Validated @RequestPart("request") FunctionalCaseEditRequest request, @RequestPart(value = "files", required = false) List<MultipartFile> files) {
String userId = SessionUtils.getUserId();
return functionalCaseService.updateFunctionalCase(request, files, userId);
}
}

View File

@ -0,0 +1,36 @@
package io.metersphere.functional.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
* @author wx
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class FunctionalCaseAttachmentDTO implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "文件ID")
private String fileId;
@Schema(description = "文件名称")
private String fileName;
@Schema(description = "文件大小")
private Long size;
@Schema(description = "是否本地")
private Boolean local;
@Schema(description = "创建人")
private String createUser;
@Schema(description = "创建时间")
private Long createTime;
}

View File

@ -74,5 +74,6 @@ public class FunctionalCaseDetailDTO implements Serializable {
@Schema(description = "自定义字段属性")
private List<TemplateCustomFieldDTO> customFields;
@Schema(description = "附件信息")
private List<FunctionalCaseAttachmentDTO> attachments;
}

View File

@ -7,7 +7,6 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
@ -31,23 +30,23 @@ public class FunctionalCaseAddRequest implements Serializable {
@NotBlank(message = "{functional_case.name.not_blank}")
private String name;
@Schema(description = "前置条件")
@Schema(description = "前置条件", defaultValue = "")
private String prerequisite;
@Schema(description = "编辑模式", allowableValues = {"STEP", "TEXT"})
@NotBlank(message = "{functional_case.case_edit_type.not_blank}")
private String caseEditType;
@Schema(description = "用例步骤")
@Schema(description = "用例步骤", defaultValue = "")
private String steps;
@Schema(description = "步骤描述")
@Schema(description = "步骤描述", defaultValue = "")
private String textDescription;
@Schema(description = "预期结果")
@Schema(description = "预期结果", defaultValue = "")
private String expectedResult;
@Schema(description = "备注")
@Schema(description = "备注", defaultValue = "")
private String description;
@Schema(description = "是否公共用例库")
@ -70,7 +69,7 @@ public class FunctionalCaseAddRequest implements Serializable {
@Schema(description = "关联文件ID集合")
private List<String> relateFileMetaIds = new ArrayList<>();
private List<String> relateFileMetaIds;
}

View File

@ -0,0 +1,23 @@
package io.metersphere.functional.request;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
/**
* @author wx
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class FunctionalCaseEditRequest extends FunctionalCaseAddRequest{
@Schema(description = "用例id")
@NotBlank(message = "{functional_case.id.not_blank}")
private String id;
@Schema(description = "取消关联id")
private List<String> deleteFileMetaIds;
}

View File

@ -1,12 +1,18 @@
package io.metersphere.functional.service;
import com.google.common.collect.Lists;
import io.metersphere.functional.domain.FunctionalCaseAttachment;
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.project.domain.FileMetadata;
import io.metersphere.project.mapper.FileMetadataMapper;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.system.uid.IDGenerator;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
@ -57,16 +63,18 @@ public class FunctionalCaseAttachmentService {
* @param userId
*/
public void relateFileMeta(List<String> relateFileMetaIds, String caseId, String userId) {
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
FunctionalCaseAttachmentMapper sessionMapper = sqlSession.getMapper(FunctionalCaseAttachmentMapper.class);
relateFileMetaIds.forEach(fileMetaId -> {
FileMetadata fileMetadata = fileMetadataMapper.selectByPrimaryKey(fileMetaId);
FunctionalCaseAttachment caseAttachment = creatModule(fileMetadata.getId(), fileMetadata.getName(), fileMetadata.getSize(), caseId, false, userId);
sessionMapper.insertSelective(caseAttachment);
});
sqlSession.flushStatements();
if (sqlSession != null && sqlSessionFactory != null) {
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
if (CollectionUtils.isNotEmpty(relateFileMetaIds)) {
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
FunctionalCaseAttachmentMapper sessionMapper = sqlSession.getMapper(FunctionalCaseAttachmentMapper.class);
relateFileMetaIds.forEach(fileMetaId -> {
FileMetadata fileMetadata = fileMetadataMapper.selectByPrimaryKey(fileMetaId);
FunctionalCaseAttachment caseAttachment = creatModule(fileMetadata.getId(), fileMetadata.getName(), fileMetadata.getSize(), caseId, false, userId);
sessionMapper.insertSelective(caseAttachment);
});
sqlSession.flushStatements();
if (sqlSession != null && sqlSessionFactory != null) {
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
}
}
}
@ -82,4 +90,44 @@ public class FunctionalCaseAttachmentService {
caseAttachment.setCreateTime(System.currentTimeMillis());
return caseAttachment;
}
/**
* 获取附件信息
*
* @param functionalCaseDetailDTO
*/
public void getAttachmentInfo(FunctionalCaseDetailDTO functionalCaseDetailDTO) {
FunctionalCaseAttachmentExample example = new FunctionalCaseAttachmentExample();
example.createCriteria().andCaseIdEqualTo(functionalCaseDetailDTO.getId());
List<FunctionalCaseAttachment> caseAttachments = functionalCaseAttachmentMapper.selectByExample(example);
if (CollectionUtils.isNotEmpty(caseAttachments)) {
caseAttachments.stream().filter(caseAttachment -> !caseAttachment.getLocal()).forEach(caseAttachment -> {
FileMetadata fileMetadata = fileMetadataMapper.selectByPrimaryKey(caseAttachment.getFileId());
caseAttachment.setFileName(fileMetadata.getName());
});
}
List<FunctionalCaseAttachmentDTO> attachmentDTOs = Lists.transform(caseAttachments, (functionalCaseAttachment) -> {
FunctionalCaseAttachmentDTO attachmentDTO = new FunctionalCaseAttachmentDTO();
BeanUtils.copyBean(attachmentDTO, functionalCaseAttachment);
return attachmentDTO;
});
functionalCaseDetailDTO.setAttachments(attachmentDTOs);
}
/**
* 更新用例时删除文件 取消关联关系
*
* @param deleteFileMetaIds
*/
public List<FunctionalCaseAttachment> deleteCaseAttachment(List<String> deleteFileMetaIds, String caseId) {
FunctionalCaseAttachmentExample example = new FunctionalCaseAttachmentExample();
example.createCriteria().andFileIdIn(deleteFileMetaIds).andCaseIdEqualTo(caseId).andLocalEqualTo(true);
List<FunctionalCaseAttachment> delAttachment = functionalCaseAttachmentMapper.selectByExample(example);
example.clear();
example.createCriteria().andFileIdIn(deleteFileMetaIds).andCaseIdEqualTo(caseId);
functionalCaseAttachmentMapper.deleteByExample(example);
return delAttachment;
}
}

View File

@ -10,7 +10,10 @@ import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
@ -55,4 +58,45 @@ public class FunctionalCaseCustomFieldService {
}
return null;
}
/**
* 更新自定义字段
*
* @param caseId
* @param customsFields
*/
public void updateCustomField(String caseId, List<CaseCustomsFieldDTO> customsFields) {
List<String> fieldIds = customsFields.stream().map(CaseCustomsFieldDTO::getFieldId).collect(Collectors.toList());
FunctionalCaseCustomFieldExample example = new FunctionalCaseCustomFieldExample();
example.createCriteria().andFieldIdIn(fieldIds).andCaseIdEqualTo(caseId);
List<FunctionalCaseCustomField> defaultFields = functionalCaseCustomFieldMapper.selectByExample(example);
Map<String, FunctionalCaseCustomField> collect = defaultFields.stream().collect(Collectors.toMap(FunctionalCaseCustomField::getFieldId, (item) -> item));
List<CaseCustomsFieldDTO> addFields = new ArrayList<>();
List<CaseCustomsFieldDTO> updateFields = new ArrayList<>();
customsFields.forEach(customsField -> {
if (collect.containsKey(customsField.getFieldId())) {
updateFields.add(customsField);
} else {
addFields.add(customsField);
}
});
if (CollectionUtils.isNotEmpty(addFields)) {
saveCustomField(caseId, addFields);
}
;
if (CollectionUtils.isNotEmpty(updateFields)) {
updateField(caseId, updateFields);
}
}
private void updateField(String caseId, List<CaseCustomsFieldDTO> updateFields) {
updateFields.forEach(customsField -> {
FunctionalCaseCustomField customField = new FunctionalCaseCustomField();
customField.setCaseId(caseId);
customField.setFieldId(customsField.getFieldId());
customField.setValue(customsField.getValue());
functionalCaseCustomFieldMapper.updateByPrimaryKeySelective(customField);
});
}
}

View File

@ -1,6 +1,7 @@
package io.metersphere.functional.service;
import io.metersphere.functional.domain.FunctionalCase;
import io.metersphere.functional.domain.FunctionalCaseAttachment;
import io.metersphere.functional.domain.FunctionalCaseBlob;
import io.metersphere.functional.domain.FunctionalCaseCustomField;
import io.metersphere.functional.dto.CaseCustomsFieldDTO;
@ -9,20 +10,21 @@ import io.metersphere.functional.mapper.ExtFunctionalCaseMapper;
import io.metersphere.functional.mapper.FunctionalCaseBlobMapper;
import io.metersphere.functional.mapper.FunctionalCaseMapper;
import io.metersphere.functional.request.FunctionalCaseAddRequest;
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.system.log.dto.LogDTO;
import io.metersphere.system.dto.sdk.TemplateCustomFieldDTO;
import io.metersphere.system.dto.sdk.TemplateDTO;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.system.file.FileRequest;
import io.metersphere.system.file.MinioRepository;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.JSON;
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.log.constants.OperationLogModule;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.log.dto.LogDTO;
import io.metersphere.system.uid.IDGenerator;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
@ -68,17 +70,13 @@ public class FunctionalCaseService {
public FunctionalCase addFunctionalCase(FunctionalCaseAddRequest request, List<MultipartFile> files, String userId) {
String caseId = IDGenerator.nextStr();
//添加功能用例
FunctionalCase functionalCase = addTestCase(caseId, request, userId);
FunctionalCase functionalCase = addCase(caseId, request, userId);
//上传文件
if (CollectionUtils.isNotEmpty(files)) {
uploadFile(request, caseId, files, true, userId);
}
uploadFile(request, caseId, files, true, userId);
//关联附件
if (CollectionUtils.isNotEmpty(request.getRelateFileMetaIds())) {
functionalCaseAttachmentService.relateFileMeta(request.getRelateFileMetaIds(), caseId, userId);
}
functionalCaseAttachmentService.relateFileMeta(request.getRelateFileMetaIds(), caseId, userId);
return functionalCase;
}
@ -87,7 +85,7 @@ public class FunctionalCaseService {
*
* @param request
*/
private FunctionalCase addTestCase(String caseId, FunctionalCaseAddRequest request, String userId) {
private FunctionalCase addCase(String caseId, FunctionalCaseAddRequest request, String userId) {
FunctionalCase functionalCase = new FunctionalCase();
BeanUtils.copyBean(functionalCase, request);
functionalCase.setId(caseId);
@ -137,21 +135,22 @@ public class FunctionalCaseService {
* @param files
*/
public void uploadFile(FunctionalCaseAddRequest request, String caseId, List<MultipartFile> files, Boolean isLocal, String userId) {
files.forEach(file -> {
String fileId = IDGenerator.nextStr();
FileRequest fileRequest = new FileRequest();
fileRequest.setFileName(file.getName());
fileRequest.setProjectId(request.getProjectId());
fileRequest.setResourceId(MsFileUtils.FUNCTIONAL_CASE_ATTACHMENT_DIR + 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);
});
if (CollectionUtils.isNotEmpty(files)) {
files.forEach(file -> {
String fileId = IDGenerator.nextStr();
FileRequest fileRequest = new FileRequest();
fileRequest.setFileName(file.getName());
fileRequest.setProjectId(request.getProjectId());
fileRequest.setResourceId(MsFileUtils.FUNCTIONAL_CASE_ATTACHMENT_DIR + "/" + 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);
});
}
}
@ -174,6 +173,9 @@ public class FunctionalCaseService {
//模板校验 获取自定义字段
functionalCaseDetailDTO = checkTemplateCustomField(functionalCaseDetailDTO, functionalCase);
//获取附件信息
functionalCaseAttachmentService.getAttachmentInfo(functionalCaseDetailDTO);
return functionalCaseDetailDTO;
}
@ -201,6 +203,72 @@ public class FunctionalCaseService {
}
/**
* 更新用例 基本信息
*
* @param request
* @param files
* @param userId
* @return
*/
public FunctionalCase updateFunctionalCase(FunctionalCaseEditRequest request, List<MultipartFile> files, String userId) {
//基本信息
FunctionalCase functionalCase = new FunctionalCase();
BeanUtils.copyBean(functionalCase, request);
updateCase(request, userId, functionalCase);
//处理删除文件id
if (CollectionUtils.isNotEmpty(request.getDeleteFileMetaIds())) {
this.deleteFile(request.getDeleteFileMetaIds(), request);
}
//上传新文件
uploadFile(request, request.getId(), files, true, userId);
//关联新附件
functionalCaseAttachmentService.relateFileMeta(request.getRelateFileMetaIds(), request.getId(), userId);
return functionalCase;
}
private void deleteFile(List<String> deleteFileMetaIds, FunctionalCaseEditRequest request) {
List<FunctionalCaseAttachment> caseAttachments = functionalCaseAttachmentService.deleteCaseAttachment(deleteFileMetaIds, request.getId());
if (CollectionUtils.isNotEmpty(caseAttachments)) {
//删除本地上传的minio文件
deleteMinioFile(caseAttachments, request.getProjectId());
}
}
private void deleteMinioFile(List<FunctionalCaseAttachment> files, String projectId) {
files.forEach(file -> {
FileRequest fileRequest = new FileRequest();
fileRequest.setFileName(file.getFileName());
fileRequest.setProjectId(projectId);
fileRequest.setResourceId(MsFileUtils.FUNCTIONAL_CASE_ATTACHMENT_DIR + "/" + 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) {
//更新用例
functionalCaseMapper.updateByPrimaryKeySelective(functionalCase);
//更新附属表信息
FunctionalCaseBlob functionalCaseBlob = new FunctionalCaseBlob();
BeanUtils.copyBean(functionalCaseBlob, request);
functionalCaseBlobMapper.updateByPrimaryKeySelective(functionalCaseBlob);
//更新自定义字段
functionalCaseCustomFieldService.updateCustomField(request.getId(), request.getCustomsFields());
}
//TODO 日志
/**
* 新增用例 日志
*
@ -223,4 +291,29 @@ public class FunctionalCaseService {
dto.setOriginalValue(JSON.toJSONBytes(requests));
return dto;
}
/**
* 更新用例 日志
*
* @param requests
* @param files
* @return
*/
public LogDTO updateFunctionalCaseLog(FunctionalCaseAddRequest requests, List<MultipartFile> files) {
//TODO 获取原值
LogDTO dto = new LogDTO(
requests.getProjectId(),
null,
null,
null,
OperationLogType.UPDATE.name(),
OperationLogModule.FUNCTIONAL_CASE,
requests.getName());
dto.setPath("/functional/case/update");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setModifiedValue(JSON.toJSONBytes(requests));
return dto;
}
}

View File

@ -2,6 +2,7 @@ package io.metersphere.functional.controller;
import io.metersphere.functional.dto.CaseCustomsFieldDTO;
import io.metersphere.functional.request.FunctionalCaseAddRequest;
import io.metersphere.functional.request.FunctionalCaseEditRequest;
import io.metersphere.functional.result.FunctionalCaseResultCode;
import io.metersphere.functional.utils.FileBaseUtils;
import io.metersphere.sdk.util.JSON;
@ -30,7 +31,8 @@ public class FunctionalCaseControllerTests extends BaseTest {
public static final String FUNCTIONAL_CASE_ADD_URL = "/functional/case/add";
public static final String DEFAULT_TEMPLATE_FIELD_URL = "/functional/case/default/template/field/";
public static final String FUNCTIONAL_CASE_DETAIL_URL = "/functional/case//detail/";
public static final String FUNCTIONAL_CASE_DETAIL_URL = "/functional/case/detail/";
public static final String FUNCTIONAL_CASE_UPDATE_URL = "/functional/case/update";
@Test
@Order(1)
@ -112,4 +114,57 @@ public class FunctionalCaseControllerTests extends BaseTest {
}
@Test
@Order(3)
public void testUpdateFunctionalCase() throws Exception {
FunctionalCaseEditRequest request = creatEditRequest();
//设置自定义字段
List<CaseCustomsFieldDTO> list = updateCustomsFields(request);
request.setCustomsFields(list);
LinkedMultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
List<MockMultipartFile> files = new ArrayList<>();
paramMap.add("request", JSON.toJSONString(request));
paramMap.add("files", files);
MvcResult mvcResult = this.requestMultipartWithOkAndReturn(FUNCTIONAL_CASE_UPDATE_URL, paramMap);
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
Assertions.assertNotNull(resultHolder);
//设置删除文件id
request.setDeleteFileMetaIds(Arrays.asList("delete_file_meta_id_1"));
paramMap = new LinkedMultiValueMap<>();
paramMap.add("request", JSON.toJSONString(request));
paramMap.add("files", files);
MvcResult updateResult = this.requestMultipartWithOkAndReturn(FUNCTIONAL_CASE_UPDATE_URL, paramMap);
String updateReturnData = updateResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder updateResultHolder = JSON.parseObject(updateReturnData, ResultHolder.class);
Assertions.assertNotNull(updateResultHolder);
}
private List<CaseCustomsFieldDTO> updateCustomsFields(FunctionalCaseEditRequest editRequest) {
List<CaseCustomsFieldDTO> list = new ArrayList<>() {{
add(new CaseCustomsFieldDTO() {{
setFieldId("customs_field_id_1");
setValue("测试更新");
}});
add(new CaseCustomsFieldDTO() {{
setFieldId("customs_field_id_2");
setValue("更新时存在新字段");
}});
}};
return list;
}
private FunctionalCaseEditRequest creatEditRequest() {
FunctionalCaseEditRequest editRequest = new FunctionalCaseEditRequest();
editRequest.setProjectId(DEFAULT_PROJECT_ID);
editRequest.setTemplateId("default_template_id");
editRequest.setName("测试用例编辑");
editRequest.setCaseEditType("STEP");
editRequest.setModuleId("default_module_id");
editRequest.setId("TEST_FUNCTIONAL_CASE_ID");
editRequest.setSteps("");
return editRequest;
}
}

View File

@ -9,3 +9,9 @@ INSERT INTO functional_case_blob(id, steps, text_description, expected_result, p
INSERT INTO functional_case_custom_field(case_id, field_id, value) VALUES ('TEST_FUNCTIONAL_CASE_ID', '100548878725546079', '22');
INSERT INTO functional_case_attachment(id, case_id, file_id, file_name, size, local, create_user, create_time) VALUES ('TEST_CASE_ATTACHMENT_ID', 'TEST_FUNCTIONAL_CASE_ID', '100548878725546079', '测试', 1, b'1', 'admin', 1698058347559);
INSERT INTO functional_case_attachment(id, case_id, file_id, file_name, size, local, create_user, create_time) VALUES ('TEST_CASE_ATTACHMENT_ID_1', 'TEST_FUNCTIONAL_CASE_ID', 'relate_file_meta_id_1', '测试1', 1, b'0', 'admin', 1698058347559);
INSERT INTO functional_case_attachment(id, case_id, file_id, file_name, size, local, create_user, create_time) VALUES ('TEST_CASE_ATTACHMENT_ID_2', 'TEST_FUNCTIONAL_CASE_ID', 'delete_file_meta_id_1', '测试删除', 1, b'1', 'admin', 1698058347559);