feat(缺陷管理): 补充缺陷管理变更日志历史及通知
This commit is contained in:
parent
b5a5f6d899
commit
0f24d581b0
|
@ -184,6 +184,7 @@ message.execute_fail=执行不通过
|
||||||
message.execute_at=执行被@
|
message.execute_at=执行被@
|
||||||
message.open=开启
|
message.open=开启
|
||||||
message.close=关闭
|
message.close=关闭
|
||||||
|
message.sync_completed=同步完成
|
||||||
message.create_user=创建人
|
message.create_user=创建人
|
||||||
message.follow_people=关注人
|
message.follow_people=关注人
|
||||||
message.operator=操作人
|
message.operator=操作人
|
||||||
|
|
|
@ -220,6 +220,7 @@ message.execute_fail=Execution failed
|
||||||
message.execute_at=Execution is @
|
message.execute_at=Execution is @
|
||||||
message.open=turn on
|
message.open=turn on
|
||||||
message.close=closure
|
message.close=closure
|
||||||
|
message.sync_completed=Sync completed
|
||||||
message.create_user=Create user
|
message.create_user=Create user
|
||||||
message.follow_people=Follow people
|
message.follow_people=Follow people
|
||||||
message.operator=Operator
|
message.operator=Operator
|
||||||
|
|
|
@ -220,6 +220,7 @@ message.execute_fail=执行不通过
|
||||||
message.execute_at=执行被@
|
message.execute_at=执行被@
|
||||||
message.open=开启
|
message.open=开启
|
||||||
message.close=关闭
|
message.close=关闭
|
||||||
|
message.sync_completed=同步完成
|
||||||
message.create_user=创建人
|
message.create_user=创建人
|
||||||
message.follow_people=关注人
|
message.follow_people=关注人
|
||||||
message.operator=操作人
|
message.operator=操作人
|
||||||
|
|
|
@ -220,6 +220,7 @@ message.execute_fail=執行不通過
|
||||||
message.execute_at=執行被@
|
message.execute_at=執行被@
|
||||||
message.open=開啟
|
message.open=開啟
|
||||||
message.close=關閉
|
message.close=關閉
|
||||||
|
message.sync_completed=同步完成
|
||||||
message.create_user=創建人
|
message.create_user=創建人
|
||||||
message.follow_people=關注人
|
message.follow_people=關注人
|
||||||
message.operator=操作人
|
message.operator=操作人
|
||||||
|
|
|
@ -4,9 +4,13 @@ import io.metersphere.bug.domain.BugComment;
|
||||||
import io.metersphere.bug.dto.request.BugCommentEditRequest;
|
import io.metersphere.bug.dto.request.BugCommentEditRequest;
|
||||||
import io.metersphere.bug.dto.response.BugCommentDTO;
|
import io.metersphere.bug.dto.response.BugCommentDTO;
|
||||||
import io.metersphere.bug.service.BugCommentService;
|
import io.metersphere.bug.service.BugCommentService;
|
||||||
|
import io.metersphere.sdk.constants.PermissionConstants;
|
||||||
|
import io.metersphere.system.security.CheckOwner;
|
||||||
import io.metersphere.system.utils.SessionUtils;
|
import io.metersphere.system.utils.SessionUtils;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
|
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -20,21 +24,32 @@ public class BugCommentController {
|
||||||
private BugCommentService bugCommentService;
|
private BugCommentService bugCommentService;
|
||||||
|
|
||||||
@GetMapping("/get/{bugId}")
|
@GetMapping("/get/{bugId}")
|
||||||
|
@Operation(summary = "缺陷管理-评论-获取评论")
|
||||||
|
@RequiresPermissions(PermissionConstants.PROJECT_BUG_READ)
|
||||||
|
@CheckOwner(resourceId = "#bugId", resourceType = "bug")
|
||||||
public List<BugCommentDTO> get(@PathVariable String bugId) {
|
public List<BugCommentDTO> get(@PathVariable String bugId) {
|
||||||
return bugCommentService.getComments(bugId);
|
return bugCommentService.getComments(bugId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/add")
|
@PostMapping("/add")
|
||||||
|
@Operation(summary = "缺陷管理-评论-新增评论")
|
||||||
|
@RequiresPermissions(PermissionConstants.PROJECT_BUG_READ)
|
||||||
|
@CheckOwner(resourceId = "#request.getBugId()", resourceType = "bug")
|
||||||
public BugComment add(@RequestBody BugCommentEditRequest request) {
|
public BugComment add(@RequestBody BugCommentEditRequest request) {
|
||||||
return bugCommentService.addComment(request, SessionUtils.getUserId());
|
return bugCommentService.addComment(request, SessionUtils.getUserId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/update")
|
@PostMapping("/update")
|
||||||
|
@Operation(summary = "缺陷管理-评论-编辑评论")
|
||||||
|
@RequiresPermissions(PermissionConstants.PROJECT_BUG_READ)
|
||||||
|
@CheckOwner(resourceId = "#request.getBugId()", resourceType = "bug")
|
||||||
public BugComment update(@RequestBody BugCommentEditRequest request) {
|
public BugComment update(@RequestBody BugCommentEditRequest request) {
|
||||||
return bugCommentService.updateComment(request, SessionUtils.getUserId());
|
return bugCommentService.updateComment(request, SessionUtils.getUserId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/delete/{commentId}")
|
@GetMapping("/delete/{commentId}")
|
||||||
|
@Operation(summary = "缺陷管理-评论-删除评论")
|
||||||
|
@RequiresPermissions(PermissionConstants.PROJECT_BUG_READ)
|
||||||
public void delete(@PathVariable String commentId) {
|
public void delete(@PathVariable String commentId) {
|
||||||
bugCommentService.deleteComment(commentId);
|
bugCommentService.deleteComment(commentId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,7 @@ import io.metersphere.bug.constants.BugExportColumns;
|
||||||
import io.metersphere.bug.dto.BugSyncResult;
|
import io.metersphere.bug.dto.BugSyncResult;
|
||||||
import io.metersphere.bug.dto.request.*;
|
import io.metersphere.bug.dto.request.*;
|
||||||
import io.metersphere.bug.dto.response.BugDTO;
|
import io.metersphere.bug.dto.response.BugDTO;
|
||||||
import io.metersphere.bug.service.BugService;
|
import io.metersphere.bug.service.*;
|
||||||
import io.metersphere.bug.service.BugStatusService;
|
|
||||||
import io.metersphere.bug.service.BugSyncService;
|
|
||||||
import io.metersphere.plugin.platform.dto.SelectOption;
|
import io.metersphere.plugin.platform.dto.SelectOption;
|
||||||
import io.metersphere.project.dto.ProjectTemplateOptionDTO;
|
import io.metersphere.project.dto.ProjectTemplateOptionDTO;
|
||||||
import io.metersphere.project.service.ProjectTemplateService;
|
import io.metersphere.project.service.ProjectTemplateService;
|
||||||
|
@ -16,6 +14,11 @@ import io.metersphere.sdk.constants.PermissionConstants;
|
||||||
import io.metersphere.sdk.constants.TemplateScene;
|
import io.metersphere.sdk.constants.TemplateScene;
|
||||||
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.log.annotation.Log;
|
||||||
|
import io.metersphere.system.log.constants.OperationLogType;
|
||||||
|
import io.metersphere.system.notice.annotation.SendNotice;
|
||||||
|
import io.metersphere.system.notice.constants.NoticeConstants;
|
||||||
|
import io.metersphere.system.security.CheckOwner;
|
||||||
import io.metersphere.system.utils.PageUtils;
|
import io.metersphere.system.utils.PageUtils;
|
||||||
import io.metersphere.system.utils.Pager;
|
import io.metersphere.system.utils.Pager;
|
||||||
import io.metersphere.system.utils.SessionUtils;
|
import io.metersphere.system.utils.SessionUtils;
|
||||||
|
@ -51,29 +54,33 @@ public class BugController {
|
||||||
private ProjectTemplateService projectTemplateService;
|
private ProjectTemplateService projectTemplateService;
|
||||||
|
|
||||||
@GetMapping("/header/custom-field/{projectId}")
|
@GetMapping("/header/custom-field/{projectId}")
|
||||||
@Operation(summary = "缺陷管理-获取表头自定义字段")
|
@Operation(summary = "缺陷管理-列表-获取表头自定义字段")
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_READ)
|
@RequiresPermissions(PermissionConstants.PROJECT_BUG_READ)
|
||||||
|
@CheckOwner(resourceId = "#projectId", resourceType = "project")
|
||||||
public List<TemplateCustomFieldDTO> getHeaderFields(@PathVariable String projectId) {
|
public List<TemplateCustomFieldDTO> getHeaderFields(@PathVariable String projectId) {
|
||||||
return bugService.getHeaderCustomFields(projectId);
|
return bugService.getHeaderCustomFields(projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/header/status-option/{projectId}")
|
@GetMapping("/header/status-option/{projectId}")
|
||||||
@Operation(summary = "缺陷管理-获取表头状态选项")
|
@Operation(summary = "缺陷管理-列表-获取表头状态选项")
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_READ)
|
@RequiresPermissions(PermissionConstants.PROJECT_BUG_READ)
|
||||||
|
@CheckOwner(resourceId = "#projectId", resourceType = "project")
|
||||||
public List<SelectOption> getHeaderStatusOption(@PathVariable String projectId) {
|
public List<SelectOption> getHeaderStatusOption(@PathVariable String projectId) {
|
||||||
return bugStatusService.getHeaderStatusOption(projectId);
|
return bugStatusService.getHeaderStatusOption(projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/header/handler-option/{projectId}")
|
@GetMapping("/header/handler-option/{projectId}")
|
||||||
@Operation(summary = "缺陷管理-获取表头处理人选项")
|
@Operation(summary = "缺陷管理-列表-获取表头处理人选项")
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_READ)
|
@RequiresPermissions(PermissionConstants.PROJECT_BUG_READ)
|
||||||
|
@CheckOwner(resourceId = "#projectId", resourceType = "project")
|
||||||
public List<SelectOption> getHeaderHandleOption(@PathVariable String projectId) {
|
public List<SelectOption> getHeaderHandleOption(@PathVariable String projectId) {
|
||||||
return bugService.getHeaderHandlerOption(projectId);
|
return bugService.getHeaderHandlerOption(projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/page")
|
@PostMapping("/page")
|
||||||
@Operation(summary = "缺陷管理-获取缺陷列表")
|
@Operation(summary = "缺陷管理-列表-分页缺陷列表")
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_READ)
|
@RequiresPermissions(PermissionConstants.PROJECT_BUG_READ)
|
||||||
|
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||||
public Pager<List<BugDTO>> page(@Validated @RequestBody BugPageRequest request) {
|
public Pager<List<BugDTO>> page(@Validated @RequestBody BugPageRequest request) {
|
||||||
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
|
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
|
||||||
StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "create_time desc");
|
StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "create_time desc");
|
||||||
|
@ -82,104 +89,121 @@ public class BugController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/add")
|
@PostMapping("/add")
|
||||||
@Operation(summary = "缺陷管理-创建缺陷")
|
@Operation(summary = "缺陷管理-列表-创建缺陷")
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_ADD)
|
@RequiresPermissions(PermissionConstants.PROJECT_BUG_ADD)
|
||||||
|
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||||
|
@Log(type = OperationLogType.ADD, expression = "#msClass.addLog(#request, #files)", msClass = BugLogService.class)
|
||||||
|
@SendNotice(taskType = NoticeConstants.TaskType.BUG_TASK, event = NoticeConstants.Event.CREATE, target = "#targetClass.getNoticeByRequest(#request)", targetClass = BugNoticeService.class)
|
||||||
public void add(@Validated({Created.class}) @RequestPart(value = "request") BugEditRequest request,
|
public void add(@Validated({Created.class}) @RequestPart(value = "request") BugEditRequest request,
|
||||||
@RequestPart(value = "file", required = false) List<MultipartFile> files) {
|
@RequestPart(value = "file", required = false) List<MultipartFile> files) {
|
||||||
bugService.addOrUpdate(request, files, SessionUtils.getUserId(), SessionUtils.getCurrentOrganizationId(), false);
|
bugService.addOrUpdate(request, files, SessionUtils.getUserId(), SessionUtils.getCurrentOrganizationId(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/update")
|
@PostMapping("/update")
|
||||||
@Operation(summary = "缺陷管理-更新缺陷")
|
@Operation(summary = "缺陷管理-列表-编辑缺陷")
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_UPDATE)
|
@RequiresPermissions(PermissionConstants.PROJECT_BUG_UPDATE)
|
||||||
|
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||||
|
@Log(type = OperationLogType.UPDATE, expression = "#msClass.updateLog(#request, #files)", msClass = BugLogService.class)
|
||||||
|
@SendNotice(taskType = NoticeConstants.TaskType.BUG_TASK, event = NoticeConstants.Event.UPDATE, target = "#targetClass.getNoticeByRequest(#request)", targetClass = BugNoticeService.class)
|
||||||
public void update(@Validated({Updated.class}) @RequestPart(value = "request") BugEditRequest request,
|
public void update(@Validated({Updated.class}) @RequestPart(value = "request") BugEditRequest request,
|
||||||
@RequestPart(value = "file", required = false) List<MultipartFile> files) {
|
@RequestPart(value = "file", required = false) List<MultipartFile> files) {
|
||||||
bugService.addOrUpdate(request, files, SessionUtils.getUserId(), SessionUtils.getCurrentOrganizationId(), true);
|
bugService.addOrUpdate(request, files, SessionUtils.getUserId(), SessionUtils.getCurrentOrganizationId(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/delete/{id}")
|
@GetMapping("/delete/{id}")
|
||||||
@Operation(summary = "缺陷管理-删除缺陷")
|
@Operation(summary = "缺陷管理-列表-删除缺陷")
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_DELETE)
|
@RequiresPermissions(PermissionConstants.PROJECT_BUG_DELETE)
|
||||||
|
@Log(type = OperationLogType.DELETE, expression = "#msClass.deleteLog(#id)", msClass = BugLogService.class)
|
||||||
|
@SendNotice(taskType = NoticeConstants.TaskType.BUG_TASK, event = NoticeConstants.Event.DELETE, target = "#targetClass.getNoticeById(#id)", targetClass = BugNoticeService.class)
|
||||||
public void delete(@PathVariable String id) {
|
public void delete(@PathVariable String id) {
|
||||||
bugService.delete(id);
|
bugService.delete(id, SessionUtils.getUserId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/template/option")
|
@GetMapping("/sync/{projectId}")
|
||||||
@Operation(summary = "缺陷管理-获取当前项目缺陷模板选项")
|
@Operation(summary = "缺陷管理-列表-同步缺陷(开源)")
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_READ)
|
@RequiresPermissions(PermissionConstants.PROJECT_BUG_UPDATE)
|
||||||
public List<ProjectTemplateOptionDTO> getTemplateOption(@RequestParam(value = "projectId") String projectId) {
|
@CheckOwner(resourceId = "#projectId", resourceType = "project")
|
||||||
return projectTemplateService.getOption(projectId, TemplateScene.BUG.name());
|
public void sync(@PathVariable String projectId) {
|
||||||
|
bugSyncService.syncBugs(projectId, SessionUtils.getUserId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/template/detail")
|
@PostMapping("/sync/all")
|
||||||
@Operation(summary = "缺陷管理-获取模板详情内容")
|
@Operation(summary = "缺陷管理-列表-同步缺陷(全量)")
|
||||||
|
@RequiresPermissions(PermissionConstants.PROJECT_BUG_UPDATE)
|
||||||
|
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||||
|
public void syncAll(@RequestBody BugSyncRequest request) {
|
||||||
|
bugSyncService.syncAllBugs(request, SessionUtils.getUserId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/sync/check/{projectId}")
|
||||||
|
@Operation(summary = "缺陷管理-列表-同步状态校验")
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_READ)
|
@RequiresPermissions(PermissionConstants.PROJECT_BUG_READ)
|
||||||
public TemplateDTO getTemplateDetail(@RequestBody BugTemplateRequest request) {
|
@CheckOwner(resourceId = "#projectId", resourceType = "project")
|
||||||
return bugService.getTemplate(request.getId(), request.getProjectId(), request.getFromStatusId(), request.getPlatformBugKey());
|
public BugSyncResult checkStatus(@PathVariable String projectId) {
|
||||||
|
return bugSyncService.checkSyncStatus(projectId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/export/columns/{projectId}")
|
||||||
|
@Operation(summary = "缺陷管理-列表-获取导出字段配置")
|
||||||
|
@RequiresPermissions(PermissionConstants.PROJECT_BUG_EXPORT)
|
||||||
|
@CheckOwner(resourceId = "#projectId", resourceType = "project")
|
||||||
|
public BugExportColumns getExportColumns(@PathVariable String projectId) {
|
||||||
|
return bugService.getExportColumns(projectId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/export")
|
||||||
|
@Operation(summary = "缺陷管理-列表-批量导出缺陷")
|
||||||
|
@RequiresPermissions(PermissionConstants.PROJECT_BUG_EXPORT)
|
||||||
|
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||||
|
public ResponseEntity<byte[]> export(@Validated @RequestBody BugExportRequest request) throws Exception {
|
||||||
|
return bugService.export(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/batch-delete")
|
@PostMapping("/batch-delete")
|
||||||
@Operation(summary = "缺陷管理-批量删除缺陷")
|
@Operation(summary = "缺陷管理-列表-批量删除缺陷")
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_DELETE)
|
@RequiresPermissions(PermissionConstants.PROJECT_BUG_DELETE)
|
||||||
|
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||||
public void batchDelete(@Validated @RequestBody BugBatchRequest request) {
|
public void batchDelete(@Validated @RequestBody BugBatchRequest request) {
|
||||||
request.setUseTrash(false);
|
request.setUseTrash(false);
|
||||||
bugService.batchDelete(request);
|
bugService.batchDelete(request, SessionUtils.getUserId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/batch-update")
|
@PostMapping("/batch-update")
|
||||||
@Operation(summary = "缺陷管理-批量编辑缺陷")
|
@Operation(summary = "缺陷管理-列表-批量编辑缺陷")
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_UPDATE)
|
@RequiresPermissions(PermissionConstants.PROJECT_BUG_UPDATE)
|
||||||
|
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||||
public void batchUpdate(@Validated @RequestBody BugBatchUpdateRequest request) {
|
public void batchUpdate(@Validated @RequestBody BugBatchUpdateRequest request) {
|
||||||
request.setUseTrash(false);
|
request.setUseTrash(false);
|
||||||
bugService.batchUpdate(request, SessionUtils.getUserId());
|
bugService.batchUpdate(request, SessionUtils.getUserId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/template/option/{projectId}")
|
||||||
|
@Operation(summary = "缺陷管理-详情-获取当前项目模板选项")
|
||||||
|
@RequiresPermissions(PermissionConstants.PROJECT_BUG_READ)
|
||||||
|
@CheckOwner(resourceId = "#projectId", resourceType = "project")
|
||||||
|
public List<ProjectTemplateOptionDTO> getTemplateOption(@PathVariable String projectId) {
|
||||||
|
return projectTemplateService.getOption(projectId, TemplateScene.BUG.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/template/detail")
|
||||||
|
@Operation(summary = "缺陷管理-详情-获取模板详情内容")
|
||||||
|
@RequiresPermissions(PermissionConstants.PROJECT_BUG_READ)
|
||||||
|
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||||
|
public TemplateDTO getTemplateDetail(@RequestBody BugTemplateRequest request) {
|
||||||
|
return bugService.getTemplate(request.getId(), request.getProjectId(), request.getFromStatusId(), request.getPlatformBugKey());
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/follow/{id}")
|
@GetMapping("/follow/{id}")
|
||||||
@Operation(summary = "缺陷管理-关注缺陷")
|
@Operation(summary = "缺陷管理-详情-关注缺陷")
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_UPDATE)
|
@RequiresPermissions(PermissionConstants.PROJECT_BUG_UPDATE)
|
||||||
public void follow(@PathVariable String id) {
|
public void follow(@PathVariable String id) {
|
||||||
bugService.follow(id, SessionUtils.getUserId());
|
bugService.follow(id, SessionUtils.getUserId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/unfollow/{id}")
|
@GetMapping("/unfollow/{id}")
|
||||||
@Operation(summary = "缺陷管理-取消关注缺陷")
|
@Operation(summary = "缺陷管理-详情-取消关注缺陷")
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_UPDATE)
|
@RequiresPermissions(PermissionConstants.PROJECT_BUG_UPDATE)
|
||||||
public void unfollow(@PathVariable String id) {
|
public void unfollow(@PathVariable String id) {
|
||||||
bugService.unfollow(id, SessionUtils.getUserId());
|
bugService.unfollow(id, SessionUtils.getUserId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/sync/{projectId}")
|
|
||||||
@Operation(summary = "缺陷管理-同步缺陷(开源)")
|
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_UPDATE)
|
|
||||||
public void sync(@PathVariable String projectId) {
|
|
||||||
bugSyncService.syncBugs(projectId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("/sync/all")
|
|
||||||
@Operation(summary = "缺陷管理-同步缺陷(全量)")
|
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_UPDATE)
|
|
||||||
public void syncAll(@RequestBody BugSyncRequest request) {
|
|
||||||
bugSyncService.syncAllBugs(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/sync/check/{projectId}")
|
|
||||||
@Operation(summary = "缺陷管理-同步状态校验")
|
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_READ)
|
|
||||||
public BugSyncResult checkStatus(@PathVariable String projectId) {
|
|
||||||
return bugSyncService.checkSyncStatus(projectId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/export/columns/{projectId}")
|
|
||||||
@Operation(summary = "缺陷管理-获取导出字段配置")
|
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_EXPORT)
|
|
||||||
public BugExportColumns getExportColumns(@PathVariable String projectId) {
|
|
||||||
return bugService.getExportColumns(projectId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("/export")
|
|
||||||
@Operation(summary = "缺陷管理-批量导出缺陷")
|
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_EXPORT)
|
|
||||||
public ResponseEntity<byte[]> export(@Validated @RequestBody BugExportRequest request) throws Exception {
|
|
||||||
return bugService.export(request);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import com.github.pagehelper.PageHelper;
|
||||||
import io.metersphere.bug.dto.request.BugRelatedCasePageRequest;
|
import io.metersphere.bug.dto.request.BugRelatedCasePageRequest;
|
||||||
import io.metersphere.bug.dto.response.BugRelateCaseDTO;
|
import io.metersphere.bug.dto.response.BugRelateCaseDTO;
|
||||||
import io.metersphere.bug.service.BugRelateCaseCommonService;
|
import io.metersphere.bug.service.BugRelateCaseCommonService;
|
||||||
|
import io.metersphere.bug.service.BugRelateCaseLogService;
|
||||||
import io.metersphere.dto.TestCaseProviderDTO;
|
import io.metersphere.dto.TestCaseProviderDTO;
|
||||||
import io.metersphere.provider.BaseAssociateCaseProvider;
|
import io.metersphere.provider.BaseAssociateCaseProvider;
|
||||||
import io.metersphere.request.AssociateCaseModuleRequest;
|
import io.metersphere.request.AssociateCaseModuleRequest;
|
||||||
|
@ -12,6 +13,8 @@ import io.metersphere.request.AssociateOtherCaseRequest;
|
||||||
import io.metersphere.request.TestCasePageProviderRequest;
|
import io.metersphere.request.TestCasePageProviderRequest;
|
||||||
import io.metersphere.sdk.constants.PermissionConstants;
|
import io.metersphere.sdk.constants.PermissionConstants;
|
||||||
import io.metersphere.system.dto.sdk.BaseTreeNode;
|
import io.metersphere.system.dto.sdk.BaseTreeNode;
|
||||||
|
import io.metersphere.system.log.annotation.Log;
|
||||||
|
import io.metersphere.system.log.constants.OperationLogType;
|
||||||
import io.metersphere.system.security.CheckOwner;
|
import io.metersphere.system.security.CheckOwner;
|
||||||
import io.metersphere.system.utils.PageUtils;
|
import io.metersphere.system.utils.PageUtils;
|
||||||
import io.metersphere.system.utils.Pager;
|
import io.metersphere.system.utils.Pager;
|
||||||
|
@ -80,6 +83,7 @@ public class BugRelateCaseController {
|
||||||
@GetMapping("/un-relate/{id}")
|
@GetMapping("/un-relate/{id}")
|
||||||
@Operation(description = "缺陷管理-关联用例-取消关联用例")
|
@Operation(description = "缺陷管理-关联用例-取消关联用例")
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_UPDATE)
|
@RequiresPermissions(PermissionConstants.PROJECT_BUG_UPDATE)
|
||||||
|
@Log(type = OperationLogType.DISASSOCIATE, expression = "#msClass.getRelateLog(#id)", msClass = BugRelateCaseLogService.class)
|
||||||
public void unRelate(@PathVariable String id) {
|
public void unRelate(@PathVariable String id) {
|
||||||
bugRelateCaseCommonService.unRelate(id);
|
bugRelateCaseCommonService.unRelate(id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,12 @@ import com.github.pagehelper.PageHelper;
|
||||||
import io.metersphere.bug.dto.request.BugBatchRequest;
|
import io.metersphere.bug.dto.request.BugBatchRequest;
|
||||||
import io.metersphere.bug.dto.request.BugPageRequest;
|
import io.metersphere.bug.dto.request.BugPageRequest;
|
||||||
import io.metersphere.bug.dto.response.BugDTO;
|
import io.metersphere.bug.dto.response.BugDTO;
|
||||||
|
import io.metersphere.bug.service.BugLogService;
|
||||||
import io.metersphere.bug.service.BugService;
|
import io.metersphere.bug.service.BugService;
|
||||||
import io.metersphere.sdk.constants.PermissionConstants;
|
import io.metersphere.sdk.constants.PermissionConstants;
|
||||||
|
import io.metersphere.system.log.annotation.Log;
|
||||||
|
import io.metersphere.system.log.constants.OperationLogType;
|
||||||
|
import io.metersphere.system.security.CheckOwner;
|
||||||
import io.metersphere.system.utils.PageUtils;
|
import io.metersphere.system.utils.PageUtils;
|
||||||
import io.metersphere.system.utils.Pager;
|
import io.metersphere.system.utils.Pager;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
@ -40,6 +44,7 @@ public class BugTrashController {
|
||||||
@GetMapping("/recover/{id}")
|
@GetMapping("/recover/{id}")
|
||||||
@Operation(summary = "回收站-恢复")
|
@Operation(summary = "回收站-恢复")
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_UPDATE)
|
@RequiresPermissions(PermissionConstants.PROJECT_BUG_UPDATE)
|
||||||
|
@Log(type = OperationLogType.RECOVER, expression = "#msClass.recoverLog(#id)", msClass = BugLogService.class)
|
||||||
public void recover(@PathVariable String id) {
|
public void recover(@PathVariable String id) {
|
||||||
bugService.recover(id);
|
bugService.recover(id);
|
||||||
}
|
}
|
||||||
|
@ -54,6 +59,7 @@ public class BugTrashController {
|
||||||
@PostMapping("/batch-recover")
|
@PostMapping("/batch-recover")
|
||||||
@Operation(summary = "回收站-批量恢复")
|
@Operation(summary = "回收站-批量恢复")
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_UPDATE)
|
@RequiresPermissions(PermissionConstants.PROJECT_BUG_UPDATE)
|
||||||
|
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||||
public void batchRecover(@Validated @RequestBody BugBatchRequest request) {
|
public void batchRecover(@Validated @RequestBody BugBatchRequest request) {
|
||||||
request.setUseTrash(true);
|
request.setUseTrash(true);
|
||||||
bugService.batchRecover(request);
|
bugService.batchRecover(request);
|
||||||
|
@ -62,6 +68,7 @@ public class BugTrashController {
|
||||||
@PostMapping("/batch-delete")
|
@PostMapping("/batch-delete")
|
||||||
@Operation(summary = "回收站-批量彻底删除")
|
@Operation(summary = "回收站-批量彻底删除")
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_DELETE)
|
@RequiresPermissions(PermissionConstants.PROJECT_BUG_DELETE)
|
||||||
|
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||||
public void batchDelete(@Validated @RequestBody BugBatchRequest request) {
|
public void batchDelete(@Validated @RequestBody BugBatchRequest request) {
|
||||||
request.setUseTrash(true);
|
request.setUseTrash(true);
|
||||||
bugService.batchDeleteTrash(request);
|
bugService.batchDeleteTrash(request);
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
package io.metersphere.bug.dto.response;
|
package io.metersphere.bug.dto.response;
|
||||||
|
|
||||||
import io.metersphere.functional.domain.FunctionalCase;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = false)
|
@EqualsAndHashCode(callSuper = false)
|
||||||
public class BugRelateCaseDTO extends FunctionalCase {
|
public class BugRelateCaseDTO{
|
||||||
|
|
||||||
@Schema(description = "关联ID")
|
@Schema(description = "关联ID")
|
||||||
private String relateId;
|
private String relateId;
|
||||||
|
|
||||||
|
@Schema(description = "关联用例名称")
|
||||||
|
private String relateCaseName;
|
||||||
|
|
||||||
@Schema(description = "关联类型")
|
@Schema(description = "关联类型")
|
||||||
private String relateCaseType;
|
private String relateCaseType;
|
||||||
|
|
||||||
|
@ -29,4 +31,10 @@ public class BugRelateCaseDTO extends FunctionalCase {
|
||||||
|
|
||||||
@Schema(description = "版本名称")
|
@Schema(description = "版本名称")
|
||||||
private String versionName;
|
private String versionName;
|
||||||
|
|
||||||
|
@Schema(description = "项目ID")
|
||||||
|
private String projectId;
|
||||||
|
|
||||||
|
@Schema(description = "版本ID")
|
||||||
|
private String versionId;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ public enum BugAttachmentSourceType {
|
||||||
*/
|
*/
|
||||||
ATTACHMENT,
|
ATTACHMENT,
|
||||||
/**
|
/**
|
||||||
* MarkDown编辑器
|
* MD图片
|
||||||
*/
|
*/
|
||||||
MD;
|
MD_PIC;
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,5 +50,14 @@ public interface ExtBugRelateCaseMapper {
|
||||||
*/
|
*/
|
||||||
List<BugRelateCaseDTO> list(@Param("request") BugRelatedCasePageRequest request);
|
List<BugRelateCaseDTO> list(@Param("request") BugRelatedCasePageRequest request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据CaseId获取关联的Case
|
||||||
|
* @param id 用例ID
|
||||||
|
* @param sourceType 用例类型
|
||||||
|
* @return 用例关联DTO
|
||||||
|
*/
|
||||||
|
BugRelateCaseDTO getRelateCase(@Param("id") String id, @Param("sourceType") String sourceType);
|
||||||
|
|
||||||
|
|
||||||
List<BugProviderDTO> getAssociateBugs(@Param("request") AssociateBugPageRequest request, @Param("sort") String sort);
|
List<BugProviderDTO> getAssociateBugs(@Param("request") AssociateBugPageRequest request, @Param("sort") String sort);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="list" resultType="io.metersphere.bug.dto.response.BugRelateCaseDTO">
|
<select id="list" resultType="io.metersphere.bug.dto.response.BugRelateCaseDTO">
|
||||||
select fc.num, fc.name, fc.project_id, fc.version_id, brc.case_type relateCaseType, brc.id relateId,
|
select fc.num relateId, fc.name relateCaseName, fc.project_id projectId, fc.version_id versionId, brc.case_type relateCaseType,
|
||||||
brc.test_plan_id is not null relatePlanCase, brc.case_id is not null relateCase
|
brc.test_plan_id is not null relatePlanCase, brc.case_id is not null relateCase
|
||||||
from bug_relation_case brc join functional_case fc on (brc.case_id = fc.id or brc.test_plan_case_id = fc.id)
|
from bug_relation_case brc join functional_case fc on (brc.case_id = fc.id or brc.test_plan_case_id = fc.id)
|
||||||
where brc.bug_id = #{request.bugId} and fc.deleted = false
|
where brc.bug_id = #{request.bugId} and fc.deleted = false
|
||||||
|
@ -55,6 +55,17 @@
|
||||||
</if>
|
</if>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="getRelateCase" resultType="io.metersphere.bug.dto.response.BugRelateCaseDTO">
|
||||||
|
select distinct c.name relateCaseName, c.project_id projectId, c.version_id versionId, brc.case_type relateCaseType, c.num relateId,
|
||||||
|
brc.test_plan_id is not null relatePlanCase, brc.case_id is not null relateCase
|
||||||
|
from bug_relation_case brc
|
||||||
|
<if test="sourceType == 'FUNCTIONAL'">
|
||||||
|
join functional_case c on (brc.case_id = c.id or brc.test_plan_case_id = c.id)
|
||||||
|
</if>
|
||||||
|
<!-- 后续根据SourceType扩展 -->
|
||||||
|
where c.id = #{id} and c.deleted = false
|
||||||
|
</select>
|
||||||
|
|
||||||
<select id="getAssociateBugs" resultType="io.metersphere.dto.BugProviderDTO">
|
<select id="getAssociateBugs" resultType="io.metersphere.dto.BugProviderDTO">
|
||||||
SELECT
|
SELECT
|
||||||
brc.id as id,
|
brc.id as id,
|
||||||
|
|
|
@ -47,7 +47,7 @@ public class BugCommentService {
|
||||||
BugCommentExample example = new BugCommentExample();
|
BugCommentExample example = new BugCommentExample();
|
||||||
example.createCriteria().andBugIdEqualTo(bugId);
|
example.createCriteria().andBugIdEqualTo(bugId);
|
||||||
List<BugComment> bugComments = bugCommentMapper.selectByExample(example);
|
List<BugComment> bugComments = bugCommentMapper.selectByExample(example);
|
||||||
return generateCommentDTOs(bugComments);
|
return wrapperComments(bugComments);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -56,7 +56,7 @@ public class BugCommentService {
|
||||||
* @param bugComments 缺陷评论集合
|
* @param bugComments 缺陷评论集合
|
||||||
* @return 缺陷评论DTO
|
* @return 缺陷评论DTO
|
||||||
*/
|
*/
|
||||||
private List<BugCommentDTO> generateCommentDTOs(List<BugComment> bugComments) {
|
private List<BugCommentDTO> wrapperComments(List<BugComment> bugComments) {
|
||||||
if (CollectionUtils.isEmpty(bugComments)) {
|
if (CollectionUtils.isEmpty(bugComments)) {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ public class BugCommentService {
|
||||||
|
|
||||||
Map<String, List<BugCommentDTO>> returnMap = new HashMap<>();
|
Map<String, List<BugCommentDTO>> returnMap = new HashMap<>();
|
||||||
for (Map.Entry<String, List<BugComment>> entry : bugCommentByBugId.entrySet()) {
|
for (Map.Entry<String, List<BugComment>> entry : bugCommentByBugId.entrySet()) {
|
||||||
returnMap.put(entry.getKey(), generateCommentDTOs(entry.getValue()));
|
returnMap.put(entry.getKey(), wrapperComments(entry.getValue()));
|
||||||
}
|
}
|
||||||
return returnMap;
|
return returnMap;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,124 @@
|
||||||
|
package io.metersphere.bug.service;
|
||||||
|
|
||||||
|
import io.metersphere.bug.domain.Bug;
|
||||||
|
import io.metersphere.bug.domain.BugContent;
|
||||||
|
import io.metersphere.bug.dto.request.BugEditRequest;
|
||||||
|
import io.metersphere.bug.dto.response.BugDTO;
|
||||||
|
import io.metersphere.bug.mapper.BugContentMapper;
|
||||||
|
import io.metersphere.bug.mapper.BugMapper;
|
||||||
|
import io.metersphere.sdk.constants.HttpMethodConstants;
|
||||||
|
import io.metersphere.sdk.util.BeanUtils;
|
||||||
|
import io.metersphere.sdk.util.JSON;
|
||||||
|
import io.metersphere.system.log.constants.OperationLogModule;
|
||||||
|
import io.metersphere.system.log.constants.OperationLogType;
|
||||||
|
import io.metersphere.system.log.dto.LogDTO;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public class BugLogService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private BugMapper bugMapper;
|
||||||
|
@Resource
|
||||||
|
private BugService bugService;
|
||||||
|
@Resource
|
||||||
|
private BugContentMapper bugContentMapper;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增缺陷日志
|
||||||
|
*
|
||||||
|
* @param request 请求参数
|
||||||
|
* @param files 文件
|
||||||
|
* @return 日志
|
||||||
|
*/
|
||||||
|
public LogDTO addLog(BugEditRequest request, List<MultipartFile> files) {
|
||||||
|
LogDTO dto = new LogDTO(request.getProjectId(), null, null, null, OperationLogType.ADD.name(), OperationLogModule.BUG_MANAGEMENT, request.getTitle());
|
||||||
|
dto.setHistory(true);
|
||||||
|
dto.setPath("/bug/add");
|
||||||
|
dto.setMethod(HttpMethodConstants.POST.name());
|
||||||
|
dto.setModifiedValue(JSON.toJSONBytes(request));
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新缺陷日志
|
||||||
|
*
|
||||||
|
* @param request 请求参数
|
||||||
|
* @param files 文件
|
||||||
|
* @return 日志
|
||||||
|
*/
|
||||||
|
public LogDTO updateLog(BugEditRequest request, List<MultipartFile> files) {
|
||||||
|
BugDTO history = getOriginalValue(request.getId());
|
||||||
|
LogDTO dto = new LogDTO(request.getProjectId(), null, request.getId(), null, OperationLogType.UPDATE.name(), OperationLogModule.BUG_MANAGEMENT, request.getTitle());
|
||||||
|
dto.setHistory(true);
|
||||||
|
dto.setPath("/bug/update");
|
||||||
|
dto.setMethod(HttpMethodConstants.POST.name());
|
||||||
|
dto.setModifiedValue(JSON.toJSONBytes(request));
|
||||||
|
dto.setOriginalValue(JSON.toJSONBytes(history));
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除缺陷日志
|
||||||
|
*
|
||||||
|
* @param id 缺陷ID
|
||||||
|
* @return 日志
|
||||||
|
*/
|
||||||
|
public LogDTO deleteLog(String id) {
|
||||||
|
Bug bug = bugMapper.selectByPrimaryKey(id);
|
||||||
|
if (bug != null) {
|
||||||
|
LogDTO dto = new LogDTO(bug.getProjectId(), null, bug.getId(), null, OperationLogType.DELETE.name(), OperationLogModule.BUG_MANAGEMENT, bug.getTitle());
|
||||||
|
dto.setPath("/bug/delete");
|
||||||
|
dto.setMethod(HttpMethodConstants.GET.name());
|
||||||
|
dto.setOriginalValue(JSON.toJSONBytes(bug));
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 恢复缺陷日志
|
||||||
|
*
|
||||||
|
* @param id 缺陷ID
|
||||||
|
* @return 日志
|
||||||
|
*/
|
||||||
|
public LogDTO recoverLog(String id) {
|
||||||
|
Bug bug = bugMapper.selectByPrimaryKey(id);
|
||||||
|
if (bug != null) {
|
||||||
|
LogDTO dto = new LogDTO(bug.getProjectId(), null, bug.getId(), null, OperationLogType.RECOVER.name(), OperationLogModule.BUG_MANAGEMENT, bug.getTitle());
|
||||||
|
dto.setPath("/bug/trash/recover");
|
||||||
|
dto.setMethod(HttpMethodConstants.GET.name());
|
||||||
|
dto.setOriginalValue(JSON.toJSONBytes(bug));
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取历史缺陷
|
||||||
|
* @param id 缺陷ID
|
||||||
|
* @return 缺陷DTO
|
||||||
|
*/
|
||||||
|
private BugDTO getOriginalValue(String id) {
|
||||||
|
// 缺陷基础信息
|
||||||
|
BugDTO originalBug = new BugDTO();
|
||||||
|
Bug bug = bugMapper.selectByPrimaryKey(id);
|
||||||
|
if (bug == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
BeanUtils.copyBean(originalBug, bug);
|
||||||
|
BugContent bugContent = bugContentMapper.selectByPrimaryKey(id);
|
||||||
|
if (bugContent != null) {
|
||||||
|
originalBug.setDescription(bugContent.getDescription());
|
||||||
|
}
|
||||||
|
// 缺陷自定义字段
|
||||||
|
return bugService.handleCustomField(List.of(originalBug), originalBug.getProjectId()).get(0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
package io.metersphere.bug.service;
|
||||||
|
|
||||||
|
import io.metersphere.bug.dto.request.BugEditRequest;
|
||||||
|
import io.metersphere.plugin.platform.dto.SelectOption;
|
||||||
|
import io.metersphere.system.dto.BugNoticeDTO;
|
||||||
|
import io.metersphere.system.dto.sdk.OptionDTO;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
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;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public class BugNoticeService {
|
||||||
|
|
||||||
|
public static final String CUSTOM_TITLE = "summary";
|
||||||
|
public static final String CUSTOM_STATUS = "status";
|
||||||
|
public static final String CUSTOM_HANDLE_USER = "处理人";
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private BugService bugService;
|
||||||
|
@Resource
|
||||||
|
private BugStatusService bugStatusService;
|
||||||
|
|
||||||
|
public BugNoticeDTO getNoticeByRequest(BugEditRequest request) {
|
||||||
|
// 获取状态选项, 处理人选项
|
||||||
|
Map<String, String> statusMap = getStatusMap(request.getProjectId());
|
||||||
|
Map<String, String> handlerMap = getHandleMap(request.getProjectId());
|
||||||
|
// 构建通知对象
|
||||||
|
BugNoticeDTO notice = new BugNoticeDTO();
|
||||||
|
notice.setTitle(request.getTitle());
|
||||||
|
// 自定义字段解析{name: value}
|
||||||
|
if (CollectionUtils.isNotEmpty(request.getCustomFields())) {
|
||||||
|
List<OptionDTO> fields = new ArrayList<>();
|
||||||
|
request.getCustomFields().forEach(field -> {
|
||||||
|
if (StringUtils.equals(field.getId(), CUSTOM_TITLE)) {
|
||||||
|
// TITLE {标题为空时, 从自定义字段中获取标题}
|
||||||
|
notice.setTitle(field.getValue());
|
||||||
|
} else if (StringUtils.equals(field.getId(), CUSTOM_STATUS)) {
|
||||||
|
// 状态 {从自定义字段中获取状态}
|
||||||
|
notice.setStatus(statusMap.get(field.getValue()));
|
||||||
|
} else if (StringUtils.equals(field.getName(), CUSTOM_HANDLE_USER)) {
|
||||||
|
// 处理人 {从自定义字段中获取状态}
|
||||||
|
notice.setHandleUser(handlerMap.get(field.getValue()));
|
||||||
|
} else {
|
||||||
|
// 其他自定义字段
|
||||||
|
OptionDTO fieldDTO = new OptionDTO();
|
||||||
|
fieldDTO.setId(field.getName());
|
||||||
|
fieldDTO.setName(field.getValue());
|
||||||
|
fields.add(fieldDTO);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
notice.setCustomFields(fields);
|
||||||
|
}
|
||||||
|
return notice;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, String> getStatusMap(String projectId) {
|
||||||
|
List<SelectOption> statusOption = bugStatusService.getHeaderStatusOption(projectId);
|
||||||
|
return statusOption.stream().collect(Collectors.toMap(SelectOption::getValue, SelectOption::getText));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, String> getHandleMap(String projectId) {
|
||||||
|
List<SelectOption> handlerOption = bugService.getHeaderHandlerOption(projectId);
|
||||||
|
return handlerOption.stream().collect(Collectors.toMap(SelectOption::getValue, SelectOption::getText));
|
||||||
|
}
|
||||||
|
}
|
|
@ -139,6 +139,7 @@ public class BugRelateCaseCommonService extends ModuleTreeService {
|
||||||
* @param request 请求参数
|
* @param request 请求参数
|
||||||
*/
|
*/
|
||||||
public List<BugRelateCaseDTO> page(BugRelatedCasePageRequest request) {
|
public List<BugRelateCaseDTO> page(BugRelatedCasePageRequest request) {
|
||||||
|
// 目前只查关联的功能用例类型, 后续多个用例类型SQL扩展
|
||||||
List<BugRelateCaseDTO> relateCases = extBugRelateCaseMapper.list(request);
|
List<BugRelateCaseDTO> relateCases = extBugRelateCaseMapper.list(request);
|
||||||
if (CollectionUtils.isEmpty(relateCases)) {
|
if (CollectionUtils.isEmpty(relateCases)) {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
package io.metersphere.bug.service;
|
||||||
|
|
||||||
|
import io.metersphere.bug.domain.BugRelationCase;
|
||||||
|
import io.metersphere.bug.dto.response.BugRelateCaseDTO;
|
||||||
|
import io.metersphere.bug.mapper.BugRelationCaseMapper;
|
||||||
|
import io.metersphere.bug.mapper.ExtBugRelateCaseMapper;
|
||||||
|
import io.metersphere.sdk.constants.HttpMethodConstants;
|
||||||
|
import io.metersphere.sdk.util.JSON;
|
||||||
|
import io.metersphere.system.log.constants.OperationLogModule;
|
||||||
|
import io.metersphere.system.log.constants.OperationLogType;
|
||||||
|
import io.metersphere.system.log.dto.LogDTO;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public class BugRelateCaseLogService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private BugRelationCaseMapper bugRelationCaseMapper;
|
||||||
|
@Resource
|
||||||
|
private ExtBugRelateCaseMapper extBugRelateCaseMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增缺陷日志
|
||||||
|
*
|
||||||
|
* @param id 取消关联的引用ID
|
||||||
|
* @return 日志
|
||||||
|
*/
|
||||||
|
public LogDTO getRelateLog(String id) {
|
||||||
|
BugRelationCase bugRelationCase = bugRelationCaseMapper.selectByPrimaryKey(id);
|
||||||
|
BugRelateCaseDTO relateCase = extBugRelateCaseMapper.getRelateCase(bugRelationCase.getCaseId(), bugRelationCase.getCaseType());
|
||||||
|
LogDTO dto = new LogDTO(relateCase.getProjectId(), null, null, null, OperationLogType.DISASSOCIATE.name(), OperationLogModule.BUG_MANAGEMENT, relateCase.getRelateCaseName());
|
||||||
|
dto.setPath("/bug/un-relate");
|
||||||
|
dto.setMethod(HttpMethodConstants.GET.name());
|
||||||
|
dto.setModifiedValue(JSON.toJSONBytes(relateCase));
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,6 +28,7 @@ import io.metersphere.project.dto.ProjectUserDTO;
|
||||||
import io.metersphere.project.dto.filemanagement.FileLogRecord;
|
import io.metersphere.project.dto.filemanagement.FileLogRecord;
|
||||||
import io.metersphere.project.mapper.FileAssociationMapper;
|
import io.metersphere.project.mapper.FileAssociationMapper;
|
||||||
import io.metersphere.project.mapper.FileMetadataMapper;
|
import io.metersphere.project.mapper.FileMetadataMapper;
|
||||||
|
import io.metersphere.project.mapper.ProjectMapper;
|
||||||
import io.metersphere.project.request.ProjectMemberRequest;
|
import io.metersphere.project.request.ProjectMemberRequest;
|
||||||
import io.metersphere.project.service.*;
|
import io.metersphere.project.service.*;
|
||||||
import io.metersphere.sdk.constants.*;
|
import io.metersphere.sdk.constants.*;
|
||||||
|
@ -37,17 +38,27 @@ import io.metersphere.sdk.util.*;
|
||||||
import io.metersphere.system.domain.ServiceIntegration;
|
import io.metersphere.system.domain.ServiceIntegration;
|
||||||
import io.metersphere.system.domain.Template;
|
import io.metersphere.system.domain.Template;
|
||||||
import io.metersphere.system.domain.TemplateCustomField;
|
import io.metersphere.system.domain.TemplateCustomField;
|
||||||
|
import io.metersphere.system.domain.User;
|
||||||
|
import io.metersphere.system.dto.BugNoticeDTO;
|
||||||
import io.metersphere.system.dto.sdk.OptionDTO;
|
import io.metersphere.system.dto.sdk.OptionDTO;
|
||||||
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.log.constants.OperationLogModule;
|
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.mapper.BaseUserMapper;
|
import io.metersphere.system.mapper.BaseUserMapper;
|
||||||
import io.metersphere.system.mapper.TemplateMapper;
|
import io.metersphere.system.mapper.TemplateMapper;
|
||||||
|
import io.metersphere.system.mapper.UserMapper;
|
||||||
|
import io.metersphere.system.notice.NoticeModel;
|
||||||
|
import io.metersphere.system.notice.constants.NoticeConstants;
|
||||||
|
import io.metersphere.system.notice.utils.MessageTemplateUtils;
|
||||||
import io.metersphere.system.service.*;
|
import io.metersphere.system.service.*;
|
||||||
import io.metersphere.system.uid.IDGenerator;
|
import io.metersphere.system.uid.IDGenerator;
|
||||||
import io.metersphere.system.uid.NumGenerator;
|
import io.metersphere.system.uid.NumGenerator;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import jodd.util.StringUtil;
|
import jodd.util.StringUtil;
|
||||||
|
import org.apache.commons.beanutils.BeanMap;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.collections4.ListUtils;
|
import org.apache.commons.collections4.ListUtils;
|
||||||
import org.apache.commons.collections4.MapUtils;
|
import org.apache.commons.collections4.MapUtils;
|
||||||
|
@ -84,24 +95,32 @@ public class BugService {
|
||||||
@Resource
|
@Resource
|
||||||
private BugMapper bugMapper;
|
private BugMapper bugMapper;
|
||||||
@Resource
|
@Resource
|
||||||
|
private UserMapper userMapper;
|
||||||
|
@Resource
|
||||||
private ExtBugMapper extBugMapper;
|
private ExtBugMapper extBugMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private BugContentMapper bugContentMapper;
|
private ProjectMapper projectMapper;
|
||||||
|
@Resource
|
||||||
|
private NoticeSendService noticeSendService;
|
||||||
@Resource
|
@Resource
|
||||||
private BaseUserMapper baseUserMapper;
|
private BaseUserMapper baseUserMapper;
|
||||||
@Resource
|
@Resource
|
||||||
protected TemplateMapper templateMapper;
|
protected TemplateMapper templateMapper;
|
||||||
@Resource
|
@Resource
|
||||||
|
private BugContentMapper bugContentMapper;
|
||||||
|
@Resource
|
||||||
private SqlSessionFactory sqlSessionFactory;
|
private SqlSessionFactory sqlSessionFactory;
|
||||||
@Resource
|
@Resource
|
||||||
private ProjectTemplateService projectTemplateService;
|
private OperationLogService operationLogService;
|
||||||
@Resource
|
|
||||||
private BaseTemplateCustomFieldService baseTemplateCustomFieldService;
|
|
||||||
@Resource
|
@Resource
|
||||||
private PlatformPluginService platformPluginService;
|
private PlatformPluginService platformPluginService;
|
||||||
@Resource
|
@Resource
|
||||||
|
private ProjectTemplateService projectTemplateService;
|
||||||
|
@Resource
|
||||||
private UserPlatformAccountService userPlatformAccountService;
|
private UserPlatformAccountService userPlatformAccountService;
|
||||||
@Resource
|
@Resource
|
||||||
|
private BaseTemplateCustomFieldService baseTemplateCustomFieldService;
|
||||||
|
@Resource
|
||||||
private BugCustomFieldMapper bugCustomFieldMapper;
|
private BugCustomFieldMapper bugCustomFieldMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private ExtBugCustomFieldMapper extBugCustomFieldMapper;
|
private ExtBugCustomFieldMapper extBugCustomFieldMapper;
|
||||||
|
@ -136,6 +155,8 @@ public class BugService {
|
||||||
@Resource
|
@Resource
|
||||||
private BugSyncExtraService bugSyncExtraService;
|
private BugSyncExtraService bugSyncExtraService;
|
||||||
@Resource
|
@Resource
|
||||||
|
private BugSyncNoticeService bugSyncNoticeService;
|
||||||
|
@Resource
|
||||||
private BugStatusService bugStatusService;
|
private BugStatusService bugStatusService;
|
||||||
@Resource
|
@Resource
|
||||||
private ProjectMemberService projectMemberService;
|
private ProjectMemberService projectMemberService;
|
||||||
|
@ -208,7 +229,7 @@ public class BugService {
|
||||||
*
|
*
|
||||||
* @param id 缺陷ID
|
* @param id 缺陷ID
|
||||||
*/
|
*/
|
||||||
public void delete(String id) {
|
public void delete(String id, String currentUser) {
|
||||||
Bug bug = checkById(id);
|
Bug bug = checkById(id);
|
||||||
if (StringUtils.equals(bug.getPlatform(), BugPlatform.LOCAL.getName())) {
|
if (StringUtils.equals(bug.getPlatform(), BugPlatform.LOCAL.getName())) {
|
||||||
Bug record = new Bug();
|
Bug record = new Bug();
|
||||||
|
@ -224,6 +245,8 @@ public class BugService {
|
||||||
clearAssociate(id, bug.getProjectId());
|
clearAssociate(id, bug.getProjectId());
|
||||||
bugMapper.deleteByPrimaryKey(id);
|
bugMapper.deleteByPrimaryKey(id);
|
||||||
}
|
}
|
||||||
|
// 发送通知
|
||||||
|
sendDeleteNotice(bug, currentUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -284,9 +307,12 @@ public class BugService {
|
||||||
* 批量删除缺陷
|
* 批量删除缺陷
|
||||||
* @param request 请求参数
|
* @param request 请求参数
|
||||||
*/
|
*/
|
||||||
public void batchDelete(BugBatchRequest request) {
|
public void batchDelete(BugBatchRequest request, String currentUser) {
|
||||||
List<String> batchIds = getBatchIdsByRequest(request);
|
List<String> batchIds = getBatchIdsByRequest(request);
|
||||||
batchIds.forEach(this::delete);
|
batchIds.forEach(id -> delete(id, currentUser));
|
||||||
|
// 批量日志
|
||||||
|
List<LogDTO> logs = getBatchLogByRequest(batchIds, OperationLogType.DELETE.name(), "/bug/batch-delete", request.getProjectId(), false, false, null);
|
||||||
|
operationLogService.batchAdd(logs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -296,6 +322,9 @@ public class BugService {
|
||||||
public void batchRecover(BugBatchRequest request) {
|
public void batchRecover(BugBatchRequest request) {
|
||||||
List<String> batchIds = getBatchIdsByRequest(request);
|
List<String> batchIds = getBatchIdsByRequest(request);
|
||||||
batchIds.forEach(this::recover);
|
batchIds.forEach(this::recover);
|
||||||
|
// 批量日志
|
||||||
|
List<LogDTO> logs = getBatchLogByRequest(batchIds, OperationLogType.RECOVER.name(), "/bug/batch-recover", request.getProjectId(), false, false, null);
|
||||||
|
operationLogService.batchAdd(logs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -315,6 +344,10 @@ public class BugService {
|
||||||
public void batchUpdate(BugBatchUpdateRequest request, String currentUser) {
|
public void batchUpdate(BugBatchUpdateRequest request, String currentUser) {
|
||||||
List<String> batchIds = getBatchIdsByRequest(request);
|
List<String> batchIds = getBatchIdsByRequest(request);
|
||||||
|
|
||||||
|
// 批量日志{修改之前}
|
||||||
|
List<LogDTO> logs = getBatchLogByRequest(batchIds, OperationLogType.UPDATE.name(), "/bug/batch-update",
|
||||||
|
request.getProjectId(), true, request.isAppend(), request.getTags());
|
||||||
|
operationLogService.batchAdd(logs);
|
||||||
// 目前只做标签的批量编辑
|
// 目前只做标签的批量编辑
|
||||||
if (request.isAppend()) {
|
if (request.isAppend()) {
|
||||||
// 标签(追加)
|
// 标签(追加)
|
||||||
|
@ -369,13 +402,14 @@ public class BugService {
|
||||||
* 同步平台缺陷(全量)
|
* 同步平台缺陷(全量)
|
||||||
* @param request 同步请求参数
|
* @param request 同步请求参数
|
||||||
* @param project 项目
|
* @param project 项目
|
||||||
|
* @param currentUser 当前用户
|
||||||
*/
|
*/
|
||||||
@Async
|
@Async
|
||||||
public void syncPlatformAllBugs(BugSyncRequest request, Project project) {
|
public void syncPlatformAllBugs(BugSyncRequest request, Project project, String currentUser) {
|
||||||
try {
|
try {
|
||||||
XpackBugService bugService = CommonBeanFactory.getBean(XpackBugService.class);
|
XpackBugService bugService = CommonBeanFactory.getBean(XpackBugService.class);
|
||||||
if (bugService != null) {
|
if (bugService != null) {
|
||||||
bugService.syncPlatformBugs(project, request);
|
bugService.syncPlatformBugs(project, request, currentUser);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogUtils.error(e);
|
LogUtils.error(e);
|
||||||
|
@ -393,7 +427,7 @@ public class BugService {
|
||||||
* @param project 项目
|
* @param project 项目
|
||||||
*/
|
*/
|
||||||
@Async
|
@Async
|
||||||
public void syncPlatformBugs(List<Bug> remainBugs, Project project) {
|
public void syncPlatformBugs(List<Bug> remainBugs, Project project, String currentUser) {
|
||||||
try {
|
try {
|
||||||
// 分页同步
|
// 分页同步
|
||||||
SubListUtils.dealForSubList(remainBugs, 500, (subBugs) -> doSyncPlatformBugs(subBugs, project));
|
SubListUtils.dealForSubList(remainBugs, 500, (subBugs) -> doSyncPlatformBugs(subBugs, project));
|
||||||
|
@ -404,6 +438,8 @@ public class BugService {
|
||||||
} finally {
|
} finally {
|
||||||
// 异常或正常结束都得删除当前项目执行同步的Key
|
// 异常或正常结束都得删除当前项目执行同步的Key
|
||||||
bugSyncExtraService.deleteSyncKey(project.getId());
|
bugSyncExtraService.deleteSyncKey(project.getId());
|
||||||
|
// 发送同步通知
|
||||||
|
bugSyncNoticeService.sendNotice(remainBugs.size(), currentUser);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -956,7 +992,7 @@ public class BugService {
|
||||||
* @param bugs 缺陷集合
|
* @param bugs 缺陷集合
|
||||||
* @return 缺陷DTO集合
|
* @return 缺陷DTO集合
|
||||||
*/
|
*/
|
||||||
private List<BugDTO> handleCustomField(List<BugDTO> bugs, String projectId) {
|
public List<BugDTO> handleCustomField(List<BugDTO> bugs, String projectId) {
|
||||||
List<String> ids = bugs.stream().map(BugDTO::getId).toList();
|
List<String> ids = bugs.stream().map(BugDTO::getId).toList();
|
||||||
List<BugCustomFieldDTO> customFields = extBugCustomFieldMapper.getBugAllCustomFields(ids, projectId);
|
List<BugCustomFieldDTO> customFields = extBugCustomFieldMapper.getBugAllCustomFields(ids, projectId);
|
||||||
Map<String, List<BugCustomFieldDTO>> customFieldMap = customFields.stream().collect(Collectors.groupingBy(BugCustomFieldDTO::getBugId));
|
Map<String, List<BugCustomFieldDTO>> customFieldMap = customFields.stream().collect(Collectors.groupingBy(BugCustomFieldDTO::getBugId));
|
||||||
|
@ -1168,7 +1204,7 @@ public class BugService {
|
||||||
* @param request 批量操作参数
|
* @param request 批量操作参数
|
||||||
* @return 缺陷集合
|
* @return 缺陷集合
|
||||||
*/
|
*/
|
||||||
private List<String> getBatchIdsByRequest(BugBatchRequest request) {
|
public List<String> getBatchIdsByRequest(BugBatchRequest request) {
|
||||||
if (request.isSelectAll()) {
|
if (request.isSelectAll()) {
|
||||||
// 全选{根据查询条件查询所有数据, 排除取消勾选的数据}
|
// 全选{根据查询条件查询所有数据, 排除取消勾选的数据}
|
||||||
BugPageRequest bugPageRequest = new BugPageRequest();
|
BugPageRequest bugPageRequest = new BugPageRequest();
|
||||||
|
@ -1272,6 +1308,11 @@ public class BugService {
|
||||||
return headerCustomFields.stream().distinct().toList();
|
return headerCustomFields.stream().distinct().toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验缺陷是否存在并返回
|
||||||
|
* @param bugId 缺陷ID
|
||||||
|
* @return 缺陷
|
||||||
|
*/
|
||||||
private Bug checkById(String bugId) {
|
private Bug checkById(String bugId) {
|
||||||
Bug bug = bugMapper.selectByPrimaryKey(bugId);
|
Bug bug = bugMapper.selectByPrimaryKey(bugId);
|
||||||
if (bug == null) {
|
if (bug == null) {
|
||||||
|
@ -1279,4 +1320,66 @@ public class BugService {
|
||||||
}
|
}
|
||||||
return bug;
|
return bug;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据批量操作参数获取批量日志
|
||||||
|
* @param batchIds 批量操作ID
|
||||||
|
* @param operationType 操作类型
|
||||||
|
* @param path 请求路径
|
||||||
|
* @param batchUpdate 是否批量更新
|
||||||
|
* @return 日志集合
|
||||||
|
*/
|
||||||
|
private List<LogDTO> getBatchLogByRequest(List<String> batchIds, String operationType, String path, String projectId, boolean batchUpdate,
|
||||||
|
boolean appendTag, List<String> modifiedTags) {
|
||||||
|
Project project = projectMapper.selectByPrimaryKey(projectId);
|
||||||
|
BugExample example = new BugExample();
|
||||||
|
example.createCriteria().andIdIn(batchIds);
|
||||||
|
List<Bug> bugs = bugMapper.selectByExample(example);
|
||||||
|
List<LogDTO> logs = new ArrayList<>();
|
||||||
|
bugs.forEach(bug -> {
|
||||||
|
LogDTO log = new LogDTO(bug.getProjectId(), project.getOrganizationId(), bug.getId(), null, operationType, OperationLogModule.BUG_MANAGEMENT, bug.getTitle());
|
||||||
|
log.setPath(path);
|
||||||
|
log.setMethod(HttpMethodConstants.POST.name());
|
||||||
|
if (batchUpdate) {
|
||||||
|
// 批量更新只记录TAG的变更内容
|
||||||
|
log.setOriginalValue(JSON.toJSONBytes(bug.getTags()));
|
||||||
|
log.setModifiedValue(JSON.toJSONBytes(appendTag ? ListUtils.union(bug.getTags(), modifiedTags) : modifiedTags));
|
||||||
|
} else {
|
||||||
|
log.setOriginalValue(JSON.toJSONBytes(bug));
|
||||||
|
}
|
||||||
|
logs.add(log);
|
||||||
|
});
|
||||||
|
return logs;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendDeleteNotice(Bug bug, String currentUser) {
|
||||||
|
List<SelectOption> statusOption = bugStatusService.getHeaderStatusOption(bug.getProjectId());
|
||||||
|
Map<String, String> statusMap = statusOption.stream().collect(Collectors.toMap(SelectOption::getValue, SelectOption::getText));
|
||||||
|
List<SelectOption> handlerOption = getHeaderHandlerOption(bug.getProjectId());
|
||||||
|
Map<String, String> handlerMap = handlerOption.stream().collect(Collectors.toMap(SelectOption::getValue, SelectOption::getText));
|
||||||
|
// 缺陷相关内容
|
||||||
|
BugNoticeDTO notice = new BugNoticeDTO();
|
||||||
|
notice.setTitle(bug.getTitle());
|
||||||
|
notice.setStatus(statusMap.get(bug.getStatus()));
|
||||||
|
notice.setHandleUser(handlerMap.get(bug.getHandleUser()));
|
||||||
|
List<BugCustomFieldDTO> customFields = extBugCustomFieldMapper.getBugAllCustomFields(List.of(bug.getId()), bug.getProjectId());
|
||||||
|
List<OptionDTO> fields = customFields.stream().map(field -> {
|
||||||
|
OptionDTO fieldDTO = new OptionDTO();
|
||||||
|
fieldDTO.setId(field.getName());
|
||||||
|
fieldDTO.setName(field.getValue());
|
||||||
|
return fieldDTO;
|
||||||
|
}).toList();
|
||||||
|
notice.setCustomFields(fields);
|
||||||
|
BeanMap beanMap = new BeanMap(notice);
|
||||||
|
User user = userMapper.selectByPrimaryKey(currentUser);
|
||||||
|
Map paramMap = new HashMap<>(beanMap);
|
||||||
|
paramMap.put(NoticeConstants.RelatedUser.OPERATOR, user.getName());
|
||||||
|
Map<String, String> defaultTemplateMap = MessageTemplateUtils.getDefaultTemplateMap();
|
||||||
|
String template = defaultTemplateMap.get(NoticeConstants.TemplateText.BUG_TASK_DELETE);
|
||||||
|
Map<String, String> defaultSubjectMap = MessageTemplateUtils.getDefaultTemplateSubjectMap();
|
||||||
|
String subject = defaultSubjectMap.get(NoticeConstants.TemplateText.BUG_TASK_DELETE);
|
||||||
|
NoticeModel noticeModel = NoticeModel.builder().operator(currentUser)
|
||||||
|
.context(template).subject(subject).paramMap(paramMap).event(NoticeConstants.Event.DELETE).build();
|
||||||
|
noticeSendService.send(NoticeConstants.TaskType.BUG_TASK, noticeModel);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package io.metersphere.bug.service;
|
||||||
|
|
||||||
|
import io.metersphere.system.domain.User;
|
||||||
|
import io.metersphere.system.mapper.UserMapper;
|
||||||
|
import io.metersphere.system.notice.NoticeModel;
|
||||||
|
import io.metersphere.system.notice.constants.NoticeConstants;
|
||||||
|
import io.metersphere.system.notice.utils.MessageTemplateUtils;
|
||||||
|
import io.metersphere.system.service.NoticeSendService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public class BugSyncNoticeService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private UserMapper userMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private NoticeSendService noticeSendService;
|
||||||
|
|
||||||
|
public void sendNotice(int total, String currentUser) {
|
||||||
|
User user = userMapper.selectByPrimaryKey(currentUser);
|
||||||
|
Map<String, String> defaultTemplateMap = MessageTemplateUtils.getDefaultTemplateMap();
|
||||||
|
String template = defaultTemplateMap.get(NoticeConstants.TemplateText.BUG_SYNC_TASK_EXECUTE_COMPLETED);
|
||||||
|
Map<String, String> defaultSubjectMap = MessageTemplateUtils.getDefaultTemplateSubjectMap();
|
||||||
|
String subject = defaultSubjectMap.get(NoticeConstants.TemplateText.BUG_SYNC_TASK_EXECUTE_COMPLETED);
|
||||||
|
// ${OPERATOR}同步了${total}条缺陷
|
||||||
|
Map paramMap = new HashMap<>();
|
||||||
|
paramMap.put(NoticeConstants.RelatedUser.OPERATOR, user.getName());
|
||||||
|
paramMap.put("total", total);
|
||||||
|
NoticeModel noticeModel = NoticeModel.builder().operator(currentUser)
|
||||||
|
.context(template).subject(subject).paramMap(paramMap).event(NoticeConstants.Event.SYNC_COMPLETED).build();
|
||||||
|
noticeSendService.send(NoticeConstants.TaskType.BUG_SYNC_TASK, noticeModel);
|
||||||
|
}
|
||||||
|
}
|
|
@ -52,8 +52,9 @@ public class BugSyncService {
|
||||||
/**
|
/**
|
||||||
* XPACK用户 (同步全量缺陷)
|
* XPACK用户 (同步全量缺陷)
|
||||||
* @param request 同步全量参数
|
* @param request 同步全量参数
|
||||||
|
* @param currentUser 当前用户
|
||||||
*/
|
*/
|
||||||
public void syncAllBugs(BugSyncRequest request) {
|
public void syncAllBugs(BugSyncRequest request, String currentUser) {
|
||||||
try {
|
try {
|
||||||
// 获取当前项目同步缺陷唯一Key
|
// 获取当前项目同步缺陷唯一Key
|
||||||
String syncValue = bugSyncExtraService.getSyncKey(request.getProjectId());
|
String syncValue = bugSyncExtraService.getSyncKey(request.getProjectId());
|
||||||
|
@ -61,7 +62,7 @@ public class BugSyncService {
|
||||||
// 不存在, 设置保证唯一性, 并开始同步
|
// 不存在, 设置保证唯一性, 并开始同步
|
||||||
bugSyncExtraService.setSyncKey(request.getProjectId());
|
bugSyncExtraService.setSyncKey(request.getProjectId());
|
||||||
Project project = getProjectById(request.getProjectId());
|
Project project = getProjectById(request.getProjectId());
|
||||||
bugService.syncPlatformAllBugs(request, project);
|
bugService.syncPlatformAllBugs(request, project, currentUser);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
bugSyncExtraService.deleteSyncKey(request.getProjectId());
|
bugSyncExtraService.deleteSyncKey(request.getProjectId());
|
||||||
|
@ -73,7 +74,7 @@ public class BugSyncService {
|
||||||
* 开源用户 (同步存量缺陷)
|
* 开源用户 (同步存量缺陷)
|
||||||
* @param projectId 项目ID
|
* @param projectId 项目ID
|
||||||
*/
|
*/
|
||||||
public void syncBugs(String projectId) {
|
public void syncBugs(String projectId, String currentUser) {
|
||||||
try {
|
try {
|
||||||
String syncValue = bugSyncExtraService.getSyncKey(projectId);
|
String syncValue = bugSyncExtraService.getSyncKey(projectId);
|
||||||
if (StringUtils.isEmpty(syncValue)) {
|
if (StringUtils.isEmpty(syncValue)) {
|
||||||
|
@ -99,7 +100,7 @@ public class BugSyncService {
|
||||||
Map<String, Template> templateMap = templates.stream().collect(Collectors.toMap(Template::getId, t -> t));
|
Map<String, Template> templateMap = templates.stream().collect(Collectors.toMap(Template::getId, t -> t));
|
||||||
// 非插件默认模板且模板不存在, 无需同步
|
// 非插件默认模板且模板不存在, 无需同步
|
||||||
bugs.removeIf(bug -> !templateMap.containsKey(bug.getTemplateId()) && !StringUtils.equals(bug.getTemplateId(), pluginTemplate.getId()));
|
bugs.removeIf(bug -> !templateMap.containsKey(bug.getTemplateId()) && !StringUtils.equals(bug.getTemplateId(), pluginTemplate.getId()));
|
||||||
bugService.syncPlatformBugs(bugs, project);
|
bugService.syncPlatformBugs(bugs, project, currentUser);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -136,11 +137,11 @@ public class BugSyncService {
|
||||||
public void syncPlatformBugBySchedule() {
|
public void syncPlatformBugBySchedule() {
|
||||||
ProjectExample example = new ProjectExample();
|
ProjectExample example = new ProjectExample();
|
||||||
List<Project> projects = projectMapper.selectByExample(example);
|
List<Project> projects = projectMapper.selectByExample(example);
|
||||||
List<String> allProjectIds = projects.stream().map(Project::getId).toList();
|
List<String> allProjectIds = projects.stream().map(Project::getId).collect(Collectors.toList());
|
||||||
List<String> syncProjectIds = projectApplicationService.filterNoLocalPlatform(allProjectIds);
|
List<String> syncProjectIds = projectApplicationService.filterNeedSyncProject(allProjectIds);
|
||||||
syncProjectIds.forEach(id -> {
|
syncProjectIds.forEach(id -> {
|
||||||
try {
|
try {
|
||||||
syncBugs(id);
|
syncBugs(id, "admin");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogUtils.error(e.getMessage(), e);
|
LogUtils.error(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ public interface XpackBugService {
|
||||||
* 同步当前项目第三方平台缺陷(前台调用)
|
* 同步当前项目第三方平台缺陷(前台调用)
|
||||||
* @param project 项目
|
* @param project 项目
|
||||||
* @param request 同步请求参数
|
* @param request 同步请求参数
|
||||||
|
* @param currentUser 当前用户
|
||||||
*/
|
*/
|
||||||
void syncPlatformBugs(Project project, BugSyncRequest request);
|
void syncPlatformBugs(Project project, BugSyncRequest request, String currentUser);
|
||||||
}
|
}
|
||||||
|
|
|
@ -304,7 +304,7 @@ public class BugControllerTests extends BaseTest {
|
||||||
@Test
|
@Test
|
||||||
@Order(9)
|
@Order(9)
|
||||||
void testGetBugTemplateOption() throws Exception {
|
void testGetBugTemplateOption() throws Exception {
|
||||||
MvcResult mvcResult = this.requestGetWithOkAndReturn(BUG_TEMPLATE_OPTION + "?projectId=default-project-for-bug");
|
MvcResult mvcResult = this.requestGetWithOkAndReturn(BUG_TEMPLATE_OPTION + "/default-project-for-bug");
|
||||||
String sortData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
String sortData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||||
ResultHolder resultHolder = JSON.parseObject(sortData, ResultHolder.class);
|
ResultHolder resultHolder = JSON.parseObject(sortData, ResultHolder.class);
|
||||||
List<ProjectTemplateOptionDTO> templateOptionDTOS = JSON.parseArray(JSON.toJSONString(resultHolder.getData()), ProjectTemplateOptionDTO.class);
|
List<ProjectTemplateOptionDTO> templateOptionDTOS = JSON.parseArray(JSON.toJSONString(resultHolder.getData()), ProjectTemplateOptionDTO.class);
|
||||||
|
@ -557,6 +557,12 @@ public class BugControllerTests extends BaseTest {
|
||||||
|
|
||||||
// 添加使用Jira默认模板的缺陷
|
// 添加使用Jira默认模板的缺陷
|
||||||
addRequest.setTemplateId("jira");
|
addRequest.setTemplateId("jira");
|
||||||
|
BugCustomFieldDTO summary = new BugCustomFieldDTO();
|
||||||
|
summary.setId("summary");
|
||||||
|
summary.setName("摘要");
|
||||||
|
summary.setType("input");
|
||||||
|
summary.setValue("这是一个系统Jira模板创建的缺陷");
|
||||||
|
addRequest.getCustomFields().add(summary);
|
||||||
MultiValueMap<String, Object> addParam3 = getDefaultMultiPartParam(addRequest, null);
|
MultiValueMap<String, Object> addParam3 = getDefaultMultiPartParam(addRequest, null);
|
||||||
this.requestMultipart(BUG_ADD, addParam3).andExpect(status().is5xxServerError());
|
this.requestMultipart(BUG_ADD, addParam3).andExpect(status().is5xxServerError());
|
||||||
|
|
||||||
|
@ -584,13 +590,13 @@ public class BugControllerTests extends BaseTest {
|
||||||
List<Bug> remainBugs = bugMapper.selectByExample(example);
|
List<Bug> remainBugs = bugMapper.selectByExample(example);
|
||||||
Project defaultProject = projectMapper.selectByPrimaryKey("default-project-for-bug");
|
Project defaultProject = projectMapper.selectByPrimaryKey("default-project-for-bug");
|
||||||
// 同步第一次
|
// 同步第一次
|
||||||
bugService.syncPlatformBugs(remainBugs, defaultProject);
|
bugService.syncPlatformBugs(remainBugs, defaultProject, "admin");
|
||||||
// 同步第二次
|
// 同步第二次
|
||||||
renameLocalFile(updateRequest2.getId()); // 重命名后, 同步时会删除本地文件
|
renameLocalFile(updateRequest2.getId()); // 重命名后, 同步时会删除本地文件
|
||||||
bugService.syncPlatformBugs(remainBugs, defaultProject);
|
bugService.syncPlatformBugs(remainBugs, defaultProject, "admin");
|
||||||
// 同步第三次
|
// 同步第三次
|
||||||
deleteLocalFile(updateRequest2.getId()); // 手动删除关联的文件, 重新同步时会下载平台附件
|
deleteLocalFile(updateRequest2.getId()); // 手动删除关联的文件, 重新同步时会下载平台附件
|
||||||
bugService.syncPlatformBugs(remainBugs, defaultProject);
|
bugService.syncPlatformBugs(remainBugs, defaultProject, "admin");
|
||||||
|
|
||||||
// 集成配置为空
|
// 集成配置为空
|
||||||
addRequest.setProjectId("default-project-for-not-integration");
|
addRequest.setProjectId("default-project-for-not-integration");
|
||||||
|
@ -686,9 +692,9 @@ public class BugControllerTests extends BaseTest {
|
||||||
Project project = projectMapper.selectByPrimaryKey("default-project-for-bug");
|
Project project = projectMapper.selectByPrimaryKey("default-project-for-bug");
|
||||||
this.requestPostWithOk(BUG_SYNC_ALL, request);
|
this.requestPostWithOk(BUG_SYNC_ALL, request);
|
||||||
BugService mockBugService = Mockito.mock(BugService.class);
|
BugService mockBugService = Mockito.mock(BugService.class);
|
||||||
Mockito.doThrow(new MSException("sync error!")).when(mockBugService).syncPlatformAllBugs(syncRequest, project);
|
Mockito.doThrow(new MSException("sync error!")).when(mockBugService).syncPlatformAllBugs(syncRequest, project, "admin");
|
||||||
ReflectionTestUtils.setField(bugSyncService, "bugService", mockBugService);
|
ReflectionTestUtils.setField(bugSyncService, "bugService", mockBugService);
|
||||||
MSException msException = assertThrows(MSException.class, () -> bugSyncService.syncAllBugs(syncRequest));
|
MSException msException = assertThrows(MSException.class, () -> bugSyncService.syncAllBugs(syncRequest, "admin"));
|
||||||
assertEquals(msException.getMessage(), "sync error!");
|
assertEquals(msException.getMessage(), "sync error!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,7 @@ public class BugRelateCaseControllerTests extends BaseTest {
|
||||||
Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(pageData.getList())).size() <= request.getPageSize());
|
Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(pageData.getList())).size() <= request.getPageSize());
|
||||||
// 返回值中取出第一条数据, 并判断是否包含关键字default
|
// 返回值中取出第一条数据, 并判断是否包含关键字default
|
||||||
BugRelateCaseDTO bugRelateCaseDTO = JSON.parseArray(JSON.toJSONString(pageData.getList()), BugRelateCaseDTO.class).get(0);
|
BugRelateCaseDTO bugRelateCaseDTO = JSON.parseArray(JSON.toJSONString(pageData.getList()), BugRelateCaseDTO.class).get(0);
|
||||||
Assertions.assertTrue(StringUtils.contains(bugRelateCaseDTO.getName(), request.getKeyword()));
|
Assertions.assertTrue(StringUtils.contains(bugRelateCaseDTO.getRelateCaseName(), request.getKeyword()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -14,7 +14,7 @@ public class XpackBugMockServiceImpl implements XpackBugService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void syncPlatformBugs(Project project, BugSyncRequest request) {
|
public void syncPlatformBugs(Project project, BugSyncRequest request, String currentUser) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
INSERT INTO project (id, num, organization_id, name, description, create_user, update_user, create_time, update_time) VALUE
|
INSERT INTO project (id, num, organization_id, name, description, create_user, update_user, create_time, update_time) VALUE
|
||||||
('bug-trash-project-tmp', null, '100001', '测试项目(缺陷)', '系统默认创建的项目(缺陷)', 'admin', 'admin', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000);
|
('bug-trash-project-tmp', null, '100001', '测试项目(缺陷)', '系统默认创建的项目(缺陷)', 'admin', 'admin', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000);
|
||||||
|
|
||||||
|
INSERT INTO project (id, num, organization_id, name, description, create_user, update_user, create_time, update_time) VALUE
|
||||||
|
('bug-trash-project', '100000043', '100001', '测试项目(缺陷)', '系统默认创建的项目(缺陷)', 'admin', 'admin', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000);
|
||||||
|
|
||||||
INSERT INTO bug (id, num, title, handle_users, handle_user, create_user, create_time,
|
INSERT INTO bug (id, num, title, handle_users, handle_user, create_user, create_time,
|
||||||
update_user, update_time, delete_user, delete_time, project_id, template_id, platform, status, tags, platform_bug_id, deleted) VALUES
|
update_user, update_time, delete_user, delete_time, project_id, template_id, platform, status, tags, platform_bug_id, deleted) VALUES
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
package io.metersphere.project.service;
|
package io.metersphere.project.service;
|
||||||
|
|
||||||
import io.metersphere.api.domain.ApiScenario;
|
import io.metersphere.api.domain.ApiScenario;
|
||||||
import io.metersphere.bug.domain.Bug;
|
|
||||||
import io.metersphere.functional.domain.CaseReview;
|
import io.metersphere.functional.domain.CaseReview;
|
||||||
import io.metersphere.load.domain.LoadTest;
|
import io.metersphere.load.domain.LoadTest;
|
||||||
import io.metersphere.plan.domain.TestPlan;
|
import io.metersphere.plan.domain.TestPlan;
|
||||||
import io.metersphere.project.dto.MessageTemplateFieldDTO;
|
import io.metersphere.project.dto.MessageTemplateFieldDTO;
|
||||||
import io.metersphere.project.dto.MessageTemplateResultDTO;
|
import io.metersphere.project.dto.MessageTemplateResultDTO;
|
||||||
import io.metersphere.sdk.constants.TemplateScene;
|
import io.metersphere.sdk.constants.TemplateScene;
|
||||||
import io.metersphere.system.dto.sdk.ApiDefinitionCaseDTO;
|
|
||||||
import io.metersphere.system.dto.sdk.FunctionalCaseMessageDTO;
|
|
||||||
import io.metersphere.system.dto.sdk.OptionDTO;
|
|
||||||
import io.metersphere.sdk.util.Translator;
|
import io.metersphere.sdk.util.Translator;
|
||||||
import io.metersphere.system.domain.CustomField;
|
import io.metersphere.system.domain.CustomField;
|
||||||
import io.metersphere.system.domain.CustomFieldExample;
|
import io.metersphere.system.domain.CustomFieldExample;
|
||||||
import io.metersphere.system.domain.Schedule;
|
import io.metersphere.system.domain.Schedule;
|
||||||
|
import io.metersphere.system.dto.BugNoticeDTO;
|
||||||
|
import io.metersphere.system.dto.sdk.ApiDefinitionCaseDTO;
|
||||||
|
import io.metersphere.system.dto.sdk.FunctionalCaseMessageDTO;
|
||||||
|
import io.metersphere.system.dto.sdk.OptionDTO;
|
||||||
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.notice.utils.MessageTemplateUtils;
|
import io.metersphere.system.notice.utils.MessageTemplateUtils;
|
||||||
|
@ -71,8 +71,8 @@ public class NoticeTemplateService {
|
||||||
//TODO:获取报告
|
//TODO:获取报告
|
||||||
}
|
}
|
||||||
case NoticeConstants.TaskType.BUG_TASK -> {
|
case NoticeConstants.TaskType.BUG_TASK -> {
|
||||||
Field[] allFields = FieldUtils.getAllFields(Bug.class);
|
Field[] allFields = FieldUtils.getAllFields(BugNoticeDTO.class);
|
||||||
addOptionDto(messageTemplateFieldDTOList, allFields, "bug_");
|
addOptionDto(messageTemplateFieldDTOList, allFields, null);
|
||||||
addCustomFiled(messageTemplateFieldDTOList, projectId, TemplateScene.BUG.toString());
|
addCustomFiled(messageTemplateFieldDTOList, projectId, TemplateScene.BUG.toString());
|
||||||
//TODO:获取报告
|
//TODO:获取报告
|
||||||
}
|
}
|
||||||
|
|
|
@ -597,27 +597,23 @@ public class ProjectApplicationService {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 过滤掉非Local平台的项目
|
* 过滤出能够同步的项目
|
||||||
*
|
*
|
||||||
* @param projectIds 项目ID集合
|
* @param projectIds 项目ID集合
|
||||||
* @return 非Local平台的项目
|
* @return 同步的项目ID集合
|
||||||
*/
|
*/
|
||||||
public List<String> filterNoLocalPlatform(List<String> projectIds) {
|
public List<String> filterNeedSyncProject(List<String> projectIds) {
|
||||||
ProjectApplicationExample example = new ProjectApplicationExample();
|
Iterator<String> iterator = projectIds.iterator();
|
||||||
example.createCriteria().andProjectIdIn(projectIds).andTypeEqualTo(ProjectApplicationType.BUG.BUG_SYNC.name() + "_PLATFORM_KEY");
|
while (iterator.hasNext()) {
|
||||||
List<ProjectApplication> allProjectPlatformKeys = projectApplicationMapper.selectByExample(example);
|
String projectId = iterator.next();
|
||||||
if (CollectionUtils.isNotEmpty(allProjectPlatformKeys)) {
|
ServiceIntegration serviceIntegration = getPlatformServiceIntegrationWithSyncOrDemand(projectId, true);
|
||||||
for (ProjectApplication projectApplication : allProjectPlatformKeys) {
|
String platformName = getPlatformName(projectId);
|
||||||
String pluginName = getPluginName(projectApplication.getTypeValue());
|
if (serviceIntegration == null || StringUtils.equals("Local", platformName)) {
|
||||||
if (StringUtils.equals("Local", pluginName)) {
|
// 项目未配置第三方平台 或者 项目同步配置为Local
|
||||||
// 本地平台
|
iterator.remove();
|
||||||
projectIds.remove(projectApplication.getProjectId());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return projectIds;
|
|
||||||
} else {
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
}
|
||||||
|
return projectIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -770,10 +770,10 @@ public class ProjectApplicationControllerTests extends BaseTest {
|
||||||
Assertions.assertFalse(projectApplicationService.isPlatformSyncMethodByIncrement("default-project-for-application-not-exist"));
|
Assertions.assertFalse(projectApplicationService.isPlatformSyncMethodByIncrement("default-project-for-application-not-exist"));
|
||||||
|
|
||||||
// 过滤Local平台项目
|
// 过滤Local平台项目
|
||||||
projectApplicationService.filterNoLocalPlatform(new ArrayList<>(List.of("default-project-for-application")));
|
projectApplicationService.filterNeedSyncProject(new ArrayList<>(new ArrayList<>(List.of("default-project-for-application"))));
|
||||||
projectApplicationService.filterNoLocalPlatform(new ArrayList<>(List.of("default-project-for-application-not-exist")));
|
projectApplicationService.filterNeedSyncProject(new ArrayList<>(new ArrayList<>(List.of("default-project-for-application-not-exist"))));
|
||||||
// 移除插件测试
|
// 移除插件测试
|
||||||
basePluginTestService.deleteJiraPlugin();
|
basePluginTestService.deleteJiraPlugin();
|
||||||
projectApplicationService.filterNoLocalPlatform(new ArrayList<>(List.of("default-project-for-application")));
|
projectApplicationService.filterNeedSyncProject(new ArrayList<>(new ArrayList<>(List.of("default-project-for-application"))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
package io.metersphere.system.dto;
|
||||||
|
|
||||||
|
import io.metersphere.system.dto.sdk.OptionDTO;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class BugNoticeDTO {
|
||||||
|
|
||||||
|
@Schema(description ="message.domain.bug_title")
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
@Schema(description ="message.domain.bug_handleUser")
|
||||||
|
private String handleUser;
|
||||||
|
|
||||||
|
@Schema(description ="message.domain.bug_status")
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
@Schema(description = "message.domain.bug_createUser")
|
||||||
|
private String createUser;
|
||||||
|
|
||||||
|
@Schema(description = "message.domain.bug_updateUser")
|
||||||
|
private String updateUser;
|
||||||
|
|
||||||
|
@Schema(description = "message.domain.bug_deleteUser")
|
||||||
|
private String deleteUser;
|
||||||
|
|
||||||
|
@Schema(description = "message.domain.bug_createTime")
|
||||||
|
private Long createTime;
|
||||||
|
|
||||||
|
@Schema(description = "message.domain.bug_updateTime")
|
||||||
|
private Long updateTime;
|
||||||
|
|
||||||
|
@Schema(description = "message.domain.bug_deleteTime")
|
||||||
|
private Long deleteTime;
|
||||||
|
|
||||||
|
@Schema(description = "自定义字段内容")
|
||||||
|
private List<OptionDTO> customFields;
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package io.metersphere.system.dto;
|
||||||
|
|
||||||
|
import io.metersphere.system.dto.sdk.OptionDTO;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class BugSyncNoticeDTO {
|
||||||
|
|
||||||
|
@Schema(description ="message.domain.bug_title")
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
@Schema(description ="message.domain.bug_handleUser")
|
||||||
|
private String handleUser;
|
||||||
|
|
||||||
|
@Schema(description ="message.domain.bug_status")
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
@Schema(description = "message.domain.bug_createUser")
|
||||||
|
private String createUser;
|
||||||
|
|
||||||
|
@Schema(description = "message.domain.bug_updateUser")
|
||||||
|
private String updateUser;
|
||||||
|
|
||||||
|
@Schema(description = "message.domain.bug_deleteUser")
|
||||||
|
private String deleteUser;
|
||||||
|
|
||||||
|
@Schema(description = "message.domain.bug_createTime")
|
||||||
|
private Long createTime;
|
||||||
|
|
||||||
|
@Schema(description = "message.domain.bug_updateTime")
|
||||||
|
private Long updateTime;
|
||||||
|
|
||||||
|
@Schema(description = "message.domain.bug_deleteTime")
|
||||||
|
private Long deleteTime;
|
||||||
|
|
||||||
|
@Schema(description = "自定义字段内容")
|
||||||
|
private List<OptionDTO> customFields;
|
||||||
|
}
|
|
@ -194,6 +194,9 @@ public interface NoticeConstants {
|
||||||
|
|
||||||
@Schema(description = "message.close")
|
@Schema(description = "message.close")
|
||||||
String CLOSE = "CLOSE";
|
String CLOSE = "CLOSE";
|
||||||
|
|
||||||
|
@Schema(description = "message.close")
|
||||||
|
String SYNC_COMPLETED = "SYNC_COMPLETED";
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RelatedUser {
|
interface RelatedUser {
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
package io.metersphere.system.notice.utils;
|
package io.metersphere.system.notice.utils;
|
||||||
|
|
||||||
import io.metersphere.api.domain.ApiScenario;
|
import io.metersphere.api.domain.ApiScenario;
|
||||||
import io.metersphere.bug.domain.Bug;
|
|
||||||
import io.metersphere.functional.domain.CaseReview;
|
import io.metersphere.functional.domain.CaseReview;
|
||||||
import io.metersphere.load.domain.LoadTest;
|
import io.metersphere.load.domain.LoadTest;
|
||||||
import io.metersphere.plan.domain.TestPlan;
|
import io.metersphere.plan.domain.TestPlan;
|
||||||
import io.metersphere.system.dto.sdk.ApiDefinitionCaseDTO;
|
|
||||||
import io.metersphere.system.dto.sdk.FunctionalCaseMessageDTO;
|
|
||||||
import io.metersphere.sdk.util.Translator;
|
import io.metersphere.sdk.util.Translator;
|
||||||
import io.metersphere.system.domain.Schedule;
|
import io.metersphere.system.domain.Schedule;
|
||||||
|
import io.metersphere.system.dto.BugNoticeDTO;
|
||||||
|
import io.metersphere.system.dto.sdk.ApiDefinitionCaseDTO;
|
||||||
|
import io.metersphere.system.dto.sdk.FunctionalCaseMessageDTO;
|
||||||
import io.metersphere.system.notice.constants.NoticeConstants;
|
import io.metersphere.system.notice.constants.NoticeConstants;
|
||||||
import io.metersphere.ui.domain.UiScenario;
|
import io.metersphere.ui.domain.UiScenario;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
@ -153,7 +153,7 @@ public class MessageTemplateUtils {
|
||||||
allFields = FieldUtils.getAllFields(FunctionalCaseMessageDTO.class);
|
allFields = FieldUtils.getAllFields(FunctionalCaseMessageDTO.class);
|
||||||
}
|
}
|
||||||
case NoticeConstants.TaskType.BUG_TASK -> {
|
case NoticeConstants.TaskType.BUG_TASK -> {
|
||||||
allFields = FieldUtils.getAllFields(Bug.class);
|
allFields = FieldUtils.getAllFields(BugNoticeDTO.class);
|
||||||
}
|
}
|
||||||
case NoticeConstants.TaskType.UI_SCENARIO_TASK -> {
|
case NoticeConstants.TaskType.UI_SCENARIO_TASK -> {
|
||||||
allFields = FieldUtils.getAllFields(UiScenario.class);
|
allFields = FieldUtils.getAllFields(UiScenario.class);
|
||||||
|
|
Loading…
Reference in New Issue