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.constant.UsePartner; import kr.wisestone.owl.domain.*; import kr.wisestone.owl.domain.enumType.ProjectType; import kr.wisestone.owl.exception.OwlRuntimeException; import kr.wisestone.owl.mapper.IssueTypeMapper; import kr.wisestone.owl.repository.IssueTypeRepository; import kr.wisestone.owl.repository.ProjectClosureRepository; import kr.wisestone.owl.repository.ProjectRepository; import kr.wisestone.owl.service.*; import kr.wisestone.owl.util.ConvertUtil; import kr.wisestone.owl.util.MapUtil; import kr.wisestone.owl.vo.*; import kr.wisestone.owl.web.condition.IssueTypeCondition; import kr.wisestone.owl.web.form.IssueTypeForm; 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.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @Service public class IssueTypeServiceImpl extends AbstractServiceImpl> implements IssueTypeService { private static final Logger log = LoggerFactory.getLogger(IssueTypeServiceImpl.class); @Autowired private IssueTypeRepository issueTypeRepository; @Autowired private ProjectRepository projectRepository; @Autowired private WorkflowService workflowService; @Autowired private WorkflowDepartmentService workflowDepartmentService; @Autowired private ProjectService projectService; @Autowired private ProjectRoleService projectRoleService; @Autowired private WorkspaceService workspaceService; @Autowired private IssueStatusService issueStatusService; @Autowired private IssueTypeMapper issueTypeMapper; @Autowired private IssueService issueService; @Autowired private UserService userService; @Autowired private ProjectClosureRepository projectClosureRepository; @Autowired private ExcelView excelView; @Autowired private ExcelConditionCheck excelConditionCheck; @Override protected JpaRepository getRepository() { return this.issueTypeRepository; } @Override @Transactional public void addDefaultIssueType(Workspace workspace, List projectTypes) { for (ProjectType projectType : projectTypes) { List issueTypes = Lists.newArrayList(); Workflow workflow = this.workflowService.findByWorkspaceIdAndProjectType(workspace.getId(), projectType); switch (projectType) { case BTS_PROJECT: issueTypes.add(new IssueType(workspace, workflow, "악성 도메인", "", "#ff5f99", 0L, false)); // 버그 issueTypes.add(new IssueType(workspace, workflow, "경유지 대응", "", "#3598fe", 0L, false)); // 개선 break; case RMS_PROJECT: issueTypes.add(new IssueType(workspace, workflow, "유포지 대응", "", "#3bcde2", 0L, false)); // 요구 사항 break; case TCM_PROJECT: issueTypes.add(new IssueType(workspace, workflow, "분석결과 대응", "", "#008ca7", 0L, false)); // 테스트 케이스, 실행 순서, 전제 조건, 기대 결과 break; } this.issueTypeRepository.saveAll(issueTypes); } } @Override @Transactional public void addDefaultUsedProject(Workspace workspace) { List issueTypes = this.issueTypeRepository.findByWorkspaceId(workspace.getId()); List projects = this.projectRepository.findByWorkspaceId(workspace.getId()); if(issueTypes != null && issueTypes.size() > 0){ for(IssueType issueType : issueTypes){ if(projects != null && projects.size()>0){ for(Project project : projects){ issueType.setProject(project); } } } } } // 이슈 유형을 생성한다. @Override @Transactional public IssueType addIssueType(IssueTypeForm issueTypeForm) { // 사용하고 있는 업무 공간이 활성 상태인지 확인한다. 사용 공간에서 로그인한 사용자가 비활성인지 확인한다. this.workspaceService.checkUseWorkspace(); // 이름 유효성 체크 this.verifyName(issueTypeForm.getName(), null); // 색상 체크 this.verifyColor(issueTypeForm.getColor()); IssueType issueType = ConvertUtil.copyProperties(issueTypeForm, IssueType.class); Workspace workspace = this.workspaceService.getWorkspace(this.userService.getUser(this.webAppUtil.getLoginId()).getLastWorkspaceId()); issueType.setWorkspace(workspace); Workflow workflow = this.workflowService.getWorkflow(issueTypeForm.getWorkflowId()); issueType.setWorkflow(workflow); Project project = this.projectService.getProject(issueTypeForm.getProjectId()); issueType.setProject(project); // 워크플로우의 담당부서와 동일하게 세팅 this.setDepartmentOfProject(project, workflow); issueType.setUsePartner(issueTypeForm.getUsePartner()); issueType.setInheritPartners(issueTypeForm.getInheritPartners()); return this.issueTypeRepository.saveAndFlush(issueType); } /** * 워크플로우의 담당부서와 동일하게 세팅 * @param project Project * @param workflow Workflow */ private void setDepartmentOfProject(Project project, Workflow workflow) { List workflowDepartments = this.workflowDepartmentService.find(workflow.getId()); // 해당 워크플로우의 담당부서가 존재 할 경우 해당 프로젝트의 담당부서에도 추가 if (workflowDepartments != null && workflowDepartments.size() > 0) { ProjectRole projectRole = this.projectRoleService.findByProjectIdAndRoleType(project.getId(), ProjectRole.TYPE_DEFAULT); for (WorkflowDepartment workflowDepartment : workflowDepartments) { // 프로젝트 담당부서로 추가 projectRole.addDepartment(workflowDepartment.getDepartment()); } } } // 이름 유효성 체크 private void verifyName(String name, Long id) { if (StringUtils.isEmpty(name)) { throw new OwlRuntimeException( this.messageAccessor.getMessage(MsgConstants.ISSUE_TYPE_NOT_NAME)); } if (name.length() > 15) { throw new OwlRuntimeException( this.messageAccessor.getMessage(MsgConstants.ISSUE_TYPE_NAME_MAX_LENGTH_OUT)); } IssueType issueType; Long workspaceId = this.userService.getUser(this.webAppUtil.getLoginId()).getLastWorkspaceId(); if (id == null) { issueType = this.issueTypeRepository.findByNameAndWorkspaceId(name, workspaceId); } else { issueType = this.issueTypeRepository.findByNameAndWorkspaceIdAndIdNot(name, workspaceId, id); } if (issueType != null) { throw new OwlRuntimeException( this.messageAccessor.getMessage(MsgConstants.ISSUE_TYPE_USED_NAME)); } } // 색상 체크 private void verifyColor(String color) { if (StringUtils.isEmpty(color)) { throw new OwlRuntimeException( this.messageAccessor.getMessage(MsgConstants.ISSUE_TYPE_NOT_COLOR)); } } // 이슈 유형 목록을 조회한다. @Override @Transactional(readOnly = true) public List findIssueType(Map resJsonData, IssueTypeCondition condition, Pageable pageable) { List downProjectIds = Lists.newArrayList(); List allProjectIds = Lists.newArrayList(); List projectClosures = Lists.newArrayList(); condition.setPage(pageable.getPageNumber() * pageable.getPageSize()); condition.setPageSize(pageable.getPageSize()); condition.setWorkspaceId(this.userService.getUser(this.webAppUtil.getLoginId()).getLastWorkspaceId()); if (condition.getProjectId() == null) { List projectVos = this.projectService.findByIncludeProject(Lists.newArrayList("01", "02", "03"), ProjectType.BTS_PROJECT.toString()); if (projectVos != null && projectVos.size() > 0) { for (ProjectVo projectVo : projectVos) { allProjectIds.add(projectVo.getId()); projectClosures = this.projectClosureRepository.findByParentProjectId(projectVo.getId()); if (projectClosures != null && projectClosures.size() > 0) { for (ProjectClosure projectClosure : projectClosures) { allProjectIds.add(projectClosure.getProject().getId()); } } } } }else { projectClosures = this.projectClosureRepository.findByParentProjectId(condition.getProjectId()); } if (projectClosures != null && projectClosures.size() > 0) { for (ProjectClosure projectClosure : projectClosures) { Long downProjectId = projectClosure.getProject().getId(); downProjectIds.add(downProjectId); allProjectIds.add(downProjectId); } } condition.setDownProjectIds(downProjectIds); if (condition.getProjectId() == null) { condition.setAllProjectIds(allProjectIds); } List> results = this.issueTypeMapper.find(condition); for (Map result : results) { Long projectId = MapUtil.getLong(result, "projectId"); if (projectId != null) { Project project = this.projectService.getProject(projectId); ProjectVo projectVo = ConvertUtil.copyProperties(project, ProjectVo.class); result.put("projectVo", projectVo); } Long issueStatusId = MapUtil.getLong(result, "completeIssueStatusId"); if (issueStatusId != null) { IssueStatus issueStatus = this.issueStatusService.getIssueStatus(issueStatusId); IssueStatusVo issueStatusVo = ConvertUtil.copyProperties(issueStatus, IssueStatusVo.class); result.put("completeIssueStatusVo", issueStatusVo); } } Long totalCount = this.issueTypeMapper.count(condition); int totalPage = (int) Math.ceil((totalCount - 1) / pageable.getPageSize()) + 1; List issueTypeVos = ConvertUtil.convertListToListClass(results, IssueTypeVo.class); // 이슈 유형에 연결된 워크플로우 정보를 셋팅한다. if (condition.getDeep() != null) { this.setUseIssueTypeByWorkflow(issueTypeVos); } this.setUseIssueTypeByProject(issueTypeVos); this.setUseIssueTypeByIssueStatus(issueTypeVos); /*this.setUseIssueTypeByCompanyField(issueTypeVos); this.setUseIssueTypeByIspField(issueTypeVos); this.setUseIssueTypeByHostingField(issueTypeVos);*/ this.setUsePartner(issueTypeVos); resJsonData.put(Constants.REQ_KEY_PAGE_VO, new ResPage(pageable.getPageNumber(), pageable.getPageSize(), totalPage, totalCount)); resJsonData.put(Constants.RES_KEY_CONTENTS, issueTypeVos); return issueTypeVos; } // 이슈 유형 목록을 조회한다. @Override @Transactional(readOnly = true) public List findIssueType(IssueTypeCondition condition) { condition.setWorkspaceId(this.userService.getUser(this.webAppUtil.getLoginId()).getLastWorkspaceId()); List> results = this.issueTypeMapper.find(condition); return ConvertUtil.convertListToListClass(results, IssueTypeVo.class); } // 이슈 유형에 연결된 워크플로우 정보를 셋팅한다. private void setUseIssueTypeByWorkflow(List issueTypeVos) { for (IssueTypeVo issueTypeVo : issueTypeVos) { IssueType issueType = this.getIssueType(issueTypeVo.getId()); issueTypeVo.setWorkflowVo(ConvertUtil.copyProperties(issueType.getWorkflow(), WorkflowVo.class)); } } // 이슈 유형에 연결된 파트너 정보를 셋팅한다. private void setUsePartner(List issueTypeVos) { for (IssueTypeVo issueTypeVo : issueTypeVos) { List usePartnerVos = Lists.newArrayList(); if (issueTypeVo.getUsePartners() != null) { for (Integer usePartner : UsePartner.partners) {// 1 // 2 // 4 UsePartnerVo usePartnerVo = UsePartner.checkUsePartner(issueTypeVo.getUsePartners(), usePartner);//3, 1 / 3, 2 / 3, 4 if (usePartnerVo != null) { usePartnerVos.add(usePartnerVo); } } issueTypeVo.setUsePartnerVos(usePartnerVos); } } } // 이슈 유형에 연결된 프로젝트 정보를 셋팅한다. private void setUseIssueTypeByProject(List issueTypeVos) { for (IssueTypeVo issueTypeVo : issueTypeVos) { IssueType issueType = this.getIssueType(issueTypeVo.getId()); Project project = issueType.getProject(); if (project != null) { issueTypeVo.setProjectVo(ConvertUtil.copyProperties(issueType.getProject(), ProjectVo.class)); } } } // 이슈 유형에 프로젝트ID로 조회 public List findByProjectId(Long projectId) { return this.issueTypeRepository.findByProjectId(projectId); } private void setUseIssueTypeByIssueStatus(List issueTypeVos) { for (IssueTypeVo issueTypeVo : issueTypeVos) { IssueType issueType = this.getIssueType(issueTypeVo.getId()); Set issueTypeApiEndStatuses = issueType.getIssueTypeApiEndStatuses(); if (issueTypeApiEndStatuses != null && issueTypeApiEndStatuses.size() > 0) { IssueTypeApiEndStatus issueTypeApiEndStatus = issueTypeApiEndStatuses.iterator().next(); issueTypeVo.setCompleteIssueStatusVo(ConvertUtil.copyProperties(issueTypeApiEndStatus.getIssueStatus(), IssueStatusVo.class)); } } } /*// 이슈 유형에 연결된 업체 정보를 셋팅한다. private void setUseIssueTypeByCompanyField(List issueTypeVos) { for (IssueTypeVo issueTypeVo : issueTypeVos){ IssueType issueType = this.getIssueType(issueTypeVo.getId()); CompanyField companyField = issueType.getCompanyField(); if(companyField != null){ issueTypeVo.setCompanyFieldVo(ConvertUtil.copyProperties(issueType.getCompanyField(), CompanyFieldVo.class)); } } } */ // 이슈 유형 상세 정보를 조회한다. @Override @Transactional(readOnly = true) public void detailIssueType(Map resJsonData, IssueTypeCondition issueTypeCondition) { IssueTypeVo issueTypeVo = new IssueTypeVo(); if (issueTypeCondition.getId() != null) { IssueType issueType = this.getIssueType(issueTypeCondition.getId()); issueTypeVo = ConvertUtil.copyProperties(issueType, IssueTypeVo.class); switch (issueTypeCondition.getDeep()) { case "01": // 워크플로우 정보를 가져온다. issueTypeVo.setWorkflowVo(ConvertUtil.copyProperties(issueType.getWorkflow(), WorkflowVo.class)); break; } Project project = issueType.getProject(); if (project != null) { issueTypeVo.setProjectVo(ConvertUtil.copyProperties(issueType.getProject(), ProjectVo.class)); } Integer using = issueType.getUsePartner() != null ? issueType.getUsePartner().intValue() : 0; List usePartnerVos = Lists.newArrayList(); for (Integer usePartner : UsePartner.partners) {// 1 // 2 // 4 UsePartnerVo usePartnerVo = UsePartner.checkUsePartner(using, usePartner);//3, 1 / 3, 2 / 3, 4 if (usePartnerVo != null) { usePartnerVos.add(usePartnerVo); } } issueTypeVo.setUsePartnerVos(usePartnerVos); } resJsonData.put(Constants.RES_KEY_CONTENTS, issueTypeVo); } // 이슈 유형을 수정한다. @Override @Transactional public IssueType modifyIssueType(IssueTypeForm issueTypeForm) { // 사용하고 있는 업무 공간이 활성 상태인지 확인한다. 사용 공간에서 로그인한 사용자가 비활성인지 확인한다. this.workspaceService.checkUseWorkspace(); IssueType issueType = this.getIssueType(issueTypeForm.getId()); // 이름 유효성 체크 this.verifyName(issueTypeForm.getName(), issueTypeForm.getId()); // 색상 체크 this.verifyColor(issueTypeForm.getColor()); Workflow workflow = this.workflowService.getWorkflow(issueTypeForm.getWorkflowId()); // 워크플로우 변경 체크 this.checkWorkflowChange(issueType.getWorkflow(), workflow, issueType); ConvertUtil.copyProperties(issueTypeForm, issueType, "id", "issueTypeType"); issueType.setWorkflow(workflow); Project project = this.projectService.getProject(issueTypeForm.getProjectId()); issueType.setProject(project); // 워크플로우의 담당부서와 동일하게 세팅 this.setDepartmentOfProject(project, workflow); issueType.setUsePartner(issueTypeForm.getUsePartner()); issueType.setInheritPartners(issueTypeForm.getInheritPartners()); /*if(issueTypeForm.getCompanyId() != null){ CompanyField companyField = this.companyFieldService.getCompany(issueTypeForm.getCompanyId()); issueType.setCompanyField(companyField); }*/ // issueType.setCompanyYn(issueTypeForm.getCompanyYn()); this.issueTypeRepository.saveAndFlush(issueType); return issueType; } // 워크플로우가 변경되었는지 확인하고 변경되었을 경우 이슈 상태가 없는 이슈는 '생성' 인 이슈 상태로 이동한다. private void checkWorkflowChange(Workflow oldWorkflow, Workflow newWorkflow, IssueType issueType) { if (!oldWorkflow.getId().equals(newWorkflow.getId())) { // 이슈 유형에서 워크플로우가 변경되었을 때 해당 워크플로우에 현재 이슈 상태가 존재하지 않으면 대기(생성) 로 변경한다. this.issueService.changeWorkflows(newWorkflow, issueType); } } @Override @Transactional(readOnly = true) public IssueType getIssueType(Long id) { if (id == null) { throw new OwlRuntimeException( this.messageAccessor.getMessage(MsgConstants.ISSUE_TYPE_NOT_EXIST)); } IssueType issueType = this.findOne(id); if (issueType == null) { throw new OwlRuntimeException( this.messageAccessor.getMessage(MsgConstants.ISSUE_TYPE_NOT_EXIST)); } return issueType; } // 이슈 유형을 삭제한다. @Override @Transactional public void removeIssueTypes(IssueTypeForm issueTypeForm) { // 사용하고 있는 업무 공간이 활성 상태인지 확인한다. 사용 공간에서 로그인한 사용자가 비활성인지 확인한다. this.workspaceService.checkUseWorkspace(); if (issueTypeForm.getRemoveIds().size() < 1) { throw new OwlRuntimeException( this.messageAccessor.getMessage(MsgConstants.ISSUE_TYPE_REMOVE_NOT_SELECT)); } for (Long projectId : issueTypeForm.getRemoveIds()) { this.removeIssueTypes(projectId); } this.issueTypeRepository.flush(); } private void removeIssueTypes(Long issueTypeId) { IssueType issueType = this.getIssueType(issueTypeId); // 삭제할 이슈 유형이 사용되고 있는지 확인한다. this.checkUseIssueType(issueType); this.issueTypeRepository.delete(issueType); } // 삭제할 이슈 유형이 사용되고 있는지 확인한다. private void checkUseIssueType(IssueType issueType) { // 이슈 유형을 사용하는 이슈 갯수를 조회한다. Long issueCount = this.issueService.countByIssueTypeId(issueType.getId()); if (issueCount > 0) { throw new OwlRuntimeException( this.messageAccessor.getMessage(MsgConstants.ISSUE_TYPE_USE_ISSUES)); } } // 워크스페이스에 있는 모든 이슈 유형을 조회한다. 이슈 엑셀 import 에서 사용 @Override @Transactional(readOnly = true) public List findByWorkspaceId() { return this.issueTypeRepository.findByWorkspaceId(this.userService.getUser(this.webAppUtil.getLoginId()).getLastWorkspaceId()); } // 워크플로우 ID로 이슈 유형 조회 @Override @Transactional(readOnly = true) public List findByWorkflowId(Long id) { return this.issueTypeRepository.findByWorkflowId(id); } // 이슈 타입 필드 목록을 엑셀로 다운로드 한다. @Override @Transactional public ModelAndView downloadExcel(HttpServletRequest request, Model model) { // 사용 공간에서 로그인한 사용자가 비활성인지 확인하고 비활성일 경우 엑셀 다운로드를 금지한다. ModelAndView modelAndView = this.workspaceService.checkUseExcelDownload(model); if (modelAndView != null) { return modelAndView; } Map conditions = new HashMap<>(); // 엑셀 다운로드에 필요한 검색 조건 정보를 추출하고 검색 조건 추출에 오류가 발생하면 경고를 표시해준다. modelAndView = this.excelConditionCheck.checkCondition(conditions, request, model); if (modelAndView != null) { return modelAndView; } IssueTypeCondition issueTypeCondition = IssueTypeCondition.make(conditions); issueTypeCondition.setWorkspaceId(this.userService.getUser(this.webAppUtil.getLoginId()).getLastWorkspaceId()); List> results = this.issueTypeMapper.find(issueTypeCondition); List issueTypeVos = ConvertUtil.convertListToListClass(results, IssueTypeVo.class); // 이슈 유형에 연결된 워크플로우 정보를 셋팅한다. if (issueTypeCondition.getDeep() != null) { this.setUseIssueTypeByWorkflow(issueTypeVos); } ExportExcelVo excelInfo = new ExportExcelVo(); excelInfo.setFileName(this.messageAccessor.message("common.issueTypeList")); // 이슈 타입 목록 excelInfo.addAttrInfos(new ExportExcelAttrVo("name", this.messageAccessor.message("common.issueType"), 15, ExportExcelAttrVo.ALIGN_LEFT)); // 이슈 타입 excelInfo.addAttrInfos(new ExportExcelAttrVo("color", this.messageAccessor.message("common.color"), 6, ExportExcelAttrVo.ALIGN_CENTER)); // 색상 excelInfo.addAttrInfos(new ExportExcelAttrVo("workflowName", this.messageAccessor.message("common.workflow"), 10, ExportExcelAttrVo.ALIGN_CENTER)); // 워크플로우 // 엑셀에 넣을 데이터 excelInfo.setDatas(this.convertExcelViewToIssueTypeVos(issueTypeVos)); model.addAttribute(Constants.EXCEL, excelInfo); return new ModelAndView(this.excelView); } // IssueTypeVo 데이터를 엑셀에서 표시할 수 있는 데이터로 변경한다. private List> convertExcelViewToIssueTypeVos(List issueTypeVos) { List> results = Lists.newArrayList(); for (IssueTypeVo issueTypeVo : issueTypeVos) { Map result = new HashMap<>(); result.put("name", issueTypeVo.getName()); result.put("color", issueTypeVo.getColor()); result.put("workflowName", issueTypeVo.getWorkflowVo().getName()); results.add(result); } return results; } }