feat(功能用例): 导入产生的变更记录

This commit is contained in:
WangXu10 2024-01-24 16:22:21 +08:00 committed by CaptainB
parent b5c20b102f
commit 25efebe991
6 changed files with 110 additions and 44 deletions

View File

@ -72,12 +72,12 @@ public class FunctionalCaseController {
@PostMapping("/add")
@Operation(summary = "用例管理-功能用例-新增用例")
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ_ADD)
@Log(type = OperationLogType.ADD, expression = "#msClass.addFunctionalCaseLog(#request, #files)", msClass = FunctionalCaseLogService.class)
@SendNotice(taskType = NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK, event = NoticeConstants.Event.CREATE, target = "#targetClass.getMainFunctionalCaseDTO(#request.name, #request.caseEditType, #request.projectId, #request.customFields)", targetClass = FunctionalCaseNoticeService.class)
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
public FunctionalCase addFunctionalCase(@Validated @RequestPart("request") FunctionalCaseAddRequest request, @RequestPart(value = "files", required = false) List<MultipartFile> files) {
String userId = SessionUtils.getUserId();
return functionalCaseService.addFunctionalCase(request, files, userId);
String organizationId = SessionUtils.getCurrentOrganizationId();
return functionalCaseService.addFunctionalCase(request, files, userId, organizationId);
}
@ -233,6 +233,7 @@ public class FunctionalCaseController {
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ_UPDATE)
public FunctionalCaseImportResponse importExcel(@RequestPart("request") FunctionalCaseImportRequest request, @RequestPart(value = "file", required = false) MultipartFile file) {
String userId = SessionUtils.getUserId();
return functionalCaseFileService.importExcel(request, userId, file);
String organizationId = SessionUtils.getCurrentOrganizationId();
return functionalCaseFileService.importExcel(request, userId, file, organizationId);
}
}

View File

@ -33,4 +33,7 @@ public class FunctionalCaseHistoryLogDTO implements Serializable {
this.caseAttachments = caseAttachments;
this.fileAssociationList = fileAssociationList;
}
public FunctionalCaseHistoryLogDTO() {
}
}

View File

@ -78,11 +78,12 @@ public class FunctionalCaseImportEventListener extends AnalysisEventListener<Map
private HashMap<String, AbstractCustomFieldValidator> customFieldValidatorMap;
private FunctionalCaseService functionalCaseService;
private String userId;
private String organizationId;
private int successCount = 0;
private Map<String, String> pathMap = new HashMap<>();
public FunctionalCaseImportEventListener(FunctionalCaseImportRequest request, Class clazz, List<TemplateCustomFieldDTO> customFields, Set<ExcelMergeInfo> mergeInfoSet, String userId) {
public FunctionalCaseImportEventListener(FunctionalCaseImportRequest request, Class clazz, List<TemplateCustomFieldDTO> customFields, Set<ExcelMergeInfo> mergeInfoSet, String userId, String organizationId) {
this.mergeInfoSet = mergeInfoSet;
this.request = request;
excelDataClass = clazz;
@ -92,6 +93,7 @@ public class FunctionalCaseImportEventListener extends AnalysisEventListener<Map
functionalCaseService = CommonBeanFactory.getBean(FunctionalCaseService.class);
customFieldValidatorMap = CustomFieldValidatorFactory.getValidatorMap();
this.userId = userId;
this.organizationId = organizationId;
}
@ -199,11 +201,11 @@ public class FunctionalCaseImportEventListener extends AnalysisEventListener<Map
*/
private void saveData() {
if (CollectionUtils.isNotEmpty(list)) {
functionalCaseService.saveImportData(list, request, moduleTree, userId, customFieldsMap, pathMap);
functionalCaseService.saveImportData(list, request, moduleTree, userId, customFieldsMap, pathMap, organizationId);
}
if (CollectionUtils.isNotEmpty(updateList)) {
functionalCaseService.updateImportData(updateList, request, moduleTree, userId, customFieldsMap, pathMap);
functionalCaseService.updateImportData(updateList, request, moduleTree, userId, customFieldsMap, pathMap, organizationId);
}
}

View File

@ -231,7 +231,7 @@ public class FunctionalCaseFileService {
* @param userId
* @param file
*/
public FunctionalCaseImportResponse importExcel(FunctionalCaseImportRequest request, String userId, MultipartFile file) {
public FunctionalCaseImportResponse importExcel(FunctionalCaseImportRequest request, String userId, MultipartFile file, String organizationId) {
if (file == null) {
throw new MSException(Translator.get("file_cannot_be_null"));
}
@ -249,7 +249,7 @@ public class FunctionalCaseFileService {
// 预处理查询合并单元格信息
EasyExcel.read(file.getInputStream(), null, new FunctionalCasePretreatmentListener(mergeInfoSet))
.extraRead(CellExtraTypeEnum.MERGE).sheet().doRead();
FunctionalCaseImportEventListener eventListener = new FunctionalCaseImportEventListener(request, clazz, customFields, mergeInfoSet, userId);
FunctionalCaseImportEventListener eventListener = new FunctionalCaseImportEventListener(request, clazz, customFields, mergeInfoSet, userId, organizationId);
EasyExcelFactory.read(file.getInputStream(), eventListener).sheet().doRead();
response.setErrorMessages(eventListener.getErrList());
response.setSuccessCount(eventListener.getSuccessCount());

View File

@ -1,6 +1,5 @@
package io.metersphere.functional.service;
import io.metersphere.api.mapper.ApiTestCaseMapper;
import io.metersphere.bug.domain.Bug;
import io.metersphere.bug.domain.BugRelationCase;
import io.metersphere.bug.mapper.BugMapper;
@ -57,32 +56,6 @@ public class FunctionalCaseLogService {
private BugMapper bugMapper;
//TODO 日志(需要修改)
/**
* 新增用例 日志
*
* @param requests
* @param files
* @return
*/
public LogDTO addFunctionalCaseLog(FunctionalCaseAddRequest requests, List<MultipartFile> files) {
LogDTO dto = new LogDTO(
requests.getProjectId(),
null,
null,
null,
OperationLogType.ADD.name(),
OperationLogModule.FUNCTIONAL_CASE,
requests.getName());
dto.setHistory(true);
dto.setPath("/functional/case/add");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setModifiedValue(JSON.toJSONBytes(requests));
return dto;
}
/**
* 更新用例 日志
*
@ -392,9 +365,9 @@ public class FunctionalCaseLogService {
null,
OperationLogType.DISASSOCIATE.name(),
OperationLogModule.FUNCTIONAL_CASE,
bug.getTitle()+"缺陷");
bug.getTitle() + "缺陷");
dto.setPath("/functional/case/test/disassociate/bug/"+id);
dto.setPath("/functional/case/test/disassociate/bug/" + id);
dto.setMethod(HttpMethodConstants.GET.name());
dto.setOriginalValue(JSON.toJSONBytes(bugRelationCase));
return dto;

View File

@ -15,22 +15,30 @@ import io.metersphere.functional.result.CaseManagementResultCode;
import io.metersphere.plan.domain.TestPlanFunctionalCaseExample;
import io.metersphere.plan.mapper.TestPlanFunctionalCaseMapper;
import io.metersphere.project.domain.FileAssociation;
import io.metersphere.project.domain.FileAssociationExample;
import io.metersphere.project.domain.ProjectVersion;
import io.metersphere.project.dto.ModuleCountDTO;
import io.metersphere.project.mapper.ExtBaseProjectVersionMapper;
import io.metersphere.project.mapper.FileAssociationMapper;
import io.metersphere.project.service.ProjectTemplateService;
import io.metersphere.provider.BaseCaseProvider;
import io.metersphere.sdk.constants.ApplicationNumScope;
import io.metersphere.sdk.constants.FunctionalCaseExecuteResult;
import io.metersphere.sdk.constants.HttpMethodConstants;
import io.metersphere.sdk.constants.TemplateScene;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.domain.CustomFieldOption;
import io.metersphere.system.dto.sdk.BaseTreeNode;
import io.metersphere.system.dto.sdk.TemplateCustomFieldDTO;
import io.metersphere.system.dto.sdk.TemplateDTO;
import io.metersphere.system.dto.sdk.request.PosRequest;
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.log.service.OperationLogService;
import io.metersphere.system.service.BaseCustomFieldOptionService;
import io.metersphere.system.service.BaseCustomFieldService;
import io.metersphere.system.uid.IDGenerator;
@ -122,9 +130,17 @@ public class FunctionalCaseService {
private TestPlanFunctionalCaseMapper testPlanFunctionalCaseMapper;
@Resource
private BaseCustomFieldOptionService baseCustomFieldOptionService;
@Resource
private OperationLogService operationLogService;
@Resource
private FunctionalCaseCustomFieldMapper functionalCaseCustomFieldMapper;
@Resource
private FunctionalCaseAttachmentMapper functionalCaseAttachmentMapper;
@Resource
private FileAssociationMapper fileAssociationMapper;
public FunctionalCase addFunctionalCase(FunctionalCaseAddRequest request, List<MultipartFile> files, String userId) {
public FunctionalCase addFunctionalCase(FunctionalCaseAddRequest request, List<MultipartFile> files, String userId, String organizationId) {
String caseId = IDGenerator.nextStr();
//添加功能用例
FunctionalCase functionalCase = addCase(caseId, request, userId);
@ -142,6 +158,10 @@ public class FunctionalCaseService {
addCaseReviewCase(request.getReviewId(), caseId, userId);
//记录日志
FunctionalCaseHistoryLogDTO historyLogDTO = getImportLogModule(functionalCase);
saveImportDataLog(functionalCase, new FunctionalCaseHistoryLogDTO(), historyLogDTO, userId, organizationId);
return functionalCase;
}
@ -785,7 +805,7 @@ public class FunctionalCaseService {
* @param userId 用户id
* @param customFieldsMap 当前默认模板的自定义字段
*/
public void saveImportData(List<FunctionalCaseExcelData> list, FunctionalCaseImportRequest request, List<BaseTreeNode> moduleTree, String userId, Map<String, TemplateCustomFieldDTO> customFieldsMap, Map<String, String> pathMap) {
public void saveImportData(List<FunctionalCaseExcelData> list, FunctionalCaseImportRequest request, List<BaseTreeNode> moduleTree, String userId, Map<String, TemplateCustomFieldDTO> customFieldsMap, Map<String, String> pathMap, String organizationId) {
//默认模板
TemplateDTO defaultTemplateDTO = projectTemplateService.getDefaultTemplateDTO(request.getProjectId(), TemplateScene.FUNCTIONAL.name());
//模块路径
@ -799,14 +819,14 @@ public class FunctionalCaseService {
FunctionalCaseCustomFieldMapper customFieldMapper = sqlSession.getMapper(FunctionalCaseCustomFieldMapper.class);
Long nextOrder = getNextOrder(request.getProjectId());
for (int i = 0; i < list.size(); i++) {
parseInsertDataToModule(list.get(i), request, userId, caseModulePathMap, defaultTemplateDTO, nextOrder, caseMapper, caseBlobMapper, customFieldMapper, customFieldsMap);
parseInsertDataToModule(list.get(i), request, userId, caseModulePathMap, defaultTemplateDTO, nextOrder, caseMapper, caseBlobMapper, customFieldMapper, customFieldsMap, organizationId);
}
sqlSession.flushStatements();
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
}
private void parseInsertDataToModule(FunctionalCaseExcelData functionalCaseExcelData, FunctionalCaseImportRequest request, String userId, Map<String, String> caseModulePathMap, TemplateDTO defaultTemplateDTO, Long nextOrder,
FunctionalCaseMapper caseMapper, FunctionalCaseBlobMapper caseBlobMapper, FunctionalCaseCustomFieldMapper customFieldMapper, Map<String, TemplateCustomFieldDTO> customFieldsMap) {
FunctionalCaseMapper caseMapper, FunctionalCaseBlobMapper caseBlobMapper, FunctionalCaseCustomFieldMapper customFieldMapper, Map<String, TemplateCustomFieldDTO> customFieldsMap, String organizationId) {
//构建用例
FunctionalCase functionalCase = new FunctionalCase();
String caseId = IDGenerator.nextStr();
@ -841,6 +861,14 @@ public class FunctionalCaseService {
//自定义字段
handleImportCustomField(functionalCaseExcelData, caseId, customFieldMapper, customFieldsMap);
//新增用例记录日志
FunctionalCaseCustomFieldExample fieldExample = new FunctionalCaseCustomFieldExample();
fieldExample.createCriteria().andCaseIdEqualTo(functionalCase.getId());
List<FunctionalCaseCustomField> customFields = functionalCaseCustomFieldMapper.selectByExample(fieldExample);
FunctionalCaseHistoryLogDTO historyLogDTO = new FunctionalCaseHistoryLogDTO(functionalCase, caseBlob, customFields, new ArrayList<>(), new ArrayList<>());
saveImportDataLog(functionalCase, new FunctionalCaseHistoryLogDTO(), historyLogDTO, userId, organizationId);
}
@ -889,7 +917,7 @@ public class FunctionalCaseService {
* @param userId 用户id
* @param customFieldsMap 当前默认模板的自定义字段
*/
public void updateImportData(List<FunctionalCaseExcelData> updateList, FunctionalCaseImportRequest request, List<BaseTreeNode> moduleTree, String userId, Map<String, TemplateCustomFieldDTO> customFieldsMap, Map<String, String> pathMap) {
public void updateImportData(List<FunctionalCaseExcelData> updateList, FunctionalCaseImportRequest request, List<BaseTreeNode> moduleTree, String userId, Map<String, TemplateCustomFieldDTO> customFieldsMap, Map<String, String> pathMap, String organizationId) {
//默认模板
TemplateDTO defaultTemplateDTO = projectTemplateService.getDefaultTemplateDTO(request.getProjectId(), TemplateScene.FUNCTIONAL.name());
//模块路径
@ -901,16 +929,19 @@ public class FunctionalCaseService {
FunctionalCaseBlobMapper caseBlobMapper = sqlSession.getMapper(FunctionalCaseBlobMapper.class);
FunctionalCaseCustomFieldMapper customFieldMapper = sqlSession.getMapper(FunctionalCaseCustomFieldMapper.class);
for (int i = 0; i < updateList.size(); i++) {
parseUpdateDataToModule(updateList.get(i), request, userId, caseModulePathMap, defaultTemplateDTO, caseMapper, caseBlobMapper, customFieldMapper, customFieldsMap);
parseUpdateDataToModule(updateList.get(i), request, userId, caseModulePathMap, defaultTemplateDTO, caseMapper, caseBlobMapper, customFieldMapper, customFieldsMap, organizationId);
}
sqlSession.flushStatements();
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
}
private void parseUpdateDataToModule(FunctionalCaseExcelData functionalCaseExcelData, FunctionalCaseImportRequest request, String userId, Map<String, String> caseModulePathMap, TemplateDTO defaultTemplateDTO, FunctionalCaseMapper caseMapper, FunctionalCaseBlobMapper caseBlobMapper, FunctionalCaseCustomFieldMapper customFieldMapper, Map<String, TemplateCustomFieldDTO> customFieldsMap) {
private void parseUpdateDataToModule(FunctionalCaseExcelData functionalCaseExcelData, FunctionalCaseImportRequest request, String userId, Map<String, String> caseModulePathMap, TemplateDTO defaultTemplateDTO, FunctionalCaseMapper caseMapper, FunctionalCaseBlobMapper caseBlobMapper, FunctionalCaseCustomFieldMapper customFieldMapper, Map<String, TemplateCustomFieldDTO> customFieldsMap, String organizationId) {
//用例表
FunctionalCase functionalCase = caseMapper.selectByPrimaryKey(functionalCaseExcelData.getNum());
//记录原值
FunctionalCaseHistoryLogDTO originalValue = getImportLogModule(functionalCase);
functionalCase.setName(functionalCaseExcelData.getName());
functionalCase.setModuleId(caseModulePathMap.get(functionalCaseExcelData.getModule()));
functionalCase.setTags(handleImportTags(functionalCaseExcelData.getTags()));
@ -935,6 +966,10 @@ public class FunctionalCaseService {
//自定义字段
handleUpdateCustomField(functionalCaseExcelData, functionalCase.getId(), customFieldMapper, customFieldsMap);
//记录新值
FunctionalCaseHistoryLogDTO modifiedLogDTO = getImportLogModule(functionalCase);
//记录日志
saveImportDataLog(functionalCase, originalValue, modifiedLogDTO, userId, organizationId);
}
private void handleUpdateCustomField(FunctionalCaseExcelData functionalCaseExcelData, String caseId, FunctionalCaseCustomFieldMapper customFieldMapper, Map<String, TemplateCustomFieldDTO> customFieldsMap) {
@ -943,4 +978,56 @@ public class FunctionalCaseService {
customFieldMapper.deleteByExample(fieldExample);
handleImportCustomField(functionalCaseExcelData, caseId, customFieldMapper, customFieldsMap);
}
/**
* 保存日志
*
* @param functionalCase 用例
* @param originalValue 原值
* @param modifiedLogDTO 新值
*/
private void saveImportDataLog(FunctionalCase functionalCase, FunctionalCaseHistoryLogDTO originalValue, FunctionalCaseHistoryLogDTO modifiedLogDTO, String userId, String organizationId) {
LogDTO dto = new LogDTO(
functionalCase.getProjectId(),
organizationId,
functionalCase.getId(),
userId,
OperationLogType.IMPORT.name(),
OperationLogModule.FUNCTIONAL_CASE,
functionalCase.getName());
dto.setHistory(true);
dto.setPath("/functional/case/import/excel");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setModifiedValue(JSON.toJSONBytes(modifiedLogDTO));
dto.setOriginalValue(JSON.toJSONBytes(originalValue));
operationLogService.add(dto);
}
/**
* 日志原值
*
* @param functionalCase
* @return
*/
private FunctionalCaseHistoryLogDTO getImportLogModule(FunctionalCase functionalCase) {
FunctionalCaseBlob functionalCaseBlob = functionalCaseBlobMapper.selectByPrimaryKey(functionalCase.getId());
//自定义字段
FunctionalCaseCustomFieldExample fieldExample = new FunctionalCaseCustomFieldExample();
fieldExample.createCriteria().andCaseIdEqualTo(functionalCase.getId());
List<FunctionalCaseCustomField> customFields = functionalCaseCustomFieldMapper.selectByExample(fieldExample);
//附件 本地 + 文件库
FunctionalCaseAttachmentExample attachmentExample = new FunctionalCaseAttachmentExample();
attachmentExample.createCriteria().andCaseIdEqualTo(functionalCase.getId());
List<FunctionalCaseAttachment> caseAttachments = functionalCaseAttachmentMapper.selectByExample(attachmentExample);
FileAssociationExample example = new FileAssociationExample();
example.createCriteria().andSourceIdEqualTo(functionalCase.getId());
List<FileAssociation> fileAssociationList = fileAssociationMapper.selectByExample(example);
FunctionalCaseHistoryLogDTO historyLogDTO = new FunctionalCaseHistoryLogDTO(functionalCase, functionalCaseBlob, customFields, caseAttachments, fileAssociationList);
return historyLogDTO;
}
}