OWL ITS + 탐지시스템(인터넷 진흥원)
src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java
@@ -1,7 +1,6 @@
package kr.wisestone.owl.service.impl;
import com.google.common.collect.Lists;
import com.sun.org.apache.bcel.internal.generic.NEW;
import kr.wisestone.owl.common.ExcelConditionCheck;
import kr.wisestone.owl.common.IssueCustomFieldValueFormComparator;
import kr.wisestone.owl.config.CommonConfiguration;
@@ -211,23 +210,16 @@
        Workflow workflow = issueType.getWorkflow();
        // 이슈 상태가 지정되어 있지 않을 경우 초기값으로 지정
        if (issueApiForm.getIssueStatusId() == null) {
            List<IssueStatusVo> issueStatusVos = issueStatusService.findByWorkflowId(workflow.getId());
            IssueStatusVo issueStatusVo = issueStatusVos.get(0);
            issueApiForm.setIssueStatusId(issueStatusVo.getId());
        }
        // 워크플로우 상태에 따른 담당부서 가져오기
        if (issueApiForm.getIssueStatusId() != null) {
            WorkflowDepartmentCondition workflowDepartmentCondition = new WorkflowDepartmentCondition();
            workflowDepartmentCondition.setIssueStatusId(issueApiForm.getIssueStatusId());
            workflowDepartmentCondition.setWorkflowId(workflow.getId());
            List<WorkflowDepartmentVo> workflowDepartmentVos = this.workflowDepartmentService.find(workflowDepartmentCondition);
            for (WorkflowDepartmentVo workflowDepartmentVo : workflowDepartmentVos) {
                issueForm.addDepartmentId(workflowDepartmentVo.getDepartmentVo().getId());
        if (issueApiForm.getApiType().equals(IssueApiForm.ApiType.add)) {
            // 이슈 상태가 지정되어 있지 않을 경우 워크플로우 대기 상태 값으로 지정
            List<Long> departmentIds = this.workflowDepartmentService.findFirstDepartmentIds(workflow);
            if (departmentIds != null && departmentIds.size() > 0) {
                for (Long departmentId : departmentIds) {
                    issueForm.addDepartmentId(departmentId);
                }
            }
        } else if (issueApiForm.getIssueStatusId() == null){
            throw new OwlRuntimeException(this.messageAccessor.getMessage(MsgConstants.API_ISSUE_STATUS_NOT_EXIST));
        }
        // 프로젝트 입력
@@ -257,15 +249,24 @@
            // 상위일감에 사용할 중복값 설정
            List<CustomFieldApiOverlap> customFieldApiOverlaps = this.customFieldApiOverlapService.find(user.getId(), issueApiForm.getIssueTypeId());
            if (customFieldApiOverlaps == null || customFieldApiOverlaps.size() == 0){
                throw new OwlRuntimeException(this.messageAccessor.getMessage(MsgConstants.API_OVERLAP_SETTING_NOT_EXIST));
            }
            for(int i=0; i < customFieldApiOverlaps.size() ; i++ ){
                CustomFieldApiOverlap customFieldApiOverlap = customFieldApiOverlaps.get(i);
                issueApiForm.addUseIssueCustomFieldId(customFieldApiOverlap.getCustomField().getId());
            }
            List<IssueVo> issueVos = this.findIssue(issueApiForm, customFieldApiOverlaps, user.getId());
            int size = issueVos.size();
            // 중복된 이슈검색
            List<Issue> issues = this.findIssue(issueApiForm, customFieldApiOverlaps, user.getId());
            int size = issues.size();
            if (size > 0) {
                issueForm.setParentIssueId(issueVos.get(0).getId());
                Issue targetIssue = issues.get(0);
                if (targetIssue.getParentIssue() != null) {
                    issueForm.setParentIssueId(targetIssue.getParentIssue().getId());
                } else {
                    issueForm.setParentIssueId(targetIssue.getId());
                }
            }
            issueForm.setIsApi(Issue.IS_API_YES);
@@ -326,9 +327,9 @@
    }
    // 중복된 상위 이슈 검색
    private List<IssueVo> findIssue(IssueApiForm issueApiform, List<CustomFieldApiOverlap> customFieldApiOverlaps, Long userId) {
    private List<Issue> findIssue(IssueApiForm issueApiform, List<CustomFieldApiOverlap> customFieldApiOverlaps, Long userId) {
        List<IssueCustomFieldValueForm> issueCustomFieldValueForms = issueApiform.getIssueCustomFieldValues();
        List<IssueVo> resultIssueVos = Lists.newArrayList();
        List<Issue> resultIssueVos = Lists.newArrayList();
        String comma = ",";
        if (issueCustomFieldValueForms.size() > 0) {
@@ -352,10 +353,11 @@
            IssueCustomFieldValueCondition issueCustomFieldValueCondition = new IssueCustomFieldValueCondition();
            issueCustomFieldValueCondition.setUseValue(concatUseValue);
            issueCustomFieldValueCondition.setIssueTypeId(issueApiform.getIssueTypeId());
            List<Map<String, Object>> results = this.issueMapper.findByCustomFieldValue(issueCustomFieldValueCondition);
            if (results != null && results.size() > 0) {
                for (Map<String, Object> result : results) {
                    resultIssueVos.add(ConvertUtil.convertMapToClass(result, IssueVo.class));
                    resultIssueVos.add(this.getIssue(MapUtil.getLong(result, "id")));
                }
            }
        }
@@ -718,11 +720,11 @@
    public List<IssueVo> findIssue(Map<String, Object> resJsonData, IssueCondition issueCondition, Pageable pageable) {
        //  검색 조건을 만든다
        /*if (!this.makeIssueSearchCondition(issueCondition, Lists.newArrayList("01", "02", "03"), pageable)) {
        if (!this.makeIssueSearchCondition(issueCondition, Lists.newArrayList("01", "02", "03"), pageable)) {
            //  이슈 목록을 찾지 못할 경우 기본 정보로 리턴한다.
            this.notFoundIssueList(resJsonData, pageable);
            return Lists.newArrayList();
        }*/
        }
        Set<String> issueIds = new HashSet<>(); //  사용자 정의 필드 검색시 나오는 이슈 아이디 저장 컬렉션
@@ -771,12 +773,19 @@
        int totalPage = (int) Math.ceil((totalCount - 1) / pageable.getPageSize()) + 1;
        //  이슈 아이디 초기화
        issueCondition.setIsApi(issueCondition.getIsApi());
        issueCondition.setIssueIds(Lists.newArrayList());
        //  Map 에 있는 데이터를 IssueVo 데이터로 변환한다.
        this.setMapToIssueVo(results, issueVos, issueCondition, user);
        this.setCountDownIssues(results, issueVos);
        if (issueCondition.getTree()) {
            this.setDownIssues(user, issueVos);
            this.setRelationIssues(issueVos);
        }
        this.setCountDownIssues(issueVos);
        this.SetWorkflowDepartment(issueVos); //워크플로우에 설정한 담당부서 가져오기
        resJsonData.put(Constants.RES_KEY_CONTENTS, issueVos);
@@ -788,11 +797,54 @@
        return issueVos;
    }
    // 하위 이슈 세팅(재귀)
    private void setDownIssues(User user, List<IssueVo> issueVos) {
        for(IssueVo issueVo : issueVos) {
            List<Issue> downIssues = this.issueRepository.findByParentIssueId(issueVo.getId());
            List<IssueVo> downIssueVos = Lists.newArrayList();
            IssueCondition issueCondition = new IssueCondition();
            issueCondition.addIssueIds(String.valueOf(issueVo.getId()));
            for(Issue downIssue : downIssues){
                IssueVo addIssueVo = ConvertUtil.copyProperties(downIssue, IssueVo.class);
                addIssueVo.setIssueTypeId(downIssue.getIssueType().getId());
                downIssueVos.add(addIssueVo);
            }
            issueVo.setIssueDownVos(downIssueVos);
            if (downIssueVos.size() > 0) {
                this.setDownIssues(user, downIssueVos);
            }
            //  이슈 사용자 정보 추가
            //this.setIssueUserList(issueVos, issueCondition);
            this.setIssueDepartmentList(issueVos, issueCondition, user);
            //  등록자 정보 추가
            this.setRegister(issueVos);  //  담당자 정보 셋팅
            //  사용자 정의 필드 정보 추가
            this.setIssueCustomFieldValue(issueVos, issueCondition);
            this.SetWorkflowDepartment(issueVos); //워크플로우에 설정한 담당부서 가져오기
        }
    }
    // 연관 이슈 세팅
    private void setRelationIssues(List<IssueVo> issueVos) {
        for(IssueVo issueVo : issueVos) {
            List<IssueVo> relationIssues = this.issueRelationService.findRelationIssue(issueVo.getId());
            for(IssueVo relationIssue : relationIssues){
                issueVo.addRelationIssueVo(ConvertUtil.copyProperties(relationIssue, IssueVo.class));
            }
        }
    }
    @Override
    @Transactional(readOnly = true)
    public void setCountDownIssues(List<Map<String, Object>> results, List<IssueVo> issueVos) {
        for (Map<String, Object> result : results){
            List<Issue> downIssues = this.issueRepository.findByParentIssueId((Long) result.get("id")); //하위이슈 가져오기
    public void setCountDownIssues(List<IssueVo> issueVos) {
        for (IssueVo issueVo : issueVos){
            List<Issue> downIssues = this.issueRepository.findByParentIssueId(issueVo.getId()); //하위이슈 가져오기
            if(downIssues != null && downIssues.size() > 0){ //상위이슈 가지고 있는 애들이 있으면
                int downIssueAllCount = 0;// 하위이슈 전체 카운트
                int downIssueCount = 0;// 하위이슈 미완료 카운트
@@ -811,12 +863,8 @@
                        downIssueCount ++;
                    }
                    for(IssueVo issueVo : issueVos){
                        if(issueVo.getId().equals(parentIssueVo.getId())){
                            issueVo.setDownIssueCount(downIssueCount);
                            issueVo.setDownIssueAllCount(parentIssueVo.getDownIssueAllCount());
                        }
                    }
                    issueVo.setDownIssueCount(downIssueCount);
                    issueVo.setDownIssueAllCount(parentIssueVo.getDownIssueAllCount());
                }
            }
        }
@@ -1038,7 +1086,6 @@
        condition.setWorkspaceId(this.userService.getUser(this.webAppUtil.getLoginId()).getLastWorkspaceId());
        projectCondition.setWorkspaceId(condition.getWorkspaceId());
        //  프로젝트 키가 존재할 경우 프로젝트 키에 해당하는 프로젝트를 조회하고 검색 조건에 셋팅한다.
        if (!this.getProjectByProjectKey(condition.getProjectKey(), condition)) {
            return false;
@@ -1047,9 +1094,7 @@
        //  프로젝트를 선택하지 않았으면 해당 업무 공간에서 참여하고 있는 프로젝트를 찾는다.
        if (condition.getProjectIds().size() < 1) {
            List<Map<String, Object>> projects = null;
            UserLevel userLevel = this.userLevelService.getUserLevel(user.getUserLevel().getId());
            if (this.userWorkspaceService.checkWorkspaceManager(user)
                    || MngPermission.checkMngPermission(userLevel.getPermission(), MngPermission.USER_PERMISSION_MNG_ISSUE_PROJECT_ALL)) {
            if (this.userWorkspaceService.checkWorkspaceManager(user)) {
                projects = this.projectMapper.findByWorkspaceManagerAll(projectCondition);
            } else  {
                projects = this.projectService.findByWorkspaceIdAndIncludeProjectAll(projectCondition);
@@ -1266,26 +1311,26 @@
    // 하위 이슈 정보를 셋팅한다
    private void setDownIssues(Issue issue, IssueVo issueVo) {
        List<Issue> downIssues = this.issueRepository.findByParentIssueId(issue.getId());
            if(downIssues != null && downIssues.size()>0){
                List<IssueVo> resultList = new ArrayList<>();
                for(Issue downIssue : downIssues){
                    IssueVo downIssueVo = ConvertUtil.copyProperties(downIssue, IssueVo.class);
                    downIssueVo.setIssueTypeVo(ConvertUtil.copyProperties(downIssue.getIssueType(), IssueTypeVo.class));
                    downIssueVo.setPriorityVo(ConvertUtil.copyProperties(downIssue.getPriority(), PriorityVo.class));
                    downIssueVo.setSeverityVo(ConvertUtil.copyProperties(downIssue.getSeverity(), SeverityVo.class));
                    //이슈 상태 추가
                    IssueStatusVo issueStatusVo = ConvertUtil.copyProperties(downIssue.getIssueStatus(), IssueStatusVo.class, "issueStatusType");
                    issueStatusVo.setIssueStatusType(downIssue.getIssueStatus().getIssueStatusType().toString());
                    downIssueVo.setIssueStatusVo(issueStatusVo);
        if(downIssues != null && downIssues.size()>0){
            List<IssueVo> resultList = new ArrayList<>();
            for(Issue downIssue : downIssues){
                IssueVo downIssueVo = ConvertUtil.copyProperties(downIssue, IssueVo.class);
                downIssueVo.setIssueTypeVo(ConvertUtil.copyProperties(downIssue.getIssueType(), IssueTypeVo.class));
                downIssueVo.setPriorityVo(ConvertUtil.copyProperties(downIssue.getPriority(), PriorityVo.class));
                downIssueVo.setSeverityVo(ConvertUtil.copyProperties(downIssue.getSeverity(), SeverityVo.class));
                //이슈 상태 추가
                IssueStatusVo issueStatusVo = ConvertUtil.copyProperties(downIssue.getIssueStatus(), IssueStatusVo.class, "issueStatusType");
                issueStatusVo.setIssueStatusType(downIssue.getIssueStatus().getIssueStatusType().toString());
                downIssueVo.setIssueStatusVo(issueStatusVo);
                    this.setRegister(downIssue, downIssueVo); // 등록자
                    this.setIssueDepartment(downIssue, downIssueVo);  //  담당부서 정보 셋팅
                    this.setIssueCustomFields(downIssue, downIssueVo);   // 사용자정의필드 정보 세팅
                this.setRegister(downIssue, downIssueVo); // 등록자
                this.setIssueDepartment(downIssue, downIssueVo);  //  담당부서 정보 셋팅
                this.setIssueCustomFields(downIssue, downIssueVo);   // 사용자정의필드 정보 세팅
                    resultList.add(downIssueVo);
                }
                issueVo.setIssueDownVos(resultList);
                resultList.add(downIssueVo);
            }
            issueVo.setIssueDownVos(resultList);
        }
    }
    //  이슈 상세 정보를 셋팅한다.
@@ -1482,10 +1527,10 @@
    // 사용자 정의 필드 값이 같은 이슈 찾기
    @Override
    @Transactional
    public List<IssueVo> findIssue(IssueApiForm issueApiform) {
    public List<Issue> findIssue(IssueApiForm issueApiform) {
        List<IssueCustomFieldValueForm> issueCustomFieldValueForms = issueApiform.getIssueCustomFieldValues();
        List<IssueVo> resultIssueVos = Lists.newArrayList();
        List<Issue> resultIssueVos = Lists.newArrayList();
        String comma = ",";
        if (issueCustomFieldValueForms.size() > 0) {
@@ -1500,10 +1545,11 @@
            IssueCustomFieldValueCondition issueCustomFieldValueCondition = new IssueCustomFieldValueCondition();
            issueCustomFieldValueCondition.setUseValue(concatUseValue);
            issueCustomFieldValueCondition.setIssueTypeId(issueApiform.getIssueTypeId());
            List<Map<String, Object>> results = this.issueMapper.findByCustomFieldValue(issueCustomFieldValueCondition);
            if (results != null && results.size() > 0) {
                for (Map<String, Object> result : results) {
                    resultIssueVos.add(ConvertUtil.convertMapToClass(result, IssueVo.class));
                    resultIssueVos.add(this.getIssue(MapUtil.getLong(result, "id")));
                }
            }
        }
@@ -1529,11 +1575,10 @@
        User user = this.convertToUser(issueApiForm.getToken());
        IssueForm issueForm = this.convertToIssueForm(issueApiForm, user);
        List<IssueVo> issueVos = this.findIssue(issueApiForm);
        if (issueVos != null && issueVos.size() > 0) {
            List<Issue> issue = Lists.newArrayList();
            for (IssueVo issueVo : issueVos) {
                IssueVo parentIssueVo = issueVo.getParentIssueVo();
        List<Issue> issue = this.findIssue(issueApiForm);
        if (issue != null && issue.size() > 0) {
            List<Issue> issues = Lists.newArrayList();
            for (Issue issueVo : issue) {
                issueForm.setId(issueVo.getId());
                // 자동 종료 상태 설정이 되어 있지 않으면 오류발생
@@ -1555,9 +1600,9 @@
                    }
                }
                issue.add(modifyIssue);
                issues.add(modifyIssue);
            }
            return issue;
            return issues;
        } else {
            throw new OwlRuntimeException(
                    this.messageAccessor.getMessage(MsgConstants.API_ISSUE_NOT_EXIST));
@@ -2163,38 +2208,39 @@
    }
    private Issue issueRemoves(Long issueId, User user) {
        Issue issue = this.findOne(issueId);
        if(issue != null){
            //  이슈 수정 권한을 갖고 있는지 확인
            this.verifyIssueModifyPermission(issue, user);
            //  이슈 첨부 파일을 삭제한다.
            if (issue.getAttachedFiles().size() > 0) {
                List<Long> attachedFileIds = Lists.newArrayList();
                for (AttachedFile attachedFile : issue.getAttachedFiles()) {
                    attachedFileIds.add(attachedFile.getId());
                }
                //  첨부파일 삭제
                this.attachedFileService.removeAttachedFiles(attachedFileIds);
            }
            // 지울 이슈가 연관이슈인지 체크 후 연관이슈 테이블에서도 삭제한다.
            List<IssueRelation> issueRelationList = this.issueRelationRepository.findByRelationIssueId(issueId);
            if (issueRelationList != null && issueRelationList.size() > 0) {
                for(IssueRelation issueRelation : issueRelationList){
                    StringBuilder sb = new StringBuilder();
                    issueHistoryService.detectRelationIssue(IssueHistoryType.DELETE, issueRelation, sb);
                    issueHistoryService.addIssueHistory(issueRelation.getIssue(), IssueHistoryType.MODIFY, sb.toString());
                    this.issueRelationRepository.delete(issueRelation);
                }
            }
            //  이슈 생성, 삭제시 예약 이메일에 등록해놓는다.
            this.reservationIssueEmail(issue, EmailType.ISSUE_REMOVE);
            //  이슈 삭제
            this.issueRepository.delete(issue);
        Issue issue = null;
        if(issueId != null){
            issue = this.getIssue(issueId);
        }
        //  이슈 수정 권한을 갖고 있는지 확인
        this.verifyIssueModifyPermission(issue, user);
        //  이슈 첨부 파일을 삭제한다.
        if (issue.getAttachedFiles().size() > 0) {
            List<Long> attachedFileIds = Lists.newArrayList();
            for (AttachedFile attachedFile : issue.getAttachedFiles()) {
                attachedFileIds.add(attachedFile.getId());
            }
            //  첨부파일 삭제
            this.attachedFileService.removeAttachedFiles(attachedFileIds);
        }
        // 지울 이슈가 연관이슈인지 체크 후 연관이슈 테이블에서도 삭제한다.
        List<IssueRelation> issueRelationList = this.issueRelationRepository.findByRelationIssueId(issueId);
        if (issueRelationList != null && issueRelationList.size() > 0) {
            for(IssueRelation issueRelation : issueRelationList){
                StringBuilder sb = new StringBuilder();
                issueHistoryService.detectRelationIssue(IssueHistoryType.DELETE, issueRelation, sb);
                issueHistoryService.addIssueHistory(issueRelation.getIssue(), IssueHistoryType.MODIFY, sb.toString());
                this.issueRelationRepository.delete(issueRelation);
            }
        }
        //  이슈 생성, 삭제시 예약 이메일에 등록해놓는다.
        this.reservationIssueEmail(issue, EmailType.ISSUE_REMOVE);
        //  이슈 삭제
        this.issueRepository.delete(issue);
        return issue;
    }
@@ -3226,45 +3272,36 @@
    //  이슈를 템플릿에 따라 파트너 담당자에게 메일로 발송한다.
    @Override
    @Transactional(readOnly = true)
    public void sendIssueEmailPartners(IssueForm issueForm) {
        if (issueForm.getSendEmails().size() < 1) {
    public void sendIssueEmailPartners(EmailTemplateForm emailTemplateForm) {
        if (emailTemplateForm.getSendEmails().size() < 1) {
            throw new OwlRuntimeException(
                    this.messageAccessor.getMessage(MsgConstants.ISSUE_NOT_SEND_USER));
        }else if (issueForm.getTemplate() == null){
        }else if (emailTemplateForm.getTemplate() == null){
            throw new OwlRuntimeException(
                    this.messageAccessor.getMessage(MsgConstants.ISSUE_NOT_SELECT_TEMPLATE));
        } else if (emailTemplateForm.getIssueId() == null) {
            throw new OwlRuntimeException(
                    this.messageAccessor.getMessage(MsgConstants.ISSUE_NOT_EXIST));
        }
        Issue issue = this.getIssue(issueForm.getId());
        Issue issue = this.getIssue(emailTemplateForm.getIssueId());
        Map<String, Object> issueMap = new HashMap<>();
        //  이슈 정보를 이메일 전송에 사용하기 위해 Map 형태로 변환한다.
        this.makeIssueMapToIssue(issue, issueMap);
        //  발신자 표시
        User user = this.webAppUtil.getLoginUserObject();
        UserVo toUser = this.webAppUtil.getLoginUser();
        issueMap.put("toUser", toUser.getName() + "(" + CommonUtil.decryptAES128(toUser.getAccount()) + ")");
        // 이슈 링크
        String projectKey = issue.getProject().getProjectKey();
        Long IssueNumber = issue.getIssueNumber();
        String link = this.configuration.getEmailSendUrl() + "/#/issues/issueList?projectKey=" + projectKey + "&issueNumber=" + IssueNumber.toString();
        issueMap.put("issueLink", link);
        issueMap.put("projectLink", link);
        //  사용자 시스템 기능 사용 정보 수집
        log.info(ElasticSearchUtil.makeUserActiveHistoryMessage(this.webAppUtil.getLoginUser(), ElasticSearchConstants.ISSUE_ANOTHER_USER_SEND_EMAIL));
        StringBuilder sb = new StringBuilder();
        if(issueForm.getTemplate().equals(EmailType.ISSUE_SEND_1.toString())){
            this.systemEmailService.directEmail(ConvertUtil.ToArray(issueForm.getSendEmails()), EmailType.ISSUE_SEND_1, issueMap, null);
        }else if(issueForm.getTemplate().equals(EmailType.ISSUE_SEND_2.toString())){
            this.systemEmailService.directEmail(ConvertUtil.ToArray(issueForm.getSendEmails()), EmailType.ISSUE_SEND_2, issueMap, null);
        }else if(issueForm.getTemplate().equals(EmailType.ISSUE_SEND_3.toString())){
            this.systemEmailService.directEmail(ConvertUtil.ToArray(issueForm.getSendEmails()), EmailType.ISSUE_SEND_3, issueMap, null);
        Locale locale = CommonUtil.getUserLanguage(user.getLanguage());
        String[] sendMails = ConvertUtil.ToArray(emailTemplateForm.getSendEmails());
        for(int i=0; i < sendMails.length; i++) {
            sendMails[i] = CommonUtil.decryptAES128(sendMails[i]);
        }
        //메일 전송 이력 남기기
        this.issueHistoryService.detectSendIssueMail(IssueHistoryType.SEND, issueForm, sb);
        this.systemEmailService.sendEmail(emailTemplateForm.getTitle(), emailTemplateForm.getTemplate(), sendMails, null);
        this.issueHistoryService.detectSendIssueMail(IssueHistoryType.SEND, emailTemplateForm.getSendEmails(), sb);
        this.issueHistoryService.addIssueHistory(issue, IssueHistoryType.SEND, sb.toString());
    }
@@ -3458,7 +3495,6 @@
        }
        this.issueHistoryService.addIssueHistory(parentIssue, IssueHistoryType.MODIFY, sb.toString()); //parentIssue = myIssue(기록은 현재 상세페이지에 해야하니까)
        this.issueRepository.saveAndFlush(issue);
    }
    @Override