refactor(用例管理): 自定义字段接口返回新增选项值@列表查询条件

This commit is contained in:
WangXu10 2023-11-16 18:02:40 +08:00 committed by Craftsman
parent 781f09c2aa
commit d67cd54ac7
13 changed files with 300 additions and 65 deletions

View File

@ -0,0 +1,26 @@
package io.metersphere.functional.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.List;
/**
* @author wx
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class AssociationDTO implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "类型",allowableValues = {"EMPTY","NOT_EMPTY"})
private String operatorType;
@Schema(description = "用例类型",allowableValues = {"API","API_SCENARIO","UI_SCENARIO","LOAD"})
private List<String> caseType;
}

View File

@ -0,0 +1,31 @@
package io.metersphere.functional.dto;
import io.metersphere.system.dto.table.TableBatchProcessDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.List;
/**
* @author wx
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class BaseFunctionalCaseBatchDTO extends TableBatchProcessDTO implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "模块id")
private List<String> moduleIds;
@Schema(description = "匹配模式 所有/任一", allowableValues = {"AND", "OR"})
private String searchMode = "AND";
@Schema(description = "版本id")
private String versionId;
@Schema(description = "版本来源")
private String refId;
}

View File

@ -1,11 +1,11 @@
package io.metersphere.functional.mapper;
import io.metersphere.functional.domain.FunctionalCase;
import io.metersphere.functional.dto.BaseFunctionalCaseBatchDTO;
import io.metersphere.functional.dto.FunctionalCasePageDTO;
import io.metersphere.functional.dto.FunctionalCaseVersionDTO;
import io.metersphere.functional.request.FunctionalCaseBatchMoveRequest;
import io.metersphere.functional.request.FunctionalCasePageRequest;
import io.metersphere.system.dto.table.TableBatchProcessDTO;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@ -32,7 +32,7 @@ public interface ExtFunctionalCaseMapper {
void recoverCase(@Param("ids") List<String> ids, @Param("userId") String userId, @Param("time") long time);
List<String> getIds(@Param("request") TableBatchProcessDTO request, @Param("projectId") String projectId, @Param("deleted") boolean deleted);
List<String> getIds(@Param("request") BaseFunctionalCaseBatchDTO request, @Param("projectId") String projectId, @Param("deleted") boolean deleted);
void batchDelete(@Param("ids") List<String> ids, @Param("userId") String userId);

View File

@ -84,7 +84,17 @@
FROM
functional_case
where deleted = #{deleted}
<include refid="queryWhereCondition"/>
and functional_case.project_id = #{request.projectId}
<choose>
<when test='request.searchMode == "AND"'>
AND <include refid="queryWhereCondition"/>
</when>
<when test='request.searchMode == "OR"'>
and (
<include refid="queryWhereCondition"/>
)
</when>
</choose>
</select>
@ -102,21 +112,24 @@
</update>
<sql id="queryWhereCondition">
<if test="request.projectId != null">
and functional_case.project_id = #{request.projectId}
</if>
<if test="request.moduleIds != null and request.moduleIds.size() > 0">
and functional_case.module_id in
functional_case.module_id in
<foreach collection="request.moduleIds" item="moduleId" separator="," open="(" close=")">
#{moduleId}
</foreach>
<include refid="queryType">
<property name="searchMode" value="request.searchMode"/>
</include>
</if>
<if test="request.keyword != null">
and (
(
functional_case.name like concat('%', #{request.keyword},'%')
or functional_case.num like concat('%', #{request.keyword},'%')
or functional_case.tags like JSON_CONTAINS(tags, concat('["',#{request.keyword},'"]'))
or JSON_CONTAINS(tags, concat('["',#{request.keyword},'"]'))
)
<include refid="queryType">
<property name="searchMode" value="request.searchMode"/>
</include>
</if>
<include refid="filters">
<property name="filter" value="request.filter"/>
@ -124,6 +137,8 @@
<include refid="combine">
<property name="condition" value="request.combine"/>
</include>
<include refid="queryAssociationCase"/>
<include refid="queryAssociationBug"/>
<include refid="queryVersionCondition">
<property name="versionTable" value="functional_case"/>
</include>
@ -135,34 +150,52 @@
<if test="values != null and values.size() > 0">
<choose>
<when test="key=='review_status'">
and functional_case.review_status in
functional_case.review_status in
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
<include refid="queryType">
<property name="searchMode" value="request.searchMode"/>
</include>
</when>
<when test="key=='last_execute_result'">
and functional_case.last_execute_result in
functional_case.last_execute_result in
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
<include refid="queryType">
<property name="searchMode" value="request.searchMode"/>
</include>
</when>
<when test="key=='version_id'">
and functional_case.version_id in
functional_case.version_id in
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
<include refid="queryType">
<property name="searchMode" value="request.searchMode"/>
</include>
</when>
<when test="key.startsWith('custom_single')">
and test_case.id in (
test_case.id in (
select resource_id from custom_field_test_case where concat('custom_single-',field_id) =
#{key}
and trim(both '"' from `value`) in
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
)
<include refid="queryType">
<property name="searchMode" value="request.searchMode"/>
</include>
</when>
<when test="key.startsWith('custom_multiple')">
and test_case.id in (
test_case.id in (
select resource_id from custom_field_test_case where concat('custom_multiple-',field_id) =
#{key}
and and JSON_CONTAINS(`value`, json_array(#{value}))
and JSON_CONTAINS(`value`, json_array(#{value}))
<include refid="queryType">
<property name="searchMode" value="request.searchMode"/>
</include>
</when>
<when test="key=='create_user'">
and functional_case.create_user in
functional_case.create_user in
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
<include refid="queryType">
<property name="searchMode" value="request.searchMode"/>
</include>
</when>
</choose>
</if>
@ -173,20 +206,26 @@
<sql id="combine">
<if test="request.combine != null">
<if test='${condition}.name != null'>
and functional_case.name
functional_case.name
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="${condition}.name"/>
</include>
<include refid="queryType">
<property name="searchMode" value="request.searchMode"/>
</include>
</if>
<if test='${condition}.id != null'>
and functional_case.num
functional_case.num
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="${condition}.id"/>
</include>
<include refid="queryType">
<property name="searchMode" value="request.searchMode"/>
</include>
</if>
<if test="${condition}.customs != null and ${condition}.customs.size() > 0">
<foreach collection="${condition}.customs" item="custom" separator="" open="" close="">
and functional_case.id ${custom.operator} (
functional_case.id ${custom.operator} (
select case_id from functional_case_custom_field where field_id = #{custom.id}
<choose>
<when test="custom.type == 'List'">
@ -206,6 +245,9 @@
</otherwise>
</choose>
)
<include refid="queryType">
<property name="searchMode" value="request.searchMode"/>
</include>
</foreach>
</if>
</if>
@ -213,16 +255,99 @@
<sql id="queryVersionCondition">
<if test="request.versionId != null">
and ${versionTable}.version_id = #{request.versionId}
${versionTable}.version_id = #{request.versionId}
</if>
<if test="request.refId != null">
and ${versionTable}.ref_id = #{request.refId}
${versionTable}.ref_id = #{request.refId}
</if>
<if test="request.versionId == null and request.refId == null">
AND ${versionTable}.latest = 1
${versionTable}.latest = 1
</if>
</sql>
<sql id="queryAssociationCase">
<if test="request.associationCase != null">
<choose>
<when test="request.associationCase.operatorType == 'EMPTY'">
functional_case.id not in (
select functional_case.id from functional_case LEFT JOIN functional_case_test on functional_case.id
= functional_case_test.case_id where functional_case_test.source_type in
<foreach collection="request.associationCase.caseType" item="item" open="(" separator="," close=")">
#{item}
</foreach>
and functional_case.project_id=#{request.projectId} and functional_case.deleted = false and
<include refid="queryVersionCondition">
<property name="versionTable" value="functional_case"/>
</include>
)
<include refid="queryType">
<property name="searchMode" value="request.searchMode"/>
</include>
</when>
<when test="request.associationCase.operatorType == 'NOT_EMPTY'">
functional_case.id in (
select functional_case.id from functional_case LEFT JOIN functional_case_test on functional_case.id
= functional_case_test.case_id where functional_case_test.source_type in
<foreach collection="request.associationCase.caseType" item="item" open="(" separator="," close=")">
#{item}
</foreach>
and functional_case.project_id=#{request.projectId} and functional_case.deleted = false and
<include refid="queryVersionCondition">
<property name="versionTable" value="functional_case"/>
</include>
)
<include refid="queryType">
<property name="searchMode" value="request.searchMode"/>
</include>
</when>
</choose>
</if>
</sql>
<sql id="queryAssociationBug">
<if test="request.associationBug != null">
<choose>
<when test="request.associationBug.operatorType == 'EMPTY'">
functional_case.id not in (
select functional_case.id from functional_case LEFT JOIN bug_relation_case on functional_case.id =
bug_relation_case.case_id where bug_relation_case.case_type = 'functional'
and functional_case.project_id=#{request.projectId} and functional_case.deleted = false and
<include refid="queryVersionCondition">
<property name="versionTable" value="functional_case"/>
</include>
)
<include refid="queryType">
<property name="searchMode" value="request.searchMode"/>
</include>
</when>
<when test="request.associationBug.operatorType == 'NOT_EMPTY'">
functional_case.id in (
select functional_case.id from functional_case LEFT JOIN bug_relation_case on functional_case.id =
bug_relation_case.case_id where bug_relation_case.case_type = 'functional'
and functional_case.project_id=#{request.projectId} and functional_case.deleted = false and
<include refid="queryVersionCondition">
<property name="versionTable" value="functional_case"/>
</include>
)
<include refid="queryType">
<property name="searchMode" value="request.searchMode"/>
</include>
</when>
</choose>
</if>
</sql>
<sql id="queryType">
<choose>
<when test='${searchMode} == "AND"'>
AND
</when>
<when test='${searchMode} == "OR"'>
OR
</when>
</choose>
</sql>
<select id="getIds" resultType="java.lang.String">
@ -231,30 +356,51 @@
FROM
functional_case
WHERE
project_id = #{projectId}
and deleted = #{deleted}
<include refid="queryWhereConditionByBaseQueryRequest"/>
functional_case.project_id = #{projectId}
and functional_case.deleted = #{deleted}
<choose>
<when test='request.searchMode == "AND"'>
AND <include refid="queryWhereConditionByBaseQueryRequest"/>
</when>
<when test='request.searchMode == "OR"'>
and (
<include refid="queryWhereConditionByBaseQueryRequest"/>
)
</when>
</choose>
</select>
<sql id="queryWhereConditionByBaseQueryRequest">
<where>
<if test="request.condition.combine != null">
<include refid="combine">
<property name="condition" value="request.condition.combine"/>
</include>
</if>
<if test="request.condition.keyword != null">
and (
functional_case.name like concat('%', #{request.keyword},'%')
or functional_case.num like concat('%', #{request.keyword},'%')
or functional_case.tags like JSON_CONTAINS(tags, concat('["',#{request.keyword},'"]'))
)
</if>
<include refid="filters">
<property name="filter" value="request.condition.filter"/>
<if test="request.moduleIds != null and request.moduleIds.size() > 0">
functional_case.module_id in
<foreach collection="request.moduleIds" item="moduleId" separator="," open="(" close=")">
#{moduleId}
</foreach>
<include refid="queryType">
<property name="searchMode" value="request.searchMode"/>
</include>
</where>
</if>
<if test="request.condition.keyword != null">
(
functional_case.name like concat('%', #{request.keyword},'%')
or functional_case.num like concat('%', #{request.keyword},'%')
or JSON_CONTAINS(tags, concat('["',#{request.keyword},'"]'))
)
<include refid="queryType">
<property name="searchMode" value="request.searchMode"/>
</include>
</if>
<include refid="filters">
<property name="filter" value="request.condition.filter"/>
</include>
<if test="request.condition.combine != null">
<include refid="combine">
<property name="condition" value="request.condition.combine"/>
</include>
</if>
<include refid="queryVersionCondition">
<property name="versionTable" value="functional_case"/>
</include>
</sql>
<select id="getRefIds" resultType="java.lang.String">

View File

@ -1,12 +1,11 @@
package io.metersphere.functional.request;
import io.metersphere.functional.dto.BaseFunctionalCaseBatchDTO;
import io.metersphere.functional.dto.CaseCustomFieldDTO;
import io.metersphere.system.dto.table.TableBatchProcessDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.List;
/**
@ -14,9 +13,8 @@ import java.util.List;
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class FunctionalCaseBatchEditRequest extends TableBatchProcessDTO implements Serializable {
public class FunctionalCaseBatchEditRequest extends BaseFunctionalCaseBatchDTO {
private static final long serialVersionUID = 1L;
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
private String projectId;

View File

@ -1,20 +1,17 @@
package io.metersphere.functional.request;
import io.metersphere.system.dto.table.TableBatchProcessDTO;
import io.metersphere.functional.dto.BaseFunctionalCaseBatchDTO;
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 FunctionalCaseBatchRequest extends TableBatchProcessDTO implements Serializable {
public class FunctionalCaseBatchRequest extends BaseFunctionalCaseBatchDTO {
private static final long serialVersionUID = 1L;
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
private String projectId;

View File

@ -1,5 +1,6 @@
package io.metersphere.functional.request;
import io.metersphere.functional.dto.AssociationDTO;
import io.metersphere.system.dto.sdk.BasePageRequest;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
@ -29,4 +30,18 @@ public class FunctionalCasePageRequest extends BasePageRequest {
@Schema(description = "模块id")
private List<String> moduleIds;
@Schema(description = "匹配模式 所有/任一", allowableValues = {"AND", "OR"})
private String searchMode = "AND";
@Schema(description = "关联用例")
private AssociationDTO associationCase;
@Schema(description = "关联需求")
private AssociationDTO associationDemand;
@Schema(description = "关联缺陷")
private AssociationDTO associationBug;
}

View File

@ -52,6 +52,8 @@ public class FunctionalCaseAttachmentService {
@Resource
private MinioRepository minioRepository;
public static final String UPLOAD_SOURCE_DIR = "/project";
/**
* 保存本地上传文件和用例关联关系
*
@ -79,7 +81,7 @@ public class FunctionalCaseAttachmentService {
String fileId = IDGenerator.nextStr();
FileRequest fileRequest = new FileRequest();
fileRequest.setFileName(file.getName());
fileRequest.setResourceId(MsFileUtils.FUNCTIONAL_CASE_DIR_NAME + "/" + request.getProjectId() + fileId);
fileRequest.setResourceId(UPLOAD_SOURCE_DIR + "/" + request.getProjectId() + "/" + MsFileUtils.FUNCTIONAL_CASE_DIR_NAME + "/" + fileId);
fileRequest.setStorage(StorageType.MINIO.name());
try {
minioRepository.saveFile(file, fileRequest);
@ -174,7 +176,7 @@ public class FunctionalCaseAttachmentService {
files.forEach(file -> {
FileRequest fileRequest = new FileRequest();
fileRequest.setFileName(file.getFileName());
fileRequest.setResourceId(MsFileUtils.FUNCTIONAL_CASE_DIR_NAME + "/" + projectId + file.getFileId());
fileRequest.setResourceId(UPLOAD_SOURCE_DIR + "/" + projectId + "/" + MsFileUtils.FUNCTIONAL_CASE_DIR_NAME + "/" + file.getFileId());
fileRequest.setStorage(StorageType.MINIO.name());
try {
minioRepository.delete(fileRequest);

View File

@ -1,10 +1,7 @@
package io.metersphere.functional.service;
import io.metersphere.functional.domain.*;
import io.metersphere.functional.dto.CaseCustomFieldDTO;
import io.metersphere.functional.dto.FunctionalCaseDetailDTO;
import io.metersphere.functional.dto.FunctionalCasePageDTO;
import io.metersphere.functional.dto.FunctionalCaseVersionDTO;
import io.metersphere.functional.dto.*;
import io.metersphere.functional.mapper.*;
import io.metersphere.functional.request.*;
import io.metersphere.functional.result.FunctionalCaseResultCode;
@ -19,7 +16,6 @@ import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.dto.sdk.TemplateCustomFieldDTO;
import io.metersphere.system.dto.sdk.TemplateDTO;
import io.metersphere.system.dto.table.TableBatchProcessDTO;
import io.metersphere.system.uid.IDGenerator;
import io.metersphere.system.uid.NumGenerator;
import jakarta.annotation.Resource;
@ -394,7 +390,7 @@ public class FunctionalCaseService {
public <T> List<String> doSelectIds(T dto, String projectId) {
TableBatchProcessDTO request = (TableBatchProcessDTO) dto;
BaseFunctionalCaseBatchDTO request = (BaseFunctionalCaseBatchDTO) dto;
if (request.isSelectAll()) {
List<String> ids = extFunctionalCaseMapper.getIds(request, projectId, false);
if (CollectionUtils.isNotEmpty(request.getExcludeIds())) {

View File

@ -118,6 +118,7 @@ public class FunctionalCaseControllerTests extends BaseTest {
@Order(3)
public void testFunctionalCaseDetail() throws Exception {
assertErrorCode(this.requestGet(FUNCTIONAL_CASE_DETAIL_URL + "ERROR_TEST_FUNCTIONAL_CASE_ID"), FunctionalCaseResultCode.FUNCTIONAL_CASE_NOT_FOUND);
this.requestGetWithOkAndReturn(FUNCTIONAL_CASE_DETAIL_URL + "TEST_FUNCTIONAL_CASE_ID_1");
MvcResult mvcResult = this.requestGetWithOkAndReturn(FUNCTIONAL_CASE_DETAIL_URL + "TEST_FUNCTIONAL_CASE_ID");
// 获取返回值
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
@ -262,7 +263,7 @@ public class FunctionalCaseControllerTests extends BaseTest {
//自定义字段 测试
Map<String, Object> map = new HashMap<>();
map.put("custom", Arrays.asList(new LinkedHashMap() {{
map.put("customs", Arrays.asList(new LinkedHashMap() {{
put("id", "TEST_FIELD_ID");
put("operator", "in");
put("value", "222");
@ -370,7 +371,7 @@ public class FunctionalCaseControllerTests extends BaseTest {
request.setTags(Arrays.asList("覆盖标签1", "覆盖标签2"));
request.setSelectAll(true);
CaseCustomFieldDTO caseCustomFieldDTO = new CaseCustomFieldDTO();
caseCustomFieldDTO.setFieldId("TEST_FIELD_ID");
caseCustomFieldDTO.setFieldId("TEST_FIELD_ID_1");
caseCustomFieldDTO.setValue("批量编辑自定义字段");
request.setCustomField(caseCustomFieldDTO);
this.requestPostWithOkAndReturn(FUNCTIONAL_CASE_BATCH_EDIT_URL, request);

View File

@ -37,6 +37,7 @@ 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_custom_field(case_id, field_id, value) VALUES ('TEST_FUNCTIONAL_CASE_ID', 'TEST_FIELD_ID', '["222","333"]');
INSERT INTO functional_case_custom_field(case_id, field_id, value) VALUES ('TEST_FUNCTIONAL_CASE_ID', 'TEST_FIELD_ID_1', '["222","333"]');
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);

View File

@ -1,8 +1,11 @@
package io.metersphere.system.dto.sdk;
import io.metersphere.system.domain.CustomFieldOption;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Data
public class TemplateCustomFieldDTO {
@ -21,4 +24,7 @@ public class TemplateCustomFieldDTO {
@Schema(title = "默认值")
private Object defaultValue;
@Schema(title = "选项值")
private List<CustomFieldOption> options;
}

View File

@ -6,10 +6,7 @@ import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.LogUtils;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.domain.CustomField;
import io.metersphere.system.domain.Template;
import io.metersphere.system.domain.TemplateCustomField;
import io.metersphere.system.domain.TemplateExample;
import io.metersphere.system.domain.*;
import io.metersphere.system.dto.sdk.TemplateCustomFieldDTO;
import io.metersphere.system.dto.sdk.TemplateDTO;
import io.metersphere.system.dto.sdk.request.TemplateCustomFieldRequest;
@ -50,6 +47,9 @@ public class BaseTemplateService {
@Resource
protected BaseCustomFieldService baseCustomFieldService;
@Resource
private BaseCustomFieldOptionService baseCustomFieldOptionService;
public List<Template> list(String scopeId, String scene) {
checkScene(scene);
List<Template> templates = getTemplates(scopeId, scene);
@ -130,6 +130,14 @@ public class BaseTemplateService {
return templateCustomFieldDTO;
}).toList();
List<String> ids = fieldDTOS.stream().map(TemplateCustomFieldDTO::getFieldId).toList();
List<CustomFieldOption> fieldOptions = baseCustomFieldOptionService.getByFieldIds(ids);
Map<String, List<CustomFieldOption>> collect = fieldOptions.stream().collect(Collectors.groupingBy(CustomFieldOption::getFieldId));
fieldDTOS.forEach(item -> {
item.setOptions(collect.get(item.getFieldId()));
});
// 封装系统字段信息
List<TemplateCustomFieldDTO> systemFieldDTOS = templateCustomFields.stream()
.filter(i -> BooleanUtils.isTrue(i.getSystemField()))
@ -140,6 +148,14 @@ public class BaseTemplateService {
return templateCustomFieldDTO;
}).toList();
List<String> sysIds = systemFieldDTOS.stream().map(TemplateCustomFieldDTO::getFieldId).toList();
List<CustomFieldOption> sysFieldOptions = baseCustomFieldOptionService.getByFieldIds(sysIds);
Map<String, List<CustomFieldOption>> sysCollect = sysFieldOptions.stream().collect(Collectors.groupingBy(CustomFieldOption::getFieldId));
systemFieldDTOS.forEach(item -> {
item.setOptions(sysCollect.get(item.getFieldId()));
});
TemplateDTO templateDTO = BeanUtils.copyBean(new TemplateDTO(), template);
templateDTO.setCustomFields(fieldDTOS);
templateDTO.setSystemFields(systemFieldDTOS);