OWL ITS + 탐지시스템(인터넷 진흥원)
src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java
@@ -47,9 +47,7 @@
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;
import static kr.wisestone.owl.domain.enumType.CustomFieldType.*;
@@ -312,7 +310,7 @@
                }
                // 중복된 상위 이슈검색
                List<Issue> issues = this.findIssue(issueApiForm, customFieldApiOverlaps, user.getId());
                List<Issue> issues = this.findIssue(issueApiForm, issueForm, customFieldApiOverlaps, user.getId());
                int size = issues.size();
                if (size > 0) {
                    Issue targetIssue = issues.get(0);
@@ -329,7 +327,6 @@
            // 사용자 정의 필드 설정
            issueForm.setIssueCustomFields(issueApiForm.getCustomFieldValues());
            //  같은 도메인 업체 찾기
            this.findCompanyField(issueForm);
            // api 입력값 적용
            ConvertUtil.copyProperties(issueApiForm, issueForm);
@@ -341,10 +338,15 @@
        }
    }
    /**
     * 도메인이 동일한 업체 찾기
     * @param issueForm IssueForm
     * @return IssueForm
     */
    private IssueForm findCompanyField(IssueForm issueForm) {
        if(issueForm.getIssueCustomFields() != null && issueForm.getIssueCustomFields().size() > 0) {
            CompanyFieldCondition condition = new CompanyFieldCondition();
            List<Map<String, Object>> companyFields = this.companyFieldService.find(condition);
            List<Map<String, Object>> companyFields = Lists.newArrayList();
            List<Map<String, Object>> issueCompanyFields = Lists.newArrayList();
            List<Map<String, Object>> issueIspFields = Lists.newArrayList();
            List<Map<String, Object>> issueHostingFields = Lists.newArrayList();
@@ -352,27 +354,36 @@
            for (Map<String, Object> issueCustomField : issueForm.getIssueCustomFields()) {
                Long customFieldId = MapUtil.getLong(issueCustomField, "customFieldId");
                CustomField customField = this.customFieldService.getCustomField(customFieldId);
                if(customField != null && customField.getCustomFieldType().toString().equals("SITE") && customField.getName().equals("도메인")) {
                if(customField != null && customField.getCustomFieldType().equals(SITE) && customField.getName().equals("도메인")) {
                    String useValue = issueCustomField.get("useValue").toString();
                    String[] urlArr = null;
                    List<String> urls = Lists.newArrayList();
                    if (useValue.contains(",")) {
                        urlArr = useValue.split(",");
                        urls.addAll(Arrays.asList(urlArr));
                    } else {
                        urls.add(useValue);
                    }
                    condition.setUrl(urls);
                    companyFields = this.companyFieldService.find(condition);
                    if(companyFields != null && companyFields.size() > 0) {
                        for (Map<String, Object> companyField : companyFields) {
                            CompanyFieldVo companyFieldVo = ConvertUtil.convertMapToClass(companyField, CompanyFieldVo.class);
                            if(companyFieldVo.getUrl() != null && useValue.equals(companyFieldVo.getUrl())) {
                                companyField.put("companyId", companyField.get("id"));
                                issueCompanyFields.add(companyField);
                                if(companyFieldVo.getIspId() != null && companyFieldVo.getIspId() != -1) {
                                    Map<String, Object> ispField = this.ispFieldService.find(companyFieldVo.getIspId());
                                    if (ispField != null) {
                                        ispField.put("ispId", ispField.get("id"));
                                        issueIspFields.add(ispField);
                                    }
                            companyField.put("companyId", companyField.get("id"));
                            issueCompanyFields.add(companyField);
                            if(companyFieldVo.getIspId() != null && companyFieldVo.getIspId() != -1) {
                                Map<String, Object> ispField = this.ispFieldService.find(companyFieldVo.getIspId());
                                if (ispField != null) {
                                    ispField.put("ispId", ispField.get("id"));
                                    issueIspFields.add(ispField);
                                }
                                if(companyFieldVo.getHostingId() != null && companyFieldVo.getHostingId() != -1) {
                                    Map<String, Object> hostingField = this.hostingFieldService.find(companyFieldVo.getHostingId());
                                    if (hostingField != null) {
                                        hostingField.put("hostingId", hostingField.get("id"));
                                        issueHostingFields.add(hostingField);
                                    }
                            }
                            if(companyFieldVo.getHostingId() != null && companyFieldVo.getHostingId() != -1) {
                                Map<String, Object> hostingField = this.hostingFieldService.find(companyFieldVo.getHostingId());
                                if (hostingField != null) {
                                    hostingField.put("hostingId", hostingField.get("id"));
                                    issueHostingFields.add(hostingField);
                                }
                            }
                        }
@@ -385,6 +396,41 @@
        }
        return issueForm;
    }
    /**
     * 조건에 맞는 파트너 정보 찾기
     * @param condition CompanyFieldCondition
     * @param issueCompanyFields List<Map<String, Object>>
     * @param issueIspFields List<Map<String, Object>>
     * @param issueHostingFields List<Map<String, Object>>
     */
    private void findPartner(CompanyFieldCondition condition, List<Map<String, Object>> issueCompanyFields
            , List<Map<String, Object>> issueIspFields, List<Map<String, Object>> issueHostingFields) {
        List<Map<String, Object>> companyFields = this.companyFieldService.find(condition);
        if(companyFields != null && companyFields.size() > 0) {
            for (Map<String, Object> companyField : companyFields) {
                CompanyFieldVo companyFieldVo = ConvertUtil.convertMapToClass(companyField, CompanyFieldVo.class);
                companyField.put("companyId", companyField.get("id"));
                issueCompanyFields.add(companyField);
                if(companyFieldVo.getIspId() != null && companyFieldVo.getIspId() != -1) {
                    Map<String, Object> ispField = this.ispFieldService.find(companyFieldVo.getIspId());
                    if (ispField != null) {
                        ispField.put("ispId", ispField.get("id"));
                        issueIspFields.add(ispField);
                    }
                }
                if(companyFieldVo.getHostingId() != null && companyFieldVo.getHostingId() != -1) {
                    Map<String, Object> hostingField = this.hostingFieldService.find(companyFieldVo.getHostingId());
                    if (hostingField != null) {
                        hostingField.put("hostingId", hostingField.get("id"));
                        issueHostingFields.add(hostingField);
                    }
                }
            }
        }
    }
    private User convertToUser(String token) {
@@ -413,10 +459,12 @@
            // 가상 상위 이슈 추가
            parentIssueForm.setUseIssueCustomFields(issueApiForm.getUseIssueCustomFieldIds());
            //  같은 도메인 업체 찾기
            IssueForm partners = this.findCompanyField(parentIssueForm);
            parentIssueForm.setIssueCompanyFields(partners.getIssueCompanyFields());
            parentIssueForm.setIssueIspFields(partners.getIssueIspFields());
            parentIssueForm.setIssueHostingFields(partners.getIssueHostingFields());
            if (parentIssueForm.getIssueCompanyFields() == null) {
                IssueForm partners = this.findCompanyField(parentIssueForm);
                parentIssueForm.setIssueCompanyFields(partners.getIssueCompanyFields());
                parentIssueForm.setIssueIspFields(partners.getIssueIspFields());
                parentIssueForm.setIssueHostingFields(partners.getIssueHostingFields());
            }
            Issue issue = addIssue(user, parentIssueForm, null);
            issues.add(issue);
@@ -438,7 +486,7 @@
    }
    // 중복된 상위 이슈 검색
    private List<Issue> findIssue(IssueApiForm issueApiform, List<CustomFieldApiOverlap> customFieldApiOverlaps, Long userId) {
    private List<Issue> findIssue(IssueApiForm issueApiform, IssueForm issueForm, List<CustomFieldApiOverlap> customFieldApiOverlaps, Long userId) {
        List<IssueCustomFieldValueForm> issueCustomFieldValueForms = issueApiform.getIssueCustomFieldValues();
        List<Issue> resultIssueVos = Lists.newArrayList();
        String comma = ",";
@@ -446,15 +494,52 @@
        if (issueCustomFieldValueForms.size() > 0) {
            String concatUseValue = "";
            int useIdx = 0;
            int cntIp = 0;
            int cntSite = 0;
            IssueCustomFieldValueFormComparator comp = new IssueCustomFieldValueFormComparator();
            Collections.sort(issueCustomFieldValueForms, comp);
            List<String> userValues = Lists.newArrayList();
            CompanyFieldCondition condition = new CompanyFieldCondition();
            List<Map<String, Object>> issueCompanyFields = Lists.newArrayList();
            List<Map<String, Object>> issueIspFields = Lists.newArrayList();
            List<Map<String, Object>> issueHostingFields = Lists.newArrayList();
            for (IssueCustomFieldValueForm issueCustomFieldValueForm : issueCustomFieldValueForms) {
                userValues.add(issueCustomFieldValueForm.getUseValue());
                for(CustomFieldApiOverlap customFieldApiOverlap : customFieldApiOverlaps) {
                    if (customFieldApiOverlap.getCustomField().getId().equals(issueCustomFieldValueForm.getCustomFieldId())) {
                        String useValue = issueCustomFieldValueForm.getUseValue();
                        if (useValue.contains(" ")) {
                            useValue = useValue.replace(" ","");
                        }
                        if (customFieldApiOverlap.getCustomField().getCustomFieldType().equals(IP_ADDRESS)) {
                            long ip = ConvertUtil.ipToLong(useValue);
                            if (cntIp == 0){
                                condition.setIp(ip);
                            }
                            cntIp ++;
                        }
                        if(customFieldApiOverlap.getCustomField().getCustomFieldType().equals(SITE)) {
                            String[] urlArr = null;
                            List<String> urls = Lists.newArrayList();
                            if (useValue.contains(",")) {
                                urlArr = useValue.split(",");
                                urls.addAll(Arrays.asList(urlArr));
                            } else {
                                urls.add(useValue);
                            }
                            if (cntSite == 0) {
                                condition.setUrl(urls);
                            }
                            cntSite ++;
                        }
                        if (useIdx > 0) {
                            concatUseValue = concatUseValue.concat(comma);
                        }
@@ -463,6 +548,13 @@
                    }
                }
            }
            // 추가 할 url or ip에 포함되어있는 파트너 찾기
            this.findPartner(condition, issueCompanyFields, issueIspFields, issueHostingFields);
            issueForm.setIssueCompanyFields(issueCompanyFields);
            issueForm.setIssueIspFields(issueIspFields);
            issueForm.setIssueHostingFields(issueHostingFields);
            IssueCustomFieldValueCondition issueCustomFieldValueCondition = new IssueCustomFieldValueCondition();
            issueCustomFieldValueCondition.setUseValue(concatUseValue);
@@ -536,6 +628,16 @@
        issue = this.issueRepository.saveAndFlush(issue);
        issue.setReverseIndex(issue.getId() * -1);  //  쿼리 속도 개선을 위해 리버스 인덱스 생성
        if (issueForm.getParentIssueId() != null){
            Issue parentIssue = this.getIssue(issueForm.getParentIssueId());
            if (issueForm.getIsApi().equals(Issue.IS_API_YES)
                    || (issueForm.getInheritYn() != null && issueForm.getInheritYn())) {
                //  하위이슈에 상위이슈의 파트너 정보 적용
                this.inheritPartners(issue, parentIssue);
            }
        }
        //  담당자 지정
        //this.issueUserService.modifyIssueUser(issue, project.getWorkspace(), issueForm.getUserIds());
        //  담당부서 지정
@@ -583,15 +685,15 @@
    //  하위이슈를 생성한다.
    @Override
    @Transactional
    public Issue addDownIssue(IssueForm issueForm, List<MultipartFile> multipartFiles) {
    public Issue addDownIssue(Map<String, Object> resJsonData, IssueForm issueForm, List<MultipartFile> multipartFiles) {
        User user = this.webAppUtil.getLoginUserObject();
        return addDownIssue(user, issueForm, multipartFiles);
        return addDownIssue(resJsonData, user, issueForm, multipartFiles);
    }
    //  하위이슈를 생성한다.
    @Override
    @Transactional
    public Issue addDownIssue(User user, IssueForm issueForm, List<MultipartFile> multipartFiles) {
    public Issue addDownIssue(Map<String, Object> resJsonData, User user, IssueForm issueForm, List<MultipartFile> multipartFiles) {
        StringBuilder detectIssueChange = new StringBuilder();
        //  사용하고 있는 업무 공간이 활성 상태인지 확인한다. 사용 공간에서 로그인한 사용자가 비활성인지 확인한다.
@@ -655,6 +757,7 @@
        this.issueHistoryService.addIssueHistory(issue, user, IssueHistoryType.ADD, null);
        //  이슈 위험 관리 생성
        this.issueRiskService.addIssueRisk(issue, project.getWorkspace());
        //  영속성 컨텍스트 비우기
        this.clear();
        //  이슈 생성, 삭제시 예약 이메일에 등록해놓는다.
@@ -664,7 +767,22 @@
        UserVo userVo = ConvertUtil.copyProperties(user, UserVo.class);
        log.info(ElasticSearchUtil.makeUserActiveHistoryMessage(userVo, ElasticSearchConstants.ISSUE_ADD));
        IssueVo issueVo = this.convertToIssueVo(issue);
        resJsonData.put(Constants.RES_KEY_CONTENTS, issueVo);
        return issue;
    }
    /**
     * Issue를 IssueVo로 변환(하위이슈의 파트너 정보 상속 시 필요)
     * @param issue Issue
     * @return IssueVo
     */
    private IssueVo convertToIssueVo(Issue issue) {
        IssueVo issueVo = ConvertUtil.copyProperties(issue, IssueVo.class);
        issueVo.setInheritPartners(issue.getIssueType().getInheritPartners());
        issueVo.setUsePartner(issue.getIssueType().getUsePartner());
        return issueVo;
    }
    //  연관이슈를 생성한다.
@@ -1276,6 +1394,9 @@
    private void setMapToIssueVo(List<Map<String, Object>> results, List<IssueVo> issueVos, IssueCondition issueCondition, User user) {
        for (Map<String, Object> result : results) {
            IssueVo issueVo = ConvertUtil.convertMapToClass(result, IssueVo.class);
            if (MapUtil.getString(result, "inheritPartners") != null && MapUtil.getString(result, "inheritPartners").equals("1")) {
                issueVo.setInheritPartners(true);
            }
            issueVos.add(issueVo);
            issueCondition.addIssueIds(String.valueOf(issueVo.getId()));
        }
@@ -2127,6 +2248,15 @@
        //  HOSTING 정보 저장
        this.issueHostingService.modifyIssueHostingField(issue, issueForm, detectIssueChange);
        //  파트너정보 하위이슈 상속
        List<Issue> downIssues = this.issueRepository.findByParentIssueId(issue.getId());
        if (issueForm.getInheritYn() != null && issueForm.getInheritYn()
                && downIssues != null && downIssues.size() > 0) {
            for (Issue downIssue : downIssues) {
                this.inheritPartners(downIssue, issue);
            }
        }
        //  이슈 이력 등록
        if (!StringUtils.isEmpty(detectIssueChange.toString())) {
            this.issueHistoryService.addIssueHistory(issue, user, IssueHistoryType.MODIFY, detectIssueChange.toString());
@@ -2566,21 +2696,24 @@
                    this.messageAccessor.getMessage(MsgConstants.ISSUE_REMOVE_NOT_SELECT));
        }
        List<Issue> removeIssues = Lists.newArrayList();
        Set<Long> removeIds = new HashSet<>();
        for (Long issueId : issueForm.getRemoveIds()) {
            removeIds.add(issueId);
            //하위이슈 체크
            List<Issue> downIssues = this.issueRepository.findByParentIssueId(issueId);
            if(downIssues != null && downIssues.size() > 0){
                for(Issue downIssue : downIssues){
                    Long downIssueId = downIssue.getId();
                    downIssue = this.issueRemoves(downIssueId, user);
                    removeIssues.add(downIssue);
                    removeIds.add(downIssueId);
                }
            }
            Issue issue = this.issueRemoves(issueId, user);
            removeIssues.add(issue);
        }
        for (Long removeId : removeIds) {
            this.issueRemoves(removeId, user);
        }
        //  사용자 시스템 기능 사용 정보 수집
        log.info(ElasticSearchUtil.makeUserActiveHistoryMessage(this.webAppUtil.getLoginUser(), ElasticSearchConstants.ISSUE_REMOVE));
    }
@@ -2838,8 +2971,16 @@
        for (IssueVo issueVo : issueVos) {
            for (Map<String, Object> issueCustomFieldValue : issueCustomFieldValues) {
                int count = 0;
                Map<String, Object> useValues = new HashMap<>();
                if (issueVo.getId().equals(MapUtil.getLong(issueCustomFieldValue, "issueId"))) {
                    IssueCustomFieldValueVo issueCustomFieldValueVo = new IssueCustomFieldValueVo();
                    useValues.put("useValue"+count, MapUtil.getString(issueCustomFieldValue, "useValue"));
                    useValues.put("customFieldId", MapUtil.getLong(issueCustomFieldValue, "customFieldId"));
                    issueCustomFieldValueVo.setUseValues(useValues);
                    issueCustomFieldValueVo.setUseValue(MapUtil.getString(issueCustomFieldValue, "useValue"));
                    CustomFieldVo customFieldVo = new CustomFieldVo();
@@ -3091,6 +3232,9 @@
            Workbook workbook;
            IssueType issueType = new IssueType();
            Workflow workflow = new Workflow();
            workbook = WorkbookFactory.create(multipartFile.getInputStream());
            Sheet sheet = workbook.getSheetAt(0);
            int lastRowNum = sheet.getLastRowNum() + 1;
@@ -3126,10 +3270,19 @@
                //  1번 헤더부터 데이터 영역
                if (rowIndex > 1) {
                    //  이슈로 등록하기 위해 IssueForm 에 데이터를 셋팅한다.
                    IssueForm newIssueForm = this.setIssueFormToExcelField(row, (rowIndex + 1), priorityMaps, severityMaps, departmentMaps, customFieldMaps,
                    IssueForm newIssueForm = this.setIssueFormToExcelField(row, (rowIndex + 1), priorityMaps, severityMaps, customFieldMaps,
                            companyFieldMaps, ispFieldMaps, hostingFieldMaps, headers);
                    ConvertUtil.copyProperties(issueForm, newIssueForm);
                    Project project = this.projectService.getProject(newIssueForm.getProjectId());
                    Long issueNumber = this.issueNumberGeneratorService.generateIssueNumber(project);
                    newIssueForm.setIssueNumber(issueNumber);
                    issueType = this.issueTypeService.getIssueType(newIssueForm.getIssueTypeId());
                    workflow = issueType.getWorkflow();
                    IssueStatus issueStatus = this.issueStatusService.findByIssueStatusTypeIsReady(workflow);
                    newIssueForm.setIssueStatusId(issueStatus.getId());
                    issueForms.add(newIssueForm);
                }
            }
@@ -3139,53 +3292,28 @@
            }
            //  1.176
            //  이슈 등록
//            this.issueMapper.insertBatch(issueForms);
            this.issueMapper.insertBatch(issueForms);
            for (IssueForm saveIssueForm : issueForms) {
                Issue issue = new Issue();
                ConvertUtil.copyProperties(saveIssueForm, issue);
                IssueType issueType = this.issueTypeService.getIssueType(saveIssueForm.getIssueTypeId());
                Workflow workflow = issueType.getWorkflow();
                Project project = this.projectService.getProject(saveIssueForm.getProjectId());
                Long issueNumber = this.issueNumberGeneratorService.generateIssueNumber(project);
                IssueStatus issueStatus = this.issueStatusService.findByIssueStatusTypeIsReady(workflow);
                issue.setPriority(this.priorityService.getPriority(saveIssueForm.getPriorityId()));
                issue.setSeverity(this.severityService.getSeverity(saveIssueForm.getSeverityId()));
                issue.setIssueStatus(issueStatus);
                issue.setIssueType(issueType);
                issue.setProject(project);
                issue.setIssueNumber(issueNumber);
                if (saveIssueForm.getParentIssueId() != null && saveIssueForm.getParentIssueId() > -1) {
                    issue.setParentIssue(this.getIssue(saveIssueForm.getParentIssueId()));
                if (issueForm.getInheritYn() != null && issueForm.getInheritYn() && issueForm.getParentIssueId() != null) {
                    Issue parentIssue = this.getIssue(issueForm.getParentIssueId());
                    //  상위이슈의 파트너 정보 상속
                    this.inheritPartners(issue, parentIssue);
                }
                issue = this.issueRepository.saveAndFlush(issue);
                saveIssueForm.setId(issue.getId());
                IssueDepartment issueDepartment = new IssueDepartment();
                issueDepartment.setIssue(issue);
                issueDepartment.setWorkspace(workspace);
                //  워크플로우 대기 상태의 부서 추가
                List<Long> departmentsIds = this.workflowDepartmentService.findFirstDepartmentIds(workflow);
                if (departmentsIds != null && departmentsIds.size() > 0) {
                    for (Long departmentId : departmentsIds) {
                        issueDepartment.setDepartment(this.departmentService.getDepartment(departmentId));
                    }
                    issue.addIssueDepartment(issueDepartment);
                    this.issueDepartmentService.add(departmentsIds, workspace, issue);
                }
                saveIssueForm.setIssueStatusId(issueStatus.getId());
                this.setIssuePartners(saveIssueForm, issue);
            }
            //  0.416 - 0.439
@@ -3224,24 +3352,21 @@
     * @param issueForm IssueForm
     */
    private void setIssuePartners(IssueForm issueForm, Issue issue) {
        IssueCompany issueCompany = new IssueCompany();
        IssueIsp issueIsp = new IssueIsp();
        IssueHosting issueHosting = new IssueHosting();
        //issueCompany 등록
        if (issueForm.getIssueCompanyFields() != null && issueForm.getIssueCompanyFields().size() > 0) {
            for (Map<String, Object> issueCompanyMap : issueForm.getIssueCompanyFields()) {
                CompanyField companyField =  ConvertUtil.convertMapToClass(issueCompanyMap, CompanyField.class);
                issueCompany = ConvertUtil.convertMapToClass(issueCompanyMap, IssueCompany.class, "id");
                IssueCompany issueCompany = ConvertUtil.convertMapToClass(issueCompanyMap, IssueCompany.class, "id", "registerDate", "modifyDate");
                issueCompany.setCompanyField(companyField);
                issueCompany.setIssue(issue);
                this.issueCompanyRepository.saveAndFlush(issueCompany);
                //  사용자가 ISP를 직접 입력하지 않았을 경우 업체에 등록되어있는 ISP 설정
                //  사용자가 ISP를 직접 입력하지 않았을 경우 업체에 등록되어있는 ISP 설정
                if (issueForm.getIssueIspFields() == null || issueForm.getIssueIspFields().size() < 1) {
                    //  업체의 ISP가 있는 경우 issueISP 등록
                    if (companyField.getIspId() != null && companyField.getIspId() != -1) {
                        IspField ispField = this.ispFieldService.getIsp(companyField.getIspId());
                        issueIsp = ConvertUtil.copyProperties(ispField, IssueIsp.class, "id");
                        IssueIsp issueIsp = ConvertUtil.copyProperties(ispField, IssueIsp.class, "id", "registerDate", "modifyDate");
                        issueIsp.setIspField(ispField);
                        issueIsp.setIssue(issue);
                        this.issueIspRepository.saveAndFlush(issueIsp);
@@ -3252,7 +3377,7 @@
                    //  업체의 호스팅이 있는 경우 issueHosting 등록
                    if (companyField.getHostingId() != null && companyField.getHostingId() != -1) {
                        HostingField hostingField = this.hostingFieldService.getHosting(companyField.getHostingId());
                        issueHosting = ConvertUtil.copyProperties(hostingField, IssueHosting.class, "id");
                        IssueHosting issueHosting = ConvertUtil.copyProperties(hostingField, IssueHosting.class, "id", "registerDate", "modifyDate");
                        issueHosting.setHostingField(hostingField);
                        issueHosting.setIssue(issue);
                        this.issueHostingRepository.saveAndFlush(issueHosting);
@@ -3263,7 +3388,7 @@
        //issueIsp 등록
        if (issueForm.getIssueIspFields() != null && issueForm.getIssueIspFields().size() > 0) {
            for (Map<String, Object> issueIspMap : issueForm.getIssueIspFields()) {
                issueIsp = ConvertUtil.convertMapToClass(issueIspMap, IssueIsp.class, "id");
                IssueIsp issueIsp = ConvertUtil.convertMapToClass(issueIspMap, IssueIsp.class, "id", "registerDate", "modifyDate");
                IspField ispField = ConvertUtil.convertMapToClass(issueIspMap, IspField.class);
                issueIsp.setIspField(ispField);
                issueIsp.setIssue(issue);
@@ -3273,7 +3398,7 @@
        //issueHosting 등록
        if (issueForm.getIssueHostingFields() != null && issueForm.getIssueHostingFields().size() > 0) {
            for (Map<String, Object> issueHostingMap : issueForm.getIssueHostingFields()) {
                issueHosting = ConvertUtil.convertMapToClass(issueHostingMap, IssueHosting.class, "id");
                IssueHosting issueHosting = ConvertUtil.convertMapToClass(issueHostingMap, IssueHosting.class, "id", "registerDate", "modifyDate");
                HostingField hostingField = ConvertUtil.convertMapToClass(issueHostingMap, HostingField.class);
                issueHosting.setHostingField(hostingField);
                issueHosting.setIssue(issue);
@@ -3381,43 +3506,51 @@
            }
            //  엑셀에 업체명을 입력하지 않았을 경우 같은 도메인 업체 찾기
            if (issueForm.getIssueCompanyFields() == null || issueForm.getIssueCompanyFields().size() < 1) {
                // 같은 도메인 업체 찾기
                IssueForm partners = this.findCompanyField(issueForm);
                Issue issue = this.findOne(issueForm.getId());
                if (partners.getIssueCompanyFields() != null && partners.getIssueCompanyFields().size() > 0) {
                    for (Map<String, Object> company : partners.getIssueCompanyFields()) {
                        IssueCompany issueCompany = ConvertUtil.convertMapToClass(company, IssueCompany.class);
                        CompanyField companyField = ConvertUtil.convertMapToClass(company, CompanyField.class);
                        issueCompany.setCompanyField(companyField);
                        issueCompany.setIssue(issue);
                        this.issueCompanyRepository.saveAndFlush(issueCompany);
                    }
                }
                if (partners.getIssueIspFields() != null && partners.getIssueIspFields().size() > 0) {
                    for (Map<String, Object> isp : partners.getIssueIspFields()) {
                        IssueIsp issueIsp = ConvertUtil.convertMapToClass(isp, IssueIsp.class);
                        IspField ispField = ConvertUtil.convertMapToClass(isp, IspField.class);
                        issueIsp.setIspField(ispField);
                        issueIsp.setIssue(issue);
                        this.issueIspRepository.saveAndFlush(issueIsp);
                    }
                }
                if (partners.getIssueHostingFields() != null && partners.getIssueHostingFields().size() > 0) {
                    for (Map<String, Object> hosting : partners.getIssueHostingFields()) {
                        IssueHosting issueHosting = ConvertUtil.convertMapToClass(hosting, IssueHosting.class);
                        HostingField hostingField = ConvertUtil.convertMapToClass(hosting, HostingField.class);
                        issueHosting.setHostingField(hostingField);
                        issueHosting.setIssue(issue);
                        this.issueHostingRepository.saveAndFlush(issueHosting);
                    }
                }
            }
            this.findPartnerByDomain(issueForm);
        }
        if (issueCustomFieldValueMaps.size() > 0) {
            this.issueMapper.insertIssueCustomFieldValueBatch(issueCustomFieldValueMaps);
        }
    }
    /**
     * 엑셀에 업체명을 입력하지 않았을 경우 같은 도메인 업체 찾기
     * @param issueForm IssueForm
     */
    private void findPartnerByDomain(IssueForm issueForm) {
        if (issueForm.getIssueCompanyFields() == null || issueForm.getIssueCompanyFields().size() < 1) {
            // 같은 도메인 업체 찾기
            IssueForm partners = this.findCompanyField(issueForm);
            Issue issue = this.findOne(issueForm.getId());
            if (partners.getIssueCompanyFields() != null && partners.getIssueCompanyFields().size() > 0) {
                for (Map<String, Object> company : partners.getIssueCompanyFields()) {
                    IssueCompany issueCompany = ConvertUtil.convertMapToClass(company, IssueCompany.class);
                    CompanyField companyField = ConvertUtil.convertMapToClass(company, CompanyField.class);
                    issueCompany.setCompanyField(companyField);
                    issueCompany.setIssue(issue);
                    this.issueCompanyRepository.saveAndFlush(issueCompany);
                }
            }
            if (partners.getIssueIspFields() != null && partners.getIssueIspFields().size() > 0) {
                for (Map<String, Object> isp : partners.getIssueIspFields()) {
                    IssueIsp issueIsp = ConvertUtil.convertMapToClass(isp, IssueIsp.class);
                    IspField ispField = ConvertUtil.convertMapToClass(isp, IspField.class);
                    issueIsp.setIspField(ispField);
                    issueIsp.setIssue(issue);
                    this.issueIspRepository.saveAndFlush(issueIsp);
                }
            }
            if (partners.getIssueHostingFields() != null && partners.getIssueHostingFields().size() > 0) {
                for (Map<String, Object> hosting : partners.getIssueHostingFields()) {
                    IssueHosting issueHosting = ConvertUtil.convertMapToClass(hosting, IssueHosting.class);
                    HostingField hostingField = ConvertUtil.convertMapToClass(hosting, HostingField.class);
                    issueHosting.setHostingField(hostingField);
                    issueHosting.setIssue(issue);
                    this.issueHostingRepository.saveAndFlush(issueHosting);
                }
            }
        }
    }
@@ -3470,23 +3603,38 @@
    }
    /**
     * cell String으로 변환 함수
     * @param cell Cell
     * @param isNull boolean
     * @return String
     */
    private String stringToCell (Cell cell, boolean isNull) {
        String cellStr = "";
        if (!isNull) {
            cellStr = CommonUtil.convertExcelStringToCell(cell);
            //  공백 제거
            cell.setCellValue(cellStr.trim());
        } else {
            cell.setCellValue(cellStr);
        }
        return cellStr;
    }
    /**
     * cell NULL 체크 함수
     * 빈 값이 아닌 cell 체크
     * @param cell Cell
     * @return boolean
     */
    private Boolean cellNullCheck (Cell cell) {
        if (cell != null ) {
            int cellType = cell.getCellType();
            if (cellType < Cell.CELL_TYPE_BLANK) {
                if (cellType == Cell.CELL_TYPE_STRING)
                {
                    if (cell.getStringCellValue() != null && !cell.getStringCellValue().equals("")) {
                        return false;
                    }
                } else {
        int cellType = cell.getCellType();
        if (cellType < Cell.CELL_TYPE_BLANK) {
            if (cellType == Cell.CELL_TYPE_STRING) {
                if (cell.getStringCellValue() != null && !cell.getStringCellValue().equals("")) {
                    return false;
                }
            } else {
                return false;
            }
        }
        return true;
@@ -3494,32 +3642,22 @@
    //  엑셀 필드에 있는 정보를 이슈 form 으로 옮긴다.
    private IssueForm setIssueFormToExcelField(Row row, int rowIndex, Map<String, Priority> priorityMaps,
                                               Map<String, Severity> severityMaps, Map<String, DepartmentVo> departmentMaps,
                                               Map<String, CustomField> customFieldMaps, Map<String, CompanyField> companyFieldMaps,
                                               Map<String, IspField> ispFieldMaps, Map<String, HostingField> hostingFieldMaps,
                                               Map<String, Severity> severityMaps, Map<String, CustomField> customFieldMaps,
                                               Map<String, CompanyField> companyFieldMaps, Map<String, IspField> ispFieldMaps, Map<String, HostingField> hostingFieldMaps,
                                               List<String> headers) throws ParseException {
        IssueForm issueForm = new IssueForm();
        issueForm.setRegisterId(this.webAppUtil.getLoginId());
        Project project = null;
        //  제목, 내용, 프로젝트 키, 이슈 타입, 우선순위, 중요도, 담당자, 시작일, 종료일, 사용자 정의 필드
        for (int cellIndex = 0; cellIndex < headers.size(); cellIndex++) {
            Cell cell = row.getCell(cellIndex);
            boolean isNull = true;
            String cellStr = "";
            boolean isNull = true;
            if (cell != null) {
                isNull = cellNullCheck(cell);
                if (!isNull) {
                    cellStr = CommonUtil.convertExcelStringToCell(cell);
                    //  공백 제거
                    cell.setCellValue(cellStr.trim());
                } else {
                    cell.setCellValue(cellStr);
                }
                cellStr = stringToCell(cell, isNull); //cell을 String으로 변환
            }
            switch (cellIndex) {
@@ -4148,11 +4286,71 @@
                this.issueHistoryService.detectDownIssues(IssueHistoryType.DELETE, issue, sb);
                issue.setParentIssue(null);
            }
            if (issueDownForm.getInheritYn() != null && issueDownForm.getInheritYn() && issue.getParentIssue() != null) {
                //  상위이슈의 파트너 정보 상속받기
                issue = this.inheritPartners(issue, parentIssue);
            }
            this.issueHistoryService.addIssueHistory(parentIssue, IssueHistoryType.MODIFY, sb.toString()); //parentIssue = myIssue(기록은 현재 상세페이지에 해야하니까)
            this.issueRepository.saveAndFlush(issue);
        }
    }
    /**
     * 상위이슈의 파트너 정보 상속받기
     * @param issue Issue
     * @param parentIssue Issue
     * @return Issue
     */
    private Issue inheritPartners(Issue issue, Issue parentIssue) {
        if (parentIssue != null) {
            if (parentIssue.getIssueType().getInheritPartners()) {
                IssueCompany issueCompany = new IssueCompany();
                IssueIsp issueIsp = new IssueIsp();
                IssueHosting issueHosting = new IssueHosting();
                if (parentIssue.getIssueCompanies() != null && parentIssue.getIssueCompanies().size() > 0) {
                    issue.getIssueCompanies().clear();
                    issue.getIssueCompanies().addAll(parentIssue.getIssueCompanies());
                    Iterator<IssueCompany> itrCompany = issue.getIssueCompanies().iterator();
                    ConvertUtil.copyProperties(itrCompany.next(), issueCompany, "id");
                    issueCompany.setIssue(issue);
                    issueCompany.setCompanyField(parentIssue.getIssueCompanies().iterator().next().getCompanyField());
                    this.issueCompanyRepository.saveAndFlush(issueCompany);
                } else {
                    this.issueCompanyRepository.deleteByIssueId(issue.getId());
                    this.issueCompanyRepository.flush();
                }
                if (parentIssue.getIssueIspFields() != null && parentIssue.getIssueIspFields().size() > 0) {
                    issue.getIssueIspFields().clear();
                    issue.getIssueIspFields().addAll(parentIssue.getIssueIspFields());
                    Iterator<IssueIsp> itrIsp = issue.getIssueIspFields().iterator();
                    ConvertUtil.copyProperties(itrIsp.next(), issueIsp, "id");
                    issueIsp.setIssue(issue);
                    issueIsp.setIspField(parentIssue.getIssueIspFields().iterator().next().getIspField());
                    this.issueIspRepository.saveAndFlush(issueIsp);
                } else {
                    this.issueIspRepository.deleteByIssueId(issue.getId());
                    this.issueIspRepository.flush();
                }
                if (parentIssue.getIssueHostingFields() != null && parentIssue.getIssueHostingFields().size() > 0) {
                    issue.getIssueHostingFields().clear();
                    issue.getIssueHostingFields().addAll(parentIssue.getIssueHostingFields());
                    Iterator<IssueHosting> itrHosting = issue.getIssueHostingFields().iterator();
                    ConvertUtil.copyProperties(itrHosting.next(), issueHosting, "id");
                    issueHosting.setIssue(issue);
                    issueHosting.setHostingField(parentIssue.getIssueHostingFields().iterator().next().getHostingField());
                    this.issueHostingRepository.saveAndFlush(issueHosting);
                } else {
                    this.issueHostingRepository.deleteByIssueId(issue.getId());
                    this.issueHostingRepository.flush();
                }
            }
        }
        return issue;
    }
    @Override
    public void findPartner(Map<String, Object> resJsonData, Map<String, Object> params) {
        Long issueTypeId = MapUtil.getLong(params, "issueTypeId");