package kr.wisestone.owl.service.impl; import com.google.common.collect.Lists; import kr.wisestone.owl.common.ExcelConditionCheck; import kr.wisestone.owl.common.MessageAccessor; import kr.wisestone.owl.constant.Constants; import kr.wisestone.owl.constant.MngPermission; 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.IssueMapper; import kr.wisestone.owl.mapper.WidgetMapper; import kr.wisestone.owl.repository.ProjectClosureRepository; import kr.wisestone.owl.repository.UserDepartmentRepository; import kr.wisestone.owl.service.*; import kr.wisestone.owl.util.*; import kr.wisestone.owl.vo.*; import kr.wisestone.owl.web.condition.IssueCondition; import kr.wisestone.owl.web.condition.WidgetCondition; import kr.wisestone.owl.web.view.ExcelView; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.StopWatch; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; 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 WidgetServiceImpl implements WidgetService { private static final Logger log = LoggerFactory.getLogger(WidgetServiceImpl.class); @Autowired private WidgetMapper widgetMapper; @Autowired private IssueMapper issueMapper; @Autowired protected WebAppUtil webAppUtil; @Autowired protected PageUtil pageUtil; @Autowired private ProjectService projectService; @Autowired private ProjectRoleDepartmentService projectRoleDepartmentService; @Autowired private ProjectClosureService projectClosureService; @Autowired private IssueStatusService issueStatusService; @Autowired private UserService userService; @Autowired private UserLevelService userLevelService; @Autowired private UserDepartmentService userDepartmentService; @Autowired private UserDepartmentRepository userDepartmentRepository; @Autowired protected MessageAccessor messageAccessor; @Autowired private ExcelView excelView; @Autowired private WorkspaceService workspaceService; @Autowired private ExcelConditionCheck excelConditionCheck; @Autowired private UserWorkspaceService userWorkspaceService; @Autowired private ProjectClosureRepository projectClosureRepository; // 전체 위젯을 조회한다. @Override @Transactional(readOnly = true) public void findAllWidget(Map resJsonData) { Long lastProjectId = userService.getUser(this.webAppUtil.getLoginId()).getLastProjectId(); // 위젯의 기본 검색 조건을 설정한다. WidgetCondition widgetCondition = this.makeWidgetCondition(); if (lastProjectId != null && lastProjectId > -1) { widgetCondition.setProjectIds(lastProjectId); resJsonData.put("dashboardType", 1); } else { resJsonData.put("dashboardType", 0); } // 페이징 설정 - 모든 위젯은 데이터를 5개만 가져온다. PageVo pageVo = this.pageUtil.getDefaultPageVo(); pageVo.setPageSize(5); Pageable pageable = this.pageUtil.convertPageable(pageVo); // 전체 이슈 정보를 조회한다. this.findStatisticsIssue(resJsonData, widgetCondition); // 1.129 - 1.06 튜닝 결과 : 0.795 - 0.686 // 전체 이슈 처리현황을 조회한다. this.findIssueComplete(resJsonData, widgetCondition, null); // 0.169 - 0.168 // 진행중인 프로젝트 현황 정보를 조회한다. this.findProjectProgress(resJsonData, widgetCondition); // 0.1 - 0.1 // 나의 이슈 현황 정보를 조회한다. - 내가 담당/할당하는 이슈 현황 정보도 여기서 추출한다. this.findMyIssueDetail(resJsonData, widgetCondition); // 5.053 - 6.933 튜닝 결과 : 0.36 - 0.33 // 나에게 할당된 이슈 정보를 조회한다. this.findMyAssigneeIssue(resJsonData, widgetCondition, pageable); // 0.442 - 0.399 튜닝 결과 : 0.266 - 0.273 // 위험 관리 이슈 정보를 조회한다. this.findRiskIssue(resJsonData, widgetCondition, pageable); // 1.153 - 1.15 - 튜닝 결과 : 0.64 - 0.63 // 내가 등록한 이슈 정보를 조회한다. this.findRegisterIssue(resJsonData, widgetCondition, pageable); // 0.263 - 0.270 - 튜닝 결과 : 0.145 - 0.149 StopWatch serviceStart = new StopWatch(); serviceStart.start(); // 지연중인 이슈 정보를 조회한다. this.findDelayIssue(resJsonData, widgetCondition, pageable); // 0.044 - 0.055 serviceStart.stop(); // 상태별 이슈 현황을 조회한다. this.findByStandIssueStatus(resJsonData, widgetCondition); // 프로젝트 별 멤버 진행률 정보를 조회한다. this.findMemberProgress(resJsonData, widgetCondition, false); // 0.271 - 0.271 // 이슈 타입 별 이슈 정보를 조회한다. this.findByStandIssueType(resJsonData, widgetCondition, false); // 0.025 // 중요도 별 이슈 정보를 조회한다. this.findSeverityIssueWidget(resJsonData, widgetCondition, null, pageable); log.debug("serviceEnd : " + serviceStart.getTime()); log.debug("완료"); } // 위젯의 기본 검색 조건을 설정한다. @Override @Transactional(readOnly = true) public WidgetCondition makeWidgetCondition() { User user = this.webAppUtil.getLoginUserObject(); UserLevel userLevel = this.userLevelService.getUserLevel(user.getUserLevel().getId()); // 해당 워크스페이스에서 참여하고 있는 프로젝트 중 상태가 오픈인 프로젝트 List> projects = null; if (this.userWorkspaceService.checkWorkspaceManager(user) || MngPermission.checkMngPermission(userLevel.getPermission(), MngPermission.USER_PERMISSION_MNG_PROJECT)) { projects = this.projectService.findByWorkspaceManagerAll(); } else { projects = this.projectService.findByWorkspaceIdAndIncludeProjectAll(Lists.newArrayList("02"), ProjectType.BTS_PROJECT.toString()); } List projectIds = Lists.newArrayList(); for (Map result : projects) { Long projectId = MapUtil.getLong(result, "id"); if (projectId != null) { projectIds.add(projectId); } } WidgetCondition widgetCondition = new WidgetCondition(); widgetCondition.setProjectIds(projectIds); widgetCondition.setProjects(projects); widgetCondition.setLoginUserId(this.webAppUtil.getLoginId()); this.SetMyDepartmentId(widgetCondition); // 로그인 한 유저가 속해있는 부서 widgetCondition.setCompleteDate(DateUtil.convertDateToStr(new Date())); widgetCondition.setWorkspaceId(this.userService.getUser(this.webAppUtil.getLoginId()).getLastWorkspaceId()); return widgetCondition; } void SetMyDepartmentId(WidgetCondition widgetCondition){ Long loginId = widgetCondition.getLoginUserId(); List myDepartmentIds = Lists.newArrayList(); List myDepartments = this.userDepartmentRepository.findByUserId(loginId); if(myDepartments != null && myDepartments.size() > 0){ for(UserDepartment myDepartment : myDepartments){ myDepartmentIds.add(myDepartment.getDepartmentId()); } } widgetCondition.setMyDepartmentIds(myDepartmentIds); } void SetMeAndDownProjectIds(List parentProjectIds, WidgetCondition widgetCondition) { List downProjectIds = Lists.newArrayList(); List projectIds = Lists.newArrayList(); projectIds.add(-1L); User user = this.webAppUtil.getLoginUserObject(); UserLevel userLevel = this.userLevelService.getUserLevel(user.getUserLevel().getId()); if(parentProjectIds != null && parentProjectIds.size() > 0){ for(Long parentProjectId : parentProjectIds){ if(!this.userWorkspaceService.checkWorkspaceManager(user) || !MngPermission.checkMngPermission(userLevel.getPermission(), MngPermission.USER_PERMISSION_MNG_PROJECT)){ Project project = this.projectService.getProject(parentProjectId); List> results = this.projectService.findByWorkspaceIdAndIncludeProject(Lists.newArrayList("01", "02", "03"), project.getProjectType().toString()); if(results == null || results.size() < 1) { widgetCondition.setMeAndDownProjectIds(projectIds); break; } } List projectClosures = this.projectClosureRepository.findByParentProjectId(parentProjectId); //내 프로젝트ID가 상위프로젝트인게 있는지 if(projectClosures != null && projectClosures.size() > 0){ for(ProjectClosure projectClosure : projectClosures){ if(projectClosure.getParentProject().getId().equals(parentProjectId)){ downProjectIds.add(projectClosure.getProject().getId()); //widgetCondition.setDownProjectIds(downProjectIds); }else{ downProjectIds.clear(); } } }else{ downProjectIds.clear(); } widgetCondition.setDownProjectIds(downProjectIds); List meAndDownProjectIds = Lists.newArrayList(); meAndDownProjectIds.addAll(widgetCondition.getProjectIds()); meAndDownProjectIds.addAll(widgetCondition.getDownProjectIds()); widgetCondition.setMeAndDownProjectIds(meAndDownProjectIds); } } } // 전체 이슈 정보를 조회한다. @Override @Transactional(readOnly = true) public void findStatisticsIssue(Map resJsonData, WidgetCondition widgetCondition) { Long noAssigneeIssue = 0L; // 미할당 이슈 Long remainIssue = 0L; // 잔여 이슈 Long assigneeIssue = 0L; // 할당된 이슈 Long registerIssue = 0L; // 등록한 이슈 Long delayIssue = 0L; // 지연된 이슈 Long completeIssue = 0L; // 완료된 이슈 widgetCondition.setLoginUserId(this.webAppUtil.getLoginId()); widgetCondition.setWorkspaceId(this.userService.getUser(this.webAppUtil.getLoginId()).getLastWorkspaceId()); User user = this.webAppUtil.getLoginUserObject(); UserLevel userLevel = this.userLevelService.getUserLevel(user.getUserLevel().getId()); if (widgetCondition.getProjectIds().size() > 0) { SetMeAndDownProjectIds(widgetCondition.getProjectIds(), widgetCondition); if (this.userWorkspaceService.checkWorkspaceManager(user) || (MngPermission.checkMngPermission(userLevel.getPermission(), MngPermission.USER_PERMISSION_MNG_ISSUE))) { remainIssue = this.widgetMapper.countRemainIssue(widgetCondition); // 잔여 이슈 delayIssue = this.widgetMapper.countTodayDelayIssue(widgetCondition); // 지연된 이슈 assigneeIssue = this.widgetMapper.countAssigneeIssue(widgetCondition); // 할당된 이슈 registerIssue = this.widgetMapper.countTodayRegisterIssue(widgetCondition); // 등록한 이슈 noAssigneeIssue = this.widgetMapper.countNoAssigneeIssue(widgetCondition); // 미할당 이슈 completeIssue = this.widgetMapper.countCompleteIssue(widgetCondition); // 완료된 이슈 } else { SetMyDepartmentId(widgetCondition); remainIssue = this.widgetMapper.countRemainIssueByDepartment(widgetCondition); // 잔여 이슈 delayIssue = this.widgetMapper.countTodayDelayIssueByDepartment(widgetCondition); // 지연된 이슈 //assigneeIssue = this.widgetMapper.countAssigneeIssueByDepartment(widgetCondition); // 할당된 이슈 assigneeIssue = this.widgetMapper.countAssigneeIssue(widgetCondition); // 할당된 이슈 //registerIssue = this.widgetMapper.countTodayRegisterIssueByDepartment(widgetCondition); // 등록한 이슈 registerIssue = this.widgetMapper.countTodayRegisterIssue(widgetCondition); // 등록한 이슈 //noAssigneeIssue = this.widgetMapper.countNoAssigneeIssueByDepartment(widgetCondition); // 일반 유저는 미할당 이슈 0개로 보이게 completeIssue = this.widgetMapper.countCompleteIssueByDepartment(widgetCondition); // 완료된 이슈 } } Map results = new HashMap<>(); results.put("today", DateUtil.convertDateToStr(new Date(), "yyyy.MM.dd")); results.put("projectIds", widgetCondition.getProjectIds()); results.put("noAssigneeIssue", noAssigneeIssue); results.put("registerIssue", registerIssue); results.put("assigneeIssue", assigneeIssue); results.put("delayIssue", delayIssue); results.put("remainIssue", remainIssue); results.put("completeIssue", completeIssue); // 업무 공간 만료가 7일전일 경우 표시 results.put("workspace", this.workspaceService.getWorkspaceExpireDay()); resJsonData.put("issueStatisticsWidget", results); } // 진행중인 프로젝트 현황 정보를 조회한다. @Override @Transactional(readOnly = true) public void findProjectProgress(Map resJsonData, WidgetCondition widgetCondition) { List> progressingProjectDetails = Lists.newArrayList(); User user = this.webAppUtil.getLoginUserObject(); UserLevel userLevel = this.userLevelService.getUserLevel(user.getUserLevel().getId()); if (widgetCondition.getProjectIds().size() > 0) { SetMeAndDownProjectIds(widgetCondition.getProjectIds(), widgetCondition); if (this.userWorkspaceService.checkWorkspaceManager(user) || MngPermission.checkMngPermission(userLevel.getPermission(), MngPermission.USER_PERMISSION_MNG_PROJECT)) { progressingProjectDetails = this.widgetMapper.findProjectProgressAll(widgetCondition); } else { progressingProjectDetails = this.widgetMapper.findProjectProgress(widgetCondition); } } Long completeIssueCount = 0L; Long remainIssueCount = 0L; for (Map progressingProjectDetail : progressingProjectDetails) { Long completeCount = MapUtil.getLong(progressingProjectDetail, "close"); // 완료 이슈 Long remainCount = MapUtil.getLong(progressingProjectDetail, "remain"); // 잔여 이슈 // 관리자 정보를 파싱하여 관리자 명, 이메일, 프로필 정보를 추출한다. this.parseManagerInfo(MapUtil.getString(progressingProjectDetail, "managerInfo"), progressingProjectDetail); // 프로젝트 진행률 정보를 구한다. this.statisticsProject(completeCount, remainCount, progressingProjectDetail, "projectProgressPercent"); if (completeCount != null) { completeIssueCount += completeCount; } if (remainCount != null) { remainIssueCount += remainCount; } } // 프로젝트 진행률 Double progressPercent = ((double) completeIssueCount / ((double) completeIssueCount + (double) remainIssueCount)) * 100.0; if (progressPercent.isNaN()) { progressPercent = 0.0; } Map results = new HashMap<>(); results.put("totalIssueCount", completeIssueCount + remainIssueCount); results.put("completeIssueCount", completeIssueCount); results.put("remainIssueCount", remainIssueCount); results.put("progressPercent", progressPercent); results.put("projects", progressingProjectDetails); resJsonData.put("projectProgressWidget", results); } // 관리자 정보를 파싱하여 관리자 명, 이메일, 프로필 정보를 추출한다. private void parseManagerInfo(String managerInfo, Map progressingProjectDetail) { if (managerInfo != null) { int count = 0; for (String text : managerInfo.split("%")) { if (!StringUtils.isEmpty(text)) { if (count == 0) { progressingProjectDetail.put("managerName", text); } if (count == 1) { progressingProjectDetail.put("managerEmail", CommonUtil.decryptAES128(text)); } if (count == 2) { progressingProjectDetail.put("managerProfile", text); } } count++; } } } // 프로젝트 진행률 정보를 구한다. private void statisticsProject(Long completeCount, Long remainCount, Map progressingProjectDetail, String mapKey) { Double projectProgressPercent = ((double) completeCount / ((double) completeCount + (double) remainCount)) * 100.0; if (projectProgressPercent.isNaN()) { projectProgressPercent = 0.0; } progressingProjectDetail.put(mapKey, projectProgressPercent); } // 나에게 할당된 이슈 정보를 조회한다. @Override @Transactional(readOnly = true) public void findMyAssigneeIssue(Map resJsonData, WidgetCondition widgetCondition, Pageable pageable) { widgetCondition.setPage(pageable.getPageNumber() * pageable.getPageSize()); widgetCondition.setPageSize(pageable.getPageSize()); // 할당된 잔여 이슈 Map myIssueWidget = (Map) resJsonData.get("myIssueWidget"); Long totalAssigneeRemainIssueCount = MapUtil.getLong(myIssueWidget, "totalAssigneeRemainIssueCount"); if (totalAssigneeRemainIssueCount == null) { totalAssigneeRemainIssueCount = 0L; } // 오늘 할당된 이슈 Long todayCount = 0L; List> assigneeIssues = Lists.newArrayList(); Long totalCount = 0L; if (widgetCondition.getProjectIds().size() > 0) { SetMeAndDownProjectIds(widgetCondition.getProjectIds(), widgetCondition); this.SetMyDepartmentId(widgetCondition); todayCount = this.widgetMapper.countTodayMyAssigneeIssue(widgetCondition); assigneeIssues = this.widgetMapper.findMyAssigneeIssue(widgetCondition); totalCount = this.widgetMapper.countMyAssigneeIssue(widgetCondition); } // 0.156 - 0.166 int totalPage = (int) Math.ceil((totalCount - 1) / pageable.getPageSize()) + 1; Map results = new HashMap<>(); results.put("todayCount", todayCount); results.put("remainCount", totalAssigneeRemainIssueCount); results.put("issues", assigneeIssues); results.put(Constants.REQ_KEY_PAGE_VO, new ResPage(pageable.getPageNumber(), pageable.getPageSize(), totalPage, totalCount)); resJsonData.put("myAssigneeIssueWidget", results); } // 지연중인 이슈 정보를 조회한다. @Override @Transactional(readOnly = true) public void findDelayIssue(Map resJsonData, WidgetCondition widgetCondition, Pageable pageable) { widgetCondition.setPage(pageable.getPageNumber() * pageable.getPageSize()); widgetCondition.setPageSize(pageable.getPageSize()); List> delayIssues = Lists.newArrayList(); Long totalCount = 0L; if (widgetCondition.getProjectIds().size() > 0) { SetMeAndDownProjectIds(widgetCondition.getProjectIds(), widgetCondition); this.SetMyDepartmentId(widgetCondition); delayIssues = this.widgetMapper.findDelayIssue(widgetCondition); totalCount = this.widgetMapper.countDelayIssue(widgetCondition); } int totalPage = (int) Math.ceil((totalCount - 1) / pageable.getPageSize()) + 1; // 오늘 날짜를 기준으로 지연일을 구한다. this.setDelayDay(delayIssues); Map results = new HashMap<>(); results.put("delayCount", totalCount); results.put("issues", delayIssues); results.put(Constants.REQ_KEY_PAGE_VO, new ResPage(pageable.getPageNumber(), pageable.getPageSize(), totalPage, totalCount)); resJsonData.put("delayIssueWidget", results); } // 오늘 날짜를 기준으로 지연일을 구한다. private void setDelayDay(List> delayIssues) { for (Map delayIssue : delayIssues) { String completeDate = MapUtil.getString(delayIssue, "completeDate"); Date convertCompleteDate = DateUtil.convertStrToDate(completeDate, "yyyy.MM.dd"); Integer diff = DateUtil.getDateDiff(convertCompleteDate, new Date()); delayIssue.put("delayDay", diff); } } // 내가 등록한 이슈 정보를 조회한다. @Override @Transactional(readOnly = true) public void findRegisterIssue(Map resJsonData, WidgetCondition widgetCondition, Pageable pageable) { widgetCondition.setPage(pageable.getPageNumber() * pageable.getPageSize()); widgetCondition.setPageSize(pageable.getPageSize()); // 등록한 잔여 이슈 Map myIssueWidget = (Map) resJsonData.get("myIssueWidget"); Long totalRegisterRemainIssueCount = MapUtil.getLong(myIssueWidget, "totalRegisterRemainIssueCount"); if (totalRegisterRemainIssueCount == null) { totalRegisterRemainIssueCount = 0L; } // 오늘 등록한 이슈 Long todayCount = 0L; List> registerIssues = Lists.newArrayList(); Long totalCount = 0L; if (widgetCondition.getProjectIds().size() > 0) { SetMeAndDownProjectIds(widgetCondition.getProjectIds(), widgetCondition); todayCount = this.widgetMapper.countTodayRegisterIssue(widgetCondition); registerIssues = this.widgetMapper.findRegisterIssue(widgetCondition); totalCount = this.widgetMapper.countRegisterIssue(widgetCondition); } int totalPage = (int) Math.ceil((totalCount - 1) / pageable.getPageSize()) + 1; Map results = new HashMap<>(); results.put("todayCount", todayCount); results.put("remainCount", totalRegisterRemainIssueCount); results.put("issues", registerIssues); results.put(Constants.REQ_KEY_PAGE_VO, new ResPage(pageable.getPageNumber(), pageable.getPageSize(), totalPage, totalCount)); resJsonData.put("registerIssueWidget", results); } // 프로젝트 별 멤버 진행률 정보를 조회한다. @Override @Transactional(readOnly = true) public void findMemberProgress(Map resJsonData, WidgetCondition widgetCondition, Boolean getWidgetCondition) { // 위젯 검색 조건을 만들고 전체 프로젝트 정보를 리턴한다. Map results = this.makeWidgetConditionAllProject(widgetCondition, getWidgetCondition); widgetCondition.setLoginUserId(this.webAppUtil.getLoginId()); widgetCondition.setWorkspaceId(this.userService.getUser(this.webAppUtil.getLoginId()).getLastWorkspaceId()); User user = this.webAppUtil.getLoginUserObject(); UserLevel userLevel = this.userLevelService.getUserLevel(user.getUserLevel().getId()); if (widgetCondition.getProjectId() != null) { SetMeAndDownProjectIds(widgetCondition.getProjectIds(), widgetCondition); List> projectMemberIssues = Lists.newArrayList(); if (this.userWorkspaceService.checkWorkspaceManager(user) || MngPermission.checkMngPermission(userLevel.getPermission(), MngPermission.USER_PERMISSION_MNG_ISSUE)) { projectMemberIssues = this.widgetMapper.findProjectMemberIssue(widgetCondition); } else { projectMemberIssues = this.widgetMapper.findProjectMemberIssueByDepartment(widgetCondition); } for (Map projectMemberIssue : projectMemberIssues) { //String departmentName = MapUtil.getString(projectMemberIssue, "departmentName"); Long completeCount = MapUtil.getLong(projectMemberIssue, "completeCount"); Long remainCount = MapUtil.getLong(projectMemberIssue, "remainCount"); //projectMemberIssue.put("account", CommonUtil.decryptAES128(MapUtil.getString(projectMemberIssue, "account"))); // 프로젝트 진행률 정보를 구한다. this.statisticsProject(completeCount, remainCount, projectMemberIssue, "projectProgressPercent"); } // 멤버별 정보 results.put("members", projectMemberIssues); } else { results.put("members", Lists.newArrayList()); } resJsonData.put("memberProgressWidget", results); } // 나의 이슈 현황 정보를 조회한다. @Override @Transactional(readOnly = true) public void findMyIssueDetail(Map resJsonData, WidgetCondition widgetCondition) { List> registerCompleteIssueMaps = Lists.newArrayList(); List> registerRemainIssueMaps = Lists.newArrayList(); List> assigneeCompleteIssueMaps = Lists.newArrayList(); List> assigneeRemainIssueMaps = Lists.newArrayList(); if (widgetCondition.getProjectIds().size() > 0) { SetMeAndDownProjectIds(widgetCondition.getProjectIds(), widgetCondition); registerCompleteIssueMaps = this.widgetMapper.findMyRegisterCompleteIssue(widgetCondition); registerRemainIssueMaps = this.widgetMapper.findMyRegisterRemainIssue(widgetCondition); assigneeCompleteIssueMaps = this.widgetMapper.findMyAssigneeCompleteIssue(widgetCondition); assigneeRemainIssueMaps = this.widgetMapper.findMyAssigneeRemainIssue(widgetCondition); } Map result = new HashMap<>(); Long totalRegisterRemainIssueCount = 0L; // 등록한 이슈 중 잔여 이슈 총 갯수 Long totalAssigneeRemainIssueCount = 0L; // 할당된 이슈 중 잔여 이슈 총 갯수 for (Map project : widgetCondition.getProjects()) { Long projectId = MapUtil.getLong(project, "id"); if (projectId != null) { // Map 에서 등록/담당하는 이슈 갯수를 추출한다. Long registerCompleteIssueCount = this.getMyIssueCount(projectId, registerCompleteIssueMaps); Long registerRemainIssueCount = this.getMyIssueCount(projectId, registerRemainIssueMaps); Long assigneeCompleteIssueCount = this.getMyIssueCount(projectId, assigneeCompleteIssueMaps); Long assigneeRemainIssueCount = this.getMyIssueCount(projectId, assigneeRemainIssueMaps); project.put("registerCompleteIssueCount", registerCompleteIssueCount); project.put("registerRemainIssueCount", registerRemainIssueCount); project.put("totalRegisterIssueCount", (registerCompleteIssueCount + registerRemainIssueCount)); project.put("assigneeCompleteIssueCount", assigneeCompleteIssueCount); project.put("assigneeRemainIssueCount", assigneeRemainIssueCount); project.put("totalAssigneeIssueCount", (assigneeCompleteIssueCount + assigneeRemainIssueCount)); this.statisticsProject(registerCompleteIssueCount, registerRemainIssueCount, project, "registerIssueProgressPercent"); this.statisticsProject(assigneeCompleteIssueCount, assigneeRemainIssueCount, project, "assigneeIssueProgressPercent"); totalRegisterRemainIssueCount += registerRemainIssueCount; totalAssigneeRemainIssueCount += assigneeRemainIssueCount; } } result.put("issues", widgetCondition.getProjects()); result.put("totalRegisterRemainIssueCount", totalRegisterRemainIssueCount); result.put("totalAssigneeRemainIssueCount", totalAssigneeRemainIssueCount); resJsonData.put("myIssueWidget", result); } // Map 에서 등록/담당하는 이슈 갯수를 추출한다. private long getMyIssueCount(Long projectId, List> maps) { long issueCount = 0L; for (Map map : maps) { Long issueProjectId = MapUtil.getLong(map, "projectId"); if (issueProjectId != null) { if (projectId.equals(issueProjectId)) { Long count = MapUtil.getLong(map, "issueCount"); if (count != null) { issueCount = count; } } } } return issueCount; } // 위험 관리 이슈 정보를 조회한다. @Override @Transactional(readOnly = true) public void findRiskIssue(Map resJsonData, WidgetCondition widgetCondition, Pageable pageable) { widgetCondition.setPage(pageable.getPageNumber() * pageable.getPageSize()); widgetCondition.setPageSize(pageable.getPageSize()); //Map countChangeStatusAndAssigneeIssue = new HashMap<>(); //countChangeStatusAndAssigneeIssue.put("changeAssigneeCount", 0L); Map countChangeStatusAndDepartmentIssue = new HashMap<>(); countChangeStatusAndDepartmentIssue.put("changeDepartmentCount", 0L); countChangeStatusAndDepartmentIssue.put("changeIssueStatusCount", 0L); // 0.212 - 0.213 List> riskIssues = Lists.newArrayList(); // 0.244 - 0.248 Long totalCount = 0L; if (widgetCondition.getProjectIds().size() > 0) { SetMeAndDownProjectIds(widgetCondition.getProjectIds(), widgetCondition); //countChangeStatusAndAssigneeIssue = this.widgetMapper.countChangeStatusAndAssigneeIssue(widgetCondition); countChangeStatusAndDepartmentIssue = this.widgetMapper.countChangeStatusAndDepartmentIssue(widgetCondition); riskIssues = this.widgetMapper.findRiskIssue(widgetCondition); totalCount = this.widgetMapper.countRiskIssue(widgetCondition); } // 이슈의 담당자 정보를 가져온다. if (riskIssues.size() > 0) { this.setIssueUsers(riskIssues); } int totalPage = (int) Math.ceil((totalCount - 1) / pageable.getPageSize()) + 1; Map results = new HashMap<>(); //results.put("changeAssigneeCount", MapUtil.getLong(countChangeStatusAndAssigneeIssue, "changeAssigneeCount")); results.put("changeDepartmentCount", MapUtil.getLong(countChangeStatusAndDepartmentIssue, "changeDepartmentCount")); results.put("changeIssueStatusCount", MapUtil.getLong(countChangeStatusAndDepartmentIssue, "changeIssueStatusCount")); results.put("issues", riskIssues); results.put(Constants.REQ_KEY_PAGE_VO, new ResPage(pageable.getPageNumber(), pageable.getPageSize(), totalPage, totalCount)); resJsonData.put("riskIssueWidget", results); } // 이슈의 담당자 정보를 가져온다. private void setIssueUsers(List> riskIssues) { List issueIds = Lists.newArrayList(); for (Map riskIssue : riskIssues) { issueIds.add(MapUtil.getString(riskIssue, "id")); } List> issueUsers = this.issueMapper.findIssueUser(new IssueCondition(issueIds)); Map mapIssueUsers = new HashMap<>(); // 이슈 번호를 키로해서 이슈 담당자 정보를 저장한다. for (Map issueUser : issueUsers) { String issueId = MapUtil.getString(issueUser, "issueId"); issueUser.put("account", CommonUtil.decryptAES128(MapUtil.getString(issueUser, "account"))); // 존재하지 않을 경우 if (mapIssueUsers.get(issueId) == null) { List> users = Lists.newArrayList(); users.add(issueUser); mapIssueUsers.put(issueId, users); } else { // 이미 존재할 경우 List> users = (List>) mapIssueUsers.get(issueId); users.add(issueUser); mapIssueUsers.put(issueId, users); } } for (Map riskIssue : riskIssues) { String issueId = MapUtil.getString(riskIssue, "id"); if (mapIssueUsers.get(issueId) == null) { riskIssue.put("issueUsers", Lists.newArrayList()); } else { riskIssue.put("issueUsers", mapIssueUsers.get(issueId)); } } } // 전체 이슈 처리 현황 @Override @Transactional(readOnly = true) public void findIssueComplete(Map resJsonData, WidgetCondition widgetCondition, String searchPeriod) { // 검색 조건이 기본 설정일 때 - 최근 7일 if (searchPeriod == null) { widgetCondition.setSearchPeriod(DateUtil.LAST_SEVEN_DAYS); } else { widgetCondition.setSearchPeriod(searchPeriod); } // 검색 일자를 구한다. List searchDates = CommonUtil.findSearchPeriod(widgetCondition.getSearchPeriod()); // 날짜가 검색되지 않았으면 오류 if (searchDates.size() < 1) { throw new OwlRuntimeException( this.messageAccessor.getMessage(MsgConstants.WIDGET_SEARCH_DATE_NOT_FOUND)); } // 위젯 검색 조건에 시작일, 종료일을 설정한다. widgetCondition.setSearchStartDate(DateUtil.convertDateToYYYYMMDD(searchDates.get(0))); widgetCondition.setSearchEndDate(DateUtil.convertDateToYYYYMMDD(DateUtil.addDays(searchDates.get(searchDates.size() - 1), 1))); // 이슈 List> dateCounts = Lists.newArrayList(); Long totalIssueCount = 0L; if (widgetCondition.getProjectIds().size() > 0) { SetMeAndDownProjectIds(widgetCondition.getProjectIds(), widgetCondition); dateCounts = this.widgetMapper.findIssueComplete(widgetCondition); totalIssueCount = this.widgetMapper.countTotalIssue(widgetCondition); } Map results = new HashMap<>(); // 전체 이슈 처리 현황을 날짜별로 구분해서 저장한다. this.setIssueCompleteCountList(searchDates, dateCounts, totalIssueCount, results); resJsonData.put("issueCompleteWidget", results); } // 전체 이슈 처리 현황을 날짜별로 구분해서 저장한다. private void setIssueCompleteCountList(List searchDates, List> dateCounts, Long totalIssueCount, Map results) { List> issueCompleteCountList = Lists.newArrayList(); Integer totalCompleteCount = 0; // 일자 별로 기본 값 셋팅 for (Date searchDate : searchDates) { Map result = new HashMap<>(); result.put("modifyDate", DateUtil.convertDateToYYYYMMDD(searchDate)); result.put("issueCount", 0); // 수정일 for (Map dateCount : dateCounts) { String targetDate = MapUtil.getString(dateCount, "modifyDate"); if (DateUtil.convertDateToYYYYMMDD(searchDate).equals(targetDate)) { Integer issueCount = MapUtil.getInteger(dateCount, "issueCount"); totalCompleteCount += issueCount; result.put("issueCount", issueCount); break; } } issueCompleteCountList.add(result); } for (Map issueCompleteCount : issueCompleteCountList) { String modifyDate = MapUtil.getString(issueCompleteCount, "modifyDate"); Date convertModifyDate = DateUtil.convertStrToDate(modifyDate, "yyyy-MM-dd"); issueCompleteCount.put("modifyDate", DateUtil.convertDateToStr(convertModifyDate, "MM.dd")); } results.put("issueCompleteCountList", issueCompleteCountList); results.put("completeCount", totalCompleteCount); results.put("totalIssueCount", totalIssueCount); // 처리율 Double issueCompleteWidget = ((double) totalCompleteCount / (double) totalIssueCount) * 100.0; if (issueCompleteWidget.isNaN()) { issueCompleteWidget = 0.0; } Double dayIssueCompleteAvg = ((double) totalCompleteCount / searchDates.size()); results.put("dayIssueCompleteAvg", dayIssueCompleteAvg); results.put("issueProgressPercent", issueCompleteWidget); } // 상태별 이슈 현황 @Override @Transactional(readOnly = true) public void findByStandIssueStatus(Map resJsonData, WidgetCondition widgetCondition) { List issueStatuses = this.issueStatusService.findByWorkspaceId(widgetCondition.getWorkspaceId()); widgetCondition.setIssueStatuses(issueStatuses); List> issueStatusMaps = Lists.newArrayList(); for (IssueStatus issueStatus : issueStatuses) { Map issueStatusMap = new HashMap<>(); issueStatusMap.put("key", issueStatus.getName()); issueStatusMap.put("color", issueStatus.getColor()); issueStatusMap.put("values", Lists.newArrayList()); issueStatusMaps.add(issueStatusMap); } List> results = Lists.newArrayList(); User user = this.webAppUtil.getLoginUserObject(); UserLevel userLevel = this.userLevelService.getUserLevel(user.getUserLevel().getId()); if (widgetCondition.getProjectIds().size() > 0) { SetMeAndDownProjectIds(widgetCondition.getProjectIds(), widgetCondition); if (this.userWorkspaceService.checkWorkspaceManager(user) || MngPermission.checkMngPermission(userLevel.getPermission(), MngPermission.USER_PERMISSION_MNG_ISSUE)) { results = this.widgetMapper.findByStandIssueStatus(widgetCondition); }else { results = this.widgetMapper.findByStandIssueStatusOfDepartment(widgetCondition); } } for (Map result : results) { for (Map issueStatusMap : issueStatusMaps) { String key = MapUtil.getString(issueStatusMap, "key"); Long value = MapUtil.getLong(result, key); List> values = (List>) issueStatusMap.get("values"); Map map = new HashMap<>(); map.put("x", MapUtil.getString(result, "projectName")); map.put("y", value); values.add(map); } } resJsonData.put("issueStatusWidget", issueStatusMaps); } // 이슈 타입 별 이슈 정보를 조회한다. @Override @Transactional(readOnly = true) public void findByStandIssueType(Map resJsonData, WidgetCondition widgetCondition, Boolean getWidgetCondition) { // 위젯 검색 조건을 얻어야 할 상황일 때 - 화면에서 탭을 눌러 데이터를 재요청했을 때 위젯 검색 조건을 만들고 전체 프로젝트 정보를 리턴한다. Map results = this.makeWidgetConditionAllProject(widgetCondition, getWidgetCondition); User user = this.webAppUtil.getLoginUserObject(); UserLevel userLevel = this.userLevelService.getUserLevel(user.getUserLevel().getId()); if (widgetCondition.getProjectId() != null) { SetMeAndDownProjectIds(widgetCondition.getProjectIds(), widgetCondition); if (widgetCondition.getMeAndDownProjectIds() != null) { for (Long meAndProjectId : widgetCondition.getMeAndDownProjectIds()) { if(meAndProjectId == -1L) { results.replace("projectVos", null); } } } List> issueTypeIssues = Lists.newArrayList(); if (this.userWorkspaceService.checkWorkspaceManager(user) || MngPermission.checkMngPermission(userLevel.getPermission(), MngPermission.USER_PERMISSION_MNG_ISSUE)) { issueTypeIssues = this.widgetMapper.findByStandIssueType(widgetCondition); } else { issueTypeIssues = this.widgetMapper.findByStandIssueTypeOfDepartment(widgetCondition); } // 이슈 정보 results.put("issues", issueTypeIssues); } else { results.put("issues", Lists.newArrayList()); } resJsonData.put("issueTypeWidget", results); } // 위젯 검색 조건을 만들고 전체 프로젝트 정보를 리턴한다. private Map makeWidgetConditionAllProject(WidgetCondition widgetCondition, boolean getWidgetCondition) { Map results = new HashMap<>(); SetMeAndDownProjectIds(widgetCondition.getProjectIds(), widgetCondition); // 위젯 검색 조건을 얻어야 할 상황일 때 - 화면에서 탭을 눌러 데이터를 재요청했을 때 if (getWidgetCondition) { WidgetCondition condition = this.makeWidgetCondition(); widgetCondition.setProjectIds(condition.getProjectIds()); } // 전체 위젯 검색 으로 들어왔을 경우 - findAllWidget() if (widgetCondition.getProjectId() == null && (widgetCondition.getProjectIds().size() > 0) && !getWidgetCondition) { widgetCondition.setProjectId(widgetCondition.getProjectIds().get(0)); } if (widgetCondition.getProjectId() != null) { List projects = this.projectService.findAll(widgetCondition.getProjectIds()); // 전체 프로젝트 Project project = this.projectService.findOne(widgetCondition.getProjectId()); results.put("projectVos", ConvertUtil.convertObjectsToClasses(projects, ProjectVo.class)); if (project != null) { results.put("projectName", project.getName()); } else { results.put("projectName", ""); } } else { results.put("projectVos", Lists.newArrayList()); results.put("projectName", ""); } return results; } //중요도 별 이슈 현황 정보를 조회한다. @Override @Transactional(readOnly = true) public void findSeverityIssueWidget(Map resJsonData, WidgetCondition widgetCondition, Map parameter, Pageable pageable) { widgetCondition.setPage(pageable.getPageNumber() * pageable.getPageSize()); widgetCondition.setPageSize(pageable.getPageSize()); Long severityId = 1L; Long projectId = null; if (parameter != null) { severityId = MapUtil.getLong(parameter,"severityId"); projectId = MapUtil.getLong(parameter,"projectId"); } // 검색조건 기본 설정 값 - 중요도: 심각 if (severityId != null) { widgetCondition.setSeverityId(severityId); } if (projectId != null) { widgetCondition.setProjectIds(projectId); widgetCondition.setProjectId(projectId); } //중요도 별 이슈 List> severityCounts = Lists.newArrayList(); List> severityIssues = Lists.newArrayList(); Long totalCount = 0L; widgetCondition.setLoginUserId(this.webAppUtil.getLoginId()); widgetCondition.setWorkspaceId(this.userService.getUser(this.webAppUtil.getLoginId()).getLastWorkspaceId()); User user = this.webAppUtil.getLoginUserObject(); UserLevel userLevel = this.userLevelService.getUserLevel(user.getUserLevel().getId()); if (widgetCondition.getProjectIds().size() > 0) { SetMeAndDownProjectIds(widgetCondition.getProjectIds(), widgetCondition); if (this.userWorkspaceService.checkWorkspaceManager(user) || MngPermission.checkMngPermission(userLevel.getPermission(), MngPermission.USER_PERMISSION_MNG_ISSUE)) { severityCounts = this.widgetMapper.countSeverityIssue(widgetCondition); severityIssues = this.widgetMapper.findSeverityIssues(widgetCondition); totalCount = this.widgetMapper.countSearchIssue(widgetCondition); }else { SetMyDepartmentId(widgetCondition); severityCounts = this.widgetMapper.countSeverityIssueByDepartment(widgetCondition); severityIssues = this.widgetMapper.findSeverityIssuesByDepartment(widgetCondition); totalCount = this.widgetMapper.countSearchIssueByDepartment(widgetCondition); } } Long criticalIssueCount = 0L, majorIssueCount = 0L, minorIssueCount = 0L, trivialIssueCount = 0L; for (Map severityCount : severityCounts) { Long criticalCount = MapUtil.getLong(severityCount, "critical"); // 중요도: 심각 갯수 Long majorCount = MapUtil.getLong(severityCount, "major"); // 중요도: 높음 갯수 Long minorCount = MapUtil.getLong(severityCount, "minor"); // 중요도: 보통 갯수 Long trivialCount = MapUtil.getLong(severityCount, "trivial"); // 중요도: 낮음 갯수 if (criticalCount != null) { criticalIssueCount += criticalCount; } if (majorCount != null) { majorIssueCount += majorCount; } if (minorCount != null) { minorIssueCount += minorCount; } if (trivialCount != null) { trivialIssueCount += trivialCount; } } int totalPage = (int) Math.ceil((totalCount - 1) / pageable.getPageSize()) + 1; Map results = new HashMap<>(); results.put("criticalIssueCount", criticalIssueCount); results.put("majorIssueCount", majorIssueCount); results.put("minorIssueCount", minorIssueCount); results.put("trivialIssueCount", trivialIssueCount); results.put(Constants.REQ_KEY_PAGE_VO, new ResPage(pageable.getPageNumber(), pageable.getPageSize(), totalPage, totalCount)); results.put("issues", severityIssues); resJsonData.put("severityIssueWidget", results); } // 엑셀 다운로드 @Override @Transactional public ModelAndView downloadExcel(HttpServletRequest request, Model model) { // 사용 공간에서 로그인한 사용자가 비활성인지 확인하고 비활성일 경우 엑셀 다운로드를 금지한다. ModelAndView modelAndView = this.workspaceService.checkUseExcelDownload(model); if (modelAndView != null) { return modelAndView; } Map params = new HashMap<>(); Enumeration e = request.getParameterNames(); while (e.hasMoreElements()) { String name = (String) e.nextElement(); if (!org.springframework.util.StringUtils.isEmpty(request.getParameter(name))) { params.put(name, request.getParameter(name)); } } // 다운로드 위젯 유형에 오류가 있을 경우 다운로드된다. - 기본적으로 Exception 발생할 때 사용될 엑셀 형식을 저장한다. ExportExcelVo excelInfo = this.excelConditionCheck.makeEmptyDownloadExcel(); String downloadWidgetType = MapUtil.getString(params, "downloadWidgetType"); if (downloadWidgetType == null) { downloadWidgetType = ""; excelInfo.setFileName(this.messageAccessor.message("common.typeErrorDownloadWidget")); // 다운로드 위젯 유형 오류 } switch (downloadWidgetType) { case "PROJECT_PROGRESS": // 진행중인 프로젝트 현황 정보를 엑셀로 다운로드 한다. excelInfo = this.downloadExcelProjectProgress(); break; case "MY_ASSIGNEE_ISSUE": // 나에게 할당된 이슈 정보를 엑셀로 다운로드 한다. excelInfo = this.downloadExcelMyAssigneeIssue(); break; case "RISK_ISSUE": // 위험 관리 정보를 엑셀로 다운로드 한다. excelInfo = this.downloadExcelRiskIssue(); break; case "REGISTER_ISSUE": // 내가 등록한 이슈 정보를 엑셀로 다운로드 한다. excelInfo = this.downloadExcelRegisterIssue(); break; case "DELAY_ISSUE": // 지연 중인 이슈 정보를 엑셀로 다운로드 한다. excelInfo = this.downloadExcelDelayIssue(); break; case "MEMBER_PROGRESS": // 프로젝트 별 멤버 진행률 정보를 엑셀로 다운로드 한다. excelInfo = this.downloadExcelMemberProgress(MapUtil.getLong(params, "projectId")); break; case "MY_ISSUE": // 나의 이슈 정보를 엑셀로 다운로드 한다. excelInfo = this.downloadExcelMyIssue(); break; case "SEVERITY_ISSUE": // 중요도 별 이슈 정보를 엑셀로 다운로드 한다. excelInfo = this.downloadExcelSeverityIssue(MapUtil.getLong(params, "severityId")); break; } model.addAttribute(Constants.EXCEL, excelInfo); return new ModelAndView(this.excelView); } // 진행중인 프로젝트 현황 정보를 엑셀로 다운로드 한다. private ExportExcelVo downloadExcelProjectProgress() { Map resJsonData = new HashMap<>(); // 진행 중인 프로젝트 현황 this.findProjectProgress(resJsonData, this.makeWidgetCondition()); Map projectProgressWidget = (Map) MapUtil.getObject(resJsonData, "projectProgressWidget"); List> projects = (List) MapUtil.getObject(projectProgressWidget, "projects"); for (Map project : projects) { // 매니저 정보 변환 project.put("manager", MapUtil.getString(project, "managerName") + "(" + MapUtil.getString(project, "managerEmail") + ")"); // 기간 정보 변환 project.put("period", MapUtil.getString(project, "startDate") + " - " + MapUtil.getString(project, "endDate")); // 진행률 자리수 제한 Double projectProgressPercent = MapUtil.getDouble(project, "projectProgressPercent"); project.put("projectProgressPercent", String.format("%.1f", projectProgressPercent) + "%"); // 이슈 키운트 정보 변환 int closeCount = MapUtil.getInteger(project, "close"); int remainCount = MapUtil.getInteger(project, "remain"); try { int totalCount = closeCount + remainCount; project.put("issueCount", CommonUtil.getDecimalFormat(MapUtil.getInteger(project, "close")) + " / " + CommonUtil.getDecimalFormat(totalCount)); } catch (Exception e) { log.debug("downloadExcelProjectProgress Null Exception"); } } ExportExcelVo excelInfo = new ExportExcelVo(); excelInfo.setFileName(this.messageAccessor.message("common.inProgressProjectStatus")); // 진행 중인 프로젝트 현황 excelInfo.setDatas((List) MapUtil.getObject(projectProgressWidget, "projects")); excelInfo.addAttrInfos(new ExportExcelAttrVo("name", this.messageAccessor.message("common.project"), 40, ExportExcelAttrVo.ALIGN_LEFT)); // 프로젝트 excelInfo.addAttrInfos(new ExportExcelAttrVo("manager", this.messageAccessor.message("common.admin"), 20, ExportExcelAttrVo.ALIGN_CENTER)); // 관리자 excelInfo.addAttrInfos(new ExportExcelAttrVo("projectProgressPercent", this.messageAccessor.message("common.progressPercent"), 6, ExportExcelAttrVo.ALIGN_CENTER)); //진행률 excelInfo.addAttrInfos(new ExportExcelAttrVo("issueCount", this.messageAccessor.message("common.issue"), 6, ExportExcelAttrVo.ALIGN_CENTER)); // 이슈 excelInfo.addAttrInfos(new ExportExcelAttrVo("teamCount", this.messageAccessor.message("common.teamMember"), 6, ExportExcelAttrVo.ALIGN_CENTER)); // 팀원 excelInfo.addAttrInfos(new ExportExcelAttrVo("period", this.messageAccessor.message("common.period"), 15, ExportExcelAttrVo.ALIGN_CENTER)); // 기간 return excelInfo; } // 나에게 할당된 이슈 정보를 엑셀로 다운로드 한다. private ExportExcelVo downloadExcelMyAssigneeIssue() { WidgetCondition widgetCondition = this.makeWidgetCondition(); /*widgetCondition.setLoginUserId(this.webAppUtil.getLoginId()); widgetCondition.setWorkspaceId(this.userService.getUser(this.webAppUtil.getLoginId()).getLastWorkspaceId()); User user = this.webAppUtil.getLoginUserObject();*/ // 나에게 할당된 이슈 List> assigneeIssues = Lists.newArrayList(); if (widgetCondition.getProjectIds().size() > 0) { //if (this.userWorkspaceService.checkWorkspaceManager(user)) { assigneeIssues = this.widgetMapper.findMyAssigneeIssue(this.makeWidgetCondition()); /*} else { assigneeIssues = this.widgetMapper.findMyAssigneeIssueByDepartment(this.makeWidgetCondition()); }*/ } ExportExcelVo excelInfo = new ExportExcelVo(); excelInfo.setFileName(this.messageAccessor.message("common.assignedToMeIssue")); // 나에게 할당된 이슈 excelInfo.setDatas(assigneeIssues); excelInfo.addAttrInfos(new ExportExcelAttrVo("issueKey", this.messageAccessor.message("common.issueKey"), 6, ExportExcelAttrVo.ALIGN_CENTER)); // 이슈 번호 excelInfo.addAttrInfos(new ExportExcelAttrVo("registerDate", this.messageAccessor.message("common.registerDate"), 8, ExportExcelAttrVo.ALIGN_CENTER)); // 등록일 excelInfo.addAttrInfos(new ExportExcelAttrVo("projectName", this.messageAccessor.message("common.project"), 15, ExportExcelAttrVo.ALIGN_LEFT)); // 프로젝트 excelInfo.addAttrInfos(new ExportExcelAttrVo("title", this.messageAccessor.message("common.issueTitle"), 40, ExportExcelAttrVo.ALIGN_LEFT)); // 이슈 excelInfo.addAttrInfos(new ExportExcelAttrVo("issueStatusName", this.messageAccessor.message("common.status"), 6, ExportExcelAttrVo.ALIGN_CENTER)); // 상태 excelInfo.addAttrInfos(new ExportExcelAttrVo("completeDate", this.messageAccessor.message("common.endDate"), 15, ExportExcelAttrVo.ALIGN_CENTER)); // 종료일 return excelInfo; } // 위험 관리 이슈 정보를 엑셀로 다운로드 한다. private ExportExcelVo downloadExcelRiskIssue() { WidgetCondition widgetCondition = this.makeWidgetCondition(); // 위험 관리 이슈 List> riskIssues = Lists.newArrayList(); if (widgetCondition.getProjectIds().size() > 0) { riskIssues = this.widgetMapper.findRiskIssue(this.makeWidgetCondition()); } // 이슈의 담당자 정보를 가져온다. this.setIssueUsers(riskIssues); for (Map risk : riskIssues) { String riskType = ""; String changeAssigneeType = MapUtil.getString(risk, "changeAssigneeType"); String changeIssueStatusType = MapUtil.getString(risk, "changeIssueStatusType"); if (changeAssigneeType != null) { if (changeAssigneeType.equals("1")) { riskType = this.messageAccessor.message("common.reversalAssigneeTeamUpdate"); // 빈번한 담당부서 변경 } } if (changeIssueStatusType != null) { if (changeIssueStatusType.equals("1")) { riskType = this.messageAccessor.message("common.reversalStatusUpdate"); // 번복되는 상태 변경 } } if (changeAssigneeType != null && changeIssueStatusType != null) { if (changeAssigneeType.equals("1") && changeIssueStatusType.equals("1")) { riskType = this.messageAccessor.message("common.reversalAssigneeTeamUpdate") + '\n' + this.messageAccessor.message("common.reversalStatusUpdate"); // 빈번한 담당부서 변경, 번복되는 상태 변경 } } risk.put("riskType", riskType); List> issueUsers = (List>) MapUtil.getObject(risk, "issueUsers"); StringBuilder stringBuilder = new StringBuilder(); for (Map issueUser : issueUsers) { if (!StringUtils.isEmpty(stringBuilder.toString())) { stringBuilder.append("\n"); } stringBuilder.append(MapUtil.getString(issueUser, "name")); stringBuilder.append("("); stringBuilder.append(MapUtil.getString(issueUser, "account")); stringBuilder.append(") "); } risk.put("issueUsers", stringBuilder.toString()); } ExportExcelVo excelInfo = new ExportExcelVo(); excelInfo.setFileName(this.messageAccessor.message("common.managementRisk")); // 위험 관리 excelInfo.setDatas(riskIssues); excelInfo.addAttrInfos(new ExportExcelAttrVo("issueKey", this.messageAccessor.message("common.issueKey"), 6, ExportExcelAttrVo.ALIGN_CENTER)); // 이슈 번호 //excelInfo.addAttrInfos(new ExportExcelAttrVo("riskType", this.messageAccessor.message("common.division"), 15, ExportExcelAttrVo.ALIGN_CENTER)); // 구분 excelInfo.addAttrInfos(new ExportExcelAttrVo("projectName", this.messageAccessor.message("common.project"), 15, ExportExcelAttrVo.ALIGN_LEFT)); // 프로젝트 excelInfo.addAttrInfos(new ExportExcelAttrVo("title", this.messageAccessor.message("common.issueTitle"), 40, ExportExcelAttrVo.ALIGN_LEFT)); // 이슈 excelInfo.addAttrInfos(new ExportExcelAttrVo("issueStatusName", this.messageAccessor.message("common.status"), 6, ExportExcelAttrVo.ALIGN_CENTER)); // 상태 //excelInfo.addAttrInfos(new ExportExcelAttrVo("issueUsers", this.messageAccessor.message("common.assignee"), 20, ExportExcelAttrVo.ALIGN_CENTER)); // 담당자 return excelInfo; } // 내가 등록한 이슈 정보를 엑셀로 다운로드 한다. private ExportExcelVo downloadExcelRegisterIssue() { WidgetCondition widgetCondition = this.makeWidgetCondition(); List> registerIssues = Lists.newArrayList(); Long totalCount = 0L; if (widgetCondition.getProjectIds().size() > 0) { totalCount = this.widgetMapper.countRegisterIssue(widgetCondition); } widgetCondition.setPage(0); widgetCondition.setPageSize(totalCount.intValue()); // 내가 등록한 이슈 if (widgetCondition.getProjectIds().size() > 0) { SetMeAndDownProjectIds(widgetCondition.getProjectIds(), widgetCondition); registerIssues = this.widgetMapper.findRegisterIssue(widgetCondition); } // 기간 정보를 셋팅한다. this.setPeriod(registerIssues); ExportExcelVo excelInfo = new ExportExcelVo(); excelInfo.setFileName(this.messageAccessor.message("common.registeredByMeIssue")); // 내가 등록한 이슈 현황 excelInfo.setDatas(registerIssues); excelInfo.addAttrInfos(new ExportExcelAttrVo("issueKey", this.messageAccessor.message("common.issueKey"), 6, ExportExcelAttrVo.ALIGN_CENTER)); // 이슈 번호 excelInfo.addAttrInfos(new ExportExcelAttrVo("issueStatusName", this.messageAccessor.message("common.status"), 6, ExportExcelAttrVo.ALIGN_CENTER)); // 상태 excelInfo.addAttrInfos(new ExportExcelAttrVo("projectName", this.messageAccessor.message("common.project"), 15, ExportExcelAttrVo.ALIGN_LEFT)); // 프로젝트 excelInfo.addAttrInfos(new ExportExcelAttrVo("title", this.messageAccessor.message("common.issueTitle"), 40, ExportExcelAttrVo.ALIGN_LEFT)); // 이슈 excelInfo.addAttrInfos(new ExportExcelAttrVo("period", this.messageAccessor.message("common.period"), 15, ExportExcelAttrVo.ALIGN_CENTER)); // 기간 return excelInfo; } // 기간 정보를 셋팅한다. private void setPeriod(List> issues) { for (Map issue : issues) { if (MapUtil.getString(issue, "startDate") == null) { issue.put("period", " - "); } else { issue.put("period", MapUtil.getString(issue, "startDate") + " - " + MapUtil.getString(issue, "completeDate")); } } } // 지연 중인 이슈 정보를 엑셀로 다운로드 한다. private ExportExcelVo downloadExcelDelayIssue() { WidgetCondition widgetCondition = this.makeWidgetCondition(); List> delayIssues = Lists.newArrayList(); Long totalCount = 0L; if (widgetCondition.getProjectIds().size() > 0) { totalCount = this.widgetMapper.countDelayIssue(widgetCondition); } widgetCondition.setPage(0); widgetCondition.setPageSize(totalCount.intValue()); if (widgetCondition.getProjectIds().size() > 0) { SetMeAndDownProjectIds(widgetCondition.getProjectIds(), widgetCondition); delayIssues = this.widgetMapper.findDelayIssue(widgetCondition); } // 오늘 날짜를 기준으로 지연일을 구한다. this.setDelayDay(delayIssues); // 기간 정보를 셋팅한다. this.setPeriod(delayIssues); ExportExcelVo excelInfo = new ExportExcelVo(); excelInfo.setFileName(this.messageAccessor.message("common.delayingIssue")); // 지연 중인 이슈 excelInfo.setDatas(delayIssues); excelInfo.addAttrInfos(new ExportExcelAttrVo("issueKey", this.messageAccessor.message("common.issueKey"), 6, ExportExcelAttrVo.ALIGN_CENTER)); // 이슈 번호 excelInfo.addAttrInfos(new ExportExcelAttrVo("delayDay", this.messageAccessor.message("common.delayDate"), 10, ExportExcelAttrVo.ALIGN_CENTER)); // 지연일 excelInfo.addAttrInfos(new ExportExcelAttrVo("projectName", this.messageAccessor.message("common.project"), 15, ExportExcelAttrVo.ALIGN_LEFT)); // 프로젝트 excelInfo.addAttrInfos(new ExportExcelAttrVo("title", this.messageAccessor.message("common.issueTitle"), 40, ExportExcelAttrVo.ALIGN_LEFT)); // 이슈 excelInfo.addAttrInfos(new ExportExcelAttrVo("issueStatusName", this.messageAccessor.message("common.status"), 6, ExportExcelAttrVo.ALIGN_CENTER)); // 상태 excelInfo.addAttrInfos(new ExportExcelAttrVo("period", this.messageAccessor.message("common.period"), 20, ExportExcelAttrVo.ALIGN_CENTER)); // 기간 return excelInfo; } // 프로젝트별 멤버 진행률 정보를 엑셀로 다운로드 한다. private ExportExcelVo downloadExcelMemberProgress(Long projectId) { Map resJsonData = new HashMap<>(); WidgetCondition widgetCondition = this.makeWidgetCondition(); widgetCondition.setProjectIds(Lists.newArrayList(projectId)); // 프로젝트 별 멤버 진행률 정보를 조회한다. this.findMemberProgress(resJsonData, widgetCondition, false); Map memberProgressWidget = (Map) MapUtil.getObject(resJsonData, "memberProgressWidget"); List> members = (List>) MapUtil.getObject(memberProgressWidget, "members"); for (Map member : members) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(MapUtil.getString(member, "name")); stringBuilder.append("("); stringBuilder.append(MapUtil.getString(member, "account")); stringBuilder.append(") "); member.put("byName", stringBuilder.toString()); // 진행률 자리수 제한 Double projectProgressPercent = MapUtil.getDouble(member, "projectProgressPercent"); member.put("projectProgressPercent", String.format("%.1f", projectProgressPercent) + "%"); int completeCount = MapUtil.getInteger(member, "completeCount"); int remainCount = MapUtil.getInteger(member, "remainCount"); int totalCount = completeCount + remainCount; // 담당 이슈 카운트 member.put("issueCount", CommonUtil.getDecimalFormat(completeCount) + " / " + CommonUtil.getDecimalFormat(totalCount)); } ExportExcelVo excelInfo = new ExportExcelVo(); excelInfo.setFileName(this.messageAccessor.message("common.progressByMember")); // 멤버별 진행률 excelInfo.setDatas(members); //excelInfo.addAttrInfos(new ExportExcelAttrVo("byName", this.messageAccessor.message("common.teamMember"), 15, ExportExcelAttrVo.ALIGN_LEFT)); // 팀원 excelInfo.addAttrInfos(new ExportExcelAttrVo("projectName", this.messageAccessor.message("common.project"), 15, ExportExcelAttrVo.ALIGN_LEFT)); // 프로젝트 excelInfo.addAttrInfos(new ExportExcelAttrVo("departmentName", this.messageAccessor.message("common.teamDepartment"), 15, ExportExcelAttrVo.ALIGN_LEFT)); // 담당부서 excelInfo.addAttrInfos(new ExportExcelAttrVo("projectProgressPercent", this.messageAccessor.message("common.progressPercent"), 6, ExportExcelAttrVo.ALIGN_LEFT)); // 진행률 excelInfo.addAttrInfos(new ExportExcelAttrVo("issueCount", this.messageAccessor.message("common.assignedIssue"), 10, ExportExcelAttrVo.ALIGN_CENTER)); // 담당 이슈 excelInfo.addAttrInfos(new ExportExcelAttrVo("delayCount", this.messageAccessor.message("common.delaying"), 6, ExportExcelAttrVo.ALIGN_CENTER)); // 지연중 return excelInfo; } // 나의 이슈 정보를 엑셀로 다운로드 한다. private ExportExcelVo downloadExcelMyIssue() { Map resJsonData = new HashMap<>(); // 나의 이슈 현황 정보를 조회한다. this.findMyIssueDetail(resJsonData, this.makeWidgetCondition()); Map myIssueWidget = (Map) MapUtil.getObject(resJsonData, "myIssueWidget"); List> issues = (List>) MapUtil.getObject(myIssueWidget, "issues"); List> newIssues = Lists.newArrayList(); for (Map issue : issues) { Map registerMaps = new HashMap<>(); Map assigneeMaps = new HashMap<>(); registerMaps.put("name", MapUtil.getString(issue, "name")); registerMaps.put("division", this.messageAccessor.message("common.registration")); // 등록 registerMaps.put("totalRegisterIssueCount", CommonUtil.getDecimalFormat(MapUtil.getInteger(issue, "totalRegisterIssueCount"))); registerMaps.put("registerCompleteIssueCount", CommonUtil.getDecimalFormat(MapUtil.getInteger(issue, "registerCompleteIssueCount"))); Double registerIssueProgressPercent = MapUtil.getDouble(issue, "registerIssueProgressPercent"); registerMaps.put("registerIssueProgressPercent", String.format("%.1f", registerIssueProgressPercent) + "%"); registerMaps.put("registerRemainIssueCount", CommonUtil.getDecimalFormat(MapUtil.getInteger(issue, "registerRemainIssueCount"))); assigneeMaps.put("division", this.messageAccessor.message("common.assigned")); // 담당 assigneeMaps.put("totalRegisterIssueCount", CommonUtil.getDecimalFormat(MapUtil.getInteger(issue, "totalAssigneeIssueCount"))); assigneeMaps.put("registerCompleteIssueCount", CommonUtil.getDecimalFormat(MapUtil.getInteger(issue, "assigneeCompleteIssueCount"))); Double assigneeIssueProgressPercent = MapUtil.getDouble(issue, "assigneeIssueProgressPercent"); assigneeMaps.put("registerIssueProgressPercent", String.format("%.1f", assigneeIssueProgressPercent) + "%"); assigneeMaps.put("registerRemainIssueCount", CommonUtil.getDecimalFormat(MapUtil.getInteger(issue, "assigneeRemainIssueCount"))); newIssues.add(registerMaps); newIssues.add(assigneeMaps); } ExportExcelVo excelInfo = new ExportExcelVo(); excelInfo.setFileName(this.messageAccessor.message("common.myIssueStatus")); // 나의 이슈 현황 excelInfo.setDatas(newIssues); excelInfo.addAttrInfos(new ExportExcelAttrVo("name", this.messageAccessor.message("common.project"), 15, ExportExcelAttrVo.ALIGN_CENTER, 1)); // 프로젝트 excelInfo.addAttrInfos(new ExportExcelAttrVo("division", this.messageAccessor.message("common.division"), 6, ExportExcelAttrVo.ALIGN_CENTER)); // 구분 excelInfo.addAttrInfos(new ExportExcelAttrVo("totalRegisterIssueCount", this.messageAccessor.message("common.issue"), 10, ExportExcelAttrVo.ALIGN_CENTER)); // 이슈 excelInfo.addAttrInfos(new ExportExcelAttrVo("registerCompleteIssueCount", this.messageAccessor.message("common.complete"), 6, ExportExcelAttrVo.ALIGN_CENTER)); // 완료 excelInfo.addAttrInfos(new ExportExcelAttrVo("registerIssueProgressPercent", this.messageAccessor.message("common.progressPercent"), 6, ExportExcelAttrVo.ALIGN_CENTER)); // 진행률 excelInfo.addAttrInfos(new ExportExcelAttrVo("registerRemainIssueCount", this.messageAccessor.message("common.remainIssue"), 6, ExportExcelAttrVo.ALIGN_CENTER)); // 잔여 이슈 return excelInfo; } // 중요도 별 이슈 정보를 엑셀로 다운로드 한다. private ExportExcelVo downloadExcelSeverityIssue(Long severityId) { WidgetCondition widgetCondition = this.makeWidgetCondition(); if (widgetCondition.getSeverityId() == null) { widgetCondition.setSeverityId(severityId); } List> severityIssue = Lists.newArrayList(); if (widgetCondition.getProjectIds().size() > 0) { severityIssue = this.widgetMapper.findSeverityIssues(widgetCondition); } //기간 정보 셋팅 this.setPeriod(severityIssue); ExportExcelVo excelInfo = new ExportExcelVo(); excelInfo.setFileName(this.messageAccessor.message("common.severityIssue")); // 중요도 별 이슈현황 excelInfo.setDatas(severityIssue); excelInfo.addAttrInfos(new ExportExcelAttrVo("issueKey", this.messageAccessor.message("common.issueKey"), 8, ExportExcelAttrVo.ALIGN_CENTER)); //이슈 번호 excelInfo.addAttrInfos(new ExportExcelAttrVo("severityName", this.messageAccessor.message("common.importance"), 6, ExportExcelAttrVo.ALIGN_CENTER)); // 중요도 excelInfo.addAttrInfos(new ExportExcelAttrVo("projectName", this.messageAccessor.message("common.project"), 15, ExportExcelAttrVo.ALIGN_LEFT)); // 프로젝트 excelInfo.addAttrInfos(new ExportExcelAttrVo("title", this.messageAccessor.message("common.issueTitle"), 40, ExportExcelAttrVo.ALIGN_CENTER)); // 이슈제목 excelInfo.addAttrInfos(new ExportExcelAttrVo("issueStatusName", this.messageAccessor.message("common.status"), 6, ExportExcelAttrVo.ALIGN_CENTER)); //이슈 상태 excelInfo.addAttrInfos(new ExportExcelAttrVo("period", this.messageAccessor.message("common.period"), 15, ExportExcelAttrVo.ALIGN_CENTER)); // 기간 return excelInfo; } }