package kr.wisestone.owl.service.impl;
|
|
import com.google.common.collect.Lists;
|
import kr.wisestone.owl.common.ExcelConditionCheck;
|
import kr.wisestone.owl.constant.Constants;
|
import kr.wisestone.owl.constant.MsgConstants;
|
import kr.wisestone.owl.domain.*;
|
import kr.wisestone.owl.domain.enumType.ProjectType;
|
import kr.wisestone.owl.exception.OwlRuntimeException;
|
import kr.wisestone.owl.mapper.WorkflowMapper;
|
import kr.wisestone.owl.repository.WorkflowRepository;
|
import kr.wisestone.owl.service.*;
|
import kr.wisestone.owl.util.ConvertUtil;
|
import kr.wisestone.owl.vo.*;
|
import kr.wisestone.owl.web.condition.WorkflowCondition;
|
import kr.wisestone.owl.web.condition.WorkflowDepartmentCondition;
|
import kr.wisestone.owl.web.form.WorkflowForm;
|
import kr.wisestone.owl.web.view.ExcelView;
|
import org.apache.commons.lang3.StringUtils;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.ui.Model;
|
import org.springframework.web.servlet.ModelAndView;
|
import javax.servlet.http.HttpServletRequest;
|
import java.util.*;
|
|
@Service
|
public class WorkflowServiceImpl extends AbstractServiceImpl<Workflow, Long, JpaRepository<Workflow, Long>>
|
implements WorkflowService {
|
|
private static final Logger log = LoggerFactory.getLogger(WorkflowServiceImpl.class);
|
|
@Autowired
|
private WorkflowRepository workflowRepository;
|
|
@Autowired
|
private IssueStatusService issueStatusService;
|
|
@Autowired
|
private WorkflowTransitionService workflowTransitionService;
|
|
@Autowired
|
private WorkflowDepartmentService workflowDepartmentService;
|
|
@Autowired
|
private WorkspaceService workspaceService;
|
|
@Autowired
|
private IssueService issueService;
|
|
@Autowired
|
private UserService userService;
|
|
@Autowired
|
private WorkflowMapper workflowMapper;
|
|
@Autowired
|
private ExcelView excelView;
|
|
@Autowired
|
private ExcelConditionCheck excelConditionCheck;
|
|
@Override
|
protected JpaRepository<Workflow, Long> getRepository() {
|
return this.workflowRepository;
|
}
|
|
// 기본 프로젝트에서 사용되는 기본 워크플로우
|
@Override
|
@Transactional
|
public void addDefaultWorkflow(Workspace workspace, List<ProjectType> projectTypes) {
|
|
for (ProjectType projectType : projectTypes) {
|
List<IssueStatus> issueStatuses = Lists.newArrayList();
|
// 워크플로우 생성
|
Workflow workflow = new Workflow();
|
workflow.setWorkspace(workspace);
|
workflow.setProjectType(projectType); // project 생성시 project type 에 맞는 워크플로우/이슈 유형을 자동 생성할 수 있게 해준다. - 프로젝트 템플릿 유형 별로 해당 project type 에 맞는 워크플로우로 생성해준다.
|
|
switch(projectType) {
|
case BTS_PROJECT:
|
workflow.setName(this.messageAccessor.message("common.btsWorkflow")); // BTS 워크플로우
|
workflow.setDescription(this.messageAccessor.message("common.usedToManageThisWorkflow")); // 버그를 관리하는데 사용하는 워크플로우 입니다.
|
issueStatuses = this.issueStatusService.findByWorkspaceId(workspace.getId());
|
break;
|
case RMS_PROJECT:
|
workflow.setName(this.messageAccessor.message("common.rmsWorkflow")); // RMS 워크플로우
|
workflow.setDescription(this.messageAccessor.message("common.userToManageRequirementsThisWorkflow")); // 요구 사항을 관리하는데 사용하는 워크플로우 입니다.
|
issueStatuses = this.issueStatusService.findByWorkspaceId(workspace.getId());
|
break;
|
case TCM_PROJECT:
|
workflow.setName(this.messageAccessor.message("common.tcmWorkflow")); // TCM 워크플로우
|
workflow.setDescription(this.messageAccessor.message("common.userToManageTestCasesThisWorkflow")); // 테스트 케이스를 관리하는데 사용하는 워크플로우 입니다.
|
issueStatuses = this.issueStatusService.findByWorkspaceId(workspace.getId());
|
break;
|
}
|
|
// 워크스페이스에 기본 제공되는 이슈 상태가 없을 경우에는 오류
|
if (issueStatuses.isEmpty()) {
|
throw new OwlRuntimeException(
|
this.messageAccessor.getMessage(MsgConstants.ISSUE_STATUS_NOT_EXIST));
|
}
|
|
this.workflowRepository.saveAndFlush(workflow);
|
// 워크플로우 전이 연결.
|
this.workflowTransitionService.addDefaultWorkflowTransition(workflow, issueStatuses, projectType);
|
}
|
}
|
|
// 워크플로우를 생성한다.
|
@Override
|
@Transactional
|
public Workflow addWorkflow(WorkflowForm workflowForm) {
|
// 사용하고 있는 업무 공간이 활성 상태인지 확인한다. 사용 공간에서 로그인한 사용자가 비활성인지 확인한다.
|
this.workspaceService.checkUseWorkspace();
|
|
// 이름 유효성 체크
|
this.verifyName(workflowForm.getName(), null);
|
Workflow workflow = ConvertUtil.copyProperties(workflowForm, Workflow.class, "projectType");
|
Workspace workspace = this.workspaceService.getWorkspace(this.userService.getUser(this.webAppUtil.getLoginId()).getLastWorkspaceId());
|
workflow.setWorkspace(workspace);
|
|
workflow = this.workflowRepository.saveAndFlush(workflow);
|
this.workflowTransitionService.modify(workflow, workflowForm.getIssueStatusVos());
|
this.workflowDepartmentService.modify(workflow, workflowForm.getIssueStatusVos());
|
|
return workflow;
|
}
|
|
// 이름 유효성 체크
|
private void verifyName(String name, Long id) {
|
if (StringUtils.isEmpty(name)) {
|
throw new OwlRuntimeException(
|
this.messageAccessor.getMessage(MsgConstants.WORKFLOW_NOT_NAME));
|
}
|
|
if (name.length() > 20) {
|
throw new OwlRuntimeException(
|
this.messageAccessor.getMessage(MsgConstants.WORKFLOW_NAME_MAX_LENGTH_OUT));
|
}
|
|
Workflow workflow;
|
Long workspaceId = this.userService.getUser(this.webAppUtil.getLoginId()).getLastWorkspaceId();
|
|
if (id == null) {
|
workflow = this.workflowRepository.findByNameAndWorkspaceId(name, workspaceId);
|
}
|
else {
|
workflow = this.workflowRepository.findByNameAndWorkspaceIdAndIdNot(name, workspaceId, id);
|
}
|
|
if (workflow != null) {
|
throw new OwlRuntimeException(
|
this.messageAccessor.getMessage(MsgConstants.WORKFLOW_USED_NAME));
|
}
|
}
|
|
// 워크플로우 목록을 조회한다.
|
@Override
|
@Transactional(readOnly = true)
|
public List<WorkflowVo> findWorkflow(Map<String, Object> resJsonData,
|
WorkflowCondition condition, Pageable pageable) {
|
|
condition.setPage(pageable.getPageNumber() * pageable.getPageSize());
|
condition.setPageSize(pageable.getPageSize());
|
condition.setWorkspaceId(this.userService.getUser(this.webAppUtil.getLoginId()).getLastWorkspaceId());
|
List<Map<String, Object>> results = this.workflowMapper.find(condition);
|
Long totalCount = this.workflowMapper.count(condition);
|
int totalPage = (int) Math.ceil((totalCount - 1) / pageable.getPageSize()) + 1;
|
List<WorkflowVo> workflowVos = ConvertUtil.convertListToListClass(results, WorkflowVo.class); //workflow 리스트
|
// 워크플로우를 사용하는 이슈 유형 정보를 추가한다.
|
this.setIssueTypeVos(workflowVos);
|
// 워크플로우 담당부서 정보를 추가한다.
|
this.setDepartmentVos(workflowVos);
|
|
resJsonData.put(Constants.REQ_KEY_PAGE_VO, new ResPage(pageable.getPageNumber(), pageable.getPageSize(),
|
totalPage, totalCount));
|
|
resJsonData.put(Constants.RES_KEY_CONTENTS, workflowVos);
|
|
return workflowVos;
|
}
|
|
// 워크플로우를 사용하는 이슈 유형 정보를 추가한다.
|
private void setIssueTypeVos(List<WorkflowVo> workflowVos) {
|
for (WorkflowVo workflowVo : workflowVos) {
|
Workflow workflow = this.getWorkflow(workflowVo.getId());
|
List<IssueTypeVo> issueTypeVos = ConvertUtil.convertObjectsToClasses(workflow.getIssueTypes(), IssueTypeVo.class);
|
workflowVo.setIssueTypeVos(issueTypeVos);
|
}
|
}
|
|
// 워크플로우를 사용하는 부서 정보를 추가한다.
|
private void setDepartmentVos(List<WorkflowVo> workflowVos) {
|
for (WorkflowVo workflowVo : workflowVos) {
|
Workflow workflow = this.getWorkflow(workflowVo.getId());
|
|
List<WorkflowDepartmentVo> workflowDepartmentVos = this.workflowDepartmentService.find(workflow.getId(), null);
|
if (workflowDepartmentVos != null && workflowDepartmentVos.size() > 0) {
|
IssueStatusVo issueStatusVo = new IssueStatusVo();
|
issueStatusVo.setWorkflowDepartmentVos(workflowDepartmentVos);
|
workflowVo.addIssueStatusVos(issueStatusVo);
|
}
|
}
|
}
|
|
// 워크플로우 상세 정보를 조회한다.
|
@Override
|
@Transactional(readOnly = true)
|
public void detailWorkflow(Map<String, Object> resJsonData, WorkflowCondition workflowCondition) {
|
WorkflowVo workflowVo = new WorkflowVo();
|
|
if (workflowCondition.getId() != null) {
|
Workflow workflow = this.getWorkflow(workflowCondition.getId());
|
workflowVo = ConvertUtil.copyProperties(workflow, WorkflowVo.class);
|
|
switch (workflowCondition.getDeep()) {
|
case "01" : // 연관된 이슈 상태와 전이선 정보를 가져온다.
|
List<IssueStatusVo> issueStatusVos = this.issueStatusService.findByWorkflowId(workflowCondition.getId());
|
for (IssueStatusVo issueStatusVo : issueStatusVos) {
|
List<WorkflowDepartmentVo> workflowDepartmentVos = this.workflowDepartmentService.find(workflowVo.getId(), issueStatusVo.getId());
|
issueStatusVo.setWorkflowDepartmentVos(workflowDepartmentVos);
|
}
|
workflowVo.setIssueStatusVos(issueStatusVos);
|
break;
|
}
|
}
|
|
resJsonData.put(Constants.RES_KEY_CONTENTS, workflowVo);
|
}
|
|
// 워크플로우를 수정한다.
|
@Override
|
@Transactional
|
public Workflow modifyWorkflow(WorkflowForm workflowForm) {
|
// 사용하고 있는 업무 공간이 활성 상태인지 확인한다. 사용 공간에서 로그인한 사용자가 비활성인지 확인한다.
|
this.workspaceService.checkUseWorkspace();
|
|
Workflow workflow = this.getWorkflow(workflowForm.getId());
|
// 이름 유효성 체크
|
this.verifyName(workflowForm.getName(), workflowForm.getId());
|
workflow.setName(workflowForm.getName());
|
|
// 담당 부서 정보 변경
|
this.workflowDepartmentService.modify(workflow, workflowForm.getIssueStatusVos());
|
this.workflowTransitionService.modify(workflow, workflowForm.getIssueStatusVos());
|
// 워크플로우가 변경되었는지 확인하고 변경되었을 경우 이슈 상태가 없는 이슈는 '생성' 인 이슈 상태로 이동한다.
|
this.checkWorkflowChange(workflow);
|
|
return workflow;
|
}
|
|
// 워크플로우가 변경되었는지 확인하고 변경되었을 경우 이슈 상태가 없는 이슈는 '생성' 인 이슈 상태로 이동한다.
|
private void checkWorkflowChange(Workflow workflow) {
|
for (IssueType issueType : workflow.getIssueTypes()) {
|
this.issueService.changeWorkflows(workflow, issueType);
|
}
|
}
|
|
@Override
|
@Transactional(readOnly = true)
|
public Workflow getWorkflow(Long id) {
|
if (id == null) {
|
throw new OwlRuntimeException(
|
this.messageAccessor.getMessage(MsgConstants.WORKFLOW_NOT_EXIST));
|
}
|
|
Workflow workflow = this.findOne(id);
|
|
if (workflow == null) {
|
throw new OwlRuntimeException(
|
this.messageAccessor.getMessage(MsgConstants.WORKFLOW_NOT_EXIST));
|
}
|
|
return workflow;
|
}
|
|
// 워크플로우를 삭제한다.
|
@Override
|
@Transactional
|
public void removeWorkflows(WorkflowForm workflowForm) {
|
// 사용하고 있는 업무 공간이 활성 상태인지 확인한다. 사용 공간에서 로그인한 사용자가 비활성인지 확인한다.
|
this.workspaceService.checkUseWorkspace();
|
|
if (workflowForm.getRemoveIds().size() < 1) {
|
throw new OwlRuntimeException(
|
this.messageAccessor.getMessage(MsgConstants.WORKFLOW_REMOVE_NOT_SELECT));
|
}
|
|
for (Long workflowId : workflowForm.getRemoveIds()) {
|
this.removeWorkflow(workflowId);
|
}
|
this.workflowRepository.flush();
|
}
|
|
private void removeWorkflow(Long workflowId) {
|
Workflow workflow = this.getWorkflow(workflowId);
|
// 워크플로우 담당부서 삭제
|
this.workflowDepartmentService.remove(workflowId);
|
// 워크플로우를 이슈 타입에서 사용하고 있는지 확인
|
this.checkIssueTypeWorkflow(workflow);
|
this.workflowRepository.delete(workflow);
|
}
|
|
// 워크플로우를 이슈 타입에서 사용하고 있는지 확인
|
private void checkIssueTypeWorkflow(Workflow workflow) {
|
if (workflow.getIssueTypes().size() > 0) {
|
throw new OwlRuntimeException(
|
this.messageAccessor.getMessage(MsgConstants.WORKFLOW_USED_ISSUE_TYPE));
|
}
|
}
|
|
// 워크스페이스의 해당 프로젝트 유형에서 사용되는 워크플로우를 찾아온다.
|
@Override
|
@Transactional(readOnly = true)
|
public Workflow findByWorkspaceIdAndProjectType(Long workspaceId, ProjectType projectType) {
|
Workflow workflow = this.workflowRepository.findByWorkspaceIdAndProjectType(workspaceId, projectType);
|
|
if (workflow == null) {
|
throw new OwlRuntimeException(
|
this.messageAccessor.getMessage(MsgConstants.WORKFLOW_NOT_EXIST));
|
}
|
|
return workflow;
|
}
|
|
// 워크스페이스에 있는 모든 워크플로우 목록을 조회한다.
|
@Override
|
@Transactional(readOnly = true)
|
public List<Workflow> findByWorkspaceId(Long workspaceId) {
|
return this.workflowRepository.findByWorkspaceId(workspaceId);
|
}
|
|
// 워크플로우 목록을 엑셀로 다운로드 한다.
|
@Override
|
@Transactional
|
public ModelAndView downloadExcel(HttpServletRequest request, Model model) {
|
// 사용 공간에서 로그인한 사용자가 비활성인지 확인하고 비활성일 경우 엑셀 다운로드를 금지한다.
|
ModelAndView modelAndView = this.workspaceService.checkUseExcelDownload(model);
|
if (modelAndView != null) {
|
return modelAndView;
|
}
|
|
Map<String, Object> conditions = new HashMap<>();
|
// 엑셀 다운로드에 필요한 검색 조건 정보를 추출하고 검색 조건 추출에 오류가 발생하면 경고를 표시해준다.
|
modelAndView = this.excelConditionCheck.checkCondition(conditions, request, model);
|
if (modelAndView != null) {
|
return modelAndView;
|
}
|
|
WorkflowCondition workflowCondition = WorkflowCondition.make(conditions);
|
workflowCondition.setWorkspaceId(this.userService.getUser(this.webAppUtil.getLoginId()).getLastWorkspaceId());
|
List<Map<String, Object>> results = this.workflowMapper.find(workflowCondition);
|
List<WorkflowVo> workflowVos = ConvertUtil.convertListToListClass(results, WorkflowVo.class);
|
|
ExportExcelVo excelInfo = new ExportExcelVo();
|
excelInfo.setFileName(this.messageAccessor.message("common.workflowList")); // 워크플로우 목록
|
excelInfo.addAttrInfos(new ExportExcelAttrVo("name", this.messageAccessor.message("common.workflow"), 15, ExportExcelAttrVo.ALIGN_LEFT)); // 워크플로우
|
// 엑셀에 넣을 데이터
|
excelInfo.setDatas(workflowVos);
|
model.addAttribute(Constants.EXCEL, excelInfo);
|
return new ModelAndView(this.excelView);
|
}
|
}
|