From 81e977cce5fa9f96749cb99759645be715767436 Mon Sep 17 00:00:00 2001 From: mjkhan21 Date: Wed, 24 May 2023 15:31:59 +0900 Subject: [PATCH] =?UTF-8?q?=EC=B5=9C=EC=B4=88=20=EC=BB=A4=EB=B0=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 96 +++ .../cokr/xit/interfaces/smg/Petition.java | 765 ++++++++++++++++++ .../xit/interfaces/smg/dao/SmgMapper.java | 110 +++ .../xit/interfaces/smg/dao/package-info.java | 3 + .../cokr/xit/interfaces/smg/package-info.java | 17 + .../interfaces/smg/service/SmgService.java | 48 ++ .../smg/service/bean/SmgInBean.java | 161 ++++ .../smg/service/bean/SmgOutBean.java | 168 ++++ .../smg/service/bean/SmgServiceBean.java | 51 ++ .../smg/service/bean/package-info.java | 3 + .../interfaces/smg/service/package-info.java | 3 + .../xit/interfaces/smg/web/SmgController.java | 56 ++ .../xit/interfaces/smg/web/package-info.java | 3 + src/main/sql/xit-smg.sql | 111 +++ 14 files changed, 1595 insertions(+) create mode 100644 pom.xml create mode 100644 src/main/java/cokr/xit/interfaces/smg/Petition.java create mode 100644 src/main/java/cokr/xit/interfaces/smg/dao/SmgMapper.java create mode 100644 src/main/java/cokr/xit/interfaces/smg/dao/package-info.java create mode 100644 src/main/java/cokr/xit/interfaces/smg/package-info.java create mode 100644 src/main/java/cokr/xit/interfaces/smg/service/SmgService.java create mode 100644 src/main/java/cokr/xit/interfaces/smg/service/bean/SmgInBean.java create mode 100644 src/main/java/cokr/xit/interfaces/smg/service/bean/SmgOutBean.java create mode 100644 src/main/java/cokr/xit/interfaces/smg/service/bean/SmgServiceBean.java create mode 100644 src/main/java/cokr/xit/interfaces/smg/service/bean/package-info.java create mode 100644 src/main/java/cokr/xit/interfaces/smg/service/package-info.java create mode 100644 src/main/java/cokr/xit/interfaces/smg/web/SmgController.java create mode 100644 src/main/java/cokr/xit/interfaces/smg/web/package-info.java create mode 100644 src/main/sql/xit-smg.sql diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..ca6bf4b --- /dev/null +++ b/pom.xml @@ -0,0 +1,96 @@ + + 4.0.0 + + cokr.xit.interfaces + xit-smg + 23.04.01-SNAPSHOT + jar + + xit-smg + http://maven.apache.org + + + UTF-8 + + 1.8 + ${java.version} + ${java.version} + + + + + + mvn2s + https://repo1.maven.org/maven2/ + + true + + + true + + + + egovframe + http://maven.egovframe.kr:8080/maven/ + + true + + + false + + + + egovframe2 + http://www.egovframe.go.kr/maven/ + + true + + + false + + + + + maven-public + http://xit.xit-nexus.com:8081/repository/maven-public/ + + + + + + + cokr.xit.interfaces + xit-filejob + 23.04.01-SNAPSHOT + + + + + install + ${basedir}/target + ${artifactId}-${version} + + + ${basedir}/src/main/resources + + + ${basedir}/src/test/resources + ${basedir}/src/main/resources + + + + + + + maven-snapshot + http://xit.xit-nexus.com:8081/repository/maven-snapshots/ + + + + maven-release + http://xit.xit-nexus.com:8081/repository/maven-releases/ + + + + \ No newline at end of file diff --git a/src/main/java/cokr/xit/interfaces/smg/Petition.java b/src/main/java/cokr/xit/interfaces/smg/Petition.java new file mode 100644 index 0000000..319427b --- /dev/null +++ b/src/main/java/cokr/xit/interfaces/smg/Petition.java @@ -0,0 +1,765 @@ +package cokr.xit.interfaces.smg; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +import cokr.xit.base.file.FileInfo; +import cokr.xit.foundation.AbstractEntity; +import cokr.xit.foundation.Assert; +import cokr.xit.foundation.util.RandomNumber; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +/**국민 신문고 민원 정보 + * @author mjkhan + */ +@Getter +@Setter +@XmlRootElement(name = "dmndinfo") +@XmlAccessorType(XmlAccessType.FIELD) +public class Petition extends AbstractEntity { + /**인터페이스 키: 필수 + * PK : number(30) - YYYYMMDDHH24MISSFF+random(9) + */ + @XmlElement(name = "interface_seq_n") + private String interfaceSeqN; + + /**시스템 구분: 필수 + * char(88) + * EC010008 과태료시스템 + */ + @XmlElement(name = "sys_gubun_c") + private String sysGubunC; + + /**송신 기관 코드: 필수 + * varchar2(7) + * 1140100 / 신청기관코드 / 신청기관코드 + * ex)경기도 - 641000 + */ + @XmlElement(name = "anc_code_v") + private String ancCodeV; + + /**민원 구분: 필수 + * char(3) + * 140:민원이송(기관코드-신문고) / 180: 답변 / 140: 반송(기관코드-연계기관) + */ + @XmlElement(name = "peti_gubun_c") + private String petiGubunC; + + /**민원 기관 코드: 필수 + * varchar2(7) + * 최초 신청기관코드 그대로 사용(절대변경불가) + */ + @XmlElement(name = "peti_anc_code_v") + private String petiAncCodeV; + + /**민원 신청 번호: 필수 + * varchar2(16) + * 국민신문고에서 생성(국민신문고의 민원 번호), 최초 이송이첩시는 null값 임. + * (신문고에서 생성된 데이터가 있을 경우는 넣어줌) + */ + @XmlElement(name = "peti_no_c") + private String petiNoC; + + /**민원 접수 번호: 필수 + * varchar2(16) + * 국민신문고에서 생성(국민신문고의 접수 번호), 최초 이송이첩시는 null값 임. + * (신문고에서 생성된 데이터가 있을 경우는 넣어줌)" + */ + @XmlElement(name = "civil_no_c") + private String civilNoC; + + /**민원 신청인 명: 이관 / 반송시 필수 + * varchar2(128) + */ + @XmlElement(name = "peter_name_v") + private String peterNameV; + + /**민원 신청인 우편번호: 이관 / 반송시 필수 + * varchar2(7) + */ + @XmlElement(name = "zip_code_c") + private String zipCodeC; + + /**민원 신청인 주소: 이관 / 반송시 필수 + * varchar2(400) + */ + @XmlElement(name = "address_v") + private String addressV; + + /**민원 신청인 이메일 + * varchar2(64) + */ + @XmlElement(name = "email_v") + private String emailV; + + /**민원 신청인 핸드폰 번호 + * varchar2(20) + */ + @XmlElement(name = "cel_no_v") + private String celNoV; + + /**민원 신청인 전화 번호 + * varchar2(20) + */ + @XmlElement(name = "tel_no_v") + private String telNoV; + + /**민원 신청 제목: 이관 / 반송시 필수 + * varchar2(500) + */ + @XmlElement(name = "peti_title_v") + private String petiTitleV; + + /**민원 신청 내용: 이관 / 반송시 필수 + * clob + */ + @XmlElement(name = "peti_reason_l") + private String petiReasonL; + + /**민원 공개 여부: 이관 / 반송시 필수 + * char(1) + * Y = 공개, N = 비공개 (default N) + * Y로 수신 시에도 내부적용 시에는 비공개로 적용 요함(개인정보보호지침) + * 송신 시는 모두 N으로 송신 + */ + @XmlElement(name = "open_yn_c") + private String openYnC; + + /**민원 신청일: 이관 / 반송시 필수 + * date : YYYYMMDDHH24MISS + */ + @XmlElement(name = "peti_reg_d") + private String petiRegD; + + /**민원 신청 내용 첨부 여부: 이관시 필수 + * char(1) + * Y = 첨부, N = 미첨부(default) + */ + @XmlElement(name = "peti_reason_attach_yn_c") + private String petiReasonAttachYnC; + + /**민원 신청 첨부파일 크기: 이관시 필수 + * number(10) + */ + @XmlElement(name = "peti_file_size_n") + private String petiFileSizeN; + + //------------------------------------------------------------- + /**민원 신청 첨부파일명1 + * varchar2(2000) + */ + @XmlElement(name = "peti_file_path1_v") + private String petiFilePath1V; + + /**민원 신청 첨부파일명2 + * varchar2(2000) + */ + @XmlElement(name = "peti_file_path2_v") + private String petiFilePath2V; + + /**민원 신청 첨부파일명3 + * varchar2(2000) + */ + @XmlElement(name = "peti_file_path3_v") + private String petiFilePath3V; + + /**민원 신청 첨부파일명4 + * varchar2(2000) + */ + @XmlElement(name = "peti_file_path4_v") + private String petiFilePath4V; + + /**민원 신청 첨부파일명5 + * varchar2(2000) + */ + @XmlElement(name = "peti_file_path5_v") + private String petiFilePath5V; + //----------------------------------------------------------------------------- + + /**등록 일자: 필수 + * date + * 반영시에 sysdate(YYYYMMDDHH24MISS)로 생성 + */ + @XmlElement(name = "reg_d") + private String regD; + + /**송신 여부: 필수 + * char(1) + * 1:송신 / 2:수신 / 1:송신 + */ + @XmlElement(name = "send_yn_c") + private String sendYnC; + + /**송신 일자 + * date : YYYYMMDDHH24MISS + */ + @XmlElement(name = "send_d") + private String sendD; + + /**적용 일자: 필수 + * date + * interface DB->XML로 적용 시 sysdate(YYYYMMDDHH24MISS)로 생성 + */ + @XmlElement(name = "apply_d") + private String applyD; + + /**완료 구분: 필수 + * char(1) + * 적용완료:Y OR N (default:N , 각 기관의 실 민원 DB에 반영 후 Y로 변경) + */ + @XmlElement(name = "apply_gubun_c") + private String applyGubunC; + + //------------------------------------------------------------------------------------ + /**처리 구분1: 필수 + * varchar2(400) + * 0 / / 0 + */ + @XmlElement(name = "pcd_gubun_v") + private String pcdGubunV; + + /**처리 구분2: 필수 + * varchar2(400) + */ + @XmlElement(name = "pcd_gubun2_v") + private String pcdGubun2V; + + /**처리 구분3: 처리 결과시 필수 + * varchar2(400) + */ + @XmlElement(name = "pcd_gubun3_v") + private String pcdGubun3V; + /**xml 인터페이스 아이디: 필수 + * varchar2(10) + */ + @XmlElement(name = "ifid") + private String ifid; + + /**소스 기관 코드: 필수 + * varchar2(7) + * 해당 연계 기관 코드 + */ + @XmlElement(name = "srcorgcd") + private String srcorgcd; + + /**타겟 기관 코드: 필수 + * varchar2(7) + * 연계 기관에서 insert시 무조건 1140100 값을 넣어 준다 + */ + @XmlElement(name = "tgtorgcd") + private String tgtorgcd; + + @XmlElement(name = "apndfilinfo") + private ApndFileInfo appendFileInfo; + //------------------------------------------------------------------------------------- + + @XmlElement(name = "peti_path_gubun_c") + private String petiPathGubunC; + + /**처리 부서 코드: 결과 처리시 필수 + * varchar2(7) + */ + @XmlElement(name = "pcd_dept_v") + private String pcdDeptV; + + /**민원 처리 부서명: 결과 처리시 필수 + * varchar2(50) + */ + @XmlElement(name = "pcd_dept_nm_v") + private String pcdDeptNmV; + + /**민원 처리 담당자 명: 결과 처리시 필수 + * varchar2(50) + */ + @XmlElement(name = "duty_id_v") + private String dutyIdV; + + /**담당자 이메일: 결과 처리시 필수 + * varchar2(64) + */ + @XmlElement(name = "pcd_email_v") + private String pcdEmailV; + + /**담당자 전화 번호: 결과 처리시 필수 + * varchar2(20) + */ + @XmlElement(name = "pcd_tel_v") + private String pcdTelV; + + /**접수 일자 + * date + */ + @XmlElement(name = "anc_reg_d") + private String ancRegD; + + /**한마디 더 + * varchar2(4000) + */ + @XmlElement(name = "more_again_v") + private String moreAgainV; + + /**만족도 항목1 + * char(8) + */ + @XmlElement(name = "satisfy_c") + private String satisfyC; + + /**만족도 항목2 + * char(8) + */ + @XmlElement(name = "satisfy2_c") + private String satisfy2C; + + /**만족도 항목3 + * char(8) + */ + @XmlElement(name = "satisfy3_c") + private String satisfy3C; + + /**만족도 입력일 + * date + */ + @XmlElement(name = "satisfy_reg_d") + private String satisfyRegD; + + /**민원 실 처리 기관 코드: 처리 결과시 필수 + * varchar2(7) + * ex)경기도 6410000 + */ + @XmlElement(name = "pcd_anc_code_v") + private String pcdAncCodeV; + + /**민원 처리 기간 + * number(5) + */ + @XmlElement(name = "peti_proc_dur_n") + private String petiProcDurN; + + /**처리 예정일 + * date + */ + @XmlElement(name = "peti_end_d") + private String petiEndD; + + //---------------------------------------------------------------------------------------------------- + // 결과(응답) 처리 + //---------------------------------------------------------------------------------------------------- + /**민원 요지: 결과 처리시 필수 + * varchar2(512) + * 민원요지를 입력하면 민원제목대신 민원요지를 표출 + */ + @XmlElement(name = "civil_gist_v") + private String civilGistV; + + /**민원 처리 요약: 결과 처리시 필수 + * clob + * 처리를 요약하여 표시 + */ + @XmlElement(name = "civil_abstract_l") + private String civilAbstractL; + + /**민원 처리 결과: 결과 처리시 필수 + * clob + */ + @XmlElement(name = "pcd_rst_cont_l") + private String pcdRstContL; + + /**민원 처리 완료 일자: 결과 처리시 필수 + * varchar2(14) : YYYYMMDDHH24MISS + */ + @XmlElement(name = "do_reg_d") + private String doRegD; + + /**민원 처리 결과 첨부 여부: 결과 처리시 필수 + * char(1) + * Y = 첨부, N = 미첨부(default) + */ + @XmlElement(name = "pcd_rst_cont_attach_yn_c") + private String pcdRstContAttachYnC; + + /**민원 처리 첨부 파일 크기 + * number(10) + */ + @XmlElement(name = "pcd_file_size_n") + private String pcdFileSizeN; + + /** 민원 처리 첨부파일명 1 */ + @XmlTransient + private String pcdFilePath1V; + + /** 민원 처리 첨부파일명 2 */ + @XmlTransient + private String pcdFilePath2V; + + /** 민원 처리 첨부파일명 3 */ + @XmlTransient + private String pcdFilePath3V; + + /** 민원 처리 첨부파일명 4 */ + @XmlTransient + private String pcdFilePath4V; + + /** 민원 처리 첨부파일명 5 */ + @XmlTransient + private String pcdFilePath5V; + + /** 원본 파일 이름 */ + @XmlTransient + private String originalFilename; + + /** 첨부파일 저장경로1 */ + @XmlTransient + private String attachmentPath1; + + /** 첨부파일 저장경로2 */ + @XmlTransient + private String attachmentPath2; + + /** 첨부파일 저장경로3 */ + @XmlTransient + private String attachmentPath3; + + /** 첨부파일 저장경로4 */ + @XmlTransient + private String attachmentPath4; + + /** 첨부파일 저장경로5 */ + @XmlTransient + private String attachmentPath5; + + /**전송 인터페이스 키 + * number(30) - YYYYMMDDHH24MISS + 0000000 + random(9) + */ + @XmlTransient + private String sendInterfaceSeqN; + + /**전송 상태 + */ + @XmlTransient + private String sendStatus; + + /**전송 상태 메시지 + */ + @XmlTransient + private String sendStatusMsg; + + /* yyyy-MM-dd hh:mm:ss -> yyyyMMddhhmmss */ + private static String dateText(String str) { + if (str == null) return ""; + return str.replaceAll("[-: ]", ""); + } + + /**일시(yyyy-MM-dd hh:mm:ss) 필드들의 값을 숫자만으로 변환한다. + * @return 현재 Petition + */ + public Petition normalize() { + petiRegD = dateText(petiRegD); + petiEndD = dateText(petiEndD); + ancRegD = dateText(ancRegD); + regD = dateText(regD); + + return this; + } + + /**민원의 답변/회수를 전송할 파일을 만들 때 + * 전송 인터페이스 키를 파일의 인터페이스 키와 파일 이름으로 사용하기 위해 + * interfaceSeqN과 sendInterfaceSeqN의 값을 교환한다. + * @return 현재 Petition + */ + public Petition swapInterfaceSeqs() { + String tmp = interfaceSeqN; + interfaceSeqN = sendInterfaceSeqN; + sendInterfaceSeqN = tmp; + return this; + } + + /**민원의 답변/회수를 전송할 파일을 만들 때 + * + * 한다. + * @param now 일시(yyyyMMddhhmmss) + * @return 현재 Petition + */ + public Petition setNow(String now) { + setSendInterfaceSeqN(now + "0000000" + RandomNumber.get(9)); + setApplyGubunC("Y"); + setSendD(now); + setApplyD(now); + setSrcorgcd(ancCodeV); + setTgtorgcd(""); + setIfid(""); + return this; + } + + /**첨부파일 정보로 첨부파일 저장 경로를 설정한다. + * @param attachments 첨부파일 정보 + * @return 현재 Petition + */ + public Petition setAttachmentPaths(List attachments) { + for (int i = 0; i < attachments.size(); ++i) { + FileInfo attachment = attachments.get(i); + String path = attachment.getPath(); + switch (i + 1) { + case 1: attachmentPath1 = path; break; + case 2: attachmentPath2 = path; break; + case 3: attachmentPath3 = path; break; + case 4: attachmentPath4 = path; break; + case 5: attachmentPath5 = path; break; + default: break; + } + } + return this; + } + + /**전송 파일 이름을 반환한다. + * @return 전송 파일 이름(EPOUGB$ + 전송 인터페이스 순번 + .xml) + */ + public String sendFilename() { + return "EPOUGB$" + getSendInterfaceSeqN() + ".xml"; + } + + /**민원 수신 파일에서 읽은 첨부파일 정보 + * @author mjkhan + */ + @Getter + @Setter + @ToString + @XmlAccessorType(XmlAccessType.FIELD) + @XmlRootElement(name="apndfilinfo") + public static class ApndFileInfo implements Serializable { + private static final long serialVersionUID = 1L; + + /**민원 신청 첨부파일명1 + * varchar2(2000) + */ + @XmlElement(name = "peti_file_path1_v") + private String petiFilePath1V; + + /**민원 신청 첨부파일명2 + * varchar2(2000) + */ + @XmlElement(name = "peti_file_path2_v") + private String petiFilePath2V; + + /**민원 신청 첨부파일명3 + * varchar2(2000) + */ + @XmlElement(name = "peti_file_path3_v") + private String petiFilePath3V; + + /**민원 신청 첨부파일명4 + * varchar2(2000) + */ + @XmlElement(name = "peti_file_path4_v") + private String petiFilePath4V; + + /**민원 신청 첨부파일명5 + * varchar2(2000) + */ + @XmlElement(name = "peti_file_path5_v") + private String petiFilePath5V; + + @XmlElement(name = "apndfilcount") + private String apndfilcount; + + @XmlElement(name = "apndfilcont1") + private String apndfilcont1; + + @XmlElement(name = "apndfilcont2") + private String apndfilcont2; + + @XmlElement(name = "apndfilcont3") + private String apndfilcont3; + + @XmlElement(name = "apndfilcont4") + private String apndfilcont4; + + @XmlElement(name = "apndfilcont5") + private String apndfilcont5; + + /**민원 수신 파일에서 첨부파일 이름과 데이터를 읽어서 파일정보를 만들어 반환한다. + * @param infoType 관련 정보 유형 + * @param infoKey 관련 정보 키 + * @return 파일정보 + */ + public List getFileInfo(String infoType, String infoKey) { + int count = Integer.valueOf(apndfilcount); + if (count < 1) + return Collections.emptyList(); + + FileInfo.Relation relation = new FileInfo.Relation() + .setInfoType(infoType) + .setInfoKey(infoKey); + ArrayList dataHolders = new ArrayList<>(); + + for (int i = 1; i <= 5; ++i) { + String filename = ""; + String filecontent = ""; + switch (i) { + case 1: + filename = petiFilePath1V; + filecontent = apndfilcont1; + break; + case 2: + filename = petiFilePath2V; + filecontent = apndfilcont2; + break; + case 3: + filename = petiFilePath3V; + filecontent = apndfilcont3; + break; + case 4: + filename = petiFilePath4V; + filecontent = apndfilcont4; + break; + case 5: + filename = petiFilePath5V; + filecontent = apndfilcont5; + break; + } + FileInfo.DataHolder dataHolder = getDataHolder(relation, filename, filecontent); + if (dataHolder != null) + dataHolders.add(dataHolder); + } + if (count != dataHolders.size()) + throw new RuntimeException("첨부파일 수가 다릅니다."); + return new FileInfo.Factory().createFileInfos(dataHolders); + } + + private FileInfo.DataHolder getDataHolder(FileInfo.Relation relation, String filename, String filecontent) { + return !Assert.isEmpty(filename) && !Assert.isEmpty(filecontent) ? + new FileInfo.DataHolder(relation, filename, filecontent) : null; + } + } + + /**민원 수신 파일의 제목과 내용에서 단속 정보를 추출하는 클래스 + * @author mjkhan + */ + public static class Violation { + private static RegexPattern + vehicleNoDatetime = new RegexPattern("(\\*\\s\\(\\d.*\\/\\d.*\\)\\s[GCS]:\\s)(.*)(\\s차량번호\\s:\\s)(.*)"), + coordinates = new RegexPattern("(\\*\\s발생지역\\s위도:)(.*)(\\s경도:)(.*)"), + location = new RegexPattern("(\\[사고발생지역\\])(.*)"), + description = new RegexPattern("(\\(.*\\))(.*)(\\s신고입니다.*)"), + entryType = new RegexPattern("(\\[민원 유입 경로\\]:\\s)(.*)"); + + private String reason; + + /**새 Violation을(를) 생성한다. + * @param reason 민원 수신 파일의 내용 + */ + public Violation (String reason) { + this.reason = reason; + } + + /**민원 수신 파일의 내용에서 단속 차량, 단속 일시 정보를 추출한다. + * @return 단속 차량, 단속 일시 + *
  • datetime: 단속 일시
  • + *
  • vehicleNo: 단속 차량 번호
  • + *
+ */ + public List> getVehicleNoDatetimes() { + Matcher matcher = vehicleNoDatetime.matcher(reason); + ArrayList> list = new ArrayList<>(); + while (matcher.find()) { + String[] found = matcher.group() + .replaceAll(vehicleNoDatetime.regex, "$2,$4") + .replaceAll("\\(위·변조 없음\\)", "") + .replaceAll("[: /]", "") + .split(","); + + HashMap info = new HashMap<>(); + info.put("datetime", found[0]); + info.put("vehicleNo", found.length > 1 ? found[1] : ""); + list.add(info); + } + return list; + } + + /**민원 수신 파일의 내용에서 단속 위치 정보를 추출한다. + * @return 단속 위치 + *
  • latitude: 위도
  • + *
  • longitude: 경도
  • + *
+ */ + public Map getCoordinates() { + Matcher matcher = coordinates.matcher(reason); + HashMap info = new HashMap<>(); + while (matcher.find()) { + String[] found = matcher.group() + .replaceAll(coordinates.regex, "$2,$4") + .split(","); + info.put("latitude", found[0]); + info.put("longitude", found[1]); + } + return info; + } + + /**민원 수신 파일의 내용에서 단속 지역 정보를 추출한다. + * @return 단속 지역 정보 + */ + public String getLocation() { + Matcher matcher = location.matcher(reason); + String found = ""; + while (matcher.find()) { + found = matcher.group().replaceAll(location.regex, "$2"); + } + return found; + } + + /**민원 수신 파일의 제목에서 사고 내역 정보를 추출한다. + * @param title 민원 수신 파일의 제목 + * @return 사고 내역 정보 + */ + public String getDescription(String title) { + Matcher matcher = description.matcher(title); + String found = ""; + while (matcher.find()) { + found = matcher.group().replaceAll(description.regex, "$2"); + } + return found; + } + + /**민원 수신 파일의 내역에서 유입 경로 정보를 추출한다. + * @return 유입 경로 정보 + */ + public String getEntryType() { + Matcher matcher = entryType.matcher(reason); + String found = ""; + while (matcher.find()) { + found = matcher.group().replaceAll(entryType.regex, "$2"); + } + return found; + } + } + + private static class RegexPattern { + private String regex; + private Pattern pattern; + + private RegexPattern(String regex) { + pattern = Pattern.compile(this.regex = regex); + } + + private Matcher matcher(String str) { + return pattern.matcher(str); + } + } + +} \ No newline at end of file diff --git a/src/main/java/cokr/xit/interfaces/smg/dao/SmgMapper.java b/src/main/java/cokr/xit/interfaces/smg/dao/SmgMapper.java new file mode 100644 index 0000000..d274ddc --- /dev/null +++ b/src/main/java/cokr/xit/interfaces/smg/dao/SmgMapper.java @@ -0,0 +1,110 @@ +package cokr.xit.interfaces.smg.dao; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.egovframe.rte.psl.dataaccess.mapper.Mapper; + +import cokr.xit.foundation.component.AbstractMapper; +import cokr.xit.interfaces.smg.Petition; + +/**국민 신문고 수신 민원 파일의 연계를 위한 DAO + * @author mjkhan + */ +@Mapper("smgMapper") +public interface SmgMapper extends AbstractMapper { + /**지정하는 인터페이스 키의 수신 민원 목록을 반환한다. + * @param interfaceSequences 인터페이스 키 + * @return 수신 민원 목록 + */ + List selectPetitions(List interfaceSequences); + + /**지정하는 인터페이스 키의 수신 민원 목록을 반환한다. + * @param interfaceSequences 인터페이스 키 + * @return 수신 민원 목록 + */ + default List selectPetitions(String... interfaceSequences) { + return selectPetitions(!isEmpty(interfaceSequences) ? Arrays.asList(interfaceSequences) : null); + } + + /**민원 정보를 등록한다. + * @param petition 민원 정보 + * @return 저장된 정보 수 + */ + int insertPetition(Petition petition); + + /**민원의 첨부파일 정보를 등록한다. + * @param petition 민원 정보 + * @return 저장된 정보 수 + */ + int insertFile(Petition petition); + + /**수신 민원 정보와 민원의 첨부 파일 정보를 등록한다. + * @param petition 수신 민원 정보 + * @return 저장된 정보 수 + */ + default int create(Petition petition) { + int affected = insertPetition(petition); + insertFile(petition); + return affected; + } + + /**민원의 답변/반송 목록을 반환한다. + * 인터페이스 키를 지정하면 해당하는 민원의 답변/반송 목록을 반환한다. + * 인터페이스 키를 지정하지 않으면 전송 대상이 되는 답변/반송 목록을 반환한다. + * @param interfaceSequences 민원의 인터페이스 키 + * @return 민원의 답변/반송 목록 + */ + List selectReplies(List interfaceSequences); + + /**인터페이스 키를 지정하면 해당하는 민원의 답변/반송 목록을 반환한다.
+ * 인터페이스 키를 지정하지 않으면 전송 대상이 되는 답변/반송 목록을 반환한다. + * @param interfaceSequences 민원의 인터페이스 키 + * @return 민원의 답변/반송 목록 + */ + default List selectReplies(String... interfaceSequences) { + return selectReplies(!isEmpty(interfaceSequences) ? Arrays.asList(interfaceSequences) : null); + } + + /**민원의 답변/반송 정보를 등록한다. + * @param params 파라미터 + *
  • reply - 답변/반송 정보
  • + *
  • currentUser - 현재 사용자 정보
  • + *
+ * @return 저장된 정보수 + */ + int insertReply(Map params); + + /**민원의 답변/반송 정보를 등록한다. + * @param reply 답변/반송 정보 + * @return 저장된 정보수 + */ + default int createReply(Petition reply) { + return insertReply( + params().set("reply", reply) + ); + } + + /**민원 답변/반송 파일 생성 후 완료/전송 상태를 업데이트 한다. + * @param params 파라미터 + *
  • replies - 답변/반송 정보 목록
  • + *
  • now - 생성 일시(yyyyMMddhhmmss)
  • + *
+ * @return 저장된 정보 수 + */ + int updateSendStatus(Map params); + + /**민원 답변/반송 파일 생성 후 완료/전송 상태를 업데이트 한다. + * @param replies 답변/반송 정보 목록 + * @param now 생성 일시(yyyyMMddhhmmss) + * @return 저장된 정보 수 + */ + default int updateSendStatus(List replies, String now) { + if (isEmpty(replies)) return 0; + return updateSendStatus(params() + .set("replies", replies) + .set("now", now) + ); + } +} \ No newline at end of file diff --git a/src/main/java/cokr/xit/interfaces/smg/dao/package-info.java b/src/main/java/cokr/xit/interfaces/smg/dao/package-info.java new file mode 100644 index 0000000..c2be5ae --- /dev/null +++ b/src/main/java/cokr/xit/interfaces/smg/dao/package-info.java @@ -0,0 +1,3 @@ +/**국민 신문고와의 파일 연계 실행을 위한 DAO + */ +package cokr.xit.interfaces.smg.dao; \ No newline at end of file diff --git a/src/main/java/cokr/xit/interfaces/smg/package-info.java b/src/main/java/cokr/xit/interfaces/smg/package-info.java new file mode 100644 index 0000000..615bd8a --- /dev/null +++ b/src/main/java/cokr/xit/interfaces/smg/package-info.java @@ -0,0 +1,17 @@ +/**국민 신문고와의 파일 연계를 제공한다. + *

국민 신문고와 연계하는 파일로는 + *

  • 수신 - 단속 민원
  • + *
  • 전송 - 단속 민원의 답변/반송
  • + *
+ * 등이 있다. + *

수신한 민원 파일은 내용을 파싱하여 데이터베이스의 다음 테이블에 저장한다. + *

  • 민원 내용 - TB_ESB_INTERFACE
  • + *
  • 민원 첨부파일 이름 및 내용 - TB_ESB_INTERFACE_FILE
  • + *
  • 첨부파일 저장 경로 - TB_FILE
  • + *
+ * 전송할 민원의 답변/반송 정보는 데이터베이스의 다음 테이블에 저장한다. + *
  • 전송 민원 답변/반송 - TB_ESB_INTERFACE_TRSM
  • + *
+ * 파일의 수신과 전송을 위한 설정은 'conf/file-job.conf' 파일에 지정한다. + */ +package cokr.xit.interfaces.smg; \ No newline at end of file diff --git a/src/main/java/cokr/xit/interfaces/smg/service/SmgService.java b/src/main/java/cokr/xit/interfaces/smg/service/SmgService.java new file mode 100644 index 0000000..4b8963e --- /dev/null +++ b/src/main/java/cokr/xit/interfaces/smg/service/SmgService.java @@ -0,0 +1,48 @@ +package cokr.xit.interfaces.smg.service; + +import java.util.List; + +import cokr.xit.interfaces.smg.Petition; + +/**국민 신문고 민원 연계 서비스 인터페이스로 + *
  • {@link #receivePetitions() 수신 민원의 등록}
  • + *
  • {@link #getPetitions(List) 등록된 민원의 조회}
  • + *
  • {@link #sendReplies() 민원의 답변/회수 전송 처리}
  • + *
  • {@link #createReply(Petition) 답변/회수 정보 등록}
  • + *
  • {@link #getReplies(List) 답변/회수 정보 조회}
  • + *
+ * 등의 서비스를 제공한다. + * @author mjkhan + */ +public interface SmgService { + /**지정한 인터페이스 키에 해당하는 국민 신문고에서 수신한 민원 목록을 반환한다. + * @param interfaceSequences 수신 민원 인터페이스 키 + * @return 국민 신문고에서 수신한 민원 목록 + */ + List getPetitions(List interfaceSequences); + + /**국민 신문고에서 수신한 민원 파일을 읽어서 민원 정보와 첨부 파일을 등록한다. + * @return 수신한 민원의 인터페이스 키 목록 + */ + List receivePetitions(); + + /**지정한 인터페이스 키에 해당하는 민원의 답변/회수 목록을 반환한다. + * @param interfaceSequences 수신 민원 인터페이스 키 + * @return 민원의 답변/회수 목록 + */ + List getReplies(List interfaceSequences); + + /**민원의 답변/회수 정보를 등록한다. + * @param reply 답변/회수 정보 + * @return 등록 여부 + *
  • 등록됐으면 true
  • + *
  • 그렇지 않으면 false
  • + *
+ */ + boolean createReply(Petition reply); + + /**수신 민원의 답변/회수 파일을 생성해 전송 처리한다. + * @return 처리한 수신 민원의 인터페이스 키 목록 + */ + List sendReplies(); +} \ No newline at end of file diff --git a/src/main/java/cokr/xit/interfaces/smg/service/bean/SmgInBean.java b/src/main/java/cokr/xit/interfaces/smg/service/bean/SmgInBean.java new file mode 100644 index 0000000..d2ce163 --- /dev/null +++ b/src/main/java/cokr/xit/interfaces/smg/service/bean/SmgInBean.java @@ -0,0 +1,161 @@ +package cokr.xit.interfaces.smg.service.bean; + +import java.io.File; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import javax.annotation.Resource; + +import org.springframework.stereotype.Component; + +import cokr.xit.base.file.FileInfo; +import cokr.xit.base.file.service.bean.FileBean; +import cokr.xit.foundation.data.XML; +import cokr.xit.foundation.web.Http; +import cokr.xit.interfaces.filejob.service.bean.FileJobBean; +import cokr.xit.interfaces.smg.Petition; +import cokr.xit.interfaces.smg.dao.SmgMapper; + +/**국민 신문고 수신 민원 파일 작업 Bean + * @author mjkhan + */ +@Component("smgInBean") +public class SmgInBean extends FileJobBean { + @Resource(name = "smgMapper") + private SmgMapper smgMapper; + @Resource(name = "fileBean") + private FileBean fileBean; + + private XML xml = new XML(config("charset")); + + /**국민 신문고 수신 민원 작업 이름(smg-in)을 반환한다. + */ + @Override + public String jobName() { + return "smg-in"; + } + + /**지정한 인터페이스 키의 민원 목록을 반환한다. + * @param interfaceSequences 민원의 인터페이스 키 + * @return 인터페이스 목록 + */ + public List getPetitions(List interfaceSequences) { + return smgMapper.selectPetitions(interfaceSequences); + } + + /**지정한 인터페이스 키의 민원 목록을 반환한다. + * @param interfaceSequences 민원의 인터페이스 키 + * @return 인터페이스 목록 + */ + public List getPetitions(String... interfaceSequences) { + return smgMapper.selectPetitions(interfaceSequences); + } + + /**수신한 민원 파일을 읽어 + *
  • 민원 정보를 데이터베이스에 등록
  • + *
  • 첨부파일을 추출하여 저장
  • + *
  • 파일 정보를 데이터베이스에 등록
  • + *
  • {@link #alert(List) 업무 시스템에 수신 민원 등록을 통보}한다.
  • + *
+ * @return + */ + public List receivePetitions() { + List parsed = parse(); + if (parsed.isEmpty()) return Collections.emptyList(); + + Map> received = parsed.stream() + .collect(Collectors.groupingBy(status -> status.isSuccess())); + + List fileStatus = received.get(true); + List interfaceSequences = processSuccess(fileStatus); + + alert(interfaceSequences); + + if (!isEmpty(fileStatus)) + move( + fileStatus.stream().map(FileStatus::getPath).collect(Collectors.toList()), + successDir() + ); + + fileStatus = received.get(false); + if (!isEmpty(fileStatus)) + move( + fileStatus.stream().map(FileStatus::getPath).collect(Collectors.toList()), + failDir() + ); + + return interfaceSequences; + } + + private List parse() { + String infoType = config("infoType"); + List paths = getReceivedFilePaths(); + return paths.stream() + .map(path -> parse(infoType, path)) + .collect(Collectors.toList()); + } + + private FileStatus parse(String infoType, Path path) { + FileStatus status = new FileStatus().setPath(path); + try { + File file = path.toFile(); + Petition petition = xml.parse(file, Petition.class); + petition.setOriginalFilename(file.getName()); + + List attachments = petition.getAppendFileInfo().getFileInfo(infoType, petition.getInterfaceSeqN()); + + return status + .set("petition", petition) + .set("attachments", attachments); + } catch (Exception e) { + return status.setCause(e); + } + } + + private List processSuccess(List success) { + if (isEmpty(success)) return Collections.emptyList(); + + String registID = jobName(); + + ArrayList interfaceSequences = new ArrayList<>(); + + success.forEach(status -> { + List attachments = status.get("attachments"); + fileBean.create(attachments); + + Petition petition = status.get("petition"); + petition.setCreatedBy(registID); + + petition.setAttachmentPaths(attachments); + + smgMapper.create(petition); + interfaceSequences.add(petition.getInterfaceSeqN()); + + }); + + return interfaceSequences; + } + + /**수신 민원이 등록됐음을 업무 시스템에 http로 통보한다. + *
  • 통보 방법: http POST 방식
  • + *
  • 파라미터: "interfaceSequences" - 인터페이스 키 배열
  • + *
+ * 작업 설정의 "alert" 항목에 통보받을 url이 지정됐을 경우에만 실행한다. + * @param interfaceSequences 등록한 인터페이스 키 목록 + */ + protected void alert(List interfaceSequences) { + if (isEmpty(interfaceSequences)) return; + + String alert = config("alert"); + if (isEmpty(alert)) return; + + new Http().post(new Http.Conf() + .url(alert) + .param("interfaceSequences", String.join(",", interfaceSequences)) + ); + } +} \ No newline at end of file diff --git a/src/main/java/cokr/xit/interfaces/smg/service/bean/SmgOutBean.java b/src/main/java/cokr/xit/interfaces/smg/service/bean/SmgOutBean.java new file mode 100644 index 0000000..351ecaa --- /dev/null +++ b/src/main/java/cokr/xit/interfaces/smg/service/bean/SmgOutBean.java @@ -0,0 +1,168 @@ +package cokr.xit.interfaces.smg.service.bean; + +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +import javax.annotation.Resource; + +import org.springframework.stereotype.Component; + +import cokr.xit.foundation.data.XML; +import cokr.xit.foundation.web.Http; +import cokr.xit.interfaces.filejob.service.bean.FileJobBean; +import cokr.xit.interfaces.smg.Petition; +import cokr.xit.interfaces.smg.dao.SmgMapper; + +/**민원의 답변/반송 파일 작업 Bean + * @author mjkhan + */ +@Component("smgOutBean") +public class SmgOutBean extends FileJobBean { + private static final SimpleDateFormat datetimeFormat = new SimpleDateFormat("yyyyMMddhhmmss"); + + @Resource(name = "smgMapper") + private SmgMapper smgMapper; + private XML xml = new XML(config("charset")); + + /**국민 신문고 민원 답변/반송 파일 작업 이름(smg-out)을 반환한다. + */ + @Override + public String jobName() { + return "smg-out"; + } + + /**지정하는 인터페이스 키의 민원의 답변/반송 목록을 반환한다. + * @param interfaceSequences 인터페이스 키 목록 + * @return 민원의 답변/반송 목록 + */ + public List getReplies(List interfaceSequences) { + return !isEmpty(interfaceSequences) ? smgMapper.selectReplies(interfaceSequences) : Collections.emptyList(); + } + + /**민원의 답변/반송을 등록한다. + * @param reply 민원의 답변/반송 + * @return 등록 여부 + *
  • 등록됐으면 true
  • + *
  • 그렇지 않으면 false
  • + *
+ */ + public boolean createReply(Petition reply) { + if (!getReplies(Arrays.asList(reply.getInterfaceSeqN())).isEmpty()) + throw applicationException(null).setMessage(message("duplicate.object", "답변/반송")); + + return smgMapper.createReply(reply) > 0; + } + + /**민원의 답변/반송 파일을 생성하기 위해 + *
  • 데이터베이스에서 전송 대상 답변/반송 정보들 조회
  • + *
  • 조회 결과로 전송 파일을 작업 디렉토리에 생성
  • + *
  • 데이터베이스의 답변/반송 정보의 상태를 완료로 수정
  • + *
  • 생성한 전송 파일을 전송 디렉토리로 이동
  • + *
  • {@link #alert(List) 업무 시스템에 답변/반송 파일을 생성했음을 통보}
  • + *
+ * 하고 답변/반송하는 민원의 인터페이스 키를 반환한다. + * @return 답변/반송 파일을 생성한 민원 정보의 인터페이스 키들의 목록 + */ + public List sendReplies() { + List replies = smgMapper.selectReplies(); + if (replies.isEmpty()) return Collections.emptyList(); + + String now = datetimeFormat.format(new Date()); + String dir = sendWorkingDir(); + mkdirs(dir); + + List processed = replies.stream() + .map(write(dir, now)) + .collect(Collectors.toList()); + + processed.forEach(status -> { + boolean success = status.isSuccess(); + Petition reply = status.get("reply"); + + reply.setSendStatus(success ? "Y" : "N"); + reply.setSendStatusMsg(success ? "전송 성공" : "전송 실패"); + reply.setApplyGubunC(success ? "Y" : "N"); + reply.setSendD(success ? now : null); + reply.setApplyD(success ? now : null); + }); + + smgMapper.updateSendStatus( + processed.stream() + .map(status -> (Petition)status.get("reply")) + .collect(Collectors.toList()), + now + ); + + List paths = processed.stream() + .filter(FileStatus::isSuccess) + .map(FileStatus::getPath) + .collect(Collectors.toList()); + + move(paths, sendDir()); + + alert(replies); + + return replies.stream() + .map(reply -> reply.getInterfaceSeqN()) + .collect(Collectors.toList()); + } + + private Function write(String dir, String now) { + return reply -> { + reply.setNow(now); + + Path path = Paths.get(dir, reply.sendFilename()); + FileStatus status = new FileStatus() + .setPath(path) + .set("reply", reply); + try { + File file = path.toFile(); + xml.write(reply.swapInterfaceSeqs(), file); + return status; + } catch (Exception e) { + return status.setCause(e); + } finally { + reply.swapInterfaceSeqs(); + } + }; + } + + /**수신 민원의 답변/반송 파일이 생성됐음을 업무 시스템에 http로 통보한다. + *
  • 통보 방법: http POST 방식
  • + *
  • 파라미터 + *
    • "success" - 전송 파일을 생성한 민원의 인터페이스 키 배열
    • + *
    • "fail" - 전송 파일을 만들지 못한 민원의 인터페이스 키 배열
    • + *
    + *
  • + *
+ * 작업 설정의 "alert" 항목에 통보받을 url이 지정됐을 경우에만 실행한다. + * @param replies 민원의 답변/반송 정보 목록 + */ + protected void alert(List replies) { + if (isEmpty(replies)) return; + + String alert = config("alert"); + if (isEmpty(alert)) return; + + Map> processed = replies.stream().collect(Collectors.groupingBy(Petition::getSendStatus)); + List list = processed.get("Y"); + String success = list != null ? list.stream().map(Petition::getInterfaceSeqN).collect(Collectors.joining(",")) : ""; + list = processed.get("N"); + String fail = list != null ? list.stream().map(Petition::getInterfaceSeqN).collect(Collectors.joining(",")) : ""; + + new Http().post(new Http.Conf() + .url(alert) + .param("success", success) + .param("fail", fail) + ); + } +} \ No newline at end of file diff --git a/src/main/java/cokr/xit/interfaces/smg/service/bean/SmgServiceBean.java b/src/main/java/cokr/xit/interfaces/smg/service/bean/SmgServiceBean.java new file mode 100644 index 0000000..666cc04 --- /dev/null +++ b/src/main/java/cokr/xit/interfaces/smg/service/bean/SmgServiceBean.java @@ -0,0 +1,51 @@ +package cokr.xit.interfaces.smg.service.bean; + +import java.util.List; + +import javax.annotation.Resource; + +import org.springframework.stereotype.Service; + +import cokr.xit.interfaces.filejob.service.bean.FileJobServiceBean; +import cokr.xit.interfaces.smg.Petition; +import cokr.xit.interfaces.smg.service.SmgService; + +/**국민 신문고 민원 연계 서비스의 구현체 + *
  • 민원 수신은 {@link SmgInBean}
  • + *
  • 민원 답변/회수는 {@link SmgOutBean}
  • + *
+ * 이 처리한다. + * @author mjkhan + */ +@Service("smgService") +public class SmgServiceBean extends FileJobServiceBean implements SmgService { + @Resource(name = "smgInBean") + private SmgInBean smgIn; + @Resource(name = "smgOutBean") + private SmgOutBean smgOut; + + @Override + public List getPetitions(List interfaceSequences) { + return smgIn.getPetitions(interfaceSequences); + } + + @Override + public List receivePetitions() { + return execute(smgIn, smgIn::receivePetitions); + } + + @Override + public List getReplies(List interfaceSequences) { + return smgOut.getReplies(interfaceSequences); + } + + @Override + public boolean createReply(Petition reply) { + return smgOut.createReply(reply); + } + + @Override + public List sendReplies() { + return execute(smgOut, smgOut::sendReplies); + } +} \ No newline at end of file diff --git a/src/main/java/cokr/xit/interfaces/smg/service/bean/package-info.java b/src/main/java/cokr/xit/interfaces/smg/service/bean/package-info.java new file mode 100644 index 0000000..2db8ac8 --- /dev/null +++ b/src/main/java/cokr/xit/interfaces/smg/service/bean/package-info.java @@ -0,0 +1,3 @@ +/**국민 신문고와의 파일 연계 서비스 구현을 위한 클래스 정의 + */ +package cokr.xit.interfaces.smg.service.bean; \ No newline at end of file diff --git a/src/main/java/cokr/xit/interfaces/smg/service/package-info.java b/src/main/java/cokr/xit/interfaces/smg/service/package-info.java new file mode 100644 index 0000000..bcfd710 --- /dev/null +++ b/src/main/java/cokr/xit/interfaces/smg/service/package-info.java @@ -0,0 +1,3 @@ +/**국민 신문고와의 파일 연계 서비스 인터페이스 + */ +package cokr.xit.interfaces.smg.service; \ No newline at end of file diff --git a/src/main/java/cokr/xit/interfaces/smg/web/SmgController.java b/src/main/java/cokr/xit/interfaces/smg/web/SmgController.java new file mode 100644 index 0000000..2913285 --- /dev/null +++ b/src/main/java/cokr/xit/interfaces/smg/web/SmgController.java @@ -0,0 +1,56 @@ +package cokr.xit.interfaces.smg.web; + +import javax.annotation.Resource; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.servlet.ModelAndView; + +import cokr.xit.foundation.web.AbstractController; +import cokr.xit.interfaces.smg.service.SmgService; + +/**파일 작업 완료 후 업무 시스템 통보를 받는 컨트롤러 + * @author mjkhan + */ +@Controller +@RequestMapping(value = "/api/smg", name = "국민 신문고 민원") +public class SmgController extends AbstractController { + /** 국민 신문고 파일 연계 서비스 */ + @Resource(name = "smgService") + protected SmgService smgService; + + /**국민 신문고에서 받은 민원을 등록했음을 통보한다. + * @param interfaceSequences 민원의 인터페이스 키 목록 + * @return jsonView + *
  • received - 통보 수신 여부(true || false)
  • + *
  • saved - 저장 여부(true || false)
  • + *
+ */ + @PostMapping(value = "/petition/receive.do", name = "국민 신문고 민원 수신") + public ModelAndView receivePetitions(String[] interfaceSequences) { + log().debug("interfaceSequences received: {}", String.join(", ", interfaceSequences)); + + return new ModelAndView("jsonView") + .addObject("received", !isEmpty(interfaceSequences)) + .addObject("saved", true); + } + + /**국민 신문고에 전송할 민원 답변/반송 파일을 생성했음을 통보한다. + * @param success 파일을 생성한 민원의 인터페이스 키 + * @param fail 파일을 생성하지 못한 민원의 인터페이스 키 + * @return jsonView + *
  • received - 통보 수신 여부(true || false)
  • + *
  • saved - 저장 여부(true || false)
  • + *
+ */ + @PostMapping(value = "/petition/reply.do", name = "국민 신문고 민원 답변/반송 생성") + public ModelAndView sendReplies(String[] success, String[] fail) { + log().debug("success: {}", String.join(", ", success)); + log().debug("fail: {}", String.join(", ", fail)); + + return new ModelAndView("jsonView") + .addObject("received", !isEmpty(success) || !isEmpty(fail)) + .addObject("saved", true); + } +} \ No newline at end of file diff --git a/src/main/java/cokr/xit/interfaces/smg/web/package-info.java b/src/main/java/cokr/xit/interfaces/smg/web/package-info.java new file mode 100644 index 0000000..dc51bc3 --- /dev/null +++ b/src/main/java/cokr/xit/interfaces/smg/web/package-info.java @@ -0,0 +1,3 @@ +/**국민 신문고와의 파일 연계 작업 후 업무 시스템 통보 + */ +package cokr.xit.interfaces.smg.web; \ No newline at end of file diff --git a/src/main/sql/xit-smg.sql b/src/main/sql/xit-smg.sql new file mode 100644 index 0000000..57cf74d --- /dev/null +++ b/src/main/sql/xit-smg.sql @@ -0,0 +1,111 @@ +CREATE OR REPLACE TABLE tb_esb_interface ( + INTERFACE_SEQ_N VARCHAR(30) NOT NULL COMMENT '인터페이스 키', + SYS_GUBUN_C VARCHAR(8) NULL DEFAULT NULL COMMENT '시스템 구분', + ANC_CODE_V VARCHAR(7) NULL DEFAULT NULL COMMENT '기관 코드', + PETI_GUBUN_C VARCHAR(3) NULL DEFAULT NULL COMMENT '민원 구분', + PETI_ANC_CODE_V VARCHAR(7) NULL DEFAULT NULL COMMENT '민원 기관 코드', + PETI_NO_C VARCHAR(16) NULL DEFAULT NULL COMMENT '민원 신청 번호', + CIVIL_NO_C VARCHAR(16) NULL DEFAULT NULL COMMENT '민원 접수 번호', + PETER_NAME_V VARCHAR(128) NULL DEFAULT NULL COMMENT '민원 신청인 명', + ZIP_CODE_C VARCHAR(7) NULL DEFAULT NULL COMMENT '민원 신청인 우편번호', + ADDRESS_V VARCHAR(400) NULL DEFAULT NULL COMMENT '민원 신청인 주소', + EMAIL_V VARCHAR(64) NULL DEFAULT NULL COMMENT '민원 신청인 이메일', + CEL_NO_V VARCHAR(20) NULL DEFAULT NULL COMMENT '민원 신청인 핸드폰번호', + TEL_NO_V VARCHAR(20) NULL DEFAULT NULL COMMENT '민원 신청인 전화번호', + PETI_TITLE_V VARCHAR(500) NULL DEFAULT NULL COMMENT '민원 신청 제목', + PETI_REASON_L VARCHAR(4000) NULL DEFAULT NULL COMMENT '민원 신청 내용', + OPEN_YN_C VARCHAR(1) NULL DEFAULT NULL COMMENT '민원 공개 여부', + PETI_REG_D VARCHAR(30) NULL DEFAULT NULL COMMENT '민원 신청 일자', + PETI_REASON_ATTACH_YN_C VARCHAR(1) NULL DEFAULT NULL COMMENT '민원 신청 내용 첨부 여부', + CIVIL_GIST_V VARCHAR(512) NULL DEFAULT NULL COMMENT '민원 요지', + CIVIL_ABSTRACT_L VARCHAR(4000) NULL DEFAULT NULL COMMENT '민원 처리 요약', + PCD_DEPT_V VARCHAR(7) NULL DEFAULT NULL COMMENT '처리 부서 코드', + PCD_DEPT_NM_V VARCHAR(50) NULL DEFAULT NULL COMMENT '민원 처리 부서명', + DUTY_ID_V VARCHAR(50) NULL DEFAULT NULL COMMENT '민원 처리 담당자 명', + PCD_EMAIL_V VARCHAR(64) NULL DEFAULT NULL COMMENT '담당자 이메일', + PCD_TEL_V VARCHAR(20) NULL DEFAULT NULL COMMENT '담당자 전화번호', + PCD_RST_CONT_L VARCHAR(4000) NULL DEFAULT NULL COMMENT '민원 처리 결과', + DO_REG_D VARCHAR(30) NULL DEFAULT NULL COMMENT '민원 처리 완료 일자', + PCD_RST_CONT_ATTACH_YN_C VARCHAR(1) NULL DEFAULT NULL COMMENT '민원 처리 결과 첨부 여부', + PCD_ANC_CODE_V VARCHAR(7) NULL DEFAULT NULL COMMENT '민원 실 처리 기관 코드', + PETI_PROC_DUR_N INT(5) NULL DEFAULT NULL COMMENT '민원 처리 기간', + PETI_END_D VARCHAR(30) NULL DEFAULT NULL COMMENT '처리 예정 일자', + ANC_REG_D VARCHAR(30) NULL DEFAULT NULL COMMENT '접수 일자', + MORE_AGAIN_V VARCHAR(1000) NULL DEFAULT NULL COMMENT '한마디더', + SATISFY_C VARCHAR(8) NULL DEFAULT NULL COMMENT '만족도 항목1', + SATISFY2_C VARCHAR(8) NULL DEFAULT NULL COMMENT '만족도 항목2', + SATISFY3_C VARCHAR(8) NULL DEFAULT NULL COMMENT '만족도 항목3', + SATISFY_REG_D VARCHAR(30) NULL DEFAULT NULL COMMENT '만족도 입력일', + REG_D VARCHAR(30) NULL DEFAULT NULL COMMENT '등록 일자', + SEND_YN_C VARCHAR(1) NULL DEFAULT NULL COMMENT '송신 여부', + SEND_D VARCHAR(30) NULL DEFAULT NULL COMMENT '송신 일자', + APPLY_D VARCHAR(30) NULL DEFAULT NULL COMMENT '적용 일자', + APPLY_GUBUN_C VARCHAR(1) NULL DEFAULT NULL COMMENT '완료 구분', + PCD_GUBUN_V VARCHAR(100) NULL DEFAULT NULL COMMENT '처리 구분1', + PCD_GUBUN2_V VARCHAR(100) NULL DEFAULT NULL COMMENT '처리 구분2', + PCD_GUBUN3_V VARCHAR(100) NULL DEFAULT NULL COMMENT '처리 구분3', + PETI_PATH_GUBUN_C VARCHAR(8) NULL DEFAULT NULL COMMENT '신청 경로 코드', + ORGNL_FILE_NM VARCHAR(200) NULL DEFAULT NULL COMMENT '원본 파일 명', + REG_DT VARCHAR(14) NULL DEFAULT NULL COMMENT '등록 일시', + RGTR VARCHAR(10) NULL DEFAULT NULL COMMENT '등록자', + PRIMARY KEY (INTERFACE_SEQ_N) USING BTREE +) COMMENT='국민신문고 민원 수신'; + +CREATE OR REPLACE TABLE tb_esb_interface_file ( + INTERFACE_SEQ_N VARCHAR(30) NOT NULL COMMENT '인터페이스 키', + PETI_FILE_SIZE_N INT(10) NULL DEFAULT NULL COMMENT '민원 신청 첨부파일 크기', + PETI_FILE_PATH1_V VARCHAR(2000) NULL DEFAULT NULL COMMENT '민원 신청 첨부파일 명1', + PETI_FILE_PATH2_V VARCHAR(2000) NULL DEFAULT NULL COMMENT '민원 신청 첨부파일 명2', + PETI_FILE_PATH3_V VARCHAR(2000) NULL DEFAULT NULL COMMENT '민원 신청 첨부파일 명3', + PETI_FILE_PATH4_V VARCHAR(2000) NULL DEFAULT NULL COMMENT '민원 신청 첨부파일 명4', + PETI_FILE_PATH5_V VARCHAR(2000) NULL DEFAULT NULL COMMENT '민원 신청 첨부파일 명5', + PCD_FILE_SIZE_N INT(10) NULL DEFAULT NULL COMMENT '민원 처리 첨부파일 크기', + PCD_FILE_PATH1_V VARCHAR(1000) NULL DEFAULT NULL COMMENT '민원 처리 첨부파일 명1', + PCD_FILE_PATH2_V VARCHAR(1000) NULL DEFAULT NULL COMMENT '민원 처리 첨부파일 명2', + PCD_FILE_PATH3_V VARCHAR(1000) NULL DEFAULT NULL COMMENT '민원 처리 첨부파일 명3', + PCD_FILE_PATH4_V VARCHAR(1000) NULL DEFAULT NULL COMMENT '민원 처리 첨부파일 명4', + PCD_FILE_PATH5_V VARCHAR(1000) NULL DEFAULT NULL COMMENT '민원 처리 첨부파일 명5', + STRG_ATCHFILE_NM1 VARCHAR(1000) NULL DEFAULT NULL COMMENT '저장 첨부파일 명1', + STRG_ATCHFILE_NM2 VARCHAR(1000) NULL DEFAULT NULL COMMENT '저장 첨부파일 명2', + STRG_ATCHFILE_NM3 VARCHAR(1000) NULL DEFAULT NULL COMMENT '저장 첨부파일 명3', + STRG_ATCHFILE_NM4 VARCHAR(1000) NULL DEFAULT NULL COMMENT '저장 첨부파일 명4', + STRG_ATCHFILE_NM5 VARCHAR(1000) NULL DEFAULT NULL COMMENT '저장 첨부파일 명5', + PRIMARY KEY (INTERFACE_SEQ_N) USING BTREE +) COMMENT='국민신문고 민원 첨부 파일'; + +CREATE OR REPLACE TABLE tb_esb_interface_trsm ( + INTERFACE_SEQ_N VARCHAR(30) NOT NULL COMMENT '인터페이스 키', + SYS_GUBUN_C VARCHAR(8) NULL DEFAULT NULL COMMENT '시스템 구분', + ANC_CODE_V VARCHAR(7) NULL DEFAULT NULL COMMENT '기관 코드', + PETI_GUBUN_C VARCHAR(3) NULL DEFAULT NULL COMMENT '민원 구분', + PETI_ANC_CODE_V VARCHAR(7) NULL DEFAULT NULL COMMENT '민원 기관 코드', + PETI_NO_C VARCHAR(16) NULL DEFAULT NULL COMMENT '민원 신청 번호', + CIVIL_NO_C VARCHAR(16) NULL DEFAULT NULL COMMENT '민원 접수 번호', + CIVIL_GIST_V VARCHAR(512) NULL DEFAULT NULL COMMENT '민원 요지', + CIVIL_ABSTRACT_L VARCHAR(4000) NULL DEFAULT NULL COMMENT '민원 처리 요약', + PCD_DEPT_V VARCHAR(7) NULL DEFAULT NULL COMMENT '처리 부서 코드', + PCD_DEPT_NM_V VARCHAR(50) NULL DEFAULT NULL COMMENT '민원 처리 부서명', + DUTY_ID_V VARCHAR(50) NULL DEFAULT NULL COMMENT '민원 처리 담당자 명', + PCD_EMAIL_V VARCHAR(64) NULL DEFAULT NULL COMMENT '담당자 이메일', + PCD_TEL_V VARCHAR(20) NULL DEFAULT NULL COMMENT '담당자 전화번호', + PCD_RST_CONT_L VARCHAR(4000) NULL DEFAULT NULL COMMENT '민원 처리 결과', + DO_REG_D VARCHAR(14) NULL DEFAULT NULL COMMENT '민원 처리 완료 일시', + PCD_RST_CONT_ATTACH_YN_C VARCHAR(1) NULL DEFAULT NULL COMMENT '민원 처리 결과 첨부 여부', + PCD_ANC_CODE_V VARCHAR(7) NULL DEFAULT NULL COMMENT '민원 실 처리 기관 코드', + REG_D VARCHAR(14) NULL DEFAULT NULL COMMENT '등록 일자', + SEND_YN_C VARCHAR(1) NULL DEFAULT NULL COMMENT '송신 여부', + SEND_D VARCHAR(14) NULL DEFAULT NULL COMMENT '송신 일자', + APPLY_D VARCHAR(14) NULL DEFAULT NULL COMMENT '적용 일자', + APPLY_GUBUN_C VARCHAR(1) NULL DEFAULT NULL COMMENT '완료 구분', + PCD_GUBUN_V VARCHAR(400) NULL DEFAULT NULL COMMENT '처리 구분1', + PCD_GUBUN2_V VARCHAR(400) NULL DEFAULT NULL COMMENT '처리 구분2', + PCD_GUBUN3_V VARCHAR(400) NULL DEFAULT NULL COMMENT '처리 구분3', + TRSM_INTERFACE_SEQ_N VARCHAR(30) NULL DEFAULT NULL COMMENT '전송 인터페이스키', + TRSM_STTS_CD VARCHAR(2) NULL DEFAULT NULL COMMENT '전송 상태 코드', + TRSM_STTS_MSG VARCHAR(1000) NULL DEFAULT NULL COMMENT '전송 상태 메시지', + REG_DT VARCHAR(14) NULL DEFAULT NULL COMMENT '등록 일시', + RGTR VARCHAR(10) NULL DEFAULT NULL COMMENT '등록자', + MDFCN_DT VARCHAR(14) NULL DEFAULT NULL COMMENT '수정 일시', + MDFR VARCHAR(10) NULL DEFAULT NULL COMMENT '수정자', + PRIMARY KEY (INTERFACE_SEQ_N) USING BTREE +) COMMENT='국민신문고 답변 전송';