refactor(项目管理): 菜单管理同步缺陷,用例管理关联需求配置

This commit is contained in:
WangXu10 2023-09-22 18:31:37 +08:00 committed by 刘瑞斌
parent 6835920918
commit c6ba62bf15
14 changed files with 433 additions and 88 deletions

View File

@ -25,6 +25,15 @@ public class ProjectApplication implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public ProjectApplication(String projectId, String type, String typeValue) {
this.projectId = projectId;
this.type = type;
this.typeValue = typeValue;
}
public ProjectApplication() {
}
public enum Column { public enum Column {
projectId("project_id", "projectId", "VARCHAR", false), projectId("project_id", "projectId", "VARCHAR", false),
type("type", "type", "VARCHAR", true), type("type", "type", "VARCHAR", true),

View File

@ -7,7 +7,7 @@ public class ProjectApplicationType {
//工作台 //工作台
public enum WORKSTATION { public enum WORKSTATION {
WORKSTATION WORKSTATION_SYNC_RULE
} }
//测试计划 //测试计划
@ -51,10 +51,15 @@ public class ProjectApplicationType {
//用例管理 //用例管理
public enum CASE{ public enum CASE{
CASE_PUBLIC, CASE_PUBLIC,
CASE_ASSOCIATION_REQUIREMENTS,
CASE_RE_REVIEW, CASE_RE_REVIEW,
} }
//用例管理-关联需求
public enum CASE_RELATED_CONFIG{
CASE_RELATED,
ENABLE,
}
//缺陷管理 //缺陷管理
public enum ISSUE{ public enum ISSUE{
@ -62,7 +67,11 @@ public class ProjectApplicationType {
} }
//缺陷管理-同步配置项
public enum ISSUE_SYNC_CONFIG{
CRON_EXPRESSION,
ENABLE,
MECHANISM,
}
} }

View File

@ -23,6 +23,7 @@ fake_error.match_type.not_blank=Match Type is required
bug_template_extend.id.not_blank=ID is required bug_template_extend.id.not_blank=ID is required
project_application.project_id.not_blank=Project ID is required project_application.project_id.not_blank=Project ID is required
project_application.type.not_blank=Type is required project_application.type.not_blank=Type is required
project_application.type_value.not_blank=Type Value is required
custom_function_blob.id.not_blank=ID is required custom_function_blob.id.not_blank=ID is required
fake_error_blob.id.not_blank=ID is required fake_error_blob.id.not_blank=ID is required
file_module.id.not_blank=ID is required file_module.id.not_blank=ID is required
@ -133,7 +134,7 @@ permission.project_application_case.read=Case read
permission.project_application_case.update=Case update permission.project_application_case.update=Case update
permission.project_application_issue.read=Issue read permission.project_application_issue.read=Issue read
permission.project_application_issue.update=Issue update permission.project_application_issue.update=Issue update
permission.project_application_workstation.reda=Workstation read permission.project_application_workstation.read=Workstation read
permission.project_application_workstation.update=Workstation update permission.project_application_workstation.update=Workstation update
permission.project_base_info.name=Project base info permission.project_base_info.name=Project base info
permission.project_log.name=Operation log permission.project_log.name=Operation log

View File

@ -23,6 +23,7 @@ fake_error.match_type.not_blank=匹配类型不能为空
bug_template_extend.id.not_blank=ID不能为空 bug_template_extend.id.not_blank=ID不能为空
project_application.project_id.not_blank=项目ID不能为空 project_application.project_id.not_blank=项目ID不能为空
project_application.type.not_blank=类型不能为空 project_application.type.not_blank=类型不能为空
project_application.type_value.not_blank=类型值不能为空
custom_function_blob.id.not_blank=ID不能为空 custom_function_blob.id.not_blank=ID不能为空
fake_error_blob.id.not_blank=ID不能为空 fake_error_blob.id.not_blank=ID不能为空
file_module.id.not_blank=ID不能为空 file_module.id.not_blank=ID不能为空
@ -133,7 +134,7 @@ permission.project_application_case.read=用例管理-查询
permission.project_application_case.update=用例管理-编辑 permission.project_application_case.update=用例管理-编辑
permission.project_application_issue.read=缺陷管理-查询 permission.project_application_issue.read=缺陷管理-查询
permission.project_application_issue.update=缺陷管理-编辑 permission.project_application_issue.update=缺陷管理-编辑
permission.project_application_workstation.reda=工作台-查询 permission.project_application_workstation.read=工作台-查询
permission.project_application_workstation.update=工作台-编辑 permission.project_application_workstation.update=工作台-编辑
permission.project_base_info.name=基本信息 permission.project_base_info.name=基本信息
permission.project_log.name=日志 permission.project_log.name=日志

View File

@ -23,6 +23,7 @@ fake_error.match_type.not_blank=匹配類型不能為空
bug_template_extend.id.not_blank=ID不能為空 bug_template_extend.id.not_blank=ID不能為空
project_application.project_id.not_blank=項目ID不能為空 project_application.project_id.not_blank=項目ID不能為空
project_application.type.not_blank=類型不能為空 project_application.type.not_blank=類型不能為空
project_application.type_value.not_blank=類型值不能為空
custom_function_blob.id.not_blank=ID不能為空 custom_function_blob.id.not_blank=ID不能為空
fake_error_blob.id.not_blank=ID不能為空 fake_error_blob.id.not_blank=ID不能為空
file_module.id.not_blank=ID不能為空 file_module.id.not_blank=ID不能為空
@ -133,7 +134,7 @@ permission.project_application_case.read=用例管理-查詢
permission.project_application_case.update=用例管理-編輯 permission.project_application_case.update=用例管理-編輯
permission.project_application_issue.read=缺陷管理-查詢 permission.project_application_issue.read=缺陷管理-查詢
permission.project_application_issue.update=缺陷管理-編輯 permission.project_application_issue.update=缺陷管理-編輯
permission.project_application_workstation.reda=工作台-查詢 permission.project_application_workstation.read=工作台-查詢
permission.project_application_workstation.update=工作台-編輯 permission.project_application_workstation.update=工作台-編輯
permission.project_base_info.name=基本信息 permission.project_base_info.name=基本信息
permission.project_log.name=日誌 permission.project_log.name=日誌

View File

@ -3,14 +3,16 @@ package io.metersphere.project.controller;
import io.metersphere.project.domain.ProjectApplication; import io.metersphere.project.domain.ProjectApplication;
import io.metersphere.project.request.ProjectApplicationRequest; import io.metersphere.project.request.ProjectApplicationRequest;
import io.metersphere.project.service.ProjectApplicationService; import io.metersphere.project.service.ProjectApplicationService;
import io.metersphere.project.service.ProjectService;
import io.metersphere.sdk.constants.ModuleType;
import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.sdk.constants.ProjectApplicationType; import io.metersphere.sdk.constants.ProjectApplicationType;
import io.metersphere.sdk.dto.OptionDTO; import io.metersphere.sdk.dto.OptionDTO;
import io.metersphere.sdk.dto.SessionUser; import io.metersphere.sdk.dto.SessionUser;
import io.metersphere.system.utils.SessionUtils;
import io.metersphere.system.domain.User; import io.metersphere.system.domain.User;
import io.metersphere.system.log.annotation.Log; import io.metersphere.system.log.annotation.Log;
import io.metersphere.system.log.constants.OperationLogType; import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.utils.SessionUtils;
import io.metersphere.validation.groups.Updated; import io.metersphere.validation.groups.Updated;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@ -22,6 +24,7 @@ import org.springframework.web.bind.annotation.*;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -33,6 +36,8 @@ public class ProjectApplicationController {
@Resource @Resource
private ProjectApplicationService projectApplicationService; private ProjectApplicationService projectApplicationService;
@Resource
private ProjectService projectService;
/** /**
* ==========测试计划========== * ==========测试计划==========
@ -75,11 +80,11 @@ public class ProjectApplicationController {
return projectApplicationService.get(request, types); return projectApplicationService.get(request, types);
} }
@GetMapping("/ui/resource/pool/{organizationId}") @GetMapping("/ui/resource/pool/{projectId}")
@Operation(summary = "UI测试-获取资源池列表") @Operation(summary = "UI测试-获取资源池列表")
@RequiresPermissions(PermissionConstants.PROJECT_APPLICATION_UI_READ) @RequiresPermissions(PermissionConstants.PROJECT_APPLICATION_UI_READ)
public List<OptionDTO> getUiResourcePoolList(@PathVariable String organizationId) { public List<OptionDTO> getUiPoolOptions(@PathVariable String projectId) {
return projectApplicationService.getResourcePoolList(StringUtils.defaultIfBlank(organizationId, SessionUtils.getCurrentOrganizationId())); return projectService.getPoolOptions(projectId, ModuleType.UI_TEST);
} }
@ -139,11 +144,11 @@ public class ProjectApplicationController {
} }
@GetMapping("/api/resource/pool/{organizationId}") @GetMapping("/api/resource/pool/{projectId}")
@Operation(summary = "接口测试-获取资源池列表") @Operation(summary = "接口测试-获取资源池列表")
@RequiresPermissions(PermissionConstants.PROJECT_APPLICATION_API_READ) @RequiresPermissions(PermissionConstants.PROJECT_APPLICATION_API_READ)
public List<OptionDTO> getResourcePoolList(@PathVariable String organizationId) { public List<OptionDTO> getApiPoolOptions(@PathVariable String projectId) {
return projectApplicationService.getResourcePoolList(StringUtils.defaultIfBlank(organizationId, SessionUtils.getCurrentOrganizationId())); return projectService.getPoolOptions(projectId, ModuleType.API_TEST);
} }
@ -185,6 +190,22 @@ public class ProjectApplicationController {
} }
@PostMapping("/update/case/related/{projectId}")
@Operation(summary = "用例管理-关联需求")
@RequiresPermissions(PermissionConstants.PROJECT_APPLICATION_CASE_UPDATE)
@Log(type = OperationLogType.UPDATE, expression = "#msClass.updateRelatedRequirementsLog(#projectId, #configs)", msClass = ProjectApplicationService.class)
public void updateRelated(@PathVariable("projectId") String projectId, @RequestBody Map<String, String> configs) {
projectApplicationService.updateRelated(projectId, configs);
}
@GetMapping("/case/related/info/{projectId}")
@Operation(summary = "用例管理-获取关联需求信息")
@RequiresPermissions(PermissionConstants.PROJECT_APPLICATION_ISSUE_READ)
public Map<String, String> getRelatedConfigInfo(@PathVariable("projectId") String projectId) {
return projectApplicationService.getRelatedConfigInfo(projectId);
}
/** /**
* ==========工作台========== * ==========工作台==========
*/ */
@ -242,6 +263,23 @@ public class ProjectApplicationController {
} }
@PostMapping("/update/issue/sync/{projectId}")
@Operation(summary = "缺陷管理-同步缺陷配置")
@RequiresPermissions(PermissionConstants.PROJECT_APPLICATION_ISSUE_UPDATE)
@Log(type = OperationLogType.UPDATE, expression = "#msClass.updateIssueSyncLog(#projectId, #configs)", msClass = ProjectApplicationService.class)
public void syncIssueConfig(@PathVariable("projectId") String projectId, @RequestBody Map<String, String> configs) {
projectApplicationService.syncIssueConfig(projectId, configs);
}
@GetMapping("/issue/sync/info/{projectId}")
@Operation(summary = "缺陷管理-获取同步缺陷信息")
@RequiresPermissions(PermissionConstants.PROJECT_APPLICATION_ISSUE_READ)
public Map<String, String> getIssueConfigInfo(@PathVariable("projectId") String projectId) {
return projectApplicationService.getIssueConfigInfo(projectId);
}
/** /**
* ==========全部========== * ==========全部==========
*/ */
@ -252,4 +290,12 @@ public class ProjectApplicationController {
SessionUser user = Objects.requireNonNull(SessionUtils.getUser()); SessionUser user = Objects.requireNonNull(SessionUtils.getUser());
return projectApplicationService.getAllConfigs(user, projectId); return projectApplicationService.getAllConfigs(user, projectId);
} }
@GetMapping("/module-setting/{projectId}")
@Operation(summary = "获取菜单列表")
public Map<String, Boolean> getModuleSetting(@PathVariable String projectId) {
return projectApplicationService.getModuleSetting(projectId);
}
} }

View File

@ -0,0 +1,21 @@
package io.metersphere.project.job;
import io.metersphere.system.sechedule.BaseScheduleJob;
import org.quartz.JobExecutionContext;
import org.quartz.JobKey;
import org.quartz.TriggerKey;
public class IssueSyncJob extends BaseScheduleJob {
@Override
protected void businessExecute(JobExecutionContext context) {
//TODO 定时任务执行 同步issue
}
public static JobKey getJobKey(String projectId) {
return new JobKey(projectId, IssueSyncJob.class.getName());
}
public static TriggerKey getTriggerKey(String projectId) {
return new TriggerKey(projectId, IssueSyncJob.class.getName());
}
}

View File

@ -8,4 +8,6 @@ import java.util.List;
public interface ExtProjectMapper { public interface ExtProjectMapper {
List<Project> getUserProject(@Param("organizationId") String organizationId, @Param("userId") String userId); List<Project> getUserProject(@Param("organizationId") String organizationId, @Param("userId") String userId);
String getModuleSetting(@Param("projectId") String projectId);
} }

View File

@ -12,4 +12,9 @@
where urr.user_id = #{userId} and u.type = 'PROJECT' where urr.user_id = #{userId} and u.type = 'PROJECT'
AND p.organization_id = #{organizationId} and p.enable = 1 and user.deleted = 0 AND p.organization_id = #{organizationId} and p.enable = 1 and user.deleted = 0
</select> </select>
<select id="getModuleSetting" resultType="java.lang.String">
select module_setting from project where id = #{projectId}
</select>
</mapper> </mapper>

View File

@ -1,19 +0,0 @@
package io.metersphere.project.mapper;
import io.metersphere.sdk.dto.OptionDTO;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author wx
*/
public interface ExtProjectTestResourcePoolMapper {
/**
* 获取当前项目资源池列表
* @param orgId
* @return
*/
List<OptionDTO> getResourcePoolList(@Param("orgId") String orgId);
}

View File

@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="io.metersphere.project.mapper.ExtProjectTestResourcePoolMapper">
<select id="getResourcePoolList" resultType="io.metersphere.sdk.dto.OptionDTO">
SELECT
id,
NAME
FROM
test_resource_pool
WHERE
all_org = 1
AND `enable` = 1
AND deleted = 0
UNION
SELECT
trp.id,
trp.NAME
FROM
test_resource_pool trp
LEFT JOIN test_resource_pool_organization trpo ON trp.id = trpo.test_resource_pool_id
WHERE
trpo.org_id = #{orgId}
AND trp.`enable` = 1
AND trp.deleted = 0
</select>
</mapper>

View File

@ -4,7 +4,8 @@ import io.metersphere.plugin.platform.api.AbstractPlatformPlugin;
import io.metersphere.project.domain.ProjectApplication; import io.metersphere.project.domain.ProjectApplication;
import io.metersphere.project.domain.ProjectApplicationExample; import io.metersphere.project.domain.ProjectApplicationExample;
import io.metersphere.project.job.CleanUpReportJob; import io.metersphere.project.job.CleanUpReportJob;
import io.metersphere.project.mapper.ExtProjectTestResourcePoolMapper; import io.metersphere.project.job.IssueSyncJob;
import io.metersphere.project.mapper.ExtProjectMapper;
import io.metersphere.project.mapper.ExtProjectUserRoleMapper; import io.metersphere.project.mapper.ExtProjectUserRoleMapper;
import io.metersphere.project.mapper.ProjectApplicationMapper; import io.metersphere.project.mapper.ProjectApplicationMapper;
import io.metersphere.project.request.ProjectApplicationRequest; import io.metersphere.project.request.ProjectApplicationRequest;
@ -13,7 +14,6 @@ import io.metersphere.sdk.dto.LogDTO;
import io.metersphere.sdk.dto.OptionDTO; import io.metersphere.sdk.dto.OptionDTO;
import io.metersphere.sdk.dto.SessionUser; import io.metersphere.sdk.dto.SessionUser;
import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.JSON;
import io.metersphere.system.utils.SessionUtils;
import io.metersphere.system.domain.*; import io.metersphere.system.domain.*;
import io.metersphere.system.log.constants.OperationLogModule; import io.metersphere.system.log.constants.OperationLogModule;
import io.metersphere.system.log.constants.OperationLogType; import io.metersphere.system.log.constants.OperationLogType;
@ -23,6 +23,7 @@ import io.metersphere.system.mapper.ServiceIntegrationMapper;
import io.metersphere.system.sechedule.ScheduleService; import io.metersphere.system.sechedule.ScheduleService;
import io.metersphere.system.service.PluginLoadService; import io.metersphere.system.service.PluginLoadService;
import io.metersphere.system.utils.ServiceUtils; import io.metersphere.system.utils.ServiceUtils;
import io.metersphere.system.utils.SessionUtils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.BooleanUtils;
@ -30,10 +31,7 @@ import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList; import java.util.*;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Service @Service
@ -48,9 +46,6 @@ public class ProjectApplicationService {
@Resource @Resource
private ExtProjectUserRoleMapper extProjectUserRoleMapper; private ExtProjectUserRoleMapper extProjectUserRoleMapper;
@Resource
private ExtProjectTestResourcePoolMapper extProjectTestResourcePoolMapper;
@Resource @Resource
private ServiceIntegrationMapper serviceIntegrationMapper; private ServiceIntegrationMapper serviceIntegrationMapper;
@Resource @Resource
@ -62,6 +57,9 @@ public class ProjectApplicationService {
@Resource @Resource
private PluginLoadService pluginLoadService; private PluginLoadService pluginLoadService;
@Resource
private ExtProjectMapper extProjectMapper;
/** /**
* 更新配置信息 * 更新配置信息
* *
@ -167,17 +165,6 @@ public class ProjectApplicationService {
} }
/**
* 获取当前项目 可用资源池
*
* @param organizationId
* @return
*/
public List<OptionDTO> getResourcePoolList(String organizationId) {
return extProjectTestResourcePoolMapper.getResourcePoolList(organizationId);
}
/** /**
* 获取平台列表 * 获取平台列表
* *
@ -274,6 +261,86 @@ public class ProjectApplicationService {
} }
/**
* 同步缺陷配置
*
* @param projectId
* @param configs
*/
public void syncIssueConfig(String projectId, Map<String, String> configs) {
List<ProjectApplication> issueSyncConfigs = configs.entrySet().stream().map(config -> new ProjectApplication(projectId, ProjectApplicationType.ISSUE.ISSUE_SYNC.name() + "_" + config.getKey().toUpperCase(), config.getValue())).collect(Collectors.toList());
//处理同步缺陷定时任务配置
doSaveOrUpdateSchedule(issueSyncConfigs, projectId);
ProjectApplicationExample example = new ProjectApplicationExample();
example.createCriteria().andProjectIdEqualTo(projectId).andTypeLike(ProjectApplicationType.ISSUE.ISSUE_SYNC.name() + "%");
if (projectApplicationMapper.countByExample(example) > 0) {
example.clear();
example.createCriteria().andTypeLike(ProjectApplicationType.ISSUE.ISSUE_SYNC.name() + "%");
projectApplicationMapper.deleteByExample(example);
projectApplicationMapper.batchInsert(issueSyncConfigs);
} else {
projectApplicationMapper.batchInsert(issueSyncConfigs);
}
}
private void doSaveOrUpdateSchedule(List<ProjectApplication> issueSyncConfigs, String projectId) {
List<ProjectApplication> syncCron = issueSyncConfigs.stream().filter(config -> config.getType().equals(ProjectApplicationType.ISSUE.ISSUE_SYNC.name() + "_" + ProjectApplicationType.ISSUE_SYNC_CONFIG.CRON_EXPRESSION.name())).collect(Collectors.toList());
List<ProjectApplication> syncEnable = issueSyncConfigs.stream().filter(config -> config.getType().equals(ProjectApplicationType.ISSUE.ISSUE_SYNC.name() + "_" + ProjectApplicationType.ISSUE_SYNC_CONFIG.ENABLE.name())).collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(syncCron)) {
Boolean enable = Boolean.valueOf(syncEnable.get(0).getTypeValue());
String typeValue = syncCron.get(0).getTypeValue();
Schedule schedule = scheduleService.getScheduleByResource(projectId, IssueSyncJob.class.getName());
Optional<Schedule> optional = Optional.ofNullable(schedule);
optional.ifPresentOrElse(s -> {
s.setEnable(enable);
s.setValue(typeValue);
scheduleService.editSchedule(s);
scheduleService.addOrUpdateCronJob(s,
IssueSyncJob.getJobKey(projectId),
IssueSyncJob.getTriggerKey(projectId),
IssueSyncJob.class);
}, () -> {
Schedule request = new Schedule();
request.setName("Issue Sync Job");
request.setResourceId(projectId);
request.setKey(projectId);
request.setProjectId(projectId);
request.setEnable(enable);
request.setCreateUser(SessionUtils.getUserId());
request.setType(ScheduleType.CRON.name());
// 每天凌晨2点执行清理任务
request.setValue(typeValue);
request.setJob(IssueSyncJob.class.getName());
scheduleService.addSchedule(request);
scheduleService.addOrUpdateCronJob(request,
IssueSyncJob.getJobKey(projectId),
IssueSyncJob.getTriggerKey(projectId),
IssueSyncJob.class);
});
}
}
/**
* 获取同步缺陷配置
*
* @param projectId
* @return
*/
public Map<String, String> getIssueConfigInfo(String projectId) {
ProjectApplicationExample example = new ProjectApplicationExample();
example.createCriteria().andProjectIdEqualTo(projectId).andTypeLike(ProjectApplicationType.ISSUE.ISSUE_SYNC.name() + "_%");
List<ProjectApplication> list = projectApplicationMapper.selectByExample(example);
Map<String, String> collect = new HashMap<>();
if (CollectionUtils.isNotEmpty(list)) {
list.stream().forEach(config -> {
collect.put(config.getType().replace(ProjectApplicationType.ISSUE.ISSUE_SYNC.name() + "_", "").toLowerCase(), config.getTypeValue());
});
}
return collect;
}
/** /**
* 测试计划 日志 * 测试计划 日志
* *
@ -356,4 +423,115 @@ public class ProjectApplicationService {
return logs; return logs;
} }
/**
* 缺陷同步配置 日志
*
* @param projectId
* @param configs
* @return
*/
public LogDTO updateIssueSyncLog(String projectId, Map<String, String> configs) {
Map<String, String> originConfig = getIssueConfigInfo(projectId);
LogDTO dto = new LogDTO(
projectId,
"",
OperationLogConstants.SYSTEM,
null,
OperationLogType.UPDATE.name(),
OperationLogModule.PROJECT_PROJECT_MANAGER,
"同步缺陷");
dto.setModifiedValue(JSON.toJSONBytes(configs));
dto.setOriginalValue(JSON.toJSONBytes(originConfig));
return dto;
}
/**
* 关联需求配置 日志
* @param projectId
* @param configs
* @return
*/
public LogDTO updateRelatedRequirementsLog(String projectId, Map<String, String> configs) {
Map<String, String> originConfig = getRelatedConfigInfo(projectId);
LogDTO dto = new LogDTO(
projectId,
"",
OperationLogConstants.SYSTEM,
null,
OperationLogType.UPDATE.name(),
OperationLogModule.PROJECT_PROJECT_MANAGER,
"关联需求");
dto.setModifiedValue(JSON.toJSONBytes(configs));
dto.setOriginalValue(JSON.toJSONBytes(originConfig));
return dto;
}
/**
* 获取菜单列表
*
* @param projectId
* @return
*/
public Map<String, Boolean> getModuleSetting(String projectId) {
String moduleSetting = extProjectMapper.getModuleSetting(projectId);
Map<String, Boolean> moudleMap = new HashMap<>();
if (StringUtils.isNotEmpty(moduleSetting)) {
ProjectApplicationExample example = new ProjectApplicationExample();
JSON.parseArray(moduleSetting).forEach(module -> {
example.clear();
example.createCriteria().andTypeEqualTo(String.valueOf(module)).andProjectIdEqualTo(projectId);
List<ProjectApplication> applications = projectApplicationMapper.selectByExample(example);
if (CollectionUtils.isNotEmpty(applications)) {
moudleMap.put(String.valueOf(module), Boolean.valueOf(applications.get(0).getTypeValue()));
} else {
moudleMap.put(String.valueOf(module), Boolean.TRUE);
}
});
}
return moudleMap;
}
/**
* 用例关联需求配置
*
* @param projectId
* @param configs
*/
public void updateRelated(String projectId, Map<String, String> configs) {
List<ProjectApplication> relatedConfigs = configs.entrySet().stream().map(config -> new ProjectApplication(projectId, ProjectApplicationType.CASE_RELATED_CONFIG.CASE_RELATED.name() + "_" + config.getKey().toUpperCase(), config.getValue())).collect(Collectors.toList());
ProjectApplicationExample example = new ProjectApplicationExample();
example.createCriteria().andProjectIdEqualTo(projectId).andTypeLike(ProjectApplicationType.CASE_RELATED_CONFIG.CASE_RELATED.name() + "%");
if (projectApplicationMapper.countByExample(example) > 0) {
example.clear();
example.createCriteria().andTypeLike(ProjectApplicationType.CASE_RELATED_CONFIG.CASE_RELATED.name() + "%");
projectApplicationMapper.deleteByExample(example);
projectApplicationMapper.batchInsert(relatedConfigs);
} else {
projectApplicationMapper.batchInsert(relatedConfigs);
}
}
/**
* 获取用例关联需求配置
*
* @param projectId
* @return
*/
public Map<String, String> getRelatedConfigInfo(String projectId) {
ProjectApplicationExample example = new ProjectApplicationExample();
example.createCriteria().andProjectIdEqualTo(projectId).andTypeLike(ProjectApplicationType.CASE_RELATED_CONFIG.CASE_RELATED.name() + "_%");
List<ProjectApplication> list = projectApplicationMapper.selectByExample(example);
Map<String, String> collect = new HashMap<>();
if (CollectionUtils.isNotEmpty(list)) {
list.stream().forEach(config -> {
collect.put(config.getType().replace(ProjectApplicationType.CASE_RELATED_CONFIG.CASE_RELATED.name() + "_", "").toLowerCase(), config.getTypeValue());
});
}
return collect;
}
} }

View File

@ -233,7 +233,7 @@
}, },
{ {
"id": "PROJECT_APPLICATION_WORKSTATION:READ", "id": "PROJECT_APPLICATION_WORKSTATION:READ",
"name": "permission.project_application_workstation.reda" "name": "permission.project_application_workstation.read"
}, },
{ {
"id": "PROJECT_APPLICATION_WORKSTATION:UPDATE", "id": "PROJECT_APPLICATION_WORKSTATION:UPDATE",

View File

@ -27,9 +27,7 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.*;
import java.util.Arrays;
import java.util.List;
import static io.metersphere.sdk.constants.InternalUserRole.ADMIN; import static io.metersphere.sdk.constants.InternalUserRole.ADMIN;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
@ -155,7 +153,7 @@ public class ProjectApplicationControllerTests extends BaseTest {
@Test @Test
@Order(6) @Order(6)
public void testGetUiResourcePool() throws Exception { public void testGetUiResourcePool() throws Exception {
this.requestGetWithOkAndReturn(GET_UI_RESOURCE_POOL_URL + "/default_organization"); this.requestGetWithOkAndReturn(GET_UI_RESOURCE_POOL_URL + "/" + DEFAULT_PROJECT_ID);
} }
/** /**
* ==========UI测试 end========== * ==========UI测试 end==========
@ -312,7 +310,7 @@ public class ProjectApplicationControllerTests extends BaseTest {
@Test @Test
@Order(21) @Order(21)
public void testGetApiResourcePool() throws Exception { public void testGetApiResourcePool() throws Exception {
this.requestGetWithOkAndReturn(GET_API_RESOURCE_POOL_URL + "/100001"); this.requestGetWithOkAndReturn(GET_API_RESOURCE_POOL_URL + "/" + DEFAULT_PROJECT_ID);
} }
/** /**
* ==========接口测试 end========== * ==========接口测试 end==========
@ -394,7 +392,7 @@ public class ProjectApplicationControllerTests extends BaseTest {
@Test @Test
@Order(27) @Order(27)
public void testWorkstation() throws Exception { public void testWorkstation() throws Exception {
List<ProjectApplication> request = creatRequest(Arrays.asList(ProjectApplicationType.WORKSTATION.WORKSTATION.name()), "true"); List<ProjectApplication> request = creatRequest(Arrays.asList(ProjectApplicationType.WORKSTATION.WORKSTATION_SYNC_RULE.name()), "true");
this.requestPost(WORKSTATION_UPDATE_URL, request); this.requestPost(WORKSTATION_UPDATE_URL, request);
} }
@ -550,4 +548,125 @@ public class ProjectApplicationControllerTests extends BaseTest {
return list; return list;
} }
public static final String UPDATE_ISSUE_CONFIG_URL = "/project/application/update/issue/sync";
public static final String GET_ISSUE_CONFIG_INFO_URL = "/project/application/issue/sync/info";
@Test
@Order(34)
public void testIssueConfig() throws Exception {
Map<String, String> congifs = mockTeseData();
MvcResult mvcResult = this.requestPostWithOkAndReturn(UPDATE_ISSUE_CONFIG_URL + "/default-project-2", congifs);
// 获取返回值
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
// 返回请求正常
Assertions.assertNotNull(resultHolder);
//更新
congifs.put("jiraKey", "222");
MvcResult updateResult = this.requestPostWithOkAndReturn(UPDATE_ISSUE_CONFIG_URL + "/default-project-2", congifs);
// 获取返回值
String updateData = updateResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder updateResultHolder = JSON.parseObject(updateData, ResultHolder.class);
// 返回请求正常
Assertions.assertNotNull(updateResultHolder);
}
private Map<String, String> mockTeseData() {
Map<String, String> configs = new HashMap<>();
configs.put("platform", "jira");
configs.put("jiraKey", "111");
configs.put("jiraIssueTypeId", "10086");
configs.put("jiraStoryTypeId", "10010");
configs.put("CRON_EXPRESSION", "0 0 0/1 * * ?");
configs.put("ENABLE", "true");
configs.put("MECHANISM", "1");
return configs;
}
@Test
@Order(35)
public void testIssueConfigInfo() throws Exception {
MvcResult mvcResult = this.requestGetWithOkAndReturn(GET_ISSUE_CONFIG_INFO_URL + "/default-project-2");
// 获取返回值
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
// 返回请求正常
Assertions.assertNotNull(resultHolder);
}
public static final String GET_MODULE_SETTING_URL = "/project/application/module-setting";
@Test
@Order(36)
public void testGetModuleSetting() throws Exception {
MvcResult mvcResult = this.requestGetWithOkAndReturn(GET_MODULE_SETTING_URL + "/100001100001");
// 获取返回值
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
// 返回请求正常
Assertions.assertNotNull(resultHolder);
//更新
List<ProjectApplication> request = creatRequest(Arrays.asList("bugManagement"), "false");
request.get(0).setProjectId("100001100001");
this.requestPost(ISSUE_UPDATE_URL, request);
MvcResult updateMvcResult = this.requestGetWithOkAndReturn(GET_MODULE_SETTING_URL + "/100001100001");
// 获取返回值
String updateReturnData = updateMvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder updateResultHolder = JSON.parseObject(updateReturnData, ResultHolder.class);
// 返回请求正常
Assertions.assertNotNull(updateResultHolder);
}
public static final String UPDATE_CASE_RELATED_CONFIG_URL = "/project/application/update/case/related";
public static final String GET_CASE_RELATED_CONFIG_INFO_URL = "/project/application/case/related/info";
@Test
@Order(37)
public void testCaseRelatedConfig() throws Exception {
Map<String, String> congifs = mockRelatedTeseData();
MvcResult mvcResult = this.requestPostWithOkAndReturn(UPDATE_CASE_RELATED_CONFIG_URL + "/default-project-2", congifs);
// 获取返回值
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
// 返回请求正常
Assertions.assertNotNull(resultHolder);
//更新
congifs.put("jiraKey", "222");
MvcResult updateResult = this.requestPostWithOkAndReturn(UPDATE_CASE_RELATED_CONFIG_URL + "/default-project-2", congifs);
// 获取返回值
String updateData = updateResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder updateResultHolder = JSON.parseObject(updateData, ResultHolder.class);
// 返回请求正常
Assertions.assertNotNull(updateResultHolder);
}
private Map<String, String> mockRelatedTeseData() {
Map<String, String> configs = new HashMap<>();
configs.put("platform", "jira");
configs.put("jiraKey", "111");
configs.put("jiraIssueTypeId", "10086");
configs.put("jiraStoryTypeId", "10010");
configs.put("ENABLE", "true");
return configs;
}
@Test
@Order(38)
public void testCaseRelatedConfigInfo() throws Exception {
MvcResult mvcResult = this.requestGetWithOkAndReturn(GET_CASE_RELATED_CONFIG_INFO_URL + "/default-project-2");
// 获取返回值
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
// 返回请求正常
Assertions.assertNotNull(resultHolder);
}
} }