OWL ITS + 탐지시스템(인터넷 진흥원)
- API로 이슈 추가 시 하위이슈처리기준 항목으로 동일한 업체 정보로 이슈 생성하여 하위이슈로 넣기
- 업체 테이블에 ip_start, ip_end 컬럼 추가
1개 파일 추가됨
21개 파일 변경됨
597 ■■■■■ 파일 변경됨
src/main/java/kr/wisestone/owl/constant/MsgConstants.java 2 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/domain/CompanyField.java 18 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/mapper/CompanyFieldMapper.java 6 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/service/impl/CompanyFieldServiceImpl.java 114 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/service/impl/IssueHistoryServiceImpl.java 3 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java 153 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/util/ConvertUtil.java 15 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/vo/CompanyFieldVo.java 27 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/web/condition/CompanyFieldCondition.java 16 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/web/form/CompanyFieldForm.java 18 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/resources/migration/V1_9__alter_data.sql 4 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/resources/mybatis/query-template/companyField-template.xml 56 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/WEB-INF/i18n/code_ko_KR.properties 2 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/WEB-INF/i18n/messages_ko_KR.properties 2 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/assets/styles/main.css 4 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/custom_components/js-table/tableColumnGenerator.directive.js 6 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/i18n/ko/global.json 5 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/scripts/app/companyField/companyFieldAdd.controller.js 14 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/scripts/app/companyField/companyFieldList.controller.js 16 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/scripts/app/companyField/companyFieldModify.controller.js 18 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/views/companyField/companyFieldAdd.html 47 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/views/companyField/companyFieldModify.html 51 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/constant/MsgConstants.java
@@ -288,6 +288,8 @@
    public static final String CODE_NOT_INVALID = "CODE_NOT_INVALID";   // 코드명에는 특수문자를 입력 할 수 없습니다.
    public static final String TEL_NOT_INVALID = "TEL_NOT_INVALID";   // 연락처에는 숫자만 또는 숫자 + 하이픈('-')만 입력 할 수 있습니다.
    public static final String EMAIL_NOT_INVALID = "EMAIL_NOT_INVALID";   //  이메일 형식이 맞지 않습니다.
    public static final String IP_NOT_INVALID = "IP_NOT_INVALID";   //  IP주소 형식이 맞지 않습니다.
    public static final String IP_START_NOT_LARGER_THAN_END = "IP_START_NOT_LARGER_THAN_END";   //  시작 IP가 끝 IP 보다 클 수 없습니다.
    public static final String PROJECT_NOT_INCLUDE_DEPARTMENT = "PROJECT_NOT_INCLUDE_DEPARTMENT";   // 선택한 부서 중 프로젝트에 참여하고 있지 않은 부서가 있습니다.
    public static final String PROJECT_DEPARTMENT_NOT_EQUAL_WORKFLOW = "PROJECT_DEPARTMENT_NOT_EQUAL_WORKFLOW"; // 해당 프로젝트에 속해있는 워크플로우의 담당부서는 프로젝트의 담당부서에서 제외시킬 수 없습니다.
src/main/java/kr/wisestone/owl/domain/CompanyField.java
@@ -14,6 +14,8 @@
    private String manager;
    private String tel;
    private String url;
    private String ipStart;
    private String ipEnd;
    private String email;
    private String memo;
    private Long ispId;
@@ -84,6 +86,22 @@
        this.url = url;
    }
    public String getIpStart() {
        return ipStart;
    }
    public void setIpStart(String ipStart) {
        this.ipStart = ipStart;
    }
    public String getIpEnd() {
        return ipEnd;
    }
    public void setIpEnd(String ipEnd) {
        this.ipEnd = ipEnd;
    }
    public Long getIspId() {
        return ispId;
    }
src/main/java/kr/wisestone/owl/mapper/CompanyFieldMapper.java
@@ -1,5 +1,6 @@
package kr.wisestone.owl.mapper;
import kr.wisestone.owl.domain.CompanyField;
import kr.wisestone.owl.web.condition.CompanyFieldCondition;
import org.springframework.stereotype.Repository;
@@ -18,4 +19,9 @@
    List<Map<String, Object>> findEvent();
    Long findByCompany(Long id);
    List<CompanyField> findByUrls(CompanyFieldCondition companyFieldCondition);
    List<CompanyField> findByUrlsAndIdNot(CompanyFieldCondition companyFieldCondition);
}
src/main/java/kr/wisestone/owl/service/impl/CompanyFieldServiceImpl.java
@@ -84,6 +84,11 @@
        //  업체명 중복 체크
        this.verifyTitle(companyFieldForm.getName(), null);
        if (companyFieldForm.getIpStart() != null && companyFieldForm.getIpEnd() != null) {
            //  아이피 유효성 체크
            this.verifyIp(companyFieldForm.getIpStart(), companyFieldForm.getIpEnd());
        }
        if (companyFieldForm.getUrl() != null) {
            //  url 유효성 체크
            this.verifyUrl(companyFieldForm.getUrl(), null);
@@ -110,6 +115,29 @@
        return companyField;
    }
    /**
     * IP 유효성 체크
     * @param ip String
     */
    private void verifyIp(String ip, String ip2) {
        if (ip2 == null) {
            if (!StringUtils.isEmpty(ip)) {
                if (!Pattern.matches("^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\" +
                        ".(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$", ip)) {
                    throw new OwlRuntimeException(this.messageAccessor.getMessage(MsgConstants.IP_NOT_INVALID));
                }
            }
        } else {
            if (!StringUtils.isEmpty(ip)) {
                long ipStart = ConvertUtil.ipToLong(ip);
                long ipEnd = ConvertUtil.ipToLong(ip2);
                if (ipEnd < ipStart) {
                    throw new OwlRuntimeException(this.messageAccessor.getMessage(MsgConstants.IP_START_NOT_LARGER_THAN_END));
                }
            }
        }
    }
    //  url 유효성 체크
    private void verifyUrl(String url, Long id) {
        /*if (StringUtils.isEmpty(url)) {
@@ -117,14 +145,33 @@
                    this.messageAccessor.getMessage(MsgConstants.COMPANY_NOT_URL));
        }*/
        if (!StringUtils.isEmpty(url)) {
            CompanyField companyField;
            if(id == null){
                companyField = this.companyFieldRepository.findByUrl(url);
            List<CompanyField> companyFieldList = Lists.newArrayList();
            CompanyFieldCondition condition = new CompanyFieldCondition();
            String[] urlArr = null;
            List<String> urls = Lists.newArrayList();
            if (url.contains(" ")) {
                url = url.replace(" ","");
            }
            if (url.contains(",")) {
                urlArr = url.split(",");
                urls.addAll(Arrays.asList(urlArr));
            } else {
                companyField = this.companyFieldRepository.findByUrlAndIdNot(url,id);
                urls.add(url);
            }
            if (companyField != null) {
            if (urls.size() > 0) {
                condition.setUrl(urls);
                if(id == null){
                    companyFieldList = this.companyFieldMapper.findByUrls(condition);
                } else {
                    condition.setId(id);
                    companyFieldList = this.companyFieldMapper.findByUrlsAndIdNot(condition);
                }
            }
            if (companyFieldList != null && companyFieldList.size() > 0) {
                throw new OwlRuntimeException(
                        this.messageAccessor.getMessage(MsgConstants.COMPANY_USED_URL));
            }
@@ -286,6 +333,8 @@
        excelInfo.setFileName(this.messageAccessor.message("common.registerExcelCompanyField")); // 엑셀로 업체 등록하기
        excelInfo.addAttrInfos(new ExportExcelAttrVo("id", this.messageAccessor.message("companyField.companyName"), 20, ExportExcelAttrVo.ALIGN_CENTER)); // 업체명
        excelInfo.addAttrInfos(new ExportExcelAttrVo("id", this.messageAccessor.message("companyField.companyUrl"), 10, ExportExcelAttrVo.ALIGN_CENTER)); // url
        excelInfo.addAttrInfos(new ExportExcelAttrVo("id", this.messageAccessor.message("companyField.companyIpStart"), 10, ExportExcelAttrVo.ALIGN_CENTER)); // ip 시작 주소
        excelInfo.addAttrInfos(new ExportExcelAttrVo("id", this.messageAccessor.message("companyField.companyIpEnd"), 10, ExportExcelAttrVo.ALIGN_CENTER)); // ip 종료 주소
        excelInfo.addAttrInfos(new ExportExcelAttrVo("id", this.messageAccessor.message("isp.ispName"), 20, ExportExcelAttrVo.ALIGN_CENTER)); // isp명
        excelInfo.addAttrInfos(new ExportExcelAttrVo("id", this.messageAccessor.message("Hosting.HostingName"), 20, ExportExcelAttrVo.ALIGN_CENTER)); // 호스팅명
        excelInfo.addAttrInfos(new ExportExcelAttrVo("id", this.messageAccessor.message("companyField.companyTel"), 10, ExportExcelAttrVo.ALIGN_CENTER)); // 연락처
@@ -422,6 +471,8 @@
                if (rowIndex > 1) {
                    //  업체로 등록하기 위해 CompanyFieldForm 에 데이터를 셋팅한다.
                    CompanyFieldForm newCompanyFieldForm = this.setCompanyFieldFormToExcelField(row, (rowIndex + 1), ispFieldMaps, hostingFieldMaps, companyTypeMaps, parentSectorMaps, childSectorMaps, regionMaps, statusMaps, headers);
                    //  ip 유효성 체크
                    this.verifyIp(newCompanyFieldForm.getIpStart(), newCompanyFieldForm.getIpEnd());
                    companyFieldForms.add(newCompanyFieldForm);
                }
@@ -526,63 +577,95 @@
                    break;
                case 2:
                    //  ip시작주소
                    this.setCompanyFormIpStart(cellStr, companyFieldForm, isNull);
                    break;
                case 3:
                    //  ip종료주소
                    this.setCompanyFormIpEnd(cellStr, companyFieldForm, isNull);
                    break;
                case 4:
                    // isp명
                    this.setCompanyFormIspName(cellStr, ispFieldMaps, companyFieldForm, rowIndex, isNull);
                    break;
                case 3:
                case 5:
                    // 호스팅명
                    this.setCompanyFormHostingName(cellStr, hostingFieldMaps, companyFieldForm, rowIndex, isNull);
                    break;
                case 4:
                case 6:
                    // 연락처
                    telTypeCheck(cell, rowIndex);
                    this.setCompanyFormTel(cellStr, companyFieldForm, isNull);
                    break;
                case 5:
                case 7:
                    // 이메일
                    this.setCompanyFormEmail(cellStr, companyFieldForm, isNull);
                    break;
                case 6:
                case 8:
                    // 담당자
                    this.setCompanyFormManager(cellStr, companyFieldForm, isNull);
                    break;
                case 7:
                case 9:
                    // 기업구분
                    this.setCompanyFormCompanyType(cellStr, companyTypeMaps, companyFieldForm, rowIndex, isNull);
                    break;
                case 8:
                case 10:
                    // 업종(대분류)
                    this.setCompanyFormParentSector(cellStr, parentSectorMaps, companyFieldForm, rowIndex, isNull);
                    break;
                case 9:
                case 11:
                    // 업종(중분류)
                    this.setCompanyFormChildSector(cellStr, childSectorMaps, companyFieldForm, rowIndex, isNull);
                    break;
                case 10:
                case 12:
                    // 지역
                    this.setCompanyFormRegion(cellStr, regionMaps, companyFieldForm, rowIndex, isNull);
                    break;
                case 11:
                case 13:
                    // 상태
                    this.setCompanyFormStatus(cellStr, statusMaps, companyFieldForm, isNull);
                    break;
                case 12:
                case 14:
                    // 비고
                    this.setCompanyFormMemo(cellStr, companyFieldForm, isNull);
            }
        }
        return companyFieldForm;
    }
    private void setCompanyFormIpEnd(String ipEnd, CompanyFieldForm companyFieldForm, boolean isNull) {
        if (!isNull) {
            if (ipEnd.contains(" ")) {
                ipEnd = ipEnd.replace(" ", "");
            }
            this.verifyIp(ipEnd, null); //ip 유효성 검사
            companyFieldForm.setIpEnd(ipEnd);
        }
    }
    private void setCompanyFormIpStart(String ipStart, CompanyFieldForm companyFieldForm, boolean isNull) {
        if (!isNull) {
            if (ipStart.contains(" ")) {
                ipStart = ipStart.replace(" ", "");
            }
            this.verifyIp(ipStart, null); //ip 유효성 검사
            companyFieldForm.setIpStart(ipStart);
        }
    }
    private void setCompanyFormMemo(String cellStr, CompanyFieldForm companyFieldForm, boolean isNull) {
@@ -823,6 +906,7 @@
        excelInfo.addAttrInfos(new ExportExcelAttrVo("tel", this.messageAccessor.message("companyField.companyTel"), 10, ExportExcelAttrVo.ALIGN_CENTER));
        excelInfo.addAttrInfos(new ExportExcelAttrVo("email", this.messageAccessor.message("companyField.companyEmail"), 10, ExportExcelAttrVo.ALIGN_CENTER));
        excelInfo.addAttrInfos(new ExportExcelAttrVo("url", this.messageAccessor.message("companyField.companyUrl"), 10, ExportExcelAttrVo.ALIGN_CENTER));
        excelInfo.addAttrInfos(new ExportExcelAttrVo("ipRange", this.messageAccessor.message("companyField.companyIp"), 10, ExportExcelAttrVo.ALIGN_CENTER));
        excelInfo.addAttrInfos(new ExportExcelAttrVo("companyTypeName", this.messageAccessor.message("companyField.companyTypeName"), 10, ExportExcelAttrVo.ALIGN_CENTER));
        excelInfo.addAttrInfos(new ExportExcelAttrVo("parentSectorName", this.messageAccessor.message("companyField.parentSectorName"), 10, ExportExcelAttrVo.ALIGN_CENTER));
        excelInfo.addAttrInfos(new ExportExcelAttrVo("childSectorName", this.messageAccessor.message("companyField.childSectorName"), 10, ExportExcelAttrVo.ALIGN_CENTER));
src/main/java/kr/wisestone/owl/service/impl/IssueHistoryServiceImpl.java
@@ -556,6 +556,7 @@
    // 업체 정보 변경 정보를 기록한다.
    @Override
    @Transactional
    public void detectIssueCompany(IssueHistoryType type, Map<String, Object> param, CompanyFieldForm companyFieldForm, IssueCompany issueCompany, StringBuilder description) {
        Long companyFieldId = 0L;
        Long id = 0L;
@@ -614,7 +615,7 @@
            companyFieldId = issueCompany.getCompanyField().getId();
        }
        if (type == IssueHistoryType.ADD) { //추가 할 경우
        if (type == IssueHistoryType.ADD && issueCompany.getCompanyField() != null) { //추가 할 경우
            description.append("<span translate=\"issue.issueCompanyAddHistory\">업체 정보가 추가되었습니다. </span>");
            description.append("<span class=\"text-primary bold\">&nbsp;>&nbsp;" + issueCompany.getCompanyField().getName() + "</span>");
        } else if (type == IssueHistoryType.MODIFY) { //수정 할 경우
src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java
@@ -310,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);
@@ -327,7 +327,6 @@
            // 사용자 정의 필드 설정
            issueForm.setIssueCustomFields(issueApiForm.getCustomFieldValues());
            //  같은 도메인 업체 찾기
            this.findCompanyField(issueForm);
            // api 입력값 적용
            ConvertUtil.copyProperties(issueApiForm, issueForm);
@@ -339,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();
@@ -350,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);
                                }
                            }
                        }
@@ -383,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) {
@@ -436,7 +484,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 = ",";
@@ -444,15 +492,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);
                        }
@@ -461,6 +546,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);
@@ -534,6 +626,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());
        //  담당부서 지정
@@ -544,15 +646,6 @@
        this.issueIspService.modifyIssueIspField(issue, issueForm, detectIssueChange);
        //  HOSTING 정보 저장
        this.issueHostingService.modifyIssueHostingField(issue, issueForm, detectIssueChange);
        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);
            }
        }
        //  첨부 파일 저장
        //  multipartFile 을 file Map List 객체로 변경한다.
@@ -3208,7 +3301,7 @@
                }
                saveIssueForm.setId(issue.getId());
                //  워크플로우 대기 상태의 부서 추가
                List<Long> departmentsIds = this.workflowDepartmentService.findFirstDepartmentIds(workflow);
                if (departmentsIds != null && departmentsIds.size() > 0) {
src/main/java/kr/wisestone/owl/util/ConvertUtil.java
@@ -558,4 +558,19 @@
        return  list.toArray(new String[list.size()]);
    }
    /**
     * ip주소 long으로 변환
     * @param ipAddress String
     * @return long
     */
    public static long ipToLong(String ipAddress) {
        long result = 0;
        String[] ipAddressArr = ipAddress.split("\\.");
        for (int i=0; i<ipAddressArr.length; i++) {
            result += Integer.parseInt(ipAddressArr[i]) * Math.pow(256, 3-i);
        }
        return result;
    }
}
src/main/java/kr/wisestone/owl/vo/CompanyFieldVo.java
@@ -10,6 +10,9 @@
    private String tel;
    private String email;
    private String url;
    private String ipStart;
    private String ipEnd;
    private String ipRange;
    private String memo;
    private Long ispId;
    private Long hostingId;
@@ -80,6 +83,30 @@
        this.url = url;
    }
    public String getIpStart() {
        return ipStart;
    }
    public void setIpStart(String ipStart) {
        this.ipStart = ipStart;
    }
    public String getIpEnd() {
        return ipEnd;
    }
    public void setIpEnd(String ipEnd) {
        this.ipEnd = ipEnd;
    }
    public String getIpRange() {
        return ipRange;
    }
    public void setIpRange(String ipRange) {
        this.ipRange = ipRange;
    }
    public IspFieldVo getIspFieldVo() {
        return ispFieldVo;
    }
src/main/java/kr/wisestone/owl/web/condition/CompanyFieldCondition.java
@@ -2,6 +2,7 @@
import kr.wisestone.owl.util.ConvertUtil;
import java.util.List;
import java.util.Map;
public class CompanyFieldCondition {
@@ -10,7 +11,8 @@
    private String manager;
    private String tel;
    private String email;
    private String url;
    private List<String> url;
    private long ip;
    private String memo;
    private Long ispId;
    private Long hostingId;
@@ -86,14 +88,22 @@
        PageSize = pageSize;
    }
    public String getUrl() {
    public List<String> getUrl() {
        return url;
    }
    public void setUrl(String url) {
    public void setUrl(List<String> url) {
        this.url = url;
    }
    public long getIp() {
        return ip;
    }
    public void setIp(long ip) {
        this.ip = ip;
    }
    public Long getIspId() {
        return ispId;
    }
src/main/java/kr/wisestone/owl/web/form/CompanyFieldForm.java
@@ -11,6 +11,8 @@
public class CompanyFieldForm extends UsePartnerForm {
    private String manager;
    private String url;
    private String ipStart;
    private String ipEnd;
    private String memo;
    private String tel;
    private Long ispId;
@@ -73,6 +75,22 @@
        this.url = url;
    }
    public String getIpStart() {
        return ipStart;
    }
    public void setIpStart(String ipStart) {
        this.ipStart = ipStart;
    }
    public String getIpEnd() {
        return ipEnd;
    }
    public void setIpEnd(String ipEnd) {
        this.ipEnd = ipEnd;
    }
    public String getMemo() {
        return memo;
    }
src/main/resources/migration/V1_9__alter_data.sql
New file
@@ -0,0 +1,4 @@
/* 업체 IP 대역대 컬럼 추가 */
ALTER TABLE `company_field` ADD COLUMN `ip_start` varchar(15) NULL;
ALTER TABLE `company_field` ADD COLUMN `ip_end` varchar(15) NULL;
src/main/resources/mybatis/query-template/companyField-template.xml
@@ -11,6 +11,9 @@
        cf.tel as tel,
        cf.email as email,
        cf.url as url,
        cf.ip_start as ipStart,
        cf.ip_end as ipEnd,
        concat(cf.ip_start, "~", cf.ip_end) AS ipRange,
        cf.memo as memo,
        cf.isp_id as ispId,
        cf.hosting_id as hostingId,
@@ -33,8 +36,16 @@
        <if test="id != '' and id != null">
            AND cf.id like CONCAT('%',#{id},'%')
        </if>
        <if test="url != '' and id != url">
            AND cf.url like CONCAT('%',#{url},'%')
        <choose>
            <when test="url != null and url.size != 0">
                AND
                <foreach collection="url" item="item" index="index" separator="or" open="(" close=")">
                    cf.url LIKE CONCAT('%',#{item},'%')
                </foreach>
            </when>
        </choose>
        <if test="ip != '' and ip != null">
            AND INET_ATON(cf.ip_start) <![CDATA[ <= ]]> #{ip} AND INET_ATON(cf.ip_end) >= #{ip}
        </if>
        ORDER BY cf.register_date DESC
        <if test="pageSize != '' and pageSize != null">
@@ -55,4 +66,45 @@
            AND cf.id like CONCAT('%',#{id},'%')
        </if>
    </select>
    <select id="findByUrls" resultType="kr.wisestone.owl.domain.CompanyField" parameterType="kr.wisestone.owl.web.condition.CompanyFieldCondition">
        SELECT
        cf.id as id,
        cf.name as name,
        cf.email as email,
        cf.url as url
        FROM
        company_field cf
        WHERE 1=1
        <choose>
            <when test="url != null and url.size != 0">
                AND
                <foreach collection="url" item="item" index="index" separator="or" open="(" close=")">
                    cf.url LIKE CONCAT('%',#{item},'%')
                </foreach>
            </when>
        </choose>
    </select>
    <select id="findByUrlsAndIdNot" resultType="kr.wisestone.owl.domain.CompanyField" parameterType="kr.wisestone.owl.web.condition.CompanyFieldCondition">
        SELECT
        cf.id as id,
        cf.name as name,
        cf.email as email,
        cf.url as url
        FROM
        company_field cf
        WHERE 1=1
        <choose>
            <when test="url != null and url.size != 0">
                AND
                <foreach collection="url" item="item" index="index" separator="or" open="(" close=")">
                    cf.url LIKE CONCAT('%',#{item},'%')
                </foreach>
            </when>
        </choose>
        <if test="id != '' and id != null">
            AND cf.id not like CONCAT('%',#{id},'%')
        </if>
    </select>
</mapper>
src/main/webapp/WEB-INF/i18n/code_ko_KR.properties
@@ -147,6 +147,8 @@
companyField.companyTel=\uC804\uD654\uBC88\uD638
companyField.companyEmail=\uC774\uBA54\uC77C
companyField.companyUrl=url
companyField.companyIpStart=ip \uC2DC\uC791\uC8FC\uC18C
companyField.companyIpEnd=ip \uC885\uB8CC\uC8FC\uC18C
companyField.companyTypeName=\uAE30\uC5C5\uAD6C\uBD84
companyField.parentSectorName=\uC5C5\uC885(\uB300\uBD84\uB958)
companyField.childSectorName=\uC5C5\uC885(\uC911\uBD84\uB958)
src/main/webapp/WEB-INF/i18n/messages_ko_KR.properties
@@ -270,3 +270,5 @@
CODE_NOT_INVALID=\uCF54\uB4DC\uBA85\uC5D0\uB294 \uD2B9\uC218\uBB38\uC790\uB97C \uC785\uB825 \uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
TEL_NOT_INVALID=\uC5F0\uB77D\uCC98\uC5D0\uB294 \uC22B\uC790\uB9CC \uB610\uB294 \uC22B\uC790 + \uD558\uC774\uD508('-')\uB9CC \uC785\uB825 \uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.
EMAIL_NOT_INVALID=\uC774\uBA54\uC77C \uD615\uC2DD\uC774 \uB9DE\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.
IP_NOT_INVALID=IP\uC8FC\uC18C \uD615\uC2DD\uC774 \uB9DE\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.
IP_START_NOT_LARGER_THAN_END=\uC2DC\uC791 IP\uAC00 \uB05D IP \uBCF4\uB2E4 \uD074 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
src/main/webapp/assets/styles/main.css
@@ -7617,6 +7617,10 @@
    height: 100% !important;
}
.mw-49 {
    max-width: 49% !important;
}
.mw-100 {
    max-width: 100% !important;
}
src/main/webapp/custom_components/js-table/tableColumnGenerator.directive.js
@@ -691,6 +691,12 @@
                                            }
                                            break;
                                        case "COMPANYFIELD_IP" :
                                            if ($rootScope.isDefined(scope.data.ipStart) && $rootScope.isDefined(scope.data.ipEnd)) {
                                                makeTag += "<span>" + scope.data.ipStart + "<br>~<br>" + scope.data.ipEnd + "</span>";
                                            }
                                            break;
                                        case "ISPFIELD_MODIFY" :
                                            if ($rootScope.checkMngPermission('USER_PERMISSION_MNG_CUSTOME_FIELD')) {
                                                makeTag += "<span class='titlename cursor table-word-break-all' ng-click='event.modify(data.id)'>" + scope.data.name.replace(/</gi, '&lt;') + "</span>";
src/main/webapp/i18n/ko/global.json
@@ -996,7 +996,7 @@
        "industry" : "산업 분류",
        "domain" : "도메인",
        "url"   : "url",
        "ipAdress" : "ip주소",
        "ipRange" : "ip 대역대",
        "tel" : "연락처",
        "code" : "코드",
        "email" : "이메일",
@@ -1019,7 +1019,8 @@
        "writeTel": "전화번호를 입력하셔야 추가할수 있습니다.",
        "registerExcelCompanyFields": "엑셀로 업체 등록하기",
        "registerExcelUploadCompanyField": "엑셀 업로드 업체 등록",
        "succeededCompanyFieldRegistration": "업체 등록 성공"
        "succeededCompanyFieldRegistration": "업체 등록 성공",
        "multiUrlWithComma": "여러개의 url을 입력 할 수 있습니다. (구분: 콤마 ',') ex: www.test.com, www.test2.com"
    },
    "ispField" : {
        "info": "ISP정보",
src/main/webapp/scripts/app/companyField/companyFieldAdd.controller.js
@@ -38,6 +38,8 @@
                        tel : "",  //전화번호
                        email : "",  //이메일
                        url : "", // url
                        ipStart : "", //ip시작주소
                        ipEnd : "", //ip종료주소
                        memo : "",  //비고
                        companyTypeId : "",
                        companyType : "", //기업구분
@@ -249,7 +251,17 @@
                            }
                            return emailList;
                        })(),
                        url : $scope.vm.form.url, // url
                        url : (function () {
                            //  모든 공백 제거
                            var regex = / /gi;
                            let url = $scope.vm.form.url;
                            if ($rootScope.isDefined(url) && url.indexOf(" ") !== -1) {
                                url = url.replace(regex, "");
                            }
                            return url;
                        })(),
                        ipStart : $scope.vm.form.ipStart, // ip시작주소
                        ipEnd : $scope.vm.form.ipEnd, // ip종료주소
                        memo : $scope.vm.form.memo,  //비고
                        companyTypeId : (function () {
                            var companyTypeId = null;
src/main/webapp/scripts/app/companyField/companyFieldList.controller.js
@@ -105,9 +105,16 @@
                        .setDAlign("text-center"));
                    $scope.vm.tableConfigs.push($tableProvider.config()
                        .setHName("companyField.url")
                        .setHWidth("bold")
                        .setHWidth("width-200-p bold")
                        .setDName("url")
                        .setDAlign("text-center"));
                    $scope.vm.tableConfigs.push($tableProvider.config()
                        .setHName("companyField.ipRange")
                        .setHWidth("width-120-p bold")
                        .setDName("ipRange")
                        .setDType("renderer")
                        .setDAlign("text-center")
                        .setDRenderer("COMPANYFIELD_IP"));
                    $scope.vm.tableConfigs.push($tableProvider.config()
                        .setHName("common.isp")
                        .setHWidth("bold")
@@ -203,6 +210,13 @@
                                        data.email = data.email.replace(/\,/g,"</br>");
                                    }
                                }
                                // url 조회시 콤마 기준으로 줄바꿈
                                if ($rootScope.isDefined(data.url)) {
                                    data.url = data.url.trim();
                                    if (data.url.indexOf(",") !== -1) {
                                        data.url = data.url.replace(/\,/g,"</br>");
                                    }
                                }
                            });
                            $scope.vm.responseData = result.data;
src/main/webapp/scripts/app/companyField/companyFieldModify.controller.js
@@ -41,6 +41,8 @@
                        tel : "",  //전화번호
                        email : "",  //이메일
                        url : "", // url
                        ipStart : "", //ip시작주소
                        ipEnd : "", //ip종료주소
                        memo : "",  //메모(비고)
                        companyTypeId : "",
                        companyType : "", //기업구분
@@ -259,8 +261,18 @@
                            }
                            return emailList;
                        })(),
                        url : $rootScope.preventXss($scope.vm.form.url), // url
                        memo : $rootScope.preventXss($scope.vm.form.memo),
                        url : (function () {
                            //  모든 공백 제거
                            var regex = / /gi;
                            let url = $scope.vm.form.url;
                            if ($rootScope.isDefined(url) && url.indexOf(" ") !== -1) {
                                url = url.replace(regex, "");
                            }
                            return url;
                        })(),
                        ipStart : $scope.vm.form.ipStart, // ip시작주소
                        ipEnd : $scope.vm.form.ipEnd, // ip종료주소
                        memo : $scope.vm.form.memo,
                        companyTypeId : (function () {
                            var companyTypeId = null;
                            if ($scope.vm.form.companyTypes != null && $scope.vm.form.companyTypes.length > 0) {
@@ -442,6 +454,8 @@
                                }
                                $scope.vm.form.url = result.data.content.url;
                                $scope.vm.form.ipStart = result.data.content.ipStart;
                                $scope.vm.form.ipEnd = result.data.content.ipEnd;
                                $scope.vm.form.memo = result.data.content.memo;
                                $scope.vm.form.companyTypeId = result.data.content.companyTypeId;
                                $scope.vm.form.companyType = result.data.content.companyTypeName;
src/main/webapp/views/companyField/companyFieldAdd.html
@@ -34,6 +34,9 @@
                <label for="companyFieldAddForm10" class="issue-label">
                    <span translate="companyField.url">url</span>
                </label>
                <div class="help-block form-text text-danger fs-09">
                    <small translate="companyField.multiUrlWithComma">여러개의 url을 입력 할 수 있습니다. (구분: ',') ex: www.test.com, www.test2.com</small>
                </div>
                <input id="companyFieldAddForm10"
                       name="url"
                       type="text"
@@ -50,6 +53,50 @@
            </div>
            <div class="row">
                <div class="col-lg-6 mw-49">
                    <div class="form-group">
                        <label for="companyFieldAddForm11" class="issue-label">
                            <span translate="companyField.ipRange">ip 대역대</span>
                        </label>
                        <input id="companyFieldAddForm11"
                               name="ipStart"
                               type="text"
                               class="form-control"
                               kr-input
                               ng-pattern="/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/"
                               placeholder="IP 주소 형식만 입력 가능합니다."
                               autocomplete="off"
                               ng-model="vm.form.ipStart"
                        >
                        <div ng-if="companyFieldAddForm.ipStart.$error.pattern" class="help-block form-text text-danger"
                             translate="common.invalidipAdressFormat">IP주소 형식이 맞지 않습니다.
                        </div>
                    </div>
                </div>
                <div class="mt-30">
                    <label class="issue-label">~</label>
                </div>
                <div class="col-lg-6 mw-49">
                    <div class="form-group">
                        <label for="companyFieldAddForm12" class="issue-label"></label>
                        <input id="companyFieldAddForm12"
                               name="ipEnd"
                               type="text"
                               class="form-control"
                               kr-input
                               ng-pattern="/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/"
                               placeholder="IP 주소 형식만 입력 가능합니다."
                               autocomplete="off"
                               ng-model="vm.form.ipEnd"
                        >
                        <div ng-if="companyFieldAddForm.ipEnd.$error.pattern" class="help-block form-text text-danger"
                             translate="common.invalidipAdressFormat">IP주소 형식이 맞지 않습니다.
                        </div>
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col-lg-6">
                    <div class="form-group">
                        <label class="issue-label">
src/main/webapp/views/companyField/companyFieldModify.html
@@ -29,10 +29,13 @@
                <!--<small translate="companyField.enterSpecialCharacters">업체 이름에는 특수 문자를 입력 할수 없습니다.</small>-->
            </div>
            <div class="form-group">
                <label for="companyFieldAddForm10" class="issue-label">
                <label for="companyFieldModifyForm10" class="issue-label">
                    <span translate="companyField.url">url</span>
                </label>
                <input id="companyFieldAddForm10"
                <div class="help-block form-text text-danger fs-09">
                    <small translate="companyField.multiUrlWithComma">여러개의 url을 입력 할 수 있습니다. (구분: ',') ex: www.test.com, www.test2.com</small>
                </div>
                <input id="companyFieldModifyForm10"
                       name="url"
                       type="text"
                       class="form-control"
@@ -47,6 +50,50 @@
                </div>-->
            </div>
            <div class="row">
                <div class="col-lg-6 mw-49">
                    <div class="form-group">
                        <label for="companyFieldModifyForm11" class="issue-label">
                            <span translate="companyField.ipRange">ip 대역대</span>
                        </label>
                        <input id="companyFieldModifyForm11"
                               name="ipStart"
                               type="text"
                               class="form-control"
                               kr-input
                               ng-pattern="/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/"
                               placeholder="IP 주소 형식만 입력 가능합니다."
                               autocomplete="off"
                               ng-model="vm.form.ipStart"
                        >
                        <div ng-if="companyFieldModifyForm.ipStart.$error.pattern" class="help-block form-text text-danger"
                             translate="common.invalidipAdressFormat">IP주소 형식이 맞지 않습니다.
                        </div>
                    </div>
                </div>
                <div class="mt-30">
                    <label class="issue-label">~</label>
                </div>
                <div class="col-lg-6 mw-49">
                    <div class="form-group">
                        <label for="companyFieldModifyForm12" class="issue-label">
                        </label>
                        <input id="companyFieldModifyForm12"
                               name="ipEnd"
                               type="text"
                               class="form-control"
                               kr-input
                               ng-pattern="/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/"
                               placeholder="IP 주소 형식만 입력 가능합니다."
                               autocomplete="off"
                               ng-model="vm.form.ipEnd"
                        >
                        <div ng-if="companyFieldModifyForm.ipEnd.$error.pattern" class="help-block form-text text-danger"
                             translate="common.invalidipAdressFormat">IP주소 형식이 맞지 않습니다.
                        </div>
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col-lg-6">
                    <div class="form-group">
                        <label class="issue-label">