feat(功能用例): 变更历史

This commit is contained in:
guoyuqi 2024-01-25 19:51:59 +08:00 committed by Craftsman
parent 3927bb271b
commit 8e0ff36aef
8 changed files with 132 additions and 1 deletions

View File

@ -17,6 +17,8 @@ import io.metersphere.project.dto.CustomFieldOptions;
import io.metersphere.project.service.ProjectTemplateService; import io.metersphere.project.service.ProjectTemplateService;
import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.sdk.constants.TemplateScene; import io.metersphere.sdk.constants.TemplateScene;
import io.metersphere.system.dto.OperationHistoryDTO;
import io.metersphere.system.dto.request.OperationHistoryRequest;
import io.metersphere.system.dto.sdk.TemplateDTO; import io.metersphere.system.dto.sdk.TemplateDTO;
import io.metersphere.system.dto.sdk.request.PosRequest; import io.metersphere.system.dto.sdk.request.PosRequest;
import io.metersphere.system.log.annotation.Log; import io.metersphere.system.log.annotation.Log;
@ -236,4 +238,14 @@ public class FunctionalCaseController {
String organizationId = SessionUtils.getCurrentOrganizationId(); String organizationId = SessionUtils.getCurrentOrganizationId();
return functionalCaseFileService.importExcel(request, userId, file, organizationId); return functionalCaseFileService.importExcel(request, userId, file, organizationId);
} }
@PostMapping("/operation-history")
@Operation(summary = "用例管理-功能用例-变更历史")
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ)
@CheckOwner(resourceId = "#request.getSourceId()", resourceType = "functional_case")
public Pager<List<OperationHistoryDTO>> operationHistoryList(@Validated @RequestBody OperationHistoryRequest request) {
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
org.apache.commons.lang3.StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "create_time desc");
return PageUtils.setPageInfo(page, functionalCaseService.operationHistoryList(request));
}
} }

View File

@ -28,9 +28,12 @@ import io.metersphere.sdk.constants.HttpMethodConstants;
import io.metersphere.sdk.constants.TemplateScene; import io.metersphere.sdk.constants.TemplateScene;
import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.BeanUtils; import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.CommonBeanFactory;
import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.Translator; import io.metersphere.sdk.util.Translator;
import io.metersphere.system.domain.CustomFieldOption; import io.metersphere.system.domain.CustomFieldOption;
import io.metersphere.system.dto.OperationHistoryDTO;
import io.metersphere.system.dto.request.OperationHistoryRequest;
import io.metersphere.system.dto.sdk.BaseTreeNode; import io.metersphere.system.dto.sdk.BaseTreeNode;
import io.metersphere.system.dto.sdk.TemplateCustomFieldDTO; import io.metersphere.system.dto.sdk.TemplateCustomFieldDTO;
import io.metersphere.system.dto.sdk.TemplateDTO; import io.metersphere.system.dto.sdk.TemplateDTO;
@ -116,6 +119,8 @@ public class FunctionalCaseService {
private static final String UPDATE_FUNCTIONAL_CASE_FILE_LOG_URL = "/functional/case/update"; 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"; private static final String FUNCTIONAL_CASE_BATCH_COPY_FILE_LOG_URL = "/functional/case/batch/copy";
private static final String CASE_TABLE = "functional_case";
@Resource @Resource
private FunctionalCaseDemandMapper functionalCaseDemandMapper; private FunctionalCaseDemandMapper functionalCaseDemandMapper;
@Resource @Resource
@ -1030,4 +1035,12 @@ public class FunctionalCaseService {
FunctionalCaseHistoryLogDTO historyLogDTO = new FunctionalCaseHistoryLogDTO(functionalCase, functionalCaseBlob, customFields, caseAttachments, fileAssociationList); FunctionalCaseHistoryLogDTO historyLogDTO = new FunctionalCaseHistoryLogDTO(functionalCase, functionalCaseBlob, customFields, caseAttachments, fileAssociationList);
return historyLogDTO; return historyLogDTO;
} }
public List<OperationHistoryDTO> operationHistoryList(OperationHistoryRequest request) {
XpackFunctionalCaseService functionalCaseService = CommonBeanFactory.getBean(XpackFunctionalCaseService.class);
if (functionalCaseService != null) {
return functionalCaseService.listHis(request, CASE_TABLE);
}
return List.of();
}
} }

View File

@ -0,0 +1,19 @@
package io.metersphere.functional.service;
import io.metersphere.system.dto.OperationHistoryDTO;
import io.metersphere.system.dto.request.OperationHistoryRequest;
import java.util.List;
/**
* 用例管理Xpack功能接口
*/
public interface XpackFunctionalCaseService {
/**
* 功能用例变更历史分页列表
* @param request 请求参数
* @return 变更历史集合
*/
List<OperationHistoryDTO> listHis(OperationHistoryRequest request,String table);
}

View File

@ -1,5 +1,6 @@
package io.metersphere.functional.config; package io.metersphere.functional.config;
import io.metersphere.functional.service.XpackFunctionalCaseService;
import io.metersphere.provider.BaseAssociateApiProvider; import io.metersphere.provider.BaseAssociateApiProvider;
import io.metersphere.provider.BaseAssociateBugProvider; import io.metersphere.provider.BaseAssociateBugProvider;
import io.metersphere.provider.BaseAssociateScenarioProvider; import io.metersphere.provider.BaseAssociateScenarioProvider;
@ -18,4 +19,7 @@ public class CaseTestConfiguration {
@MockBean @MockBean
BaseAssociateBugProvider baseAssociateBugProvider; BaseAssociateBugProvider baseAssociateBugProvider;
@MockBean
XpackFunctionalCaseService xpackFunctionalCaseService;
} }

View File

@ -24,14 +24,18 @@ import io.metersphere.sdk.util.Translator;
import io.metersphere.system.base.BaseTest; import io.metersphere.system.base.BaseTest;
import io.metersphere.system.controller.handler.ResultHolder; import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.domain.CustomField; import io.metersphere.system.domain.CustomField;
import io.metersphere.system.dto.OperationHistoryDTO;
import io.metersphere.system.dto.request.OperationHistoryRequest;
import io.metersphere.system.dto.sdk.TemplateCustomFieldDTO; import io.metersphere.system.dto.sdk.TemplateCustomFieldDTO;
import io.metersphere.system.dto.sdk.TemplateDTO; import io.metersphere.system.dto.sdk.TemplateDTO;
import io.metersphere.system.dto.sdk.request.PosRequest; import io.metersphere.system.dto.sdk.request.PosRequest;
import io.metersphere.system.mapper.CustomFieldMapper; import io.metersphere.system.mapper.CustomFieldMapper;
import io.metersphere.system.notice.constants.NoticeConstants; import io.metersphere.system.notice.constants.NoticeConstants;
import io.metersphere.system.service.OperationHistoryService;
import io.metersphere.system.uid.IDGenerator; import io.metersphere.system.uid.IDGenerator;
import io.metersphere.system.utils.Pager; import io.metersphere.system.utils.Pager;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.junit.jupiter.api.*; import org.junit.jupiter.api.*;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
@ -73,6 +77,7 @@ public class FunctionalCaseControllerTests extends BaseTest {
public static final String DOWNLOAD_EXCEL_TEMPLATE_URL = "/functional/case/download/excel/template/"; public static final String DOWNLOAD_EXCEL_TEMPLATE_URL = "/functional/case/download/excel/template/";
public static final String CHECK_EXCEL_URL = "/functional/case/pre-check/excel"; public static final String CHECK_EXCEL_URL = "/functional/case/pre-check/excel";
public static final String IMPORT_EXCEL_URL = "/functional/case/import/excel"; public static final String IMPORT_EXCEL_URL = "/functional/case/import/excel";
public static final String OPERATION_HISTORY_URL = "/functional/case/operation-history";
@Resource @Resource
private NotificationMapper notificationMapper; private NotificationMapper notificationMapper;
@ -83,6 +88,11 @@ public class FunctionalCaseControllerTests extends BaseTest {
private ProjectTemplateService projectTemplateService; private ProjectTemplateService projectTemplateService;
@Resource @Resource
private FunctionalCaseCustomFieldMapper functionalCaseCustomFieldMapper; private FunctionalCaseCustomFieldMapper functionalCaseCustomFieldMapper;
@Resource
private OperationHistoryService operationHistoryService;
protected static String functionalCaseId;
@Test @Test
@Order(1) @Order(1)
@ -121,7 +131,6 @@ public class FunctionalCaseControllerTests extends BaseTest {
String functionalCaseData = functionalCaseMvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8); String functionalCaseData = functionalCaseMvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder functionalCaseResultHolder = JSON.parseObject(functionalCaseData, ResultHolder.class); ResultHolder functionalCaseResultHolder = JSON.parseObject(functionalCaseData, ResultHolder.class);
FunctionalCase functionalCase = JSON.parseObject(JSON.toJSONString(functionalCaseResultHolder.getData()), FunctionalCase.class); FunctionalCase functionalCase = JSON.parseObject(JSON.toJSONString(functionalCaseResultHolder.getData()), FunctionalCase.class);
NotificationExample notificationExample = new NotificationExample(); NotificationExample notificationExample = new NotificationExample();
notificationExample.createCriteria().andResourceNameEqualTo(functionalCase.getName()).andResourceTypeEqualTo(NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK); notificationExample.createCriteria().andResourceNameEqualTo(functionalCase.getName()).andResourceTypeEqualTo(NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK);
List<Notification> notifications = notificationMapper.selectByExampleWithBLOBs(notificationExample); List<Notification> notifications = notificationMapper.selectByExampleWithBLOBs(notificationExample);
@ -134,6 +143,7 @@ public class FunctionalCaseControllerTests extends BaseTest {
paramMap.add("request", JSON.toJSONString(request)); paramMap.add("request", JSON.toJSONString(request));
paramMap.add("files", new LinkedMultiValueMap<>()); paramMap.add("files", new LinkedMultiValueMap<>());
functionalCaseMvcResult = this.requestMultipartWithOkAndReturn(FUNCTIONAL_CASE_ADD_URL, paramMap); functionalCaseMvcResult = this.requestMultipartWithOkAndReturn(FUNCTIONAL_CASE_ADD_URL, paramMap);
functionalCaseId = functionalCase.getId();
// 获取返回值 // 获取返回值
returnData = functionalCaseMvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8); returnData = functionalCaseMvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
resultHolder = JSON.parseObject(returnData, ResultHolder.class); resultHolder = JSON.parseObject(returnData, ResultHolder.class);
@ -631,4 +641,34 @@ public class FunctionalCaseControllerTests extends BaseTest {
paramMap.add("file", file2); paramMap.add("file", file2);
this.requestMultipart(IMPORT_EXCEL_URL, paramMap); this.requestMultipart(IMPORT_EXCEL_URL, paramMap);
} }
@Test
@Order(22)
public void operationHistoryList() throws Exception {
OperationHistoryRequest request = new OperationHistoryRequest();
request.setSourceId(functionalCaseId);
request.setProjectId(DEFAULT_PROJECT_ID);
request.setCurrent(1);
request.setPageSize(10);
request.setSort(Map.of("createTime", "asc"));
MvcResult mvcResult = this.requestPostWithOkAndReturn(OPERATION_HISTORY_URL, request);
// 获取返回值
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
// 返回请求正常
Assertions.assertNotNull(resultHolder);
Pager<?> pageData = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), Pager.class);
// 返回值不为空
Assertions.assertNotNull(pageData);
// 返回值的页码和当前页码相同
Assertions.assertEquals(pageData.getCurrent(), request.getCurrent());
// 返回的数据量不超过规定要返回的数据量相同
Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(pageData.getList())).size() <= request.getPageSize());
request.setSort(Map.of());
this.requestPost(OPERATION_HISTORY_URL, request);
List<OperationHistoryDTO> operationHistoryDTOS = operationHistoryService.listWidthLimit(request, "functional_case");
Assertions.assertTrue(CollectionUtils.isNotEmpty(operationHistoryDTOS));
}
} }

View File

@ -16,4 +16,6 @@ public interface BaseOperationHistoryMapper {
void deleteByIds(@Param("sourceId") String sourceId, @Param("ids") List<Long> ids); void deleteByIds(@Param("sourceId") String sourceId, @Param("ids") List<Long> ids);
List<OperationHistoryDTO> list(@Param("request") OperationHistoryRequest request); List<OperationHistoryDTO> list(@Param("request") OperationHistoryRequest request);
List<OperationHistoryDTO> listWidthLimit(@Param("request") OperationHistoryRequest request, @Param("table") String table);
} }

View File

@ -40,4 +40,28 @@
</if> </if>
</where> </where>
</select> </select>
<select id="listWidthLimit" resultType="io.metersphere.system.dto.OperationHistoryDTO">
SELECT operation_history.id, operation_history.project_id, operation_history.create_time, operation_history.create_user, operation_history.source_id, operation_history.`type`, operation_history.`module`, operation_history.ref_id, project_version.name as versionName
FROM operation_history
LEFT JOIN ${table} sourceTable ON sourceTable.id = operation_history.source_id
LEFT JOIN project_version ON project_version.id = sourceTable.version_id
<where>
<if test="request.projectId != null and request.projectId != ''">
AND operation_history.project_id = #{request.projectId,jdbcType=VARCHAR}
</if>
<if test="request.sourceId != null and request.sourceId != ''">
AND operation_history.source_id = #{request.sourceId,jdbcType=VARCHAR}
</if>
<if test="request.createUser != null and request.createUser != ''">
AND operation_history.create_user = #{request.createUser,jdbcType=VARCHAR}
</if>
<if test="request.type != null and request.type != ''">
AND operation_history.`type` = #{request.type,jdbcType=VARCHAR}
</if>
<if test="request.module != null and request.module != ''">
AND operation_history.`module` = #{request.module,jdbcType=VARCHAR}
</if>
</where>
</select>
</mapper> </mapper>

View File

@ -46,6 +46,23 @@ public class OperationHistoryService {
return list; return list;
} }
public List<OperationHistoryDTO> listWidthLimit(OperationHistoryRequest request, String table) {
List<OperationHistoryDTO> list = baseOperationHistoryMapper.listWidthLimit(request, table);
if (CollectionUtils.isNotEmpty(list)) {
List<String> userIds = list.stream().distinct()
.map(OperationHistoryDTO::getCreateUser).toList();
Map<String, String> userMap = baseUserMapper.selectUserOptionByIds(userIds).stream()
.collect(Collectors.toMap(OptionDTO::getId, OptionDTO::getName));
list.forEach(item -> item.setCreateUserName(userMap.getOrDefault(item.getCreateUser(), StringUtils.EMPTY)));
}
return list;
}
public void associationRefId(Long refLogId, Long logId) { public void associationRefId(Long refLogId, Long logId) {
OperationHistory operationHistory = operationHistoryMapper.selectByPrimaryKey(logId); OperationHistory operationHistory = operationHistoryMapper.selectByPrimaryKey(logId);
operationHistory.setRefId(refLogId); operationHistory.setRefId(refLogId);