Compare commits
No commits in common. 'main' and 'internalApi' have entirely different histories.
main
...
internalAp
@ -1,13 +0,0 @@
|
||||
-- 자동차 과태료 대상 ID 시퀀스
|
||||
-- 테이블: seq_car_ffnlg_trgt_incmp_id
|
||||
-- 컬럼: CAR_FFNLG_TRGT_INCMP_ID (varchar(20))
|
||||
|
||||
-- 시퀀스 삭제 (존재하는 경우)
|
||||
DROP SEQUENCE IF EXISTS seq_car_ffnlg_trgt_incmp_id;
|
||||
|
||||
-- 시퀀스 생성
|
||||
CREATE SEQUENCE seq_car_ffnlg_trgt_incmp_id
|
||||
START WITH 1000
|
||||
INCREMENT BY 1
|
||||
MINVALUE 1
|
||||
MAXVALUE 99999999999999999;
|
||||
@ -1,108 +1,106 @@
|
||||
create table tb_car_bass_matter_inqire
|
||||
(
|
||||
CAR_BASS_MATTER_INQIRE_ID varchar(20) not null comment '자동차 기본 사항 조회 ID'
|
||||
CAR_BASS_MATTER_INQIRE_ID varchar(20) not null comment '자동차 기본 사항 조회 ID'
|
||||
primary key,
|
||||
TX_ID varchar(25) null comment '트랜잭션 ID',
|
||||
INFO_SYS_ID varchar(6) null comment '정보 시스템 ID',
|
||||
INFO_SYS_IP_ADDR varchar(23) null comment '정보 시스템 IP',
|
||||
SGG_CD varchar(5) null comment '시군구 코드',
|
||||
LINK_INFO_CD varchar(15) null comment '연계 정보 코드',
|
||||
PIC_ID varchar(15) null comment '담당자 ID',
|
||||
PIC_IP_ADDR varchar(23) null comment '담당자 IP',
|
||||
PIC_NM varchar(75) null comment '담당자명',
|
||||
DMND_LEVY_CRTR_YMD varchar(8) null comment '요청 부과 기준일',
|
||||
DMND_INQ_SE_CD varchar(1) null comment '요청 조회 구분 코드',
|
||||
DMND_VHRNO varchar(30) null comment '요청 자동차등록번호',
|
||||
DMND_VIN varchar(17) null comment '요청 차대번호',
|
||||
LINK_RSLT_CD varchar(10) null comment '연계 결과 코드',
|
||||
LINK_RSLT_DTL varchar(4000) null comment '연계 결과 상세',
|
||||
YRIDNW varchar(4) null comment '연식',
|
||||
REG_YMD varchar(10) null comment '등록일',
|
||||
ERSR_REG_SE_CD varchar(4) null comment '말소 등록 구분 코드',
|
||||
ERSR_REG_SE_NM varchar(30) null comment '말소 등록 구분명',
|
||||
ERSR_REG_YMD varchar(10) null comment '말소 등록일',
|
||||
REG_DTL_CD varchar(3) null comment '등록 상세 코드',
|
||||
DSPLVL varchar(10) null comment '배기량',
|
||||
USGSRHLD_STDG_CD varchar(10) null comment '사용 본거지 법정동 코드',
|
||||
USGSRHLD_DONG_CD varchar(10) null comment '사용 본거지 행정동 코드',
|
||||
USGSRHLD_MTN_YN varchar(2) null comment '사용 본거지 산',
|
||||
USGSRHLD_LNBR varchar(4) null comment '사용 본거지 번지',
|
||||
USGSRHLD_HO varchar(4) null comment '사용 본거지 호',
|
||||
USGSRHLD_ADDR_NM varchar(300) null comment '사용 본거지 상세주소',
|
||||
USGSRHLD_ROAD_NM_CD varchar(12) null comment '사용 본거지 도로명 코드',
|
||||
USGSRHLD_UDGD_BLDG_SE_CD varchar(1) null comment '사용 본거지 지하 건물 구분 코드',
|
||||
USGSRHLD_BMNO varchar(5) null comment '사용 본거지 건물 주요 번호',
|
||||
USGSRHLD_BSNO varchar(5) null comment '사용 본거지 건물 부 번호',
|
||||
USGSRHLD_WHOL_ADDR varchar(750) null comment '사용 본거지 전체주소',
|
||||
RPRS_OWNR_MBR_SE_CD varchar(2) null comment '대표소유자 회원 구분 코드',
|
||||
RPRS_OWNR_NM varchar(75) null comment '대표소유자 성명',
|
||||
RPRSV_OWNR_IDECNO varchar(100) null comment '대표소유자 회원 번호',
|
||||
RPRS_OWNR_TELNO varchar(25) null comment '대표소유자 전화번호',
|
||||
OWNR_STDG_CD varchar(10) null comment '소유자 법정동 코드',
|
||||
OWNR_DONG_CD varchar(10) null comment '소유자 행정동 코드',
|
||||
OWNR_MTN_YN varchar(2) null comment '소유자 산',
|
||||
OWNR_LNBR varchar(4) null comment '소유자 번지',
|
||||
OWNR_HO varchar(4) null comment '소유자 호',
|
||||
OWNR_ADDR_NM varchar(300) null comment '소유자 상세주소',
|
||||
OWNR_ROAD_NM_CD varchar(12) null comment '소유자 도로명 코드',
|
||||
OWNR_UDGD_BLDG_SE_CD varchar(1) null comment '소유자 지하건물 구분 코드',
|
||||
OWNR_BMNO varchar(5) null comment '소유자 건물 주요 번호',
|
||||
OWNR_BSNO varchar(5) null comment '소유자 건물 부 번호',
|
||||
OWNR_WHOL_ADDR varchar(750) null comment '소유자 전체주소',
|
||||
REAR_VHRNO varchar(30) null comment '신 차량번호',
|
||||
USE_FUEL_CD varchar(1) null comment '사용 연료 코드',
|
||||
USG_SE_CD varchar(2) null comment '용도 구분 코드',
|
||||
MTRS_FOM_NM varchar(75) null comment '원동기 형식명',
|
||||
BFR_VHRNO varchar(30) null comment '이전 차량번호',
|
||||
VHRNO varchar(30) null comment '차량번호',
|
||||
VIN varchar(17) null comment '차대번호',
|
||||
ATMB_NM varchar(75) null comment '차명',
|
||||
VHCL_TOTL_WT varchar(6) null comment '차량 총 중량',
|
||||
VEAG_END_YMD varchar(10) null comment '차령 만료일자',
|
||||
CHG_YMD varchar(10) null comment '차번호 변경시기',
|
||||
CARMDL_ASORT_CD varchar(1) null comment '차종 종별 코드',
|
||||
CARMDL_TYPE_CD varchar(1) null comment '차종 유형 코드',
|
||||
CARMDL_SE_CD varchar(1) null comment '차종 분류 코드',
|
||||
MXMM_LDG varchar(10) null comment '최대 적재량',
|
||||
CARMDL_ASORT_NM varchar(150) null comment '차종 종별명',
|
||||
CARMDL_TYPE_NM varchar(150) null comment '차종 유형명',
|
||||
CARMDL_CLSF_NM varchar(150) null comment '차종 분류명',
|
||||
FRST_REG_YMD varchar(10) null comment '최초 등록일',
|
||||
FOM_NM varchar(75) null comment '형식',
|
||||
ACQS_YMD varchar(10) null comment '취득 일자',
|
||||
ACQS_END_YMD varchar(10) null comment '취득 종료일자',
|
||||
FBCTN_YMD varchar(10) null comment '제작 년월일',
|
||||
TRANSR_REG_YMD varchar(10) null comment '이전 등록일',
|
||||
SPCF_REG_STTS_CD varchar(6) null comment '제원 등록 상태 코드',
|
||||
COLOR_NM varchar(75) null comment '색상명',
|
||||
MRTG_CNT varchar(9) null comment '저당수',
|
||||
SZR_CNT varchar(9) null comment '압류건수',
|
||||
STRCT_CHG_CNT varchar(9) null comment '구조변경수',
|
||||
NOPLT_CSDY_YN varchar(1) null comment '번호판 영치 여부',
|
||||
NOPLT_CSDY_AVTSMT_YMD varchar(10) null comment '번호판 영치 최고일',
|
||||
SRC_SE_CD varchar(1) null comment '출처 구분 코드',
|
||||
NOPLT_SPCFCT_CD varchar(1) null comment '번호판 규격 코드',
|
||||
ACQS_AMT varchar(100) null comment '취득 금액',
|
||||
INSP_VLD_PD_BGNG_YMD varchar(10) null comment '검사 유효 기간 시작일',
|
||||
INSP_VLD_PD_END_YMD varchar(10) null comment '검사 유효 기간 종료일',
|
||||
USGSRHLD_GRC_CD varchar(4) null comment '사용 본거지 관청 코드',
|
||||
RDCPCT_CNT varchar(3) null comment '승차정원수',
|
||||
SPMNNO varchar(25) null comment '제원관리번호',
|
||||
DRVNG_DSTNC varchar(10) null comment '주행거리',
|
||||
FRST_REG_APLY_RCPT_NO varchar(25) null comment '최초 등록 접수번호',
|
||||
VLNT_ERSR_PRVNTC_AVTSMT_YMD varchar(10) null comment '예고통지일',
|
||||
OGNZ_NM varchar(150) null comment '등록 기관명',
|
||||
PRCS_IMPRTY_RSN_CD varchar(2) null comment '처리 불가 사유 코드',
|
||||
PRCS_IMPRTY_RSN_DTLS varchar(75) null comment '처리 불가 사유 명세',
|
||||
CBD_LT varchar(10) null comment '차체 길이',
|
||||
CBD_BT varchar(10) null comment '차체 너비',
|
||||
CBD_HG varchar(10) null comment '차체 높이',
|
||||
FRST_MXMM_LDG varchar(10) null comment '최초 최대 적재량',
|
||||
FUEL_CNSMPRT varchar(5) null comment '연료 소비율',
|
||||
ELCTY_CMPND_FUEL_CNSMPRT varchar(5) null comment '전기 복합 연료 소비율',
|
||||
CAR_FFNLG_TRGT_ID varchar(20) null comment '자동차 과태료 대상 ID',
|
||||
REG_DT datetime null comment '등록 일시',
|
||||
RGTR varchar(11) null comment '등록자'
|
||||
INFO_SYS_ID varchar(6) null comment '정보 시스템 ID',
|
||||
INFO_SYS_IP varchar(23) null comment '정보 시스템 IP',
|
||||
SIGUNGU_CODE varchar(5) null comment '시군구 코드',
|
||||
CNTC_INFO_CODE varchar(15) null comment '연계 정보 코드',
|
||||
CHARGER_ID varchar(15) null comment '담당자 ID',
|
||||
CHARGER_IP varchar(23) null comment '담당자 IP',
|
||||
CHARGER_NM varchar(75) null comment '담당자명',
|
||||
DMND_LEVY_STDDE varchar(8) null comment '요청 부과 기준일',
|
||||
DMND_INQIRE_SE_CODE varchar(1) null comment '요청 조회 구분 코드',
|
||||
DMND_VHRNO varchar(30) null comment '요청 자동차등록번호',
|
||||
DMND_VIN varchar(17) null comment '요청 차대번호',
|
||||
CNTC_RESULT_CODE varchar(8) null comment '연계 결과 코드',
|
||||
CNTC_RESULT_DTLS varchar(4000) null comment '연계 결과 상세',
|
||||
PRYE varchar(4) null comment '연식',
|
||||
REGIST_DE varchar(8) null comment '등록일',
|
||||
ERSR_REGIST_SE_CODE varchar(4) null comment '말소 등록 구분 코드',
|
||||
ERSR_REGIST_SE_NM varchar(30) null comment '말소 등록 구분명',
|
||||
ERSR_REGIST_DE varchar(8) null comment '말소 등록일',
|
||||
REGIST_DETAIL_CODE varchar(3) null comment '등록 상세 코드',
|
||||
DSPLVL varchar(6) null comment '배기량',
|
||||
USE_STRNGHLD_LEGALDONG_CODE varchar(10) null comment '사용 본거지 법정동 코드',
|
||||
USE_STRNGHLD_ADSTRD_CODE varchar(10) null comment '사용 본거지 행정동 코드',
|
||||
USE_STRNGHLD_MNTN varchar(2) null comment '사용 본거지 산',
|
||||
USE_STRNGHLD_LNBR varchar(4) null comment '사용 본거지 번지',
|
||||
USE_STRNGHLD_HO varchar(4) null comment '사용 본거지 호',
|
||||
USE_STRNGHLD_ADRES_NM varchar(300) null comment '사용 본거지 상세주소',
|
||||
USE_STRNGHLD_ROAD_NM_CODE varchar(12) null comment '사용 본거지 도로명 코드',
|
||||
USGSRHLD_UNDGRND_BULD_SE_CODE varchar(1) null comment '사용 본거지 지하 건물 구분 코드',
|
||||
USE_STRNGHLD_BULD_MAIN_NO varchar(5) null comment '사용 본거지 건물 주요 번호',
|
||||
USE_STRNGHLD_BULD_SUB_NO varchar(5) null comment '사용 본거지 건물 부 번호',
|
||||
USGSRHLD_ADRES_FULL varchar(750) null comment '사용 본거지 전체주소',
|
||||
MBER_SE_CODE varchar(2) null comment '대표소유자 회원 구분 코드',
|
||||
MBER_SE_NO varchar(100) null comment '대표소유자 회원 번호',
|
||||
TELNO varchar(20) null comment '대표소유자 전화번호',
|
||||
OWNER_LEGALDONG_CODE varchar(10) null comment '소유자 법정동 코드',
|
||||
OWNER_ADSTRD_CODE varchar(10) null comment '소유자 행정동 코드',
|
||||
OWNER_MNTN varchar(2) null comment '소유자 산',
|
||||
OWNER_LNBR varchar(4) null comment '소유자 번지',
|
||||
OWNER_HO varchar(4) null comment '소유자 호',
|
||||
OWNER_ADRES_NM varchar(300) null comment '소유자 상세주소',
|
||||
OWNER_ROAD_NM_CODE varchar(12) null comment '소유자 도로명 코드',
|
||||
OWNER_UNDGRND_BULD_SE_CODE varchar(1) null comment '소유자 지하건물 구분 코드',
|
||||
OWNER_BULD_MAIN_NO varchar(5) null comment '소유자 건물 주요 번호',
|
||||
OWNER_BULD_SUB_NO varchar(5) null comment '소유자 건물 부 번호',
|
||||
OWNR_WHOLADDR varchar(750) null comment '소유자 전체주소',
|
||||
AFTR_VHRNO varchar(30) null comment '신 차량번호',
|
||||
USE_FUEL_CODE varchar(1) null comment '사용 연료 코드',
|
||||
PRPOS_SE_CODE varchar(2) null comment '용도 구분 코드',
|
||||
MTRS_FOM_NM varchar(75) null comment '원동기 형식명',
|
||||
FRNT_VHRNO varchar(30) null comment '이전 차량번호',
|
||||
VHRNO varchar(30) null comment '차량번호',
|
||||
VIN varchar(17) null comment '차대번호',
|
||||
CNM varchar(75) null comment '차명',
|
||||
VHCLE_TOT_WT varchar(6) null comment '차량 총 중량',
|
||||
CAAG_ENDDE varchar(8) null comment '차령 만료일자',
|
||||
CHANGE_DE varchar(8) null comment '차번호 변경시기',
|
||||
VHCTY_ASORT_CODE varchar(1) null comment '차종 종별 코드',
|
||||
VHCTY_TY_CODE varchar(1) null comment '차종 유형 코드',
|
||||
VHCTY_SE_CODE varchar(1) null comment '차종 분류 코드',
|
||||
MXMM_LDG varchar(10) null comment '최대 적재량',
|
||||
VHCTY_ASORT_NM varchar(150) null comment '차종 종별명',
|
||||
VHCTY_TY_NM varchar(150) null comment '차종 유형명',
|
||||
VHCTY_SE_NM varchar(150) null comment '차종 분류명',
|
||||
FRST_REGIST_DE varchar(8) null comment '최초 등록일',
|
||||
FOM_NM varchar(75) null comment '형식',
|
||||
ACQS_DE varchar(8) null comment '취득 일자',
|
||||
ACQS_END_DE varchar(8) null comment '취득 종료일자',
|
||||
YBL_MD varchar(8) null comment '제작 년월일',
|
||||
TRANSR_REGIST_DE varchar(8) null comment '이전 등록일',
|
||||
SPCF_REGIST_STTUS_CODE varchar(6) null comment '제원 등록 상태 코드',
|
||||
COLOR_NM varchar(75) null comment '색상명',
|
||||
MRTG_CO varchar(9) null comment '저당수',
|
||||
SEIZR_CO varchar(9) null comment '압류건수',
|
||||
STMD_CO varchar(9) null comment '구조변경수',
|
||||
NMPL_CSDY_AT varchar(1) null comment '번호판 영치 여부',
|
||||
NMPL_CSDY_REMNR_DE varchar(8) null comment '번호판 영치 최고일',
|
||||
ORIGIN_SE_CODE varchar(1) null comment '출처 구분 코드',
|
||||
NMPL_STNDRD_CODE varchar(1) null comment '번호판 규격 코드',
|
||||
ACQS_AMOUNT varchar(18) null comment '취득 금액',
|
||||
INSPT_VALID_PD_BGNDE varchar(8) null comment '검사 유효 기간 시작일',
|
||||
INSPT_VALID_PD_ENDDE varchar(8) null comment '검사 유효 기간 종료일',
|
||||
USE_STRNGHLD_GRC_CODE varchar(4) null comment '사용 본거지 관청 코드',
|
||||
TKCAR_PSCAP_CO varchar(3) null comment '승차정원수',
|
||||
SPMNNO varchar(17) null comment '제원관리번호',
|
||||
TRVL_DSTNC varchar(10) null comment '주행거리',
|
||||
FRST_REGIST_RQRCNO varchar(20) null comment '최초 등록 접수번호',
|
||||
VLNT_ERSR_PRVNTC_NTICE_DE varchar(8) null comment '예고통지일',
|
||||
REGIST_INSTT_NM varchar(150) null comment '등록 기관명',
|
||||
PROCESS_IMPRTY_RESN_CODE varchar(2) null comment '처리 불가 사유 코드',
|
||||
PROCESS_IMPRTY_RESN_DTLS varchar(75) null comment '처리 불가 사유 명세',
|
||||
CBD_LT varchar(10) null comment '차체 길이',
|
||||
CBD_BT varchar(10) null comment '차체 너비',
|
||||
CBD_HG varchar(10) null comment '차체 높이',
|
||||
FRST_MXMM_LDG varchar(10) null comment '최초 최대 적재량',
|
||||
FUEL_CNSMP_RT varchar(5) null comment '연료 소비율',
|
||||
ELCTY_CMPND_FUEL_CNSMP_RT varchar(5) null comment '전기 복합 연료 소비율',
|
||||
REG_DT datetime null comment '등록 일시',
|
||||
RGTR varchar(11) null comment '등록자',
|
||||
MBER_NM varchar(75) null comment '대표소유자 성명'
|
||||
)
|
||||
comment '자동차 기본 사항 조회';
|
||||
|
||||
|
||||
@ -1,41 +0,0 @@
|
||||
create table tb_car_ffnlg_trgt_incmp
|
||||
(
|
||||
CAR_FFNLG_TRGT_INCMP_ID varchar(20) not null comment '자동차 과태료 대상 미필 ID'
|
||||
primary key,
|
||||
RCPT_YMD varchar(10) null comment '접수 일자',
|
||||
PRGRM_ID varchar(10) null comment '프로그램 ID',
|
||||
PRCS_YMD varchar(100) null comment '처리 일자',
|
||||
OTPT_DT varchar(100) null comment '출력 일시',
|
||||
NO decimal null comment '번호',
|
||||
VHCLNO varchar(30) null comment '차량번호',
|
||||
OWNR_NM varchar(75) null comment '소유자 명',
|
||||
RRNO varchar(100) null comment '주민등록번호',
|
||||
CAR_NM varchar(100) null comment '자동차 명',
|
||||
USE_STRHLD_ADDR varchar(600) null comment '사용 본거지 주소',
|
||||
USE_STRHLD_ADDR_DTL varchar(600) null comment '사용 본거지 주소 상세',
|
||||
INSP_VLD_PRD varchar(30) null comment '검사 유효 기간',
|
||||
TASK_PRCS_STTS_CD varchar(2) null comment '업무 처리 상태 코드',
|
||||
TASK_PRCS_YMD varchar(10) null comment '업무 처리 일자',
|
||||
RMRK varchar(4000) null comment '비고',
|
||||
RMRK_DTL TEXT null comment '비고 상세',
|
||||
CAR_BASS_MATTER_INQIRE_ID varchar(20) null comment '자동차 기본 사항 조회 ID',
|
||||
CAR_LEDGER_FRMBK_ID varchar(20) null comment '자동차 등록 원부 갑 ID',
|
||||
CAR_BSC_MTTR_INQ_FLNM varchar(75) null comment '자동차 기본 사항 조회 성명',
|
||||
CAR_BSC_MTTR_INQ_SGG_CD varchar(5) null comment '자동차 기본 사항 조회 시군구 코드',
|
||||
CAR_BSC_MTTR_INQ_SGG_NM varchar(75) null comment '자동차 기본 사항 조회 시군구 명',
|
||||
CAR_REG_FRMBK_CHG_TASK_SE_CD varchar(2) null comment '자동차 등록 원부갑 변경 업무 구분 코드',
|
||||
CAR_REG_FRMBK_CHG_TASK_SE_NM varchar(75) null comment '자동차 등록 원부갑 변경 업무 구분 명',
|
||||
CAR_REG_FRMBK_CHG_YMD varchar(10) null comment '자동차 등록 원부갑 변경 일자',
|
||||
CAR_REG_FRMBK_DTL varchar(2000) null comment '자동차 등록 원부갑 상세',
|
||||
REG_DT datetime null comment '등록 일시',
|
||||
RGTR varchar(11) null comment '등록자',
|
||||
DEL_YN char not null comment '삭제 여부',
|
||||
DEL_DT datetime null comment '삭제 일시',
|
||||
DLTR varchar(11) null comment '삭제자'
|
||||
)
|
||||
comment '자동차 과태료 대상 미필';
|
||||
|
||||
|
||||
|
||||
ALTER TABLE tb_car_ffnlg_trgt_incmp
|
||||
MODIFY COLUMN RMRK_DTL TEXT NULL COMMENT '비고 상세';
|
||||
@ -1,90 +1,87 @@
|
||||
create table tb_car_ledger_frmbk
|
||||
(
|
||||
CAR_LEDGER_FRMBK_ID varchar(20) not null comment '자동차 등록 원부 갑 ID'
|
||||
CAR_LEDGER_FRMBK_ID varchar(20) not null comment '자동차 등록 원부 갑 ID'
|
||||
primary key,
|
||||
TX_ID varchar(25) null comment '트랜잭션 ID',
|
||||
INFO_SYS_ID varchar(6) null comment '정보 시스템 ID',
|
||||
INFO_SYS_IP_ADDR varchar(23) null comment '정보 시스템 IP',
|
||||
SGG_CD varchar(5) null comment '시군구 코드',
|
||||
LINK_INFO_CD varchar(15) null comment '연계 정보 코드',
|
||||
PIC_ID varchar(15) null comment '담당자 ID',
|
||||
PIC_IP_ADDR varchar(23) null comment '담당자 IP',
|
||||
PIC_NM varchar(75) null comment '담당자명',
|
||||
DMND_VHRNO varchar(30) null comment '요청 자동차등록번호',
|
||||
DMND_PRVC_RLS varchar(1) null comment '요청 개인 정보 공개',
|
||||
DMND_CVLPR_NM varchar(75) null comment '요청 민원인 성명',
|
||||
DMND_CVLPR_IDECNO varchar(100) null comment '요청 민원인 주민번호',
|
||||
DMND_CVLPR_STDG_CD varchar(10) null comment '요청 민원인 법정동 코드',
|
||||
DMND_PATH_SE_CD varchar(1) null comment '요청 경로 구분 코드',
|
||||
DMND_DSCTN_INDCT varchar(1) null comment '요청 내역 표시',
|
||||
DMND_INQ_SE_CD varchar(1) null comment '요청 조회 구분 코드',
|
||||
LINK_RSLT_CD varchar(8) null comment '연계 결과 코드',
|
||||
LINK_RSLT_DTL varchar(4000) null comment '연계 결과 상세',
|
||||
LEDGER_GROUP_NO varchar(10) null comment '원부 그룹 번호',
|
||||
LEDGER_INDIV_NO varchar(10) null comment '원부 개별 번호',
|
||||
VHMNO varchar(25) null comment '차량관리번호',
|
||||
VHRNO varchar(30) null comment '차량등록번호',
|
||||
VIN varchar(17) null comment '차대번호',
|
||||
CARMDL_ASORT_CD varchar(1) null comment '차종 종별 코드',
|
||||
CARMDL_ASORT_NM varchar(30) null comment '차종 종별명',
|
||||
ATMB_NM varchar(75) null comment '차명',
|
||||
COLOR_CD varchar(2) null comment '색상 코드',
|
||||
COLOR_NM varchar(30) null comment '색상명',
|
||||
NOPLT_SPCFCT_CD varchar(1) null comment '번호판 규격 코드',
|
||||
NOPLT_SPCFCT_NM varchar(30) null comment '번호판 규격명',
|
||||
USG_SE_CD varchar(2) null comment '용도 구분 코드',
|
||||
USG_SE_NM varchar(20) null comment '용도 구분명',
|
||||
MTRS_FOM_NM varchar(75) null comment '원동기 형식명',
|
||||
FOM_NM varchar(75) null comment '형식명',
|
||||
ACQS_AMT varchar(100) null comment '취득 금액',
|
||||
REG_DTL_CD varchar(8) null comment '등록 상세 코드',
|
||||
REG_DTL_NM varchar(30) null comment '등록 상세명',
|
||||
FRST_REG_YMD varchar(10) null comment '최초 등록일',
|
||||
VEAG_END_YMD varchar(10) null comment '차령 종료일',
|
||||
YRIDNW varchar(4) null comment '연식',
|
||||
SPMNNO_1 varchar(10) null comment '제원관리번호1',
|
||||
SPMNNO_2 varchar(20) null comment '제원관리번호2',
|
||||
FBCTN_YMD varchar(10) null comment '제작 년월일',
|
||||
DRVNG_DSTNC varchar(10) null comment '주행 거리',
|
||||
INSP_VLD_PD_BGNG_YMD varchar(10) null comment '검사 유효 기간 시작일',
|
||||
INSP_VLD_PD_END_YMD varchar(10) null comment '검사 유효 기간 종료일',
|
||||
CHCK_VLD_PD_BGNG_YMD varchar(10) null comment '점검 유효 기간 시작일',
|
||||
CHCK_VLD_PD_END_YMD varchar(10) null comment '점검 유효 기간 종료일',
|
||||
REG_APLY_SE_NM varchar(75) null comment '등록 신청 구분명',
|
||||
FRST_REG_APLY_RCPT_NO varchar(20) null comment '최초 등록 접수번호',
|
||||
NOPLT_CSDY_AVTSMT_YMD varchar(10) null comment '번호판 영치 최고일',
|
||||
NOPLT_CSDY_YN varchar(1) null comment '번호판 영치 여부',
|
||||
BSS_USE_PD_YMD varchar(30) null comment '사업용 사용 기간',
|
||||
OCTHT_ERSR_PRVNTC_AVTSMT_YMD varchar(10) null comment '직권 말소 예고 통지일',
|
||||
ERSR_REG_YMD varchar(10) null comment '말소 등록일',
|
||||
ERSR_REG_SE_CD varchar(4) null comment '말소 등록 구분 코드',
|
||||
ERSR_REG_SE_NM varchar(200) null comment '말소 등록 구분명',
|
||||
MRTG_CNT varchar(4) null comment '저당수',
|
||||
SZR_CNT varchar(4) null comment '압류건수',
|
||||
STRCT_CHG_CNT varchar(4) null comment '구조변경수',
|
||||
USGSRHLD_ADDR_1 varchar(750) null comment '사용 본거지 주소',
|
||||
USGSRHLD_ADDR_DTL_1 varchar(300) null comment '사용 본거지 주소상세',
|
||||
OWNR_ADDR varchar(750) null comment '소유자 주소',
|
||||
OWNR_ADDR_DTL varchar(300) null comment '소유자 주소상세',
|
||||
INDVDL_BZMN_YN varchar(1) null comment '개인 사업자 여부',
|
||||
RPRS_OWNR_TELNO varchar(30) null comment '대표소유자 전화번호',
|
||||
RPRS_OWNR_NM varchar(75) null comment '대표소유자 성명',
|
||||
RPRS_OWNR_MBR_SE_CD varchar(2) null comment '대표소유자 회원 구분 코드',
|
||||
RPRSV_OWNR_IDECNO varchar(100) null comment '대표소유자 회원 번호',
|
||||
TAXXMPT_TRPR_SE_CD varchar(2) null comment '비과세 대상 구분 코드',
|
||||
TAXXMPT_APLCN_SE_CD varchar(30) null comment '비과세 대상 구분 코드명',
|
||||
SPCABL_MTTR_CNT varchar(5) null comment '특기사항 건수',
|
||||
USGSRHLD_DONG_NM varchar(75) null comment '사용 본거지 행정동명',
|
||||
PRVNTC_CNT varchar(4) null comment '예고수',
|
||||
XPORT_FLFL_YN_DCLR_YMD varchar(10) null comment '수출 이행 여부 신고일',
|
||||
ISSU_NO varchar(13) null comment '발급번호',
|
||||
FRST_TRNSFR_YMD varchar(10) null comment '최초 양도일',
|
||||
DRIV_SRGBTRY_IDNTF_NO varchar(20) null comment '구동축전지 식별번호',
|
||||
PRCS_IMPRTY_RSN_CD varchar(2) null comment '처리 불가 사유 코드',
|
||||
PRCS_IMPRTY_RSN_DTLS varchar(200) null comment '처리 불가 사유 명세',
|
||||
CAR_FFNLG_TRGT_ID varchar(20) null comment '자동차 과태료 대상 ID',
|
||||
REG_DT datetime null comment '등록 일시',
|
||||
RGTR varchar(11) null comment '등록자'
|
||||
INFO_SYS_ID varchar(6) null comment '정보 시스템 ID',
|
||||
INFO_SYS_IP varchar(23) null comment '정보 시스템 IP',
|
||||
SIGUNGU_CODE varchar(5) null comment '시군구 코드',
|
||||
CNTC_INFO_CODE varchar(15) null comment '연계 정보 코드',
|
||||
CHARGER_ID varchar(15) null comment '담당자 ID',
|
||||
CHARGER_IP varchar(23) null comment '담당자 IP',
|
||||
CHARGER_NM varchar(75) null comment '담당자명',
|
||||
DMND_VHRNO varchar(30) null comment '요청 자동차등록번호',
|
||||
DMND_ONES_INFORMATION_OPEN varchar(1) null comment '요청 개인 정보 공개',
|
||||
DMND_CPTTR_NM varchar(75) null comment '요청 민원인 성명',
|
||||
DMND_CPTTR_IHIDNUM varchar(100) null comment '요청 민원인 주민번호',
|
||||
DMND_CPTTR_LEGALDONG_CODE varchar(10) null comment '요청 민원인 법정동 코드',
|
||||
DMND_ROUTE_SE_CODE varchar(1) null comment '요청 경로 구분 코드',
|
||||
DMND_DETAIL_EXPRESSION varchar(1) null comment '요청 내역 표시',
|
||||
DMND_INQIRE_SE_CODE varchar(1) null comment '요청 조회 구분 코드',
|
||||
CNTC_RESULT_CODE varchar(8) null comment '연계 결과 코드',
|
||||
CNTC_RESULT_DTLS varchar(4000) null comment '연계 결과 상세',
|
||||
LEDGER_GROUP_NO varchar(6) null comment '원부 그룹 번호',
|
||||
LEDGER_INDVDLZ_NO varchar(6) null comment '원부 개별 번호',
|
||||
VHMNO varchar(20) null comment '차량관리번호',
|
||||
VHRNO varchar(30) null comment '차량등록번호',
|
||||
VIN varchar(17) null comment '차대번호',
|
||||
VHCTY_ASORT_CODE varchar(1) null comment '차종 종별 코드',
|
||||
VHCTY_ASORT_NM varchar(30) null comment '차종 종별명',
|
||||
CNM varchar(75) null comment '차명',
|
||||
COLOR_CODE varchar(2) null comment '색상 코드',
|
||||
COLOR_NM varchar(30) null comment '색상명',
|
||||
NMPL_STNDRD_CODE varchar(1) null comment '번호판 규격 코드',
|
||||
NMPL_STNDRD_NM varchar(30) null comment '번호판 규격명',
|
||||
PRPOS_SE_CODE varchar(2) null comment '용도 구분 코드',
|
||||
PRPOS_SE_NM varchar(20) null comment '용도 구분명',
|
||||
MTRS_FOM_NM varchar(75) null comment '원동기 형식명',
|
||||
FOM_NM varchar(75) null comment '형식명',
|
||||
ACQS_AMOUNT varchar(50) null comment '취득 금액',
|
||||
REGIST_DETAIL_CODE varchar(8) null comment '등록 상세 코드',
|
||||
REGIST_DETAIL_NM varchar(30) null comment '등록 상세명',
|
||||
FRST_REGIST_DE varchar(8) null comment '최초 등록일',
|
||||
CAAG_ENDDE varchar(8) null comment '차령 종료일',
|
||||
PRYE varchar(4) null comment '연식',
|
||||
SPMNNO1 varchar(3) null comment '제원관리번호1',
|
||||
SPMNNO2 varchar(14) null comment '제원관리번호2',
|
||||
YBL_MD varchar(8) null comment '제작 년월일',
|
||||
TRVL_DSTNC varchar(10) null comment '주행 거리',
|
||||
INSPT_VALID_PD_BGNDE varchar(8) null comment '검사 유효 기간 시작일',
|
||||
INSPT_VALID_PD_ENDDE varchar(8) null comment '검사 유효 기간 종료일',
|
||||
CHCK_VALID_PD_BGNDE varchar(8) null comment '점검 유효 기간 시작일',
|
||||
CHCK_VALID_PD_ENDDE varchar(8) null comment '점검 유효 기간 종료일',
|
||||
REGIST_REQST_SE_NM varchar(75) null comment '등록 신청 구분명',
|
||||
FRST_REGIST_RQRCNO varchar(20) null comment '최초 등록 접수번호',
|
||||
NMPL_CSDY_REMNR_DE varchar(8) null comment '번호판 영치 최고일',
|
||||
NMPL_CSDY_AT varchar(1) null comment '번호판 영치 여부',
|
||||
BSS_USE_PD varchar(30) null comment '사업용 사용 기간',
|
||||
OCTHT_ERSR_PRVNTC_NTICE_DE varchar(8) null comment '직권 말소 예고 통지일',
|
||||
ERSR_REGIST_DE varchar(8) null comment '말소 등록일',
|
||||
ERSR_REGIST_SE_CODE varchar(4) null comment '말소 등록 구분 코드',
|
||||
ERSR_REGIST_SE_NM varchar(200) null comment '말소 등록 구분명',
|
||||
MRTGCNT varchar(4) null comment '저당수',
|
||||
VHCLECNT varchar(4) null comment '압류건수',
|
||||
STMDCNT varchar(4) null comment '구조변경수',
|
||||
ADRES1 varchar(750) null comment '사용 본거지 주소',
|
||||
ADRES_NM1 varchar(300) null comment '사용 본거지 주소상세',
|
||||
ADRES varchar(750) null comment '소유자 주소',
|
||||
ADRES_NM varchar(300) null comment '소유자 주소상세',
|
||||
INDVDL_BSNM_AT varchar(1) null comment '개인 사업자 여부',
|
||||
TELNO varchar(30) null comment '대표소유자 전화번호',
|
||||
MBER_NM varchar(75) null comment '대표소유자 성명',
|
||||
MBER_SE_CODE varchar(2) null comment '대표소유자 회원 구분 코드',
|
||||
MBER_SE_NO varchar(100) null comment '대표소유자 회원 번호',
|
||||
TAXXMPT_TRGTER_SE_CODE varchar(2) null comment '비과세 대상 구분 코드',
|
||||
TAXXMPT_TRGTER_SE_CODE_NM varchar(30) null comment '비과세 대상 구분 코드명',
|
||||
CNT_MATTER varchar(5) null comment '특기사항 건수',
|
||||
EMD_NM varchar(75) null comment '사용 본거지 행정동명',
|
||||
PRVNTCCNT varchar(4) null comment '예고수',
|
||||
XPORT_FLFL_AT_STTEMNT_DE varchar(8) null comment '수출 이행 여부 신고일',
|
||||
PARTN_RQRCNO varchar(13) null comment '발급번호',
|
||||
FRST_TRNSFR_DE varchar(8) null comment '최초 양도일',
|
||||
PROCESS_IMPRTY_RESN_CODE varchar(2) null comment '처리 불가 사유 코드',
|
||||
PROCESS_IMPRTY_RESN_DTLS varchar(200) null comment '처리 불가 사유 명세',
|
||||
REG_DT datetime null comment '등록 일시',
|
||||
RGTR varchar(11) null comment '등록자'
|
||||
)
|
||||
comment '자동차 등록 원부 갑';
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,958 @@
|
||||
# VMIS API 통합 아키텍처 문서
|
||||
|
||||
## 📋 목차
|
||||
- [1. 개요](#1-개요)
|
||||
- [2. 패키지 구조](#2-패키지-구조)
|
||||
- [3. 아키텍처 패턴](#3-아키텍처-패턴)
|
||||
- [4. Internal Mode 상세](#4-internal-mode-상세)
|
||||
- [5. External Mode 상세](#5-external-mode-상세)
|
||||
- [6. 공통 구성요소](#6-공통-구성요소)
|
||||
- [7. 데이터 흐름](#7-데이터-흐름)
|
||||
- [8. 설정 가이드](#8-설정-가이드)
|
||||
- [9. 사용 예제](#9-사용-예제)
|
||||
|
||||
---
|
||||
|
||||
## 1. 개요
|
||||
|
||||
### 1.1 목적
|
||||
VMIS(차량관리정보시스템) API 통합 모듈은 차량 정보 조회 기능을 제공하며, 두 가지 운영 모드를 지원합니다:
|
||||
- **Internal Mode**: 내부 VMIS 모듈을 직접 호출 (성능 우선)
|
||||
- **External Mode**: 외부 REST API 서버 호출 (분리된 아키텍처)
|
||||
|
||||
### 1.2 설계 원칙
|
||||
- **Strategy Pattern**: 런타임에 알고리즘(구현체) 전환
|
||||
- **Dependency Inversion**: 인터페이스에 의존, 구현체는 교체 가능
|
||||
- **Single Responsibility**: 각 클래스는 단일 책임만 수행
|
||||
- **Open-Closed**: 확장에는 열려있고 수정에는 닫혀있음
|
||||
|
||||
---
|
||||
|
||||
## 2. 패키지 구조
|
||||
|
||||
```
|
||||
src/main/java/go/kr/project/api/
|
||||
├── VehicleInfoService.java # 공통 인터페이스
|
||||
│
|
||||
├── config/ # 공통 설정
|
||||
│ ├── ApiConstant.java # API 상수
|
||||
│ ├── ApiMapperConfig.java # API Mapper 스캔 설정
|
||||
│ ├── VmisIntegrationConfig.java # 통합 설정 및 모니터링
|
||||
│ └── properties/
|
||||
│ └── VmisProperties.java # 설정 바인딩 클래스
|
||||
│
|
||||
├── vo/ # 공통 응답 VO (공유)
|
||||
│ ├── VehicleApiResponseVO.java # 최상위 응답 객체
|
||||
│ ├── VehicleBasicInfoVO.java # 차량 기본정보 VO
|
||||
│ ├── VehicleLedgerVO.java # 차량 등록원부 VO
|
||||
│ ├── VehicleBasicRequestVO.java # 기본정보 요청 VO
|
||||
│ └── VehicleLedgerRequestVO.java # 등록원부 요청 VO
|
||||
│
|
||||
├── internal/ # Internal Mode (내부 모듈)
|
||||
│ ├── service/
|
||||
│ │ ├── InternalVehicleInfoServiceImpl.java # 내부 모드 구현체 ⭐
|
||||
│ │ ├── VmisCarBassMatterInqireService.java # 기본정보 조회 서비스
|
||||
│ │ ├── VmisCarBassMatterInqireLogService.java # 기본정보 로그 서비스
|
||||
│ │ ├── VmisCarLedgerFrmbkService.java # 등록원부 조회 서비스
|
||||
│ │ └── VmisCarLedgerFrmbkLogService.java # 등록원부 로그 서비스
|
||||
│ │
|
||||
│ ├── client/
|
||||
│ │ ├── GovernmentApi.java # 정부 API 인터페이스
|
||||
│ │ └── GovernmentApiClient.java # 정부 API 클라이언트
|
||||
│ │
|
||||
│ ├── mapper/
|
||||
│ │ ├── VmisCarBassMatterInqireMapper.java # 기본정보 Mapper
|
||||
│ │ └── VmisCarLedgerFrmbkMapper.java # 등록원부 Mapper
|
||||
│ │
|
||||
│ ├── model/ # Internal 전용 모델
|
||||
│ │ ├── basic/
|
||||
│ │ │ ├── BasicRequest.java # 기본정보 요청
|
||||
│ │ │ ├── BasicResponse.java # 기본정보 응답
|
||||
│ │ │ └── VmisCarBassMatterInqireVO.java
|
||||
│ │ ├── ledger/
|
||||
│ │ │ ├── LedgerRequest.java # 등록원부 요청
|
||||
│ │ │ ├── LedgerResponse.java # 등록원부 응답
|
||||
│ │ │ ├── VmisCarLedgerFrmbkVO.java
|
||||
│ │ │ └── VmisCarLedgerFrmbkDtlVO.java
|
||||
│ │ └── common/
|
||||
│ │ └── Envelope.java # 공통 Envelope
|
||||
│ │
|
||||
│ ├── config/
|
||||
│ │ ├── HttpClientConfig.java # RestTemplate 설정
|
||||
│ │ ├── OpenApiConfig.java # OpenAPI 설정
|
||||
│ │ ├── PropertiesConfig.java # Properties 빈 등록
|
||||
│ │ ├── GpkiConfig.java # GPKI 설정
|
||||
│ │ └── Globals.java # 전역 상수
|
||||
│ │
|
||||
│ ├── controller/
|
||||
│ │ └── VehicleInterfaceController.java # REST API 컨트롤러
|
||||
│ │
|
||||
│ ├── enricher/
|
||||
│ │ └── VmisRequestEnricher.java # 요청 데이터 자동 보강
|
||||
│ │
|
||||
│ ├── gpki/
|
||||
│ │ ├── GpkiService.java # GPKI 인터페이스
|
||||
│ │ ├── RealGpkiService.java # 실제 GPKI 구현
|
||||
│ │ └── NoopGpkiService.java # GPKI 비활성화 구현
|
||||
│ │
|
||||
│ └── util/
|
||||
│ └── VehicleResponseMapper.java # 내부↔외부 VO 변환
|
||||
│
|
||||
└── external/ # External Mode (외부 API)
|
||||
└── service/
|
||||
├── ExternalVehicleInfoServiceImpl.java # 외부 모드 구현체 ⭐
|
||||
└── ExternalVehicleApiService.java # 외부 API 호출 서비스
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 아키텍처 패턴
|
||||
|
||||
### 3.1 Strategy Pattern (전략 패턴)
|
||||
|
||||
```java
|
||||
// 공통 인터페이스
|
||||
public interface VehicleInfoService {
|
||||
VehicleApiResponseVO getVehicleInfo(String vehicleNumber);
|
||||
List<VehicleApiResponseVO> getVehiclesInfo(List<String> vehicleNumbers);
|
||||
}
|
||||
|
||||
// Internal Mode 구현체
|
||||
@Service
|
||||
@ConditionalOnProperty(name = "vmis.integration.mode", havingValue = "internal")
|
||||
public class InternalVehicleInfoServiceImpl implements VehicleInfoService {
|
||||
// 내부 VMIS 모듈 직접 호출
|
||||
}
|
||||
|
||||
// External Mode 구현체
|
||||
@Service
|
||||
@ConditionalOnProperty(name = "vmis.integration.mode", havingValue = "external", matchIfMissing = true)
|
||||
public class ExternalVehicleInfoServiceImpl implements VehicleInfoService {
|
||||
// 외부 REST API 호출
|
||||
}
|
||||
```
|
||||
|
||||
**장점:**
|
||||
- 런타임에 구현체 전환 가능
|
||||
- 클라이언트 코드는 인터페이스만 의존
|
||||
- 새로운 전략 추가 시 기존 코드 수정 불필요
|
||||
|
||||
### 3.2 의존성 주입 (Dependency Injection)
|
||||
|
||||
```yaml
|
||||
# application.yml
|
||||
vmis:
|
||||
integration:
|
||||
mode: internal # 또는 external
|
||||
```
|
||||
|
||||
Spring의 `@ConditionalOnProperty`를 통해 설정값에 따라 자동으로 적절한 구현체가 Bean으로 등록됩니다.
|
||||
|
||||
```java
|
||||
@Autowired
|
||||
private VehicleInfoService vehicleInfoService;
|
||||
// 설정에 따라 InternalVehicleInfoServiceImpl 또는
|
||||
// ExternalVehicleInfoServiceImpl이 주입됨
|
||||
```
|
||||
|
||||
### 3.3 계층화 아키텍처
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ Controller Layer │ ← REST API 엔드포인트
|
||||
├─────────────────────────────────────┤
|
||||
│ Service Layer (VehicleInfoService)│ ← 비즈니스 로직
|
||||
├─────────────────────────────────────┤
|
||||
│ Client/Mapper Layer │ ← 데이터 접근
|
||||
├─────────────────────────────────────┤
|
||||
│ External System (정부 API/DB) │ ← 외부 시스템
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Internal Mode 상세
|
||||
|
||||
### 4.1 개요
|
||||
내부 VMIS 모듈을 직접 사용하여 정부 시스템(MOLIT)과 통신합니다.
|
||||
|
||||
**장점:**
|
||||
- 네트워크 오버헤드 감소 (외부 서버 호출 불필요)
|
||||
- 빠른 응답 속도
|
||||
- 단일 애플리케이션으로 운영 가능
|
||||
|
||||
**단점:**
|
||||
- GPKI 인증서 관리 필요
|
||||
- 정부 API 연동 복잡도 증가
|
||||
|
||||
### 4.2 주요 구성요소
|
||||
|
||||
#### 4.2.1 InternalVehicleInfoServiceImpl
|
||||
```java
|
||||
@Service
|
||||
@ConditionalOnProperty(name = "vmis.integration.mode", havingValue = "internal")
|
||||
public class InternalVehicleInfoServiceImpl implements VehicleInfoService {
|
||||
|
||||
private final VmisCarBassMatterInqireService carBassMatterInqireService;
|
||||
private final VmisCarLedgerFrmbkService carLedgerFrmbkService;
|
||||
|
||||
@Override
|
||||
public VehicleApiResponseVO getVehicleInfo(String vehicleNumber) {
|
||||
// 1. 기본정보 조회
|
||||
VehicleBasicInfoVO basicInfo = getBasicInfo(vehicleNumber);
|
||||
|
||||
// 2. 등록원부 조회
|
||||
VehicleLedgerVO ledgerInfo = getLedgerInfo(vehicleNumber);
|
||||
|
||||
// 3. 결과 통합
|
||||
return VehicleApiResponseVO.builder()
|
||||
.vhrno(vehicleNumber)
|
||||
.basicInfo(basicInfo)
|
||||
.ledgerInfo(ledgerInfo)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 4.2.2 GovernmentApiClient
|
||||
정부 API와 실제 HTTP 통신을 수행합니다.
|
||||
|
||||
```java
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class GovernmentApiClient implements GovernmentApi {
|
||||
|
||||
@Qualifier("vmisRestTemplate")
|
||||
private final RestTemplate restTemplate;
|
||||
|
||||
@Override
|
||||
public ResponseEntity<String> basic(String requestBody) {
|
||||
String url = baseUrl + basicServicePath;
|
||||
return restTemplate.postForEntity(url, requestBody, String.class);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 4.2.3 VmisRequestEnricher
|
||||
요청 데이터를 자동으로 보강합니다.
|
||||
|
||||
```java
|
||||
@Component
|
||||
public class VmisRequestEnricher {
|
||||
|
||||
public void enrichBasicRequest(BasicRequest request) {
|
||||
// 시스템 정보 자동 설정
|
||||
request.setInfoSysId(vmisProperties.getSystem().getInfoSysId());
|
||||
request.setInfoSysIp(vmisProperties.getSystem().getInfoSysIp());
|
||||
request.setRegionCode(vmisProperties.getSystem().getRegionCode());
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 4.2.4 GPKI 암호화
|
||||
운영 환경에서 정부 API 통신 시 GPKI 암호화를 사용합니다.
|
||||
|
||||
```java
|
||||
public interface GpkiService {
|
||||
String encrypt(String plainText);
|
||||
String decrypt(String encryptedText);
|
||||
}
|
||||
|
||||
// 개발: NoopGpkiService (암호화 없음)
|
||||
// 운영: RealGpkiService (실제 GPKI 암호화)
|
||||
```
|
||||
|
||||
### 4.3 데이터 흐름
|
||||
|
||||
```
|
||||
[Client]
|
||||
│
|
||||
▼
|
||||
[InternalVehicleInfoServiceImpl]
|
||||
│
|
||||
├─► [VmisCarBassMatterInqireService]
|
||||
│ │
|
||||
│ ├─► [VmisRequestEnricher] ──► Request 보강
|
||||
│ ├─► [GovernmentApiClient] ──► HTTP POST
|
||||
│ │ │
|
||||
│ │ ▼
|
||||
│ │ [정부 API - 기본정보]
|
||||
│ │ │
|
||||
│ │ ▼
|
||||
│ ├─► [GpkiService] ──► 암호화/복호화
|
||||
│ ├─► [VmisCarBassMatterInqireMapper] ──► DB 저장
|
||||
│ └─► BasicResponse
|
||||
│
|
||||
├─► [VmisCarLedgerFrmbkService]
|
||||
│ │
|
||||
│ └─► (기본정보와 동일한 흐름)
|
||||
│
|
||||
└─► [VehicleResponseMapper] ──► 내부 VO → 외부 VO 변환
|
||||
│
|
||||
▼
|
||||
VehicleApiResponseVO
|
||||
```
|
||||
|
||||
### 4.4 설정 예시
|
||||
|
||||
```yaml
|
||||
vmis:
|
||||
integration:
|
||||
mode: internal
|
||||
|
||||
system:
|
||||
infoSysId: "41-345"
|
||||
infoSysIp: "105.19.10.135"
|
||||
regionCode: "41460"
|
||||
|
||||
gov:
|
||||
scheme: "http"
|
||||
host: "10.188.225.94:29001"
|
||||
basePath: "/piss/api/molit"
|
||||
services:
|
||||
basic:
|
||||
path: "/SignguCarBassMatterInqireService"
|
||||
apiKey: "${GOV_API_KEY_BASIC}"
|
||||
ledger:
|
||||
path: "/SignguCarLedgerFrmbkService"
|
||||
apiKey: "${GOV_API_KEY_LEDGER}"
|
||||
|
||||
gpki:
|
||||
enabled: "Y" # 운영: Y, 개발: N
|
||||
certServerId: "SVR5640020001"
|
||||
targetServerId: "SVR1500000015"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. External Mode 상세
|
||||
|
||||
### 5.1 개요
|
||||
외부 VMIS-interface 서버의 REST API를 호출하여 차량 정보를 조회합니다.
|
||||
|
||||
**장점:**
|
||||
- 마이크로서비스 아키텍처 지원
|
||||
- GPKI 관리를 외부 서버에 위임
|
||||
- 간단한 설정
|
||||
|
||||
**단점:**
|
||||
- 네트워크 오버헤드 증가
|
||||
- 외부 서버 의존성
|
||||
|
||||
### 5.2 주요 구성요소
|
||||
|
||||
#### 5.2.1 ExternalVehicleInfoServiceImpl
|
||||
```java
|
||||
@Service
|
||||
@ConditionalOnProperty(name = "vmis.integration.mode", havingValue = "external", matchIfMissing = true)
|
||||
public class ExternalVehicleInfoServiceImpl implements VehicleInfoService {
|
||||
|
||||
private final ExternalVehicleApiService externalVehicleApiService;
|
||||
|
||||
@Override
|
||||
public VehicleApiResponseVO getVehicleInfo(String vehicleNumber) {
|
||||
// 외부 API 서비스에 위임
|
||||
return externalVehicleApiService.getVehicleInfo(vehicleNumber);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 5.2.2 ExternalVehicleApiService
|
||||
외부 REST API를 호출합니다.
|
||||
|
||||
```java
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class ExternalVehicleApiService {
|
||||
|
||||
private final RestTemplate restTemplate;
|
||||
|
||||
public VehicleApiResponseVO getVehicleInfo(String vehicleNumber) {
|
||||
String url = vmisProperties.getExternal().getApi().getUrl();
|
||||
|
||||
VehicleBasicRequestVO request = new VehicleBasicRequestVO();
|
||||
request.setVhrno(vehicleNumber);
|
||||
|
||||
return restTemplate.postForObject(url + "/basic", request, VehicleApiResponseVO.class);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5.3 데이터 흐름
|
||||
|
||||
```
|
||||
[Client]
|
||||
│
|
||||
▼
|
||||
[ExternalVehicleInfoServiceImpl]
|
||||
│
|
||||
▼
|
||||
[ExternalVehicleApiService]
|
||||
│
|
||||
▼
|
||||
[RestTemplate] ──► HTTP POST
|
||||
│
|
||||
▼
|
||||
[VMIS-interface Server] (외부)
|
||||
│
|
||||
├─► 정부 API 호출
|
||||
├─► GPKI 암호화/복호화
|
||||
├─► DB 저장
|
||||
└─► VehicleApiResponseVO 반환
|
||||
│
|
||||
▼
|
||||
[Client]
|
||||
```
|
||||
|
||||
### 5.4 설정 예시
|
||||
|
||||
```yaml
|
||||
vmis:
|
||||
integration:
|
||||
mode: external
|
||||
|
||||
external:
|
||||
api:
|
||||
url: "http://localhost:8081/api/v1/vehicles"
|
||||
connectTimeoutMillis: 5000
|
||||
readTimeoutMillis: 10000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 공통 구성요소
|
||||
|
||||
### 6.1 VehicleInfoService 인터페이스
|
||||
```java
|
||||
public interface VehicleInfoService {
|
||||
// 단일 차량 조회
|
||||
VehicleApiResponseVO getVehicleInfo(String vehicleNumber);
|
||||
|
||||
// 일괄 조회
|
||||
List<VehicleApiResponseVO> getVehiclesInfo(List<String> vehicleNumbers);
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 공통 VO (vo 패키지)
|
||||
|
||||
#### VehicleApiResponseVO
|
||||
```java
|
||||
@Data
|
||||
@Builder
|
||||
public class VehicleApiResponseVO {
|
||||
private String vhrno; // 차량번호
|
||||
private boolean success; // 성공 여부
|
||||
private String message; // 메시지
|
||||
private VehicleBasicInfoVO basicInfo; // 기본정보
|
||||
private VehicleLedgerVO ledgerInfo; // 등록원부 정보
|
||||
}
|
||||
```
|
||||
|
||||
#### VehicleBasicInfoVO
|
||||
차량 기본정보 (소유자, 차종, 연식 등)
|
||||
|
||||
#### VehicleLedgerVO
|
||||
자동차 등록원부 정보 (등록일, 변경이력 등)
|
||||
|
||||
### 6.3 VmisProperties
|
||||
application.yml의 설정을 바인딩하는 클래스입니다.
|
||||
|
||||
```java
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "vmis")
|
||||
public class VmisProperties {
|
||||
private Integration integration;
|
||||
private System system;
|
||||
private Gov gov;
|
||||
private Gpki gpki;
|
||||
private External external;
|
||||
}
|
||||
```
|
||||
|
||||
### 6.4 ApiMapperConfig
|
||||
API 전용 MyBatis Mapper를 스캔합니다.
|
||||
|
||||
```java
|
||||
@Configuration
|
||||
@MapperScan(basePackages = "go.kr.project.api.internal.mapper")
|
||||
public class ApiMapperConfig {
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 데이터 흐름
|
||||
|
||||
### 7.1 Internal Mode 전체 흐름
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ 1. Client Request │
|
||||
│ vehicleInfoService.getVehicleInfo("12가3456") │
|
||||
└────────────────────────┬────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ 2. InternalVehicleInfoServiceImpl │
|
||||
│ - BasicRequest 생성 (vhrno="12가3456") │
|
||||
│ - LedgerRequest 생성 (vhrno="12가3456") │
|
||||
└────────────────────────┬────────────────────────────────────────────┘
|
||||
│
|
||||
┌───────────────┴───────────────┐
|
||||
│ │
|
||||
▼ ▼
|
||||
┌──────────────────────┐ ┌──────────────────────┐
|
||||
│ 3-1. Basic Service │ │ 3-2. Ledger Service │
|
||||
│ - VmisRequestEnricher│ │ - VmisRequestEnricher│
|
||||
│ (시스템 정보 자동 설정)│ │ (시스템 정보 자동 설정)│
|
||||
└──────┬───────────────┘ └──────┬───────────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌──────────────────────┐ ┌──────────────────────┐
|
||||
│ 4-1. 정부 API 호출 │ │ 4-2. 정부 API 호출 │
|
||||
│ - GovernmentApiClient│ │ - GovernmentApiClient│
|
||||
│ - GPKI 암호화 (운영) │ │ - GPKI 암호화 (운영) │
|
||||
│ - HTTP POST │ │ - HTTP POST │
|
||||
└──────┬───────────────┘ └──────┬───────────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌──────────────────────┐ ┌──────────────────────┐
|
||||
│ 5-1. 응답 처리 │ │ 5-2. 응답 처리 │
|
||||
│ - GPKI 복호화 │ │ - GPKI 복호화 │
|
||||
│ - JSON 파싱 │ │ - JSON 파싱 │
|
||||
│ - DB 저장 (Mapper) │ │ - DB 저장 (Mapper) │
|
||||
└──────┬───────────────┘ └──────┬───────────────┘
|
||||
│ │
|
||||
└───────────────┬───────────────┘
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ 6. VehicleResponseMapper │
|
||||
│ - BasicResponse → VehicleBasicInfoVO 변환 │
|
||||
│ - LedgerResponse → VehicleLedgerVO 변환 │
|
||||
└────────────────────────┬────────────────────────────────────────────┘
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ 7. Response │
|
||||
│ VehicleApiResponseVO { │
|
||||
│ vhrno: "12가3456", │
|
||||
│ success: true, │
|
||||
│ basicInfo: { ... }, │
|
||||
│ ledgerInfo: { ... } │
|
||||
│ } │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 7.2 External Mode 전체 흐름
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ 1. Client Request │
|
||||
│ vehicleInfoService.getVehicleInfo("12가3456") │
|
||||
└────────────────────────┬────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ 2. ExternalVehicleInfoServiceImpl │
|
||||
│ - ExternalVehicleApiService에 위임 │
|
||||
└────────────────────────┬────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ 3. ExternalVehicleApiService │
|
||||
│ - VehicleBasicRequestVO 생성 │
|
||||
│ - RestTemplate으로 외부 API 호출 │
|
||||
└────────────────────────┬────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ 4. HTTP Request to External Server │
|
||||
│ POST http://localhost:8081/api/v1/vehicles/basic │
|
||||
│ Body: { vhrno: "12가3456" } │
|
||||
└────────────────────────┬────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ 5. VMIS-interface Server (외부) │
|
||||
│ - 정부 API 호출 │
|
||||
│ - GPKI 처리 │
|
||||
│ - DB 저장 │
|
||||
│ - VehicleApiResponseVO 반환 │
|
||||
└────────────────────────┬────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ 6. Response │
|
||||
│ VehicleApiResponseVO { │
|
||||
│ vhrno: "12가3456", │
|
||||
│ success: true, │
|
||||
│ basicInfo: { ... }, │
|
||||
│ ledgerInfo: { ... } │
|
||||
│ } │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 설정 가이드
|
||||
|
||||
### 8.1 Internal Mode 설정
|
||||
|
||||
```yaml
|
||||
vmis:
|
||||
integration:
|
||||
mode: internal # ⭐ Internal Mode 활성화
|
||||
|
||||
# 시스템 정보 (요청 헤더에 자동 포함)
|
||||
system:
|
||||
infoSysId: "41-345"
|
||||
infoSysIp: "${SERVER_IP:105.19.10.135}"
|
||||
regionCode: "41460"
|
||||
departmentCode: ""
|
||||
chargerId: ""
|
||||
chargerIp: ""
|
||||
chargerNm: ""
|
||||
|
||||
# 정부 API 연동 설정
|
||||
gov:
|
||||
scheme: "http"
|
||||
host: "10.188.225.94:29001"
|
||||
basePath: "/piss/api/molit"
|
||||
connectTimeoutMillis: 5000
|
||||
readTimeoutMillis: 10000
|
||||
services:
|
||||
basic:
|
||||
path: "/SignguCarBassMatterInqireService"
|
||||
cntcInfoCode: "AC1_FD11_01"
|
||||
apiKey: "${GOV_API_KEY_BASIC}"
|
||||
ledger:
|
||||
path: "/SignguCarLedgerFrmbkService"
|
||||
cntcInfoCode: "AC1_FD11_02"
|
||||
apiKey: "${GOV_API_KEY_LEDGER}"
|
||||
|
||||
# GPKI 암호화 (운영 환경 필수)
|
||||
gpki:
|
||||
enabled: "Y" # Y: 암호화 사용, N: 암호화 미사용
|
||||
certServerId: "SVR5640020001"
|
||||
targetServerId: "SVR1500000015"
|
||||
envCertFilePathName: "src/GPKI/certs/SVR5640020001_env.cer"
|
||||
sigCertFilePathName: "src/GPKI/certs/SVR5640020001_sig.cer"
|
||||
```
|
||||
|
||||
### 8.2 External Mode 설정
|
||||
|
||||
```yaml
|
||||
vmis:
|
||||
integration:
|
||||
mode: external # ⭐ External Mode 활성화
|
||||
|
||||
# 외부 API 서버 설정
|
||||
external:
|
||||
api:
|
||||
url: "http://localhost:8081/api/v1/vehicles"
|
||||
connectTimeoutMillis: 5000
|
||||
readTimeoutMillis: 10000
|
||||
```
|
||||
|
||||
### 8.3 개발 환경 설정 (GPKI 비활성화)
|
||||
|
||||
```yaml
|
||||
vmis:
|
||||
integration:
|
||||
mode: internal
|
||||
|
||||
gpki:
|
||||
enabled: "N" # ⭐ GPKI 비활성화
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. 사용 예제
|
||||
|
||||
### 9.1 기본 사용법
|
||||
|
||||
```java
|
||||
@RestController
|
||||
@RequestMapping("/api/vehicles")
|
||||
@RequiredArgsConstructor
|
||||
public class VehicleController {
|
||||
|
||||
private final VehicleInfoService vehicleInfoService;
|
||||
|
||||
/**
|
||||
* 단일 차량 조회
|
||||
*/
|
||||
@GetMapping("/{vehicleNumber}")
|
||||
public ResponseEntity<VehicleApiResponseVO> getVehicle(
|
||||
@PathVariable String vehicleNumber) {
|
||||
|
||||
VehicleApiResponseVO response = vehicleInfoService.getVehicleInfo(vehicleNumber);
|
||||
|
||||
if (response.isSuccess()) {
|
||||
return ResponseEntity.ok(response);
|
||||
} else {
|
||||
return ResponseEntity.badRequest().body(response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 일괄 조회
|
||||
*/
|
||||
@PostMapping("/batch")
|
||||
public ResponseEntity<List<VehicleApiResponseVO>> getVehicles(
|
||||
@RequestBody List<String> vehicleNumbers) {
|
||||
|
||||
List<VehicleApiResponseVO> responses =
|
||||
vehicleInfoService.getVehiclesInfo(vehicleNumbers);
|
||||
|
||||
return ResponseEntity.ok(responses);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 9.2 Service Layer에서 사용
|
||||
|
||||
```java
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class InspectionService {
|
||||
|
||||
private final VehicleInfoService vehicleInfoService;
|
||||
|
||||
public void performInspection(String vehicleNumber) {
|
||||
// 1. 차량 정보 조회
|
||||
VehicleApiResponseVO vehicleInfo =
|
||||
vehicleInfoService.getVehicleInfo(vehicleNumber);
|
||||
|
||||
if (!vehicleInfo.isSuccess()) {
|
||||
throw new VehicleNotFoundException(vehicleNumber);
|
||||
}
|
||||
|
||||
// 2. 차량 정보를 사용한 비즈니스 로직
|
||||
VehicleBasicInfoVO basicInfo = vehicleInfo.getBasicInfo();
|
||||
String ownerName = basicInfo.getVhrNm(); // 소유자명
|
||||
String modelYear = basicInfo.getYridnw(); // 연식
|
||||
|
||||
// 3. 검사 수행
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 9.3 응답 데이터 활용
|
||||
|
||||
```java
|
||||
VehicleApiResponseVO response = vehicleInfoService.getVehicleInfo("12가3456");
|
||||
|
||||
if (response.isSuccess()) {
|
||||
// 기본정보 활용
|
||||
VehicleBasicInfoVO basic = response.getBasicInfo();
|
||||
System.out.println("차량번호: " + basic.getVhrno());
|
||||
System.out.println("소유자: " + basic.getVhrNm());
|
||||
System.out.println("차종: " + basic.getVhctyNm());
|
||||
System.out.println("용도: " + basic.getVhclPrposNm());
|
||||
|
||||
// 등록원부 활용
|
||||
VehicleLedgerVO ledger = response.getLedgerInfo();
|
||||
System.out.println("최초등록일: " + ledger.getFrstRegistDe());
|
||||
System.out.println("등록상태: " + ledger.getRegistSttusNm());
|
||||
} else {
|
||||
System.err.println("조회 실패: " + response.getMessage());
|
||||
}
|
||||
```
|
||||
|
||||
### 9.4 일괄 조회 예제
|
||||
|
||||
```java
|
||||
List<String> vehicleNumbers = Arrays.asList(
|
||||
"12가3456",
|
||||
"34나5678",
|
||||
"56다7890"
|
||||
);
|
||||
|
||||
List<VehicleApiResponseVO> responses =
|
||||
vehicleInfoService.getVehiclesInfo(vehicleNumbers);
|
||||
|
||||
// 성공/실패 분류
|
||||
List<VehicleApiResponseVO> successful = responses.stream()
|
||||
.filter(VehicleApiResponseVO::isSuccess)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<VehicleApiResponseVO> failed = responses.stream()
|
||||
.filter(r -> !r.isSuccess())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
System.out.println("성공: " + successful.size());
|
||||
System.out.println("실패: " + failed.size());
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. 모드 전환 시나리오
|
||||
|
||||
### 10.1 개발 → 운영 전환
|
||||
|
||||
```yaml
|
||||
# 개발 환경 (application-local.yml)
|
||||
vmis:
|
||||
integration:
|
||||
mode: internal
|
||||
gpki:
|
||||
enabled: "N" # GPKI 비활성화
|
||||
```
|
||||
|
||||
```yaml
|
||||
# 운영 환경 (application-prod.yml)
|
||||
vmis:
|
||||
integration:
|
||||
mode: internal
|
||||
gpki:
|
||||
enabled: "Y" # GPKI 활성화
|
||||
system:
|
||||
infoSysIp: "${SERVER_IP}" # 실제 서버 IP
|
||||
```
|
||||
|
||||
### 10.2 Monolithic → MSA 전환
|
||||
|
||||
```yaml
|
||||
# Phase 1: 단일 애플리케이션 (Internal Mode)
|
||||
vmis:
|
||||
integration:
|
||||
mode: internal
|
||||
```
|
||||
|
||||
```yaml
|
||||
# Phase 2: 마이크로서비스 (External Mode)
|
||||
vmis:
|
||||
integration:
|
||||
mode: external
|
||||
external:
|
||||
api:
|
||||
url: "http://vmis-service:8080/api/v1/vehicles"
|
||||
```
|
||||
|
||||
**코드 변경 없이 설정만으로 전환 가능!**
|
||||
|
||||
---
|
||||
|
||||
## 11. 트러블슈팅
|
||||
|
||||
### 11.1 Bean 충돌 오류
|
||||
|
||||
**증상:**
|
||||
```
|
||||
expected single matching bean but found 2:
|
||||
internalVehicleInfoServiceImpl, externalVehicleInfoServiceImpl
|
||||
```
|
||||
|
||||
**원인:**
|
||||
`vmis.integration.mode` 설정이 잘못되었거나 누락됨
|
||||
|
||||
**해결:**
|
||||
```yaml
|
||||
vmis:
|
||||
integration:
|
||||
mode: internal # 또는 external (반드시 지정)
|
||||
```
|
||||
|
||||
### 11.2 Mapper 중복 스캔 경고
|
||||
|
||||
**증상:**
|
||||
```
|
||||
Skipping MapperFactoryBean with name 'vmisCarBassMatterInqireMapper'
|
||||
Bean already defined with the same name!
|
||||
```
|
||||
|
||||
**원인:**
|
||||
여러 `@MapperScan`에서 같은 패키지를 중복 스캔
|
||||
|
||||
**해결:**
|
||||
`ApiMapperConfig`에서 API 전용 Mapper만 스캔하도록 분리되어 있음
|
||||
|
||||
### 11.3 GPKI 오류 (운영 환경)
|
||||
|
||||
**증상:**
|
||||
```
|
||||
GPKI 초기화 실패: 인증서 파일을 찾을 수 없습니다
|
||||
```
|
||||
|
||||
**해결:**
|
||||
1. GPKI 인증서 파일 경로 확인
|
||||
2. 개발 환경에서는 `gpki.enabled: "N"` 설정
|
||||
|
||||
---
|
||||
|
||||
## 12. 성능 최적화
|
||||
|
||||
### 12.1 Internal Mode 최적화
|
||||
- RestTemplate Connection Pool 설정 활용
|
||||
- GPKI 세션 재사용
|
||||
- DB 커넥션 풀 튜닝
|
||||
|
||||
### 12.2 External Mode 최적화
|
||||
- 외부 API 서버와 동일 네트워크 배치
|
||||
- Circuit Breaker 패턴 적용 (향후)
|
||||
- 캐싱 전략 (향후)
|
||||
|
||||
---
|
||||
|
||||
## 13. 보안 고려사항
|
||||
|
||||
### 13.1 GPKI 인증서 관리
|
||||
- 인증서 파일 접근 권한 제한
|
||||
- 패스워드는 환경변수로 관리
|
||||
- 인증서 만료 모니터링
|
||||
|
||||
### 13.2 API Key 관리
|
||||
```yaml
|
||||
vmis:
|
||||
gov:
|
||||
services:
|
||||
basic:
|
||||
apiKey: "${GOV_API_KEY_BASIC}" # 환경변수 사용
|
||||
```
|
||||
|
||||
### 13.3 로깅 주의사항
|
||||
- 차량번호 등 개인정보는 마스킹 처리
|
||||
- 요청/응답 전문은 DEBUG 레벨로 출력
|
||||
|
||||
---
|
||||
|
||||
## 14. 확장 가능성
|
||||
|
||||
### 14.1 새로운 모드 추가
|
||||
Strategy Pattern을 사용하므로 새로운 구현체 추가 가능:
|
||||
|
||||
```java
|
||||
@Service
|
||||
@ConditionalOnProperty(name = "vmis.integration.mode", havingValue = "cache")
|
||||
public class CachedVehicleInfoServiceImpl implements VehicleInfoService {
|
||||
// 캐시 기반 구현
|
||||
}
|
||||
```
|
||||
|
||||
### 14.2 새로운 차량 정보 조회 API 추가
|
||||
1. 정부 API 인터페이스 메서드 추가
|
||||
2. Service 계층에 메서드 추가
|
||||
3. Mapper 및 Model 추가
|
||||
4. VehicleInfoService 인터페이스 확장
|
||||
|
||||
---
|
||||
|
||||
## 15. 참고 자료
|
||||
|
||||
### 15.1 관련 설정 파일
|
||||
- `src/main/resources/application.yml`
|
||||
- `src/main/resources/mybatis/mapper/api-internal/`
|
||||
|
||||
### 15.2 관련 문서
|
||||
- Spring Boot Conditional Beans
|
||||
- Strategy Pattern
|
||||
- MyBatis Integration
|
||||
|
||||
---
|
||||
|
||||
**문서 버전:** 1.0
|
||||
**최종 수정일:** 2025-11-07
|
||||
**작성자:** VIPS Development Team
|
||||
@ -1,813 +0,0 @@
|
||||
# Rocky Linux 9.5 MariaDB 설치 및 설정 가이드
|
||||
|
||||
## 요구사항
|
||||
1. Rocky Linux 9.5 version
|
||||
2. root 권한 또는 sudo 권한이 있는 계정
|
||||
3. 목표: MariaDB 설치, 보안 설정, 사용자 생성, 데이터베이스 생성, 백업 스키마 복원
|
||||
|
||||
---
|
||||
|
||||
## 1단계: MariaDB 설치
|
||||
|
||||
### 1.1 MariaDB 서버 설치
|
||||
```bash
|
||||
# MariaDB 서버 및 클라이언트 설치
|
||||
dnf install -y mariadb-server mariadb
|
||||
|
||||
# 또는 yum 사용
|
||||
yum install -y mariadb-server mariadb
|
||||
```
|
||||
|
||||
### 1.2 MariaDB 서비스 시작 및 자동 시작 설정
|
||||
```bash
|
||||
# MariaDB 서비스 시작
|
||||
systemctl start mariadb
|
||||
|
||||
# 부팅 시 자동 시작 설정
|
||||
systemctl enable mariadb
|
||||
|
||||
# 서비스 상태 확인
|
||||
systemctl status mariadb
|
||||
```
|
||||
|
||||
### 1.3 MariaDB 버전 확인
|
||||
```bash
|
||||
# MariaDB 버전 확인
|
||||
mysql --version
|
||||
|
||||
# 또는 MariaDB 접속 후 확인
|
||||
mysql -e "SELECT VERSION();"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2단계: MariaDB 보안 설정
|
||||
|
||||
### 2.1 초기 보안 설정 실행
|
||||
```bash
|
||||
# MariaDB 보안 설정 스크립트 실행
|
||||
mysql_secure_installation
|
||||
```
|
||||
|
||||
### 2.2 보안 설정 질문 및 권장 답변
|
||||
설정 중 아래와 같은 질문이 나타납니다:
|
||||
|
||||
```
|
||||
1. Enter current password for root (enter for none):
|
||||
→ 처음 설치 시 비밀번호가 없으므로 Enter 입력
|
||||
|
||||
2. Switch to unix_socket authentication [Y/n]
|
||||
→ n (기존 방식 유지 권장)
|
||||
|
||||
3. Change the root password? [Y/n]
|
||||
→ Y (root 비밀번호 설정)
|
||||
→ 새 비밀번호 입력 및 확인
|
||||
|
||||
4. Remove anonymous users? [Y/n]
|
||||
→ Y (익명 사용자 제거)
|
||||
|
||||
5. Disallow root login remotely? [Y/n]
|
||||
→ Y (원격 root 로그인 차단 - 보안 강화)
|
||||
→ n (원격 접속이 필요한 경우)
|
||||
|
||||
6. Remove test database and access to it? [Y/n]
|
||||
→ Y (테스트 데이터베이스 제거)
|
||||
|
||||
7. Reload privilege tables now? [Y/n]
|
||||
→ Y (권한 테이블 즉시 적용)
|
||||
```
|
||||
|
||||
### 2.3 root로 MariaDB 접속 확인
|
||||
```bash
|
||||
# root 계정으로 MariaDB 접속
|
||||
mysql -u root -p
|
||||
# 비밀번호 입력 후 접속
|
||||
|
||||
# 접속 확인 후 종료
|
||||
MariaDB [(none)]> show databases;
|
||||
MariaDB [(none)]> exit;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3단계: 커스텀 포트 설정 (53306)
|
||||
|
||||
### 3.1 MariaDB 포트 변경
|
||||
```bash
|
||||
# MariaDB 설정 파일 편집
|
||||
vi /etc/my.cnf.d/mariadb-server.cnf
|
||||
```
|
||||
|
||||
설정 파일에 포트 추가:
|
||||
```ini
|
||||
[mysqld]
|
||||
port=53306
|
||||
```
|
||||
|
||||
설정 변경 후 서비스 재시작:
|
||||
```bash
|
||||
# MariaDB 재시작
|
||||
systemctl restart mariadb
|
||||
|
||||
# 포트 확인
|
||||
ss -tlnp | grep 53306
|
||||
```
|
||||
|
||||
### 3.2 방화벽 설정 (외부 접속 허용)
|
||||
```bash
|
||||
# 커스텀 포트(53306) 방화벽 허용
|
||||
firewall-cmd --permanent --add-port=53306/tcp
|
||||
firewall-cmd --reload
|
||||
|
||||
# 방화벽 설정 확인
|
||||
firewall-cmd --list-all
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4단계: 데이터베이스 생성
|
||||
|
||||
### 4.1 MariaDB 접속
|
||||
```bash
|
||||
# root로 MariaDB 접속
|
||||
mysql -u root -p
|
||||
# 비밀번호 입력
|
||||
```
|
||||
|
||||
### 4.2 데이터베이스 생성
|
||||
```sql
|
||||
-- VIPS 데이터베이스 생성
|
||||
CREATE DATABASE vips CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- 데이터베이스 목록 확인
|
||||
SHOW DATABASES;
|
||||
|
||||
-- VIPS 데이터베이스 선택
|
||||
USE vips;
|
||||
```
|
||||
|
||||
### 4.3 데이터베이스 문자셋 확인
|
||||
```sql
|
||||
-- 데이터베이스 문자셋 확인
|
||||
SELECT
|
||||
SCHEMA_NAME,
|
||||
DEFAULT_CHARACTER_SET_NAME,
|
||||
DEFAULT_COLLATION_NAME
|
||||
FROM information_schema.SCHEMATA
|
||||
WHERE SCHEMA_NAME = 'vips';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5단계: 사용자 생성 및 권한 부여
|
||||
|
||||
### 5.1 로컬 접속용 사용자 생성
|
||||
```sql
|
||||
-- VIPS 로컬 접속용 사용자 생성
|
||||
CREATE USER 'vips'@'localhost' IDENTIFIED BY 'xit5811807';
|
||||
|
||||
-- VIPS 데이터베이스에 모든 권한 부여
|
||||
GRANT ALL PRIVILEGES ON vips.* TO 'vips'@'localhost';
|
||||
|
||||
-- 권한 적용
|
||||
FLUSH PRIVILEGES;
|
||||
```
|
||||
|
||||
### 5.2 원격 접속용 사용자 생성
|
||||
```sql
|
||||
-- 특정 IP에서 접속 가능한 사용자 생성
|
||||
CREATE USER 'vips'@'192.168.1.100' IDENTIFIED BY 'xit5811807';
|
||||
GRANT ALL PRIVILEGES ON vips.* TO 'vips'@'192.168.1.100';
|
||||
|
||||
-- 모든 IP에서 접속 가능한 사용자 생성 (application-prd.yml 설정)
|
||||
CREATE USER 'vips'@'%' IDENTIFIED BY 'xit5811807';
|
||||
GRANT ALL PRIVILEGES ON vips.* TO 'vips'@'%';
|
||||
|
||||
-- 권한 적용
|
||||
FLUSH PRIVILEGES;
|
||||
```
|
||||
|
||||
### 5.3 읽기 전용 사용자 생성 (선택사항)
|
||||
```sql
|
||||
-- 읽기 전용 사용자 생성
|
||||
CREATE USER 'vips_readonly'@'%' IDENTIFIED BY 'vips_readonly_password';
|
||||
GRANT SELECT ON vips.* TO 'vips_readonly'@'%';
|
||||
FLUSH PRIVILEGES;
|
||||
```
|
||||
|
||||
### 5.4 사용자 목록 및 권한 확인
|
||||
```sql
|
||||
-- 사용자 목록 확인
|
||||
SELECT User, Host FROM mysql.user;
|
||||
|
||||
-- VIPS 사용자의 권한 확인
|
||||
SHOW GRANTS FOR 'vips'@'localhost';
|
||||
SHOW GRANTS FOR 'vips'@'%';
|
||||
|
||||
-- 현재 사용자 확인
|
||||
SELECT USER(), CURRENT_USER();
|
||||
```
|
||||
|
||||
### 5.5 원격 접속을 위한 MariaDB 설정 변경
|
||||
```bash
|
||||
# MariaDB 설정 파일 편집
|
||||
vi /etc/my.cnf.d/mariadb-server.cnf
|
||||
```
|
||||
|
||||
설정 파일에서 다음 부분 수정:
|
||||
```ini
|
||||
[mysqld]
|
||||
# bind-address를 주석 처리하거나 0.0.0.0으로 변경
|
||||
# bind-address=127.0.0.1
|
||||
bind-address=0.0.0.0
|
||||
|
||||
# 또는 특정 IP만 허용
|
||||
# bind-address=192.168.1.50
|
||||
```
|
||||
|
||||
설정 변경 후 서비스 재시작:
|
||||
```bash
|
||||
# MariaDB 재시작
|
||||
systemctl restart mariadb
|
||||
|
||||
# 재시작 확인
|
||||
systemctl status mariadb
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6단계: 백업 스키마 업로드 (전체 데이터베이스 복원)
|
||||
|
||||
### 6.1 백업 파일 서버로 전송
|
||||
|
||||
**방법 1: SCP 사용 (로컬 PC에서 실행)**
|
||||
```bash
|
||||
# Windows PowerShell 또는 CMD에서 실행
|
||||
scp C:\backup\vips_backup.sql root@서버IP:/tmp/
|
||||
```
|
||||
|
||||
**방법 2: SFTP 사용**
|
||||
```bash
|
||||
# SFTP 접속
|
||||
sftp root@서버IP
|
||||
|
||||
# 파일 전송
|
||||
put vips_backup.sql /tmp/
|
||||
exit
|
||||
```
|
||||
|
||||
### 6.2 백업 파일 권한 설정
|
||||
```bash
|
||||
# 백업 파일 권한 확인
|
||||
ls -la /tmp/vips_backup.sql
|
||||
|
||||
# 필요시 권한 변경
|
||||
chmod 644 /tmp/vips_backup.sql
|
||||
```
|
||||
|
||||
### 6.3 백업 파일 복원 - 방법 1 (명령행에서 직접 복원)
|
||||
```bash
|
||||
# 커스텀 포트 53306 사용하여 복원
|
||||
mysql -u root -p -P 53306 vips < /tmp/vips_backup.sql
|
||||
|
||||
# 비밀번호 입력 없이 실행 (스크립트용)
|
||||
mysql -u root -p비밀번호 -P 53306 vips < /tmp/vips_backup.sql
|
||||
```
|
||||
|
||||
### 6.4 백업 파일 복원 - 방법 2 (MySQL 내부에서 복원)
|
||||
```bash
|
||||
# MariaDB 접속 (포트 53306 명시)
|
||||
mysql -u root -p -P 53306
|
||||
```
|
||||
|
||||
```sql
|
||||
-- VIPS 데이터베이스 선택
|
||||
USE vips;
|
||||
|
||||
-- 백업 파일 실행
|
||||
SOURCE /tmp/vips_backup.sql;
|
||||
|
||||
-- 또는
|
||||
\. /tmp/vips_backup.sql
|
||||
```
|
||||
|
||||
### 6.5 백업 파일 복원 - 방법 3 (새 데이터베이스 생성 포함)
|
||||
백업 파일에 CREATE DATABASE가 포함된 경우:
|
||||
```bash
|
||||
# 데이터베이스 이름 지정 없이 복원 (포트 53306)
|
||||
mysql -u root -p -P 53306 < /tmp/vips_backup.sql
|
||||
```
|
||||
|
||||
### 6.6 대용량 백업 파일 복원
|
||||
대용량 파일의 경우 타임아웃 방지를 위한 옵션 추가:
|
||||
```bash
|
||||
# 타임아웃 설정 증가 (포트 53306)
|
||||
mysql -u root -p -P 53306 \
|
||||
--max_allowed_packet=512M \
|
||||
--connect_timeout=3600 \
|
||||
--wait_timeout=3600 \
|
||||
vips < /tmp/vips_backup.sql
|
||||
```
|
||||
|
||||
### 6.7 압축된 백업 파일 복원
|
||||
```bash
|
||||
# .gz 파일 복원 (포트 53306)
|
||||
gunzip < /tmp/vips_backup.sql.gz | mysql -u root -p -P 53306 vips
|
||||
|
||||
# .zip 파일 복원 (포트 53306)
|
||||
unzip -p /tmp/vips_backup.sql.zip | mysql -u root -p -P 53306 vips
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7단계: 복원 결과 확인
|
||||
|
||||
### 7.1 MariaDB 접속
|
||||
```bash
|
||||
# VIPS 사용자로 접속 (포트 53306)
|
||||
mysql -u vips -p -P 53306 vips
|
||||
# 비밀번호 입력: xit5811807
|
||||
```
|
||||
|
||||
### 7.2 데이터베이스 및 테이블 확인
|
||||
```sql
|
||||
-- 현재 데이터베이스 확인
|
||||
SELECT DATABASE();
|
||||
|
||||
-- 테이블 목록 확인
|
||||
SHOW TABLES;
|
||||
|
||||
-- 테이블 개수 확인
|
||||
SELECT COUNT(*) AS table_count
|
||||
FROM information_schema.tables
|
||||
WHERE table_schema = 'vips';
|
||||
|
||||
-- 각 테이블의 상세 정보 확인
|
||||
SHOW TABLE STATUS FROM vips;
|
||||
```
|
||||
|
||||
### 7.3 테이블 구조 확인
|
||||
```sql
|
||||
-- 특정 테이블 구조 확인 (VIPS 테이블 예시)
|
||||
DESC tb_vehicle_info;
|
||||
-- 또는
|
||||
DESCRIBE tb_vehicle_info;
|
||||
-- 또는
|
||||
SHOW COLUMNS FROM tb_vehicle_info;
|
||||
|
||||
-- 테이블 생성 DDL 확인
|
||||
SHOW CREATE TABLE tb_vehicle_info;
|
||||
```
|
||||
|
||||
### 7.4 데이터 확인
|
||||
```sql
|
||||
-- 특정 테이블의 레코드 수 확인
|
||||
SELECT COUNT(*) FROM tb_vehicle_info;
|
||||
|
||||
-- 상위 10개 데이터 조회
|
||||
SELECT * FROM tb_vehicle_info LIMIT 10;
|
||||
|
||||
-- 모든 테이블의 레코드 수 확인
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
TABLE_ROWS
|
||||
FROM information_schema.TABLES
|
||||
WHERE TABLE_SCHEMA = 'vips'
|
||||
ORDER BY TABLE_ROWS DESC;
|
||||
```
|
||||
|
||||
### 7.5 인덱스 및 제약조건 확인
|
||||
```sql
|
||||
-- 특정 테이블의 인덱스 확인
|
||||
SHOW INDEX FROM tb_vehicle_info;
|
||||
|
||||
-- 외래키 제약조건 확인
|
||||
SELECT
|
||||
CONSTRAINT_NAME,
|
||||
TABLE_NAME,
|
||||
COLUMN_NAME,
|
||||
REFERENCED_TABLE_NAME,
|
||||
REFERENCED_COLUMN_NAME
|
||||
FROM information_schema.KEY_COLUMN_USAGE
|
||||
WHERE TABLE_SCHEMA = 'vips'
|
||||
AND REFERENCED_TABLE_NAME IS NOT NULL;
|
||||
```
|
||||
|
||||
### 7.6 데이터베이스 용량 확인
|
||||
```sql
|
||||
-- VIPS 데이터베이스 전체 크기 확인
|
||||
SELECT
|
||||
table_schema AS 'Database',
|
||||
ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS 'Size (MB)'
|
||||
FROM information_schema.tables
|
||||
WHERE table_schema = 'vips'
|
||||
GROUP BY table_schema;
|
||||
|
||||
-- 테이블별 크기 확인
|
||||
SELECT
|
||||
table_name AS 'Table',
|
||||
ROUND(((data_length + index_length) / 1024 / 1024), 2) AS 'Size (MB)'
|
||||
FROM information_schema.tables
|
||||
WHERE table_schema = 'vips'
|
||||
ORDER BY (data_length + index_length) DESC;
|
||||
```
|
||||
|
||||
### 7.7 문자셋 확인
|
||||
```sql
|
||||
-- 데이터베이스 문자셋 확인
|
||||
SHOW VARIABLES LIKE 'character_set%';
|
||||
SHOW VARIABLES LIKE 'collation%';
|
||||
|
||||
-- 포트 확인
|
||||
SHOW VARIABLES LIKE 'port';
|
||||
|
||||
-- VIPS 테이블의 문자셋 확인
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
TABLE_COLLATION
|
||||
FROM information_schema.TABLES
|
||||
WHERE TABLE_SCHEMA = 'vips';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8단계: 접속 테스트 및 문제 해결
|
||||
|
||||
### 8.1 로컬 접속 테스트
|
||||
```bash
|
||||
# VIPS 사용자로 로컬 접속 테스트 (포트 53306)
|
||||
mysql -u vips -p -P 53306 vips
|
||||
|
||||
# 접속 후 간단한 쿼리 실행
|
||||
mysql -u vips -pxit5811807 -P 53306 vips -e "SELECT COUNT(*) AS table_count FROM information_schema.tables WHERE table_schema='vips';"
|
||||
```
|
||||
|
||||
### 8.2 원격 접속 테스트 (다른 서버에서)
|
||||
```bash
|
||||
# 원격 서버에서 접속 테스트 (application-prd.yml 설정과 동일)
|
||||
mysql -h 211.119.124.117 -P 53306 -u vips -p vips
|
||||
|
||||
# 비밀번호 포함하여 테스트 (스크립트용)
|
||||
mysql -h 211.119.124.117 -P 53306 -u vips -pxit5811807 vips -e "SHOW TABLES;"
|
||||
```
|
||||
|
||||
### 8.3 접속 문제 해결
|
||||
|
||||
**문제 1: Access denied for user**
|
||||
```sql
|
||||
-- MariaDB에 root로 접속하여 사용자 확인
|
||||
SELECT User, Host FROM mysql.user WHERE User='vips';
|
||||
|
||||
-- 호스트가 일치하지 않으면 재생성
|
||||
DROP USER 'vips'@'잘못된호스트';
|
||||
CREATE USER 'vips'@'올바른호스트' IDENTIFIED BY 'xit5811807';
|
||||
GRANT ALL PRIVILEGES ON vips.* TO 'vips'@'올바른호스트';
|
||||
FLUSH PRIVILEGES;
|
||||
```
|
||||
|
||||
**문제 2: Can't connect to MySQL server**
|
||||
```bash
|
||||
# MariaDB 서비스 상태 확인
|
||||
systemctl status mariadb
|
||||
|
||||
# 서비스가 중지되어 있으면 시작
|
||||
systemctl start mariadb
|
||||
|
||||
# 커스텀 포트 53306 리스닝 확인
|
||||
ss -tlnp | grep 53306
|
||||
netstat -tlnp | grep 53306
|
||||
|
||||
# 포트 설정 확인
|
||||
mysql -u root -p -e "SHOW VARIABLES LIKE 'port';"
|
||||
|
||||
# 방화벽 확인
|
||||
firewall-cmd --list-all
|
||||
```
|
||||
|
||||
**문제 3: 원격 접속 불가**
|
||||
```bash
|
||||
# bind-address 설정 확인
|
||||
grep bind-address /etc/my.cnf.d/mariadb-server.cnf
|
||||
|
||||
# 0.0.0.0 또는 원하는 IP로 설정되어 있는지 확인
|
||||
# 변경 후 재시작 필요
|
||||
systemctl restart mariadb
|
||||
```
|
||||
|
||||
**문제 4: 복원 중 에러 발생**
|
||||
```bash
|
||||
# 에러 로그 확인
|
||||
tail -100 /var/log/mariadb/mariadb.log
|
||||
|
||||
# 또는
|
||||
journalctl -u mariadb -n 100
|
||||
|
||||
# SQL 파일 문법 확인 (일부만 실행해보기)
|
||||
head -100 /tmp/myapp_db_backup.sql
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9단계: 백업 설정 (추가 운영 관리)
|
||||
|
||||
### 9.1 수동 백업 명령어
|
||||
```bash
|
||||
# VIPS 전체 데이터베이스 백업 (포트 53306)
|
||||
mysqldump -u root -p -P 53306 vips > /backup/vips_$(date +%Y%m%d_%H%M%S).sql
|
||||
|
||||
# 압축 백업
|
||||
mysqldump -u root -p -P 53306 vips | gzip > /backup/vips_$(date +%Y%m%d_%H%M%S).sql.gz
|
||||
|
||||
# 특정 테이블만 백업
|
||||
mysqldump -u root -p -P 53306 vips tb_vehicle_info tb_user > /backup/vips_tables_$(date +%Y%m%d).sql
|
||||
|
||||
# 구조만 백업 (데이터 제외)
|
||||
mysqldump -u root -p -P 53306 --no-data vips > /backup/vips_schema_only.sql
|
||||
|
||||
# 데이터만 백업 (구조 제외)
|
||||
mysqldump -u root -p -P 53306 --no-create-info vips > /backup/vips_data_only.sql
|
||||
```
|
||||
|
||||
### 9.2 백업 디렉토리 생성 및 권한 설정
|
||||
```bash
|
||||
# 백업 디렉토리 생성
|
||||
mkdir -p /backup/mariadb
|
||||
|
||||
# 권한 설정
|
||||
chown root:root /backup/mariadb
|
||||
chmod 700 /backup/mariadb
|
||||
```
|
||||
|
||||
### 9.3 자동 백업 스크립트 생성
|
||||
```bash
|
||||
# 백업 스크립트 생성
|
||||
vi /backup/mariadb_backup.sh
|
||||
```
|
||||
|
||||
스크립트 내용:
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# VIPS 데이터베이스 백업 스크립트
|
||||
DB_NAME="vips"
|
||||
DB_USER="root"
|
||||
DB_PASS="your_root_password"
|
||||
DB_PORT="53306"
|
||||
BACKUP_DIR="/backup/mariadb"
|
||||
DATE=$(date +%Y%m%d_%H%M%S)
|
||||
BACKUP_FILE="$BACKUP_DIR/${DB_NAME}_${DATE}.sql.gz"
|
||||
RETENTION_DAYS=7
|
||||
|
||||
# 백업 디렉토리 생성 (없으면)
|
||||
mkdir -p $BACKUP_DIR
|
||||
|
||||
# 백업 실행
|
||||
echo "Starting VIPS database backup at $(date)"
|
||||
mysqldump -u $DB_USER -p$DB_PASS -P $DB_PORT $DB_NAME | gzip > $BACKUP_FILE
|
||||
|
||||
# 백업 결과 확인
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "Backup completed successfully: $BACKUP_FILE"
|
||||
|
||||
# 파일 크기 확인
|
||||
FILE_SIZE=$(du -h "$BACKUP_FILE" | cut -f1)
|
||||
echo "Backup file size: $FILE_SIZE"
|
||||
|
||||
# 오래된 백업 파일 삭제 (7일 이상)
|
||||
find $BACKUP_DIR -name "${DB_NAME}_*.sql.gz" -mtime +$RETENTION_DAYS -delete
|
||||
echo "Old backups cleaned up (retention: $RETENTION_DAYS days)"
|
||||
else
|
||||
echo "Backup failed!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Backup process finished at $(date)"
|
||||
```
|
||||
|
||||
스크립트 실행 권한 부여:
|
||||
```bash
|
||||
chmod 700 /backup/mariadb_backup.sh
|
||||
```
|
||||
|
||||
### 9.4 cron을 이용한 자동 백업 설정
|
||||
```bash
|
||||
# crontab 편집
|
||||
crontab -e
|
||||
```
|
||||
|
||||
cron 설정 추가:
|
||||
```bash
|
||||
# 매일 새벽 2시에 백업 실행
|
||||
0 2 * * * /backup/mariadb_backup.sh >> /backup/mariadb/backup.log 2>&1
|
||||
|
||||
# 매주 일요일 새벽 3시에 백업 실행
|
||||
0 3 * * 0 /backup/mariadb_backup.sh >> /backup/mariadb/backup.log 2>&1
|
||||
|
||||
# 매월 1일 새벽 4시에 백업 실행
|
||||
0 4 1 * * /backup/mariadb_backup.sh >> /backup/mariadb/backup.log 2>&1
|
||||
```
|
||||
|
||||
cron 설정 확인:
|
||||
```bash
|
||||
# crontab 목록 확인
|
||||
crontab -l
|
||||
|
||||
# cron 서비스 상태 확인
|
||||
systemctl status crond
|
||||
|
||||
# cron 로그 확인
|
||||
tail -f /var/log/cron
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 전체 실행 순서 요약
|
||||
|
||||
```bash
|
||||
# 1. MariaDB 설치
|
||||
dnf install -y mariadb-server mariadb
|
||||
systemctl start mariadb
|
||||
systemctl enable mariadb
|
||||
|
||||
# 2. 보안 설정
|
||||
mysql_secure_installation
|
||||
|
||||
# 3. 커스텀 포트 설정 (53306)
|
||||
vi /etc/my.cnf.d/mariadb-server.cnf
|
||||
# [mysqld] 섹션에 port=53306 추가
|
||||
|
||||
# 4. 원격 접속 설정
|
||||
vi /etc/my.cnf.d/mariadb-server.cnf
|
||||
# bind-address=0.0.0.0 설정
|
||||
systemctl restart mariadb
|
||||
|
||||
# 5. 방화벽 설정
|
||||
firewall-cmd --permanent --add-port=53306/tcp
|
||||
firewall-cmd --reload
|
||||
|
||||
# 6. 포트 확인
|
||||
ss -tlnp | grep 53306
|
||||
|
||||
# 7. MariaDB 접속하여 데이터베이스 및 사용자 생성
|
||||
mysql -u root -p -P 53306
|
||||
```
|
||||
|
||||
```sql
|
||||
-- VIPS 데이터베이스 생성
|
||||
CREATE DATABASE vips CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- VIPS 사용자 생성 및 권한 부여
|
||||
CREATE USER 'vips'@'localhost' IDENTIFIED BY 'xit5811807';
|
||||
GRANT ALL PRIVILEGES ON vips.* TO 'vips'@'localhost';
|
||||
|
||||
-- 원격 접속용 사용자 (application-prd.yml 설정)
|
||||
CREATE USER 'vips'@'%' IDENTIFIED BY 'xit5811807';
|
||||
GRANT ALL PRIVILEGES ON vips.* TO 'vips'@'%';
|
||||
|
||||
FLUSH PRIVILEGES;
|
||||
exit;
|
||||
```
|
||||
|
||||
```bash
|
||||
# 8. 백업 파일 업로드 (로컬 PC에서)
|
||||
scp vips_backup.sql root@서버IP:/tmp/
|
||||
|
||||
# 9. 백업 복원 (서버에서, 포트 53306 명시)
|
||||
mysql -u root -p -P 53306 vips < /tmp/vips_backup.sql
|
||||
|
||||
# 10. 복원 확인
|
||||
mysql -u vips -pxit5811807 -P 53306 vips
|
||||
```
|
||||
|
||||
```sql
|
||||
-- 테이블 확인
|
||||
SHOW TABLES;
|
||||
SELECT COUNT(*) AS table_count FROM information_schema.tables WHERE table_schema='vips';
|
||||
exit;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 유용한 MariaDB 관리 명령어
|
||||
|
||||
### 데이터베이스 관리
|
||||
```sql
|
||||
-- 모든 데이터베이스 목록
|
||||
SHOW DATABASES;
|
||||
|
||||
-- 데이터베이스 삭제 (주의!)
|
||||
DROP DATABASE vips;
|
||||
|
||||
-- 데이터베이스 이름 변경 (직접 지원 안함, 백업/복원 필요)
|
||||
-- 방법: 백업 → 새 DB 생성 → 복원 → 기존 DB 삭제
|
||||
```
|
||||
|
||||
### 사용자 관리
|
||||
```sql
|
||||
-- 모든 사용자 목록
|
||||
SELECT User, Host FROM mysql.user;
|
||||
|
||||
-- VIPS 사용자 비밀번호 변경
|
||||
ALTER USER 'vips'@'localhost' IDENTIFIED BY 'new_password';
|
||||
ALTER USER 'vips'@'%' IDENTIFIED BY 'new_password';
|
||||
|
||||
-- 사용자 삭제
|
||||
DROP USER 'vips'@'localhost';
|
||||
DROP USER 'vips'@'%';
|
||||
|
||||
-- 특정 권한만 회수
|
||||
REVOKE DELETE ON vips.* FROM 'vips'@'localhost';
|
||||
|
||||
-- 모든 권한 회수
|
||||
REVOKE ALL PRIVILEGES ON vips.* FROM 'vips'@'localhost';
|
||||
```
|
||||
|
||||
### 테이블 관리
|
||||
```sql
|
||||
-- 테이블 삭제
|
||||
DROP TABLE table_name;
|
||||
|
||||
-- 테이블 비우기 (구조는 유지)
|
||||
TRUNCATE TABLE table_name;
|
||||
|
||||
-- 테이블 이름 변경
|
||||
RENAME TABLE old_name TO new_name;
|
||||
|
||||
-- 테이블 복사
|
||||
CREATE TABLE new_table LIKE old_table;
|
||||
INSERT INTO new_table SELECT * FROM old_table;
|
||||
```
|
||||
|
||||
### 성능 모니터링
|
||||
```sql
|
||||
-- 현재 실행 중인 쿼리 확인
|
||||
SHOW PROCESSLIST;
|
||||
|
||||
-- 특정 프로세스 강제 종료
|
||||
KILL [process_id];
|
||||
|
||||
-- 상태 변수 확인
|
||||
SHOW STATUS;
|
||||
SHOW VARIABLES;
|
||||
|
||||
-- 느린 쿼리 확인
|
||||
SHOW VARIABLES LIKE 'slow_query%';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 보안 권장사항
|
||||
|
||||
1. **강력한 비밀번호 사용**
|
||||
- 최소 12자 이상, 대소문자/숫자/특수문자 조합
|
||||
|
||||
2. **최소 권한 원칙**
|
||||
- 애플리케이션 사용자에게 필요한 최소 권한만 부여
|
||||
- 읽기 전용 작업에는 SELECT 권한만 부여
|
||||
|
||||
3. **원격 root 접속 차단**
|
||||
- root는 localhost에서만 접속 허용
|
||||
|
||||
4. **정기적인 백업**
|
||||
- 매일 자동 백업 설정
|
||||
- 백업 파일 주기적 확인
|
||||
|
||||
5. **방화벽 설정**
|
||||
- 필요한 IP만 53306 포트 접근 허용
|
||||
- 특정 IP 대역만 접근 허용 설정
|
||||
```bash
|
||||
# 특정 IP만 허용 (예시)
|
||||
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port protocol="tcp" port="53306" accept'
|
||||
firewall-cmd --reload
|
||||
```
|
||||
|
||||
6. **MariaDB 업데이트**
|
||||
- 정기적인 보안 패치 적용
|
||||
```bash
|
||||
dnf update mariadb-server
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 참고사항
|
||||
|
||||
- **VIPS 프로젝트 설정**
|
||||
- 데이터베이스: vips
|
||||
- 사용자: vips
|
||||
- 비밀번호: xit5811807
|
||||
- 포트: 53306 (커스텀 포트)
|
||||
- 문자셋: UTF-8 (utf8mb4)
|
||||
|
||||
- **MariaDB 기본 정보**
|
||||
- 기본 포트: 3306 (VIPS는 53306 사용)
|
||||
- 설정 파일 위치: `/etc/my.cnf`, `/etc/my.cnf.d/mariadb-server.cnf`
|
||||
- 데이터 디렉토리: `/var/lib/mysql/`
|
||||
- 로그 파일: `/var/log/mariadb/mariadb.log`
|
||||
- 소켓 파일: `/var/lib/mysql/mysql.sock`
|
||||
|
||||
---
|
||||
|
||||
## 문의 및 추가 정보
|
||||
|
||||
- MariaDB 공식 문서: https://mariadb.com/kb/
|
||||
- Rocky Linux 공식 문서: https://docs.rockylinux.org/
|
||||
@ -1,23 +0,0 @@
|
||||
자동차 검사 경과 안내서 대상차량 대장
|
||||
---------------------------------------
|
||||
프로그램 ID : VGD01B
|
||||
처 리 일 자 : 2025년07월11일~2025년07월11일 출 력 일 시 : 2025년12월04일17시01분
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
번호 자동차번호 소유자명 주민등록번호 차 명 사용 본거지 주소 검사유효기간
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
1 11라7770 정배영 카이엔 경기도 용인시 기흥구 연원로42번길 10 2023-07-12~2025-07-11
|
||||
810301-1177777 126동 302호(마북동, 블루밍 구성 더센트럴)
|
||||
2 15저5555 이유희 스파크 1.0 DOHC 경기도 용인시 기흥구 이현로29번길 72-33 2023-07-12~2025-07-11
|
||||
810306-1637778 132동 902호(보정동, 성호샤인힐즈아파트)
|
||||
3 22소5555 박윤성 쏘렌토 경기도 용인시 수지구 죽전로 155 2023-07-12~2025-07-11
|
||||
670406-1777778 5층(죽전동)
|
||||
4 33고3355 주식회사 올놀카(상품용) C220 d 4Matic 경기도 용인시 기흥구 중부대로 255 2023-07-12~2025-07-11
|
||||
134511-0327770 A동 3층 S367호(영덕동, 오토허브)
|
||||
5 65조4444 정문치 레이 경기도 용인시 기흥구 흥덕4로15번길 23-55 2021-07-12~2025-07-11
|
||||
791203-1067771 304호(영덕동)
|
||||
6 88조8888 고영유 그랜저(GRANDEUR) 경기도 용인시 수지구 성복2로 555 2023-07-12~2025-07-11
|
||||
900426-1087772 2층 204호(성복동)
|
||||
7 99모9999 주윤산업(주) 포터Ⅱ(PORTERⅡ) 경기도 용인시 기흥구 농서로153번길 55-1 2024-07-12~2025-07-11
|
||||
134511-0347779 (농서동)
|
||||
8 경기99아9999 (주)삼성에우앤유 마이티 경기도 용인시 수지구 손곡로 55 2024-07-12~2025-07-11
|
||||
130111-0007776 (동천동)
|
||||
@ -0,0 +1,25 @@
|
||||
유효기간경과 과태료부과대상 리스트
|
||||
------------------------------------
|
||||
|
||||
|
||||
* 최종등록일이 검사일자보다 늦는 경우는 소유자 및 사용본거지 주소를 재확인하여 주시기 바랍니다. (재검여부 = *일수)
|
||||
* 전출차량( *차번호)인 경우 전출 전의 주소입니다. 소유자 및 사용본거지 주소를 재확인하여 주시기 바랍니다.
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
검사소 검사일자 자동차번호 소유자명 주민등록번호 차 명 차 종 용 도 종료일 일수 과태료
|
||||
최종등록일 주 소 유효기간만료일 매매상품용
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
H494 2025-11-01 경기11사2222 행주운수(주) 1111110081111 엠뱅크언더리프 특수차구난형소영업용 2021-01-05 1761 30만원
|
||||
2025-07-14 경기도 용인시 기흥구 강남로 9, 111-111호(신행동, 진주만프라자) 2020-12-05
|
||||
|
||||
H500 2025-11-01 22고2222 주식회사 아일공행산업 1111106811111 그랜드 스타렉스 화물차밴형소형자가용 2025-04-28 187 60만원
|
||||
2025-10-01 경기도 용인시 처인구 포곡읍 포곡로 222-2, 202호 2025-03-28
|
||||
|
||||
H692 2025-11-01 33마3333 홍길동 7604092328316 SM6 승용차일반형중자가용 2025-07-14 110 56만원
|
||||
2025-09-22 경기도 용인시 기흥구 관곡로 53, 605동 1802호(구갈동, 가현마을신안아파트) 2025-06-11
|
||||
|
||||
H271 2025-11-01 44구4444 제제제이엔지 주식회사 1111110064044 봉고Ⅲ 1톤 화물차일반형- 자가용 2025-08-25 68 28만원
|
||||
2020-05-20 경기도 용인시 처인구 포곡읍 에버랜드로 444(0-44동(4층)) 2025-07-24
|
||||
|
||||
H420 2025-11-01 55서5555 김철수 5555261080555 아이오닉6 (IONI 승용차일반형중자가용 2025-08-25 68 28만원
|
||||
2024-09-09 경기도 용인시 수지구 성복1로 55, 505동 505호(성오동, 성오역 서피오타치오) 2025-07-25
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
유효기간경과 과태료부과대상 리스트
|
||||
------------------------------------
|
||||
|
||||
|
||||
* 최종등록일이 검사일자보다 늦는 경우는 소유자 및 사용본거지 주소를 재확인하여 주시기 바랍니다. (재검여부 = *일수)
|
||||
* 전출차량( *차번호)인 경우 전출 전의 주소입니다. 소유자 및 사용본거지 주소를 재확인하여 주시기 바랍니다.
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
검사소 검사일자 자동차번호 소유자명 주민등록번호 차 명 차 종 용 도 종료일 일수 과태료
|
||||
최종등록일 주 소 유효기간만료일 매매상품용
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
H494 2025-11-01 경기11사2222 행주운수(주) 1111110081111 엠뱅크언더리프 특수차구난형소영업용 2021-01-05 1761 30만원
|
||||
2025-07-14 경기도 용인시 기흥구 강남로 9, 111-111호(신행동, 진주만프라자) 2020-12-05
|
||||
|
||||
H500 2025-11-01 22고2222 주식회사 아일공행산업 111110681111 그랜드 스타렉스 화물차밴형소형자가용 2025-04-28 187 60만원
|
||||
2025-10-01 경기도 용인시 처인구 포곡읍 포곡로 222-2, 202호 2025-03-28
|
||||
|
||||
H692 2025-11-01 33마3333 홍길동 7604092328316 SM6 승용차일반형중자가용 2025-07-14 110 56만원
|
||||
2025-09-22 경기도 용인시 기흥구 관곡로 53, 605동 1802호(구갈동, 가현마을신안아파트) 2025-06-11
|
||||
|
||||
H271 2025-11-01 44구4444 제제제이엔지 주식회사 1111110064044 봉고Ⅲ 1톤 화물차일반형- 자가용 2025-08-25 68 28만원
|
||||
2020-05-20 경기도 용인시 처인구 포곡읍 에버랜드로 444(0-44동(4층)) 2025-07-24
|
||||
|
||||
H420 2025-11-01 55서5555 김철수 5555261080555 아이오닉6 (IONI 승용차일반형중자가용 2025-08-25 68 28만원
|
||||
2024-09-09 경기도 용인시 수지구 성복1로 55, 505동 505호(성오동, 성오역 서피오타치오) 2025-07-25
|
||||
|
||||
@ -1,252 +0,0 @@
|
||||
# VIPS 서버 관리 가이드
|
||||
|
||||
## 목차
|
||||
- [1. 서버 접속](#1-서버-접속)
|
||||
- [1.1 최초 터미널 접속](#11-최초-터미널-접속)
|
||||
- [1.2 root 계정 접속](#12-root-계정-접속)
|
||||
- [1.3 xit 계정 접속](#13-xit-계정-접속)
|
||||
- [2. MariaDB 접속](#2-mariadb-접속)
|
||||
- [3. WAR 파일 배포](#3-war-파일-배포)
|
||||
- [4. 애플리케이션 실행](#4-애플리케이션-실행)
|
||||
- [4.1 소스 위치 정보](#41-소스-위치-정보)
|
||||
- [4.2 직접 실행](#42-직접-실행)
|
||||
- [4.3 백그라운드 실행](#43-백그라운드-실행)
|
||||
- [4.4 백그라운드 프로세스 중지](#44-백그라운드-프로세스-중지)
|
||||
- [5. Systemd 서비스 설정](#5-systemd-서비스-설정)
|
||||
- [5.1 서비스 파일 설정](#51-서비스-파일-설정)
|
||||
- [5.2 Systemd 명령어](#52-systemd-명령어)
|
||||
- [6. MariaDB 데이터베이스 백업](#6-mariadb-데이터베이스-백업)
|
||||
- [6.1 백업 디렉토리 생성](#61-백업-디렉토리-생성)
|
||||
- [6.2 백업 스크립트 생성](#62-백업-스크립트-생성)
|
||||
- [6.3 Crontab 설정 (매일 밤 12시 자동 백업)](#63-crontab-설정-매일-밤-12시-자동-백업)
|
||||
- [6.4 백업 관련 명령어](#64-백업-관련-명령어)
|
||||
|
||||
---
|
||||
|
||||
## 1. 서버 접속
|
||||
|
||||
### 1.1 최초 터미널 접속
|
||||
PuTTY를 이용하여 자동차 검사 서버에 접속합니다.
|
||||
|
||||
```bash
|
||||
id: tune
|
||||
password: dyddls12# # 한글명: 용인12#
|
||||
```
|
||||
|
||||
### 1.2 root 계정 접속
|
||||
|
||||
```bash
|
||||
su -
|
||||
password: dyddls12# # 한글명: 용인12#
|
||||
```
|
||||
|
||||
### 1.3 xit 계정 접속
|
||||
|
||||
```bash
|
||||
su - xit
|
||||
password: xit5811807
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. MariaDB 접속
|
||||
리눅스 root 계정에서 실행합니다.
|
||||
|
||||
```bash
|
||||
mysql -u vips -p -P 53306
|
||||
password: xit5811807 # mariadb root 계정 비밀번호도 동일
|
||||
```
|
||||
|
||||
```sql
|
||||
use vips;
|
||||
show tables;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. WAR 파일 배포
|
||||
Windows에서 Linux로 SCP를 이용하여 소스를 업로드합니다.
|
||||
|
||||
**Windows CMD에서 실행:**
|
||||
```cmd
|
||||
scp -P1922 c:\VIPS\VIPS-BOOT.war xit@105.19.10.124:/app/VIPS/
|
||||
password: xit5811807
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 애플리케이션 실행
|
||||
리눅스 xit 계정에서 실행합니다.
|
||||
|
||||
### 4.1 소스 위치 정보
|
||||
|
||||
```bash
|
||||
cd /app/VIPS/ # 애플리케이션 디렉토리
|
||||
cd /app/VIPS/logs/ # 로그 디렉토리
|
||||
```
|
||||
|
||||
### 4.2 직접 실행
|
||||
실시간 로그 확인 가능, `Ctrl+C`로 즉시 중지
|
||||
|
||||
```bash
|
||||
java -Dspring.profiles.active=prd -jar /app/VIPS/VIPS-BOOT.war
|
||||
```
|
||||
|
||||
### 4.3 백그라운드 실행
|
||||
|
||||
```bash
|
||||
nohup java -Dspring.profiles.active=prd -jar /app/VIPS/VIPS-BOOT.war > /dev/null 2>&1 &
|
||||
```
|
||||
|
||||
### 4.4 백그라운드 프로세스 중지
|
||||
|
||||
```bash
|
||||
# 프로세스 확인
|
||||
ps -ef | grep VIPS
|
||||
|
||||
# PID 확인 후 종료
|
||||
kill -9 [PID]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Systemd 서비스 설정
|
||||
자동 재기동을 위한 systemd 서비스 설정입니다. **root 계정**에서 실행합니다.
|
||||
|
||||
### 5.1 서비스 파일 설정
|
||||
|
||||
```bash
|
||||
vi /etc/systemd/system/vips.service
|
||||
```
|
||||
|
||||
**서비스 파일 내용:**
|
||||
```ini
|
||||
[Unit]
|
||||
Description=VIPS Spring Boot Application
|
||||
After=network.target
|
||||
# 600초(10분) 동안의 재시작 횟수를 카운트, 최대 5번까지만 재시작 시도
|
||||
StartLimitIntervalSec=600
|
||||
StartLimitBurst=5
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=xit
|
||||
Group=xit
|
||||
WorkingDirectory=/app/VIPS
|
||||
# ExecStart=/usr/lib/jvm/java-1.8.0-openjdk/bin/java -Xms512m -Xmx1024m -Dspring.profiles.active=prd -jar /app/VIPS/VIPS-BOOT.war
|
||||
ExecStart=/usr/lib/jvm/java-1.8.0-openjdk/bin/java -Dspring.profiles.active=prd -jar /app/VIPS/VIPS-BOOT.war
|
||||
# ExecStop=/bin/kill -15 $MAINPID
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
### 5.2 Systemd 명령어
|
||||
|
||||
```bash
|
||||
# systemd 데몬 리로드 (서비스 파일 수정 후 실행)
|
||||
systemctl daemon-reload
|
||||
|
||||
# 부팅 시 자동 시작 설정
|
||||
systemctl enable vips
|
||||
|
||||
# 상태 확인
|
||||
systemctl status vips
|
||||
|
||||
# 서비스 시작
|
||||
systemctl start vips
|
||||
|
||||
# 서비스 중지
|
||||
systemctl stop vips
|
||||
|
||||
# 서비스 재시작
|
||||
systemctl restart vips
|
||||
|
||||
# 실시간 로그 확인
|
||||
journalctl -u vips -f
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. MariaDB 데이터베이스 백업
|
||||
**root 계정**에서 실행합니다.
|
||||
|
||||
### 6.1 백업 디렉토리 생성
|
||||
|
||||
```bash
|
||||
mkdir -p /app/db/backup
|
||||
chmod 755 /app/db/backup
|
||||
```
|
||||
|
||||
### 6.2 백업 스크립트 생성
|
||||
|
||||
```bash
|
||||
vi /app/db/backup/backup_vips.sh
|
||||
```
|
||||
|
||||
**스크립트 내용:**
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# 백업 설정
|
||||
BACKUP_DIR="/app/db/backup"
|
||||
DB_NAME="vips"
|
||||
DB_USER="vips"
|
||||
DB_PASSWORD="xit5811807"
|
||||
DB_PORT="53306"
|
||||
DATE=$(date +%Y%m%d_%H%M%S)
|
||||
BACKUP_FILE="${BACKUP_DIR}/${DB_NAME}_${DATE}.sql"
|
||||
|
||||
# 백업 실행
|
||||
mysqldump -u ${DB_USER} -p${DB_PASSWORD} -P ${DB_PORT} ${DB_NAME} > ${BACKUP_FILE}
|
||||
|
||||
# 백업 파일 압축
|
||||
gzip ${BACKUP_FILE}
|
||||
|
||||
# 30일 이상 된 백업 파일 삭제
|
||||
find ${BACKUP_DIR} -name "${DB_NAME}_*.sql.gz" -type f -mtime +30 -delete
|
||||
|
||||
# 백업 결과 로그
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') - 백업 성공: ${BACKUP_FILE}.gz" >> ${BACKUP_DIR}/backup.log
|
||||
else
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') - 백업 실패" >> ${BACKUP_DIR}/backup.log
|
||||
fi
|
||||
```
|
||||
|
||||
**실행 권한 부여:**
|
||||
```bash
|
||||
chmod 700 /app/db/backup/backup_vips.sh
|
||||
```
|
||||
|
||||
### 6.3 Crontab 설정 (매일 밤 12시 자동 백업)
|
||||
|
||||
```bash
|
||||
# crontab 편집
|
||||
crontab -e
|
||||
|
||||
# 아래 내용 추가
|
||||
0 0 * * * /app/db/backup/backup_vips.sh
|
||||
```
|
||||
|
||||
### 6.4 백업 관련 명령어
|
||||
|
||||
```bash
|
||||
# 수동 백업 실행
|
||||
/app/db/backup/backup_vips.sh
|
||||
|
||||
# 백업 파일 목록 확인
|
||||
ls -lh /app/db/backup/
|
||||
|
||||
# 백업 로그 확인
|
||||
tail -f /app/db/backup/backup.log
|
||||
|
||||
# crontab 설정 확인
|
||||
crontab -l
|
||||
|
||||
# 백업 복원 (필요시)
|
||||
gunzip /app/db/backup/vips_20240101_000000.sql.gz
|
||||
mysql -u vips -p -P 53306 vips < /app/db/backup/vips_20240101_000000.sql
|
||||
```
|
||||
@ -0,0 +1,25 @@
|
||||
유효기간경과 과태료부과대상 리스트
|
||||
------------------------------------
|
||||
|
||||
|
||||
* 최종등록일이 검사일자보다 늦는 경우는 소유자 및 사용본거지 주소를 재확인하여 주시기 바랍니다. (재검여부 = *일수)
|
||||
* 전출차량( *차번호)인 경우 전출 전의 주소입니다. 소유자 및 사용본거지 주소를 재확인하여 주시기 바랍니다.
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
검사소 검사일자 자동차번호 소유자명 주민등록번호 차 명 차 종 용 도 종료일 일수 과태료
|
||||
최종등록일 주 소 유효기간만료일 매매상품용
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
H494 2025-11-01 경기11사2222 행주운수(주) 1111110081111 엠뱅크언더리프 특수차구난형소영업용 2021-01-05 1761 30만원
|
||||
2025-07-14 경기도 용인시 기흥구 강남로 9, 111-111호(신행동, 진주만프라자) 2020-12-05
|
||||
|
||||
H500 2025-11-01 22고2222 주식회사 아일공행산업 1111106811111 그랜드 스타렉스 화물차밴형소형자가용 2025-04-28 187 60만원
|
||||
2025-10-01 경기도 용인시 처인구 포곡읍 포곡로 222-2, 202호 2025-03-28
|
||||
|
||||
H692 2025-11-01 33마3333 홍길동 7604092328316 SM6 승용차일반형중자가용 2025-07-14 110 56만원
|
||||
2025-09-22 경기도 용인시 기흥구 관곡로 53, 605동 1802호(구갈동, 가현마을신안아파트) 2025-06-11
|
||||
|
||||
H271 2025-11-01 44구4444 제제제이엔지 주식회사 1111110064044 봉고Ⅲ 1톤 화물차일반형- 자가용 2025-08-25 68 28만원
|
||||
2020-05-20 경기도 용인시 처인구 포곡읍 에버랜드로 444(0-44동(4층)) 2025-07-24
|
||||
|
||||
H420 2025-11-01 55서5555 김철수 5555261080555 아이오닉6 (IONI 승용차일반형중자가용 2025-08-25 68 28만원
|
||||
2024-09-09 경기도 용인시 수지구 성복1로 55, 505동 505호(성오동, 성오역 서피오타치오) 2025-07-25
|
||||
|
||||
@ -0,0 +1,152 @@
|
||||
# 자동차 과태료 비교 로직 정리
|
||||
|
||||
## 개요
|
||||
|
||||
### 중요 사항
|
||||
- ⚠️ **순서가 중요합니다!**
|
||||
- 조건에 걸리는 순간 다음 차량번호 비교를 진행합니다.
|
||||
|
||||
### 로직 변경 사항
|
||||
|
||||
#### 변경 전
|
||||
- 하나의 API를 호출해서 비교 로직 진행
|
||||
|
||||
#### 변경 후
|
||||
1. **기본 호출**: `TB_CAR_FFNLG_TRGT.검사일` 기준으로 API 호출 (기본정보 + 갑부정보)
|
||||
2. **추가 호출**: 각 비교 로직마다 필요한 API 추가 호출
|
||||
- 차량기본정보
|
||||
- 갑부정보
|
||||
- 기본정보 + 갑부정보
|
||||
|
||||
**예시**: 이첩-2의 경우, `(TB_CAR_FFNLG_TRGT.검사종료일자 + 115일)` 기준으로 차량기본정보 API 추가 호출
|
||||
|
||||
---
|
||||
|
||||
## 비교 로직 상세
|
||||
|
||||
### 1. 상품용 검증 [차량기본정보 필요]
|
||||
|
||||
#### 조건
|
||||
1. `TB_CAR_FFNLG_TRGT.검사일` 기준 API 호출
|
||||
2. `api.MBER_NM like '%상품용%'`
|
||||
3. 갑부 상세(LedgerRecord) 리스트에서 다음 조건 확인:
|
||||
```
|
||||
(List.CHG_YMD between TB_CAR_FFNLG_TRGT.유효기간만료일 and TB_CAR_FFNLG_TRGT.검사종료일자)
|
||||
AND
|
||||
(List.CHANGE_JOB_SE_CODE = '11') -- 명의이전 코드
|
||||
```
|
||||
|
||||
#### 처리 결과
|
||||
- **TB_CAR_FFNLG_TRGT.비고**: `"[상품용] 갑부정보"`
|
||||
|
||||
---
|
||||
|
||||
### 2. 이첩-1 [차량등록원부(갑) 필요]
|
||||
|
||||
#### 조건
|
||||
1. `TB_CAR_FFNLG_TRGT.검사일` 기준 API 호출
|
||||
2. 법정동코드 불일치 검증
|
||||
|
||||
#### 검증 로직 (Java)
|
||||
|
||||
```java
|
||||
/**
|
||||
* 이첩 조건1: 법정동코드 불일치
|
||||
* 사용본거지법정동코드 앞 4자리 != 사용자 조직코드 앞 4자리
|
||||
*/
|
||||
private boolean checkTransferCondition1_LegalDongMismatch(
|
||||
BasicResponse.Record basicInfo,
|
||||
String userId,
|
||||
String vhclno
|
||||
) {
|
||||
String useStrnghldLegaldongCode = basicInfo.getUseStrnghldLegaldongCode();
|
||||
|
||||
// 법정동코드 유효성 검사
|
||||
if (useStrnghldLegaldongCode == null || useStrnghldLegaldongCode.length() < 4) {
|
||||
log.debug("[이첩][조건1] 법정동코드 없음. 차량번호: {}", vhclno);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 사용자 정보 조회
|
||||
SystemUserVO userInfo = userMapper.selectUser(userId);
|
||||
if (userInfo == null || userInfo.getOrgCd() == null) {
|
||||
log.debug("[이첩][조건1] 사용자 정보 없음. 사용자ID: {}", userId);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 법정동코드 앞 4자리 vs 사용자 조직코드 앞 4자리 비교
|
||||
String legalDong4 = useStrnghldLegaldongCode.substring(0, 4);
|
||||
String userOrgCd = userInfo.getOrgCd();
|
||||
String userOrg4 = userOrgCd.length() >= 4 ? userOrgCd.substring(0, 4) : userOrgCd;
|
||||
|
||||
if (legalDong4.equals(userOrg4)) {
|
||||
log.debug("[이첩][조건1] 법정동코드 일치. 차량번호: {}, 법정동: {}, 조직: {}",
|
||||
vhclno, legalDong4, userOrg4);
|
||||
return false;
|
||||
}
|
||||
|
||||
log.info("[이첩][조건1] 법정동코드 불일치! 차량번호: {}, 법정동: {}, 조직: {}",
|
||||
vhclno, legalDong4, userOrg4);
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
#### 처리 결과
|
||||
- **TB_CAR_FFNLG_TRGT.비고**: `"서울시 용산구 / 이경호, 검사일사용본거지, [검사대상, 사용자 조직코드 앞 4자리 및 법정동명]"`
|
||||
|
||||
---
|
||||
|
||||
### 3. 이첩-2 [차량기본정보 필요]
|
||||
|
||||
#### 조건
|
||||
1. `TB_CAR_FFNLG_TRGT.DAYCNT` (textFile 일수) > 115
|
||||
2. **검사일 기준** API 호출
|
||||
3. **(검사종료일자 + 115일) 기준** API 호출 (추가)
|
||||
4. 2번 API와 3번 API의 자동차기본정보 비교
|
||||
- **사용본거지법정동코드 앞 4자리**가 다를 경우
|
||||
|
||||
#### 처리 결과
|
||||
- **TB_CAR_FFNLG_TRGT.비고**: `"전라남도 순천시 / 김정대, 115일 도래지, [2개의 API 법정동코드 및 법정동명]"`
|
||||
|
||||
---
|
||||
|
||||
## 데이터 흐름도
|
||||
|
||||
```
|
||||
TB_CAR_FFNLG_TRGT (과태료 대상)
|
||||
↓
|
||||
검사일 기준 API 호출 (기본정보 + 갑부정보)
|
||||
↓
|
||||
┌─────────────┬─────────────┬─────────────┐
|
||||
│ 상품용 │ 이첩-1 │ 이첩-2 │
|
||||
│ 검증 로직 │ 검증 로직 │ 검증 로직 │
|
||||
└─────────────┴─────────────┴─────────────┘
|
||||
↓ ↓ ↓
|
||||
조건 만족 시 비고 업데이트 → 다음 차량번호 처리
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 핵심 필드 매핑
|
||||
|
||||
| 테이블 | 필드명 | 설명 |
|
||||
|--------|--------|------|
|
||||
| TB_CAR_FFNLG_TRGT | 검사일 | API 호출 기준일 (기본) |
|
||||
| TB_CAR_FFNLG_TRGT | 검사종료일자 | 이첩-2에서 +115일 계산에 사용 |
|
||||
| TB_CAR_FFNLG_TRGT | 유효기간만료일 | 상품용 검증 기간 시작일 |
|
||||
| TB_CAR_FFNLG_TRGT | DAYCNT | 일수 (이첩-2 조건) |
|
||||
| TB_CAR_FFNLG_TRGT | 비고 | 검증 결과 저장 |
|
||||
| API 기본정보 | MBER_NM | 회원명 (상품용 검증) |
|
||||
| API 기본정보 | useStrnghldLegaldongCode | 사용본거지법정동코드 (이첩 검증) |
|
||||
| API 갑부 상세 | CHG_YMD | 변경일자 (상품용 기간 검증) |
|
||||
| API 갑부 상세 | CHANGE_JOB_SE_CODE | 변경작업구분코드 (명의이전: 11) |
|
||||
| 사용자 정보 | OrgCd | 조직코드 (이첩-1 검증) |
|
||||
|
||||
---
|
||||
|
||||
## 주의사항
|
||||
|
||||
1. **순차 처리**: 각 차량번호는 조건에 걸리는 즉시 다음 차량번호로 넘어갑니다.
|
||||
2. **API 호출 최적화**: 기본적으로 검사일 기준 API를 호출하고, 필요시에만 추가 호출합니다.
|
||||
3. **로그 기록**: 각 검증 단계마다 상세 로그를 남겨 추적 가능하도록 합니다.
|
||||
4. **에러 처리**: API 호출 실패 또는 데이터 부재 시 적절한 에러 처리가 필요합니다.
|
||||
@ -1,264 +0,0 @@
|
||||
# 자동차 과태료 비교 로직 명세서 (미필)
|
||||
|
||||
## 개요
|
||||
|
||||
자동차 과태료 부과 대상(미필)을 검증하기 위한 비교 로직 정의서입니다.
|
||||
|
||||
### 구현 위치
|
||||
- **Checker 클래스**: `src/main/java/go/kr/project/carInspectionPenalty/registrationOm/service/impl/om_checker/`
|
||||
- `ProductUseOmChecker.java` - 1. 상품용 : 상품용
|
||||
- `OwnerTransferOmChecker.java` - 2. 명의이전 소유자 확인 : 명의이전(25.9.5.) 이전소유자 상품용, 경상남도 창원시/ 현대캐피탈 주식회사, 미수검명의이전(25.5.19.)(37하1553)
|
||||
- `TransferOmChecker.java` - 3. 이첩 : 경기도 과천시/ 이정호, 115일 도래지
|
||||
|
||||
### 기본 설정
|
||||
- 비교로직에 사용되는 API: `ExternalVehicleApiServiceImpl.getBasicInfo`, `getLedgerInfo` 호출
|
||||
- 날짜 유틸리티: `DateUtil.parseDate()`, `DateUtil.formatDateString()` 사용
|
||||
- **미필 부과일자**: 검사유효기간 종료일 + 146일 (`levyCrtrYmd`)
|
||||
|
||||
### 문서 이력
|
||||
|
||||
| 일자 | 변경 내용 | 비고 |
|
||||
|------|----------|------|
|
||||
| 2025-12-08 | om_checker 소스 기준 전면 작성 | 실제 코드와 일치하도록 정리 |
|
||||
| 2025-12-09 | 검사유효기간 종료일 + 31일 로직 반영 | ProductUseOmChecker, OwnerTransferOmChecker |
|
||||
|
||||
### 처리 규칙
|
||||
|
||||
> **중요**: 순서가 중요함!
|
||||
> 1. 상품용 → 2. 명의이전 소유자 확인 → 3. 이첩
|
||||
> - 조건에 걸리는 순간 다음 차량번호 비교로 진행
|
||||
> - 각 비교 로직별로 개별 API 호출 수행
|
||||
|
||||
---
|
||||
|
||||
## 비교 로직 상세
|
||||
|
||||
### 1. 상품용 검증 (`ProductUseOmChecker`)
|
||||
|
||||
**처리상태코드**: `02` (상품용)
|
||||
**클래스**: `ProductUseOmChecker.java`
|
||||
|
||||
#### API 호출 순서
|
||||
|
||||
| 순서 | API | 입력 파라미터 | 출력 데이터 | 용도 |
|
||||
|------|-----|--------------|-------------|------|
|
||||
| 1 | 자동차기본정보 | `차량번호`, `부과일자=검사유효기간종료일+146일` | `차대번호(vin)`, `소유자명`, `대표소유자회원번호` | 부과일자 기준 소유자 확인 |
|
||||
| 2 | 자동차기본정보 | `1.차대번호`, `부과일자=오늘` | `차량번호`, `성명`, `주민번호`, `법정동코드` | 현재 소유자 정보 |
|
||||
| 3 | 자동차등록원부(갑) | `2.차량번호`, `2.성명`, `2.주민번호`, `2.법정동코드` | 갑부 상세 List | 명의이전 이력 조회 |
|
||||
| 4 | 자동차기본정보 | `1.차대번호`, `부과일자=CHG_YMD` | `소유자명`, `대표소유자회원번호` | 명의이전 시점 소유자 확인 |
|
||||
|
||||
#### 비교 조건
|
||||
|
||||
```
|
||||
1. Step1 소유자명.contains("상품용") ← 상품용 아니면 return null
|
||||
|
||||
2. Step2 대표소유자회원번호 == Step1 대표소유자회원번호
|
||||
← 불일치면 return null
|
||||
|
||||
3. 갑부에서 명의이전(11) 레코드 찾기
|
||||
- CHG_TASK_SE_CD == "11"
|
||||
- CHG_YMD <= 검사유효기간 종료일 + 31일
|
||||
- 가장 마지막 일자 선택
|
||||
← 없으면 return null
|
||||
|
||||
4. Step4 대표소유자회원번호 == Step1 대표소유자회원번호
|
||||
← 불일치면 return null
|
||||
|
||||
→ 모든 조건 충족: 상품용(02) 처리
|
||||
```
|
||||
|
||||
#### DB 업데이트 필드
|
||||
|
||||
```java
|
||||
existingData.setTaskPrcsSttsCd("02"); // 상품용
|
||||
existingData.setCarBscMttrInqFlnm(step4OwnerName);
|
||||
existingData.setCarRegFrmbkChgTaskSeCd("11");
|
||||
existingData.setCarRegFrmbkChgYmd(targetRecord.getChgYmd());
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. 명의이전 소유자 확인 (`OwnerTransferOmChecker`)
|
||||
|
||||
**처리상태코드**: `01` (그대로 접수)
|
||||
**클래스**: `OwnerTransferOmChecker.java`
|
||||
|
||||
#### API 호출 순서
|
||||
|
||||
| 순서 | API | 입력 파라미터 | 출력 데이터 | 용도 |
|
||||
|------|-----|--------------|-------------|------|
|
||||
| 1 | 자동차기본정보 | `차량번호`, `부과일자=검사유효기간종료일+146일` | `차대번호(vin)`, `소유자명` | 부과일자 기준 소유자 확인 |
|
||||
| 2 | 자동차기본정보 | `1.차대번호`, `부과일자=오늘` | `차량번호`, `성명`, `주민번호`, `법정동코드` | 현재 소유자 정보 |
|
||||
| 3 | 자동차등록원부(갑) | `2.차량번호`, `2.성명`, `2.주민번호`, `2.법정동코드` | 갑부 상세 List | 명의이전 이력 조회 |
|
||||
| 4 | 자동차기본정보 | `1.차대번호`, `부과일자=CHG_YMD-1일` | `소유자명` | 명의이전 직전 소유자 확인 |
|
||||
|
||||
#### 비교 조건
|
||||
|
||||
```
|
||||
1. Step1 소유자명.contains("상품용") → return null (1번에서 처리됨)
|
||||
!Step1 소유자명.contains("상품용") → 계속 진행
|
||||
|
||||
2. 갑부에서 명의이전(11) 레코드 찾기
|
||||
- CHG_TASK_SE_CD == "11"
|
||||
- CHG_YMD > 검사유효기간 종료일 + 31일
|
||||
- 가장 마지막 일자 선택
|
||||
← 없으면 return null
|
||||
|
||||
3. Step4 소유자명 확인
|
||||
- "상품용" 포함 → 접수(01)
|
||||
- "상품용" 미포함 → 접수(01)
|
||||
|
||||
→ 모든 조건 충족: 접수(01) 처리
|
||||
```
|
||||
|
||||
#### 결과 분기
|
||||
|
||||
| Step4 소유자명 | 처리상태코드 | 비고 형식 |
|
||||
|---------------|-----------|-----------|
|
||||
| 상품용 포함 | `01` (접수) | 명의이전(날짜) 이전소유자 상품용 |
|
||||
| 상품용 미포함 | `01` (접수) | 명의이전(날짜) |
|
||||
|
||||
#### DB 업데이트 필드
|
||||
|
||||
```java
|
||||
existingData.setTaskPrcsSttsCd("01"); // 접수
|
||||
existingData.setCarBscMttrInqFlnm(step4OwnerName);
|
||||
existingData.setCarRegFrmbkChgTaskSeCd("11");
|
||||
existingData.setCarRegFrmbkChgYmd(targetRecord.getChgYmd());
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. 이첩 검증 (`TransferOmChecker`)
|
||||
|
||||
**처리상태코드**: `03` (이첩)
|
||||
**클래스**: `TransferOmChecker.java`
|
||||
|
||||
#### API 호출 순서
|
||||
|
||||
| 순서 | API | 입력 파라미터 | 출력 데이터 | 용도 |
|
||||
|------|-----|--------------|-------------|------|
|
||||
| 1 | 자동차기본정보 | `차량번호`, `부과일자=검사유효기간종료일+146일` | `소유자명`, `소유자회원번호`, `사용본거지법정동코드`, `차대번호` | 부과일자 기준 정보 |
|
||||
| 2 | 자동차기본정보 | `1.차대번호`, `부과일자=검사유효기간종료일-90일` | `소유자명`, `소유자회원번호` | 90일 전 소유자 확인 |
|
||||
| 3 | 자동차기본정보 | `1.차대번호`, `부과일자=오늘` | `소유자명`, `소유자회원번호` | 현재 소유자 확인 |
|
||||
|
||||
#### 비교 조건
|
||||
|
||||
```
|
||||
1. Step1 소유자명.contains("상품용") → return null (1번에서 처리됨)
|
||||
!Step1 소유자명.contains("상품용") → 계속 진행
|
||||
|
||||
2. Step1 소유자회원번호 != Step2 소유자회원번호
|
||||
← 불일치면 return null
|
||||
|
||||
3. Step1 소유자회원번호 != Step3 소유자회원번호
|
||||
← 불일치면 return null
|
||||
|
||||
4. 법정동코드 앞 4자리 == 사용자 조직코드 앞 4자리
|
||||
← 일치하면 return null
|
||||
|
||||
→ 불일치: 이첩(03) 처리
|
||||
```
|
||||
|
||||
#### 결과 처리
|
||||
|
||||
| 구분 | 비고 컬럼 형식 |
|
||||
|------|---------------|
|
||||
| 이첩 | `"{시군구명}, 115일 도래지, [법정동코드: {legalDong4}, 법정동명: {sggNm}]"` |
|
||||
|
||||
#### DB 업데이트 필드
|
||||
|
||||
```java
|
||||
existingData.setTaskPrcsSttsCd("03"); // 이첩
|
||||
existingData.setCarBscMttrInqFlnm(step1RprsOwnrNm);
|
||||
existingData.setCarBscMttrInqSggCd(sggCd);
|
||||
existingData.setCarBscMttrInqSggNm(sggNm);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 처리 흐름도
|
||||
|
||||
```
|
||||
시작
|
||||
│
|
||||
▼
|
||||
[차량번호 조회]
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────────────────────────┐
|
||||
│ 1. 상품용 (ProductUseOmChecker) │
|
||||
│ 조건: 부과일자 소유자명.contains("상품용") │
|
||||
│ + 명의이전(11) 레코드 존재 │
|
||||
│ + CHG_YMD <= 검사유효기간종료일+31일 │
|
||||
│ + 소유자회원번호 일치 │
|
||||
│ → 조건 충족: 상품용(02) │
|
||||
└──────────────────────────────────────────────┘
|
||||
│ (조건 미충족)
|
||||
▼
|
||||
┌──────────────────────────────────────────────┐
|
||||
│ 2. 명의이전 소유자 확인 (OwnerTransferOmChecker)│
|
||||
│ 조건: 부과일자 소유자명에 상품용 미포함 │
|
||||
│ + CHG_YMD > 검사유효기간종료일+31일 │
|
||||
│ + 명의이전(11) 레코드 존재 │
|
||||
│ → 조건 충족: 접수(01) │
|
||||
└──────────────────────────────────────────────┘
|
||||
│ (조건 미충족)
|
||||
▼
|
||||
┌──────────────────────────────────────────────┐
|
||||
│ 3. 이첩 (TransferOmChecker) │
|
||||
│ 조건: 소유자명에 상품용 미포함 │
|
||||
│ + 1단계/2단계 소유자 같음 │
|
||||
│ + 1단계/3단계 소유자 같음 │
|
||||
│ + 법정동코드 앞4자리 != 조직코드 앞4자리│
|
||||
│ → 조건 충족: 이첩(03) │
|
||||
└──────────────────────────────────────────────┘
|
||||
│ (조건 미충족)
|
||||
▼
|
||||
[다음 차량]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 요약 정리
|
||||
|
||||
### 처리상태코드 매핑
|
||||
|
||||
| 코드 | 상태명 | 처리 로직 | 클래스 |
|
||||
|------|--------|--------------------------|--------|
|
||||
| 02 | 상품용 | 부과일자 소유자가 상품용 + 명의이전(11) CHG_YMD <= 종료일+31일 | `ProductUseOmChecker` |
|
||||
| 01 | 접수 | 검사유효기간종료일+31일 이후 명의이전 존재 | `OwnerTransferOmChecker` |
|
||||
| 03 | 이첩 | 소유자 일치 + 법정동코드 불일치 | `TransferOmChecker` |
|
||||
|
||||
### 미필 vs 지연 비교
|
||||
|
||||
| 구분 | 미필 | 지연 |
|
||||
|------|-----|------|
|
||||
| 부과일자 | 검사유효기간 종료일 + 146일 | 검사일 |
|
||||
| 상품용 조건 | 부과일자 기준 소유자명 | 검사일 기준 소유자명 |
|
||||
| Checker 개수 | 3개 | 7개 |
|
||||
| 이첩 로직 | 3단계 API + 소유자 비교 | DAYCNT 기반 |
|
||||
|
||||
---
|
||||
|
||||
## 참고 상수 및 유틸리티
|
||||
|
||||
### 상수
|
||||
```java
|
||||
// 부과일자 계산 (미필)
|
||||
levyCrtrYmd = 검사유효기간 종료일 + 146일
|
||||
|
||||
// 처리상태코드
|
||||
TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_02_PRODUCT_USE = "02"
|
||||
TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_03_TRANSFER = "03"
|
||||
|
||||
// 변경업무구분코드
|
||||
"11" = 명의이전
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**문서 최종 수정일**: 2025-12-09
|
||||
**실제 소스 코드 기준**: om_checker 폴더 내 Checker 클래스들
|
||||
**분석 대상 클래스**: 3개 (ProductUseOmChecker, OwnerTransferOmChecker, TransferOmChecker)
|
||||
**주요 변경사항**: 검사유효기간 종료일 + 31일 로직 적용
|
||||
@ -1,474 +0,0 @@
|
||||
# 자동차 과태료 비교 로직 명세서 (지연)
|
||||
|
||||
## 개요
|
||||
|
||||
자동차 과태료 부과 대상(지연)을 검증하기 위한 비교 로직 정의서입니다.
|
||||
|
||||
### 구현 위치
|
||||
- **Checker 클래스**: `src/main/java/go/kr/project/carInspectionPenalty/registration/service/impl/delay_checker/`
|
||||
- `ProductUseChecker.java` - 1. 상품용(명의이전) : 상품용
|
||||
- `ProductUseChnageChecker.java` - 1-1. 상품용(변경등록) : 상품용
|
||||
- `ProductCloseWithin31Checker.java` - 2. 내사종결(명의이전 이전소유자 상품용, 31일 이내) : 명의이전(25.9.11.) 이전소유자 상품용
|
||||
- `OwnerCloseWithin31Checker.java` - 3. 내사종결(순수 명의이전, 31일 이내) : 명의이전(25.8.28.)
|
||||
- `ProductLevyOver31Checker.java` - 4. 날짜수정후부과(명의이전 이전소유자 상품용, 31일 초과) : 경기도 고양시/ 장준혁, 미수검명의이전(25.8.19.)
|
||||
- `OwnerLevyOver31Checker.java` - 5. 날짜수정후부과(순수 명의이전, 31일 초과) : 대구광역시 달서구/ 하나캐피탈(주), 미수검명의이전(25.9.3.)
|
||||
- `TransferCase115DayChecker.java` - 6. 이첩 : case 1 = 경상남도 창원시/ 현대캐피탈 주식회사, 115일 도래지 case 2 = 인천광역시 부평구/ (주)우리카드, 검사일사용본거지
|
||||
|
||||
### 기본 설정
|
||||
- 비교로직에 사용되는 API: `ExternalVehicleApiServiceImpl.getBasicInfo`, `getLedgerInfo` 호출
|
||||
- 날짜 유틸리티: `DateUtil.parseDate()`, `DateUtil.formatDateString()` 사용
|
||||
- 일수 계산 기준: `DAYS_THRESHOLD = 31일`
|
||||
|
||||
### 문서 이력
|
||||
|
||||
| 일자 | 변경 내용 | 비고 |
|
||||
|------|----------|------|
|
||||
| 2025-12-08 | delay_checker 소스 기준 전면 재작성 | 실제 코드와 일치하도록 정리 |
|
||||
| 2025-12-03 | 실제 소스 코드 기준으로 전면 재작성 | Javadoc과 실제 로직 차이 명시 |
|
||||
| 2025-12-02 | 내사종결 로직 추가 및 상품용 조건 변경 | 명의이전 31일 이내 조건 추가 |
|
||||
|
||||
### 처리 규칙
|
||||
|
||||
> **중요**: 순서가 중요함!
|
||||
> 1. 상품용(명의이전) → 1-1. 상품용(변경등록) → 2. 내사종결(상품용) → 3. 내사종결(명의이전) → 4. 날짜수정(상품용) → 5. 날짜수정(명의이전) → 6. 이첩
|
||||
> - 조건에 걸리는 순간 다음 차량번호 비교로 진행
|
||||
> - 각 비교 로직별로 개별 API 호출 수행
|
||||
|
||||
---
|
||||
|
||||
## 비교 로직 상세
|
||||
|
||||
### 1. 상품용 검증 (`ProductUseChecker`)
|
||||
|
||||
**처리상태코드**: `02` (상품용)
|
||||
**클래스**: `ProductUseChecker.java`
|
||||
|
||||
#### API 호출 순서
|
||||
|
||||
| 순서 | API | 입력 파라미터 | 출력 데이터 | 용도 |
|
||||
|------|-----|--------------|-------------|------|
|
||||
| 1 | 자동차기본정보 | `차량번호`, `부과일자=검사일` | `차대번호(vin)`, `소유자명`, `대표소유자회원번호` | 검사일 기준 소유자 확인 |
|
||||
| 2 | 자동차기본정보 | `1.차대번호`, `부과일자=오늘` | `차량번호`, `성명`, `주민번호`, `법정동코드` | 현재 소유자 정보 |
|
||||
| 3 | 자동차등록원부(갑) | `2.차량번호`, `2.성명`, `2.주민번호`, `2.법정동코드` | 갑부 상세 List | 명의이전 이력 조회 |
|
||||
| 4 | 자동차기본정보 | `1.차대번호`, `부과일자=CHG_YMD` | `소유자명`, `대표소유자회원번호` | 명의이전 시점 소유자 확인 |
|
||||
|
||||
#### 비교 조건
|
||||
|
||||
```
|
||||
1. Step1 소유자명.contains("상품용") ← 상품용 아니면 return null
|
||||
|
||||
2. 갑부에서 명의이전(11) 레코드 찾기
|
||||
- CHG_TASK_SE_CD == "11"
|
||||
- CHG_YMD <= 검사종료일자
|
||||
- 가장 마지막 일자 선택
|
||||
← 없으면 return null
|
||||
|
||||
3. Step4 대표소유자회원번호 == Step1 대표소유자회원번호
|
||||
← 불일치면 return null
|
||||
|
||||
→ 모든 조건 충족: 상품용(02) 처리
|
||||
```
|
||||
|
||||
#### DB 업데이트 필드
|
||||
|
||||
```java
|
||||
existingData.setTaskPrcsSttsCd("02"); // 상품용
|
||||
existingData.setCarBscMttrInqFlnm(step4OwnerName);
|
||||
existingData.setCarRegFrmbkChgTaskSeCd("11");
|
||||
existingData.setCarRegFrmbkChgYmd(targetRecord.getChgYmd());
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 1-1. 상품용-변경등록 검증 (`ProductUseChnageChecker`)
|
||||
|
||||
**처리상태코드**: `02` (상품용)
|
||||
**클래스**: `ProductUseChnageChecker.java`
|
||||
|
||||
#### API 호출 순서
|
||||
|
||||
| 순서 | API | 입력 파라미터 | 출력 데이터 | 용도 |
|
||||
|------|-----|--------------|-------------|------|
|
||||
| 1 | 자동차기본정보 | `차량번호`, `부과일자=검사일` | `차대번호(vin)`, `소유자명`, `대표소유자회원번호` | 검사일 기준 소유자 확인 |
|
||||
| 2 | 자동차기본정보 | `1.차대번호`, `부과일자=오늘` | `차량번호`, `성명`, `주민번호`, `법정동코드` | 현재 소유자 정보 |
|
||||
| 3 | 자동차등록원부(갑) | `2.차량번호`, `2.성명`, `2.주민번호`, `2.법정동코드` | 갑부 상세 List | 변경등록 이력 조회 |
|
||||
| 4 | 자동차기본정보 | `1.차대번호`, `부과일자=CHG_YMD` | `소유자명`, `대표소유자회원번호` | 변경등록 시점 소유자 확인 |
|
||||
|
||||
#### 비교 조건
|
||||
|
||||
```
|
||||
1. Step1 소유자명.contains("상품용") ← 상품용 아니면 return null
|
||||
|
||||
2. 갑부에서 변경등록(21) 레코드 찾기
|
||||
- CHG_TASK_SE_CD == "21"
|
||||
- CHG_YMD <= 검사종료일자
|
||||
- spcablMttr.contains("성명") ← 성명 변경 포함 필수
|
||||
- 가장 마지막 일자 선택
|
||||
← 없으면 return null
|
||||
|
||||
3. Step4 대표소유자회원번호 == Step1 대표소유자회원번호
|
||||
← 불일치면 return null
|
||||
|
||||
→ 모든 조건 충족: 상품용(02) 처리
|
||||
```
|
||||
|
||||
#### DB 업데이트 필드
|
||||
|
||||
```java
|
||||
existingData.setTaskPrcsSttsCd("02"); // 상품용
|
||||
existingData.setCarBscMttrInqFlnm(step4OwnerName);
|
||||
existingData.setCarRegFrmbkChgTaskSeCd("21");
|
||||
existingData.setCarRegFrmbkChgYmd(targetRecord.getChgYmd());
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. 내사종결 - 명의이전 이전소유자 상품용, 31일 이내 (`ProductCloseWithin31Checker`)
|
||||
|
||||
**처리상태코드**: `04` (내사종결)
|
||||
**클래스**: `ProductCloseWithin31Checker.java`
|
||||
|
||||
#### API 호출 순서
|
||||
|
||||
| 순서 | API | 입력 파라미터 | 출력 데이터 | 용도 |
|
||||
|------|-----|--------------|-------------|------|
|
||||
| 1 | 자동차기본정보 | `차량번호`, `부과일자=검사일` | `차대번호`, `소유자명` | 검사일 기준 소유자 확인 |
|
||||
| 2 | 자동차기본정보 | `1.차대번호`, `부과일자=오늘` | `차량번호`, `성명`, `주민번호`, `법정동코드` | 현재 소유자 정보 |
|
||||
| 3 | 자동차등록원부(갑) | `2.차량번호`, `2.성명`, `2.주민번호`, `2.법정동코드` | 갑부 상세 List | 명의이전 이력 조회 |
|
||||
| 4 | 자동차기본정보 | `1.차대번호`, `부과일자=CHG_YMD-1일` | `소유자명` | 명의이전 직전 소유자 확인 |
|
||||
|
||||
#### 비교 조건
|
||||
|
||||
```
|
||||
1. Step1 소유자명.contains("상품용") → return null (1번에서 처리됨)
|
||||
!Step1 소유자명.contains("상품용") → 계속 진행
|
||||
|
||||
2. 갑부에서 명의이전(11) 레코드 찾기
|
||||
- CHG_TASK_SE_CD == "11"
|
||||
- CHG_YMD <= 검사일
|
||||
- 가장 마지막 일자 선택
|
||||
← 없으면 return null
|
||||
|
||||
3. 일수 계산: 명의이전일자 ~ 검사일
|
||||
- 0~31일 이내 → 계속 진행
|
||||
- 31일 초과 → return null (4번에서 처리)
|
||||
|
||||
4. Step4 소유자명.contains("상품용")
|
||||
← 상품용 아니면 return null
|
||||
|
||||
→ 모든 조건 충족: 내사종결(04) 처리
|
||||
```
|
||||
|
||||
#### DB 업데이트 필드
|
||||
|
||||
```java
|
||||
existingData.setTaskPrcsSttsCd("04"); // 내사종결
|
||||
existingData.setCarBscMttrInqFlnm(step4OwnerName); // 명의이전 직전 소유자명
|
||||
existingData.setCarRegFrmbkChgTaskSeCd("11");
|
||||
existingData.setCarRegFrmbkChgYmd(targetRecord.getChgYmd());
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. 내사종결 - 순수 명의이전, 31일 이내 (`OwnerCloseWithin31Checker`)
|
||||
|
||||
**처리상태코드**: `04` (내사종결)
|
||||
**클래스**: `OwnerCloseWithin31Checker.java`
|
||||
|
||||
#### API 호출 순서
|
||||
|
||||
| 순서 | API | 입력 파라미터 | 출력 데이터 | 용도 |
|
||||
|------|-----|--------------|-------------|------|
|
||||
| 1 | 자동차기본정보 | `차량번호`, `부과일자=검사일` | `차대번호`, `소유자명`, `대표소유자회원번호` | 검사일 기준 소유자 확인 |
|
||||
| 2 | 자동차기본정보 | `1.차대번호`, `부과일자=오늘` | `차량번호`, `성명`, `주민번호`, `법정동코드` | 현재 소유자 정보 |
|
||||
| 3 | 자동차등록원부(갑) | `2.차량번호`, `2.성명`, `2.주민번호`, `2.법정동코드` | 갑부 상세 List | 명의이전 이력 조회 |
|
||||
| 4 | 자동차기본정보 | `1.차대번호`, `부과일자=CHG_YMD` | `소유자명`, `대표소유자회원번호` | 명의이전 시점 소유자 확인 |
|
||||
|
||||
#### 비교 조건
|
||||
|
||||
```
|
||||
1. Step1 소유자명.contains("상품용") → return null (1번에서 처리됨)
|
||||
!Step1 소유자명.contains("상품용") → 계속 진행
|
||||
|
||||
2. 갑부에서 명의이전(11) 레코드 찾기
|
||||
- CHG_TASK_SE_CD == "11"
|
||||
- 유효기간만료일-90일 <= CHG_YMD <= 검사종료일자
|
||||
- 가장 마지막 일자 선택
|
||||
← 없으면 return null
|
||||
|
||||
3. 일수 계산: 명의이전일자 ~ 검사일
|
||||
- 0~31일 이내 → 계속 진행
|
||||
- 31일 초과 → return null (5번에서 처리)
|
||||
|
||||
4. Step4 대표소유자회원번호 == Step1 대표소유자회원번호
|
||||
← 불일치면 return null
|
||||
|
||||
→ 모든 조건 충족: 내사종결(04) 처리
|
||||
```
|
||||
|
||||
#### DB 업데이트 필드
|
||||
|
||||
```java
|
||||
existingData.setTaskPrcsSttsCd("04"); // 내사종결
|
||||
existingData.setCarBscMttrInqFlnm(step4OwnerName);
|
||||
existingData.setCarRegFrmbkChgTaskSeCd("11");
|
||||
existingData.setCarRegFrmbkChgYmd(targetRecord.getChgYmd());
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. 날짜수정후부과 - 명의이전 이전소유자 상품용, 31일 초과 (`ProductLevyOver31Checker`)
|
||||
|
||||
**처리상태코드**: `05` (날짜 수정 후 부과)
|
||||
**클래스**: `ProductLevyOver31Checker.java`
|
||||
|
||||
#### API 호출 순서
|
||||
|
||||
| 순서 | API | 입력 파라미터 | 출력 데이터 | 용도 |
|
||||
|------|-----|--------------|-------------|------|
|
||||
| 1 | 자동차기본정보 | `차량번호`, `부과일자=검사일` | `차대번호`, `소유자명` | 검사일 기준 소유자 확인 |
|
||||
| 2 | 자동차기본정보 | `1.차대번호`, `부과일자=오늘` | `차량번호`, `성명`, `주민번호`, `법정동코드` | 현재 소유자 정보 |
|
||||
| 3 | 자동차등록원부(갑) | `2.차량번호`, `2.성명`, `2.주민번호`, `2.법정동코드` | 갑부 상세 List | 명의이전 이력 조회 |
|
||||
| 4 | 자동차기본정보 | `1.차대번호`, `부과일자=CHG_YMD-1일` | `소유자명` | 명의이전 직전 소유자 확인 |
|
||||
|
||||
#### 비교 조건
|
||||
|
||||
```
|
||||
1. Step1 소유자명.contains("상품용") → return null (1번에서 처리됨)
|
||||
!Step1 소유자명.contains("상품용") → 계속 진행
|
||||
|
||||
2. 갑부에서 명의이전(11) 레코드 찾기
|
||||
- CHG_TASK_SE_CD == "11"
|
||||
- CHG_YMD <= 검사일
|
||||
- 가장 마지막 일자 선택
|
||||
← 없으면 return null
|
||||
|
||||
3. 일수 계산: 명의이전일자 ~ 검사일
|
||||
- 31일 초과 → 계속 진행
|
||||
- 0~31일 이내 → return null (2번에서 처리)
|
||||
|
||||
4. Step4 소유자명.contains("상품용")
|
||||
← 상품용 아니면 return null
|
||||
|
||||
→ 모든 조건 충족: 날짜수정후부과(05) 처리
|
||||
```
|
||||
|
||||
#### DB 업데이트 필드
|
||||
|
||||
```java
|
||||
existingData.setTaskPrcsSttsCd("05"); // 날짜수정후부과
|
||||
existingData.setCarBscMttrInqFlnm(step4OwnerName); // 명의이전 직전 소유자명
|
||||
existingData.setCarRegFrmbkChgTaskSeCd("11");
|
||||
existingData.setCarRegFrmbkChgYmd(targetRecord.getChgYmd());
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5. 날짜수정후부과 - 순수 명의이전, 31일 초과 (`OwnerLevyOver31Checker`)
|
||||
|
||||
**처리상태코드**: `05` (날짜 수정 후 부과)
|
||||
**클래스**: `OwnerLevyOver31Checker.java`
|
||||
|
||||
#### API 호출 순서
|
||||
|
||||
| 순서 | API | 입력 파라미터 | 출력 데이터 | 용도 |
|
||||
|------|-----|--------------|-------------|------|
|
||||
| 1 | 자동차기본정보 | `차량번호`, `부과일자=검사일` | `차대번호`, `소유자명`, `대표소유자회원번호` | 검사일 기준 소유자 확인 |
|
||||
| 2 | 자동차기본정보 | `1.차대번호`, `부과일자=오늘` | `차량번호`, `성명`, `주민번호`, `법정동코드` | 현재 소유자 정보 |
|
||||
| 3 | 자동차등록원부(갑) | `2.차량번호`, `2.성명`, `2.주민번호`, `2.법정동코드` | 갑부 상세 List | 명의이전 이력 조회 |
|
||||
| 4 | 자동차기본정보 | `1.차대번호`, `부과일자=CHG_YMD` | `소유자명`, `대표소유자회원번호` | 명의이전 시점 소유자 확인 |
|
||||
|
||||
#### 비교 조건
|
||||
|
||||
```
|
||||
1. Step1 소유자명.contains("상품용") → return null (1번에서 처리됨)
|
||||
!Step1 소유자명.contains("상품용") → 계속 진행
|
||||
|
||||
2. 갑부에서 명의이전(11) 레코드 찾기
|
||||
- CHG_TASK_SE_CD == "11"
|
||||
- 유효기간만료일-90일 <= CHG_YMD <= 검사종료일자
|
||||
- 가장 마지막 일자 선택
|
||||
← 없으면 return null
|
||||
|
||||
3. 일수 계산: 명의이전일자 ~ 검사일
|
||||
- 31일 초과 → 계속 진행
|
||||
- 0~31일 이내 → return null (3번에서 처리)
|
||||
|
||||
4. Step4 대표소유자회원번호 == Step1 대표소유자회원번호
|
||||
← 불일치면 return null
|
||||
|
||||
→ 모든 조건 충족: 날짜수정후부과(05) 처리
|
||||
```
|
||||
|
||||
#### DB 업데이트 필드
|
||||
|
||||
```java
|
||||
existingData.setTaskPrcsSttsCd("05"); // 날짜수정후부과
|
||||
existingData.setCarBscMttrInqFlnm(step4OwnerName);
|
||||
existingData.setCarRegFrmbkChgTaskSeCd("11");
|
||||
existingData.setCarRegFrmbkChgYmd(targetRecord.getChgYmd());
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 6. 이첩 검증 (`TransferCase115DayChecker`)
|
||||
|
||||
**처리상태코드**: `03` (이첩)
|
||||
**클래스**: `TransferCase115DayChecker.java`
|
||||
|
||||
#### API 호출
|
||||
|
||||
| API | 입력 파라미터 | 출력 데이터 | 용도 |
|
||||
|-----|--------------|-------------|------|
|
||||
| 자동차기본정보 | `차량번호`, `부과일자=부과기준일` | `사용본거지법정동코드` | 부과기준일 기준 사용본거지 확인 |
|
||||
|
||||
#### 비교 조건
|
||||
|
||||
```
|
||||
1. DAYCNT 값으로 부과기준일 계산
|
||||
- DAYCNT > 115: 이첩-2 (부과기준일 = 검사종료일자 + 115일)
|
||||
- DAYCNT <= 115: 이첩-1 (부과기준일 = 검사일자)
|
||||
← DAYCNT 없으면 return null
|
||||
|
||||
2. 자동차기본정보(차량번호, 부과기준일) 호출
|
||||
→ 사용본거지법정동코드 조회
|
||||
|
||||
3. 법정동코드 앞 4자리 != 사용자 조직코드 앞 4자리
|
||||
← 일치하면 return null
|
||||
|
||||
→ 불일치: 이첩(03) 처리
|
||||
```
|
||||
|
||||
#### 결과 처리
|
||||
|
||||
| 구분 | 조건 | 비고 컬럼 형식 |
|
||||
|------|------|---------------|
|
||||
| 이첩-1 | `DAYCNT <= 115` | `"{시군구명}, 검사일사용본거지, [사용자 조직코드 앞 4자리: {userOrg4}, 법정동명: {sggNm}]"` |
|
||||
| 이첩-2 | `DAYCNT > 115` | `"{시군구명}, 115일 도래지, [법정동코드: {legalDong4}, 법정동명: {sggNm}]"` |
|
||||
|
||||
#### DB 업데이트 필드
|
||||
|
||||
```java
|
||||
existingData.setTaskPrcsSttsCd("03"); // 이첩
|
||||
existingData.setCarBscMttrInqFlnm(existingData.getOwnrNm()); // 기존 소유자명 유지
|
||||
existingData.setCarBscMttrInqSggCd(sggCd);
|
||||
existingData.setCarBscMttrInqSggNm(sggNm);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 처리 흐름도
|
||||
|
||||
```
|
||||
시작
|
||||
│
|
||||
▼
|
||||
[차량번호 조회]
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────────────────────────┐
|
||||
│ 1. 상품용-명의이전 (ProductUseChecker) │
|
||||
│ 조건: 검사일 소유자명.contains("상품용") │
|
||||
│ + 명의이전(11) 레코드 존재 │
|
||||
│ → 조건 충족: 상품용(02) │
|
||||
└──────────────────────────────────────────────┘
|
||||
│ (조건 미충족)
|
||||
▼
|
||||
┌──────────────────────────────────────────────┐
|
||||
│ 1-1. 상품용-변경등록 (ProductUseChnageChecker)│
|
||||
│ 조건: 검사일 소유자명.contains("상품용") │
|
||||
│ + 변경등록(21) + 성명변경 포함 │
|
||||
│ → 조건 충족: 상품용(02) │
|
||||
└──────────────────────────────────────────────┘
|
||||
│ (조건 미충족)
|
||||
▼
|
||||
┌──────────────────────────────────────────────┐
|
||||
│ 2. 내사종결-상품용 (ProductCloseWithin31Checker) │
|
||||
│ 조건: 31일 이내 + 명의이전 전 상품용 │
|
||||
│ → 조건 충족: 내사종결(04) │
|
||||
└──────────────────────────────────────────────┘
|
||||
│ (조건 미충족)
|
||||
▼
|
||||
┌──────────────────────────────────────────────┐
|
||||
│ 3. 내사종결-명의이전 (OwnerCloseWithin31Checker) │
|
||||
│ 조건: 31일 이내 + 동일 소유자 │
|
||||
│ → 조건 충족: 내사종결(04) │
|
||||
└──────────────────────────────────────────────┘
|
||||
│ (조건 미충족)
|
||||
▼
|
||||
┌──────────────────────────────────────────────┐
|
||||
│ 4. 날짜수정-상품용 (ProductLevyOver31Checker) │
|
||||
│ 조건: 31일 초과 + 명의이전 전 상품용 │
|
||||
│ → 조건 충족: 날짜수정후부과(05) │
|
||||
└──────────────────────────────────────────────┘
|
||||
│ (조건 미충족)
|
||||
▼
|
||||
┌──────────────────────────────────────────────┐
|
||||
│ 5. 날짜수정-명의이전 (OwnerLevyOver31Checker) │
|
||||
│ 조건: 31일 초과 + 동일 소유자 │
|
||||
│ → 조건 충족: 날짜수정후부과(05) │
|
||||
└──────────────────────────────────────────────┘
|
||||
│ (조건 미충족)
|
||||
▼
|
||||
┌──────────────────────────────────────────────┐
|
||||
│ 6. 이첩 (TransferCase115DayChecker) │
|
||||
│ 조건: 법정동코드 앞4자리 != 조직코드 앞4자리│
|
||||
│ → 조건 충족: 이첩(03) │
|
||||
└──────────────────────────────────────────────┘
|
||||
│ (조건 미충족)
|
||||
▼
|
||||
[다음 차량]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 요약 정리
|
||||
|
||||
### 처리상태코드 매핑
|
||||
|
||||
| 코드 | 상태명 | 처리 로직 | 클래스 |
|
||||
|------|--------|----------|--------|
|
||||
| 02 | 상품용 | 검사일 소유자가 상품용 + 명의이전(11) | `ProductUseChecker` |
|
||||
| 02 | 상품용 | 검사일 소유자가 상품용 + 변경등록(21) + 성명변경 | `ProductUseChnageChecker` |
|
||||
| 04 | 내사종결 | 명의이전 전 상품용 (31일 이내) | `ProductCloseWithin31Checker` |
|
||||
| 04 | 내사종결 | 순수 명의이전 (31일 이내) | `OwnerCloseWithin31Checker` |
|
||||
| 05 | 날짜수정후부과 | 명의이전 전 상품용 (31일 초과) | `ProductLevyOver31Checker` |
|
||||
| 05 | 날짜수정후부과 | 순수 명의이전 (31일 초과) | `OwnerLevyOver31Checker` |
|
||||
| 03 | 이첩 | 법정동코드 불일치 | `TransferCase115DayChecker` |
|
||||
|
||||
### 상품용 vs 순수 명의이전 비교
|
||||
|
||||
| 구분 | 상품용 케이스 (2, 4번) | 순수 명의이전 케이스 (3, 5번) |
|
||||
|------|----------------------|----------------------------|
|
||||
| 검사일 소유자 | 상품용 아님 | 상품용 아님 |
|
||||
| 명의이전 직전 소유자 | 상품용 **포함** | 소유자 회원번호 **일치** |
|
||||
| Step 4 확인사항 | 소유자명.contains("상품용") | 대표소유자회원번호 == Step1 |
|
||||
| 갑부 검색 조건 | CHG_YMD <= 검사일 | 유효기간만료일-90일 <= CHG_YMD <= 검사종료일자 |
|
||||
| 일수 기준 | 31일 이내/초과 | 31일 이내/초과 |
|
||||
| 처리상태코드 | 31일 이내: 04, 초과: 05 | 31일 이내: 04, 초과: 05 |
|
||||
|
||||
---
|
||||
|
||||
## 참고 상수 및 유틸리티
|
||||
|
||||
### 상수
|
||||
```java
|
||||
// 일수 기준값
|
||||
private static final int DAYS_THRESHOLD = 31;
|
||||
|
||||
// 처리상태코드
|
||||
TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_02_PRODUCT_USE = "02"
|
||||
TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_03_TRANSFER = "03"
|
||||
TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_04_INVESTIGATION_CLOSED = "04"
|
||||
TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_05_DATE_MODIFIED_LEVY = "05"
|
||||
|
||||
// 변경업무구분코드
|
||||
"11" = 명의이전
|
||||
"21" = 변경등록
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**문서 작성 완료일**: 2025-12-08
|
||||
**실제 소스 코드 기준**: delay_checker 폴더 내 Checker 클래스들
|
||||
**분석 대상 클래스**: 7개 (ProductUseChecker, ProductUseChnageChecker, ProductCloseWithin31Checker, OwnerCloseWithin31Checker, ProductLevyOver31Checker, OwnerLevyOver31Checker, TransferCase115DayChecker)
|
||||
@ -1,19 +0,0 @@
|
||||
유효기간경과 과태료부과대상 리스트
|
||||
------------------------------------
|
||||
|
||||
|
||||
* 최종등록일이 검사일자보다 늦는 경우는 소유자 및 사용본거지 주소를 재확인하여 주시기 바랍니다. (재검여부 = *일수)
|
||||
* 전출차량( *차번호)인 경우 전출 전의 주소입니다. 소유자 및 사용본거지 주소를 재확인하여 주시기 바랍니다.
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
검사소 검사일자 자동차번호 소유자명 주민등록번호 차 명 차 종 용 도 종료일 일수 과태료
|
||||
최종등록일 주 소 유효기간만료일 매매상품용
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
H494 2025-09-01 *162고6489 1244110241315 엠뱅크언더리프 특수차구난형소영업용 2025-08-25 *7 4만원
|
||||
2025-07-14 경기도 용인시 기흥구 강남로 9, 111-111호(신행동, 진주만프라자) 2020-12-05
|
||||
|
||||
H494 2025-09-01 271구5475 (주)케이비캐피탈 1301110013499 엠뱅크언더리프 특수차구난형소영업용 2024-09-24 303 60만원
|
||||
2025-07-14 경기도 용인시 기흥구 강남로 9, 111-111호(신행동, 진주만프라자) 2020-12-05
|
||||
|
||||
H494 2025-09-11 180너6976 (주)기아주식회사 1101110037998 엠뱅크언더리프 특수차구난형소영업용 2025-05-26 109 56만원
|
||||
2025-07-14 경기도 용인시 기흥구 강남로 9, 111-111호(신행동, 진주만프라자) 2020-12-05
|
||||
|
||||
@ -1,16 +0,0 @@
|
||||
유효기간경과 과태료부과대상 리스트
|
||||
------------------------------------
|
||||
|
||||
|
||||
* 최종등록일이 검사일자보다 늦는 경우는 소유자 및 사용본거지 주소를 재확인하여 주시기 바랍니다. (재검여부 = *일수)
|
||||
* 전출차량( *차번호)인 경우 전출 전의 주소입니다. 소유자 및 사용본거지 주소를 재확인하여 주시기 바랍니다.
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
검사소 검사일자 자동차번호 소유자명 주민등록번호 차 명 차 종 용 도 종료일 일수 과태료
|
||||
최종등록일 주 소 유효기간만료일 매매상품용
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
H494 2025-09-14 142러3779 서찬규 1244110241315 엠뱅크언더리프 특수차구난형소영업용 2025-06-19 90 42만원
|
||||
2025-05-17 경기도 용인시 기흥구 강남로 9, 111-111호(신행동, 진주만프라자) 2020-12-05
|
||||
|
||||
H494 2025-09-07 22루2283 송동건 1301110013499 엠뱅크언더리프 특수차구난형소영업용 2025-03-10 182 60만원
|
||||
2025-02-05 경기도 용인시 기흥구 강남로 9, 111-111호(신행동, 진주만프라자) 2020-12-05
|
||||
|
||||
@ -1,16 +0,0 @@
|
||||
유효기간경과 과태료부과대상 리스트
|
||||
------------------------------------
|
||||
|
||||
|
||||
* 최종등록일이 검사일자보다 늦는 경우는 소유자 및 사용본거지 주소를 재확인하여 주시기 바랍니다. (재검여부 = *일수)
|
||||
* 전출차량( *차번호)인 경우 전출 전의 주소입니다. 소유자 및 사용본거지 주소를 재확인하여 주시기 바랍니다.
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
검사소 검사일자 자동차번호 소유자명 주민등록번호 차 명 차 종 용 도 종료일 일수 과태료
|
||||
최종등록일 주 소 유효기간만료일 매매상품용
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
H494 2025-09-12 254고9785 서찬규 1244110241315 엠뱅크언더리프 특수차구난형소영업용 2025-09-01 90 42만원
|
||||
2025-08-01 경기도 용인시 기흥구 강남로 9, 111-111호(신행동, 진주만프라자) 2025-08-01
|
||||
|
||||
H494 2025-09-15 254고9785 서찬규 1244110241315 엠뱅크언더리프 특수차구난형소영업용 2025-09-01 90 42만원
|
||||
2025-08-01 경기도 용인시 기흥구 강남로 9, 111-111호(신행동, 진주만프라자) 2025-08-01
|
||||
|
||||
Binary file not shown.
@ -0,0 +1,23 @@
|
||||
package go.kr.project.api.config;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* API 전용 MyBatis Mapper 스캔 설정
|
||||
*
|
||||
* <p>VMIS API 통합 모듈의 Mapper 인터페이스만 스캔합니다.</p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>DataSource: egovframework 기본 설정 사용 (DataSourceProxyConfig)</li>
|
||||
* <li>TransactionManager: egovframework 기본 설정 사용 (EgovConfigTransaction.txManager)</li>
|
||||
* <li>SqlSessionFactory: MyBatis Spring Boot Starter가 자동 생성</li>
|
||||
* <li>MapperScan: go.kr.project.api.internal.mapper만 스캔 (API 전용)</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>일반 프로젝트의 Mapper는 egovframework 설정에서 별도로 스캔됩니다.</p>
|
||||
*/
|
||||
@Configuration
|
||||
@MapperScan(basePackages = "go.kr.project.api.internal.mapper")
|
||||
public class ApiMapperConfig {
|
||||
}
|
||||
@ -0,0 +1,117 @@
|
||||
package go.kr.project.api.config;
|
||||
|
||||
import go.kr.project.api.config.properties.VmisProperties;
|
||||
import go.kr.project.api.service.VehicleInfoService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* VMIS 통합 설정 및 모니터링
|
||||
*
|
||||
* <p>이 설정 클래스는 VMIS 통합 모드에 대한 정보를 제공하고,
|
||||
* 애플리케이션 시작 시 현재 활성화된 모드를 로그로 출력합니다.</p>
|
||||
*
|
||||
* <h3>주요 기능:</h3>
|
||||
* <ul>
|
||||
* <li>애플리케이션 시작 시 VMIS 통합 모드 출력</li>
|
||||
* <li>활성화된 VehicleInfoService 구현체 표시</li>
|
||||
* <li>설정 검증 및 경고 메시지 출력</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h3>지원하는 모드:</h3>
|
||||
* <ul>
|
||||
* <li>internal: 내부 VMIS 모듈 직접 호출 (InternalVehicleInfoServiceImpl)</li>
|
||||
* <li>external: 외부 REST API 호출 (ExternalVehicleInfoServiceImpl)</li>
|
||||
* </ul>
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
@RequiredArgsConstructor
|
||||
public class VmisIntegrationConfig {
|
||||
|
||||
private final VmisProperties vmisProperties;
|
||||
|
||||
/**
|
||||
* VMIS 통합 모드 정보 출력
|
||||
*
|
||||
* <p>애플리케이션 시작 시 현재 설정된 VMIS 통합 모드와
|
||||
* 관련 설정 정보를 로그로 출력합니다.</p>
|
||||
*
|
||||
* @param vehicleInfoService 활성화된 VehicleInfoService 구현체
|
||||
* @return CommandLineRunner
|
||||
*/
|
||||
@Bean
|
||||
public CommandLineRunner vmisIntegrationModeLogger(VehicleInfoService vehicleInfoService) {
|
||||
return args -> {
|
||||
String mode = vmisProperties.getIntegration().getMode();
|
||||
String implClass = vehicleInfoService.getClass().getSimpleName();
|
||||
|
||||
log.info("========================================");
|
||||
log.info("VMIS Integration Mode: {}", mode);
|
||||
log.info("Active Implementation: {}", implClass);
|
||||
log.info("========================================");
|
||||
|
||||
if ("internal".equalsIgnoreCase(mode)) {
|
||||
logInternalModeInfo();
|
||||
} else if ("external".equalsIgnoreCase(mode)) {
|
||||
logExternalModeInfo();
|
||||
} else {
|
||||
log.warn("알 수 없는 VMIS 통합 모드: {}. 'internal' 또는 'external'을 사용하세요.", mode);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal 모드 설정 정보 출력
|
||||
*/
|
||||
private void logInternalModeInfo() {
|
||||
log.info("[Internal Mode] 내부 VMIS 모듈을 직접 사용합니다");
|
||||
log.info(" - 정부 API 호스트: {}://{}",
|
||||
vmisProperties.getGov().getScheme(),
|
||||
vmisProperties.getGov().getHost());
|
||||
log.info(" - 기본사항 조회 경로: {}",
|
||||
vmisProperties.getGov().getServices().getBasic().getPath());
|
||||
log.info(" - 등록원부 조회 경로: {}",
|
||||
vmisProperties.getGov().getServices().getLedger().getPath());
|
||||
log.info(" - GPKI 암호화: {}",
|
||||
vmisProperties.getGpki().getEnabled());
|
||||
log.info(" - 연결 타임아웃: {}ms",
|
||||
vmisProperties.getRestTemplate().getInternal().getTimeout().getConnectTimeoutMillis());
|
||||
log.info(" - 읽기 타임아웃: {}ms",
|
||||
vmisProperties.getRestTemplate().getInternal().getTimeout().getReadTimeoutMillis());
|
||||
log.info(" - Rate Limit: 초당 {} 건",
|
||||
vmisProperties.getRestTemplate().getInternal().getRateLimit().getPermitsPerSecond());
|
||||
|
||||
if ("Y".equalsIgnoreCase(vmisProperties.getGpki().getEnabled())) {
|
||||
log.info(" - GPKI 인증서 서버 ID: {}",
|
||||
vmisProperties.getGpki().getCertServerId());
|
||||
log.info(" - GPKI 대상 서버 ID: {}",
|
||||
vmisProperties.getGpki().getTargetServerId());
|
||||
} else {
|
||||
log.warn(" - GPKI 암호화가 비활성화되어 있습니다. 개발 환경에서만 사용하세요.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* External 모드 설정 정보 출력
|
||||
*/
|
||||
private void logExternalModeInfo() {
|
||||
log.info("[External Mode] 외부 REST API를 사용합니다");
|
||||
log.info(" - 외부 API Base URL: {}",
|
||||
vmisProperties.getExternal().getApi().getUrl().getBase());
|
||||
log.info(" - 연결 타임아웃: {}ms",
|
||||
vmisProperties.getRestTemplate().getExternal().getTimeout().getConnectTimeoutMillis());
|
||||
log.info(" - 읽기 타임아웃: {}ms",
|
||||
vmisProperties.getRestTemplate().getExternal().getTimeout().getReadTimeoutMillis());
|
||||
log.info(" - Rate Limit: 초당 {} 건",
|
||||
vmisProperties.getRestTemplate().getExternal().getRateLimit().getPermitsPerSecond());
|
||||
log.warn(" - 외부 VMIS-interface 서버가 실행 중이어야 합니다.");
|
||||
log.info(" - 기본사항 조회: POST {}",
|
||||
vmisProperties.getExternal().getApi().getUrl().buildBasicUrl());
|
||||
log.info(" - 등록원부 조회: POST {}",
|
||||
vmisProperties.getExternal().getApi().getUrl().buildLedgerUrl());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package go.kr.project.api.external.service;
|
||||
|
||||
import go.kr.project.api.model.VehicleApiResponseVO;
|
||||
import go.kr.project.api.model.request.BasicRequest;
|
||||
import go.kr.project.api.model.request.LedgerRequest;
|
||||
import go.kr.project.api.model.response.BasicResponse;
|
||||
import go.kr.project.api.model.response.LedgerResponse;
|
||||
|
||||
/**
|
||||
* 외부 VMIS-interface API 호출 서비스 인터페이스
|
||||
* VMIS-interface 프로그램의 API를 호출하여 차량 정보를 조회하는 서비스
|
||||
*/
|
||||
public interface ExternalVehicleApiService {
|
||||
|
||||
/**
|
||||
* 단일 차량에 대한 정보 조회 (상세 파라미터 포함)
|
||||
*
|
||||
* @param basicRequest 기본정보 조회 요청 (차량번호, 부과기준일, 조회구분 등 포함)
|
||||
* @return 차량 정보 응답
|
||||
*/
|
||||
VehicleApiResponseVO getVehicleInfo(BasicRequest basicRequest);
|
||||
|
||||
/**
|
||||
* 차량 기본정보만 조회 (외부 REST 호출)
|
||||
* 중요: 기본정보 조회는 차량번호 외에 부과기준일, 조회구분 등 필수 파라미터 필요
|
||||
*/
|
||||
BasicResponse getBasicInfo(BasicRequest request);
|
||||
|
||||
/**
|
||||
* 자동차 등록원부(갑)만 조회 (외부 REST 호출)
|
||||
* 중요: 등록원부 조회는 차량번호 외에 소유자정보 등 필수 파라미터 필요
|
||||
*/
|
||||
LedgerResponse getLedgerInfo(LedgerRequest request);
|
||||
}
|
||||
@ -0,0 +1,237 @@
|
||||
package go.kr.project.api.external.service.impl;
|
||||
|
||||
import egovframework.exception.MessageException;
|
||||
import go.kr.project.api.config.ApiConstant;
|
||||
import go.kr.project.api.config.properties.VmisProperties;
|
||||
import go.kr.project.api.external.service.ExternalVehicleApiService;
|
||||
import go.kr.project.api.internal.util.ExceptionDetailUtil;
|
||||
import go.kr.project.api.model.Envelope;
|
||||
import go.kr.project.api.model.VehicleApiResponseVO;
|
||||
import go.kr.project.api.model.request.BasicRequest;
|
||||
import go.kr.project.api.model.request.LedgerRequest;
|
||||
import go.kr.project.api.model.response.*;
|
||||
import go.kr.project.api.service.VmisCarBassMatterInqireLogService;
|
||||
import go.kr.project.api.service.VmisCarLedgerFrmbkLogService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 외부 VMIS-interface API 호출 서비스 구현체
|
||||
* VMIS-interface 프로그램의 API를 호출하여 차량 정보를 조회하는 서비스
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class ExternalVehicleApiServiceImpl extends EgovAbstractServiceImpl implements ExternalVehicleApiService {
|
||||
|
||||
private final RestTemplate restTemplate;
|
||||
private final VmisProperties vmisProperties; // 프로퍼티 주입 (외부 API URL 구성에 사용)
|
||||
private final VmisCarBassMatterInqireLogService bassMatterLogService; // 기본사항 조회 로그 서비스
|
||||
private final VmisCarLedgerFrmbkLogService ledgerLogService; // 등록원부 로그 서비스
|
||||
|
||||
@Override
|
||||
public VehicleApiResponseVO getVehicleInfo(BasicRequest basicRequest) {
|
||||
String vehicleNumber = basicRequest.getVhrno();
|
||||
log.info("차량 정보 조회 시작 - 차량번호: {}, 부과기준일: {}, 조회구분: {}",
|
||||
vehicleNumber, basicRequest.getLevyStdde(), basicRequest.getInqireSeCode());
|
||||
|
||||
VehicleApiResponseVO response = new VehicleApiResponseVO();
|
||||
response.setVhrno(vehicleNumber);
|
||||
|
||||
try {
|
||||
// 1. 차량 기본정보 조회
|
||||
// 중요 로직: BasicRequest 전체를 사용하여 조회
|
||||
BasicResponse basicInfo = getBasicInfo(basicRequest);
|
||||
response.setBasicInfo(basicInfo);
|
||||
|
||||
// 2. 자동차 등록원부 조회
|
||||
// 중요 로직: 통합 조회 시에는 차량번호와 기본정보를 바탕으로 LedgerRequest 생성
|
||||
LedgerRequest ledgerRequest = new LedgerRequest();
|
||||
ledgerRequest.setVhrno(vehicleNumber);
|
||||
|
||||
// basicInfo에서 민원인 정보 가져오기
|
||||
if (basicInfo != null && basicInfo.getRecord() != null && !basicInfo.getRecord().isEmpty()) {
|
||||
BasicResponse.Record record = basicInfo.getRecord().get(0);
|
||||
ledgerRequest.setCpttrNm(record.getMberNm()); // 민원인성명
|
||||
ledgerRequest.setCpttrIhidnum(record.getMberSeNo()); // 민원인주민번호
|
||||
}
|
||||
// 고정값 설정
|
||||
ledgerRequest.setCpttrLegaldongCode(null); // 민원인법정동코드
|
||||
ledgerRequest.setRouteSeCode("3"); // 경로구분코드
|
||||
ledgerRequest.setDetailExpression("1"); // 내역표시 (전체내역)
|
||||
|
||||
LedgerResponse ledgerInfo = getLedgerInfo(ledgerRequest);
|
||||
response.setLedgerInfo(ledgerInfo);
|
||||
|
||||
// 3. 결과 검증
|
||||
if (basicInfo != null && ApiConstant.CNTC_RESULT_CODE_SUCCESS.equals(basicInfo.getCntcResultCode())) {
|
||||
response.setSuccess(true);
|
||||
response.setMessage("조회 성공");
|
||||
log.info("차량번호 {} 조회 성공", vehicleNumber);
|
||||
} else {
|
||||
response.setSuccess(false);
|
||||
response.setMessage(basicInfo != null ? basicInfo.getCntcResultDtls() : "조회 실패");
|
||||
log.warn("차량번호 {} 조회 실패 - {}", vehicleNumber, response.getMessage());
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
response.setSuccess(false);
|
||||
response.setMessage("API 호출 오류: " + e.getMessage());
|
||||
log.error("차량번호 {} API 호출 중 오류 발생", vehicleNumber, e);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 차량 기본정보 조회 API 호출
|
||||
* 중요 로직: 기본정보 조회는 BasicRequest 전체를 받아서 외부 API에 전달
|
||||
* (차량번호, 부과기준일, 조회구분, 차대번호 등 필수 파라미터 포함)
|
||||
*
|
||||
* @param request 기본정보 조회 요청 (차량번호, 부과기준일, 조회구분 등 포함)
|
||||
* @return 차량 기본정보
|
||||
*/
|
||||
@Override
|
||||
public BasicResponse getBasicInfo(BasicRequest request) {
|
||||
log.debug("차량 기본정보 조회 API 호출 - 차량번호: {}", request.getVhrno());
|
||||
|
||||
String generatedId = null;
|
||||
try {
|
||||
// 1) 최초 요청 로그 저장 (별도 트랜잭션)
|
||||
VmisCarBassMatterInqireVO logEntity = VmisCarBassMatterInqireVO.fromRequest(request);
|
||||
generatedId = bassMatterLogService.createInitialRequestNewTx(logEntity);
|
||||
|
||||
// Envelope로 감싸기 (요청 객체는 이미 모든 필수 파라미터를 포함)
|
||||
Envelope<BasicRequest> requestEnvelope = new Envelope<>(request);
|
||||
|
||||
// HTTP 헤더 설정
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
|
||||
HttpEntity<Envelope<BasicRequest>> requestEntity = new HttpEntity<>(requestEnvelope, headers);
|
||||
|
||||
// 2) API 호출
|
||||
ResponseEntity<Envelope<BasicResponse>> responseEntity = restTemplate.exchange(
|
||||
vmisProperties.getExternal().getApi().getUrl().buildBasicUrl(),
|
||||
HttpMethod.POST,
|
||||
requestEntity,
|
||||
new ParameterizedTypeReference<Envelope<BasicResponse>>() {}
|
||||
);
|
||||
|
||||
// 3) 응답 로그 업데이트 (별도 트랜잭션)
|
||||
if (responseEntity.getStatusCode() == HttpStatus.OK && responseEntity.getBody() != null) {
|
||||
List<BasicResponse> data = responseEntity.getBody().getData();
|
||||
if (data != null && !data.isEmpty()) {
|
||||
VmisCarBassMatterInqireVO update = VmisCarBassMatterInqireVO.fromResponse(generatedId, responseEntity.getBody());
|
||||
if (update != null) {
|
||||
bassMatterLogService.updateResponseNewTx(update);
|
||||
}
|
||||
return data.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
log.warn("차량 기본정보 조회 응답이 비어있음 - 차량번호: {}", request.getVhrno());
|
||||
return null;
|
||||
|
||||
} catch (Exception e) {
|
||||
// 4) 오류 로그 업데이트 (별도 트랜잭션)
|
||||
if (generatedId != null) {
|
||||
try {
|
||||
String detail = ExceptionDetailUtil.buildForLog(e);
|
||||
VmisCarBassMatterInqireVO errorLog = VmisCarBassMatterInqireVO.builder()
|
||||
.carBassMatterInqireId(generatedId)
|
||||
.cntcResultCode(ApiConstant.CNTC_RESULT_CODE_ERROR)
|
||||
.cntcResultDtls(detail)
|
||||
.build();
|
||||
bassMatterLogService.updateResponseNewTx(errorLog);
|
||||
log.error("[EXTERNAL-BASIC-ERR-LOG] API 호출 에러 정보 저장 완료(별도TX) - ID: {}, detail: {}", generatedId, detail, e);
|
||||
} catch (Exception ignore) {
|
||||
log.error("[EXTERNAL-BASIC-ERR-LOG] 에러 로그 저장 실패 - ID: {}", generatedId, ignore);
|
||||
}
|
||||
}
|
||||
log.error("차량 기본정보 조회 API 호출 실패 - 차량번호: {}", request.getVhrno(), e);
|
||||
throw new MessageException("차량 기본정보 조회 실패: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 자동차 등록원부(갑) 조회 API 호출
|
||||
* 중요 로직: 등록원부 조회는 차량번호 외에 소유자정보, 조회구분 등 필수 파라미터를 받아서 호출
|
||||
*
|
||||
* @param request 등록원부 조회 요청 (차량번호, 소유자정보, 조회구분 등 포함)
|
||||
* @return 등록원부 정보
|
||||
*/
|
||||
@Override
|
||||
public LedgerResponse getLedgerInfo(LedgerRequest request) {
|
||||
log.debug("자동차 등록원부 조회 API 호출 - 차량번호: {}", request.getVhrno());
|
||||
|
||||
String generatedId = null;
|
||||
try {
|
||||
// 1) 최초 요청 로그 저장 (별도 트랜잭션)
|
||||
VmisCarLedgerFrmbkVO init = VmisCarLedgerFrmbkVO.fromRequest(request);
|
||||
generatedId = ledgerLogService.createInitialRequestNewTx(init);
|
||||
|
||||
// Envelope로 감싸기 (요청 객체는 이미 모든 필수 파라미터를 포함)
|
||||
Envelope<LedgerRequest> requestEnvelope = new Envelope<>(request);
|
||||
|
||||
// HTTP 헤더 설정
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
|
||||
HttpEntity<Envelope<LedgerRequest>> requestEntity = new HttpEntity<>(requestEnvelope, headers);
|
||||
|
||||
// 2) API 호출
|
||||
ResponseEntity<Envelope<LedgerResponse>> responseEntity = restTemplate.exchange(
|
||||
vmisProperties.getExternal().getApi().getUrl().buildLedgerUrl(),
|
||||
HttpMethod.POST,
|
||||
requestEntity,
|
||||
new ParameterizedTypeReference<Envelope<LedgerResponse>>() {}
|
||||
);
|
||||
|
||||
// 3) 응답 로그 업데이트 (마스터 + 상세, 별도 트랜잭션)
|
||||
if (responseEntity.getStatusCode() == HttpStatus.OK && responseEntity.getBody() != null) {
|
||||
List<LedgerResponse> data = responseEntity.getBody().getData();
|
||||
if (data != null && !data.isEmpty()) {
|
||||
LedgerResponse body = data.get(0);
|
||||
VmisCarLedgerFrmbkVO masterUpdate = VmisCarLedgerFrmbkVO.fromResponseMaster(generatedId, body);
|
||||
ledgerLogService.updateResponseNewTx(masterUpdate);
|
||||
|
||||
List<VmisCarLedgerFrmbkDtlVO> details = VmisCarLedgerFrmbkDtlVO.listFromResponse(body, generatedId);
|
||||
if (details != null && !details.isEmpty()) {
|
||||
ledgerLogService.saveDetailsNewTx(generatedId, details);
|
||||
}
|
||||
return body;
|
||||
}
|
||||
}
|
||||
|
||||
log.warn("자동차 등록원부 조회 응답이 비어있음 - 차량번호: {}", request.getVhrno());
|
||||
return null;
|
||||
|
||||
} catch (Exception e) {
|
||||
// 4) 오류 로그 업데이트 (별도 트랜잭션)
|
||||
if (generatedId != null) {
|
||||
try {
|
||||
String detail = ExceptionDetailUtil.buildForLog(e);
|
||||
VmisCarLedgerFrmbkVO errorLog = VmisCarLedgerFrmbkVO.builder()
|
||||
.carLedgerFrmbkId(generatedId)
|
||||
.cntcResultCode(ApiConstant.CNTC_RESULT_CODE_ERROR)
|
||||
.cntcResultDtls(detail)
|
||||
.build();
|
||||
ledgerLogService.updateResponseNewTx(errorLog);
|
||||
log.error("[EXTERNAL-LEDGER-ERR-LOG] API 호출 에러 정보 저장 완료(별도TX) - ID: {}, detail: {}", generatedId, detail, e);
|
||||
} catch (Exception ignore) {
|
||||
log.error("[EXTERNAL-LEDGER-ERR-LOG] 에러 로그 저장 실패 - ID: {}", generatedId, ignore);
|
||||
}
|
||||
}
|
||||
log.error("자동차 등록원부 조회 API 호출 실패 - 차량번호: {}", request.getVhrno(), e);
|
||||
throw new MessageException("자동차 등록원부 조회 실패: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,91 @@
|
||||
package go.kr.project.api.external.service.impl;
|
||||
|
||||
import go.kr.project.api.external.service.ExternalVehicleApiService;
|
||||
import go.kr.project.api.model.VehicleApiResponseVO;
|
||||
import go.kr.project.api.model.request.BasicRequest;
|
||||
import go.kr.project.api.model.request.LedgerRequest;
|
||||
import go.kr.project.api.model.response.BasicResponse;
|
||||
import go.kr.project.api.model.response.LedgerResponse;
|
||||
import go.kr.project.api.service.VehicleInfoService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 외부 REST API를 호출하는 차량 정보 조회 서비스 구현체
|
||||
*
|
||||
* <p>이 구현체는 외부 VMIS-interface 서버의 REST API를 호출하여
|
||||
* 차량 정보를 조회합니다. 기존 ExternalVehicleApiService를 그대로 활용합니다.</p>
|
||||
*
|
||||
* <h3>활성화 조건:</h3>
|
||||
* <pre>
|
||||
* # application.yml
|
||||
* vmis:
|
||||
* integration:
|
||||
* mode: external
|
||||
* </pre>
|
||||
*
|
||||
* <h3>처리 흐름:</h3>
|
||||
* <ol>
|
||||
* <li>기존 ExternalVehicleApiService에 요청 위임</li>
|
||||
* <li>ExternalVehicleApiService가 외부 REST API 호출</li>
|
||||
* <li>결과를 그대로 반환</li>
|
||||
* </ol>
|
||||
*
|
||||
* <h3>외부 API 서버:</h3>
|
||||
* <ul>
|
||||
* <li>서버 URL: vmis.external.api.url 설정값 사용</li>
|
||||
* <li>기본값: http://localhost:8081/api/v1/vehicles</li>
|
||||
* <li>별도의 VMIS-interface 프로젝트가 실행 중이어야 함</li>
|
||||
* </ul>
|
||||
*
|
||||
* @see VehicleInfoService
|
||||
* @see ExternalVehicleApiService
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@ConditionalOnProperty(name = "vmis.integration.mode", havingValue = "external", matchIfMissing = true)
|
||||
public class ExternalVehicleInfoServiceImpl extends EgovAbstractServiceImpl implements VehicleInfoService {
|
||||
|
||||
private final ExternalVehicleApiService externalVehicleApiService;
|
||||
|
||||
@Override
|
||||
public VehicleApiResponseVO getVehicleInfo(BasicRequest basicRequest) {
|
||||
String vehicleNumber = basicRequest.getVhrno();
|
||||
log.info("[External Mode] 차량 정보 조회 시작 - 차량번호: {}, 부과기준일: {}, 조회구분: {}",
|
||||
vehicleNumber, basicRequest.getLevyStdde(), basicRequest.getInqireSeCode());
|
||||
|
||||
VehicleApiResponseVO response = externalVehicleApiService.getVehicleInfo(basicRequest);
|
||||
|
||||
if (response.isSuccess()) {
|
||||
log.info("[External Mode] 차량번호 {} 조회 성공", vehicleNumber);
|
||||
} else {
|
||||
log.warn("[External Mode] 차량번호 {} 조회 실패 - {}", vehicleNumber, response.getMessage());
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 외부 REST - 기본정보 단독 조회
|
||||
* 중요 로직: 외부 API 호출은 ExternalVehicleApiService에 위임 (BasicRequest 전체 전달)
|
||||
*/
|
||||
@Override
|
||||
public BasicResponse getBasicInfo(BasicRequest request) {
|
||||
// 중요 로직: 외부 API 호출은 ExternalVehicleApiService에 위임
|
||||
return externalVehicleApiService.getBasicInfo(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 외부 REST - 등록원부 단독 조회
|
||||
* 중요 로직: 등록원부 조회는 LedgerRequest 전체를 받아서 외부 API에 전달
|
||||
*/
|
||||
@Override
|
||||
public LedgerResponse getLedgerInfo(LedgerRequest request) {
|
||||
// 중요 로직: 외부 API 호출은 ExternalVehicleApiService에 위임
|
||||
return externalVehicleApiService.getLedgerInfo(request);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package go.kr.project.api.internal.client;
|
||||
|
||||
import go.kr.project.api.model.Envelope;
|
||||
import go.kr.project.api.model.request.BasicRequest;
|
||||
import go.kr.project.api.model.request.LedgerRequest;
|
||||
import go.kr.project.api.model.response.BasicResponse;
|
||||
import go.kr.project.api.model.response.LedgerResponse;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
/**
|
||||
* 정부 시스템 연계 API 추상화 인터페이스.
|
||||
*
|
||||
* <p>외부 정부 시스템과의 통신 계약을 명확히 하여 테스트 용이성과
|
||||
* 추후 교체 가능성을 높입니다.</p>
|
||||
*/
|
||||
public interface GovernmentApi {
|
||||
|
||||
ResponseEntity<Envelope<BasicResponse>> callBasic(Envelope<BasicRequest> envelope);
|
||||
|
||||
ResponseEntity<Envelope<LedgerResponse>> callLedger(Envelope<LedgerRequest> envelope);
|
||||
}
|
||||
@ -0,0 +1,627 @@
|
||||
package go.kr.project.api.internal.client;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import go.kr.project.api.config.properties.VmisProperties;
|
||||
import go.kr.project.api.internal.gpki.GpkiService;
|
||||
import go.kr.project.api.internal.util.TxIdUtil;
|
||||
import go.kr.project.api.model.Envelope;
|
||||
import go.kr.project.api.model.request.BasicRequest;
|
||||
import go.kr.project.api.model.request.LedgerRequest;
|
||||
import go.kr.project.api.model.response.BasicResponse;
|
||||
import go.kr.project.api.model.response.LedgerResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.client.HttpStatusCodeException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* 정부 시스템 API 클라이언트
|
||||
*
|
||||
* <p>이 클래스는 시군구연계 자동차 정보 조회를 위해 정부 시스템의 API를 호출하는
|
||||
* 클라이언트 역할을 수행합니다. HTTP 통신, 암호화, 에러 처리 등 정부 API와의
|
||||
* 모든 상호작용을 캡슐화합니다.</p>
|
||||
*
|
||||
* <h3>주요 책임:</h3>
|
||||
* <ul>
|
||||
* <li>정부 API 엔드포인트로 HTTP 요청 전송</li>
|
||||
* <li>GPKI(행정전자서명) 암호화/복호화 처리</li>
|
||||
* <li>필수 HTTP 헤더 구성 및 관리</li>
|
||||
* <li>요청/응답 데이터의 JSON 직렬화/역직렬화</li>
|
||||
* <li>트랜잭션 ID(tx_id) 생성 및 추적</li>
|
||||
* <li>네트워크 오류 및 HTTP 에러 처리</li>
|
||||
* <li>상세한 로깅을 통한 디버깅 지원</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h3>아키텍처 패턴:</h3>
|
||||
* <ul>
|
||||
* <li>Adapter 패턴: 외부 정부 시스템 API를 내부 인터페이스로 변환</li>
|
||||
* <li>Template Method 패턴: callModel 메서드가 공통 흐름을 정의</li>
|
||||
* <li>Dependency Injection: 생성자를 통한 의존성 주입</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h3>보안 특성:</h3>
|
||||
* <ul>
|
||||
* <li>GPKI 암호화를 통한 데이터 보안 (선택적 활성화)</li>
|
||||
* <li>API 키 기반 인증</li>
|
||||
* <li>기관 식별 정보(INFO_SYS_ID, REGION_CODE 등)를 헤더에 포함</li>
|
||||
* </ul>
|
||||
*
|
||||
* @see RestTemplate
|
||||
* @see GpkiService
|
||||
* @see VmisProperties
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Component
|
||||
public class GovernmentApiClient implements GovernmentApi {
|
||||
|
||||
/**
|
||||
* Spring RestTemplate (통합 RestTemplate 사용)
|
||||
*
|
||||
* <p>HTTP 클라이언트로서 실제 네트워크 통신을 수행합니다.
|
||||
* 이 객체는 Spring Bean으로 주입되며, 설정에 따라 다음을 포함할 수 있습니다:</p>
|
||||
* <ul>
|
||||
* <li>Connection Timeout 설정</li>
|
||||
* <li>Read Timeout 설정</li>
|
||||
* <li>Connection Pool 관리</li>
|
||||
* <li>Rate Limiting (초당 요청 수 제한)</li>
|
||||
* <li>메시지 컨버터 (Jackson for JSON)</li>
|
||||
* <li>인터셉터 (로깅, 헤더 추가 등)</li>
|
||||
* </ul>
|
||||
*/
|
||||
private final RestTemplate restTemplate;
|
||||
|
||||
/**
|
||||
* VMIS 설정 속성
|
||||
*
|
||||
* <p>application.yml 또는 application.properties에서 로드된 설정값들입니다.
|
||||
* 포함되는 주요 설정:</p>
|
||||
* <ul>
|
||||
* <li>정부 API URL (호스트, 포트, 경로)</li>
|
||||
* <li>API 키 및 인증 정보</li>
|
||||
* <li>시스템 식별 정보 (INFO_SYS_ID, REGION_CODE 등)</li>
|
||||
* <li>GPKI 설정 (인증서 서버 ID 등)</li>
|
||||
* </ul>
|
||||
*/
|
||||
private final VmisProperties props;
|
||||
|
||||
/**
|
||||
* GPKI(행정전자서명) 서비스
|
||||
*
|
||||
* <p>정부24 등 공공기관 간 통신에 사용되는 암호화 서비스입니다.
|
||||
* 주요 기능:</p>
|
||||
* <ul>
|
||||
* <li>요청 데이터 암호화 (공개키 암호화)</li>
|
||||
* <li>응답 데이터 복호화 (개인키 복호화)</li>
|
||||
* <li>전자서명 생성 및 검증</li>
|
||||
* <li>암호화 활성화 여부 확인</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>암호화가 비활성화된 경우 평문(Plain Text)으로 통신합니다.</p>
|
||||
*/
|
||||
private final GpkiService gpkiService;
|
||||
|
||||
/**
|
||||
* Jackson ObjectMapper
|
||||
*
|
||||
* <p>Java 객체와 JSON 문자열 간의 변환을 담당합니다.
|
||||
* 주요 역할:</p>
|
||||
* <ul>
|
||||
* <li>요청 객체를 JSON 문자열로 직렬화 (Serialization)</li>
|
||||
* <li>응답 JSON을 Java 객체로 역직렬화 (Deserialization)</li>
|
||||
* <li>제네릭 타입 처리 (TypeReference 사용)</li>
|
||||
* <li>날짜/시간 포맷 변환</li>
|
||||
* <li>null 값 처리</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>Spring Boot가 자동 구성한 ObjectMapper를 주입받아 사용하므로
|
||||
* 전역 설정(날짜 포맷, 네이밍 전략 등)이 일관되게 적용됩니다.</p>
|
||||
*/
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
|
||||
/**
|
||||
* 서비스 타입 열거형
|
||||
*
|
||||
* <p>정부 API 서비스의 종류를 구분하는 열거형입니다.
|
||||
* 각 서비스 타입은 서로 다른 엔드포인트와 API 키를 가집니다.</p>
|
||||
*
|
||||
* <h4>서비스 타입:</h4>
|
||||
* <ul>
|
||||
* <li>BASIC: 자동차 기본사항 조회 서비스
|
||||
* <ul>
|
||||
* <li>차량번호로 기본 정보(소유자, 차종, 용도 등) 조회</li>
|
||||
* <li>비교적 간단한 정보 제공</li>
|
||||
* <li>응답 속도가 빠름</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li>LEDGER: 자동차 등록원부(갑) 조회 서비스
|
||||
* <ul>
|
||||
* <li>상세한 등록 정보 및 법적 권리관계 조회</li>
|
||||
* <li>저당권, 압류, 소유권 이전 이력 등 포함</li>
|
||||
* <li>민감 정보를 포함하여 권한 검증이 엄격함</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* </ul>
|
||||
*/
|
||||
public enum ServiceType {
|
||||
/**
|
||||
* Basic service type.
|
||||
*/
|
||||
BASIC,
|
||||
/**
|
||||
* Ledger service type.
|
||||
*/
|
||||
LEDGER }
|
||||
|
||||
/**
|
||||
* HTTP 헤더 구성
|
||||
*
|
||||
* <p>정부 API 호출에 필요한 모든 HTTP 헤더를 구성하는 private 메서드입니다.
|
||||
* 정부 시스템은 엄격한 헤더 검증을 수행하므로 모든 필수 헤더가 정확히 포함되어야 합니다.</p>
|
||||
*
|
||||
* <h3>헤더 구성 항목:</h3>
|
||||
* <table border="1">
|
||||
* <tr>
|
||||
* <th>헤더명</th>
|
||||
* <th>설명</th>
|
||||
* <th>예시값</th>
|
||||
* <th>필수여부</th>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>Content-Type</td>
|
||||
* <td>요청 바디의 미디어 타입 및 문자 인코딩</td>
|
||||
* <td>application/json; charset=UTF-8</td>
|
||||
* <td>필수</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>Accept</td>
|
||||
* <td>클라이언트가 수용 가능한 응답 형식</td>
|
||||
* <td>application/json</td>
|
||||
* <td>필수</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>gpki_yn</td>
|
||||
* <td>GPKI 암호화 사용 여부 (Y/N)</td>
|
||||
* <td>Y</td>
|
||||
* <td>필수</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>tx_id</td>
|
||||
* <td>트랜잭션 고유 ID (요청 추적용)</td>
|
||||
* <td>20250104123045_abc123</td>
|
||||
* <td>필수</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>cert_server_id</td>
|
||||
* <td>인증서 서버 식별자</td>
|
||||
* <td>VMIS_SERVER_01</td>
|
||||
* <td>필수</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>api_key</td>
|
||||
* <td>서비스별 API 인증 키</td>
|
||||
* <td>abc123def456...</td>
|
||||
* <td>필수</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>cvmis_apikey</td>
|
||||
* <td>CVMIS 시스템 API 키</td>
|
||||
* <td>xyz789uvw012...</td>
|
||||
* <td>필수</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>INFO_SYS_ID</td>
|
||||
* <td>정보시스템 식별자</td>
|
||||
* <td>VMIS_SEOUL</td>
|
||||
* <td>필수</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*
|
||||
* <h3>문자 인코딩:</h3>
|
||||
* <ul>
|
||||
* <li>Content-Type에 UTF-8 인코딩을 명시적으로 지정</li>
|
||||
* <li>한글 데이터 처리를 위해 필수</li>
|
||||
* <li>정부 시스템이 다양한 클라이언트와 호환되도록 표준 인코딩 사용</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h3>보안 고려사항:</h3>
|
||||
* <ul>
|
||||
* <li>API 키는 설정 파일에서 안전하게 관리</li>
|
||||
* <li>로그에 API 키가 노출되지 않도록 주의</li>
|
||||
* <li>각 서비스(BASIC, LEDGER)마다 별도의 API 키 사용 가능</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param svc 서비스 설정 객체 (API 키, 경로 등 포함)
|
||||
* @param txId 이번 요청의 트랜잭션 ID
|
||||
* @return HttpHeaders 구성된 HTTP 헤더 객체
|
||||
*/
|
||||
private HttpHeaders buildHeaders(VmisProperties.GovProps.Service svc, String txId) {
|
||||
// 1. 빈 HttpHeaders 객체 생성
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
|
||||
// 2. Content-Type 설정
|
||||
// UTF-8 인코딩을 명시하여 한글 데이터가 올바르게 전송되도록 함
|
||||
headers.setContentType(new MediaType("application", "json", StandardCharsets.UTF_8));
|
||||
|
||||
// 3. Accept 헤더 설정
|
||||
// 서버에게 JSON 형식의 응답을 요청함
|
||||
headers.setAccept(java.util.Collections.singletonList(MediaType.APPLICATION_JSON));
|
||||
|
||||
// 4. GPKI 암호화 사용 여부
|
||||
// 정부 서버가 요청 바디 복호화 여부를 결정하는 데 사용
|
||||
headers.add("gpki_yn", gpkiService.isEnabled() ? "Y" : "N");
|
||||
|
||||
// 5. 트랜잭션 ID
|
||||
// 요청 추적, 로그 연관, 문제 해결 시 사용
|
||||
headers.add("tx_id", txId);
|
||||
|
||||
// 6. 인증서 서버 ID
|
||||
// GPKI 인증서를 발급받은 서버의 식별자
|
||||
headers.add("cert_server_id", props.getGpki().getCertServerId());
|
||||
|
||||
// 7. API 인증 키
|
||||
// 서비스별로 다른 API 키 사용 가능 (BASIC과 LEDGER 각각)
|
||||
headers.add("api_key", svc.getApiKey());
|
||||
|
||||
// 8. CVMIS API 키
|
||||
// CVMIS(Car Vehicle Management Information System) 전용 API 키
|
||||
headers.add("cvmis_apikey", svc.getCvmisApikey());
|
||||
|
||||
// 구성 완료된 헤더 반환
|
||||
return headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* 자동차 기본사항 조회 API 호출
|
||||
*
|
||||
* <p>타입 안전성이 보장되는 자동차 기본사항 조회 메서드입니다.
|
||||
* 내부적으로 {@link #callModel}을 호출하여 실제 통신을 수행합니다.</p>
|
||||
*
|
||||
* <h3>특징:</h3>
|
||||
* <ul>
|
||||
* <li>제네릭 타입으로 컴파일 타입 타입 체크</li>
|
||||
* <li>요청/응답 객체가 Envelope로 감싸져 있음</li>
|
||||
* <li>Jackson TypeReference를 사용한 제네릭 역직렬화</li>
|
||||
* <li>API 호출 전후로 DB에 로그성 데이터 저장</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h3>처리 흐름:</h3>
|
||||
* <ol>
|
||||
* <li>요청 정보를 DB에 INSERT (로그 저장)</li>
|
||||
* <li>정부 API 호출</li>
|
||||
* <li>응답 정보를 DB에 UPDATE</li>
|
||||
* <li>에러 발생 시 에러 정보도 DB에 UPDATE</li>
|
||||
* </ol>
|
||||
*
|
||||
* <h3>사용 예시:</h3>
|
||||
* <pre>
|
||||
* BasicRequest request = new BasicRequest();
|
||||
* request.setVehicleNo("12가3456");
|
||||
*
|
||||
* Envelope<BasicRequest> envelope = new Envelope<>();
|
||||
* envelope.setData(request);
|
||||
*
|
||||
* ResponseEntity<Envelope<BasicResponse>> response = govClient.callBasic(envelope);
|
||||
* BasicResponse data = response.getBody().getData();
|
||||
* </pre>
|
||||
*
|
||||
* @param envelope 자동차 기본사항 조회 요청을 담은 Envelope
|
||||
* @return ResponseEntity<Envelope<BasicResponse>> 조회 결과를 담은 응답
|
||||
*/
|
||||
public ResponseEntity<Envelope<BasicResponse>> callBasic(Envelope<BasicRequest> envelope) {
|
||||
// 순수한 전송 책임만 수행: DB 로깅은 서비스 레이어에서 처리
|
||||
return callModel(ServiceType.BASIC, envelope, new TypeReference<Envelope<BasicResponse>>(){});
|
||||
}
|
||||
|
||||
/**
|
||||
* 자동차 등록원부(갑) 조회 API 호출
|
||||
*
|
||||
* <p>타입 안전성이 보장되는 자동차 등록원부 조회 메서드입니다.
|
||||
* 내부적으로 {@link #callModel}을 호출하여 실제 통신을 수행합니다.</p>
|
||||
*
|
||||
* <h3>특징:</h3>
|
||||
* <ul>
|
||||
* <li>제네릭 타입으로 컴파일 타임 타입 체크</li>
|
||||
* <li>요청/응답 객체가 Envelope로 감싸져 있음</li>
|
||||
* <li>Jackson TypeReference를 사용한 제네릭 역직렬화</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h3>사용 예시:</h3>
|
||||
* <pre>
|
||||
* LedgerRequest request = new LedgerRequest();
|
||||
* request.setVehicleNo("12가3456");
|
||||
* request.setOwnerName("홍길동");
|
||||
*
|
||||
* Envelope<LedgerRequest> envelope = new Envelope<>();
|
||||
* envelope.setData(request);
|
||||
*
|
||||
* ResponseEntity<Envelope<LedgerResponse>> response = govClient.callLedger(envelope);
|
||||
* LedgerResponse data = response.getBody().getData();
|
||||
* </pre>
|
||||
*
|
||||
* @param envelope 자동차 등록원부 조회 요청을 담은 Envelope
|
||||
* @return ResponseEntity<Envelope<LedgerResponse>> 조회 결과를 담은 응답
|
||||
*/
|
||||
public ResponseEntity<Envelope<LedgerResponse>> callLedger(Envelope<LedgerRequest> envelope) {
|
||||
// TypeReference를 사용하여 제네릭 타입 정보 전달
|
||||
// 익명 클래스를 생성하여 타입 소거(Type Erasure) 문제 해결
|
||||
return callModel(ServiceType.LEDGER, envelope, new TypeReference<Envelope<LedgerResponse>>(){});
|
||||
}
|
||||
|
||||
/**
|
||||
* 정부 API 호출 (타입 안전 모델 기반)
|
||||
*
|
||||
* <p>이 메서드는 정부 API 호출의 핵심 로직을 담고 있는 제네릭 메서드입니다.
|
||||
* Java 객체를 받아 JSON으로 변환하고, 암호화하여 전송한 후, 응답을 복호화하여
|
||||
* 다시 Java 객체로 변환하는 전체 파이프라인을 처리합니다.</p>
|
||||
*
|
||||
* <h3>Template Method 패턴:</h3>
|
||||
* <ul>
|
||||
* <li>이 메서드는 Template Method 패턴의 템플릿 역할</li>
|
||||
* <li>공통 처리 흐름을 정의하고 서비스별 차이는 파라미터로 처리</li>
|
||||
* <li>코드 중복을 제거하고 일관성을 보장</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h3>제네릭 타입 파라미터:</h3>
|
||||
* <ul>
|
||||
* <li><TReq>: 요청 데이터 타입 (BasicRequest 또는 LedgerRequest)</li>
|
||||
* <li><TResp>: 응답 데이터 타입 (BasicResponse 또는 LedgerResponse)</li>
|
||||
* <li>타입 안전성을 보장하여 런타임 에러 방지</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h3>처리 흐름 (상세):</h3>
|
||||
* <ol>
|
||||
* <li><b>설정 로드:</b>
|
||||
* <ul><li>서비스 타입에 따라 BASIC 또는 LEDGER 설정 선택</li></ul>
|
||||
* </li>
|
||||
* <li><b>URL 및 트랜잭션 ID 구성:</b>
|
||||
* <ul><li>완전한 API URL 생성</li>
|
||||
* <li>고유 트랜잭션 ID 생성</li></ul>
|
||||
* </li>
|
||||
* <li><b>직렬화 (Serialization):</b>
|
||||
* <ul><li>Java 객체(Envelope<TReq>)를 JSON 문자열로 변환</li>
|
||||
* <li>ObjectMapper.writeValueAsString() 사용</li></ul>
|
||||
* </li>
|
||||
* <li><b>헤더 구성:</b>
|
||||
* <ul><li>buildHeaders() 메서드 호출</li>
|
||||
* <li>모든 필수 헤더 추가</li></ul>
|
||||
* </li>
|
||||
* <li><b>GPKI 암호화 (선택적):</b>
|
||||
* <ul><li>GPKI가 활성화된 경우 JSON을 암호화</li>
|
||||
* <li>gpkiEncrypt() 메서드 호출</li></ul>
|
||||
* </li>
|
||||
* <li><b>HTTP 요청 전송:</b>
|
||||
* <ul><li>RestTemplate.exchange()로 POST 요청</li>
|
||||
* <li>요청 로그 기록</li></ul>
|
||||
* </li>
|
||||
* <li><b>GPKI 복호화 (선택적):</b>
|
||||
* <ul><li>성공 응답(2xx)이고 GPKI가 활성화된 경우</li>
|
||||
* <li>gpkiDecrypt() 메서드 호출</li></ul>
|
||||
* </li>
|
||||
* <li><b>역직렬화 (Deserialization):</b>
|
||||
* <ul><li>JSON 문자열을 Java 객체(Envelope<TResp>)로 변환</li>
|
||||
* <li>TypeReference를 사용하여 제네릭 타입 정보 보존</li></ul>
|
||||
* </li>
|
||||
* <li><b>응답 반환:</b>
|
||||
* <ul><li>ResponseEntity로 감싸서 HTTP 정보 포함</li></ul>
|
||||
* </li>
|
||||
* </ol>
|
||||
*
|
||||
* <h3>에러 처리 전략 (3단계):</h3>
|
||||
* <ol>
|
||||
* <li><b>HttpStatusCodeException (HTTP 에러):</b>
|
||||
* <ul>
|
||||
* <li>정부 API가 4xx 또는 5xx 상태 코드를 반환한 경우</li>
|
||||
* <li>에러 응답 바디를 파싱하여 Envelope 객체로 변환 시도</li>
|
||||
* <li>파싱 실패 시 빈 Envelope 객체 반환</li>
|
||||
* <li>에러 로그 기록 (WARN 레벨)</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li><b>JSON 파싱 에러:</b>
|
||||
* <ul>
|
||||
* <li>응답 JSON이 예상한 형식과 다른 경우</li>
|
||||
* <li>RuntimeException으로 래핑하여 상위로 전파</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li><b>기타 예외:</b>
|
||||
* <ul>
|
||||
* <li>네트워크 타임아웃, 연결 실패 등</li>
|
||||
* <li>RuntimeException으로 래핑하여 상위로 전파</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* </ol>
|
||||
*
|
||||
* <h3>TypeReference의 필요성:</h3>
|
||||
* <p>Java의 제네릭은 런타임에 타입 소거(Type Erasure)가 발생하여
|
||||
* {@code objectMapper.readValue(json, Envelope<TResp>.class)}와 같은 코드는
|
||||
* 컴파일되지 않습니다. TypeReference는 익명 클래스를 사용하여 컴파일 타임의
|
||||
* 제네릭 타입 정보를 런타임에 전달하는 Jackson의 메커니즘입니다.</p>
|
||||
*
|
||||
* <h3>로깅 정보:</h3>
|
||||
* <ul>
|
||||
* <li>요청 로그: [GOV-REQ] url, tx_id, gpki, length</li>
|
||||
* <li>에러 로그: [GOV-ERR] status, body</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param <TReq> 요청 데이터의 제네릭 타입
|
||||
* @param <TResp> 응답 데이터의 제네릭 타입
|
||||
* @param type 서비스 타입 (BASIC 또는 LEDGER)
|
||||
* @param envelope 요청 데이터를 담은 Envelope 객체
|
||||
* @param respType 응답 타입에 대한 TypeReference (제네릭 타입 정보 보존용)
|
||||
* @return ResponseEntity<Envelope<TResp>> 응답 데이터를 담은 ResponseEntity
|
||||
* @throws RuntimeException JSON 직렬화/역직렬화 실패, 네트워크 오류, GPKI 암복호화 실패 등
|
||||
*/
|
||||
private <TReq, TResp> ResponseEntity<Envelope<TResp>> callModel(ServiceType type,
|
||||
Envelope<TReq> envelope,
|
||||
TypeReference<Envelope<TResp>> respType) {
|
||||
// 1. 서비스 타입에 따른 설정 로드
|
||||
VmisProperties.GovProps gov = props.getGov();
|
||||
VmisProperties.GovProps.Service svc = (type == ServiceType.BASIC)
|
||||
? gov.getServices().getBasic()
|
||||
: gov.getServices().getLedger();
|
||||
|
||||
// 2. URL 및 트랜잭션 ID 생성
|
||||
String url = gov.buildServiceUrl(svc.getPath());
|
||||
String txId = TxIdUtil.generate();
|
||||
|
||||
try {
|
||||
// 3. 직렬화: Java 객체 → JSON 문자열
|
||||
// ObjectMapper가 Envelope 객체를 JSON으로 변환
|
||||
// 날짜, null 값 등의 처리는 ObjectMapper 설정에 따름
|
||||
String jsonBody = objectMapper.writeValueAsString(envelope);
|
||||
|
||||
// 4. HTTP 헤더 구성
|
||||
HttpHeaders headers = buildHeaders(svc, txId);
|
||||
|
||||
// 5. GPKI 암호화 처리
|
||||
String bodyToSend = jsonBody;
|
||||
if (gpkiService.isEnabled()) {
|
||||
// JSON 평문을 암호화된 문자열로 변환
|
||||
bodyToSend = gpkiEncrypt(jsonBody);
|
||||
}
|
||||
|
||||
// 6. HTTP 엔티티 생성 (헤더 + 바디)
|
||||
HttpEntity<String> request = new HttpEntity<>(bodyToSend, headers);
|
||||
|
||||
// 7. 요청 로그 기록
|
||||
log.info("[GOV-REQ] url={}, tx_id={}, gpki={}, length={}", url, txId, gpkiService.isEnabled(), bodyToSend != null ? bodyToSend.length() : 0);
|
||||
|
||||
// 8. 실제 HTTP POST 요청 전송
|
||||
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, request, String.class);
|
||||
String respBody = response.getBody();
|
||||
|
||||
// 9. GPKI 복호화 처리 (성공 응답인 경우만)
|
||||
if (gpkiService.isEnabled() && response.getStatusCode().is2xxSuccessful()) {
|
||||
// 암호화된 응답을 평문 JSON으로 복호화
|
||||
respBody = gpkiDecrypt(respBody);
|
||||
}
|
||||
|
||||
// 10. 역직렬화: JSON 문자열 → Java 객체
|
||||
// TypeReference를 사용하여 제네릭 타입 정보 전달
|
||||
Envelope<TResp> mapped = objectMapper.readValue(respBody, respType);
|
||||
|
||||
// 11. 응답 반환 (상태 코드, 헤더, 바디 모두 포함)
|
||||
return ResponseEntity.status(response.getStatusCode()).headers(response.getHeaders()).body(mapped);
|
||||
|
||||
} catch (HttpStatusCodeException ex) {
|
||||
// HTTP 에러 처리 (4xx, 5xx)
|
||||
log.warn("[GOV-ERR] status={}, body={}", ex.getStatusCode(), ex.getResponseBodyAsString());
|
||||
|
||||
// 에러 응답 바디 파싱 시도
|
||||
// 정부 API는 에러 응답도 Envelope 형식으로 반환할 수 있음
|
||||
Envelope<TResp> empty = new Envelope<>();
|
||||
try {
|
||||
// 에러 응답을 Envelope 객체로 파싱
|
||||
Envelope<TResp> parsed = objectMapper.readValue(ex.getResponseBodyAsString(), respType);
|
||||
return ResponseEntity.status(ex.getStatusCode()).headers(ex.getResponseHeaders() != null ? ex.getResponseHeaders() : new HttpHeaders()).body(parsed);
|
||||
} catch (Exception parseEx) {
|
||||
// 파싱 실패 시 빈 Envelope 반환
|
||||
// 호출자는 HTTP 상태 코드로 에러 판단 가능
|
||||
return ResponseEntity.status(ex.getStatusCode()).headers(ex.getResponseHeaders() != null ? ex.getResponseHeaders() : new HttpHeaders()).body(empty);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 기타 모든 예외 (네트워크 오류, JSON 파싱 오류, GPKI 오류 등)
|
||||
// RuntimeException으로 래핑하여 상위로 전파
|
||||
// Spring의 @ExceptionHandler에서 처리 가능
|
||||
throw new RuntimeException("정부 API 호출 중 오류", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GPKI 암호화 처리
|
||||
*
|
||||
* <p>평문 JSON 문자열을 GPKI(행정전자서명) 알고리즘으로 암호화하는 헬퍼 메서드입니다.
|
||||
* 암호화 실패 시 명확한 에러 메시지와 함께 RuntimeException을 발생시킵니다.</p>
|
||||
*
|
||||
* <h3>암호화 과정:</h3>
|
||||
* <ol>
|
||||
* <li>평문 JSON 문자열을 바이트 배열로 변환</li>
|
||||
* <li>정부 시스템의 공개키를 사용하여 암호화</li>
|
||||
* <li>암호화된 바이트 배열을 Base64로 인코딩</li>
|
||||
* <li>Base64 문자열 반환</li>
|
||||
* </ol>
|
||||
*
|
||||
* <h3>에러 처리:</h3>
|
||||
* <ul>
|
||||
* <li>인증서 오류: GPKI 인증서가 유효하지 않거나 만료된 경우</li>
|
||||
* <li>암호화 오류: 암호화 알고리즘 실행 중 오류 발생</li>
|
||||
* <li>인코딩 오류: Base64 인코딩 실패</li>
|
||||
* <li>모든 예외는 RuntimeException으로 래핑하여 즉시 중단</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h3>보안 고려사항:</h3>
|
||||
* <ul>
|
||||
* <li>공개키 암호화 방식 사용 (비대칭키)</li>
|
||||
* <li>정부 시스템만 개인키로 복호화 가능</li>
|
||||
* <li>민감한 개인정보 보호</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param jsonBody 암호화할 평문 JSON 문자열
|
||||
* @return String Base64로 인코딩된 암호화 문자열
|
||||
* @throws RuntimeException GPKI 암호화 실패 시
|
||||
*/
|
||||
private String gpkiEncrypt(String jsonBody) {
|
||||
try {
|
||||
// GpkiService에 암호화 위임
|
||||
// 실제 암호화 로직은 GpkiService가 캡슐화
|
||||
return gpkiService.encrypt(jsonBody);
|
||||
} catch (Exception e) {
|
||||
// 암호화 실패는 치명적 오류
|
||||
// 평문 데이터를 전송할 수 없으므로 즉시 중단
|
||||
throw new RuntimeException("GPKI 암호화 실패", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GPKI 복호화 처리
|
||||
*
|
||||
* <p>암호화된 응답 문자열을 GPKI(행정전자서명) 알고리즘으로 복호화하는 헬퍼 메서드입니다.
|
||||
* 복호화 실패 시 명확한 에러 메시지와 함께 RuntimeException을 발생시킵니다.</p>
|
||||
*
|
||||
* <h3>복호화 과정:</h3>
|
||||
* <ol>
|
||||
* <li>Base64로 인코딩된 암호문을 바이트 배열로 디코딩</li>
|
||||
* <li>우리 시스템의 개인키를 사용하여 복호화</li>
|
||||
* <li>복호화된 바이트 배열을 UTF-8 문자열로 변환</li>
|
||||
* <li>평문 JSON 문자열 반환</li>
|
||||
* </ol>
|
||||
*
|
||||
* <h3>에러 처리:</h3>
|
||||
* <ul>
|
||||
* <li>인증서 오류: GPKI 인증서가 유효하지 않거나 만료된 경우</li>
|
||||
* <li>복호화 오류: 암호문이 손상되었거나 올바르지 않은 경우</li>
|
||||
* <li>디코딩 오류: Base64 디코딩 실패</li>
|
||||
* <li>문자 인코딩 오류: UTF-8 변환 실패</li>
|
||||
* <li>모든 예외는 RuntimeException으로 래핑하여 즉시 중단</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h3>보안 고려사항:</h3>
|
||||
* <ul>
|
||||
* <li>개인키 암호화 방식 사용 (비대칭키)</li>
|
||||
* <li>개인키는 안전하게 저장 및 관리 필요</li>
|
||||
* <li>복호화 실패 시 상세 에러 정보 로깅 주의 (정보 유출 방지)</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param cipher Base64로 인코딩된 암호화 문자열
|
||||
* @return String 복호화된 평문 JSON 문자열
|
||||
* @throws RuntimeException GPKI 복호화 실패 시
|
||||
*/
|
||||
private String gpkiDecrypt(String cipher) {
|
||||
try {
|
||||
// GpkiService에 복호화 위임
|
||||
// 실제 복호화 로직은 GpkiService가 캡슐화
|
||||
return gpkiService.decrypt(cipher);
|
||||
} catch (Exception e) {
|
||||
// 복호화 실패는 치명적 오류
|
||||
// 암호문을 해석할 수 없으므로 즉시 중단
|
||||
throw new RuntimeException("GPKI 복호화 실패", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package go.kr.project.api.internal.config;
|
||||
|
||||
import go.kr.project.api.config.properties.VmisProperties;
|
||||
import go.kr.project.api.internal.gpki.GpkiService;
|
||||
import go.kr.project.api.internal.gpki.NoopGpkiService;
|
||||
import go.kr.project.api.internal.gpki.RealGpkiService;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class GpkiConfig {
|
||||
|
||||
@Bean
|
||||
public GpkiService gpkiService(VmisProperties properties) {
|
||||
if (properties.getGpki().isEnabledFlag()) {
|
||||
return new RealGpkiService(properties);
|
||||
}
|
||||
return new NoopGpkiService();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package go.kr.project.api.internal.config;
|
||||
|
||||
import io.swagger.v3.oas.models.ExternalDocumentation;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.info.Contact;
|
||||
import io.swagger.v3.oas.models.info.Info;
|
||||
import io.swagger.v3.oas.models.info.License;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class OpenApiConfig {
|
||||
|
||||
@Bean
|
||||
public OpenAPI vmisOpenAPI() {
|
||||
return new OpenAPI()
|
||||
.info(new Info()
|
||||
.title("VMIS Interface API")
|
||||
.description("시군구연계 자동차 정보 인터페이스 API (자망연계)")
|
||||
.version("v0.1.0")
|
||||
.contact(new Contact().name("VMIS").email("support@example.com"))
|
||||
.license(new License().name("Apache 2.0").url("https://www.apache.org/licenses/LICENSE-2.0.html")))
|
||||
.externalDocs(new ExternalDocumentation()
|
||||
.description("Reference")
|
||||
.url(""));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
package go.kr.project.api.internal.config;
|
||||
|
||||
import go.kr.project.api.config.properties.VmisProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(VmisProperties.class)
|
||||
public class PropertiesConfig {
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package go.kr.project.api.internal.gpki;
|
||||
|
||||
public interface GpkiService {
|
||||
String encrypt(String plain) throws Exception;
|
||||
String decrypt(String cipher) throws Exception;
|
||||
boolean isEnabled();
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package go.kr.project.api.internal.gpki;
|
||||
|
||||
public class NoopGpkiService implements GpkiService {
|
||||
@Override
|
||||
public String encrypt(String plain) {
|
||||
return plain;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String decrypt(String cipher) {
|
||||
return cipher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package go.kr.project.api.internal.gpki;
|
||||
|
||||
import go.kr.project.api.config.properties.VmisProperties;
|
||||
import go.kr.project.api.internal.util.GpkiCryptoUtil;
|
||||
|
||||
/**
|
||||
* Real GPKI service backed by native GPKI JNI via legacy NewGpkiUtil wrapper.
|
||||
* Uses YAML-configured paths and options in {@link VmisProperties.GpkiProps}.
|
||||
*/
|
||||
public class RealGpkiService implements GpkiService {
|
||||
|
||||
private final VmisProperties props;
|
||||
private final GpkiCryptoUtil crypto;
|
||||
|
||||
public RealGpkiService(VmisProperties props) {
|
||||
this.props = props;
|
||||
try {
|
||||
this.crypto = GpkiCryptoUtil.from(props.getGpki());
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("Failed to initialize GPKI (JNI) util. Check YAML paths/passwords and license.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encrypt(String plain) throws Exception {
|
||||
String charset = props.getGpki().getCharset();
|
||||
String targetId = props.getGpki().getTargetServerId();
|
||||
return crypto.encryptToBase64(plain, targetId, charset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String decrypt(String cipher) throws Exception {
|
||||
String charset = props.getGpki().getCharset();
|
||||
return crypto.decryptFromBase64(cipher, charset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package go.kr.project.api.internal.mapper;
|
||||
|
||||
import go.kr.project.api.model.response.VmisCarLedgerFrmbkDtlVO;
|
||||
import go.kr.project.api.model.response.VmisCarLedgerFrmbkVO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 자동차 등록 원부(갑) Mapper
|
||||
*/
|
||||
@Mapper
|
||||
public interface VmisCarLedgerFrmbkMapper {
|
||||
|
||||
// ID 시퀀스
|
||||
String selectNextCarLedgerFrmbkId();
|
||||
String selectNextCarLedgerFrmbkDtlId();
|
||||
|
||||
// 마스터 INSERT/UPDATE/SELECT
|
||||
int insertCarLedgerFrmbk(VmisCarLedgerFrmbkVO vo);
|
||||
int updateCarLedgerFrmbk(VmisCarLedgerFrmbkVO vo);
|
||||
VmisCarLedgerFrmbkVO selectCarLedgerFrmbkById(String carLedgerFrmbkId);
|
||||
|
||||
// 상세 INSERT (단건)
|
||||
int insertCarLedgerFrmbkDtl(VmisCarLedgerFrmbkDtlVO vo);
|
||||
|
||||
// 편의: 상세 일괄 (MyBatis foreach를 XML에서 사용할 수도 있으나, 여기서는 단건 호출을 반복)
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package go.kr.project.api.internal.service;
|
||||
|
||||
import go.kr.project.api.model.Envelope;
|
||||
import go.kr.project.api.model.request.BasicRequest;
|
||||
import go.kr.project.api.model.response.BasicResponse;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
/**
|
||||
* 자동차 기본사항 조회 서비스 인터페이스
|
||||
*
|
||||
* <p>API 호출 정보를 관리하는 서비스입니다.</p>
|
||||
* <ul>
|
||||
* <li>요청 데이터 보강</li>
|
||||
* <li>최초 요청 로그 저장</li>
|
||||
* <li>외부 API 호출</li>
|
||||
* <li>응답 로그 업데이트</li>
|
||||
* </ul>
|
||||
*/
|
||||
public interface VmisCarBassMatterInqireService {
|
||||
|
||||
/**
|
||||
* 자동차 기본사항 조회
|
||||
*
|
||||
* @param envelope 요청 Envelope
|
||||
* @return 응답 Envelope
|
||||
*/
|
||||
ResponseEntity<Envelope<BasicResponse>> basic(Envelope<BasicRequest> envelope);
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package go.kr.project.api.internal.service;
|
||||
|
||||
import go.kr.project.api.model.Envelope;
|
||||
import go.kr.project.api.model.request.LedgerRequest;
|
||||
import go.kr.project.api.model.response.LedgerResponse;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
/**
|
||||
* 자동차 등록 원부(갑) 서비스 인터페이스
|
||||
* - 요청 보강, 외부 API 호출, 로그 서비스 위임
|
||||
*/
|
||||
public interface VmisCarLedgerFrmbkService {
|
||||
|
||||
/**
|
||||
* 자동차 등록원부(갑) 조회
|
||||
*
|
||||
* @param envelope 요청 Envelope
|
||||
* @return 응답 Envelope
|
||||
*/
|
||||
ResponseEntity<Envelope<LedgerResponse>> ledger(Envelope<LedgerRequest> envelope);
|
||||
}
|
||||
@ -0,0 +1,85 @@
|
||||
package go.kr.project.api.internal.service;
|
||||
|
||||
import go.kr.project.api.config.properties.VmisProperties;
|
||||
import go.kr.project.api.model.Envelope;
|
||||
import go.kr.project.api.model.request.BasicRequest;
|
||||
import go.kr.project.api.model.request.LedgerRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Populates incoming request models with values from YAML configuration.
|
||||
* Unconditionally overwrites the listed fields per requirement:
|
||||
* - INFO_SYS_ID, INFO_SYS_IP, SIGUNGU_CODE
|
||||
* - CNTC_INFO_CODE (service specific)
|
||||
* - CHARGER_ID, CHARGER_IP, CHARGER_NM
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class VmisRequestEnricher {
|
||||
|
||||
private final VmisProperties props;
|
||||
|
||||
public VmisRequestEnricher(VmisProperties props) {
|
||||
this.props = props;
|
||||
}
|
||||
|
||||
public void enrichBasic(Envelope<BasicRequest> envelope) {
|
||||
if (envelope == null || envelope.getData() == null) return;
|
||||
VmisProperties.SystemProps sys = props.getSystem();
|
||||
String cntc = props.getGov().getServices().getBasic().getCntcInfoCode();
|
||||
for (BasicRequest req : envelope.getData()) {
|
||||
if (req == null) continue;
|
||||
req.setInfoSysId(sys.getInfoSysId());
|
||||
req.setInfoSysIp(sys.getInfoSysIp());
|
||||
req.setSigunguCode(sys.getSigunguCode());
|
||||
req.setCntcInfoCode(cntc);
|
||||
req.setChargerId(sys.getChargerId());
|
||||
req.setChargerIp(sys.getChargerIp());
|
||||
req.setChargerNm(sys.getChargerNm());
|
||||
|
||||
// 조회구분코드 자동 설정: VHRNO가 있으면 "3" (자동차번호), VIN이 있으면 "2" (차대번호)
|
||||
if (req.getInqireSeCode() == null) {
|
||||
if (req.getVhrno() != null && !req.getVhrno().trim().isEmpty()) {
|
||||
req.setInqireSeCode("3"); // 자동차번호로 조회
|
||||
} else if (req.getVin() != null && !req.getVin().trim().isEmpty()) {
|
||||
req.setInqireSeCode("2"); // 차대번호로 조회
|
||||
}
|
||||
}
|
||||
}
|
||||
log.debug("[ENRICH] basic: applied INFO_SYS_ID={}, INFO_SYS_IP={}, SIGUNGU_CODE={}, CNTC_INFO_CODE={}",
|
||||
sys.getInfoSysId(), sys.getInfoSysIp(), sys.getSigunguCode(), cntc);
|
||||
}
|
||||
|
||||
public void enrichLedger(Envelope<LedgerRequest> envelope) {
|
||||
if (envelope == null || envelope.getData() == null) return;
|
||||
VmisProperties.SystemProps sys = props.getSystem();
|
||||
String cntc = props.getGov().getServices().getLedger().getCntcInfoCode();
|
||||
for (LedgerRequest req : envelope.getData()) {
|
||||
if (req == null) continue;
|
||||
req.setInfoSysId(sys.getInfoSysId());
|
||||
req.setInfoSysIp(sys.getInfoSysIp());
|
||||
req.setSigunguCode(sys.getSigunguCode());
|
||||
req.setCntcInfoCode(cntc);
|
||||
req.setChargerId(sys.getChargerId());
|
||||
req.setChargerIp(sys.getChargerIp());
|
||||
req.setChargerNm(sys.getChargerNm());
|
||||
|
||||
// 고정값 설정 (값이 없는 경우에만 설정)
|
||||
if (req.getOnesInformationOpen() == null || req.getOnesInformationOpen().isEmpty()) {
|
||||
req.setOnesInformationOpen("1"); // 개인정보공개 (소유자공개)
|
||||
}
|
||||
if (req.getRouteSeCode() == null || req.getRouteSeCode().isEmpty()) {
|
||||
req.setRouteSeCode("3"); // 경로구분코드
|
||||
}
|
||||
if (req.getDetailExpression() == null || req.getDetailExpression().isEmpty()) {
|
||||
req.setDetailExpression("1"); // 내역표시 (전체내역)
|
||||
}
|
||||
if (req.getInqireSeCode() == null || req.getInqireSeCode().isEmpty()) {
|
||||
req.setInqireSeCode("1"); // 조회구분코드 (열람)
|
||||
}
|
||||
}
|
||||
log.debug("[ENRICH] ledger: applied INFO_SYS_ID={}, INFO_SYS_IP={}, SIGUNGU_CODE={}, CNTC_INFO_CODE={}",
|
||||
sys.getInfoSysId(), sys.getInfoSysIp(), sys.getSigunguCode(), cntc);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,213 @@
|
||||
package go.kr.project.api.internal.service.impl;
|
||||
|
||||
import go.kr.project.api.config.ApiConstant;
|
||||
import go.kr.project.api.internal.service.VmisCarBassMatterInqireService;
|
||||
import go.kr.project.api.internal.service.VmisCarLedgerFrmbkService;
|
||||
import go.kr.project.api.model.Envelope;
|
||||
import go.kr.project.api.model.VehicleApiResponseVO;
|
||||
import go.kr.project.api.model.request.BasicRequest;
|
||||
import go.kr.project.api.model.request.LedgerRequest;
|
||||
import go.kr.project.api.model.response.BasicResponse;
|
||||
import go.kr.project.api.model.response.LedgerResponse;
|
||||
import go.kr.project.api.service.VehicleInfoService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 내부 VMIS 모듈을 직접 호출하는 차량 정보 조회 서비스 구현체
|
||||
*
|
||||
* <p>이 구현체는 외부 REST API 호출 없이 내부 VMIS 모듈을 직접 사용하여
|
||||
* 정부 시스템과 통신합니다. 네트워크 오버헤드가 없어 성능이 향상됩니다.</p>
|
||||
*
|
||||
* <h3>활성화 조건:</h3>
|
||||
* <pre>
|
||||
* # application.yml
|
||||
* vmis:
|
||||
* integration:
|
||||
* mode: internal
|
||||
* </pre>
|
||||
*
|
||||
* <h3>처리 흐름:</h3>
|
||||
* <ol>
|
||||
* <li>차량번호를 받아 BasicRequest, LedgerRequest 생성</li>
|
||||
* <li>VmisCarBassMatterInqireService.basic() 호출 (기본정보)</li>
|
||||
* <li>VmisCarLedgerFrmbkService.ledger() 호출 (등록원부)</li>
|
||||
* <li>BasicResponse, LedgerResponse를 직접 VehicleApiResponseVO에 설정</li>
|
||||
* <li>VehicleApiResponseVO로 결과 반환</li>
|
||||
* </ol>
|
||||
*
|
||||
* @see VehicleInfoService
|
||||
* @see VmisCarBassMatterInqireService
|
||||
* @see VmisCarLedgerFrmbkService
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@ConditionalOnProperty(name = "vmis.integration.mode", havingValue = "internal")
|
||||
public class InternalVehicleInfoServiceImpl extends EgovAbstractServiceImpl implements VehicleInfoService {
|
||||
|
||||
private final VmisCarBassMatterInqireService carBassMatterInqireService;
|
||||
private final VmisCarLedgerFrmbkService carLedgerFrmbkService;
|
||||
private final go.kr.project.carInspectionPenalty.history.service.VehicleApiHistoryService vehicleApiHistoryService;
|
||||
|
||||
|
||||
@Override
|
||||
public VehicleApiResponseVO getVehicleInfo(BasicRequest basicRequest) {
|
||||
String vehicleNumber = basicRequest.getVhrno();
|
||||
log.info("[Internal Mode] 차량 정보 조회 시작 - 차량번호: {}, 부과기준일: {}, 조회구분: {}",
|
||||
vehicleNumber, basicRequest.getLevyStdde(), basicRequest.getInqireSeCode());
|
||||
|
||||
VehicleApiResponseVO response = new VehicleApiResponseVO();
|
||||
response.setVhrno(vehicleNumber);
|
||||
|
||||
try {
|
||||
// 1. 차량 기본정보 조회
|
||||
// 중요 로직: BasicRequest 전체를 사용하여 조회 (RequestEnricher가 나머지 채움)
|
||||
BasicResponse basicInfo = getBasicInfo(basicRequest);
|
||||
response.setBasicInfo(basicInfo);
|
||||
|
||||
// 2. 자동차 등록원부 조회
|
||||
// 중요 로직: 통합 조회 시에는 차량번호와 기본정보를 바탕으로 LedgerRequest 생성 (RequestEnricher가 나머지 채움)
|
||||
LedgerRequest ledgerRequest = new LedgerRequest();
|
||||
ledgerRequest.setVhrno(vehicleNumber);
|
||||
ledgerRequest.setOnesInformationOpen("1"); //개인정보공개 {1:소유자공개, 2:비공개, 3:비공개(주민등록번호), 4:비공개(사용본거지)}
|
||||
|
||||
// basicInfo에서 민원인 정보 가져오기
|
||||
if (basicInfo != null && basicInfo.getRecord() != null && !basicInfo.getRecord().isEmpty()) {
|
||||
BasicResponse.Record record = basicInfo.getRecord().get(0);
|
||||
ledgerRequest.setCpttrNm(record.getMberNm()); // 민원인성명
|
||||
ledgerRequest.setCpttrIhidnum(record.getMberSeNo()); // 민원인주민번호
|
||||
}
|
||||
|
||||
// 고정값 설정
|
||||
ledgerRequest.setCpttrLegaldongCode(null); // 민원인법정동코드
|
||||
|
||||
LedgerResponse ledgerInfo = getLedgerInfo(ledgerRequest);
|
||||
response.setLedgerInfo(ledgerInfo);
|
||||
|
||||
// 3. 결과 검증
|
||||
if (basicInfo != null && ApiConstant.CNTC_RESULT_CODE_SUCCESS.equals(basicInfo.getCntcResultCode())) {
|
||||
response.setSuccess(true);
|
||||
response.setMessage("조회 성공");
|
||||
log.info("[Internal Mode] 차량번호 {} 조회 성공", vehicleNumber);
|
||||
|
||||
// 4. API 호출 성공 시 히스토리 ID 조회 및 설정
|
||||
try {
|
||||
String carBassMatterInqireId = vehicleApiHistoryService.selectLatestCarBassMatterInqireIdByVhclno(vehicleNumber);
|
||||
String carLedgerFrmbkId = vehicleApiHistoryService.selectLatestCarLedgerFrmbkIdByVhclno(vehicleNumber);
|
||||
response.setCarBassMatterInqireId(carBassMatterInqireId);
|
||||
response.setCarLedgerFrmbkId(carLedgerFrmbkId);
|
||||
log.debug("[Internal Mode] 히스토리 ID 설정 완료 - 차량번호: {}, 기본정보ID: {}, 원부ID: {}",
|
||||
vehicleNumber, carBassMatterInqireId, carLedgerFrmbkId);
|
||||
} catch (Exception e) {
|
||||
log.warn("[Internal Mode] 히스토리 ID 조회 실패 - 차량번호: {}", vehicleNumber, e);
|
||||
// ID 조회 실패는 치명적이지 않으므로 계속 진행
|
||||
}
|
||||
} else {
|
||||
response.setSuccess(false);
|
||||
response.setMessage(basicInfo != null ? basicInfo.getCntcResultDtls() : "조회 실패");
|
||||
log.warn("[Internal Mode] 차량번호 {} 조회 실패 - {}", vehicleNumber, response.getMessage());
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
response.setSuccess(false);
|
||||
response.setMessage("내부 API 호출 오류: " + e.getMessage());
|
||||
log.error("[Internal Mode] 차량번호 {} 내부 API 호출 중 오류 발생", vehicleNumber, e);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 차량 기본정보 조회 (내부 모듈 직접 호출)
|
||||
* 중요 로직: 기본정보 조회는 BasicRequest 전체를 받아서 내부 서비스에 전달
|
||||
*
|
||||
* @param request 기본정보 조회 요청 (차량번호, 부과기준일, 조회구분 등 포함)
|
||||
* @return 차량 기본정보 응답
|
||||
*/
|
||||
@Override
|
||||
public BasicResponse getBasicInfo(BasicRequest request) {
|
||||
log.debug("[Internal Mode] 차량 기본정보 조회 - 차량번호: {}", request.getVhrno());
|
||||
|
||||
// Envelope로 감싸기 (요청 객체는 이미 모든 필수 파라미터를 포함)
|
||||
Envelope<BasicRequest> requestEnvelope = new Envelope<BasicRequest>();
|
||||
requestEnvelope.setData(Collections.singletonList(request));
|
||||
|
||||
try {
|
||||
// 내부 서비스 호출
|
||||
ResponseEntity<Envelope<BasicResponse>> responseEntity =
|
||||
carBassMatterInqireService.basic(requestEnvelope);
|
||||
|
||||
if (responseEntity.getBody() != null &&
|
||||
responseEntity.getBody().getData() != null &&
|
||||
!responseEntity.getBody().getData().isEmpty()) {
|
||||
|
||||
return responseEntity.getBody().getData().get(0);
|
||||
}
|
||||
|
||||
log.warn("[Internal Mode] 차량 기본정보 조회 응답이 비어있음 - 차량번호: {}", request.getVhrno());
|
||||
return null;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("[Internal Mode] 차량 기본정보 조회 실패 - 차량번호: {}", request.getVhrno(), e);
|
||||
throw new RuntimeException("차량 기본정보 조회 실패: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 자동차 등록원부(갑) 조회 (내부 모듈 직접 호출)
|
||||
* 중요 로직: 등록원부 조회는 LedgerRequest 전체를 받아서 내부 서비스에 전달
|
||||
*
|
||||
* @param request 등록원부 조회 요청 (차량번호, 소유자정보, 조회구분 등 포함)
|
||||
* @return 등록원부 정보 응답
|
||||
*/
|
||||
@Override
|
||||
public LedgerResponse getLedgerInfo(LedgerRequest request) {
|
||||
log.debug("[Internal Mode] 자동차 등록원부 조회 - 차량번호: {}", request.getVhrno());
|
||||
|
||||
// Envelope로 감싸기 (요청 객체는 이미 모든 필수 파라미터를 포함)
|
||||
Envelope<LedgerRequest> requestEnvelope = new Envelope<LedgerRequest>();
|
||||
requestEnvelope.setData(Collections.singletonList(request));
|
||||
|
||||
try {
|
||||
// 내부 서비스 호출
|
||||
ResponseEntity<Envelope<LedgerResponse>> responseEntity =
|
||||
carLedgerFrmbkService.ledger(requestEnvelope);
|
||||
|
||||
if (responseEntity.getBody() != null &&
|
||||
responseEntity.getBody().getData() != null &&
|
||||
!responseEntity.getBody().getData().isEmpty()) {
|
||||
|
||||
return responseEntity.getBody().getData().get(0);
|
||||
}
|
||||
|
||||
log.warn("[Internal Mode] 자동차 등록원부 조회 응답이 비어있음 - 차량번호: {}", request.getVhrno());
|
||||
return null;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("[Internal Mode] 자동차 등록원부 조회 실패 - 차량번호: {}", request.getVhrno(), e);
|
||||
throw new RuntimeException("자동차 등록원부 조회 실패: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 성공한 응답 개수 계산
|
||||
*/
|
||||
private int countSuccessful(List<VehicleApiResponseVO> responses) {
|
||||
int count = 0;
|
||||
for (VehicleApiResponseVO response : responses) {
|
||||
if (response.isSuccess()) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
package go.kr.project.api.internal.service.impl;
|
||||
|
||||
import go.kr.project.api.config.ApiConstant;
|
||||
import go.kr.project.api.internal.client.GovernmentApi;
|
||||
import go.kr.project.api.internal.service.VmisCarBassMatterInqireService;
|
||||
import go.kr.project.api.internal.service.VmisRequestEnricher;
|
||||
import go.kr.project.api.internal.util.ExceptionDetailUtil;
|
||||
import go.kr.project.api.model.Envelope;
|
||||
import go.kr.project.api.model.request.BasicRequest;
|
||||
import go.kr.project.api.model.response.BasicResponse;
|
||||
import go.kr.project.api.model.response.VmisCarBassMatterInqireVO;
|
||||
import go.kr.project.api.service.VmisCarBassMatterInqireLogService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* 자동차 기본 사항 조회 서비스 구현체
|
||||
*
|
||||
* <p>API 호출 정보를 관리하는 서비스 클래스입니다.</p>
|
||||
* <ul>
|
||||
* <li>최초 요청: createInitialRequest() - 시퀀스로 ID 생성 후 INSERT</li>
|
||||
* <li>결과 업데이트: updateResponse() - 응답 데이터 UPDATE</li>
|
||||
* </ul>
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class VmisCarBassMatterInqireServiceImpl extends EgovAbstractServiceImpl implements VmisCarBassMatterInqireService {
|
||||
|
||||
private final GovernmentApi governmentApi;
|
||||
private final VmisRequestEnricher enricher;
|
||||
private final VmisCarBassMatterInqireLogService logService;
|
||||
|
||||
/**
|
||||
* 자동차 기본사항 조회: 보강 -> 최초요청로그 -> 외부호출 -> 응답로그.
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public ResponseEntity<Envelope<BasicResponse>> basic(Envelope<BasicRequest> envelope) {
|
||||
// 1) 요청 보강
|
||||
enricher.enrichBasic(envelope);
|
||||
|
||||
String generatedId = null;
|
||||
try {
|
||||
// 2) 최초 요청 로그 저장 (첫 번째 데이터 기준)
|
||||
if (envelope.getData() != null && !envelope.getData().isEmpty()) {
|
||||
BasicRequest req = envelope.getData().get(0);
|
||||
VmisCarBassMatterInqireVO logEntity = VmisCarBassMatterInqireVO.fromRequest(req);
|
||||
generatedId = logService.createInitialRequestNewTx(logEntity);
|
||||
}
|
||||
|
||||
// 3) 외부 API 호출
|
||||
ResponseEntity<Envelope<BasicResponse>> response = governmentApi.callBasic(envelope);
|
||||
|
||||
// 4) 응답 로그 업데이트
|
||||
// 원본 소스, 정상적인 호출, 리턴(에러 리턴포함) 일 경우에만 에러 로그 남김
|
||||
if (generatedId != null && response.getBody() != null) {
|
||||
VmisCarBassMatterInqireVO update = VmisCarBassMatterInqireVO.fromResponse(generatedId, response.getBody());
|
||||
if (update != null) {
|
||||
logService.updateResponseNewTx(update);
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
} catch (Exception e) {
|
||||
// 5) 오류 로그 업데이트
|
||||
if (generatedId != null) {
|
||||
try {
|
||||
String detail = ExceptionDetailUtil.buildForLog(e);
|
||||
VmisCarBassMatterInqireVO errorLog = VmisCarBassMatterInqireVO.builder()
|
||||
.carBassMatterInqireId(generatedId) // 자동차기본사항조회 ID (PK)
|
||||
.cntcResultCode(ApiConstant.CNTC_RESULT_CODE_ERROR) // 연계결과코드 (에러)
|
||||
.cntcResultDtls(detail) // 연계결과상세 (에러 메시지)
|
||||
.build();
|
||||
logService.updateResponseNewTx(errorLog);
|
||||
log.error("[BASIC-ERR-LOG] API 호출 에러 정보 저장 완료(별도TX) - ID: {}, detail: {}", generatedId, detail, e);
|
||||
} catch (Exception ignore) {
|
||||
log.error("[BASIC-ERR-LOG] 에러 로그 저장 실패 - ID: {}", generatedId, ignore);
|
||||
}
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
package go.kr.project.api.internal.service.impl;
|
||||
|
||||
import go.kr.project.api.config.ApiConstant;
|
||||
import go.kr.project.api.internal.client.GovernmentApi;
|
||||
import go.kr.project.api.internal.service.VmisCarLedgerFrmbkService;
|
||||
import go.kr.project.api.internal.service.VmisRequestEnricher;
|
||||
import go.kr.project.api.internal.util.ExceptionDetailUtil;
|
||||
import go.kr.project.api.model.Envelope;
|
||||
import go.kr.project.api.model.request.LedgerRequest;
|
||||
import go.kr.project.api.model.response.LedgerResponse;
|
||||
import go.kr.project.api.model.response.VmisCarLedgerFrmbkDtlVO;
|
||||
import go.kr.project.api.model.response.VmisCarLedgerFrmbkVO;
|
||||
import go.kr.project.api.service.VmisCarLedgerFrmbkLogService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 자동차 등록 원부(갑) 서비스 구현체 (오케스트레이션)
|
||||
* - 요청 보강, 외부 API 호출, 로그 서비스 위임
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class VmisCarLedgerFrmbkServiceImpl extends EgovAbstractServiceImpl implements VmisCarLedgerFrmbkService {
|
||||
|
||||
private final GovernmentApi governmentApi;
|
||||
private final VmisRequestEnricher enricher;
|
||||
private final VmisCarLedgerFrmbkLogService logService;
|
||||
|
||||
/**
|
||||
* 자동차 등록원부(갑) 조회: 보강 -> 최초요청로그(별도TX) -> 외부호출 -> 응답로그(마스터/상세, 별도TX) -> 오류 시 에러로그(별도TX).
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public ResponseEntity<Envelope<LedgerResponse>> ledger(Envelope<LedgerRequest> envelope) {
|
||||
// 1) 요청 보강
|
||||
enricher.enrichLedger(envelope);
|
||||
|
||||
String generatedId = null;
|
||||
try {
|
||||
// 2) 최초 요청 로그 저장 (첫 번째 데이터 기준)
|
||||
if (envelope.getData() != null && !envelope.getData().isEmpty()) {
|
||||
LedgerRequest req = envelope.getData().get(0);
|
||||
VmisCarLedgerFrmbkVO init = VmisCarLedgerFrmbkVO.fromRequest(req);
|
||||
generatedId = logService.createInitialRequestNewTx(init);
|
||||
}
|
||||
|
||||
// 3) 외부 API 호출
|
||||
ResponseEntity<Envelope<LedgerResponse>> response = governmentApi.callLedger(envelope);
|
||||
|
||||
// 4) 응답 로그 업데이트 (마스터 + 상세)
|
||||
if (generatedId != null && response.getBody() != null &&
|
||||
response.getBody().getData() != null && !response.getBody().getData().isEmpty()) {
|
||||
LedgerResponse body = response.getBody().getData().get(0);
|
||||
VmisCarLedgerFrmbkVO masterUpdate = VmisCarLedgerFrmbkVO.fromResponseMaster(generatedId, body);
|
||||
logService.updateResponseNewTx(masterUpdate);
|
||||
|
||||
List<VmisCarLedgerFrmbkDtlVO> details = VmisCarLedgerFrmbkDtlVO.listFromResponse(body, generatedId);
|
||||
if (details != null && !details.isEmpty()) {
|
||||
logService.saveDetailsNewTx(generatedId, details);
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
} catch (Exception e) {
|
||||
// 5) 오류 로그 업데이트
|
||||
if (generatedId != null) {
|
||||
try {
|
||||
String detail = ExceptionDetailUtil.buildForLog(e);
|
||||
VmisCarLedgerFrmbkVO errorLog = VmisCarLedgerFrmbkVO.builder()
|
||||
.carLedgerFrmbkId(generatedId)
|
||||
.cntcResultCode(ApiConstant.CNTC_RESULT_CODE_ERROR)
|
||||
.cntcResultDtls(detail)
|
||||
.build();
|
||||
logService.updateResponseNewTx(errorLog);
|
||||
log.error("[LEDGER-ERR-LOG] API 호출 에러 정보 저장 완료(별도TX) - ID: {}, detail: {}", generatedId, detail, e);
|
||||
} catch (Exception ignore) {
|
||||
log.error("[LEDGER-ERR-LOG] 에러 로그 저장 실패 - ID: {}", generatedId, ignore);
|
||||
}
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package go.kr.project.api.util;
|
||||
package go.kr.project.api.internal.util;
|
||||
|
||||
/**
|
||||
* Common helper to extract root-cause message and truncate to DB column limit (default 4000 chars).
|
||||
@ -0,0 +1,98 @@
|
||||
package go.kr.project.api.internal.util;
|
||||
|
||||
import go.kr.project.api.config.properties.VmisProperties;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Wrapper utility around legacy {@link NewGpkiUtil} using configuration from YAML.
|
||||
*
|
||||
* Notes:
|
||||
* - Place this class under src/main/java/util as requested.
|
||||
* - Uses Lombok for getters/setters.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class GpkiCryptoUtil {
|
||||
|
||||
private String gpkiLicPath;
|
||||
private Boolean ldap; // null -> legacy default
|
||||
private String certFilePath;
|
||||
private String envCertFilePathName;
|
||||
private String envPrivateKeyFilePathName;
|
||||
private String envPrivateKeyPasswd;
|
||||
private String sigCertFilePathName;
|
||||
private String sigPrivateKeyFilePathName;
|
||||
private String sigPrivateKeyPasswd;
|
||||
private String myServerId; // equals to certServerId (INFO system server cert id)
|
||||
private String targetServerIdList; // comma joined list (can be single id)
|
||||
|
||||
private transient NewGpkiUtil delegate;
|
||||
|
||||
public static GpkiCryptoUtil from(VmisProperties.GpkiProps props) throws Exception {
|
||||
GpkiCryptoUtil util = new GpkiCryptoUtil();
|
||||
util.setGpkiLicPath(props.getGpkiLicPath());
|
||||
util.setLdap(props.getLdap());
|
||||
util.setCertFilePath(props.getCertFilePath());
|
||||
util.setEnvCertFilePathName(props.getEnvCertFilePathName());
|
||||
util.setEnvPrivateKeyFilePathName(props.getEnvPrivateKeyFilePathName());
|
||||
util.setEnvPrivateKeyPasswd(props.getEnvPrivateKeyPasswd());
|
||||
util.setSigCertFilePathName(props.getSigCertFilePathName());
|
||||
util.setSigPrivateKeyFilePathName(props.getSigPrivateKeyFilePathName());
|
||||
util.setSigPrivateKeyPasswd(props.getSigPrivateKeyPasswd());
|
||||
util.setMyServerId(props.getCertServerId());
|
||||
// Accept single targetServerId but allow list if provided by YAML in future
|
||||
util.setTargetServerIdList(props.getTargetServerId());
|
||||
util.initialize();
|
||||
return util;
|
||||
}
|
||||
|
||||
public void initialize() throws Exception {
|
||||
NewGpkiUtil g = new NewGpkiUtil();
|
||||
if (gpkiLicPath != null) g.setGpkiLicPath(gpkiLicPath);
|
||||
if (ldap != null) g.setIsLDAP(ldap);
|
||||
if (certFilePath != null) g.setCertFilePath(certFilePath);
|
||||
if (envCertFilePathName != null) g.setEnvCertFilePathName(envCertFilePathName);
|
||||
if (envPrivateKeyFilePathName != null) g.setEnvPrivateKeyFilePathName(envPrivateKeyFilePathName);
|
||||
if (envPrivateKeyPasswd != null) g.setEnvPrivateKeyPasswd(envPrivateKeyPasswd);
|
||||
if (sigCertFilePathName != null) g.setSigCertFilePathName(sigCertFilePathName);
|
||||
if (sigPrivateKeyFilePathName != null) g.setSigPrivateKeyFilePathName(sigPrivateKeyFilePathName);
|
||||
if (sigPrivateKeyPasswd != null) g.setSigPrivateKeyPasswd(sigPrivateKeyPasswd);
|
||||
if (myServerId != null) g.setMyServerId(myServerId);
|
||||
if (targetServerIdList != null) g.setTargetServerIdList(targetServerIdList);
|
||||
g.init();
|
||||
this.delegate = g;
|
||||
}
|
||||
|
||||
public String encryptToBase64(String plain, String targetServerId, String charset) throws Exception {
|
||||
ensureInit();
|
||||
byte[] enc = delegate.encrypt(plain.getBytes(charset), targetServerId, true);
|
||||
return delegate.encode(enc);
|
||||
}
|
||||
|
||||
public String decryptFromBase64(String base64, String charset) throws Exception {
|
||||
ensureInit();
|
||||
byte[] bin = delegate.decode(base64);
|
||||
byte[] dec = delegate.decrypt(bin);
|
||||
return new String(dec, charset);
|
||||
}
|
||||
|
||||
public String signToBase64(String plain, String charset) throws Exception {
|
||||
ensureInit();
|
||||
byte[] sig = delegate.sign(plain.getBytes(charset));
|
||||
return delegate.encode(sig);
|
||||
}
|
||||
|
||||
public String verifyAndExtractBase64(String signedBase64, String charset) throws Exception {
|
||||
ensureInit();
|
||||
byte[] signed = delegate.decode(signedBase64);
|
||||
byte[] data = delegate.validate(signed);
|
||||
return new String(data, charset);
|
||||
}
|
||||
|
||||
private void ensureInit() {
|
||||
if (delegate == null) {
|
||||
throw new IllegalStateException("GpkiCryptoUtil is not initialized. Call initialize() or from(props).");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,382 @@
|
||||
package go.kr.project.api.internal.util;
|
||||
|
||||
import com.gpki.gpkiapi.GpkiApi;
|
||||
import com.gpki.gpkiapi.cert.X509Certificate;
|
||||
import com.gpki.gpkiapi.crypto.PrivateKey;
|
||||
import com.gpki.gpkiapi.storage.Disk;
|
||||
import com.gpki.gpkiapi_jni;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
public class NewGpkiUtil {
|
||||
byte[] myEnvCert, myEnvKey, mySigCert, mySigKey;
|
||||
private Map<String, X509Certificate> targetServerCertMap = new HashMap<String, X509Certificate>();
|
||||
|
||||
// properties
|
||||
private String myServerId;
|
||||
private String targetServerIdList;
|
||||
private String envCertFilePathName;
|
||||
private String envPrivateKeyFilePathName;
|
||||
private String envPrivateKeyPasswd;
|
||||
private String sigCertFilePathName;
|
||||
private String sigPrivateKeyFilePathName;
|
||||
private String sigPrivateKeyPasswd;
|
||||
private String certFilePath;
|
||||
private String gpkiLicPath = ".";
|
||||
private boolean isLDAP;
|
||||
private boolean testGPKI = false;
|
||||
|
||||
|
||||
public void init() throws Exception {
|
||||
GpkiApi.init(gpkiLicPath);
|
||||
gpkiapi_jni gpki = this.getGPKI();
|
||||
if(log.isDebugEnabled()){
|
||||
if(gpki.API_GetInfo()==0)
|
||||
log.debug(gpki.sReturnString);
|
||||
else
|
||||
log.error(gpki.sDetailErrorString);
|
||||
}
|
||||
if(targetServerIdList!=null){
|
||||
String certIdList[] = targetServerIdList.split(",");
|
||||
for(int i = 0 ; i < certIdList.length ; i++){
|
||||
String certId = certIdList[i].trim();
|
||||
if(!certId.equals("")){
|
||||
load(gpki, certId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.info("Loading gpki certificate : myServerId="
|
||||
+ this.getMyServerId());
|
||||
|
||||
X509Certificate _myEnvCert = Disk.readCert(this
|
||||
.getEnvCertFilePathName());
|
||||
myEnvCert = _myEnvCert.getCert();
|
||||
|
||||
PrivateKey _myEnvKey = Disk.readPriKey(this
|
||||
.getEnvPrivateKeyFilePathName(), this.getEnvPrivateKeyPasswd());
|
||||
myEnvKey = _myEnvKey.getKey();
|
||||
|
||||
X509Certificate _mySigCert = Disk.readCert(this
|
||||
.getSigCertFilePathName());
|
||||
mySigCert = _mySigCert.getCert();
|
||||
|
||||
PrivateKey _mySigKey = Disk.readPriKey(this
|
||||
.getSigPrivateKeyFilePathName(), this.getSigPrivateKeyPasswd());
|
||||
mySigKey = _mySigKey.getKey();
|
||||
|
||||
//test my cert GPKI
|
||||
if(testGPKI){
|
||||
load(gpki, this.getMyServerId());
|
||||
testGpki(gpki);
|
||||
}
|
||||
this.finish(gpki);
|
||||
log.info("GpkiUtil initialized");
|
||||
}
|
||||
|
||||
private void load(gpkiapi_jni gpki, String certId) throws Exception {
|
||||
|
||||
log.debug("Loading gpki certificate : targetServerId="+ certId);
|
||||
|
||||
X509Certificate cert = targetServerCertMap.get(certId);
|
||||
if (cert != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isLDAP) {
|
||||
// String ldapUrl = "ldap://10.1.7.140:389/cn=";
|
||||
// String ldapUrl = "ldap://ldap.gcc.go.kr:389/cn=";
|
||||
String ldapUrl = "ldap://10.1.7.118:389/cn="; // 행정망인 경우
|
||||
// String ldapUrl = "ldap://152.99.57.127:389/cn="; // 인터넷망인 경우
|
||||
String ldapUri;
|
||||
if (certId.charAt(3) > '9') {
|
||||
ldapUri = ",ou=Group of Server,o=Public of Korea,c=KR";
|
||||
} else {
|
||||
ldapUri = ",ou=Group of Server,o=Government of Korea,c=KR";
|
||||
}
|
||||
|
||||
int ret = gpki.LDAP_GetAnyDataByURL("userCertificate;binary", ldapUrl + certId + ldapUri);
|
||||
this.checkResult(ret, gpki);
|
||||
cert = new X509Certificate(gpki.baReturnArray);
|
||||
} else {
|
||||
if(certFilePath != null){
|
||||
cert = Disk.readCert(certFilePath + File.separator + certId + ".cer");
|
||||
}else{
|
||||
log.debug("not certFilePath");
|
||||
}
|
||||
}
|
||||
|
||||
targetServerCertMap.put(certId, cert);
|
||||
}
|
||||
|
||||
private gpkiapi_jni getGPKI(){
|
||||
gpkiapi_jni gpki = new gpkiapi_jni();
|
||||
if(gpki.API_Init(gpkiLicPath) != 0){
|
||||
log.error(gpki.sDetailErrorString);
|
||||
}
|
||||
return gpki;
|
||||
}
|
||||
private void finish(gpkiapi_jni gpki){
|
||||
if(gpki.API_Finish() != 0){
|
||||
log.error(gpki.sDetailErrorString);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] encrypt(byte[] plain, String certId , boolean load) throws Exception {
|
||||
X509Certificate targetEnvCert = targetServerCertMap.get(certId);
|
||||
if (targetEnvCert == null) {
|
||||
throw new Exception("Certificate not found : targetServerId=" + certId);
|
||||
}
|
||||
|
||||
gpkiapi_jni gpki = this.getGPKI();
|
||||
try{
|
||||
int result = gpki.CMS_MakeEnvelopedData(targetEnvCert.getCert(), plain,
|
||||
gpkiapi_jni.SYM_ALG_NEAT_CBC);
|
||||
checkResult(result, "Fail to encrypt message", gpki);
|
||||
|
||||
return gpki.baReturnArray;
|
||||
}catch(Exception ex){
|
||||
throw ex;
|
||||
}finally{
|
||||
finish(gpki);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] encrypt(byte[] plain, String certId) throws Exception {
|
||||
return encrypt(plain,certId , false);
|
||||
}
|
||||
|
||||
public byte[] decrypt(byte[] encrypted) throws Exception {
|
||||
|
||||
gpkiapi_jni gpki = this.getGPKI();
|
||||
try{
|
||||
int result = gpki.CMS_ProcessEnvelopedData(myEnvCert, myEnvKey,
|
||||
encrypted);
|
||||
checkResult(result, "Fail to decrpyt message", gpki);
|
||||
|
||||
return gpki.baReturnArray;
|
||||
}catch(Exception ex){
|
||||
throw ex;
|
||||
}finally{
|
||||
finish(gpki);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] sign(byte[] plain) throws Exception {
|
||||
|
||||
gpkiapi_jni gpki = this.getGPKI();
|
||||
try{
|
||||
int result = gpki.CMS_MakeSignedData(mySigCert, mySigKey, plain, null);
|
||||
checkResult(result, "Fail to sign message", gpki);
|
||||
|
||||
return gpki.baReturnArray;
|
||||
}catch(Exception ex){
|
||||
throw ex;
|
||||
}finally{
|
||||
finish(gpki);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] validate(byte[] signed) throws Exception {
|
||||
|
||||
gpkiapi_jni gpki = this.getGPKI();
|
||||
try{
|
||||
int result = gpki.CMS_ProcessSignedData(signed);
|
||||
checkResult(result, "Fail to validate signed message", gpki);
|
||||
return gpki.baData;
|
||||
}catch(Exception ex){
|
||||
throw ex;
|
||||
}finally{
|
||||
finish(gpki);
|
||||
}
|
||||
}
|
||||
|
||||
public String encode(byte[] plain) throws Exception {
|
||||
|
||||
gpkiapi_jni gpki = this.getGPKI();
|
||||
try{
|
||||
int result = gpki.BASE64_Encode(plain);
|
||||
checkResult(result, "Fail to encode message", gpki);
|
||||
|
||||
return gpki.sReturnString;
|
||||
}catch(Exception ex){
|
||||
throw ex;
|
||||
}finally{
|
||||
finish(gpki);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public byte[] decode(String base64) throws Exception {
|
||||
|
||||
gpkiapi_jni gpki = this.getGPKI();
|
||||
try{
|
||||
int result = gpki.BASE64_Decode(base64);
|
||||
checkResult(result, "Fail to decode base64 message", gpki);
|
||||
|
||||
return gpki.baReturnArray;
|
||||
}catch(Exception ex){
|
||||
throw ex;
|
||||
}finally{
|
||||
finish(gpki);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkResult(int result, gpkiapi_jni gpki)throws Exception{
|
||||
this.checkResult(result, null, gpki);
|
||||
}
|
||||
|
||||
private void checkResult(int result ,String message, gpkiapi_jni gpki)throws Exception{
|
||||
if( 0 != result){
|
||||
if(null != gpki){
|
||||
throw new Exception(message + " : gpkiErrorMessage=" + gpki.sDetailErrorString);
|
||||
}else{
|
||||
throw new Exception(message + " : gpkiErrorCode=" + result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testGpki(gpkiapi_jni gpki) throws Exception{
|
||||
//gpki test eng
|
||||
log.info("=======================================================");
|
||||
log.info("================ TEST GPKI START ======================");
|
||||
log.info("=======================================================");
|
||||
String original_Eng = "abc";
|
||||
log.info("=== TEST ENG STRING: "+ original_Eng);
|
||||
try {
|
||||
byte[] encrypted = encrypt(original_Eng.getBytes(), myServerId);
|
||||
log.info("=== TEST ENG ENCRYPT STRING: "+ encode(encrypted));
|
||||
String decrypted = new String(decrypt(encrypted));
|
||||
log.info("=== TEST ENG DECRYPT STRING: "+decrypted);
|
||||
|
||||
if (!original_Eng.equals(decrypted)) {
|
||||
throw new Exception("GpkiUtil not initialized properly(english)");
|
||||
}
|
||||
log.info("=== TEST ENG: OK");
|
||||
} catch (Exception e) {
|
||||
log.warn("Gpki Test error(english)", e);
|
||||
throw e;
|
||||
}
|
||||
//gpki test kor
|
||||
String original = "한글테스트";
|
||||
log.info("=== TEST KOR STRING: "+ original);
|
||||
try {
|
||||
byte[] encrypted = encrypt(original.getBytes(), myServerId);
|
||||
log.info("=== TEST KOR ENCRYPT STRING: "+ encode(encrypted));
|
||||
String decrypted = new String(decrypt(encrypted));
|
||||
log.info("=== TEST KOR DECRYPT STRING: "+decrypted);
|
||||
if (!original.equals(decrypted)) {
|
||||
throw new Exception("GpkiUtil not initialized properly(korean)");
|
||||
}
|
||||
log.info("=== TEST KOR: OK");
|
||||
} catch (Exception e) {
|
||||
log.warn("Gpki Test error(korean)", e);
|
||||
throw e;
|
||||
}finally{
|
||||
log.info("=======================================================");
|
||||
log.info("================ TEST GPKI END ========================");
|
||||
log.info("=======================================================");
|
||||
}
|
||||
}
|
||||
|
||||
public String getMyServerId() {
|
||||
return myServerId;
|
||||
}
|
||||
|
||||
public void setMyServerId(String myServerId) {
|
||||
this.myServerId = myServerId.trim();
|
||||
}
|
||||
|
||||
public String getEnvCertFilePathName() {
|
||||
return envCertFilePathName;
|
||||
}
|
||||
|
||||
public void setEnvCertFilePathName(String envCertFilePathName) {
|
||||
this.envCertFilePathName = envCertFilePathName.trim();
|
||||
}
|
||||
|
||||
public String getEnvPrivateKeyFilePathName() {
|
||||
return envPrivateKeyFilePathName;
|
||||
}
|
||||
|
||||
public void setEnvPrivateKeyFilePathName(String envPrivateKeyFilePathName) {
|
||||
this.envPrivateKeyFilePathName = envPrivateKeyFilePathName.trim();
|
||||
}
|
||||
|
||||
public String getEnvPrivateKeyPasswd() {
|
||||
return envPrivateKeyPasswd;
|
||||
}
|
||||
|
||||
public void setEnvPrivateKeyPasswd(String envPrivateKeyPasswd) {
|
||||
this.envPrivateKeyPasswd = envPrivateKeyPasswd.trim();
|
||||
}
|
||||
|
||||
public String getSigPrivateKeyPasswd() {
|
||||
return sigPrivateKeyPasswd;
|
||||
}
|
||||
|
||||
public void setSigPrivateKeyPasswd(String sigPrivateKeyPasswd) {
|
||||
this.sigPrivateKeyPasswd = sigPrivateKeyPasswd.trim();
|
||||
}
|
||||
|
||||
public String getSigCertFilePathName() {
|
||||
return sigCertFilePathName;
|
||||
}
|
||||
|
||||
public void setSigCertFilePathName(String sigCertFilePathName) {
|
||||
this.sigCertFilePathName = sigCertFilePathName.trim();
|
||||
}
|
||||
|
||||
public String getSigPrivateKeyFilePathName() {
|
||||
return sigPrivateKeyFilePathName;
|
||||
}
|
||||
|
||||
public void setSigPrivateKeyFilePathName(String sigPrivateKeyFilePathName) {
|
||||
this.sigPrivateKeyFilePathName = sigPrivateKeyFilePathName.trim();
|
||||
}
|
||||
|
||||
public boolean getIsLDAP() {
|
||||
return isLDAP;
|
||||
}
|
||||
|
||||
public void setIsLDAP(boolean isLDAP) {
|
||||
this.isLDAP = isLDAP;
|
||||
}
|
||||
|
||||
public String getCertFilePath() {
|
||||
return certFilePath;
|
||||
}
|
||||
|
||||
public void setCertFilePath(String certFilePath) {
|
||||
this.certFilePath = certFilePath.trim();
|
||||
}
|
||||
|
||||
public String getTargetServerIdList() {
|
||||
return targetServerIdList;
|
||||
}
|
||||
|
||||
public void setTargetServerIdList(String targetServerIdList) {
|
||||
this.targetServerIdList = targetServerIdList;
|
||||
}
|
||||
|
||||
public String getGpkiLicPath() {
|
||||
return gpkiLicPath;
|
||||
}
|
||||
|
||||
public void setGpkiLicPath(String gpkiLicPath) {
|
||||
this.gpkiLicPath = gpkiLicPath;
|
||||
}
|
||||
|
||||
public boolean getTestGPKI() {
|
||||
return testGPKI;
|
||||
}
|
||||
|
||||
public void setTestGPKI(boolean testGPKI) {
|
||||
this.testGPKI = testGPKI;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package go.kr.project.api.internal.util;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.Random;
|
||||
|
||||
public final class TxIdUtil {
|
||||
private static final Random RANDOM = new Random();
|
||||
|
||||
private TxIdUtil() {}
|
||||
|
||||
public static String generate() {
|
||||
String time = new SimpleDateFormat("yyyyMMddHHmmssSSS", Locale.KOREA).format(new Date());
|
||||
int random = 100000 + RANDOM.nextInt(900000);
|
||||
return time + "_" + random;
|
||||
}
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
package go.kr.project.api.mapper;
|
||||
|
||||
import go.kr.project.api.model.CarLedgerFrmbkDtlVO;
|
||||
import go.kr.project.api.model.CarLedgerFrmbkVO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 자동차 등록 원부(갑) Mapper
|
||||
*/
|
||||
@Mapper
|
||||
public interface VmisCarLedgerFrmbkMapper {
|
||||
|
||||
// ID 시퀀스
|
||||
String selectNextCarLedgerFrmbkId();
|
||||
String selectNextCarLedgerFrmbkDtlId();
|
||||
|
||||
// 마스터 INSERT/UPDATE/SELECT
|
||||
int insertCarLedgerFrmbk(CarLedgerFrmbkVO vo);
|
||||
int updateCarLedgerFrmbk(CarLedgerFrmbkVO vo);
|
||||
CarLedgerFrmbkVO selectCarLedgerFrmbkById(String carLedgerFrmbkId);
|
||||
|
||||
// 상세 INSERT (단건)
|
||||
int insertCarLedgerFrmbkDtl(CarLedgerFrmbkDtlVO vo);
|
||||
|
||||
// 편의: 상세 일괄 (MyBatis foreach를 XML에서 사용할 수도 있으나, 여기서는 단건 호출을 반복)
|
||||
|
||||
/**
|
||||
* txId로 CAR_FFNLG_TRGT_ID를 업데이트합니다. (지연/미필 공통)
|
||||
*
|
||||
* @param txId 트랜잭션 ID
|
||||
* @param carFfnlgTrgtId 과태료 대상 ID (지연 또는 미필)
|
||||
* @return 업데이트된 행 수
|
||||
*/
|
||||
int updateCarFfnlgTrgtIdByTxId(String txId, String carFfnlgTrgtId);
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
package go.kr.project.api.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* 외부 VMIS-interface 신규 응답 래퍼
|
||||
* { "txId": "yyyyMMddHHmmssSSS12345678", "request": {"data": [...]}, "response": {"data": [...]} }
|
||||
*
|
||||
* 중요로직: 외부호출 프로젝트에서 요청/응답을 함께 반환하므로 해당 구조를 그대로 매핑한다.
|
||||
*/
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@Getter
|
||||
@Setter
|
||||
public class ApiExchangeEnvelope<TReq, TRes> {
|
||||
|
||||
/** 트랜잭션 ID */
|
||||
@JsonProperty("txId")
|
||||
private String txId;
|
||||
|
||||
/** 요청 데이터 래퍼 */
|
||||
@JsonProperty("request")
|
||||
private Envelope<TReq> request;
|
||||
|
||||
/** 응답 데이터 래퍼 */
|
||||
@JsonProperty("response")
|
||||
private Envelope<TRes> response;
|
||||
}
|
||||
@ -1,861 +0,0 @@
|
||||
package go.kr.project.api.model;
|
||||
|
||||
import go.kr.project.api.model.request.NewBasicRequest;
|
||||
import go.kr.project.api.model.request.OldBasicRequest;
|
||||
import go.kr.project.api.model.response.NewBasicResponse;
|
||||
import go.kr.project.api.model.response.OldBasicResponse;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 자동차 기본 사항 조회 엔티티, DB 저장용
|
||||
*
|
||||
* <p>API 호출 정보를 저장하는 테이블 매핑 클래스입니다.
|
||||
* 최초 요청 시 INSERT, 결과 수신 시 UPDATE 형태로 사용됩니다.</p>
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class CarBassMatterInqireVO {
|
||||
/**
|
||||
* 자동차 기본 사항 조회 ID (PK)
|
||||
* 형식: CBMI000000000001
|
||||
*/
|
||||
private String carBassMatterInqireId;
|
||||
|
||||
// 신규 응답용 txId
|
||||
private String txId;
|
||||
|
||||
// ===== 요청 정보 =====
|
||||
/**
|
||||
* 정보 시스템 ID
|
||||
*/
|
||||
private String infoSysId;
|
||||
|
||||
/**
|
||||
* 정보 시스템 IP
|
||||
*/
|
||||
private String infoSysIpAddr;
|
||||
|
||||
/**
|
||||
* 시군구 코드
|
||||
*/
|
||||
private String sggCd;
|
||||
|
||||
/**
|
||||
* 연계 정보 코드
|
||||
*/
|
||||
private String linkInfoCd;
|
||||
|
||||
/**
|
||||
* 담당자 ID
|
||||
*/
|
||||
private String picId;
|
||||
|
||||
/**
|
||||
* 담당자 IP
|
||||
*/
|
||||
private String picIpAddr;
|
||||
|
||||
/**
|
||||
* 담당자명
|
||||
*/
|
||||
private String picNm;
|
||||
|
||||
/**
|
||||
* 요청 부과 기준일
|
||||
*/
|
||||
private String dmndLevyCrtrYmd;
|
||||
|
||||
/**
|
||||
* 요청 조회 구분 코드
|
||||
*/
|
||||
private String dmndInqSeCd;
|
||||
|
||||
/**
|
||||
* 요청 자동차등록번호
|
||||
*/
|
||||
private String dmndVhrno;
|
||||
|
||||
/**
|
||||
* 요청 차대번호
|
||||
*/
|
||||
private String dmndVin;
|
||||
|
||||
// ===== 응답 정보 (결과 수신 시 UPDATE) =====
|
||||
/**
|
||||
* 연계 결과 코드 - LINK_RSLT_CD
|
||||
*/
|
||||
private String linkRsltCd;
|
||||
|
||||
/**
|
||||
* 연계 결과 상세 - LINK_RSLT_DTL
|
||||
*/
|
||||
private String linkRsltDtl;
|
||||
|
||||
/**
|
||||
* 연식 - YRIDNW
|
||||
*/
|
||||
private String yridnw;
|
||||
|
||||
/**
|
||||
* 등록일 - REG_YMD
|
||||
*/
|
||||
private String regYmd;
|
||||
|
||||
/**
|
||||
* 말소 등록 구분 코드 - ERSR_REG_SE_CD
|
||||
*/
|
||||
private String ersrRegSeCd;
|
||||
|
||||
/**
|
||||
* 말소 등록 구분명 - ERSR_REG_SE_NM
|
||||
*/
|
||||
private String ersrRegSeNm;
|
||||
|
||||
/**
|
||||
* 말소 등록일 - ERSR_REG_YMD
|
||||
*/
|
||||
private String ersrRegYmd;
|
||||
|
||||
/**
|
||||
* 등록 상세 코드 - REG_DTL_CD
|
||||
*/
|
||||
private String regDtlCd;
|
||||
|
||||
/**
|
||||
* 배기량 - DSPLVL
|
||||
*/
|
||||
private String dsplvl;
|
||||
|
||||
/**
|
||||
* 사용 본거지 법정동 코드 - USGSRHLD_STDG_CD
|
||||
*/
|
||||
private String usgsrhldStdgCd;
|
||||
|
||||
/**
|
||||
* 사용 본거지 행정동 코드 - USGSRHLD_DONG_CD
|
||||
*/
|
||||
private String usgsrhldDongCd;
|
||||
|
||||
/**
|
||||
* 사용 본거지 산 - USGSRHLD_MTN_YN
|
||||
*/
|
||||
private String usgsrhldMtnYn;
|
||||
|
||||
/**
|
||||
* 사용 본거지 번지 - USGSRHLD_LNBR
|
||||
*/
|
||||
private String usgsrhldLnbr;
|
||||
|
||||
/**
|
||||
* 사용 본거지 호 - USGSRHLD_HO
|
||||
*/
|
||||
private String usgsrhldHo;
|
||||
|
||||
/**
|
||||
* 사용 본거지 상세주소 - USGSRHLD_ADDR_NM
|
||||
*/
|
||||
private String usgsrhldAddrNm;
|
||||
|
||||
/**
|
||||
* 사용 본거지 도로명 코드 - USGSRHLD_ROAD_NM_CD
|
||||
*/
|
||||
private String usgsrhldRoadNmCd;
|
||||
|
||||
/**
|
||||
* 사용 본거지 지하 건물 구분 코드 - USGSRHLD_UDGD_BLDG_SE_CD
|
||||
*/
|
||||
private String usgsrhldUdgdBldgSeCd;
|
||||
|
||||
/**
|
||||
* 사용 본거지 건물 주요 번호 - USGSRHLD_BMNO
|
||||
*/
|
||||
private String usgsrhldBmno;
|
||||
|
||||
/**
|
||||
* 사용 본거지 건물 부 번호 - USGSRHLD_BSNO
|
||||
*/
|
||||
private String usgsrhldBsno;
|
||||
|
||||
/**
|
||||
* 사용 본거지 전체주소 - USGSRHLD_WHOL_ADDR
|
||||
*/
|
||||
private String usgsrhldWholAddr;
|
||||
|
||||
/**
|
||||
* 대표소유자 회원 구분 코드 - RPRS_OWNR_MBR_SE_CD
|
||||
*/
|
||||
private String rprsOwnrMbrSeCd;
|
||||
|
||||
/**
|
||||
* 대표소유자 회원 번호 - RPRSV_OWNR_IDECNO
|
||||
*/
|
||||
private String rprsvOwnrIdecno;
|
||||
|
||||
/**
|
||||
* 대표소유자 전화번호 - RPRS_OWNR_TELNO
|
||||
*/
|
||||
private String rprsOwnrTelno;
|
||||
|
||||
/**
|
||||
* 소유자 법정동 코드 - OWNR_STDG_CD
|
||||
*/
|
||||
private String ownrStdgCd;
|
||||
|
||||
/**
|
||||
* 소유자 행정동 코드 - OWNR_DONG_CD
|
||||
*/
|
||||
private String ownrDongCd;
|
||||
|
||||
/**
|
||||
* 소유자 산 - OWNR_MTN_YN
|
||||
*/
|
||||
private String ownrMtnYn;
|
||||
|
||||
/**
|
||||
* 소유자 번지 - OWNR_LNBR
|
||||
*/
|
||||
private String ownrLnbr;
|
||||
|
||||
/**
|
||||
* 소유자 호 - OWNR_HO
|
||||
*/
|
||||
private String ownrHo;
|
||||
|
||||
/**
|
||||
* 소유자 상세주소 - OWNR_ADDR_NM
|
||||
*/
|
||||
private String ownrAddrNm;
|
||||
|
||||
/**
|
||||
* 소유자 도로명 코드 - OWNR_ROAD_NM_CD
|
||||
*/
|
||||
private String ownrRoadNmCd;
|
||||
|
||||
/**
|
||||
* 소유자 지하건물 구분 코드 - OWNR_UDGD_BLDG_SE_CD
|
||||
*/
|
||||
private String ownrUdgdBldgSeCd;
|
||||
|
||||
/**
|
||||
* 소유자 건물 주요 번호 - OWNR_BMNO
|
||||
*/
|
||||
private String ownrBmno;
|
||||
|
||||
/**
|
||||
* 소유자 건물 부 번호 - OWNR_BSNO
|
||||
*/
|
||||
private String ownrBsno;
|
||||
|
||||
/**
|
||||
* 소유자 전체주소 - OWNR_WHOL_ADDR
|
||||
*/
|
||||
private String ownrWholaddr;
|
||||
|
||||
/**
|
||||
* 신 차량번호 - REAR_VHRNO
|
||||
*/
|
||||
private String rearVhrno;
|
||||
|
||||
/**
|
||||
* 사용 연료 코드 - USE_FUEL_CD
|
||||
*/
|
||||
private String useFuelCd;
|
||||
|
||||
/**
|
||||
* 용도 구분 코드 - USG_SE_CD
|
||||
*/
|
||||
private String usgSeCd;
|
||||
|
||||
/**
|
||||
* 원동기 형식명 - MTRS_FOM_NM
|
||||
*/
|
||||
private String mtrsFomNm;
|
||||
|
||||
/**
|
||||
* 이전 차량번호 - BFR_VHRNO
|
||||
*/
|
||||
private String bfrVhrno;
|
||||
|
||||
/**
|
||||
* 차량번호 - VHRNO
|
||||
*/
|
||||
private String vhrno;
|
||||
|
||||
/**
|
||||
* 차대번호 - VIN
|
||||
*/
|
||||
private String vin;
|
||||
|
||||
/**
|
||||
* 차명 - ATMB_NM
|
||||
*/
|
||||
private String atmbNm;
|
||||
|
||||
/**
|
||||
* 차량 총 중량 - VHCL_TOTL_WT
|
||||
*/
|
||||
private String vhclTotlWt;
|
||||
|
||||
/**
|
||||
* 차령 만료일자 - VEAG_END_YMD
|
||||
*/
|
||||
private String veagEndYmd;
|
||||
|
||||
/**
|
||||
* 차번호 변경시기 - CHG_YMD
|
||||
*/
|
||||
private String chgYmd;
|
||||
|
||||
/**
|
||||
* 차종 종별 코드 - CARMDL_ASORT_CD
|
||||
*/
|
||||
private String carmdlAsortCd;
|
||||
|
||||
/**
|
||||
* 차종 유형 코드 - CARMDL_TYPE_CD
|
||||
*/
|
||||
private String carmdlTypeCd;
|
||||
|
||||
/**
|
||||
* 차종 분류 코드 - CARMDL_SE_CD
|
||||
*/
|
||||
private String carmdlSeCd;
|
||||
|
||||
/**
|
||||
* 최대 적재량 - MXMM_LDG
|
||||
*/
|
||||
private String mxmmLdg;
|
||||
|
||||
/**
|
||||
* 차종 종별명 - CARMDL_ASORT_NM
|
||||
*/
|
||||
private String carmdlAsortNm;
|
||||
|
||||
/**
|
||||
* 차종 유형명 - CARMDL_TYPE_NM
|
||||
*/
|
||||
private String carmdlTypeNm;
|
||||
|
||||
/**
|
||||
* 차종 분류명 - CARMDL_CLSF_NM
|
||||
*/
|
||||
private String carmdlClsfNm;
|
||||
|
||||
/**
|
||||
* 최초 등록일 - FRST_REG_YMD
|
||||
*/
|
||||
private String frstRegYmd;
|
||||
|
||||
/**
|
||||
* 형식 - FOM_NM
|
||||
*/
|
||||
private String fomNm;
|
||||
|
||||
/**
|
||||
* 취득 일자 - ACQS_YMD
|
||||
*/
|
||||
private String acqsYmd;
|
||||
|
||||
/**
|
||||
* 취득 종료일자 - ACQS_END_YMD
|
||||
*/
|
||||
private String acqsEndYmd;
|
||||
|
||||
/**
|
||||
* 제작 년월일 - FBCTN_YMD
|
||||
*/
|
||||
private String fbctnYmd;
|
||||
|
||||
/**
|
||||
* 이전 등록일 - TRANSR_REG_YMD
|
||||
*/
|
||||
private String transrRegYmd;
|
||||
|
||||
/**
|
||||
* 제원 등록 상태 코드 - SPCF_REG_STTS_CD
|
||||
*/
|
||||
private String spcfRegSttsCd;
|
||||
|
||||
/**
|
||||
* 색상명 - COLOR_NM
|
||||
*/
|
||||
private String colorNm;
|
||||
|
||||
/**
|
||||
* 저당수 - MRTG_CNT
|
||||
*/
|
||||
private String mrtgCnt;
|
||||
|
||||
/**
|
||||
* 압류건수 - SZR_CNT
|
||||
*/
|
||||
private String szrCnt;
|
||||
|
||||
/**
|
||||
* 구조변경수 - STRCT_CHG_CNT
|
||||
*/
|
||||
private String strctChgCnt;
|
||||
|
||||
/**
|
||||
* 번호판 영치 여부 - NOPLT_CSDY_YN
|
||||
*/
|
||||
private String nopltCsdyYn;
|
||||
|
||||
/**
|
||||
* 번호판 영치 최고일 - NOPLT_CSDY_AVTSMT_YMD
|
||||
*/
|
||||
private String nopltCsdyAvtsmtYmd;
|
||||
|
||||
/**
|
||||
* 출처 구분 코드 - SRC_SE_CD
|
||||
*/
|
||||
private String srcSeCd;
|
||||
|
||||
/**
|
||||
* 번호판 규격 코드 - NOPLT_SPCFCT_CD
|
||||
*/
|
||||
private String nopltSpcfctCd;
|
||||
|
||||
/**
|
||||
* 취득 금액 - ACQS_AMT
|
||||
*/
|
||||
private String acqsAmt;
|
||||
|
||||
/**
|
||||
* 검사 유효 기간 시작일 - INSP_VLD_PD_BGNG_YMD
|
||||
*/
|
||||
private String inspVldPdBgngYmd;
|
||||
|
||||
/**
|
||||
* 검사 유효 기간 종료일 - INSP_VLD_PD_END_YMD
|
||||
*/
|
||||
private String inspVldPdEndYmd;
|
||||
|
||||
/**
|
||||
* 사용 본거지 관청 코드 - USGSRHLD_GRC_CD
|
||||
*/
|
||||
private String usgsrhldGrcCd;
|
||||
|
||||
/**
|
||||
* 승차정원수 - RDCPCT_CNT
|
||||
*/
|
||||
private String rdcpctCnt;
|
||||
|
||||
/**
|
||||
* 제원관리번호 - SPMNNO
|
||||
*/
|
||||
private String spmnno;
|
||||
|
||||
/**
|
||||
* 주행거리 - DRVNG_DSTNC
|
||||
*/
|
||||
private String drvngDstnc;
|
||||
|
||||
/**
|
||||
* 최초 등록 접수번호 - FRST_REG_APLY_RCPT_NO
|
||||
*/
|
||||
private String frstRegAplyRcptNo;
|
||||
|
||||
/**
|
||||
* 예고통지일 - VLNT_ERSR_PRVNTC_AVTSMT_YMD
|
||||
*/
|
||||
private String vlntErsrPrvntcAvtsmtYmd;
|
||||
|
||||
/**
|
||||
* 등록 기관명 - OGNZ_NM
|
||||
*/
|
||||
private String ognzNm;
|
||||
|
||||
/**
|
||||
* 처리 불가 사유 코드 - PRCS_IMPRTY_RSN_CD
|
||||
*/
|
||||
private String prcsImprtyRsnCd;
|
||||
|
||||
/**
|
||||
* 처리 불가 사유 명세 - PRCS_IMPRTY_RSN_DTLS
|
||||
*/
|
||||
private String prcsImprtyRsnDtls;
|
||||
|
||||
/**
|
||||
* 차체 길이 - CBD_LT
|
||||
*/
|
||||
private String cbdLt;
|
||||
|
||||
/**
|
||||
* 차체 너비 - CBD_BT
|
||||
*/
|
||||
private String cbdBt;
|
||||
|
||||
/**
|
||||
* 차체 높이 - CBD_HG
|
||||
*/
|
||||
private String cbdHg;
|
||||
|
||||
/**
|
||||
* 최초 최대 적재량 - FRST_MXMM_LDG
|
||||
*/
|
||||
private String frstMxmmLdg;
|
||||
|
||||
/**
|
||||
* 연료 소비율 - FUEL_CNSMPRT
|
||||
*/
|
||||
private String fuelCnsmprt;
|
||||
|
||||
/**
|
||||
* 전기 복합 연료 소비율 - ELCTY_CMPND_FUEL_CNSMPRT
|
||||
*/
|
||||
private String elctyCmpndFuelCnsmprt;
|
||||
|
||||
/**
|
||||
* 자동차 과태료 대상 ID - CAR_FFNLG_TRGT_ID
|
||||
*/
|
||||
private String carFfnlgTrgtId;
|
||||
|
||||
/**
|
||||
* 등록 일시 - REG_DT
|
||||
*/
|
||||
private LocalDateTime regDt;
|
||||
|
||||
/**
|
||||
* 등록자 - RGTR
|
||||
*/
|
||||
private String rgtr;
|
||||
|
||||
/**
|
||||
* 대표소유자 성명 - RPRS_OWNR_NM
|
||||
*/
|
||||
private String rprsOwnrNm;
|
||||
|
||||
/**
|
||||
* OldBasicRequest에서 VO로 변환 (최초 요청 로그 저장용)
|
||||
*
|
||||
* @param request OldBasicRequest 요청 객체
|
||||
* @return 초기 요청 정보가 담긴 VO
|
||||
*/
|
||||
public static CarBassMatterInqireVO fromOldRequest(OldBasicRequest request) {
|
||||
if (request == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// record 배열에서 첫 번째 요청 데이터 추출
|
||||
OldBasicRequest.Record record = null;
|
||||
if (request.getRecord() != null && !request.getRecord().isEmpty()) {
|
||||
record = request.getRecord().get(0);
|
||||
}
|
||||
|
||||
CarBassMatterInqireVO.CarBassMatterInqireVOBuilder builder = CarBassMatterInqireVO.builder()
|
||||
// 헤더 정보 (request 외부 클래스에서)
|
||||
.infoSysId(request.getInfoSysId()) // INFO_SYS_ID → infoSysId
|
||||
.infoSysIpAddr(request.getInfoSysIp()) // INFO_SYS_IP → infoSysIpAddr
|
||||
.sggCd(request.getSigunguCode()) // SIGUNGU_CODE → sggCd
|
||||
.linkInfoCd(request.getCntcInfoCode()) // CNTC_INFO_CODE → linkInfoCd
|
||||
.picId(request.getChargerId()) // CHARGER_ID → picId
|
||||
.picIpAddr(request.getChargerIp()) // CHARGER_IP → picIpAddr
|
||||
.picNm(request.getChargerNm()); // CHARGER_NM → picNm
|
||||
|
||||
// 요청 본문 정보 (request.record[0]에서)
|
||||
if (record != null) {
|
||||
builder
|
||||
.dmndLevyCrtrYmd(record.getLevyStdde()) // LEVY_STDDE → dmndLevyCrtrYmd
|
||||
.dmndInqSeCd(record.getInqireSeCode()) // INQIRE_SE_CODE → dmndInqSeCd
|
||||
.dmndVhrno(record.getVhrno()) // VHRNO → dmndVhrno
|
||||
.dmndVin(record.getVin()); // VIN → dmndVin
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* ApiExchangeEnvelope<OldBasicRequest, OldBasicResponse>에서 VO로 변환 (응답 업데이트용)
|
||||
*
|
||||
* @param generatedId 생성된 PK ID
|
||||
* @param envelope API 응답 Envelope
|
||||
* @return 응답 정보가 담긴 VO
|
||||
*/
|
||||
public static CarBassMatterInqireVO fromOldExchange(
|
||||
String generatedId,
|
||||
ApiExchangeEnvelope<OldBasicRequest, OldBasicResponse> envelope) {
|
||||
|
||||
if (envelope == null || envelope.getResponse() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Envelope<OldBasicResponse> response = envelope.getResponse();
|
||||
List<OldBasicResponse> data = response.getData();
|
||||
|
||||
if (data == null || data.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
OldBasicResponse firstData = data.get(0);
|
||||
List<OldBasicResponse.Record> records = firstData.getRecord();
|
||||
|
||||
// 응답 정보 업데이트용 VO 빌드
|
||||
CarBassMatterInqireVO.CarBassMatterInqireVOBuilder builder = CarBassMatterInqireVO.builder()
|
||||
.carBassMatterInqireId(generatedId)
|
||||
.txId(envelope.getTxId())
|
||||
.linkRsltCd(firstData.getCntcResultCode())
|
||||
.linkRsltDtl(firstData.getCntcResultDtls());
|
||||
|
||||
// record가 있는 경우 첫 번째 record의 상세 정보 매핑
|
||||
if (records != null && !records.isEmpty()) {
|
||||
OldBasicResponse.Record record = records.get(0);
|
||||
|
||||
builder
|
||||
.yridnw(record.getPrye())
|
||||
.regYmd(record.getRegistDe())
|
||||
.ersrRegSeCd(record.getErsrRegistSeCode())
|
||||
.ersrRegSeNm(record.getErsrRegistSeNm())
|
||||
.ersrRegYmd(record.getErsrRegistDe())
|
||||
.regDtlCd(record.getRegistDetailCode())
|
||||
.dsplvl(record.getDsplvl())
|
||||
.usgsrhldStdgCd(record.getUseStrnghldLegaldongCode())
|
||||
.usgsrhldDongCd(record.getUseStrnghldAdstrdCode())
|
||||
.usgsrhldMtnYn(record.getUseStrnghldMntn())
|
||||
.usgsrhldLnbr(record.getUseStrnghldLnbr())
|
||||
.usgsrhldHo(record.getUseStrnghldHo())
|
||||
.usgsrhldAddrNm(record.getUseStrnghldAdresNm())
|
||||
.usgsrhldRoadNmCd(record.getUseStrnghldRoadNmCode())
|
||||
.usgsrhldUdgdBldgSeCd(record.getUsgsrhldUndgrndBuldSeCode())
|
||||
.usgsrhldBmno(record.getUseStrnghldBuldMainNo())
|
||||
.usgsrhldBsno(record.getUseStrnghldBuldSubNo())
|
||||
.usgsrhldWholAddr(record.getUsgsrhldAdresFull())
|
||||
.rprsOwnrMbrSeCd(record.getMberSeCode())
|
||||
.rprsOwnrNm(record.getMberNm())
|
||||
.rprsvOwnrIdecno(record.getMberSeNo())
|
||||
.rprsOwnrTelno(record.getTelno())
|
||||
.ownrStdgCd(record.getOwnerLegaldongCode())
|
||||
.ownrDongCd(record.getOwnerAdstrdCode())
|
||||
.ownrMtnYn(record.getOwnerMntn())
|
||||
.ownrLnbr(record.getOwnerLnbr())
|
||||
.ownrHo(record.getOwnerHo())
|
||||
.ownrAddrNm(record.getOwnerAdresNm())
|
||||
.ownrRoadNmCd(record.getOwnerRoadNmCode())
|
||||
.ownrUdgdBldgSeCd(record.getOwnerUndgrndBuldSeCode())
|
||||
.ownrBmno(record.getOwnerBuldMainNo())
|
||||
.ownrBsno(record.getOwnerBuldSubNo())
|
||||
.ownrWholaddr(record.getOwnerAdresFull())
|
||||
.rearVhrno(record.getAftrVhrno())
|
||||
.useFuelCd(record.getUseFuelCode())
|
||||
.usgSeCd(record.getPrposSeCode())
|
||||
.mtrsFomNm(record.getMtrsFomNm())
|
||||
.bfrVhrno(record.getFrntVhrno())
|
||||
.vhrno(record.getVhrno())
|
||||
.vin(record.getVin())
|
||||
.atmbNm(record.getCnm())
|
||||
.vhclTotlWt(record.getVhcleTotWt())
|
||||
.veagEndYmd(record.getCaagEndde())
|
||||
.chgYmd(record.getChangeDe())
|
||||
.carmdlAsortCd(record.getVhctyAsortCode())
|
||||
.carmdlTypeCd(record.getVhctyTyCode())
|
||||
.carmdlSeCd(record.getVhctySeCode())
|
||||
.mxmmLdg(record.getMxmmLdg())
|
||||
.carmdlAsortNm(record.getVhctyAsortNm())
|
||||
.carmdlTypeNm(record.getVhctyTyNm())
|
||||
.carmdlClsfNm(record.getVhctySeNm())
|
||||
.frstRegYmd(record.getFrstRegistDe())
|
||||
.fomNm(record.getFomNm())
|
||||
.acqsYmd(record.getAcqsDe())
|
||||
.acqsEndYmd(record.getAcqsEndDe())
|
||||
.fbctnYmd(record.getYblMd())
|
||||
.transrRegYmd(record.getTransrRegistDe())
|
||||
.spcfRegSttsCd(record.getSpcfRegistSttusCode())
|
||||
.colorNm(record.getColorNm())
|
||||
.mrtgCnt(record.getMrtgCo())
|
||||
.szrCnt(record.getSeizrCo())
|
||||
.strctChgCnt(record.getStmdCo())
|
||||
.nopltCsdyYn(record.getNmplCsdyAt())
|
||||
.nopltCsdyAvtsmtYmd(record.getNmplCsdyRemnrDe())
|
||||
.srcSeCd(record.getOriginSeCode())
|
||||
.nopltSpcfctCd(record.getNmplStndrdCode())
|
||||
.acqsAmt(record.getAcqsAmount())
|
||||
.inspVldPdBgngYmd(record.getInsptValidPdBgnde())
|
||||
.inspVldPdEndYmd(record.getInsptValidPdEndde())
|
||||
.usgsrhldGrcCd(record.getUseStrnghldGrcCode())
|
||||
.rdcpctCnt(record.getTkcarPscapCo())
|
||||
.spmnno(record.getSpmnno())
|
||||
.drvngDstnc(record.getTrvlDstnc())
|
||||
.frstRegAplyRcptNo(record.getFrstRegistRqrcno())
|
||||
.vlntErsrPrvntcAvtsmtYmd(record.getVlntErsrPrvntcNticeDe())
|
||||
.ognzNm(record.getRegistInsttNm())
|
||||
.prcsImprtyRsnCd(record.getProcessImprtyResnCode())
|
||||
.prcsImprtyRsnDtls(record.getProcessImprtyResnDtls())
|
||||
.cbdLt(record.getCbdLt())
|
||||
.cbdBt(record.getCbdBt())
|
||||
.cbdHg(record.getCbdHg())
|
||||
.frstMxmmLdg(record.getFrstMxmmLdg())
|
||||
.fuelCnsmprt(record.getFuelCnsmpRt())
|
||||
.elctyCmpndFuelCnsmprt(record.getElctyCmpndFuelCnsmpRt());
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* NewBasicRequest에서 VO로 변환 (요청 초기 저장용)
|
||||
*
|
||||
* @param request 신규 API 요청 객체
|
||||
* @return 요청 정보가 담긴 VO
|
||||
*/
|
||||
public static CarBassMatterInqireVO fromNewRequest(NewBasicRequest request) {
|
||||
if (request == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 공통 메타 정보 매핑
|
||||
CarBassMatterInqireVO.CarBassMatterInqireVOBuilder builder = CarBassMatterInqireVO.builder()
|
||||
.infoSysId(request.getInfoSysId())
|
||||
.infoSysIpAddr(request.getInfoSysIpAddr())
|
||||
.sggCd(request.getSggCd())
|
||||
.linkInfoCd(request.getLinkInfoCd())
|
||||
.picId(request.getPicId())
|
||||
.picIpAddr(request.getPicIpAddr())
|
||||
.picNm(request.getPicNm());
|
||||
|
||||
// record가 있는 경우 첫 번째 record의 요청 정보 매핑
|
||||
if (request.getRecord() != null && !request.getRecord().isEmpty()) {
|
||||
NewBasicRequest.Record record = request.getRecord().get(0);
|
||||
builder
|
||||
.dmndLevyCrtrYmd(record.getLevyCrtrYmd()) // 과태료 기준일자
|
||||
.dmndInqSeCd(record.getInqSeCd()) // 조회 구분 코드
|
||||
.dmndVhrno(record.getVhrno()) // 차량번호
|
||||
.dmndVin(record.getVin()); // 차대번호
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* ApiExchangeEnvelope<NewBasicRequest, NewBasicResponse>에서 VO로 변환 (응답 업데이트용)
|
||||
*
|
||||
* @param generatedId 생성된 PK ID
|
||||
* @param envelope API 응답 Envelope
|
||||
* @return 응답 정보가 담긴 VO
|
||||
*/
|
||||
public static CarBassMatterInqireVO fromNewExchange(
|
||||
String generatedId,
|
||||
ApiExchangeEnvelope<NewBasicRequest, NewBasicResponse> envelope) {
|
||||
|
||||
if (envelope == null || envelope.getResponse() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Envelope<NewBasicResponse> response = envelope.getResponse();
|
||||
List<NewBasicResponse> data = response.getData();
|
||||
|
||||
if (data == null || data.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
NewBasicResponse firstData = data.get(0);
|
||||
List<NewBasicResponse.Record> records = firstData.getRecord();
|
||||
|
||||
// 응답 정보 업데이트용 VO 빌드
|
||||
CarBassMatterInqireVO.CarBassMatterInqireVOBuilder builder = CarBassMatterInqireVO.builder()
|
||||
.carBassMatterInqireId(generatedId)
|
||||
.txId(envelope.getTxId())
|
||||
.linkRsltCd(firstData.getLinkRsltCd())
|
||||
.linkRsltDtl(firstData.getLinkRsltDtl());
|
||||
|
||||
// record가 있는 경우 첫 번째 record의 상세 정보 매핑
|
||||
if (records != null && !records.isEmpty()) {
|
||||
NewBasicResponse.Record record = records.get(0);
|
||||
|
||||
builder
|
||||
.yridnw(record.getYridnw())
|
||||
.regYmd(record.getRegYmd())
|
||||
.ersrRegSeCd(record.getErsrRegSeCd())
|
||||
.ersrRegSeNm(record.getErsrRegSeNm())
|
||||
.ersrRegYmd(record.getErsrRegYmd())
|
||||
.regDtlCd(record.getRegDtlCd())
|
||||
.dsplvl(record.getDsplvl())
|
||||
.usgsrhldStdgCd(record.getUsgsrhldStdgCd())
|
||||
.usgsrhldDongCd(record.getUsgsrhldDongCd())
|
||||
.usgsrhldMtnYn(record.getUsgsrhldMtnYn())
|
||||
.usgsrhldLnbr(record.getUsgsrhldLnbr())
|
||||
.usgsrhldHo(record.getUsgsrhldHo())
|
||||
.usgsrhldAddrNm(record.getUsgsrhldAddrNm())
|
||||
.usgsrhldRoadNmCd(record.getUsgsrhldRoadNmCd())
|
||||
.usgsrhldUdgdBldgSeCd(record.getUsgsrhldUdgdBldgSeCd())
|
||||
.usgsrhldBmno(record.getUsgsrhldBmno())
|
||||
.usgsrhldBsno(record.getUsgsrhldBsno())
|
||||
.usgsrhldWholAddr(record.getUsgsrhldWholAddr())
|
||||
.rprsOwnrMbrSeCd(record.getRprsOwnrMbrSeCd())
|
||||
.rprsOwnrNm(record.getRprsOwnrNm())
|
||||
.rprsvOwnrIdecno(record.getRprsvOwnrIdecno())
|
||||
.rprsOwnrTelno(record.getRprsOwnrTelno())
|
||||
.ownrStdgCd(record.getOwnrStdgCd())
|
||||
.ownrDongCd(record.getOwnrDongCd())
|
||||
.ownrMtnYn(record.getOwnrMtnYn())
|
||||
.ownrLnbr(record.getOwnrLnbr())
|
||||
.ownrHo(record.getOwnrHo())
|
||||
.ownrAddrNm(record.getOwnrAddrNm())
|
||||
.ownrRoadNmCd(record.getOwnrRoadNmCd())
|
||||
.ownrUdgdBldgSeCd(record.getOwnrUdgdBldgSeCd())
|
||||
.ownrBmno(record.getOwnrBmno())
|
||||
.ownrBsno(record.getOwnrBsno())
|
||||
.ownrWholaddr(record.getOwnrWholAddr())
|
||||
.rearVhrno(record.getRearVhrno())
|
||||
.useFuelCd(record.getUseFuelCd())
|
||||
.usgSeCd(record.getUsgSeCd())
|
||||
.mtrsFomNm(record.getMtrsFomNm())
|
||||
.bfrVhrno(record.getBfrVhrno())
|
||||
.vhrno(record.getVhrno())
|
||||
.vin(record.getVin())
|
||||
.atmbNm(record.getAtmbNm())
|
||||
.vhclTotlWt(record.getVhclTotlWt())
|
||||
.veagEndYmd(record.getVeagEndYmd())
|
||||
.chgYmd(record.getChgYmd())
|
||||
.carmdlAsortCd(record.getCarmdlAsortCd())
|
||||
.carmdlTypeCd(record.getCarmdlTypeCd())
|
||||
.carmdlSeCd(record.getCarmdlSeCd())
|
||||
.mxmmLdg(record.getMxmmLdg())
|
||||
.carmdlAsortNm(record.getCarmdlAsortNm())
|
||||
.carmdlTypeNm(record.getCarmdlTypeNm())
|
||||
.carmdlClsfNm(record.getCarmdlClsfNm())
|
||||
.frstRegYmd(record.getFrstRegYmd())
|
||||
.fomNm(record.getFomNm())
|
||||
.acqsYmd(record.getAcqsYmd())
|
||||
.acqsEndYmd(record.getAcqsEndYmd())
|
||||
.fbctnYmd(record.getFbctnYmd())
|
||||
.transrRegYmd(record.getTransrRegYmd())
|
||||
.spcfRegSttsCd(record.getSpcfRegSttsCd())
|
||||
.colorNm(record.getColorNm())
|
||||
.mrtgCnt(record.getMrtgCnt())
|
||||
.szrCnt(record.getSzrCnt())
|
||||
.strctChgCnt(record.getStrctChgCnt())
|
||||
.nopltCsdyYn(record.getNoplTcsdyYn())
|
||||
.nopltCsdyAvtsmtYmd(record.getNoplTcsdyAvtsmtYmd())
|
||||
.srcSeCd(record.getSrcSeCd())
|
||||
.nopltSpcfctCd(record.getNoplTSpcfctCd())
|
||||
.acqsAmt(record.getAcqsAmt())
|
||||
.inspVldPdBgngYmd(record.getInspVldPdBgngYmd())
|
||||
.inspVldPdEndYmd(record.getInspVldPdEndYmd())
|
||||
.usgsrhldGrcCd(record.getUsgsrhldGrcCd())
|
||||
.rdcpctCnt(record.getRdcpctCnt())
|
||||
.spmnno(record.getSpmnno())
|
||||
.drvngDstnc(record.getDrvngDstnc())
|
||||
.frstRegAplyRcptNo(record.getFrstRegAplyRcptNo())
|
||||
.vlntErsrPrvntcAvtsmtYmd(record.getVlntErsrPrvntcAvtsmtYmd())
|
||||
.ognzNm(record.getOgnzNm())
|
||||
.prcsImprtyRsnCd(record.getPrcsImprtyRsnCd())
|
||||
.prcsImprtyRsnDtls(record.getPrcsImprtyRsnDtls())
|
||||
.cbdLt(record.getCbdLt())
|
||||
.cbdBt(record.getCbdBt())
|
||||
.cbdHg(record.getCbdHg())
|
||||
.frstMxmmLdg(record.getFrstMxmmLdg())
|
||||
.fuelCnsmprt(record.getFuelCnsmprt())
|
||||
.elctyCmpndFuelCnsmprt(record.getElctyCmpndFuelCnsmprt());
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
@ -1,137 +0,0 @@
|
||||
package go.kr.project.api.model;
|
||||
|
||||
import go.kr.project.api.model.request.NewLedgerRequest;
|
||||
import go.kr.project.api.model.response.NewLedgerResponse;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 자동차 등록 원부(갑) 상세 엔티티 VO, DB 저장용
|
||||
*
|
||||
* <p>tb_car_ledger_frmbk_dtl 테이블 매핑</p>
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class CarLedgerFrmbkDtlVO {
|
||||
|
||||
// PK
|
||||
private String carLedgerFrmbkDtlId;
|
||||
|
||||
// FK
|
||||
private String carLedgerFrmbkId; // CAR_LEDGER_FRMBK_ID
|
||||
|
||||
// 본문 - DB 컬럼명과 정확히 일치
|
||||
private String szrRmvDtlSn; // SZR_RMV_DTL_SN
|
||||
private String chgTaskSeCd; // CHG_TASK_SE_CD
|
||||
private String mainNo; // MAIN_NO
|
||||
private String sno; // SNO
|
||||
private String spcablMttr; // SPCABL_MTTR
|
||||
private String hshldrNm; // HSHLDR_NM
|
||||
private String hshldrIdecno; // HSHLDR_IDECNO
|
||||
private String aplyRcptNo; // APLY_RCPT_NO
|
||||
private String vhmno; // VHMNO
|
||||
private String ledgerGroupNo; // LEDGER_GROUP_NO
|
||||
private String ledgerIndivNo; // LEDGER_INDIV_NO
|
||||
private String chgTaskSeNm; // CHG_TASK_SE_NM
|
||||
private String chgYmd; // CHG_YMD
|
||||
private String dtlSn; // DTL_SN
|
||||
private String flag; // FLAG
|
||||
|
||||
// 감사
|
||||
private String rgtr; // RGTR
|
||||
|
||||
/**
|
||||
* ApiExchangeEnvelope에서 상세 VO 리스트로 변환
|
||||
*
|
||||
* @param envelope API 응답 Envelope
|
||||
* @param generatedId 생성된 마스터 PK ID
|
||||
* @return 상세 VO 리스트
|
||||
*/
|
||||
public static List<CarLedgerFrmbkDtlVO> listNewFromExchange(
|
||||
ApiExchangeEnvelope<NewLedgerRequest, NewLedgerResponse> envelope,
|
||||
String generatedId) {
|
||||
|
||||
if (envelope == null || envelope.getResponse() == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
Envelope<NewLedgerResponse> response = envelope.getResponse();
|
||||
List<NewLedgerResponse> data = response.getData();
|
||||
|
||||
if (data == null || data.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
NewLedgerResponse firstData = data.get(0);
|
||||
List<NewLedgerResponse.Record> records = firstData.getRecord();
|
||||
|
||||
if (records == null || records.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
// Record 리스트를 VmisCarLedgerFrmbkDtlVO 리스트로 변환
|
||||
return records.stream()
|
||||
.map(record -> CarLedgerFrmbkDtlVO.builder()
|
||||
.carLedgerFrmbkId(generatedId)
|
||||
.szrRmvDtlSn(record.getSzrRmvDtlSn())
|
||||
.chgTaskSeCd(record.getChgTaskSeCd())
|
||||
.mainNo(record.getMainNo())
|
||||
.sno(record.getSno())
|
||||
.spcablMttr(record.getSpcablMttr())
|
||||
.hshldrNm(record.getHshldrNm())
|
||||
.hshldrIdecno(record.getHshldrIdecno())
|
||||
.aplyRcptNo(record.getAplyRcptNo())
|
||||
.vhmno(record.getVhmno())
|
||||
.ledgerGroupNo(record.getLedgerGroupNo())
|
||||
.ledgerIndivNo(record.getLedgerIndivNo())
|
||||
.chgTaskSeNm(record.getChgTaskSeNm())
|
||||
.chgYmd(record.getChgYmd())
|
||||
.dtlSn(record.getDtlSn())
|
||||
.flag(record.getFlag())
|
||||
.build())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* NewLedgerResponse.Record에서 단일 상세 VO로 변환
|
||||
*
|
||||
* @param record NewLedgerResponse.Record 객체
|
||||
* @param carLedgerFrmbkId 마스터 PK ID
|
||||
* @return 상세 VO
|
||||
*/
|
||||
public static CarLedgerFrmbkDtlVO fromRecord(
|
||||
NewLedgerResponse.Record record,
|
||||
String carLedgerFrmbkId) {
|
||||
|
||||
if (record == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return CarLedgerFrmbkDtlVO.builder()
|
||||
.carLedgerFrmbkId(carLedgerFrmbkId)
|
||||
.szrRmvDtlSn(record.getSzrRmvDtlSn())
|
||||
.chgTaskSeCd(record.getChgTaskSeCd())
|
||||
.mainNo(record.getMainNo())
|
||||
.sno(record.getSno())
|
||||
.spcablMttr(record.getSpcablMttr())
|
||||
.hshldrNm(record.getHshldrNm())
|
||||
.hshldrIdecno(record.getHshldrIdecno())
|
||||
.aplyRcptNo(record.getAplyRcptNo())
|
||||
.vhmno(record.getVhmno())
|
||||
.ledgerGroupNo(record.getLedgerGroupNo())
|
||||
.ledgerIndivNo(record.getLedgerIndivNo())
|
||||
.chgTaskSeNm(record.getChgTaskSeNm())
|
||||
.chgYmd(record.getChgYmd())
|
||||
.dtlSn(record.getDtlSn())
|
||||
.flag(record.getFlag())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@ -1,244 +0,0 @@
|
||||
package go.kr.project.api.model;
|
||||
|
||||
import go.kr.project.api.model.request.NewLedgerRequest;
|
||||
import go.kr.project.api.model.response.NewLedgerResponse;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 자동차 등록 원부(갑) 마스터 엔티티 VO, DB 저장용
|
||||
*
|
||||
* <p>tb_car_ledger_frmbk 테이블 매핑</p>
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class CarLedgerFrmbkVO {
|
||||
// PK
|
||||
private String carLedgerFrmbkId;
|
||||
|
||||
// 신규 응답용 txId
|
||||
private String txId;
|
||||
|
||||
// 요청(헤더/본문) 정보 - DB 컬럼명과 동일하게
|
||||
private String infoSysId; // INFO_SYS_ID
|
||||
private String infoSysIpAddr; // INFO_SYS_IP_ADDR
|
||||
private String sggCd; // SGG_CD
|
||||
private String linkInfoCd; // LINK_INFO_CD
|
||||
private String picId; // PIC_ID
|
||||
private String picIpAddr; // PIC_IP_ADDR
|
||||
private String picNm; // PIC_NM
|
||||
|
||||
// 요청 본문 - DB 컬럼명과 동일하게
|
||||
private String dmndVhrno; // DMND_VHRNO
|
||||
private String dmndPrvcRls; // DMND_PRVC_RLS
|
||||
private String dmndCvlprNm; // DMND_CVLPR_NM
|
||||
private String dmndCvlprIdecno; // DMND_CVLPR_IDECNO
|
||||
private String dmndCvlprStdgCd; // DMND_CVLPR_STDG_CD
|
||||
private String dmndPathSeCd; // DMND_PATH_SE_CD
|
||||
private String dmndDsctnIndct; // DMND_DSCTN_INDCT
|
||||
private String dmndInqSeCd; // DMND_INQ_SE_CD
|
||||
|
||||
// 응답 요약 정보 - DB 컬럼명과 동일하게
|
||||
private String linkRsltCd; // LINK_RSLT_CD
|
||||
private String linkRsltDtl; // LINK_RSLT_DTL
|
||||
|
||||
// 응답 본문(마스터) - DB 컬럼명과 정확히 일치
|
||||
private String ledgerGroupNo; // LEDGER_GROUP_NO
|
||||
private String ledgerIndivNo; // LEDGER_INDIV_NO
|
||||
private String vhmno; // VHMNO
|
||||
private String vhrno; // VHRNO
|
||||
private String vin; // VIN
|
||||
private String carmdlAsortCd; // CARMDL_ASORT_CD
|
||||
private String carmdlAsortNm; // CARMDL_ASORT_NM
|
||||
private String atmbNm; // ATMB_NM
|
||||
private String colorCd; // COLOR_CD
|
||||
private String colorNm; // COLOR_NM
|
||||
private String nopltSpcfctCd; // NOPLT_SPCFCT_CD
|
||||
private String nopltSpcfctNm; // NOPLT_SPCFCT_NM
|
||||
private String usgSeCd; // USG_SE_CD
|
||||
private String usgSeNm; // USG_SE_NM
|
||||
private String mtrsFomNm; // MTRS_FOM_NM
|
||||
private String fomNm; // FOM_NM
|
||||
private String acqsAmt; // ACQS_AMT
|
||||
private String regDtlCd; // REG_DTL_CD
|
||||
private String regDtlNm; // REG_DTL_NM
|
||||
private String frstRegYmd; // FRST_REG_YMD
|
||||
private String veagEndYmd; // VEAG_END_YMD
|
||||
private String yridnw; // YRIDNW
|
||||
private String spmnno1; // SPMNNO_1
|
||||
private String spmnno2; // SPMNNO_2
|
||||
private String fbctnYmd; // FBCTN_YMD
|
||||
private String drvngDstnc; // DRVNG_DSTNC
|
||||
private String inspVldPdBgngYmd; // INSP_VLD_PD_BGNG_YMD
|
||||
private String inspVldPdEndYmd; // INSP_VLD_PD_END_YMD
|
||||
private String chckVldPdBgngYmd; // CHCK_VLD_PD_BGNG_YMD
|
||||
private String chckVldPdEndYmd; // CHCK_VLD_PD_END_YMD
|
||||
private String regAplySeNm; // REG_APLY_SE_NM
|
||||
private String frstRegAplyRcptNo; // FRST_REG_APLY_RCPT_NO
|
||||
private String nopltCsdyAvtsmtYmd; // NOPLT_CSDY_AVTSMT_YMD
|
||||
private String nopltCsdyYn; // NOPLT_CSDY_YN
|
||||
private String bssUsePdYmd; // BSS_USE_PD_YMD
|
||||
private String octhtErsrPrvntcAvtsmtYmd;// OCTHT_ERSR_PRVNTC_AVTSMT_YMD
|
||||
private String ersrRegYmd; // ERSR_REG_YMD
|
||||
private String ersrRegSeCd; // ERSR_REG_SE_CD
|
||||
private String ersrRegSeNm; // ERSR_REG_SE_NM
|
||||
private String mrtgCnt; // MRTG_CNT
|
||||
private String szrCnt; // SZR_CNT
|
||||
private String strctChgCnt; // STRCT_CHG_CNT
|
||||
private String usgsrhldAddr1; // USGSRHLD_ADDR_1
|
||||
private String usgsrhldAddrDtl1; // USGSRHLD_ADDR_DTL_1
|
||||
private String ownrAddr; // OWNR_ADDR
|
||||
private String ownrAddrDtl; // OWNR_ADDR_DTL
|
||||
private String indvdlBzmnYn; // INDVDL_BZMN_YN
|
||||
private String rprsOwnrTelno; // RPRS_OWNR_TELNO
|
||||
private String rprsOwnrNm; // RPRS_OWNR_NM
|
||||
private String rprsOwnrMbrSeCd; // RPRS_OWNR_MBR_SE_CD
|
||||
private String rprsvOwnrIdecno; // RPRSV_OWNR_IDECNO
|
||||
private String taxxmptTrprSeCd; // TAXXMPT_TRPR_SE_CD
|
||||
private String taxxmptAplcnSeCd; // TAXXMPT_APLCN_SE_CD
|
||||
private String spcablMttrCnt; // SPCABL_MTTR_CNT
|
||||
private String usgsrhldDongNm; // USGSRHLD_DONG_NM
|
||||
private String prvntcCnt; // PRVNTC_CNT
|
||||
private String xportFlflYnDclrYmd; // XPORT_FLFL_YN_DCLR_YMD
|
||||
private String issuNo; // ISSU_NO
|
||||
private String frstTrnsfrYmd; // FRST_TRNSFR_YMD
|
||||
private String drivSrgbtryIdntfNo; // DRIV_SRGBTRY_IDNTF_NO
|
||||
private String prcsImprtyRsnCd; // PRCS_IMPRTY_RSN_CD
|
||||
private String prcsImprtyRsnDtls; // PRCS_IMPRTY_RSN_DTLS
|
||||
private String carFfnlgTrgtId; // CAR_FFNLG_TRGT_ID
|
||||
|
||||
// 감사
|
||||
private String rgtr;
|
||||
|
||||
private List<CarLedgerFrmbkDtlVO> record;
|
||||
|
||||
/**
|
||||
* NewLedgerRequest에서 VO로 변환 (최초 요청 로그 저장용)
|
||||
*
|
||||
* @param request NewLedgerRequest 요청 객체
|
||||
* @return 초기 요청 정보가 담긴 VO
|
||||
*/
|
||||
public static CarLedgerFrmbkVO fromNewRequest(NewLedgerRequest request) {
|
||||
if (request == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return CarLedgerFrmbkVO.builder()
|
||||
.infoSysId(request.getInfoSysId())
|
||||
.infoSysIpAddr(request.getInfoSysIpAddr())
|
||||
.sggCd(request.getSggCd())
|
||||
.linkInfoCd(request.getLinkInfoCd())
|
||||
.picId(request.getPicId())
|
||||
.picIpAddr(request.getPicIpAddr())
|
||||
.picNm(request.getPicNm())
|
||||
.dmndVhrno(request.getVhrno())
|
||||
.dmndPrvcRls(request.getPrvcRls())
|
||||
.dmndCvlprNm(request.getCvlprNm())
|
||||
.dmndCvlprIdecno(request.getCvlprIdecno())
|
||||
.dmndCvlprStdgCd(request.getCvlprStdgCd())
|
||||
.dmndPathSeCd(request.getPathSeCd())
|
||||
.dmndDsctnIndct(request.getDsctnIndct())
|
||||
.dmndInqSeCd(request.getInqSeCd())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* NewLedgerResponse에서 VO로 변환 (응답 마스터 정보 업데이트용)
|
||||
*
|
||||
* @param generatedId 생성된 PK ID
|
||||
* @param response NewLedgerResponse 응답 객체
|
||||
* @return 응답 마스터 정보가 담긴 VO
|
||||
*/
|
||||
public static CarLedgerFrmbkVO fromNewResponseMaster(
|
||||
String generatedId,
|
||||
NewLedgerResponse response) {
|
||||
|
||||
if (response == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return CarLedgerFrmbkVO.builder()
|
||||
.carLedgerFrmbkId(generatedId)
|
||||
.linkRsltCd(response.getLinkRsltCd())
|
||||
.linkRsltDtl(response.getLinkRsltDtl())
|
||||
.ledgerGroupNo(response.getLedgerGroupNo())
|
||||
.ledgerIndivNo(response.getLedgerIndivNo())
|
||||
.vhmno(response.getVhmno())
|
||||
.vhrno(response.getVhrno())
|
||||
.vin(response.getVin())
|
||||
.carmdlAsortCd(response.getCarmdlAsortCd())
|
||||
.carmdlAsortNm(response.getCarmdlAsortNm())
|
||||
.atmbNm(response.getAtmbNm())
|
||||
.colorCd(response.getColorCd())
|
||||
.colorNm(response.getColorNm())
|
||||
.nopltSpcfctCd(response.getNopltSpcfctCd())
|
||||
.nopltSpcfctNm(response.getNopltSpcfctNm())
|
||||
.usgSeCd(response.getUsgSeCd())
|
||||
.usgSeNm(response.getUsgSeNm())
|
||||
.mtrsFomNm(response.getMtrsFomNm())
|
||||
.fomNm(response.getFomNm())
|
||||
.acqsAmt(response.getAcqsAmt())
|
||||
.regDtlCd(response.getRegDtlCd())
|
||||
.regDtlNm(response.getRegDtlNm())
|
||||
.frstRegYmd(response.getFrstRegYmd())
|
||||
.veagEndYmd(response.getVeagEndYmd())
|
||||
.yridnw(response.getYridnw())
|
||||
.spmnno1(response.getSpmnno1())
|
||||
.spmnno2(response.getSpmnno2())
|
||||
.fbctnYmd(response.getFbctnYmd())
|
||||
.drvngDstnc(response.getDrvngDstnc())
|
||||
.inspVldPdBgngYmd(response.getInspVldPdBgngYmd())
|
||||
.inspVldPdEndYmd(response.getInspVldPdEndYmd())
|
||||
.chckVldPdBgngYmd(response.getChckVldPdBgngYmd())
|
||||
.chckVldPdEndYmd(response.getChckVldPdEndYmd())
|
||||
.regAplySeNm(response.getRegAplySeNm())
|
||||
.frstRegAplyRcptNo(response.getFrstRegAplyRcptNo())
|
||||
.nopltCsdyAvtsmtYmd(response.getNopltCsdyAvtsmtYmd())
|
||||
.nopltCsdyYn(response.getNopltCsdyYn())
|
||||
.bssUsePdYmd(response.getBssUsePdYmd())
|
||||
.octhtErsrPrvntcAvtsmtYmd(response.getOcthtErsrPrvntcAvtsmtYmd())
|
||||
.ersrRegYmd(response.getErsrRegYmd())
|
||||
.ersrRegSeCd(response.getErsrRegSeCd())
|
||||
.ersrRegSeNm(response.getErsrRegSeNm())
|
||||
.mrtgCnt(response.getMrtgCnt())
|
||||
.szrCnt(response.getSzrCnt())
|
||||
.strctChgCnt(response.getStrctChgCnt())
|
||||
.usgsrhldAddr1(response.getUsgsrhldAddr1())
|
||||
.usgsrhldAddrDtl1(response.getUsgsrhldAddrDtl1())
|
||||
.ownrAddr(response.getOwnrAddr())
|
||||
.ownrAddrDtl(response.getOwnrAddrDtl())
|
||||
.indvdlBzmnYn(response.getIndvdlBzmnYn())
|
||||
.rprsOwnrTelno(response.getRprsOwnrTelno())
|
||||
.rprsOwnrNm(response.getRprsOwnrNm())
|
||||
.rprsOwnrMbrSeCd(response.getRprsOwnrMbrSeCd())
|
||||
.rprsvOwnrIdecno(response.getRprsvOwnrIdecno())
|
||||
.taxxmptTrprSeCd(response.getTaxxmptTrprSeCd())
|
||||
.taxxmptAplcnSeCd(response.getTaxxmptAplcnSeCd())
|
||||
.spcablMttrCnt(response.getSpcablMttrCnt())
|
||||
.usgsrhldDongNm(response.getUsgsrhldDongNm())
|
||||
.prvntcCnt(response.getPrvntcCnt())
|
||||
.xportFlflYnDclrYmd(response.getXportFlflYnDclrYmd())
|
||||
.issuNo(response.getIssuNo())
|
||||
.frstTrnsfrYmd(response.getFrstTrnsfrYmd())
|
||||
.drivSrgbtryIdntfNo(response.getDrivSrgbtryIdntfNo())
|
||||
.prcsImprtyRsnCd(response.getProcessImprtyResnCode())
|
||||
.prcsImprtyRsnDtls(response.getProcessImprtyResnDtls())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* NewLedgerRequest에서 필수 조회 항목 추출 (DB 조회용)
|
||||
*
|
||||
* @param request NewLedgerRequest 요청 객체
|
||||
* @return 차량번호
|
||||
*/
|
||||
public static String extractVhrno(NewLedgerRequest request) {
|
||||
return request != null ? request.getVhrno() : null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,89 @@
|
||||
package go.kr.project.api.model.request;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@Getter
|
||||
@Setter
|
||||
@Schema(description = "자동차기본사항조회 요청 항목")
|
||||
public class BasicRequest {
|
||||
|
||||
// 본문 공통 메타 (VmisRequestEnricher에서 자동 설정)
|
||||
@Schema(description = "정보시스템ID (자동설정: vmis.system.infoSysId)", example = "41-345")
|
||||
@JsonProperty("INFO_SYS_ID")
|
||||
private String infoSysId;
|
||||
|
||||
@Schema(description = "정보시스템IP (자동설정: vmis.system.infoSysIp)", example = "105.19.10.135")
|
||||
@JsonProperty("INFO_SYS_IP")
|
||||
private String infoSysIp;
|
||||
|
||||
@Schema(description = "시군구코드 (자동설정: vmis.system.sigunguCode)", example = "41460")
|
||||
@JsonProperty("SIGUNGU_CODE")
|
||||
private String sigunguCode;
|
||||
|
||||
// 서비스별 필드 (VmisRequestEnricher에서 자동 설정)
|
||||
@Schema(description = "연계정보코드 (자동설정: vmis.gov.services.basic.cntcInfoCode)", example = "AC1_FD11_01")
|
||||
@JsonProperty("CNTC_INFO_CODE")
|
||||
private String cntcInfoCode;
|
||||
|
||||
@Schema(description = "담당자ID (자동설정: vmis.system.chargerId)", example = "")
|
||||
@JsonProperty("CHARGER_ID")
|
||||
private String chargerId;
|
||||
|
||||
@Schema(description = "담당자IP (자동설정: vmis.system.chargerIp)", example = "")
|
||||
@JsonProperty("CHARGER_IP")
|
||||
private String chargerIp;
|
||||
|
||||
@Schema(description = "담당자명(사용자) (자동설정: vmis.system.chargerNm)", example = "")
|
||||
@JsonProperty("CHARGER_NM")
|
||||
private String chargerNm;
|
||||
|
||||
@Schema(description = "부과기준일", example = "20250101")
|
||||
@JsonProperty("LEVY_STDDE")
|
||||
private String levyStdde;
|
||||
|
||||
@Schema(description = "조회구분코드 {2:차대번호(VIN), 3:자동차번호(VHRNO)} (VmisRequestEnricher에서 자동설정)")
|
||||
@JsonProperty("INQIRE_SE_CODE")
|
||||
private String inqireSeCode;
|
||||
|
||||
@Schema(description = "자동차등록번호", example = "12가3456")
|
||||
@JsonProperty("VHRNO")
|
||||
private String vhrno;
|
||||
|
||||
@Schema(description = "차대번호", example = "KMHAB812345678901")
|
||||
@JsonProperty("VIN")
|
||||
private String vin;
|
||||
|
||||
/*
|
||||
// 추가 항목 (명세 샘플 기준)
|
||||
@Schema(description = "개인정보공개", example = "Y")
|
||||
@JsonProperty("ONES_INFORMATION_OPEN")
|
||||
private String onesInformationOpen;
|
||||
|
||||
@Schema(description = "민원인성명")
|
||||
@JsonProperty("CPTTR_NM")
|
||||
private String cpttrNm;
|
||||
|
||||
@Schema(description = "민원인주민번호")
|
||||
@JsonProperty("CPTTR_IHIDNUM")
|
||||
@Size(max = 13)
|
||||
private String cpttrIhidnum;
|
||||
|
||||
@Schema(description = "민원인법정동코드")
|
||||
@JsonProperty("CPTTR_LEGALDONG_CODE")
|
||||
private String cpttrLegaldongCode;
|
||||
|
||||
@Schema(description = "경로구분코드")
|
||||
@JsonProperty("ROUTE_SE_CODE")
|
||||
private String routeSeCode;
|
||||
|
||||
@Schema(description = "내역표시")
|
||||
@JsonProperty("DETAIL_EXPRESSION")
|
||||
private String detailExpression;
|
||||
*/
|
||||
|
||||
}
|
||||
@ -0,0 +1,80 @@
|
||||
package go.kr.project.api.model.request;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@Schema(description = "자동차등록원부(갑) 요청 항목")
|
||||
@Getter
|
||||
@Setter
|
||||
public class LedgerRequest {
|
||||
|
||||
// 본문 공통 메타 (VmisRequestEnricher에서 자동 설정)
|
||||
@Schema(description = "정보시스템ID (자동설정: vmis.system.infoSysId)", example = "41-345")
|
||||
@JsonProperty("INFO_SYS_ID")
|
||||
private String infoSysId;
|
||||
|
||||
@Schema(description = "정보시스템IP (자동설정: vmis.system.infoSysIp)", example = "105.19.10.135")
|
||||
@JsonProperty("INFO_SYS_IP")
|
||||
private String infoSysIp;
|
||||
|
||||
@Schema(description = "시군구코드 (자동설정: vmis.system.sigunguCode)", example = "41460")
|
||||
@JsonProperty("SIGUNGU_CODE")
|
||||
private String sigunguCode;
|
||||
|
||||
// 서비스별 필드 (VmisRequestEnricher에서 자동 설정)
|
||||
@Schema(description = "연계정보코드 (자동설정: vmis.gov.services.ledger.cntcInfoCode)", example = "AC1_FD11_02")
|
||||
@JsonProperty("CNTC_INFO_CODE")
|
||||
private String cntcInfoCode;
|
||||
|
||||
@Schema(description = "담당자ID (자동설정: vmis.system.chargerId)", example = "")
|
||||
@JsonProperty("CHARGER_ID")
|
||||
private String chargerId;
|
||||
|
||||
@Schema(description = "담당자IP (자동설정: vmis.system.chargerIp)", example = "")
|
||||
@JsonProperty("CHARGER_IP")
|
||||
private String chargerIp;
|
||||
|
||||
@Schema(description = "담당자명(사용자) (자동설정: vmis.system.chargerNm)", example = "")
|
||||
@JsonProperty("CHARGER_NM")
|
||||
private String chargerNm;
|
||||
|
||||
@Schema(description = "자동차등록번호 (필수)", example = "12가3456")
|
||||
@JsonProperty("VHRNO")
|
||||
private String vhrno;
|
||||
|
||||
@Schema(description = "개인정보공개 {1:소유자공개, 2:비공개, 3:비공개(주민등록번호), 4:비공개(사용본거지)} (기본값: 1, VmisRequestEnricher에서 자동설정)")
|
||||
@JsonProperty("ONES_INFORMATION_OPEN")
|
||||
private String onesInformationOpen;
|
||||
|
||||
@Schema(description = "민원인성명 (통합조회 시 BasicResponse의 MBER_NM에서 자동매핑)")
|
||||
@JsonProperty("CPTTR_NM")
|
||||
private String cpttrNm;
|
||||
|
||||
@Schema(description = "민원인주민번호 (통합조회 시 BasicResponse의 MBER_SE_NO에서 자동매핑)")
|
||||
@JsonProperty("CPTTR_IHIDNUM")
|
||||
@Size(max = 13)
|
||||
private String cpttrIhidnum;
|
||||
|
||||
@Schema(description = "민원인법정동코드 (기본값: null)")
|
||||
@JsonProperty("CPTTR_LEGALDONG_CODE")
|
||||
private String cpttrLegaldongCode;
|
||||
|
||||
@Schema(description = "경로구분코드 (기본값: 3, VmisRequestEnricher에서 자동설정)")
|
||||
@JsonProperty("ROUTE_SE_CODE")
|
||||
private String routeSeCode;
|
||||
|
||||
@Schema(description = "내역표시 {1:전체내역, 2:최종내역} (기본값: 1, VmisRequestEnricher에서 자동설정)")
|
||||
@JsonProperty("DETAIL_EXPRESSION")
|
||||
private String detailExpression;
|
||||
|
||||
@Schema(description = "조회구분코드 {1:열람, 2:발급} (기본값: 1, VmisRequestEnricher에서 자동설정)")
|
||||
@JsonProperty("INQIRE_SE_CODE")
|
||||
private String inqireSeCode;
|
||||
|
||||
}
|
||||
@ -1,71 +0,0 @@
|
||||
package go.kr.project.api.model.request;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@Getter
|
||||
@Setter
|
||||
@Schema(description = "자동차기본사항조회 요청 항목 (신버전)")
|
||||
public class NewBasicRequest { // 총 8개 필드 (외부 클래스 8개, 중첩 Record 클래스 4개)
|
||||
|
||||
// 본문 공통 메타 (application.yml에서 자동 설정)
|
||||
@Schema(description = "정보시스템ID (자동설정: new.vmis.system.infoSysId)", example = "41-345")
|
||||
@JsonProperty("INFO_SYS_ID")
|
||||
private String infoSysId;
|
||||
|
||||
@Schema(description = "정보시스템IP (자동설정: new.vmis.system.infoSysIpAddr)", example = "105.19.10.135")
|
||||
@JsonProperty("INFO_SYS_IP_ADDR")
|
||||
private String infoSysIpAddr;
|
||||
|
||||
@Schema(description = "시군구코드 (자동설정: new.vmis.system.sggCd)", example = "41460")
|
||||
@JsonProperty("SGG_CD")
|
||||
private String sggCd;
|
||||
|
||||
// 서비스별 필드 (application.yml에서 자동 설정)
|
||||
@Schema(description = "연계정보코드 (자동설정: new.vmis.gov.services.basic.linkInfoCd)", example = "AC1_FD11_01")
|
||||
@JsonProperty("LINK_INFO_CD")
|
||||
private String linkInfoCd;
|
||||
|
||||
@Schema(description = "담당자ID (자동설정: new.vmis.system.picId)", example = "")
|
||||
@JsonProperty("PIC_ID")
|
||||
private String picId;
|
||||
|
||||
@Schema(description = "담당자IP (자동설정: new.vmis.system.picIpAddr)", example = "")
|
||||
@JsonProperty("PIC_IP_ADDR")
|
||||
private String picIpAddr;
|
||||
|
||||
@Schema(description = "담당자명 (자동설정: new.vmis.system.picNm)", example = "")
|
||||
@JsonProperty("PIC_NM")
|
||||
private String picNm;
|
||||
|
||||
@Schema(description = "조회 대상 record 배열")
|
||||
@JsonProperty("record")
|
||||
private java.util.List<Record> record;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@Getter
|
||||
@Setter
|
||||
@Schema(name = "NewBasicRequest.Record", description = "기본사항 요청 record 항목 (신버전)")
|
||||
public static class Record {
|
||||
@Schema(description = "부과기준일", example = "20250101")
|
||||
@JsonProperty("LEVY_CRTR_YMD")
|
||||
private String levyCrtrYmd;
|
||||
|
||||
@Schema(description = "조회구분코드 (자동설정: VHRNO not null → 3:자동차번호, VIN not null → 2:차대번호)")
|
||||
@JsonProperty("INQ_SE_CD")
|
||||
private String inqSeCd;
|
||||
|
||||
@Schema(description = "자동차등록번호", example = "12가3456")
|
||||
@JsonProperty("VHRNO")
|
||||
private String vhrno;
|
||||
|
||||
@Schema(description = "차대번호", example = "KMHAB812345678901")
|
||||
@JsonProperty("VIN")
|
||||
private String vin;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,80 +0,0 @@
|
||||
package go.kr.project.api.model.request;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@Schema(description = "자동차등록원부(갑) 요청 항목 (신버전)")
|
||||
@Getter
|
||||
@Setter
|
||||
public class NewLedgerRequest { // 총 15개 필드
|
||||
|
||||
// 본문 공통 메타 (application.yml에서 자동 설정)
|
||||
@Schema(description = "정보시스템ID (자동설정: new.vmis.system.infoSysId)", example = "41-345")
|
||||
@JsonProperty("INFO_SYS_ID")
|
||||
private String infoSysId;
|
||||
|
||||
@Schema(description = "정보시스템IP주소 (자동설정: new.vmis.system.infoSysIpAddr)", example = "105.19.10.135")
|
||||
@JsonProperty("INFO_SYS_IP_ADDR")
|
||||
private String infoSysIpAddr;
|
||||
|
||||
@Schema(description = "시군구코드 (자동설정: new.vmis.system.sggCd)", example = "41460")
|
||||
@JsonProperty("SGG_CD")
|
||||
private String sggCd;
|
||||
|
||||
// 서비스별 필드 (application.yml에서 자동 설정)
|
||||
@Schema(description = "연계정보코드 (자동설정: new.vmis.gov.services.ledger.linkInfoCd)", example = "AC1_FD11_02")
|
||||
@JsonProperty("LINK_INFO_CD")
|
||||
private String linkInfoCd;
|
||||
|
||||
@Schema(description = "담당자ID (자동설정: new.vmis.system.picId)", example = "")
|
||||
@JsonProperty("PIC_ID")
|
||||
private String picId;
|
||||
|
||||
@Schema(description = "담당자IP주소 (자동설정: new.vmis.system.picIpAddr)", example = "")
|
||||
@JsonProperty("PIC_IP_ADDR")
|
||||
private String picIpAddr;
|
||||
|
||||
@Schema(description = "담당자명 (자동설정: new.vmis.system.picNm)", example = "")
|
||||
@JsonProperty("PIC_NM")
|
||||
private String picNm;
|
||||
|
||||
@Schema(description = "자동차등록번호")
|
||||
@JsonProperty("VHRNO")
|
||||
private String vhrno;
|
||||
|
||||
@Schema(description = "개인정보공개 {1:소유자공개, 2:비공개, 3:비공개(주민등록번호), 4:비공개(사용본거지)}")
|
||||
@JsonProperty("PRVC_RLS")
|
||||
private String prvcRls;
|
||||
|
||||
@Schema(description = "민원인성명")
|
||||
@JsonProperty("CVLPR_NM")
|
||||
private String cvlprNm;
|
||||
|
||||
@Schema(description = "민원인주민번호")
|
||||
@JsonProperty("CVLPR_IDECNO")
|
||||
@Size(max = 13)
|
||||
private String cvlprIdecno;
|
||||
|
||||
@Schema(description = "민원인법정동코드")
|
||||
@JsonProperty("CVLPR_STDG_CD")
|
||||
private String cvlprStdgCd;
|
||||
|
||||
@Schema(description = "경로구분코드 고정코드:3")
|
||||
@JsonProperty("PATH_SE_CD")
|
||||
private String pathSeCd;
|
||||
|
||||
@Schema(description = "내역표시 {1:전체내역, 2:최종내역}")
|
||||
@JsonProperty("DSCTN_INDCT")
|
||||
private String dsctnIndct;
|
||||
|
||||
@Schema(description = "조회구분코드 (자동설정: 1:열람 고정)")
|
||||
@JsonProperty("INQ_SE_CD")
|
||||
private String inqSeCd;
|
||||
|
||||
}
|
||||
@ -1,71 +0,0 @@
|
||||
package go.kr.project.api.model.request;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@Getter
|
||||
@Setter
|
||||
@Schema(description = "자동차기본사항조회 요청 항목 (구버전)")
|
||||
public class OldBasicRequest { // 총 8개 필드 (외부 클래스 8개, 중첩 Record 클래스 4개)
|
||||
|
||||
// 본문 공통 메타 (application.yml에서 자동 설정)
|
||||
@Schema(description = "정보시스템ID (자동설정: old.vmis.system.infoSysId)", example = "41-345")
|
||||
@JsonProperty("INFO_SYS_ID")
|
||||
private String infoSysId;
|
||||
|
||||
@Schema(description = "정보시스템IP (자동설정: old.vmis.system.infoSysIp)", example = "105.19.10.135")
|
||||
@JsonProperty("INFO_SYS_IP")
|
||||
private String infoSysIp;
|
||||
|
||||
@Schema(description = "시군구코드 (자동설정: old.vmis.system.sigunguCode)", example = "41460")
|
||||
@JsonProperty("SIGUNGU_CODE")
|
||||
private String sigunguCode;
|
||||
|
||||
// 서비스별 필드 (application.yml에서 자동 설정)
|
||||
@Schema(description = "연계정보코드 (자동설정: old.vmis.gov.services.basic.cntcInfoCode)", example = "AC1_FD11_01")
|
||||
@JsonProperty("CNTC_INFO_CODE")
|
||||
private String cntcInfoCode;
|
||||
|
||||
@Schema(description = "담당자ID (자동설정: old.vmis.system.chargerId)", example = "")
|
||||
@JsonProperty("CHARGER_ID")
|
||||
private String chargerId;
|
||||
|
||||
@Schema(description = "담당자IP (자동설정: old.vmis.system.chargerIp)", example = "")
|
||||
@JsonProperty("CHARGER_IP")
|
||||
private String chargerIp;
|
||||
|
||||
@Schema(description = "담당자명 (자동설정: old.vmis.system.chargerNm)", example = "")
|
||||
@JsonProperty("CHARGER_NM")
|
||||
private String chargerNm;
|
||||
|
||||
@Schema(description = "조회 대상 record 배열")
|
||||
@JsonProperty("record")
|
||||
private java.util.List<Record> record;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@Getter
|
||||
@Setter
|
||||
@Schema(name = "OldBasicRequest.Record", description = "기본사항 요청 record 항목 (구버전)")
|
||||
public static class Record {
|
||||
@Schema(description = "부과기준일", example = "20250101")
|
||||
@JsonProperty("LEVY_STDDE")
|
||||
private String levyStdde;
|
||||
|
||||
@Schema(description = "조회구분코드 (자동설정: VHRNO not null → 3:자동차번호, VIN not null → 2:차대번호)")
|
||||
@JsonProperty("INQIRE_SE_CODE")
|
||||
private String inqireSeCode;
|
||||
|
||||
@Schema(description = "자동차등록번호", example = "12가3456")
|
||||
@JsonProperty("VHRNO")
|
||||
private String vhrno;
|
||||
|
||||
@Schema(description = "차대번호", example = "KMHAB812345678901")
|
||||
@JsonProperty("VIN")
|
||||
private String vin;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,208 @@
|
||||
package go.kr.project.api.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@Schema(description = "자동차기본사항조회 응답 모델")
|
||||
@Getter
|
||||
@Setter
|
||||
public class BasicResponse {
|
||||
|
||||
/** 연계결과코드 */
|
||||
@JsonProperty("CNTC_RESULT_CODE")
|
||||
private String cntcResultCode;
|
||||
|
||||
/** 연계결과상세 */
|
||||
@JsonProperty("CNTC_RESULT_DTLS")
|
||||
private String cntcResultDtls;
|
||||
|
||||
/** 레코드 목록 */
|
||||
@JsonProperty("record")
|
||||
private List<Record> record;
|
||||
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@Schema(name = "BasicRecord", description = "기본사항 record 항목")
|
||||
@Getter
|
||||
@Setter
|
||||
public static class Record {
|
||||
/** 생산년도 */
|
||||
@JsonProperty("PRYE") private String prye;
|
||||
/** 등록일자 */
|
||||
@JsonProperty("REGIST_DE") private String registDe;
|
||||
/** 말소등록구분코드 */
|
||||
@JsonProperty("ERSR_REGIST_SE_CODE") private String ersrRegistSeCode;
|
||||
/** 말소등록구분명 */
|
||||
@JsonProperty("ERSR_REGIST_SE_NM") private String ersrRegistSeNm;
|
||||
/** 말소등록일자 */
|
||||
@JsonProperty("ERSR_REGIST_DE") private String ersrRegistDe;
|
||||
/** 등록상세코드 */
|
||||
@JsonProperty("REGIST_DETAIL_CODE") private String registDetailCode;
|
||||
/** 배기량 */
|
||||
@JsonProperty("DSPLVL") private String dsplvl;
|
||||
/** 사용본거지법정동코드 */
|
||||
@JsonProperty("USE_STRNGHLD_LEGALDONG_CODE") private String useStrnghldLegaldongCode;
|
||||
/** 사용본거지행정동코드 */
|
||||
@JsonProperty("USE_STRNGHLD_ADSTRD_CODE") private String useStrnghldAdstrdCode;
|
||||
/** 사용본거지산 */
|
||||
@JsonProperty("USE_STRNGHLD_MNTN") private String useStrnghldMntn;
|
||||
/** 사용본거지번지 */
|
||||
@JsonProperty("USE_STRNGHLD_LNBR") private String useStrnghldLnbr;
|
||||
/** 사용본거지호 */
|
||||
@JsonProperty("USE_STRNGHLD_HO") private String useStrnghldHo;
|
||||
/** 사용본거지주소명 */
|
||||
@JsonProperty("USE_STRNGHLD_ADRES_NM") private String useStrnghldAdresNm;
|
||||
/** 사용본거지도로명코드 */
|
||||
@JsonProperty("USE_STRNGHLD_ROAD_NM_CODE") private String useStrnghldRoadNmCode;
|
||||
/** 사용본거지지하건물구분코드 */
|
||||
@JsonProperty("USGSRHLD_UNDGRND_BULD_SE_CODE") private String usgsrhldUndgrndBuldSeCode;
|
||||
/** 사용본거지건물본번 */
|
||||
@JsonProperty("USE_STRNGHLD_BULD_MAIN_NO") private String useStrnghldBuldMainNo;
|
||||
/** 사용본거지건물부번 */
|
||||
@JsonProperty("USE_STRNGHLD_BULD_SUB_NO") private String useStrnghldBuldSubNo;
|
||||
/** 사용본거지주소전체 */
|
||||
@JsonProperty("USGSRHLD_ADRES_FULL") private String usgsrhldAdresFull;
|
||||
/** 소유자구분코드 */
|
||||
@JsonProperty("MBER_SE_CODE") private String mberSeCode;
|
||||
/** 소유자명 */
|
||||
@JsonProperty("MBER_NM") private String mberNm;
|
||||
/** 소유자구분번호 */
|
||||
@JsonProperty("MBER_SE_NO") private String mberSeNo;
|
||||
/** 전화번호 */
|
||||
@JsonProperty("TELNO") private String telno;
|
||||
/** 소유자법정동코드 */
|
||||
@JsonProperty("OWNER_LEGALDONG_CODE") private String ownerLegaldongCode;
|
||||
/** 소유자행정동코드 */
|
||||
@JsonProperty("OWNER_ADSTRD_CODE") private String ownerAdstrdCode;
|
||||
/** 소유자산 */
|
||||
@JsonProperty("OWNER_MNTN") private String ownerMntn;
|
||||
/** 소유자번지 */
|
||||
@JsonProperty("OWNER_LNBR") private String ownerLnbr;
|
||||
/** 소유자호 */
|
||||
@JsonProperty("OWNER_HO") private String ownerHo;
|
||||
/** 소유자주소명 */
|
||||
@JsonProperty("OWNER_ADRES_NM") private String ownerAdresNm;
|
||||
/** 소유자도로명코드 */
|
||||
@JsonProperty("OWNER_ROAD_NM_CODE") private String ownerRoadNmCode;
|
||||
/** 소유자지하건물구분코드 */
|
||||
@JsonProperty("OWNER_UNDGRND_BULD_SE_CODE") private String ownerUndgrndBuldSeCode;
|
||||
/** 소유자건물본번 */
|
||||
@JsonProperty("OWNER_BULD_MAIN_NO") private String ownerBuldMainNo;
|
||||
/** 소유자건물부번 */
|
||||
@JsonProperty("OWNER_BULD_SUB_NO") private String ownerBuldSubNo;
|
||||
/** 소유자주소전체 */
|
||||
@JsonProperty("OWNER_ADRES_FULL") private String ownerAdresFull;
|
||||
/** 변경후차량번호 */
|
||||
@JsonProperty("AFTR_VHRNO") private String aftrVhrno;
|
||||
/** 사용연료코드 */
|
||||
@JsonProperty("USE_FUEL_CODE") private String useFuelCode;
|
||||
/** 용도구분코드 */
|
||||
@JsonProperty("PRPOS_SE_CODE") private String prposSeCode;
|
||||
/** 제작사명 */
|
||||
@JsonProperty("MTRS_FOM_NM") private String mtrsFomNm;
|
||||
/** 변경전차량번호 */
|
||||
@JsonProperty("FRNT_VHRNO") private String frntVhrno;
|
||||
/** 차량번호 */
|
||||
@JsonProperty("VHRNO") private String vhrno;
|
||||
/** 차대번호 */
|
||||
@JsonProperty("VIN") private String vin;
|
||||
/** 차명 */
|
||||
@JsonProperty("CNM") private String cnm;
|
||||
/** 차량총중량 */
|
||||
@JsonProperty("VHCLE_TOT_WT") private String vhcleTotWt;
|
||||
/** 자동차보험종료일자 */
|
||||
@JsonProperty("CAAG_ENDDE") private String caagEndde;
|
||||
/** 변경일자 */
|
||||
@JsonProperty("CHANGE_DE") private String changeDe;
|
||||
/** 차종분류코드 */
|
||||
@JsonProperty("VHCTY_ASORT_CODE") private String vhctyAsortCode;
|
||||
/** 차종유형코드 */
|
||||
@JsonProperty("VHCTY_TY_CODE") private String vhctyTyCode;
|
||||
/** 차종구분코드 */
|
||||
@JsonProperty("VHCTY_SE_CODE") private String vhctySeCode;
|
||||
/** 최대적재량 */
|
||||
@JsonProperty("MXMM_LDG") private String mxmmLdg;
|
||||
/** 차종분류명 */
|
||||
@JsonProperty("VHCTY_ASORT_NM") private String vhctyAsortNm;
|
||||
/** 차종유형명 */
|
||||
@JsonProperty("VHCTY_TY_NM") private String vhctyTyNm;
|
||||
/** 차종구분명 */
|
||||
@JsonProperty("VHCTY_SE_NM") private String vhctySeNm;
|
||||
/** 최초등록일자 */
|
||||
@JsonProperty("FRST_REGIST_DE") private String frstRegistDe;
|
||||
/** 형식명 */
|
||||
@JsonProperty("FOM_NM") private String fomNm;
|
||||
/** 취득일자 */
|
||||
@JsonProperty("ACQS_DE") private String acqsDe;
|
||||
/** 취득종료일자 */
|
||||
@JsonProperty("ACQS_END_DE") private String acqsEndDe;
|
||||
/** 연식월 */
|
||||
@JsonProperty("YBL_MD") private String yblMd;
|
||||
/** 이전등록일자 */
|
||||
@JsonProperty("TRANSR_REGIST_DE") private String transrRegistDe;
|
||||
/** 특정등록상태코드 */
|
||||
@JsonProperty("SPCF_REGIST_STTUS_CODE") private String spcfRegistSttusCode;
|
||||
/** 색상명 */
|
||||
@JsonProperty("COLOR_NM") private String colorNm;
|
||||
/** 저당건수 */
|
||||
@JsonProperty("MRTG_CO") private String mrtgCo;
|
||||
/** 압류건수 */
|
||||
@JsonProperty("SEIZR_CO") private String seizrCo;
|
||||
/** 압인건수 */
|
||||
@JsonProperty("STMD_CO") private String stmdCo;
|
||||
/** 번호판보관여부 */
|
||||
@JsonProperty("NMPL_CSDY_AT") private String nmplCsdyAt;
|
||||
/** 번호판보관반납일자 */
|
||||
@JsonProperty("NMPL_CSDY_REMNR_DE") private String nmplCsdyRemnrDe;
|
||||
/** 원산지구분코드 */
|
||||
@JsonProperty("ORIGIN_SE_CODE") private String originSeCode;
|
||||
/** 번호판규격코드 */
|
||||
@JsonProperty("NMPL_STNDRD_CODE") private String nmplStndrdCode;
|
||||
/** 취득금액 */
|
||||
@JsonProperty("ACQS_AMOUNT") private String acqsAmount;
|
||||
/** 검사유효기간시작일자 */
|
||||
@JsonProperty("INSPT_VALID_PD_BGNDE") private String insptValidPdBgnde;
|
||||
/** 검사유효기간종료일자 */
|
||||
@JsonProperty("INSPT_VALID_PD_ENDDE") private String insptValidPdEndde;
|
||||
/** 사용본거지우편번호코드 */
|
||||
@JsonProperty("USE_STRNGHLD_GRC_CODE") private String useStrnghldGrcCode;
|
||||
/** 화물차승차정원수 */
|
||||
@JsonProperty("TKCAR_PSCAP_CO") private String tkcarPscapCo;
|
||||
/** 사양번호 */
|
||||
@JsonProperty("SPMNNO") private String spmnno;
|
||||
/** 주행거리 */
|
||||
@JsonProperty("TRVL_DSTNC") private String trvlDstnc;
|
||||
/** 최초등록신청번호 */
|
||||
@JsonProperty("FRST_REGIST_RQRCNO") private String frstRegistRqrcno;
|
||||
/** 자진말소예방공지일자 */
|
||||
@JsonProperty("VLNT_ERSR_PRVNTC_NTICE_DE") private String vlntErsrPrvntcNticeDe;
|
||||
/** 등록기관명 */
|
||||
@JsonProperty("REGIST_INSTT_NM") private String registInsttNm;
|
||||
/** 처리불가사유코드 */
|
||||
@JsonProperty("PROCESS_IMPRTY_RESN_CODE") private String processImprtyResnCode;
|
||||
/** 처리불가사유상세 */
|
||||
@JsonProperty("PROCESS_IMPRTY_RESN_DTLS") private String processImprtyResnDtls;
|
||||
/** 차체길이 */
|
||||
@JsonProperty("CBD_LT") private String cbdLt;
|
||||
/** 차체너비 */
|
||||
@JsonProperty("CBD_BT") private String cbdBt;
|
||||
/** 차체높이 */
|
||||
@JsonProperty("CBD_HG") private String cbdHg;
|
||||
/** 최초최대적재량 */
|
||||
@JsonProperty("FRST_MXMM_LDG") private String frstMxmmLdg;
|
||||
/** 연료소비율 */
|
||||
@JsonProperty("FUEL_CNSMP_RT") private String fuelCnsmpRt;
|
||||
/** 전기복합연료소비율 */
|
||||
@JsonProperty("ELCTY_CMPND_FUEL_CNSMP_RT") private String elctyCmpndFuelCnsmpRt;
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,324 @@
|
||||
package go.kr.project.api.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@Schema(description = "자동차등록원부(갑) 응답 모델")
|
||||
@Getter
|
||||
@Setter
|
||||
public class LedgerResponse {
|
||||
|
||||
/** 연계결과코드 */
|
||||
@JsonProperty("CNTC_RESULT_CODE")
|
||||
private String cntcResultCode;
|
||||
|
||||
/** 연계결과상세 */
|
||||
@JsonProperty("CNTC_RESULT_DTLS")
|
||||
private String cntcResultDtls;
|
||||
|
||||
/** 원부그룹번호 */
|
||||
@JsonProperty("LEDGER_GROUP_NO")
|
||||
private String ledgerGroupNo;
|
||||
|
||||
/** 원부개별화번호 */
|
||||
@JsonProperty("LEDGER_INDVDLZ_NO")
|
||||
private String ledgerIndvdlzNo;
|
||||
|
||||
/** 차량관리번호 */
|
||||
@JsonProperty("VHMNO")
|
||||
private String vhmno;
|
||||
|
||||
/** 차량번호 */
|
||||
@JsonProperty("VHRNO")
|
||||
private String vhrno;
|
||||
|
||||
/** 차대번호 */
|
||||
@JsonProperty("VIN")
|
||||
private String vin;
|
||||
|
||||
/** 차종분류코드 */
|
||||
@JsonProperty("VHCTY_ASORT_CODE")
|
||||
private String vhctyAsortCode;
|
||||
|
||||
/** 차종분류명 */
|
||||
@JsonProperty("VHCTY_ASORT_NM")
|
||||
private String vhctyAsortNm;
|
||||
|
||||
/** 차명 */
|
||||
@JsonProperty("CNM")
|
||||
private String cnm;
|
||||
|
||||
/** 색상코드 */
|
||||
@JsonProperty("COLOR_CODE")
|
||||
private String colorCode;
|
||||
|
||||
/** 색상명 */
|
||||
@JsonProperty("COLOR_NM")
|
||||
private String colorNm;
|
||||
|
||||
/** 번호판규격코드 */
|
||||
@JsonProperty("NMPL_STNDRD_CODE")
|
||||
private String nmplStndrdCode;
|
||||
|
||||
/** 번호판규격명 */
|
||||
@JsonProperty("NMPL_STNDRD_NM")
|
||||
private String nmplStndrdNm;
|
||||
|
||||
/** 용도구분코드 */
|
||||
@JsonProperty("PRPOS_SE_CODE")
|
||||
private String prposSeCode;
|
||||
|
||||
/** 용도구분명 */
|
||||
@JsonProperty("PRPOS_SE_NM")
|
||||
private String prposSeNm;
|
||||
|
||||
/** 제작사명 */
|
||||
@JsonProperty("MTRS_FOM_NM")
|
||||
private String mtrsFomNm;
|
||||
|
||||
/** 형식명 */
|
||||
@JsonProperty("FOM_NM")
|
||||
private String fomNm;
|
||||
|
||||
/** 취득금액 */
|
||||
@JsonProperty("ACQS_AMOUNT")
|
||||
private String acqsAmount;
|
||||
|
||||
/** 등록상세코드 */
|
||||
@JsonProperty("REGIST_DETAIL_CODE")
|
||||
private String registDetailCode;
|
||||
|
||||
/** 등록상세명 */
|
||||
@JsonProperty("REGIST_DETAIL_NM")
|
||||
private String registDetailNm;
|
||||
|
||||
/** 최초등록일자 */
|
||||
@JsonProperty("FRST_REGIST_DE")
|
||||
private String frstRegistDe;
|
||||
|
||||
/** 자동차보험종료일자 */
|
||||
@JsonProperty("CAAG_ENDDE")
|
||||
private String caagEndde;
|
||||
|
||||
/** 생산년도 */
|
||||
@JsonProperty("PRYE")
|
||||
private String prye;
|
||||
|
||||
/** 사양번호1 */
|
||||
@JsonProperty("SPMNNO1")
|
||||
private String spmnno1;
|
||||
|
||||
/** 사양번호2 */
|
||||
@JsonProperty("SPMNNO2")
|
||||
private String spmnno2;
|
||||
|
||||
/** 연식월 */
|
||||
@JsonProperty("YBL_MD")
|
||||
private String yblMd;
|
||||
|
||||
/** 주행거리 */
|
||||
@JsonProperty("TRVL_DSTNC")
|
||||
private String trvlDstnc;
|
||||
|
||||
/** 검사유효기간시작일자 */
|
||||
@JsonProperty("INSPT_VALID_PD_BGNDE")
|
||||
private String insptValidPdBgnde;
|
||||
|
||||
/** 검사유효기간종료일자 */
|
||||
@JsonProperty("INSPT_VALID_PD_ENDDE")
|
||||
private String insptValidPdEndde;
|
||||
|
||||
/** 점검유효기간시작일자 */
|
||||
@JsonProperty("CHCK_VALID_PD_BGNDE")
|
||||
private String chckValidPdBgnde;
|
||||
|
||||
/** 점검유효기간종료일자 */
|
||||
@JsonProperty("CHCK_VALID_PD_ENDDE")
|
||||
private String chckValidPdEndde;
|
||||
|
||||
/** 등록신청구분명 */
|
||||
@JsonProperty("REGIST_REQST_SE_NM")
|
||||
private String registReqstSeNm;
|
||||
|
||||
/** 최초등록신청번호 */
|
||||
@JsonProperty("FRST_REGIST_RQRCNO")
|
||||
private String frstRegistRqrcno;
|
||||
|
||||
/** 번호판보관반납일자 */
|
||||
@JsonProperty("NMPL_CSDY_REMNR_DE")
|
||||
private String nmplCsdyRemnrDe;
|
||||
|
||||
/** 번호판보관여부 */
|
||||
@JsonProperty("NMPL_CSDY_AT")
|
||||
private String nmplCsdyAt;
|
||||
|
||||
/** 영업용사용기간 */
|
||||
@JsonProperty("BSS_USE_PD")
|
||||
private String bssUsePd;
|
||||
|
||||
/** 직권말소예방공지일자 */
|
||||
@JsonProperty("OCTHT_ERSR_PRVNTC_NTICE_DE")
|
||||
private String octhtErsrPrvntcNticeDe;
|
||||
|
||||
/** 말소등록일자 */
|
||||
@JsonProperty("ERSR_REGIST_DE")
|
||||
private String ersrRegistDe;
|
||||
|
||||
/** 말소등록구분코드 */
|
||||
@JsonProperty("ERSR_REGIST_SE_CODE")
|
||||
private String ersrRegistSeCode;
|
||||
|
||||
/** 말소등록구분명 */
|
||||
@JsonProperty("ERSR_REGIST_SE_NM")
|
||||
private String ersrRegistSeNm;
|
||||
|
||||
/** 저당건수 */
|
||||
@JsonProperty("MRTGCNT")
|
||||
private String mrtgcnt;
|
||||
|
||||
/** 차량건수 */
|
||||
@JsonProperty("VHCLECNT")
|
||||
private String vhclecnt;
|
||||
|
||||
/** 압인건수 */
|
||||
@JsonProperty("STMDCNT")
|
||||
private String stmdcnt;
|
||||
|
||||
/** 주소1 */
|
||||
@JsonProperty("ADRES1")
|
||||
private String adres1;
|
||||
|
||||
/** 주소명1 */
|
||||
@JsonProperty("ADRES_NM1")
|
||||
private String adresNm1;
|
||||
|
||||
/** 주소 */
|
||||
@JsonProperty("ADRES")
|
||||
private String adres;
|
||||
|
||||
/** 주소명 */
|
||||
@JsonProperty("ADRES_NM")
|
||||
private String adresNm;
|
||||
|
||||
/** 개인법인여부 */
|
||||
@JsonProperty("INDVDL_BSNM_AT")
|
||||
private String indvdlBsnmAt;
|
||||
|
||||
/** 전화번호 */
|
||||
@JsonProperty("TELNO")
|
||||
private String telno;
|
||||
|
||||
/** 소유자명 */
|
||||
@JsonProperty("MBER_NM")
|
||||
private String mberNm;
|
||||
|
||||
/** 소유자구분코드 */
|
||||
@JsonProperty("MBER_SE_CODE")
|
||||
private String mberSeCode;
|
||||
|
||||
/** 소유자구분번호 */
|
||||
@JsonProperty("MBER_SE_NO")
|
||||
private String mberSeNo;
|
||||
|
||||
/** 면세대상자구분코드 */
|
||||
@JsonProperty("TAXXMPT_TRGTER_SE_CODE")
|
||||
private String taxxmptTrgterSeCode;
|
||||
|
||||
/** 면세대상자구분코드명 */
|
||||
@JsonProperty("TAXXMPT_TRGTER_SE_CODE_NM")
|
||||
private String taxxmptTrgterSeCodeNm;
|
||||
|
||||
/** 건수사항 */
|
||||
@JsonProperty("CNT_MATTER")
|
||||
private String cntMatter;
|
||||
|
||||
/** 읍면동명 */
|
||||
@JsonProperty("EMD_NM")
|
||||
private String emdNm;
|
||||
|
||||
/** 예방건수 */
|
||||
@JsonProperty("PRVNTCCNT")
|
||||
private String prvntccnt;
|
||||
|
||||
/** 수출이행여부확인일자 */
|
||||
@JsonProperty("XPORT_FLFL_AT_STTEMNT_DE")
|
||||
private String xportFlflAtSttemntDe;
|
||||
|
||||
/** 협력사신청번호 */
|
||||
@JsonProperty("PARTN_RQRCNO")
|
||||
private String partnRqrcno;
|
||||
|
||||
/** 레코드 목록 */
|
||||
@JsonProperty("record")
|
||||
private List<Record> record;
|
||||
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@Schema(name = "LedgerRecord", description = "원부 변경내역 record")
|
||||
@Getter
|
||||
@Setter
|
||||
public static class Record {
|
||||
/** 메인체크 */
|
||||
@JsonProperty("MAINCHK") private String mainchk;
|
||||
/** 변경작업구분코드 */
|
||||
@JsonProperty("CHANGE_JOB_SE_CODE") private String changeJobSeCode;
|
||||
/** 주번호 */
|
||||
@JsonProperty("MAINNO") private String mainno;
|
||||
/** 부번호 */
|
||||
@JsonProperty("SUBNO") private String subno;
|
||||
/** 상세내역 */
|
||||
@JsonProperty("DTLS") private String dtls;
|
||||
/** 신청번호 */
|
||||
@JsonProperty("RQRCNO") private String rqrcno;
|
||||
/** 차량관리번호 */
|
||||
@JsonProperty("VHMNO") private String vhmno;
|
||||
/** 원부그룹번호 */
|
||||
@JsonProperty("LEDGER_GROUP_NO") private String ledgerGroupNo;
|
||||
/** 원부개별화번호 */
|
||||
@JsonProperty("LEDGER_INDVDLZ_NO") private String ledgerIndvdlzNo;
|
||||
/** 구분명 */
|
||||
@JsonProperty("GUBUN_NM") private String gubunNm;
|
||||
/** 변경일자 */
|
||||
@JsonProperty("CHANGE_DE") private String changeDe;
|
||||
/** 상세일련번호 */
|
||||
@JsonProperty("DETAIL_SN") private String detailSn;
|
||||
/** 플래그 */
|
||||
@JsonProperty("FLAG") private String flag;
|
||||
|
||||
public String getMainchk() { return mainchk; }
|
||||
public void setMainchk(String mainchk) { this.mainchk = mainchk; }
|
||||
public String getChangeJobSeCode() { return changeJobSeCode; }
|
||||
public void setChangeJobSeCode(String changeJobSeCode) { this.changeJobSeCode = changeJobSeCode; }
|
||||
public String getMainno() { return mainno; }
|
||||
public void setMainno(String mainno) { this.mainno = mainno; }
|
||||
public String getSubno() { return subno; }
|
||||
public void setSubno(String subno) { this.subno = subno; }
|
||||
public String getDtls() { return dtls; }
|
||||
public void setDtls(String dtls) { this.dtls = dtls; }
|
||||
public String getRqrcno() { return rqrcno; }
|
||||
public void setRqrcno(String rqrcno) { this.rqrcno = rqrcno; }
|
||||
public String getVhmno() { return vhmno; }
|
||||
public void setVhmno(String vhmno) { this.vhmno = vhmno; }
|
||||
public String getLedgerGroupNo() { return ledgerGroupNo; }
|
||||
public void setLedgerGroupNo(String ledgerGroupNo) { this.ledgerGroupNo = ledgerGroupNo; }
|
||||
public String getLedgerIndvdlzNo() { return ledgerIndvdlzNo; }
|
||||
public void setLedgerIndvdlzNo(String ledgerIndvdlzNo) { this.ledgerIndvdlzNo = ledgerIndvdlzNo; }
|
||||
public String getGubunNm() { return gubunNm; }
|
||||
public void setGubunNm(String gubunNm) { this.gubunNm = gubunNm; }
|
||||
public String getChangeDe() { return changeDe; }
|
||||
public void setChangeDe(String changeDe) { this.changeDe = changeDe; }
|
||||
public String getDetailSn() { return detailSn; }
|
||||
public void setDetailSn(String detailSn) { this.detailSn = detailSn; }
|
||||
public String getFlag() { return flag; }
|
||||
public void setFlag(String flag) { this.flag = flag; }
|
||||
}
|
||||
}
|
||||
@ -1,136 +0,0 @@
|
||||
package go.kr.project.api.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 자동차기본사항조회 응답 모델 (신버전)
|
||||
*
|
||||
* <p>
|
||||
* 국토교통부 → 지자체 응답 규격을 매핑한 모델입니다. 상위에 연계결과 정보가 오고,
|
||||
* 상세 데이터는 record 배열로 전달됩니다.
|
||||
* </p>
|
||||
*/
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@Schema(description = "자동차기본사항조회 응답 모델 (신버전)")
|
||||
@Getter
|
||||
@Setter
|
||||
public class NewBasicResponse { // 총 3개 필드 (외부 클래스 3개, 중첩 Record 클래스 84개)
|
||||
|
||||
/** LOG 생성 키 (내부 처리용) */
|
||||
private String generatedId;
|
||||
|
||||
/** 트랜잭션 ID (내부 처리용) */
|
||||
private String txId;
|
||||
|
||||
/** 연계결과코드 (성공/실패 코드) */
|
||||
@JsonProperty("LINK_RSLT_CD")
|
||||
private String linkRsltCd;
|
||||
|
||||
/** 연계결과상세 (에러 메시지 등 상세 사유) */
|
||||
@JsonProperty("LINK_RSLT_DTL")
|
||||
private String linkRsltDtl;
|
||||
|
||||
/** 응답 레코드 목록 */
|
||||
@JsonProperty("record")
|
||||
private List<Record> record;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@Schema(name = "NewBasicRecord", description = "기본사항 record 항목 (신버전)")
|
||||
@Getter
|
||||
@Setter
|
||||
public static class Record {
|
||||
@JsonProperty("VHRNO") private String vhrno; // 차량번호
|
||||
@JsonProperty("ATMB_NM") private String atmbNm; // 차명
|
||||
@JsonProperty("RPRS_OWNR_NM") private String rprsOwnrNm; // 대표소유자성명
|
||||
@JsonProperty("RPRSV_OWNR_IDECNO") private String rprsvOwnrIdecno; // 대표소유자회원번호
|
||||
@JsonProperty("ERSR_REG_YMD") private String ersrRegYmd; // 말소등록일
|
||||
@JsonProperty("PRCS_IMPRTY_RSN_CD") private String prcsImprtyRsnCd; // 처리불가사유코드
|
||||
@JsonProperty("PRCS_IMPRTY_RSN_DTLS") private String prcsImprtyRsnDtls; // 처리불가사유명세
|
||||
@JsonProperty("YRIDNW") private String yridnw; // 연식
|
||||
@JsonProperty("VIN") private String vin; // 차대번호
|
||||
@JsonProperty("CARMDL_ASORT_NM") private String carmdlAsortNm; // 차종종별명
|
||||
@JsonProperty("FRST_REG_YMD") private String frstRegYmd; // 최초등록일
|
||||
@JsonProperty("COLOR_NM") private String colorNm; // 색상명
|
||||
@JsonProperty("STRCT_CHG_CNT") private String strctChgCnt; // 구조변경수
|
||||
@JsonProperty("NOPLT_CSDY_YN") private String noplTcsdyYn; // 번호판영치여부
|
||||
@JsonProperty("NOPLT_CSDY_AVTSMT_YMD") private String noplTcsdyAvtsmtYmd; // 번호판영치최고일
|
||||
@JsonProperty("INSP_VLD_PD_BGNG_YMD") private String inspVldPdBgngYmd; // 검사유효기간시작일
|
||||
@JsonProperty("INSP_VLD_PD_END_YMD") private String inspVldPdEndYmd; // 검사유효기간종료일
|
||||
@JsonProperty("SPMNNO") private String spmnno; // 제원관리번호
|
||||
@JsonProperty("DRVNG_DSTNC") private String drvngDstnc; // 주행거리
|
||||
@JsonProperty("FOM_NM") private String fomNm; // 형식
|
||||
@JsonProperty("DSPLVL") private String dsplvl; // 배기량
|
||||
@JsonProperty("CARMDL_CLSF_NM") private String carmdlClsfNm; // 차종분류명
|
||||
@JsonProperty("FBCTN_YMD") private String fbctnYmd; // 제작년월일
|
||||
@JsonProperty("USGSRHLD_ADDR_NM") private String usgsrhldAddrNm; // 사용본거지상세주소
|
||||
@JsonProperty("MTRS_FOM_NM") private String mtrsFomNm; // 원동기형식명
|
||||
@JsonProperty("RDCPCT_CNT") private String rdcpctCnt; // 승차정원수
|
||||
@JsonProperty("FRST_REG_APLY_RCPT_NO") private String frstRegAplyRcptNo; // 최초등록접수번호
|
||||
@JsonProperty("OGNZ_NM") private String ognzNm; // 등록기관명
|
||||
@JsonProperty("ERSR_REG_SE_NM") private String ersrRegSeNm; // 말소등록구분명
|
||||
@JsonProperty("BFR_VHRNO") private String bfrVhrno; // 이전차량번호
|
||||
@JsonProperty("USE_FUEL_CD") private String useFuelCd; // 사용연료코드
|
||||
@JsonProperty("RPRS_OWNR_MBR_SE_CD") private String rprsOwnrMbrSeCd; // 대표소유자회원구분코드
|
||||
@JsonProperty("RPRS_OWNR_TELNO") private String rprsOwnrTelno; // 대표소유자전화번호
|
||||
@JsonProperty("OWNR_STDG_CD") private String ownrStdgCd; // 소유자법정동코드
|
||||
@JsonProperty("OWNR_WHOL_ADDR") private String ownrWholAddr; // 소유자전체주소
|
||||
@JsonProperty("VHCL_TOTL_WT") private String vhclTotlWt; // 차량총중량
|
||||
@JsonProperty("MXMM_LDG") private String mxmmLdg; // 최대적재량
|
||||
@JsonProperty("CBD_LT") private String cbdLt; // 차체길이
|
||||
@JsonProperty("CBD_BT") private String cbdBt; // 차체너비
|
||||
@JsonProperty("CBD_HG") private String cbdHg; // 차체높이
|
||||
@JsonProperty("CARMDL_ASORT_CD") private String carmdlAsortCd; // 차종종별코드
|
||||
@JsonProperty("CARMDL_TYPE_CD") private String carmdlTypeCd; // 차종유형코드
|
||||
@JsonProperty("FUEL_CNSMPRT") private String fuelCnsmprt; // 연료소비율
|
||||
@JsonProperty("ERSR_REG_SE_CD") private String ersrRegSeCd; // 말소등록구분코드
|
||||
@JsonProperty("REG_DTL_CD") private String regDtlCd; // 등록상세코드
|
||||
@JsonProperty("USGSRHLD_STDG_CD") private String usgsrhldStdgCd; // 사용본거지법정동코드
|
||||
@JsonProperty("USGSRHLD_DONG_CD") private String usgsrhldDongCd; // 사용본거지행정동코드
|
||||
@JsonProperty("USGSRHLD_MTN_YN") private String usgsrhldMtnYn; // 사용본거지산 여부
|
||||
@JsonProperty("USGSRHLD_LNBR") private String usgsrhldLnbr; // 사용본거지번지
|
||||
@JsonProperty("USGSRHLD_HO") private String usgsrhldHo; // 사용본거지호
|
||||
@JsonProperty("USGSRHLD_ROAD_NM_CD") private String usgsrhldRoadNmCd; // 사용본거지도로명코드
|
||||
@JsonProperty("USGSRHLD_UDGD_BLDG_SE_CD") private String usgsrhldUdgdBldgSeCd; // 사용본거지지하건물구분코드
|
||||
@JsonProperty("USGSRHLD_BMNO") private String usgsrhldBmno; // 사용본거지건물주요번호
|
||||
@JsonProperty("USGSRHLD_BSNO") private String usgsrhldBsno; // 사용본거지건물부번호
|
||||
@JsonProperty("OWNR_DONG_CD") private String ownrDongCd; // 소유자행정동코드
|
||||
@JsonProperty("OWNR_MTN_YN") private String ownrMtnYn; // 소유자산 여부
|
||||
@JsonProperty("OWNR_LNBR") private String ownrLnbr; // 소유자번지
|
||||
@JsonProperty("OWNR_HO") private String ownrHo; // 소유자호
|
||||
@JsonProperty("OWNR_ADDR_NM") private String ownrAddrNm; // 소유자상세주소
|
||||
@JsonProperty("OWNR_ROAD_NM_CD") private String ownrRoadNmCd; // 소유자도로명코드
|
||||
@JsonProperty("OWNR_UDGD_BLDG_SE_CD") private String ownrUdgdBldgSeCd; // 소유자지하건물구분코드
|
||||
@JsonProperty("OWNR_BMNO") private String ownrBmno; // 소유자건물주요번호
|
||||
@JsonProperty("OWNR_BSNO") private String ownrBsno; // 소유자건물부번호
|
||||
@JsonProperty("REAR_VHRNO") private String rearVhrno; // 신차량번호
|
||||
@JsonProperty("USG_SE_CD") private String usgSeCd; // 용도구분코드
|
||||
@JsonProperty("VEAG_END_YMD") private String veagEndYmd; // 차령만료일자
|
||||
@JsonProperty("CHG_YMD") private String chgYmd; // 차번호변경시기
|
||||
@JsonProperty("CARMDL_SE_CD") private String carmdlSeCd; // 차종분류코드
|
||||
@JsonProperty("CARMDL_TYPE_NM") private String carmdlTypeNm; // 차종유형명
|
||||
@JsonProperty("ACQS_YMD") private String acqsYmd; // 취득일자
|
||||
@JsonProperty("ACQS_END_YMD") private String acqsEndYmd; // 취득종료일자
|
||||
@JsonProperty("TRANSR_REG_YMD") private String transrRegYmd; // 이전등록일(양수일)
|
||||
@JsonProperty("SPCF_REG_STTS_CD") private String spcfRegSttsCd; // 제원등록상태코드
|
||||
@JsonProperty("SRC_SE_CD") private String srcSeCd; // 출처구분코드
|
||||
@JsonProperty("NOPLT_SPCFCT_CD") private String noplTSpcfctCd; // 번호판규격코드
|
||||
@JsonProperty("ACQS_AMT") private String acqsAmt; // 취득금액
|
||||
@JsonProperty("USGSRHLD_GRC_CD") private String usgsrhldGrcCd; // 사용본거지관청코드
|
||||
@JsonProperty("VLNT_ERSR_PRVNTC_AVTSMT_YMD") private String vlntErsrPrvntcAvtsmtYmd; // 예고통지일
|
||||
@JsonProperty("FRST_MXMM_LDG") private String frstMxmmLdg; // 최초최대적재량
|
||||
@JsonProperty("REG_YMD") private String regYmd; // 등록일(변경일)
|
||||
@JsonProperty("ELCTY_CMPND_FUEL_CNSMPRT") private String elctyCmpndFuelCnsmprt; // 전기복합연료소비율
|
||||
@JsonProperty("USGSRHLD_WHOL_ADDR") private String usgsrhldWholAddr; // 사용본거지전체주소
|
||||
@JsonProperty("MRTG_CNT") private String mrtgCnt; // 저당수
|
||||
@JsonProperty("SZR_CNT") private String szrCnt; // 압류건수
|
||||
}
|
||||
}
|
||||
@ -1,349 +0,0 @@
|
||||
package go.kr.project.api.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@Schema(description = "자동차등록원부(갑) 응답 모델 (신버전)")
|
||||
@Getter
|
||||
@Setter
|
||||
public class NewLedgerResponse { // 총 64개 필드 (외부 클래스 66개, 중첩 Record 클래스 16개)
|
||||
|
||||
/** LOG 생성 키 (내부 처리용) */
|
||||
private String generatedId;
|
||||
|
||||
/** 트랜잭션 ID (내부 처리용) */
|
||||
private String txId;
|
||||
|
||||
@JsonProperty("LINK_RSLT_CD")
|
||||
private String linkRsltCd;
|
||||
|
||||
@JsonProperty("LINK_RSLT_DTL")
|
||||
private String linkRsltDtl;
|
||||
|
||||
/** 원부그룹번호 */
|
||||
@JsonProperty("LEDGER_GROUP_NO")
|
||||
private String ledgerGroupNo;
|
||||
|
||||
/** 원부개별번호 */
|
||||
@JsonProperty("LEDGER_INDIV_NO")
|
||||
private String ledgerIndivNo;
|
||||
|
||||
/** 차량관리번호 */
|
||||
@JsonProperty("VHMNO")
|
||||
private String vhmno;
|
||||
|
||||
/** 차량등록번호 */
|
||||
@JsonProperty("VHRNO")
|
||||
private String vhrno;
|
||||
|
||||
/** 차대번호 */
|
||||
@JsonProperty("VIN")
|
||||
private String vin;
|
||||
|
||||
/** 차종종별코드 */
|
||||
@JsonProperty("CARMDL_ASORT_CD")
|
||||
private String carmdlAsortCd;
|
||||
|
||||
/** 차종종별명 */
|
||||
@JsonProperty("CARMDL_ASORT_NM")
|
||||
private String carmdlAsortNm;
|
||||
|
||||
/** 차명 */
|
||||
@JsonProperty("ATMB_NM")
|
||||
private String atmbNm;
|
||||
|
||||
/** 색상코드 */
|
||||
@JsonProperty("COLOR_CD")
|
||||
private String colorCd;
|
||||
|
||||
/** 색상명 */
|
||||
@JsonProperty("COLOR_NM")
|
||||
private String colorNm;
|
||||
|
||||
/** 번호판규격코드 */
|
||||
@JsonProperty("NOPLT_SPCFCT_CD")
|
||||
private String nopltSpcfctCd;
|
||||
|
||||
/** 번호판규격명 */
|
||||
@JsonProperty("NOPLT_SPCFCT_NM")
|
||||
private String nopltSpcfctNm;
|
||||
|
||||
/** 용도구분코드 */
|
||||
@JsonProperty("USG_SE_CD")
|
||||
private String usgSeCd;
|
||||
|
||||
/** 용도구분명 */
|
||||
@JsonProperty("USG_SE_NM")
|
||||
private String usgSeNm;
|
||||
|
||||
/** 원동기형식명 */
|
||||
@JsonProperty("MTRS_FOM_NM")
|
||||
private String mtrsFomNm;
|
||||
|
||||
/** 형식명 */
|
||||
@JsonProperty("FOM_NM")
|
||||
private String fomNm;
|
||||
|
||||
/** 취득금액 */
|
||||
@JsonProperty("ACQS_AMT")
|
||||
private String acqsAmt;
|
||||
|
||||
/** 등록상세코드 */
|
||||
@JsonProperty("REG_DTL_CD")
|
||||
private String regDtlCd;
|
||||
|
||||
/** 등록상세명 */
|
||||
@JsonProperty("REG_DTL_NM")
|
||||
private String regDtlNm;
|
||||
|
||||
/** 최초등록일 */
|
||||
@JsonProperty("FRST_REG_YMD")
|
||||
private String frstRegYmd;
|
||||
|
||||
/** 차령종료일 */
|
||||
@JsonProperty("VEAG_END_YMD")
|
||||
private String veagEndYmd;
|
||||
|
||||
/** 연식 */
|
||||
@JsonProperty("YRIDNW")
|
||||
private String yridnw;
|
||||
|
||||
/** 제원관리번호1 */
|
||||
@JsonProperty("SPMNNO_1")
|
||||
private String spmnno1;
|
||||
|
||||
/** 제원관리번호2 */
|
||||
@JsonProperty("SPMNNO_2")
|
||||
private String spmnno2;
|
||||
|
||||
/** 제작년월일 */
|
||||
@JsonProperty("FBCTN_YMD")
|
||||
private String fbctnYmd;
|
||||
|
||||
/** 주행거리 */
|
||||
@JsonProperty("DRVNG_DSTNC")
|
||||
private String drvngDstnc;
|
||||
|
||||
/** 검사유효기간시작일 */
|
||||
@JsonProperty("INSP_VLD_PD_BGNG_YMD")
|
||||
private String inspVldPdBgngYmd;
|
||||
|
||||
/** 검사유효기간종료일 */
|
||||
@JsonProperty("INSP_VLD_PD_END_YMD")
|
||||
private String inspVldPdEndYmd;
|
||||
|
||||
/** 점검유효기간시작일 */
|
||||
@JsonProperty("CHCK_VLD_PD_BGNG_YMD")
|
||||
private String chckVldPdBgngYmd;
|
||||
|
||||
/** 점검유효기간종료일 */
|
||||
@JsonProperty("CHCK_VLD_PD_END_YMD")
|
||||
private String chckVldPdEndYmd;
|
||||
|
||||
/** 등록신청구분명 */
|
||||
@JsonProperty("REG_APLY_SE_NM")
|
||||
private String regAplySeNm;
|
||||
|
||||
/** 최초등록접수번호 */
|
||||
@JsonProperty("FRST_REG_APLY_RCPT_NO")
|
||||
private String frstRegAplyRcptNo;
|
||||
|
||||
/** 번호판영치최고일 */
|
||||
@JsonProperty("NOPLT_CSDY_AVTSMT_YMD")
|
||||
private String nopltCsdyAvtsmtYmd;
|
||||
|
||||
/** 번호판영치여부 */
|
||||
@JsonProperty("NOPLT_CSDY_YN")
|
||||
private String nopltCsdyYn;
|
||||
|
||||
/** 사업용사용기간 */
|
||||
@JsonProperty("BSS_USE_PD_YMD")
|
||||
private String bssUsePdYmd;
|
||||
|
||||
/** 직권말소예고통지일 */
|
||||
@JsonProperty("OCTHT_ERSR_PRVNTC_AVTSMT_YMD")
|
||||
private String octhtErsrPrvntcAvtsmtYmd;
|
||||
|
||||
/** 말소등록일 */
|
||||
@JsonProperty("ERSR_REG_YMD")
|
||||
private String ersrRegYmd;
|
||||
|
||||
/** 말소등록구분코드 */
|
||||
@JsonProperty("ERSR_REG_SE_CD")
|
||||
private String ersrRegSeCd;
|
||||
|
||||
/** 말소등록구분명 */
|
||||
@JsonProperty("ERSR_REG_SE_NM")
|
||||
private String ersrRegSeNm;
|
||||
|
||||
/** 저당수 */
|
||||
@JsonProperty("MRTG_CNT")
|
||||
private String mrtgCnt;
|
||||
|
||||
/** 압류건수 */
|
||||
@JsonProperty("SZR_CNT")
|
||||
private String szrCnt;
|
||||
|
||||
/** 구조변경수 */
|
||||
@JsonProperty("STRCT_CHG_CNT")
|
||||
private String strctChgCnt;
|
||||
|
||||
/** 사용본거지주소 */
|
||||
@JsonProperty("USGSRHLD_ADDR_1")
|
||||
private String usgsrhldAddr1;
|
||||
|
||||
/** 사용본거지주소상세 */
|
||||
@JsonProperty("USGSRHLD_ADDR_DTL_1")
|
||||
private String usgsrhldAddrDtl1;
|
||||
|
||||
/** 소유자주소 */
|
||||
@JsonProperty("OWNR_ADDR")
|
||||
private String ownrAddr;
|
||||
|
||||
/** 소유자주소상세 */
|
||||
@JsonProperty("OWNR_ADDR_DTL")
|
||||
private String ownrAddrDtl;
|
||||
|
||||
/** 개인사업자여부 */
|
||||
@JsonProperty("INDVDL_BZMN_YN")
|
||||
private String indvdlBzmnYn;
|
||||
|
||||
/** 대표소유자전화번호 */
|
||||
@JsonProperty("RPRS_OWNR_TELNO")
|
||||
private String rprsOwnrTelno;
|
||||
|
||||
/** 대표소유자성명 */
|
||||
@JsonProperty("RPRS_OWNR_NM")
|
||||
private String rprsOwnrNm;
|
||||
|
||||
/** 대표소유자회원구분코드 */
|
||||
@JsonProperty("RPRS_OWNR_MBR_SE_CD")
|
||||
private String rprsOwnrMbrSeCd;
|
||||
|
||||
/** 대표소유자회원번호 */
|
||||
@JsonProperty("RPRSV_OWNR_IDECNO")
|
||||
private String rprsvOwnrIdecno;
|
||||
|
||||
/** 비과세대상구분코드명 */
|
||||
@JsonProperty("TAXXMPT_APLCN_SE_CD")
|
||||
private String taxxmptAplcnSeCd;
|
||||
|
||||
/** 비과세대상구분코드 */
|
||||
@JsonProperty("TAXXMPT_TRPR_SE_CD")
|
||||
private String taxxmptTrprSeCd;
|
||||
|
||||
/** 특기사항건수 */
|
||||
@JsonProperty("SPCABL_MTTR_CNT")
|
||||
private String spcablMttrCnt;
|
||||
|
||||
/** 사용본거지행정동명 */
|
||||
@JsonProperty("USGSRHLD_DONG_NM")
|
||||
private String usgsrhldDongNm;
|
||||
|
||||
/** 예고수 */
|
||||
@JsonProperty("PRVNTC_CNT")
|
||||
private String prvntcCnt;
|
||||
|
||||
/** 수출이행여부신고일 */
|
||||
@JsonProperty("XPORT_FLFL_YN_DCLR_YMD")
|
||||
private String xportFlflYnDclrYmd;
|
||||
|
||||
/** 발급번호 */
|
||||
@JsonProperty("ISSU_NO")
|
||||
private String issuNo;
|
||||
|
||||
/** 최초양도일 */
|
||||
@JsonProperty("FRST_TRNSFR_YMD")
|
||||
private String frstTrnsfrYmd;
|
||||
|
||||
/** 구동축전지식별번호 */
|
||||
@JsonProperty("DRIV_SRGBTRY_IDNTF_NO")
|
||||
private String drivSrgbtryIdntfNo;
|
||||
|
||||
/** 처리불가사유코드 */
|
||||
@JsonProperty("PROCESS_IMPRTY_RESN_CODE")
|
||||
private String processImprtyResnCode;
|
||||
|
||||
/** 처리불가사유상세 */
|
||||
@JsonProperty("PROCESS_IMPRTY_RESN_DTLS")
|
||||
private String processImprtyResnDtls;
|
||||
|
||||
@JsonProperty("record")
|
||||
private List<Record> record;
|
||||
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@Schema(name = "NewLedgerRecord", description = "원부 변경내역 record (신버전)")
|
||||
@Getter
|
||||
@Setter
|
||||
public static class Record {
|
||||
/** 해제여부 */
|
||||
@JsonProperty("SZR_RMV_DTL_SN")
|
||||
private String szrRmvDtlSn;
|
||||
|
||||
/** 변경업무구분코드 */
|
||||
@JsonProperty("CHG_TASK_SE_CD")
|
||||
private String chgTaskSeCd;
|
||||
|
||||
/** 주번호 */
|
||||
@JsonProperty("MAIN_NO")
|
||||
private String mainNo;
|
||||
|
||||
/** 부번호 */
|
||||
@JsonProperty("SNO")
|
||||
private String sno;
|
||||
|
||||
/** 사항란 */
|
||||
@JsonProperty("SPCABL_MTTR")
|
||||
private String spcablMttr;
|
||||
|
||||
/** 세대주명 */
|
||||
@JsonProperty("HSHLDR_NM")
|
||||
private String hshldrNm;
|
||||
|
||||
/** 세대주개인암호화번호 */
|
||||
@JsonProperty("HSHLDR_IDECNO")
|
||||
private String hshldrIdecno;
|
||||
|
||||
/** 접수번호 */
|
||||
@JsonProperty("APLY_RCPT_NO")
|
||||
private String aplyRcptNo;
|
||||
|
||||
/** 차량관리번호 */
|
||||
@JsonProperty("VHMNO")
|
||||
private String vhmno;
|
||||
|
||||
/** 원부그룹번호 */
|
||||
@JsonProperty("LEDGER_GROUP_NO")
|
||||
private String ledgerGroupNo;
|
||||
|
||||
/** 원부개별번호 */
|
||||
@JsonProperty("LEDGER_INDIV_NO")
|
||||
private String ledgerIndivNo;
|
||||
|
||||
/** 변경업무구분명 */
|
||||
@JsonProperty("CHG_TASK_SE_NM")
|
||||
private String chgTaskSeNm;
|
||||
|
||||
/** 변경일자 */
|
||||
@JsonProperty("CHG_YMD")
|
||||
private String chgYmd;
|
||||
|
||||
/** 상세순번 */
|
||||
@JsonProperty("DTL_SN")
|
||||
private String dtlSn;
|
||||
|
||||
/** 표기여부 */
|
||||
@JsonProperty("FLAG")
|
||||
private String flag;
|
||||
}
|
||||
}
|
||||
@ -1,132 +0,0 @@
|
||||
package go.kr.project.api.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 자동차기본사항조회 응답 모델 (구버전)
|
||||
*
|
||||
* <p>
|
||||
* 구 규격(도로교통공단/교통안전공단 구버전) 응답을 매핑한 모델입니다.
|
||||
* 상단에 연계 결과코드/상세가 오고, 상세 데이터는 record 배열로 내려옵니다.
|
||||
* </p>
|
||||
*/
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@Schema(description = "자동차기본사항조회 응답 모델 (구버전)")
|
||||
@Getter
|
||||
@Setter
|
||||
public class OldBasicResponse { // 총 3개 필드 (외부 클래스 3개, 중첩 Record 클래스 84개)
|
||||
|
||||
/** 연계결과코드 */
|
||||
@JsonProperty("CNTC_RESULT_CODE")
|
||||
private String cntcResultCode;
|
||||
|
||||
/** 연계결과상세 */
|
||||
@JsonProperty("CNTC_RESULT_DTLS")
|
||||
private String cntcResultDtls;
|
||||
|
||||
/** 응답 레코드 목록 */
|
||||
@JsonProperty("record")
|
||||
private List<Record> record;
|
||||
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@Schema(name = "OldBasicRecord", description = "기본사항 record 항목 (구버전)")
|
||||
@Getter
|
||||
@Setter
|
||||
public static class Record {
|
||||
@JsonProperty("PRYE") private String prye; // 연식
|
||||
@JsonProperty("REGIST_DE") private String registDe; // 등록일자(변경일)
|
||||
@JsonProperty("ERSR_REGIST_SE_CODE") private String ersrRegistSeCode; // 말소등록구분코드
|
||||
@JsonProperty("ERSR_REGIST_SE_NM") private String ersrRegistSeNm; // 말소등록구분명
|
||||
@JsonProperty("ERSR_REGIST_DE") private String ersrRegistDe; // 말소등록일자
|
||||
@JsonProperty("REGIST_DETAIL_CODE") private String registDetailCode; // 등록상세코드
|
||||
@JsonProperty("DSPLVL") private String dsplvl; // 배기량
|
||||
@JsonProperty("USE_STRNGHLD_LEGALDONG_CODE") private String useStrnghldLegaldongCode; // 사용본거지법정동코드
|
||||
@JsonProperty("USE_STRNGHLD_ADSTRD_CODE") private String useStrnghldAdstrdCode; // 사용본거지행정동코드
|
||||
@JsonProperty("USE_STRNGHLD_MNTN") private String useStrnghldMntn; // 사용본거지산 여부
|
||||
@JsonProperty("USE_STRNGHLD_LNBR") private String useStrnghldLnbr; // 사용본거지번지
|
||||
@JsonProperty("USE_STRNGHLD_HO") private String useStrnghldHo; // 사용본거지호
|
||||
@JsonProperty("USE_STRNGHLD_ADRES_NM") private String useStrnghldAdresNm; // 사용본거지상세주소
|
||||
@JsonProperty("USE_STRNGHLD_ROAD_NM_CODE") private String useStrnghldRoadNmCode; // 사용본거지도로명코드
|
||||
@JsonProperty("USGSRHLD_UNDGRND_BULD_SE_CODE") private String usgsrhldUndgrndBuldSeCode; // 사용본거지지하건물구분코드
|
||||
@JsonProperty("USE_STRNGHLD_BULD_MAIN_NO") private String useStrnghldBuldMainNo; // 사용본거지건물주요번호
|
||||
@JsonProperty("USE_STRNGHLD_BULD_SUB_NO") private String useStrnghldBuldSubNo; // 사용본거지건물부번호
|
||||
@JsonProperty("USGSRHLD_ADRES_FULL") private String usgsrhldAdresFull; // 사용본거지전체주소
|
||||
@JsonProperty("MBER_SE_CODE") private String mberSeCode; // 대표소유자회원구분코드
|
||||
@JsonProperty("MBER_NM") private String mberNm; // 대표소유자성명
|
||||
@JsonProperty("MBER_SE_NO") private String mberSeNo; // 대표소유자회원번호
|
||||
@JsonProperty("TELNO") private String telno; // 대표소유자전화번호
|
||||
@JsonProperty("OWNER_LEGALDONG_CODE") private String ownerLegaldongCode; // 소유자법정동코드
|
||||
@JsonProperty("OWNER_ADSTRD_CODE") private String ownerAdstrdCode; // 소유자행정동코드
|
||||
@JsonProperty("OWNER_MNTN") private String ownerMntn; // 소유자산 여부
|
||||
@JsonProperty("OWNER_LNBR") private String ownerLnbr; // 소유자번지
|
||||
@JsonProperty("OWNER_HO") private String ownerHo; // 소유자호
|
||||
@JsonProperty("OWNER_ADRES_NM") private String ownerAdresNm; // 소유자상세주소
|
||||
@JsonProperty("OWNER_ROAD_NM_CODE") private String ownerRoadNmCode; // 소유자도로명코드
|
||||
@JsonProperty("OWNER_UNDGRND_BULD_SE_CODE") private String ownerUndgrndBuldSeCode; // 소유자지하건물구분코드
|
||||
@JsonProperty("OWNER_BULD_MAIN_NO") private String ownerBuldMainNo; // 소유자건물주요번호
|
||||
@JsonProperty("OWNER_BULD_SUB_NO") private String ownerBuldSubNo; // 소유자건물부번호
|
||||
@JsonProperty("OWNER_ADRES_FULL") private String ownerAdresFull; // 소유자전체주소
|
||||
@JsonProperty("AFTR_VHRNO") private String aftrVhrno; // 신차량번호
|
||||
@JsonProperty("USE_FUEL_CODE") private String useFuelCode; // 사용연료코드
|
||||
@JsonProperty("PRPOS_SE_CODE") private String prposSeCode; // 용도구분코드
|
||||
@JsonProperty("MTRS_FOM_NM") private String mtrsFomNm; // 원동기형식명
|
||||
@JsonProperty("FRNT_VHRNO") private String frntVhrno; // 이전차량번호
|
||||
@JsonProperty("VHRNO") private String vhrno; // 차량번호
|
||||
@JsonProperty("VIN") private String vin; // 차대번호
|
||||
@JsonProperty("CNM") private String cnm; // 차명
|
||||
@JsonProperty("VHCLE_TOT_WT") private String vhcleTotWt; // 차량총중량
|
||||
@JsonProperty("CAAG_ENDDE") private String caagEndde; // 차령만료일자
|
||||
@JsonProperty("CHANGE_DE") private String changeDe; // 차번호변경시기
|
||||
@JsonProperty("VHCTY_ASORT_CODE") private String vhctyAsortCode; // 차종종별코드
|
||||
@JsonProperty("VHCTY_TY_CODE") private String vhctyTyCode; // 차종유형코드
|
||||
@JsonProperty("VHCTY_SE_CODE") private String vhctySeCode; // 차종분류코드
|
||||
@JsonProperty("MXMM_LDG") private String mxmmLdg; // 최대적재량
|
||||
@JsonProperty("VHCTY_ASORT_NM") private String vhctyAsortNm; // 차종종별명
|
||||
@JsonProperty("VHCTY_TY_NM") private String vhctyTyNm; // 차종유형명
|
||||
@JsonProperty("VHCTY_SE_NM") private String vhctySeNm; // 차종분류명
|
||||
@JsonProperty("FRST_REGIST_DE") private String frstRegistDe; // 최초등록일
|
||||
@JsonProperty("FOM_NM") private String fomNm; // 형식
|
||||
@JsonProperty("ACQS_DE") private String acqsDe; // 취득일자
|
||||
@JsonProperty("ACQS_END_DE") private String acqsEndDe; // 취득종료일자
|
||||
@JsonProperty("YBL_MD") private String yblMd; // 제작연월(추정)
|
||||
@JsonProperty("TRANSR_REGIST_DE") private String transrRegistDe; // 이전등록일(양수일)
|
||||
@JsonProperty("SPCF_REGIST_STTUS_CODE") private String spcfRegistSttusCode; // 제원등록상태코드
|
||||
@JsonProperty("COLOR_NM") private String colorNm; // 색상명
|
||||
@JsonProperty("MRTG_CO") private String mrtgCo; // 저당수
|
||||
@JsonProperty("SEIZR_CO") private String seizrCo; // 압류건수
|
||||
@JsonProperty("STMD_CO") private String stmdCo; // 기타 설정/처분 건수(추정)
|
||||
@JsonProperty("NMPL_CSDY_AT") private String nmplCsdyAt; // 번호판영치여부
|
||||
@JsonProperty("NMPL_CSDY_REMNR_DE") private String nmplCsdyRemnrDe; // 번호판영치최고일
|
||||
@JsonProperty("ORIGIN_SE_CODE") private String originSeCode; // 출처구분코드
|
||||
@JsonProperty("NMPL_STNDRD_CODE") private String nmplStndrdCode; // 번호판규격코드
|
||||
@JsonProperty("ACQS_AMOUNT") private String acqsAmount; // 취득금액
|
||||
@JsonProperty("INSPT_VALID_PD_BGNDE") private String insptValidPdBgnde; // 검사유효기간시작일
|
||||
@JsonProperty("INSPT_VALID_PD_ENDDE") private String insptValidPdEndde; // 검사유효기간종료일
|
||||
@JsonProperty("USE_STRNGHLD_GRC_CODE") private String useStrnghldGrcCode; // 사용본거지관청코드
|
||||
@JsonProperty("TKCAR_PSCAP_CO") private String tkcarPscapCo; // 승차정원수
|
||||
@JsonProperty("SPMNNO") private String spmnno; // 제원관리번호
|
||||
@JsonProperty("TRVL_DSTNC") private String trvlDstnc; // 주행거리
|
||||
@JsonProperty("FRST_REGIST_RQRCNO") private String frstRegistRqrcno; // 최초등록접수번호
|
||||
@JsonProperty("VLNT_ERSR_PRVNTC_NTICE_DE") private String vlntErsrPrvntcNticeDe; // 예고통지일
|
||||
@JsonProperty("REGIST_INSTT_NM") private String registInsttNm; // 등록기관명
|
||||
@JsonProperty("PROCESS_IMPRTY_RESN_CODE") private String processImprtyResnCode; // 처리불가사유코드
|
||||
@JsonProperty("PROCESS_IMPRTY_RESN_DTLS") private String processImprtyResnDtls; // 처리불가사유명세
|
||||
@JsonProperty("CBD_LT") private String cbdLt; // 차체길이
|
||||
@JsonProperty("CBD_BT") private String cbdBt; // 차체너비
|
||||
@JsonProperty("CBD_HG") private String cbdHg; // 차체높이
|
||||
@JsonProperty("FRST_MXMM_LDG") private String frstMxmmLdg; // 최초최대적재량
|
||||
@JsonProperty("FUEL_CNSMP_RT") private String fuelCnsmpRt; // 연료소비율
|
||||
@JsonProperty("ELCTY_CMPND_FUEL_CNSMP_RT") private String elctyCmpndFuelCnsmpRt; // 전기복합연료소비율
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,647 @@
|
||||
package go.kr.project.api.model.response;
|
||||
|
||||
import go.kr.project.api.config.ApiConstant;
|
||||
import go.kr.project.api.model.Envelope;
|
||||
import go.kr.project.api.model.request.BasicRequest;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 자동차 기본 사항 조회 엔티티, DB 저장용
|
||||
*
|
||||
* <p>API 호출 정보를 저장하는 테이블 매핑 클래스입니다.
|
||||
* 최초 요청 시 INSERT, 결과 수신 시 UPDATE 형태로 사용됩니다.</p>
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class VmisCarBassMatterInqireVO {
|
||||
|
||||
// ==== Static factory/mapping methods (moved from Service) ====
|
||||
public static VmisCarBassMatterInqireVO fromRequest(BasicRequest request) {
|
||||
return VmisCarBassMatterInqireVO.builder()
|
||||
.infoSysId(request.getInfoSysId())
|
||||
.infoSysIp(request.getInfoSysIp())
|
||||
.sigunguCode(request.getSigunguCode())
|
||||
.cntcInfoCode(request.getCntcInfoCode())
|
||||
.chargerId(request.getChargerId())
|
||||
.chargerIp(request.getChargerIp())
|
||||
.chargerNm(request.getChargerNm())
|
||||
.dmndLevyStdde(request.getLevyStdde())
|
||||
.dmndInqireSeCode(request.getInqireSeCode())
|
||||
.dmndVhrno(request.getVhrno())
|
||||
.dmndVin(request.getVin())
|
||||
.rgtr(ApiConstant.DEFAULT_REGISTRANT)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static VmisCarBassMatterInqireVO fromResponse(String id, Envelope<BasicResponse> envelope) {
|
||||
if (envelope == null || envelope.getData() == null || envelope.getData().isEmpty()) return null;
|
||||
BasicResponse response = envelope.getData().get(0);
|
||||
VmisCarBassMatterInqireVO.VmisCarBassMatterInqireVOBuilder builder = VmisCarBassMatterInqireVO.builder()
|
||||
.carBassMatterInqireId(id)
|
||||
.cntcResultCode(response.getCntcResultCode())
|
||||
.cntcResultDtls(response.getCntcResultDtls());
|
||||
if (response.getRecord() != null && !response.getRecord().isEmpty()) {
|
||||
BasicResponse.Record record = response.getRecord().get(0);
|
||||
applyRecord(builder, record);
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private static void applyRecord(VmisCarBassMatterInqireVO.VmisCarBassMatterInqireVOBuilder builder, BasicResponse.Record record) {
|
||||
builder
|
||||
.prye(record.getPrye()) // 연식
|
||||
.registDe(record.getRegistDe()) // 등록일
|
||||
.ersrRegistSeCode(record.getErsrRegistSeCode()) // 말소 등록 구분 코드
|
||||
.ersrRegistSeNm(record.getErsrRegistSeNm()) // 말소 등록 구분명
|
||||
.ersrRegistDe(record.getErsrRegistDe()) // 말소 등록일
|
||||
.registDetailCode(record.getRegistDetailCode()) // 등록 상세 코드
|
||||
.dsplvl(record.getDsplvl()) // 배기량
|
||||
.useStrnghldLegaldongCode(record.getUseStrnghldLegaldongCode()) // 사용 본거지 법정동 코드
|
||||
.useStrnghldAdstrdCode(record.getUseStrnghldAdstrdCode()) // 사용 본거지 행정동 코드
|
||||
.useStrnghldMntn(record.getUseStrnghldMntn()) // 사용 본거지 산
|
||||
.useStrnghldLnbr(record.getUseStrnghldLnbr()) // 사용 본거지 번지
|
||||
.useStrnghldHo(record.getUseStrnghldHo()) // 사용 본거지 호
|
||||
.useStrnghldAdresNm(record.getUseStrnghldAdresNm()) // 사용 본거지 상세주소
|
||||
.useStrnghldRoadNmCode(record.getUseStrnghldRoadNmCode()) // 사용 본거지 도로명 코드
|
||||
.usgsrhldUndgrndBuldSeCode(record.getUsgsrhldUndgrndBuldSeCode()) // 사용 본거지 지하 건물 구분 코드
|
||||
.useStrnghldBuldMainNo(record.getUseStrnghldBuldMainNo()) // 사용 본거지 건물 주요 번호
|
||||
.useStrnghldBuldSubNo(record.getUseStrnghldBuldSubNo()) // 사용 본거지 건물 부 번호
|
||||
.usgsrhldAdresFull(record.getUsgsrhldAdresFull()) // 사용 본거지 전체주소
|
||||
.mberSeCode(record.getMberSeCode()) // 대표소유자 회원 구분 코드
|
||||
.mberSeNo(record.getMberSeNo()) // 대표소유자 회원 번호
|
||||
.mberNm(record.getMberNm()) // 대표소유자 성명
|
||||
.telno(record.getTelno()) // 대표소유자 전화번호
|
||||
.ownerLegaldongCode(record.getOwnerLegaldongCode()) // 소유자 법정동 코드
|
||||
.ownerAdstrdCode(record.getOwnerAdstrdCode()) // 소유자 행정동 코드
|
||||
.ownerMntn(record.getOwnerMntn()) // 소유자 산
|
||||
.ownerLnbr(record.getOwnerLnbr()) // 소유자 번지
|
||||
.ownerHo(record.getOwnerHo()) // 소유자 호
|
||||
.ownerAdresNm(record.getOwnerAdresNm()) // 소유자 상세주소
|
||||
.ownerRoadNmCode(record.getOwnerRoadNmCode()) // 소유자 도로명 코드
|
||||
.ownerUndgrndBuldSeCode(record.getOwnerUndgrndBuldSeCode()) // 소유자 지하건물 구분 코드
|
||||
.ownerBuldMainNo(record.getOwnerBuldMainNo()) // 소유자 건물 주요 번호
|
||||
.ownerBuldSubNo(record.getOwnerBuldSubNo()) // 소유자 건물 부 번호
|
||||
.ownrWholaddr(record.getOwnerAdresFull()) // 소유자 전체주소
|
||||
.aftrVhrno(record.getAftrVhrno()) // 신 차량번호
|
||||
.useFuelCode(record.getUseFuelCode()) // 사용 연료 코드
|
||||
.prposSeCode(record.getPrposSeCode()) // 용도 구분 코드
|
||||
.mtrsFomNm(record.getMtrsFomNm()) // 원동기 형식명
|
||||
.frntVhrno(record.getFrntVhrno()) // 이전 차량번호
|
||||
.vhrno(record.getVhrno()) // 차량번호
|
||||
.vin(record.getVin()) // 차대번호
|
||||
.cnm(record.getCnm()) // 차명
|
||||
.vhcleTotWt(record.getVhcleTotWt()) // 차량 총 중량
|
||||
.caagEndde(record.getCaagEndde()) // 차령 만료일자
|
||||
.changeDe(record.getChangeDe()) // 차번호 변경시기
|
||||
.vhctyAsortCode(record.getVhctyAsortCode()) // 차종 종별 코드
|
||||
.vhctyTyCode(record.getVhctyTyCode()) // 차종 유형 코드
|
||||
.vhctySeCode(record.getVhctySeCode()) // 차종 분류 코드
|
||||
.mxmmLdg(record.getMxmmLdg()) // 최대 적재량
|
||||
.vhctyAsortNm(record.getVhctyAsortNm()) // 차종 종별명
|
||||
.vhctyTyNm(record.getVhctyTyNm()) // 차종 유형명
|
||||
.vhctySeNm(record.getVhctySeNm()) // 차종 분류명
|
||||
.frstRegistDe(record.getFrstRegistDe()) // 최초 등록일
|
||||
.fomNm(record.getFomNm()) // 형식
|
||||
.acqsDe(record.getAcqsDe()) // 취득 일자
|
||||
.acqsEndDe(record.getAcqsEndDe()) // 취득 종료일자
|
||||
.yblMd(record.getYblMd()) // 제작 년월일
|
||||
.transrRegistDe(record.getTransrRegistDe()) // 이전 등록일
|
||||
.spcfRegistSttusCode(record.getSpcfRegistSttusCode()) // 제원 등록 상태 코드
|
||||
.colorNm(record.getColorNm()) // 색상명
|
||||
.mrtgCo(record.getMrtgCo()) // 저당수
|
||||
.seizrCo(record.getSeizrCo()) // 압류건수
|
||||
.stmdCo(record.getStmdCo()) // 구조변경수
|
||||
.nmplCsdyAt(record.getNmplCsdyAt()) // 번호판 영치 여부
|
||||
.nmplCsdyRemnrDe(record.getNmplCsdyRemnrDe()) // 번호판 영치 최고일
|
||||
.originSeCode(record.getOriginSeCode()) // 출처 구분 코드
|
||||
.nmplStndrdCode(record.getNmplStndrdCode()) // 번호판 규격 코드
|
||||
.acqsAmount(record.getAcqsAmount()) // 취득 금액
|
||||
.insptValidPdBgnde(record.getInsptValidPdBgnde()) // 검사 유효 기간 시작일
|
||||
.insptValidPdEndde(record.getInsptValidPdEndde()) // 검사 유효 기간 종료일
|
||||
.useStrnghldGrcCode(record.getUseStrnghldGrcCode()) // 사용 본거지 관청 코드
|
||||
.tkcarPscapCo(record.getTkcarPscapCo()) // 승차정원수
|
||||
.spmnno(record.getSpmnno()) // 제원관리번호
|
||||
.trvlDstnc(record.getTrvlDstnc()) // 주행거리
|
||||
.frstRegistRqrcno(record.getFrstRegistRqrcno()) // 최초 등록 접수번호
|
||||
.vlntErsrPrvntcNticeDe(record.getVlntErsrPrvntcNticeDe()) // 예고통지일
|
||||
.registInsttNm(record.getRegistInsttNm()) // 등록 기관명
|
||||
.processImprtyResnCode(record.getProcessImprtyResnCode()) // 처리 불가 사유 코드
|
||||
.processImprtyResnDtls(record.getProcessImprtyResnDtls()) // 처리 불가 사유 명세
|
||||
.cbdLt(record.getCbdLt()) // 차체 길이
|
||||
.cbdBt(record.getCbdBt()) // 차체 너비
|
||||
.cbdHg(record.getCbdHg()) // 차체 높이
|
||||
.frstMxmmLdg(record.getFrstMxmmLdg()) // 최초 최대 적재량
|
||||
.fuelCnsmpRt(record.getFuelCnsmpRt()) // 연료 소비율
|
||||
.elctyCmpndFuelCnsmpRt(record.getElctyCmpndFuelCnsmpRt()); // 전기 복합 연료 소비율
|
||||
}
|
||||
|
||||
/**
|
||||
* 자동차 기본 사항 조회 ID (PK)
|
||||
* 형식: CBMI000000000001
|
||||
*/
|
||||
private String carBassMatterInqireId;
|
||||
|
||||
// ===== 요청 정보 =====
|
||||
/**
|
||||
* 정보 시스템 ID
|
||||
*/
|
||||
private String infoSysId;
|
||||
|
||||
/**
|
||||
* 정보 시스템 IP
|
||||
*/
|
||||
private String infoSysIp;
|
||||
|
||||
/**
|
||||
* 시군구 코드
|
||||
*/
|
||||
private String sigunguCode;
|
||||
|
||||
/**
|
||||
* 연계 정보 코드
|
||||
*/
|
||||
private String cntcInfoCode;
|
||||
|
||||
/**
|
||||
* 담당자 ID
|
||||
*/
|
||||
private String chargerId;
|
||||
|
||||
/**
|
||||
* 담당자 IP
|
||||
*/
|
||||
private String chargerIp;
|
||||
|
||||
/**
|
||||
* 담당자명
|
||||
*/
|
||||
private String chargerNm;
|
||||
|
||||
/**
|
||||
* 요청 부과 기준일
|
||||
*/
|
||||
private String dmndLevyStdde;
|
||||
|
||||
/**
|
||||
* 요청 조회 구분 코드
|
||||
*/
|
||||
private String dmndInqireSeCode;
|
||||
|
||||
/**
|
||||
* 요청 자동차등록번호
|
||||
*/
|
||||
private String dmndVhrno;
|
||||
|
||||
/**
|
||||
* 요청 차대번호
|
||||
*/
|
||||
private String dmndVin;
|
||||
|
||||
// ===== 응답 정보 (결과 수신 시 UPDATE) =====
|
||||
/**
|
||||
* 연계 결과 코드
|
||||
*/
|
||||
private String cntcResultCode;
|
||||
|
||||
/**
|
||||
* 연계 결과 상세
|
||||
*/
|
||||
private String cntcResultDtls;
|
||||
|
||||
/**
|
||||
* 연식
|
||||
*/
|
||||
private String prye;
|
||||
|
||||
/**
|
||||
* 등록일
|
||||
*/
|
||||
private String registDe;
|
||||
|
||||
/**
|
||||
* 말소 등록 구분 코드
|
||||
*/
|
||||
private String ersrRegistSeCode;
|
||||
|
||||
/**
|
||||
* 말소 등록 구분명
|
||||
*/
|
||||
private String ersrRegistSeNm;
|
||||
|
||||
/**
|
||||
* 말소 등록일
|
||||
*/
|
||||
private String ersrRegistDe;
|
||||
|
||||
/**
|
||||
* 등록 상세 코드
|
||||
*/
|
||||
private String registDetailCode;
|
||||
|
||||
/**
|
||||
* 배기량
|
||||
*/
|
||||
private String dsplvl;
|
||||
|
||||
/**
|
||||
* 사용 본거지 법정동 코드
|
||||
*/
|
||||
private String useStrnghldLegaldongCode;
|
||||
|
||||
/**
|
||||
* 사용 본거지 행정동 코드
|
||||
*/
|
||||
private String useStrnghldAdstrdCode;
|
||||
|
||||
/**
|
||||
* 사용 본거지 산
|
||||
*/
|
||||
private String useStrnghldMntn;
|
||||
|
||||
/**
|
||||
* 사용 본거지 번지
|
||||
*/
|
||||
private String useStrnghldLnbr;
|
||||
|
||||
/**
|
||||
* 사용 본거지 호
|
||||
*/
|
||||
private String useStrnghldHo;
|
||||
|
||||
/**
|
||||
* 사용 본거지 상세주소
|
||||
*/
|
||||
private String useStrnghldAdresNm;
|
||||
|
||||
/**
|
||||
* 사용 본거지 도로명 코드
|
||||
*/
|
||||
private String useStrnghldRoadNmCode;
|
||||
|
||||
/**
|
||||
* 사용 본거지 지하 건물 구분 코드
|
||||
*/
|
||||
private String usgsrhldUndgrndBuldSeCode;
|
||||
|
||||
/**
|
||||
* 사용 본거지 건물 주요 번호
|
||||
*/
|
||||
private String useStrnghldBuldMainNo;
|
||||
|
||||
/**
|
||||
* 사용 본거지 건물 부 번호
|
||||
*/
|
||||
private String useStrnghldBuldSubNo;
|
||||
|
||||
/**
|
||||
* 사용 본거지 전체주소
|
||||
*/
|
||||
private String usgsrhldAdresFull;
|
||||
|
||||
/**
|
||||
* 대표소유자 회원 구분 코드
|
||||
*/
|
||||
private String mberSeCode;
|
||||
|
||||
/**
|
||||
* 대표소유자 회원 번호
|
||||
*/
|
||||
private String mberSeNo;
|
||||
|
||||
/**
|
||||
* 대표소유자 전화번호
|
||||
*/
|
||||
private String telno;
|
||||
|
||||
/**
|
||||
* 소유자 법정동 코드
|
||||
*/
|
||||
private String ownerLegaldongCode;
|
||||
|
||||
/**
|
||||
* 소유자 행정동 코드
|
||||
*/
|
||||
private String ownerAdstrdCode;
|
||||
|
||||
/**
|
||||
* 소유자 산
|
||||
*/
|
||||
private String ownerMntn;
|
||||
|
||||
/**
|
||||
* 소유자 번지
|
||||
*/
|
||||
private String ownerLnbr;
|
||||
|
||||
/**
|
||||
* 소유자 호
|
||||
*/
|
||||
private String ownerHo;
|
||||
|
||||
/**
|
||||
* 소유자 상세주소
|
||||
*/
|
||||
private String ownerAdresNm;
|
||||
|
||||
/**
|
||||
* 소유자 도로명 코드
|
||||
*/
|
||||
private String ownerRoadNmCode;
|
||||
|
||||
/**
|
||||
* 소유자 지하건물 구분 코드
|
||||
*/
|
||||
private String ownerUndgrndBuldSeCode;
|
||||
|
||||
/**
|
||||
* 소유자 건물 주요 번호
|
||||
*/
|
||||
private String ownerBuldMainNo;
|
||||
|
||||
/**
|
||||
* 소유자 건물 부 번호
|
||||
*/
|
||||
private String ownerBuldSubNo;
|
||||
|
||||
/**
|
||||
* 소유자 전체주소
|
||||
*/
|
||||
private String ownrWholaddr;
|
||||
|
||||
/**
|
||||
* 신 차량번호
|
||||
*/
|
||||
private String aftrVhrno;
|
||||
|
||||
/**
|
||||
* 사용 연료 코드
|
||||
*/
|
||||
private String useFuelCode;
|
||||
|
||||
/**
|
||||
* 용도 구분 코드
|
||||
*/
|
||||
private String prposSeCode;
|
||||
|
||||
/**
|
||||
* 원동기 형식명
|
||||
*/
|
||||
private String mtrsFomNm;
|
||||
|
||||
/**
|
||||
* 이전 차량번호
|
||||
*/
|
||||
private String frntVhrno;
|
||||
|
||||
/**
|
||||
* 차량번호
|
||||
*/
|
||||
private String vhrno;
|
||||
|
||||
/**
|
||||
* 차대번호
|
||||
*/
|
||||
private String vin;
|
||||
|
||||
/**
|
||||
* 차명
|
||||
*/
|
||||
private String cnm;
|
||||
|
||||
/**
|
||||
* 차량 총 중량
|
||||
*/
|
||||
private String vhcleTotWt;
|
||||
|
||||
/**
|
||||
* 차령 만료일자
|
||||
*/
|
||||
private String caagEndde;
|
||||
|
||||
/**
|
||||
* 차번호 변경시기
|
||||
*/
|
||||
private String changeDe;
|
||||
|
||||
/**
|
||||
* 차종 종별 코드
|
||||
*/
|
||||
private String vhctyAsortCode;
|
||||
|
||||
/**
|
||||
* 차종 유형 코드
|
||||
*/
|
||||
private String vhctyTyCode;
|
||||
|
||||
/**
|
||||
* 차종 분류 코드
|
||||
*/
|
||||
private String vhctySeCode;
|
||||
|
||||
/**
|
||||
* 최대 적재량
|
||||
*/
|
||||
private String mxmmLdg;
|
||||
|
||||
/**
|
||||
* 차종 종별명
|
||||
*/
|
||||
private String vhctyAsortNm;
|
||||
|
||||
/**
|
||||
* 차종 유형명
|
||||
*/
|
||||
private String vhctyTyNm;
|
||||
|
||||
/**
|
||||
* 차종 분류명
|
||||
*/
|
||||
private String vhctySeNm;
|
||||
|
||||
/**
|
||||
* 최초 등록일
|
||||
*/
|
||||
private String frstRegistDe;
|
||||
|
||||
/**
|
||||
* 형식
|
||||
*/
|
||||
private String fomNm;
|
||||
|
||||
/**
|
||||
* 취득 일자
|
||||
*/
|
||||
private String acqsDe;
|
||||
|
||||
/**
|
||||
* 취득 종료일자
|
||||
*/
|
||||
private String acqsEndDe;
|
||||
|
||||
/**
|
||||
* 제작 년월일
|
||||
*/
|
||||
private String yblMd;
|
||||
|
||||
/**
|
||||
* 이전 등록일
|
||||
*/
|
||||
private String transrRegistDe;
|
||||
|
||||
/**
|
||||
* 제원 등록 상태 코드
|
||||
*/
|
||||
private String spcfRegistSttusCode;
|
||||
|
||||
/**
|
||||
* 색상명
|
||||
*/
|
||||
private String colorNm;
|
||||
|
||||
/**
|
||||
* 저당수
|
||||
*/
|
||||
private String mrtgCo;
|
||||
|
||||
/**
|
||||
* 압류건수
|
||||
*/
|
||||
private String seizrCo;
|
||||
|
||||
/**
|
||||
* 구조변경수
|
||||
*/
|
||||
private String stmdCo;
|
||||
|
||||
/**
|
||||
* 번호판 영치 여부
|
||||
*/
|
||||
private String nmplCsdyAt;
|
||||
|
||||
/**
|
||||
* 번호판 영치 최고일
|
||||
*/
|
||||
private String nmplCsdyRemnrDe;
|
||||
|
||||
/**
|
||||
* 출처 구분 코드
|
||||
*/
|
||||
private String originSeCode;
|
||||
|
||||
/**
|
||||
* 번호판 규격 코드
|
||||
*/
|
||||
private String nmplStndrdCode;
|
||||
|
||||
/**
|
||||
* 취득 금액
|
||||
*/
|
||||
private String acqsAmount;
|
||||
|
||||
/**
|
||||
* 검사 유효 기간 시작일
|
||||
*/
|
||||
private String insptValidPdBgnde;
|
||||
|
||||
/**
|
||||
* 검사 유효 기간 종료일
|
||||
*/
|
||||
private String insptValidPdEndde;
|
||||
|
||||
/**
|
||||
* 사용 본거지 관청 코드
|
||||
*/
|
||||
private String useStrnghldGrcCode;
|
||||
|
||||
/**
|
||||
* 승차정원수
|
||||
*/
|
||||
private String tkcarPscapCo;
|
||||
|
||||
/**
|
||||
* 제원관리번호
|
||||
*/
|
||||
private String spmnno;
|
||||
|
||||
/**
|
||||
* 주행거리
|
||||
*/
|
||||
private String trvlDstnc;
|
||||
|
||||
/**
|
||||
* 최초 등록 접수번호
|
||||
*/
|
||||
private String frstRegistRqrcno;
|
||||
|
||||
/**
|
||||
* 예고통지일
|
||||
*/
|
||||
private String vlntErsrPrvntcNticeDe;
|
||||
|
||||
/**
|
||||
* 등록 기관명
|
||||
*/
|
||||
private String registInsttNm;
|
||||
|
||||
/**
|
||||
* 처리 불가 사유 코드
|
||||
*/
|
||||
private String processImprtyResnCode;
|
||||
|
||||
/**
|
||||
* 처리 불가 사유 명세
|
||||
*/
|
||||
private String processImprtyResnDtls;
|
||||
|
||||
/**
|
||||
* 차체 길이
|
||||
*/
|
||||
private String cbdLt;
|
||||
|
||||
/**
|
||||
* 차체 너비
|
||||
*/
|
||||
private String cbdBt;
|
||||
|
||||
/**
|
||||
* 차체 높이
|
||||
*/
|
||||
private String cbdHg;
|
||||
|
||||
/**
|
||||
* 최초 최대 적재량
|
||||
*/
|
||||
private String frstMxmmLdg;
|
||||
|
||||
/**
|
||||
* 연료 소비율
|
||||
*/
|
||||
private String fuelCnsmpRt;
|
||||
|
||||
/**
|
||||
* 전기 복합 연료 소비율
|
||||
*/
|
||||
private String elctyCmpndFuelCnsmpRt;
|
||||
|
||||
/**
|
||||
* 등록 일시
|
||||
*/
|
||||
private LocalDateTime regDt;
|
||||
|
||||
/**
|
||||
* 등록자
|
||||
*/
|
||||
private String rgtr;
|
||||
|
||||
/**
|
||||
* 대표소유자 성명
|
||||
*/
|
||||
private String mberNm;
|
||||
}
|
||||
@ -0,0 +1,73 @@
|
||||
package go.kr.project.api.model.response;
|
||||
|
||||
import go.kr.project.api.config.ApiConstant;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 자동차 등록 원부(갑) 상세 엔티티 VO, DB 저장용
|
||||
*
|
||||
* <p>tb_car_ledger_frmbk_dtl 테이블 매핑</p>
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class VmisCarLedgerFrmbkDtlVO {
|
||||
|
||||
// ==== Static factory/mapping methods (moved from Service) ====
|
||||
public static List<VmisCarLedgerFrmbkDtlVO> listFromResponse(LedgerResponse res, String masterId) {
|
||||
List<VmisCarLedgerFrmbkDtlVO> list = new ArrayList<>();
|
||||
if (res == null || res.getRecord() == null) return list;
|
||||
for (LedgerResponse.Record r : res.getRecord()) {
|
||||
VmisCarLedgerFrmbkDtlVO vo = VmisCarLedgerFrmbkDtlVO.builder()
|
||||
.carLedgerFrmbkId(masterId) // 원부 마스터 ID (FK)
|
||||
.mainchk(r.getMainchk()) // 주요 체크
|
||||
.changeJobSeCode(r.getChangeJobSeCode()) // 변경 작업 구분 코드
|
||||
.mainno(r.getMainno()) // 주번호
|
||||
.subno(r.getSubno()) // 부번호
|
||||
.dtls(r.getDtls()) // 상세 내역
|
||||
.rqrcno(r.getRqrcno()) // 접수번호
|
||||
.vhmno(r.getVhmno()) // 차량관리번호
|
||||
.ledgerGroupNo(r.getLedgerGroupNo()) // 원부 그룹 번호
|
||||
.ledgerIndvdlzNo(r.getLedgerIndvdlzNo()) // 원부 개별화 번호
|
||||
.gubunNm(r.getGubunNm()) // 구분명
|
||||
.changeDe(r.getChangeDe()) // 변경일자
|
||||
.detailSn(r.getDetailSn()) // 상세 순번
|
||||
.flag(r.getFlag()) // 플래그
|
||||
.rgtr(ApiConstant.DEFAULT_REGISTRANT) // 등록자
|
||||
.build();
|
||||
list.add(vo);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
// PK
|
||||
private String carLedgerFrmbkDtlId;
|
||||
|
||||
// FK
|
||||
private String carLedgerFrmbkId;
|
||||
|
||||
// 본문
|
||||
private String mainchk;
|
||||
private String changeJobSeCode;
|
||||
private String mainno;
|
||||
private String subno;
|
||||
private String dtls;
|
||||
private String rqrcno;
|
||||
private String vhmno;
|
||||
private String ledgerGroupNo;
|
||||
private String ledgerIndvdlzNo;
|
||||
private String gubunNm;
|
||||
private String changeDe;
|
||||
private String detailSn;
|
||||
private String flag;
|
||||
|
||||
// 감사
|
||||
private String rgtr;
|
||||
}
|
||||
@ -0,0 +1,192 @@
|
||||
package go.kr.project.api.model.response;
|
||||
|
||||
import go.kr.project.api.config.ApiConstant;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 자동차 등록 원부(갑) 마스터 엔티티 VO, DB 저장용
|
||||
*
|
||||
* <p>tb_car_ledger_frmbk 테이블 매핑</p>
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class VmisCarLedgerFrmbkVO {
|
||||
|
||||
// ==== Static factory/mapping methods (moved from Service) ====
|
||||
public static VmisCarLedgerFrmbkVO fromRequest(go.kr.project.api.model.request.LedgerRequest request) {
|
||||
return VmisCarLedgerFrmbkVO.builder()
|
||||
.infoSysId(request.getInfoSysId())
|
||||
.infoSysIp(request.getInfoSysIp())
|
||||
.sigunguCode(request.getSigunguCode())
|
||||
.cntcInfoCode(request.getCntcInfoCode())
|
||||
.chargerId(request.getChargerId())
|
||||
.chargerIp(request.getChargerIp())
|
||||
.chargerNm(request.getChargerNm())
|
||||
.dmndVhrno(request.getVhrno())
|
||||
.rgtr(ApiConstant.DEFAULT_REGISTRANT)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static VmisCarLedgerFrmbkVO fromResponseMaster(String id, go.kr.project.api.model.response.LedgerResponse res) {
|
||||
return VmisCarLedgerFrmbkVO.builder()
|
||||
.carLedgerFrmbkId(id) // 등록원부 ID
|
||||
.cntcResultCode(res.getCntcResultCode()) // 연계 결과 코드
|
||||
.cntcResultDtls(res.getCntcResultDtls()) // 연계 결과 상세
|
||||
.ledgerGroupNo(res.getLedgerGroupNo()) // 원부 그룹 번호
|
||||
.ledgerIndvdlzNo(res.getLedgerIndvdlzNo()) // 원부 개별화 번호
|
||||
.vhmno(res.getVhmno()) // 차량관리번호
|
||||
.vhrno(res.getVhrno()) // 차량번호
|
||||
.vin(res.getVin()) // 차대번호
|
||||
.vhctyAsortCode(res.getVhctyAsortCode()) // 차종 종별 코드
|
||||
.vhctyAsortNm(res.getVhctyAsortNm()) // 차종 종별명
|
||||
.cnm(res.getCnm()) // 차명
|
||||
.colorCode(res.getColorCode()) // 색상 코드
|
||||
.colorNm(res.getColorNm()) // 색상명
|
||||
.nmplStndrdCode(res.getNmplStndrdCode()) // 번호판 규격 코드
|
||||
.nmplStndrdNm(res.getNmplStndrdNm()) // 번호판 규격명
|
||||
.prposSeCode(res.getPrposSeCode()) // 용도 구분 코드
|
||||
.prposSeNm(res.getPrposSeNm()) // 용도 구분명
|
||||
.mtrsFomNm(res.getMtrsFomNm()) // 원동기 형식명
|
||||
.fomNm(res.getFomNm()) // 형식명
|
||||
.acqsAmount(res.getAcqsAmount()) // 취득 금액
|
||||
.registDetailCode(res.getRegistDetailCode()) // 등록 상세 코드
|
||||
.registDetailNm(res.getRegistDetailNm()) // 등록 상세명
|
||||
.frstRegistDe(res.getFrstRegistDe()) // 최초 등록일
|
||||
.caagEndde(res.getCaagEndde()) // 차령 만료일자
|
||||
.prye(res.getPrye()) // 연식
|
||||
.spmnno1(res.getSpmnno1()) // 제원관리번호1
|
||||
.spmnno2(res.getSpmnno2()) // 제원관리번호2
|
||||
.yblMd(res.getYblMd()) // 제작 년월일
|
||||
.trvlDstnc(res.getTrvlDstnc()) // 주행거리
|
||||
.insptValidPdBgnde(res.getInsptValidPdBgnde()) // 검사 유효 기간 시작일
|
||||
.insptValidPdEndde(res.getInsptValidPdEndde()) // 검사 유효 기간 종료일
|
||||
.chckValidPdBgnde(res.getChckValidPdBgnde()) // 점검 유효 기간 시작일
|
||||
.chckValidPdEndde(res.getChckValidPdEndde()) // 점검 유효 기간 종료일
|
||||
.registReqstSeNm(res.getRegistReqstSeNm()) // 등록 청구 구분명
|
||||
.frstRegistRqrcno(res.getFrstRegistRqrcno()) // 최초 등록 접수번호
|
||||
.nmplCsdyRemnrDe(res.getNmplCsdyRemnrDe()) // 번호판 영치 최고일
|
||||
.nmplCsdyAt(res.getNmplCsdyAt()) // 번호판 영치 여부
|
||||
.bssUsePd(res.getBssUsePd()) // 사업용 기간
|
||||
.octhtErsrPrvntcNticeDe(res.getOcthtErsrPrvntcNticeDe()) // 직권말소 예고통지일
|
||||
.ersrRegistDe(res.getErsrRegistDe()) // 말소 등록일
|
||||
.ersrRegistSeCode(res.getErsrRegistSeCode()) // 말소 등록 구분 코드
|
||||
.ersrRegistSeNm(res.getErsrRegistSeNm()) // 말소 등록 구분명
|
||||
.mrtgcnt(res.getMrtgcnt()) // 저당건수
|
||||
.vhclecnt(res.getVhclecnt()) // 압류건수
|
||||
.stmdcnt(res.getStmdcnt()) // 구조변경건수
|
||||
.adres1(res.getAdres1()) // 주소1
|
||||
.adresNm1(res.getAdresNm1()) // 주소명1
|
||||
.adres(res.getAdres()) // 주소
|
||||
.adresNm(res.getAdresNm()) // 주소명
|
||||
.indvdlBsnmAt(res.getIndvdlBsnmAt()) // 개인사업자 여부
|
||||
.telno(res.getTelno()) // 전화번호
|
||||
.mberNm(res.getMberNm()) // 소유자명
|
||||
.mberSeCode(res.getMberSeCode()) // 소유자 구분 코드
|
||||
.mberSeNo(res.getMberSeNo()) // 소유자 번호
|
||||
.taxxmptTrgterSeCode(res.getTaxxmptTrgterSeCode()) // 면세 대상 구분 코드
|
||||
.taxxmptTrgterSeCodeNm(res.getTaxxmptTrgterSeCodeNm()) // 면세 대상 구분명
|
||||
.cntMatter(res.getCntMatter()) // 내용 사항
|
||||
.emdNm(res.getEmdNm()) // 읍면동명
|
||||
.prvntccnt(res.getPrvntccnt()) // 예방건수
|
||||
.xportFlflAtSttemntDe(res.getXportFlflAtSttemntDe()) // 수출이행신고일
|
||||
.partnRqrcno(res.getPartnRqrcno()) // 협력업체 접수번호
|
||||
.build();
|
||||
}
|
||||
|
||||
// PK
|
||||
private String carLedgerFrmbkId;
|
||||
|
||||
// 요청(헤더/본문) 정보
|
||||
private String infoSysId;
|
||||
private String infoSysIp;
|
||||
private String sigunguCode;
|
||||
private String cntcInfoCode;
|
||||
private String chargerId;
|
||||
private String chargerIp;
|
||||
private String chargerNm;
|
||||
|
||||
// 요청 본문
|
||||
private String dmndVhrno;
|
||||
private String dmndOnesInformationOpen;
|
||||
private String dmndCpttrNm;
|
||||
private String dmndCpttrIhidnum;
|
||||
private String dmndCpttrLegaldongCode;
|
||||
private String dmndRouteSeCode;
|
||||
private String dmndDetailExpression;
|
||||
private String dmndInqireSeCode;
|
||||
|
||||
// 응답 요약 정보
|
||||
private String cntcResultCode;
|
||||
private String cntcResultDtls;
|
||||
|
||||
// 응답 본문(마스터)
|
||||
private String ledgerGroupNo;
|
||||
private String ledgerIndvdlzNo;
|
||||
private String vhmno;
|
||||
private String vhrno;
|
||||
private String vin;
|
||||
private String vhctyAsortCode;
|
||||
private String vhctyAsortNm;
|
||||
private String cnm;
|
||||
private String colorCode;
|
||||
private String colorNm;
|
||||
private String nmplStndrdCode;
|
||||
private String nmplStndrdNm;
|
||||
private String prposSeCode;
|
||||
private String prposSeNm;
|
||||
private String mtrsFomNm;
|
||||
private String fomNm;
|
||||
private String acqsAmount;
|
||||
private String registDetailCode;
|
||||
private String registDetailNm;
|
||||
private String frstRegistDe;
|
||||
private String caagEndde;
|
||||
private String prye;
|
||||
private String spmnno1;
|
||||
private String spmnno2;
|
||||
private String yblMd;
|
||||
private String trvlDstnc;
|
||||
private String insptValidPdBgnde;
|
||||
private String insptValidPdEndde;
|
||||
private String chckValidPdBgnde;
|
||||
private String chckValidPdEndde;
|
||||
private String registReqstSeNm;
|
||||
private String frstRegistRqrcno;
|
||||
private String nmplCsdyRemnrDe;
|
||||
private String nmplCsdyAt;
|
||||
private String bssUsePd;
|
||||
private String octhtErsrPrvntcNticeDe;
|
||||
private String ersrRegistDe;
|
||||
private String ersrRegistSeCode;
|
||||
private String ersrRegistSeNm;
|
||||
private String mrtgcnt;
|
||||
private String vhclecnt;
|
||||
private String stmdcnt;
|
||||
private String adres1;
|
||||
private String adresNm1;
|
||||
private String adres;
|
||||
private String adresNm;
|
||||
private String indvdlBsnmAt;
|
||||
private String telno;
|
||||
private String mberNm;
|
||||
private String mberSeCode;
|
||||
private String mberSeNo;
|
||||
private String taxxmptTrgterSeCode;
|
||||
private String taxxmptTrgterSeCodeNm;
|
||||
private String cntMatter;
|
||||
private String emdNm;
|
||||
private String prvntccnt;
|
||||
private String xportFlflAtSttemntDe;
|
||||
private String partnRqrcno;
|
||||
private String frstTrnsfrDe;
|
||||
private String processImprtyResnCode;
|
||||
private String processImprtyResnDtls;
|
||||
|
||||
// 감사
|
||||
private String rgtr;
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
package go.kr.project.api.service;
|
||||
|
||||
import go.kr.project.api.model.request.NewBasicRequest;
|
||||
import go.kr.project.api.model.request.NewLedgerRequest;
|
||||
import go.kr.project.api.model.response.NewBasicResponse;
|
||||
import go.kr.project.api.model.response.NewLedgerResponse;
|
||||
|
||||
/**
|
||||
* 외부 VMIS-interface API 호출 서비스 인터페이스
|
||||
* VMIS-interface 프로그램의 API를 호출하여 차량 정보를 조회하는 서비스
|
||||
*/
|
||||
public interface ExternalVehicleApiService {
|
||||
|
||||
/**
|
||||
* 기본정보 조회 (YAML 설정에 따라 old/new 자동 선택)
|
||||
* vmis.external.api.url.basic.old-or-new 설정 값에 따라 자동 분기
|
||||
* @param request 신규 포맷 요청 (내부에서 old/new 변환)
|
||||
*/
|
||||
NewBasicResponse getBasicInfo(NewBasicRequest request);
|
||||
|
||||
/**
|
||||
* 등록원부(갑) 조회 (YAML 설정에 따라 old/new 자동 선택)
|
||||
* vmis.external.api.url.ledger.old-or-new 설정 값에 따라 자동 분기
|
||||
* @param request 신규 포맷 요청 (내부에서 old/new 변환)
|
||||
*/
|
||||
NewLedgerResponse getLedgerInfo(NewLedgerRequest request);
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
package go.kr.project.api.service;
|
||||
|
||||
import go.kr.project.api.model.VehicleApiResponseVO;
|
||||
import go.kr.project.api.model.request.BasicRequest;
|
||||
import go.kr.project.api.model.request.LedgerRequest;
|
||||
import go.kr.project.api.model.response.BasicResponse;
|
||||
import go.kr.project.api.model.response.LedgerResponse;
|
||||
|
||||
/**
|
||||
* 차량 정보 조회 서비스 인터페이스
|
||||
*
|
||||
* <p>이 인터페이스는 차량 정보를 조회하는 두 가지 구현체를 추상화합니다:</p>
|
||||
* <ul>
|
||||
* <li>InternalVehicleInfoServiceImpl: 내부 VMIS 모듈을 직접 호출 (vmis.integration.mode=internal)</li>
|
||||
* <li>ExternalVehicleInfoServiceImpl: 외부 REST API를 호출 (vmis.integration.mode=external)</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h3>설정 방법:</h3>
|
||||
* <pre>
|
||||
* # application.yml
|
||||
* vmis:
|
||||
* integration:
|
||||
* mode: internal # 또는 external
|
||||
* </pre>
|
||||
*
|
||||
* <h3>사용 예시:</h3>
|
||||
* <pre>
|
||||
* {@code
|
||||
* @Autowired
|
||||
* private VehicleInfoService vehicleInfoService;
|
||||
*
|
||||
* // 단일 차량 조회
|
||||
* VehicleApiResponseVO response = vehicleInfoService.getVehicleInfo("12가3456");
|
||||
*
|
||||
* // 여러 차량 일괄 조회
|
||||
* List<VehicleApiResponseVO> responses = vehicleInfoService.getVehiclesInfo(
|
||||
* Arrays.asList("12가3456", "34나5678")
|
||||
* );
|
||||
*
|
||||
* // 단독 조회 (기본/등록원부)
|
||||
* BasicResponse basic = vehicleInfoService.getBasicInfo("12가3456");
|
||||
* LedgerResponse ledger = vehicleInfoService.getLedgerInfo("12가3456");
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public interface VehicleInfoService {
|
||||
|
||||
/**
|
||||
* 단일 차량에 대한 정보 조회 (상세 파라미터 포함)
|
||||
*
|
||||
* <p>차량 기본정보와 등록원부 정보를 함께 조회합니다.</p>
|
||||
* <p>차량번호 외에 부과기준일, 조회구분, 차대번호 등 추가 파라미터를 포함하여 조회할 수 있습니다.</p>
|
||||
*
|
||||
* @param basicRequest 기본정보 조회 요청 (차량번호, 부과기준일, 조회구분 등 포함)
|
||||
* @return 차량 정보 응답 (기본정보 + 등록원부 정보)
|
||||
*/
|
||||
VehicleApiResponseVO getVehicleInfo(BasicRequest basicRequest);
|
||||
|
||||
/**
|
||||
* 차량 기본정보만 조회 (단독)
|
||||
* 중요: 차량번호 외에 부과기준일, 조회구분, 차대번호 등 필수 파라미터를 모두 포함한 BasicRequest 필요
|
||||
*
|
||||
* @param request 기본정보 조회 요청 (차량번호, 부과기준일, 조회구분 등 포함)
|
||||
* @return 기본정보 응답
|
||||
*/
|
||||
BasicResponse getBasicInfo(BasicRequest request);
|
||||
|
||||
/**
|
||||
* 자동차 등록원부(갑)만 조회 (단독)
|
||||
* 중요: 차량번호 외에 소유자정보, 조회구분 등 필수 파라미터를 모두 포함한 LedgerRequest 필요
|
||||
*
|
||||
* @param request 등록원부 조회 요청 (차량번호, 소유자정보, 조회구분 등 포함)
|
||||
* @return 등록원부 응답
|
||||
*/
|
||||
LedgerResponse getLedgerInfo(LedgerRequest request);
|
||||
}
|
||||
@ -1,434 +0,0 @@
|
||||
package go.kr.project.api.service.impl;
|
||||
|
||||
import egovframework.exception.MessageException;
|
||||
import go.kr.project.api.config.ApiConstant;
|
||||
import go.kr.project.api.config.properties.VmisProperties;
|
||||
import go.kr.project.api.model.*;
|
||||
import go.kr.project.api.service.ExternalVehicleApiService;
|
||||
import go.kr.project.api.util.ExceptionDetailUtil;
|
||||
import go.kr.project.api.model.request.OldBasicRequest;
|
||||
import go.kr.project.api.model.request.NewBasicRequest;
|
||||
import go.kr.project.api.model.request.NewLedgerRequest;
|
||||
import go.kr.project.api.model.response.*;
|
||||
import go.kr.project.api.service.VmisCarBassMatterInqireLogService;
|
||||
import go.kr.project.api.service.VmisCarLedgerFrmbkLogService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 외부 VMIS-interface API 호출 서비스 구현체
|
||||
* VMIS-interface 프로그램의 API를 호출하여 차량 정보를 조회하는 서비스
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class ExternalVehicleApiServiceImpl extends EgovAbstractServiceImpl implements ExternalVehicleApiService {
|
||||
|
||||
private final RestTemplate restTemplate;
|
||||
private final VmisProperties vmisProperties;
|
||||
private final VmisCarBassMatterInqireLogService bassMatterLogService;
|
||||
private final VmisCarLedgerFrmbkLogService ledgerLogService;
|
||||
|
||||
|
||||
/**
|
||||
* 기본정보 조회 (YAML 설정에 따라 old/new 자동 선택)
|
||||
* vmis.external.api.url.basic.old-or-new 설정 값에 따라 자동 분기
|
||||
*/
|
||||
@Override
|
||||
public NewBasicResponse getBasicInfo(NewBasicRequest request) {
|
||||
String apiVersion = vmisProperties.getExternal().getApi().getUrl().getBasic().getOldOrNew();
|
||||
log.debug("[AUTO-BASIC] YAML 설정에 따른 API 버전: {}", apiVersion);
|
||||
|
||||
if ("old".equalsIgnoreCase(apiVersion)) {
|
||||
return callOldBasicApi(request);
|
||||
} else {
|
||||
return callNewBasicApi(request);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 등록원부(갑) 조회 (YAML 설정에 따라 old/new 자동 선택)
|
||||
* vmis.external.api.url.ledger.old-or-new 설정 값에 따라 자동 분기
|
||||
*/
|
||||
@Override
|
||||
public NewLedgerResponse getLedgerInfo(NewLedgerRequest request) {
|
||||
String apiVersion = vmisProperties.getExternal().getApi().getUrl().getLedger().getOldOrNew();
|
||||
log.debug("[AUTO-LEDGER] YAML 설정에 따른 API 버전: {}", apiVersion);
|
||||
|
||||
if ("old".equalsIgnoreCase(apiVersion)) {
|
||||
return null;
|
||||
} else {
|
||||
return callNewLedgerApi(request);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 구 기본정보 API 호출 (내부용)
|
||||
*/
|
||||
private NewBasicResponse callOldBasicApi(NewBasicRequest newRequest) {
|
||||
log.debug("[OLD-BASIC] 자동차 기본정보 조회 API 호출");
|
||||
|
||||
String generatedId = null;
|
||||
try {
|
||||
// NewBasicRequest → OldBasicRequest 변환
|
||||
OldBasicRequest oldRequest = convertToOldBasicRequest(newRequest);
|
||||
|
||||
CarBassMatterInqireVO logEntity = CarBassMatterInqireVO.fromOldRequest(oldRequest);
|
||||
generatedId = bassMatterLogService.createInitialRequestNewTx(logEntity);
|
||||
|
||||
Envelope<OldBasicRequest> requestEnvelope = new Envelope<>(oldRequest);
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
HttpEntity<Envelope<OldBasicRequest>> requestEntity = new HttpEntity<>(requestEnvelope, headers);
|
||||
|
||||
ResponseEntity<ApiExchangeEnvelope<OldBasicRequest, OldBasicResponse>> responseEntity = restTemplate.exchange(
|
||||
vmisProperties.getExternal().getApi().getUrl().buildOldBasicUrl(),
|
||||
HttpMethod.POST,
|
||||
requestEntity,
|
||||
new ParameterizedTypeReference<ApiExchangeEnvelope<OldBasicRequest, OldBasicResponse>>() {}
|
||||
);
|
||||
|
||||
if (responseEntity.getStatusCode() == HttpStatus.OK && responseEntity.getBody() != null) {
|
||||
ApiExchangeEnvelope<OldBasicRequest, OldBasicResponse> env = responseEntity.getBody();
|
||||
List<OldBasicResponse> data = (env.getResponse() != null) ? env.getResponse().getData() : null;
|
||||
if (data != null && !data.isEmpty()) {
|
||||
OldBasicResponse oldBody = data.get(0);
|
||||
// 응답 정보 업데이트 (txId 포함)
|
||||
CarBassMatterInqireVO responseUpdate = CarBassMatterInqireVO.fromOldExchange(generatedId, env);
|
||||
bassMatterLogService.updateResponseNewTx(responseUpdate);
|
||||
|
||||
log.debug("[OLD-BASIC] txId: {}", env.getTxId());
|
||||
// OldBasicResponse를 NewBasicResponse로 변환하여 반환
|
||||
NewBasicResponse newResponse = convertToNewBasicResponse(oldBody);
|
||||
// txId를 response에 설정
|
||||
newResponse.setTxId(env.getTxId());
|
||||
newResponse.setGeneratedId(generatedId);
|
||||
|
||||
return newResponse;
|
||||
}
|
||||
}
|
||||
|
||||
log.warn("[OLD-BASIC] 응답이 비어있음");
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
if (generatedId != null) {
|
||||
try {
|
||||
String detail = ExceptionDetailUtil.buildForLog(e);
|
||||
CarBassMatterInqireVO errorLog = CarBassMatterInqireVO.builder()
|
||||
.carBassMatterInqireId(generatedId)
|
||||
.linkRsltCd(ApiConstant.CNTC_RESULT_CODE_ERROR)
|
||||
.linkRsltDtl(detail)
|
||||
.build();
|
||||
bassMatterLogService.updateResponseNewTx(errorLog);
|
||||
log.error("[EXTERNAL-OLD-BASIC-ERR-LOG] 저장 완료 - ID: {}, detail: {}", generatedId, detail, e);
|
||||
} catch (Exception ignore) {
|
||||
log.error("[EXTERNAL-OLD-BASIC-ERR-LOG] 에러 로그 저장 실패 - ID: {}", generatedId, ignore);
|
||||
}
|
||||
}
|
||||
throw new MessageException("[OLD-BASIC] 차량 기본정보 조회 실패: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 신 기본정보 API 호출 (내부용)
|
||||
*/
|
||||
private NewBasicResponse callNewBasicApi(NewBasicRequest request) {
|
||||
log.debug("[NEW-BASIC] 자동차 기본정보 조회 API 호출");
|
||||
|
||||
String generatedId = null;
|
||||
try {
|
||||
CarBassMatterInqireVO logEntity = CarBassMatterInqireVO.fromNewRequest(request);
|
||||
generatedId = bassMatterLogService.createInitialRequestNewTx(logEntity);
|
||||
|
||||
Envelope<NewBasicRequest> requestEnvelope = new Envelope<>(request);
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
HttpEntity<Envelope<NewBasicRequest>> requestEntity = new HttpEntity<>(requestEnvelope, headers);
|
||||
|
||||
ResponseEntity<ApiExchangeEnvelope<NewBasicRequest, NewBasicResponse>> responseEntity = restTemplate.exchange(
|
||||
vmisProperties.getExternal().getApi().getUrl().buildNewBasicUrl(),
|
||||
HttpMethod.POST,
|
||||
requestEntity,
|
||||
new ParameterizedTypeReference<ApiExchangeEnvelope<NewBasicRequest, NewBasicResponse>>() {}
|
||||
);
|
||||
|
||||
if (responseEntity.getStatusCode() == HttpStatus.OK && responseEntity.getBody() != null) {
|
||||
ApiExchangeEnvelope<NewBasicRequest, NewBasicResponse> env = responseEntity.getBody();
|
||||
List<NewBasicResponse> data = (env.getResponse() != null) ? env.getResponse().getData() : null;
|
||||
if (data != null && !data.isEmpty()) {
|
||||
NewBasicResponse body = data.get(0);
|
||||
// 응답 정보 업데이트 (txId 포함)
|
||||
CarBassMatterInqireVO responseUpdate = CarBassMatterInqireVO.fromNewExchange(generatedId, env);
|
||||
bassMatterLogService.updateResponseNewTx(responseUpdate);
|
||||
|
||||
// txId를 response에 설정
|
||||
body.setTxId(env.getTxId());
|
||||
body.setGeneratedId(generatedId);
|
||||
|
||||
log.debug("[NEW-BASIC] txId: {}", env.getTxId());
|
||||
return body;
|
||||
}
|
||||
}
|
||||
|
||||
log.warn("[NEW-BASIC] 응답이 비어있음");
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
if (generatedId != null) {
|
||||
try {
|
||||
String detail = ExceptionDetailUtil.buildForLog(e);
|
||||
CarBassMatterInqireVO errorLog = CarBassMatterInqireVO.builder()
|
||||
.carBassMatterInqireId(generatedId)
|
||||
.linkRsltCd(ApiConstant.CNTC_RESULT_CODE_ERROR)
|
||||
.linkRsltDtl(detail)
|
||||
.build();
|
||||
bassMatterLogService.updateResponseNewTx(errorLog);
|
||||
log.error("[EXTERNAL-NEW-BASIC-ERR-LOG] 저장 완료 - ID: {}, detail: {}", generatedId, detail, e);
|
||||
} catch (Exception ignore) {
|
||||
log.error("[EXTERNAL-NEW-BASIC-ERR-LOG] 에러 로그 저장 실패 - ID: {}", generatedId, ignore);
|
||||
}
|
||||
}
|
||||
throw new MessageException("[NEW-BASIC] 차량 기본정보 조회 실패: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 신 등록원부 API 호출 (내부용)
|
||||
*/
|
||||
private NewLedgerResponse callNewLedgerApi(NewLedgerRequest request) {
|
||||
log.debug("[NEW-LEDGER] 자동차 등록원부 조회 API 호출");
|
||||
|
||||
String generatedId = null;
|
||||
try {
|
||||
CarLedgerFrmbkVO init = CarLedgerFrmbkVO.fromNewRequest(request);
|
||||
generatedId = ledgerLogService.createInitialRequestNewTx(init);
|
||||
|
||||
Envelope<NewLedgerRequest> requestEnvelope = new Envelope<>(request);
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
HttpEntity<Envelope<NewLedgerRequest>> requestEntity = new HttpEntity<>(requestEnvelope, headers);
|
||||
|
||||
ResponseEntity<ApiExchangeEnvelope<NewLedgerRequest, NewLedgerResponse>> responseEntity = restTemplate.exchange(
|
||||
vmisProperties.getExternal().getApi().getUrl().buildNewLedgerUrl(),
|
||||
HttpMethod.POST,
|
||||
requestEntity,
|
||||
new ParameterizedTypeReference<ApiExchangeEnvelope<NewLedgerRequest, NewLedgerResponse>>() {}
|
||||
);
|
||||
|
||||
if (responseEntity.getStatusCode() == HttpStatus.OK && responseEntity.getBody() != null) {
|
||||
ApiExchangeEnvelope<NewLedgerRequest, NewLedgerResponse> env = responseEntity.getBody();
|
||||
List<NewLedgerResponse> data = (env.getResponse() != null) ? env.getResponse().getData() : null;
|
||||
if (data != null && !data.isEmpty()) {
|
||||
NewLedgerResponse body = data.get(0);
|
||||
CarLedgerFrmbkVO masterUpdate = CarLedgerFrmbkVO.fromNewResponseMaster(generatedId, body);
|
||||
masterUpdate.setTxId(env.getTxId());
|
||||
ledgerLogService.updateResponseNewTx(masterUpdate);
|
||||
|
||||
List<CarLedgerFrmbkDtlVO> details = CarLedgerFrmbkDtlVO.listNewFromExchange(env, generatedId);
|
||||
if (details != null && !details.isEmpty()) {
|
||||
ledgerLogService.saveDetailsNewTx(generatedId, details);
|
||||
}
|
||||
|
||||
// txId를 response에 설정
|
||||
body.setTxId(env.getTxId());
|
||||
body.setGeneratedId(generatedId);
|
||||
|
||||
log.debug("[NEW-LEDGER] txId: {}", env.getTxId());
|
||||
return body;
|
||||
}
|
||||
}
|
||||
|
||||
log.warn("[NEW-LEDGER] 자동차 등록원부 조회 응답이 비어있음");
|
||||
return null;
|
||||
|
||||
} catch (Exception e) {
|
||||
if (generatedId != null) {
|
||||
try {
|
||||
String detail = ExceptionDetailUtil.buildForLog(e);
|
||||
CarLedgerFrmbkVO errorLog = CarLedgerFrmbkVO.builder()
|
||||
.carLedgerFrmbkId(generatedId)
|
||||
.linkRsltCd(ApiConstant.CNTC_RESULT_CODE_ERROR)
|
||||
.linkRsltDtl(detail)
|
||||
.build();
|
||||
ledgerLogService.updateResponseNewTx(errorLog);
|
||||
log.error("[EXTERNAL-NEW-LEDGER-ERR-LOG] API 호출 에러 정보 저장 완료(별도TX) - ID: {}, detail: {}", generatedId, detail, e);
|
||||
} catch (Exception ignore) {
|
||||
log.error("[EXTERNAL-NEW-LEDGER-ERR-LOG] 에러 로그 저장 실패 - ID: {}", generatedId, ignore);
|
||||
}
|
||||
}
|
||||
log.error("[NEW-LEDGER] 자동차 등록원부 조회 API 호출 실패", e);
|
||||
throw new MessageException("[NEW-LEDGER] 자동차 등록원부 조회 실패: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* NewBasicRequest를 OldBasicRequest로 변환
|
||||
*/
|
||||
private OldBasicRequest convertToOldBasicRequest(NewBasicRequest newRequest) {
|
||||
OldBasicRequest oldRequest = new OldBasicRequest();
|
||||
|
||||
// 공통 메타 정보 복사 (필드명이 다름)
|
||||
oldRequest.setInfoSysId(newRequest.getInfoSysId());
|
||||
oldRequest.setInfoSysIp(newRequest.getInfoSysIpAddr());
|
||||
oldRequest.setSigunguCode(newRequest.getSggCd());
|
||||
oldRequest.setCntcInfoCode(newRequest.getLinkInfoCd());
|
||||
oldRequest.setChargerId(newRequest.getPicId());
|
||||
oldRequest.setChargerIp(newRequest.getPicIpAddr());
|
||||
oldRequest.setChargerNm(newRequest.getPicNm());
|
||||
|
||||
// Record 변환
|
||||
if (newRequest.getRecord() != null && !newRequest.getRecord().isEmpty()) {
|
||||
List<OldBasicRequest.Record> oldRecords = newRequest.getRecord().stream()
|
||||
.map(this::convertToOldRecord)
|
||||
.collect(Collectors.toList());
|
||||
oldRequest.setRecord(oldRecords);
|
||||
}
|
||||
|
||||
return oldRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* NewBasicRequest.Record를 OldBasicRequest.Record로 변환
|
||||
*/
|
||||
private OldBasicRequest.Record convertToOldRecord(NewBasicRequest.Record newRecord) {
|
||||
OldBasicRequest.Record oldRecord = new OldBasicRequest.Record();
|
||||
oldRecord.setLevyStdde(newRecord.getLevyCrtrYmd());
|
||||
oldRecord.setInqireSeCode(newRecord.getInqSeCd());
|
||||
oldRecord.setVhrno(newRecord.getVhrno());
|
||||
oldRecord.setVin(newRecord.getVin());
|
||||
return oldRecord;
|
||||
}
|
||||
|
||||
/**
|
||||
* OldBasicResponse를 NewBasicResponse로 변환
|
||||
*
|
||||
* @param oldResponse 구 API 응답 객체
|
||||
* @return 신 API 응답 형식의 객체
|
||||
*/
|
||||
private NewBasicResponse convertToNewBasicResponse(OldBasicResponse oldResponse) {
|
||||
if (oldResponse == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
NewBasicResponse newResponse = new NewBasicResponse();
|
||||
|
||||
// 공통 응답 필드 변환 (필드명이 다름)
|
||||
newResponse.setLinkRsltCd(oldResponse.getCntcResultCode());
|
||||
newResponse.setLinkRsltDtl(oldResponse.getCntcResultDtls());
|
||||
|
||||
// Record 변환
|
||||
if (oldResponse.getRecord() != null && !oldResponse.getRecord().isEmpty()) {
|
||||
List<NewBasicResponse.Record> newRecords = oldResponse.getRecord().stream()
|
||||
.map(this::convertOldRecordToNewRecord)
|
||||
.collect(Collectors.toList());
|
||||
newResponse.setRecord(newRecords);
|
||||
}
|
||||
|
||||
return newResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* OldBasicResponse.Record를 NewBasicResponse.Record로 변환
|
||||
*
|
||||
* @param oldRecord 구 API Record 객체
|
||||
* @return 신 API Record 객체
|
||||
*/
|
||||
private NewBasicResponse.Record convertOldRecordToNewRecord(OldBasicResponse.Record oldRecord) {
|
||||
NewBasicResponse.Record newRecord = new NewBasicResponse.Record();
|
||||
|
||||
// 필드명 매핑 (구 → 신)
|
||||
newRecord.setYridnw(oldRecord.getPrye());
|
||||
newRecord.setRegYmd(oldRecord.getRegistDe());
|
||||
newRecord.setErsrRegSeCd(oldRecord.getErsrRegistSeCode());
|
||||
newRecord.setErsrRegSeNm(oldRecord.getErsrRegistSeNm());
|
||||
newRecord.setErsrRegYmd(oldRecord.getErsrRegistDe());
|
||||
newRecord.setRegDtlCd(oldRecord.getRegistDetailCode());
|
||||
newRecord.setDsplvl(oldRecord.getDsplvl());
|
||||
newRecord.setUsgsrhldStdgCd(oldRecord.getUseStrnghldLegaldongCode());
|
||||
newRecord.setUsgsrhldDongCd(oldRecord.getUseStrnghldAdstrdCode());
|
||||
newRecord.setUsgsrhldMtnYn(oldRecord.getUseStrnghldMntn());
|
||||
newRecord.setUsgsrhldLnbr(oldRecord.getUseStrnghldLnbr());
|
||||
newRecord.setUsgsrhldHo(oldRecord.getUseStrnghldHo());
|
||||
newRecord.setUsgsrhldAddrNm(oldRecord.getUseStrnghldAdresNm());
|
||||
newRecord.setUsgsrhldRoadNmCd(oldRecord.getUseStrnghldRoadNmCode());
|
||||
newRecord.setUsgsrhldUdgdBldgSeCd(oldRecord.getUsgsrhldUndgrndBuldSeCode());
|
||||
newRecord.setUsgsrhldBmno(oldRecord.getUseStrnghldBuldMainNo());
|
||||
newRecord.setUsgsrhldBsno(oldRecord.getUseStrnghldBuldSubNo());
|
||||
newRecord.setUsgsrhldWholAddr(oldRecord.getUsgsrhldAdresFull());
|
||||
newRecord.setRprsOwnrMbrSeCd(oldRecord.getMberSeCode());
|
||||
newRecord.setRprsOwnrNm(oldRecord.getMberNm());
|
||||
newRecord.setRprsvOwnrIdecno(oldRecord.getMberSeNo());
|
||||
newRecord.setRprsOwnrTelno(oldRecord.getTelno());
|
||||
newRecord.setOwnrStdgCd(oldRecord.getOwnerLegaldongCode());
|
||||
newRecord.setOwnrDongCd(oldRecord.getOwnerAdstrdCode());
|
||||
newRecord.setOwnrMtnYn(oldRecord.getOwnerMntn());
|
||||
newRecord.setOwnrLnbr(oldRecord.getOwnerLnbr());
|
||||
newRecord.setOwnrHo(oldRecord.getOwnerHo());
|
||||
newRecord.setOwnrAddrNm(oldRecord.getOwnerAdresNm());
|
||||
newRecord.setOwnrRoadNmCd(oldRecord.getOwnerRoadNmCode());
|
||||
newRecord.setOwnrUdgdBldgSeCd(oldRecord.getOwnerUndgrndBuldSeCode());
|
||||
newRecord.setOwnrBmno(oldRecord.getOwnerBuldMainNo());
|
||||
newRecord.setOwnrBsno(oldRecord.getOwnerBuldSubNo());
|
||||
newRecord.setOwnrWholAddr(oldRecord.getOwnerAdresFull());
|
||||
newRecord.setRearVhrno(oldRecord.getAftrVhrno());
|
||||
newRecord.setUseFuelCd(oldRecord.getUseFuelCode());
|
||||
newRecord.setUsgSeCd(oldRecord.getPrposSeCode());
|
||||
newRecord.setMtrsFomNm(oldRecord.getMtrsFomNm());
|
||||
newRecord.setBfrVhrno(oldRecord.getFrntVhrno());
|
||||
newRecord.setVhrno(oldRecord.getVhrno());
|
||||
newRecord.setVin(oldRecord.getVin());
|
||||
newRecord.setAtmbNm(oldRecord.getCnm());
|
||||
newRecord.setVhclTotlWt(oldRecord.getVhcleTotWt());
|
||||
newRecord.setVeagEndYmd(oldRecord.getCaagEndde());
|
||||
newRecord.setChgYmd(oldRecord.getChangeDe());
|
||||
newRecord.setCarmdlAsortCd(oldRecord.getVhctyAsortCode());
|
||||
newRecord.setCarmdlTypeCd(oldRecord.getVhctyTyCode());
|
||||
newRecord.setCarmdlSeCd(oldRecord.getVhctySeCode());
|
||||
newRecord.setMxmmLdg(oldRecord.getMxmmLdg());
|
||||
newRecord.setCarmdlAsortNm(oldRecord.getVhctyAsortNm());
|
||||
newRecord.setCarmdlTypeNm(oldRecord.getVhctyTyNm());
|
||||
newRecord.setCarmdlClsfNm(oldRecord.getVhctySeNm());
|
||||
newRecord.setFrstRegYmd(oldRecord.getFrstRegistDe());
|
||||
newRecord.setFomNm(oldRecord.getFomNm());
|
||||
newRecord.setAcqsYmd(oldRecord.getAcqsDe());
|
||||
newRecord.setAcqsEndYmd(oldRecord.getAcqsEndDe());
|
||||
newRecord.setFbctnYmd(oldRecord.getYblMd());
|
||||
newRecord.setTransrRegYmd(oldRecord.getTransrRegistDe());
|
||||
newRecord.setSpcfRegSttsCd(oldRecord.getSpcfRegistSttusCode());
|
||||
newRecord.setColorNm(oldRecord.getColorNm());
|
||||
newRecord.setMrtgCnt(oldRecord.getMrtgCo());
|
||||
newRecord.setSzrCnt(oldRecord.getSeizrCo());
|
||||
newRecord.setStrctChgCnt(oldRecord.getStmdCo());
|
||||
newRecord.setNoplTcsdyYn(oldRecord.getNmplCsdyAt());
|
||||
newRecord.setNoplTcsdyAvtsmtYmd(oldRecord.getNmplCsdyRemnrDe());
|
||||
newRecord.setSrcSeCd(oldRecord.getOriginSeCode());
|
||||
newRecord.setNoplTSpcfctCd(oldRecord.getNmplStndrdCode());
|
||||
newRecord.setAcqsAmt(oldRecord.getAcqsAmount());
|
||||
newRecord.setInspVldPdBgngYmd(oldRecord.getInsptValidPdBgnde());
|
||||
newRecord.setInspVldPdEndYmd(oldRecord.getInsptValidPdEndde());
|
||||
newRecord.setUsgsrhldGrcCd(oldRecord.getUseStrnghldGrcCode());
|
||||
newRecord.setRdcpctCnt(oldRecord.getTkcarPscapCo());
|
||||
newRecord.setSpmnno(oldRecord.getSpmnno());
|
||||
newRecord.setDrvngDstnc(oldRecord.getTrvlDstnc());
|
||||
newRecord.setFrstRegAplyRcptNo(oldRecord.getFrstRegistRqrcno());
|
||||
newRecord.setVlntErsrPrvntcAvtsmtYmd(oldRecord.getVlntErsrPrvntcNticeDe());
|
||||
newRecord.setOgnzNm(oldRecord.getRegistInsttNm());
|
||||
newRecord.setPrcsImprtyRsnCd(oldRecord.getProcessImprtyResnCode());
|
||||
newRecord.setPrcsImprtyRsnDtls(oldRecord.getProcessImprtyResnDtls());
|
||||
newRecord.setCbdLt(oldRecord.getCbdLt());
|
||||
newRecord.setCbdBt(oldRecord.getCbdBt());
|
||||
newRecord.setCbdHg(oldRecord.getCbdHg());
|
||||
newRecord.setFrstMxmmLdg(oldRecord.getFrstMxmmLdg());
|
||||
newRecord.setFuelCnsmprt(oldRecord.getFuelCnsmpRt());
|
||||
newRecord.setElctyCmpndFuelCnsmprt(oldRecord.getElctyCmpndFuelCnsmpRt());
|
||||
|
||||
return newRecord;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,331 @@
|
||||
package go.kr.project.carInspectionPenalty.history.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.*;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* packageName : go.kr.project.carInspectionPenalty.history.model
|
||||
* fileName : CarBassMatterInqireVO
|
||||
* author : 시스템 관리자
|
||||
* date : 2025-11-06
|
||||
* description : 자동차 기본 사항 조회 이력 VO
|
||||
* ===========================================================
|
||||
* DATE AUTHOR NOTE
|
||||
* -----------------------------------------------------------
|
||||
* 2025-11-06 시스템 관리자 최초 생성
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
public class CarBassMatterInqireVO {
|
||||
|
||||
/** 자동차 기본 사항 조회 ID */
|
||||
private String carBassMatterInqireId;
|
||||
|
||||
/** 정보 시스템 ID */
|
||||
private String infoSysId;
|
||||
|
||||
/** 정보 시스템 IP */
|
||||
private String infoSysIp;
|
||||
|
||||
/** 시군구 코드 */
|
||||
private String sigunguCode;
|
||||
|
||||
/** 연계 정보 코드 */
|
||||
private String cntcInfoCode;
|
||||
|
||||
/** 담당자 ID */
|
||||
private String chargerId;
|
||||
|
||||
/** 담당자 IP */
|
||||
private String chargerIp;
|
||||
|
||||
/** 담당자명 */
|
||||
private String chargerNm;
|
||||
|
||||
/** 요청 부과 기준일 */
|
||||
private String dmndLevyStdde;
|
||||
|
||||
/** 요청 조회 구분 코드 */
|
||||
private String dmndInqireSeCode;
|
||||
|
||||
/** 요청 자동차등록번호 */
|
||||
private String dmndVhrno;
|
||||
|
||||
/** 요청 차대번호 */
|
||||
private String dmndVin;
|
||||
|
||||
/** 연계 결과 코드 */
|
||||
private String cntcResultCode;
|
||||
|
||||
/** 연계 결과 상세 */
|
||||
private String cntcResultDtls;
|
||||
|
||||
/** 연식 */
|
||||
private String prye;
|
||||
|
||||
/** 등록일 */
|
||||
private String registDe;
|
||||
|
||||
/** 말소 등록 구분 코드 */
|
||||
private String ersrRegistSeCode;
|
||||
|
||||
/** 말소 등록 구분명 */
|
||||
private String ersrRegistSeNm;
|
||||
|
||||
/** 말소 등록일 */
|
||||
private String ersrRegistDe;
|
||||
|
||||
/** 등록 상세 코드 */
|
||||
private String registDetailCode;
|
||||
|
||||
/** 배기량 */
|
||||
private String dsplvl;
|
||||
|
||||
/** 사용 본거지 법정동 코드 */
|
||||
private String useStrnghldLegaldongCode;
|
||||
|
||||
/** 사용 본거지 행정동 코드 */
|
||||
private String useStrnghldAdstrdCode;
|
||||
|
||||
/** 사용 본거지 산 */
|
||||
private String useStrnghldMntn;
|
||||
|
||||
/** 사용 본거지 번지 */
|
||||
private String useStrnghldLnbr;
|
||||
|
||||
/** 사용 본거지 호 */
|
||||
private String useStrnghldHo;
|
||||
|
||||
/** 사용 본거지 상세주소 */
|
||||
private String useStrnghldAdresNm;
|
||||
|
||||
/** 사용 본거지 도로명 코드 */
|
||||
private String useStrnghldRoadNmCode;
|
||||
|
||||
/** 사용 본거지 지하 건물 구분 코드 */
|
||||
private String usgsrhldUndgrndBuldSeCode;
|
||||
|
||||
/** 사용 본거지 건물 주요 번호 */
|
||||
private String useStrnghldBuldMainNo;
|
||||
|
||||
/** 사용 본거지 건물 부 번호 */
|
||||
private String useStrnghldBuldSubNo;
|
||||
|
||||
/** 사용 본거지 전체주소 */
|
||||
private String usgsrhldAdresFull;
|
||||
|
||||
/** 대표소유자 회원 구분 코드 */
|
||||
private String mberSeCode;
|
||||
|
||||
/** 대표소유자 회원 번호 */
|
||||
private String mberSeNo;
|
||||
|
||||
/** 대표소유자 전화번호 */
|
||||
private String telno;
|
||||
|
||||
/** 소유자 법정동 코드 */
|
||||
private String ownerLegaldongCode;
|
||||
|
||||
/** 소유자 행정동 코드 */
|
||||
private String ownerAdstrdCode;
|
||||
|
||||
/** 소유자 산 */
|
||||
private String ownerMntn;
|
||||
|
||||
/** 소유자 번지 */
|
||||
private String ownerLnbr;
|
||||
|
||||
/** 소유자 호 */
|
||||
private String ownerHo;
|
||||
|
||||
/** 소유자 상세주소 */
|
||||
private String ownerAdresNm;
|
||||
|
||||
/** 소유자 도로명 코드 */
|
||||
private String ownerRoadNmCode;
|
||||
|
||||
/** 소유자 지하건물 구분 코드 */
|
||||
private String ownerUndgrndBuldSeCode;
|
||||
|
||||
/** 소유자 건물 주요 번호 */
|
||||
private String ownerBuldMainNo;
|
||||
|
||||
/** 소유자 건물 부 번호 */
|
||||
private String ownerBuldSubNo;
|
||||
|
||||
/** 소유자 전체주소 */
|
||||
private String ownrWholaddr;
|
||||
|
||||
/** 신 차량번호 */
|
||||
private String aftrVhrno;
|
||||
|
||||
/** 사용 연료 코드 */
|
||||
private String useFuelCode;
|
||||
|
||||
/** 용도 구분 코드 */
|
||||
private String prposSeCode;
|
||||
|
||||
/** 원동기 형식명 */
|
||||
private String mtrsFomNm;
|
||||
|
||||
/** 이전 차량번호 */
|
||||
private String frntVhrno;
|
||||
|
||||
/** 차량번호 */
|
||||
private String vhrno;
|
||||
|
||||
/** 차대번호 */
|
||||
private String vin;
|
||||
|
||||
/** 차명 */
|
||||
private String cnm;
|
||||
|
||||
/** 차량 총 중량 */
|
||||
private String vhcleTotWt;
|
||||
|
||||
/** 차령 만료일자 */
|
||||
private String caagEndde;
|
||||
|
||||
/** 차번호 변경시기 */
|
||||
private String changeDe;
|
||||
|
||||
/** 차종 종별 코드 */
|
||||
private String vhctyAsortCode;
|
||||
|
||||
/** 차종 유형 코드 */
|
||||
private String vhctyTyCode;
|
||||
|
||||
/** 차종 분류 코드 */
|
||||
private String vhctySeCode;
|
||||
|
||||
/** 최대 적재량 */
|
||||
private String mxmmLdg;
|
||||
|
||||
/** 차종 종별명 */
|
||||
private String vhctyAsortNm;
|
||||
|
||||
/** 차종 유형명 */
|
||||
private String vhctyTyNm;
|
||||
|
||||
/** 차종 분류명 */
|
||||
private String vhctySeNm;
|
||||
|
||||
/** 최초 등록일 */
|
||||
private String frstRegistDe;
|
||||
|
||||
/** 형식 */
|
||||
private String fomNm;
|
||||
|
||||
/** 취득 일자 */
|
||||
private String acqsDe;
|
||||
|
||||
/** 취득 종료일자 */
|
||||
private String acqsEndDe;
|
||||
|
||||
/** 제작 년월일 */
|
||||
private String yblMd;
|
||||
|
||||
/** 이전 등록일 */
|
||||
private String transrRegistDe;
|
||||
|
||||
/** 제원 등록 상태 코드 */
|
||||
private String spcfRegistSttusCode;
|
||||
|
||||
/** 색상명 */
|
||||
private String colorNm;
|
||||
|
||||
/** 저당수 */
|
||||
private String mrtgCo;
|
||||
|
||||
/** 압류건수 */
|
||||
private String seizrCo;
|
||||
|
||||
/** 구조변경수 */
|
||||
private String stmdCo;
|
||||
|
||||
/** 번호판 영치 여부 */
|
||||
private String nmplCsdyAt;
|
||||
|
||||
/** 번호판 영치 최고일 */
|
||||
private String nmplCsdyRemnrDe;
|
||||
|
||||
/** 출처 구분 코드 */
|
||||
private String originSeCode;
|
||||
|
||||
/** 번호판 규격 코드 */
|
||||
private String nmplStndrdCode;
|
||||
|
||||
/** 취득 금액 */
|
||||
private String acqsAmount;
|
||||
|
||||
/** 검사 유효 기간 시작일 */
|
||||
private String insptValidPdBgnde;
|
||||
|
||||
/** 검사 유효 기간 종료일 */
|
||||
private String insptValidPdEndde;
|
||||
|
||||
/** 사용 본거지 관청 코드 */
|
||||
private String useStrnghldGrcCode;
|
||||
|
||||
/** 승차정원수 */
|
||||
private String tkcarPscapCo;
|
||||
|
||||
/** 제원관리번호 */
|
||||
private String spmnno;
|
||||
|
||||
/** 주행거리 */
|
||||
private String trvlDstnc;
|
||||
|
||||
/** 최초 등록 접수번호 */
|
||||
private String frstRegistRqrcno;
|
||||
|
||||
/** 예고통지일 */
|
||||
private String vlntErsrPrvntcNticeDe;
|
||||
|
||||
/** 등록 기관명 */
|
||||
private String registInsttNm;
|
||||
|
||||
/** 처리 불가 사유 코드 */
|
||||
private String processImprtyResnCode;
|
||||
|
||||
/** 처리 불가 사유 명세 */
|
||||
private String processImprtyResnDtls;
|
||||
|
||||
/** 차체 길이 */
|
||||
private String cbdLt;
|
||||
|
||||
/** 차체 너비 */
|
||||
private String cbdBt;
|
||||
|
||||
/** 차체 높이 */
|
||||
private String cbdHg;
|
||||
|
||||
/** 최초 최대 적재량 */
|
||||
private String frstMxmmLdg;
|
||||
|
||||
/** 연료 소비율 */
|
||||
private String fuelCnsmpRt;
|
||||
|
||||
/** 전기 복합 연료 소비율 */
|
||||
private String elctyCmpndFuelCnsmpRt;
|
||||
|
||||
/** 등록 일시 */
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
|
||||
private LocalDateTime regDt;
|
||||
|
||||
/** 등록자 */
|
||||
private String rgtr;
|
||||
|
||||
/** 등록자명 */
|
||||
private String rgtrNm;
|
||||
|
||||
/** 대표소유자 성명 */
|
||||
private String mberNm;
|
||||
}
|
||||
@ -0,0 +1,79 @@
|
||||
package go.kr.project.carInspectionPenalty.history.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.*;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* packageName : go.kr.project.carInspectionPenalty.history.model
|
||||
* fileName : CarLedgerFrmbkDtlVO
|
||||
* author : 시스템 관리자
|
||||
* date : 2025-11-06
|
||||
* description : 자동차 등록 원부 갑 상세 이력 VO
|
||||
* ===========================================================
|
||||
* DATE AUTHOR NOTE
|
||||
* -----------------------------------------------------------
|
||||
* 2025-11-06 시스템 관리자 최초 생성
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
public class CarLedgerFrmbkDtlVO {
|
||||
|
||||
/** 자동차 등록 원부 갑 상세 ID */
|
||||
private String carLedgerFrmbkDtlId;
|
||||
|
||||
/** 자동차 등록 원부 갑 ID */
|
||||
private String carLedgerFrmbkId;
|
||||
|
||||
/** 해제여부 */
|
||||
private String mainchk;
|
||||
|
||||
/** 변경 업무 구분 코드 */
|
||||
private String changeJobSeCode;
|
||||
|
||||
/** 주번호 */
|
||||
private String mainno;
|
||||
|
||||
/** 부번호 */
|
||||
private String subno;
|
||||
|
||||
/** 사항란 */
|
||||
private String dtls;
|
||||
|
||||
/** 접수번호 */
|
||||
private String rqrcno;
|
||||
|
||||
/** 차량관리번호 */
|
||||
private String vhmno;
|
||||
|
||||
/** 원부 그룹 번호 */
|
||||
private String ledgerGroupNo;
|
||||
|
||||
/** 원부 개별 번호 */
|
||||
private String ledgerIndvdlzNo;
|
||||
|
||||
/** 변경 업무 구분명 */
|
||||
private String gubunNm;
|
||||
|
||||
/** 변경 일자 */
|
||||
private String changeDe;
|
||||
|
||||
/** 상세 순번 */
|
||||
private String detailSn;
|
||||
|
||||
/** 표기여부 */
|
||||
private String flag;
|
||||
|
||||
/** 등록 일시 */
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
|
||||
private LocalDateTime regDt;
|
||||
|
||||
/** 등록자 */
|
||||
private String rgtr;
|
||||
}
|
||||
@ -0,0 +1,278 @@
|
||||
package go.kr.project.carInspectionPenalty.history.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.*;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* packageName : go.kr.project.carInspectionPenalty.history.model
|
||||
* fileName : CarLedgerFrmbkVO
|
||||
* author : 시스템 관리자
|
||||
* date : 2025-11-06
|
||||
* description : 자동차 등록 원부 갑 이력 VO
|
||||
* ===========================================================
|
||||
* DATE AUTHOR NOTE
|
||||
* -----------------------------------------------------------
|
||||
* 2025-11-06 시스템 관리자 최초 생성
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
public class CarLedgerFrmbkVO {
|
||||
|
||||
/** 자동차 등록 원부 갑 ID */
|
||||
private String carLedgerFrmbkId;
|
||||
|
||||
/** 정보 시스템 ID */
|
||||
private String infoSysId;
|
||||
|
||||
/** 정보 시스템 IP */
|
||||
private String infoSysIp;
|
||||
|
||||
/** 시군구 코드 */
|
||||
private String sigunguCode;
|
||||
|
||||
/** 연계 정보 코드 */
|
||||
private String cntcInfoCode;
|
||||
|
||||
/** 담당자 ID */
|
||||
private String chargerId;
|
||||
|
||||
/** 담당자 IP */
|
||||
private String chargerIp;
|
||||
|
||||
/** 담당자명 */
|
||||
private String chargerNm;
|
||||
|
||||
/** 요청 자동차등록번호 */
|
||||
private String dmndVhrno;
|
||||
|
||||
/** 요청 개인 정보 공개 */
|
||||
private String dmndOnesInformationOpen;
|
||||
|
||||
/** 요청 민원인 성명 */
|
||||
private String dmndCpttrNm;
|
||||
|
||||
/** 요청 민원인 주민번호 */
|
||||
private String dmndCpttrIhidnum;
|
||||
|
||||
/** 요청 민원인 법정동 코드 */
|
||||
private String dmndCpttrLegaldongCode;
|
||||
|
||||
/** 요청 경로 구분 코드 */
|
||||
private String dmndRouteSeCode;
|
||||
|
||||
/** 요청 내역 표시 */
|
||||
private String dmndDetailExpression;
|
||||
|
||||
/** 요청 조회 구분 코드 */
|
||||
private String dmndInqireSeCode;
|
||||
|
||||
/** 연계 결과 코드 */
|
||||
private String cntcResultCode;
|
||||
|
||||
/** 연계 결과 상세 */
|
||||
private String cntcResultDtls;
|
||||
|
||||
/** 원부 그룹 번호 */
|
||||
private String ledgerGroupNo;
|
||||
|
||||
/** 원부 개별 번호 */
|
||||
private String ledgerIndvdlzNo;
|
||||
|
||||
/** 차량관리번호 */
|
||||
private String vhmno;
|
||||
|
||||
/** 차량등록번호 */
|
||||
private String vhrno;
|
||||
|
||||
/** 차대번호 */
|
||||
private String vin;
|
||||
|
||||
/** 차종 종별 코드 */
|
||||
private String vhctyAsortCode;
|
||||
|
||||
/** 차종 종별명 */
|
||||
private String vhctyAsortNm;
|
||||
|
||||
/** 차명 */
|
||||
private String cnm;
|
||||
|
||||
/** 색상 코드 */
|
||||
private String colorCode;
|
||||
|
||||
/** 색상명 */
|
||||
private String colorNm;
|
||||
|
||||
/** 번호판 규격 코드 */
|
||||
private String nmplStndrdCode;
|
||||
|
||||
/** 번호판 규격명 */
|
||||
private String nmplStndrdNm;
|
||||
|
||||
/** 용도 구분 코드 */
|
||||
private String prposSeCode;
|
||||
|
||||
/** 용도 구분명 */
|
||||
private String prposSeNm;
|
||||
|
||||
/** 원동기 형식명 */
|
||||
private String mtrsFomNm;
|
||||
|
||||
/** 형식명 */
|
||||
private String fomNm;
|
||||
|
||||
/** 취득 금액 */
|
||||
private String acqsAmount;
|
||||
|
||||
/** 등록 상세 코드 */
|
||||
private String registDetailCode;
|
||||
|
||||
/** 등록 상세명 */
|
||||
private String registDetailNm;
|
||||
|
||||
/** 최초 등록일 */
|
||||
private String frstRegistDe;
|
||||
|
||||
/** 차령 종료일 */
|
||||
private String caagEndde;
|
||||
|
||||
/** 연식 */
|
||||
private String prye;
|
||||
|
||||
/** 제원관리번호1 */
|
||||
private String spmnno1;
|
||||
|
||||
/** 제원관리번호2 */
|
||||
private String spmnno2;
|
||||
|
||||
/** 제작 년월일 */
|
||||
private String yblMd;
|
||||
|
||||
/** 주행 거리 */
|
||||
private String trvlDstnc;
|
||||
|
||||
/** 검사 유효 기간 시작일 */
|
||||
private String insptValidPdBgnde;
|
||||
|
||||
/** 검사 유효 기간 종료일 */
|
||||
private String insptValidPdEndde;
|
||||
|
||||
/** 점검 유효 기간 시작일 */
|
||||
private String chckValidPdBgnde;
|
||||
|
||||
/** 점검 유효 기간 종료일 */
|
||||
private String chckValidPdEndde;
|
||||
|
||||
/** 등록 신청 구분명 */
|
||||
private String registReqstSeNm;
|
||||
|
||||
/** 최초 등록 접수번호 */
|
||||
private String frstRegistRqrcno;
|
||||
|
||||
/** 번호판 영치 최고일 */
|
||||
private String nmplCsdyRemnrDe;
|
||||
|
||||
/** 번호판 영치 여부 */
|
||||
private String nmplCsdyAt;
|
||||
|
||||
/** 사업용 사용 기간 */
|
||||
private String bssUsePd;
|
||||
|
||||
/** 직권 말소 예고 통지일 */
|
||||
private String octhtErsrPrvntcNticeDe;
|
||||
|
||||
/** 말소 등록일 */
|
||||
private String ersrRegistDe;
|
||||
|
||||
/** 말소 등록 구분 코드 */
|
||||
private String ersrRegistSeCode;
|
||||
|
||||
/** 말소 등록 구분명 */
|
||||
private String ersrRegistSeNm;
|
||||
|
||||
/** 저당수 */
|
||||
private String mrtgcnt;
|
||||
|
||||
/** 압류건수 */
|
||||
private String vhclecnt;
|
||||
|
||||
/** 구조변경수 */
|
||||
private String stmdcnt;
|
||||
|
||||
/** 사용 본거지 주소 */
|
||||
private String adres1;
|
||||
|
||||
/** 사용 본거지 주소상세 */
|
||||
private String adresNm1;
|
||||
|
||||
/** 소유자 주소 */
|
||||
private String adres;
|
||||
|
||||
/** 소유자 주소상세 */
|
||||
private String adresNm;
|
||||
|
||||
/** 개인 사업자 여부 */
|
||||
private String indvdlBsnmAt;
|
||||
|
||||
/** 대표소유자 전화번호 */
|
||||
private String telno;
|
||||
|
||||
/** 대표소유자 성명 */
|
||||
private String mberNm;
|
||||
|
||||
/** 대표소유자 회원 구분 코드 */
|
||||
private String mberSeCode;
|
||||
|
||||
/** 대표소유자 회원 번호 */
|
||||
private String mberSeNo;
|
||||
|
||||
/** 비과세 대상 구분 코드 */
|
||||
private String taxxmptTrgterSeCode;
|
||||
|
||||
/** 비과세 대상 구분 코드명 */
|
||||
private String taxxmptTrgterSeCodeNm;
|
||||
|
||||
/** 특기사항 건수 */
|
||||
private String cntMatter;
|
||||
|
||||
/** 사용 본거지 행정동명 */
|
||||
private String emdNm;
|
||||
|
||||
/** 예고수 */
|
||||
private String prvntccnt;
|
||||
|
||||
/** 수출 이행 여부 신고일 */
|
||||
private String xportFlflAtSttemntDe;
|
||||
|
||||
/** 발급번호 */
|
||||
private String partnRqrcno;
|
||||
|
||||
/** 최초 양도일 */
|
||||
private String frstTrnsfrDe;
|
||||
|
||||
/** 처리 불가 사유 코드 */
|
||||
private String processImprtyResnCode;
|
||||
|
||||
/** 처리 불가 사유 명세 */
|
||||
private String processImprtyResnDtls;
|
||||
|
||||
/** 등록 일시 */
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
|
||||
private LocalDateTime regDt;
|
||||
|
||||
/** 등록자 */
|
||||
private String rgtr;
|
||||
|
||||
/** 등록자명 */
|
||||
private String rgtrNm;
|
||||
|
||||
/** 등록원부 변경 이력 */
|
||||
private List<CarLedgerFrmbkDtlVO> record;
|
||||
}
|
||||
@ -1,132 +0,0 @@
|
||||
package go.kr.project.carInspectionPenalty.registration.model;
|
||||
|
||||
import egovframework.util.excel.ExcelColumn;
|
||||
import egovframework.util.excel.ExcelSheet;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* 과태료 대상 목록 엑셀 다운로드용 VO 클래스
|
||||
*
|
||||
* <p>엑셀 다운로드 시 사용되는 전용 VO로 @ExcelColumn 어노테이션을 포함</p>
|
||||
* <p>엑셀 샘플 순서에 맞게 필드를 정렬하고, 필요한 컬럼만 헤더 설정</p>
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
@ExcelSheet(name = "과태료대상목록")
|
||||
public class CarFfnlgTrgtExcelVO {
|
||||
|
||||
/** 접수일자 */
|
||||
@ExcelColumn(headerName = "접수일자", headerWidth = 15, align = ExcelColumn.Align.CENTER)
|
||||
private String rcptYmd;
|
||||
|
||||
/** 검사소코드 */
|
||||
@ExcelColumn(headerName = "검사소코드", headerWidth = 15, align = ExcelColumn.Align.CENTER)
|
||||
private String inspstnCd;
|
||||
|
||||
/** 검사일자 */
|
||||
@ExcelColumn(headerName = "검사일자", headerWidth = 15, align = ExcelColumn.Align.CENTER)
|
||||
private String inspYmd;
|
||||
|
||||
/** 차량번호 */
|
||||
@ExcelColumn(headerName = "차량번호", headerWidth = 15, align = ExcelColumn.Align.CENTER)
|
||||
private String vhclno;
|
||||
|
||||
/** 소유자명 */
|
||||
@ExcelColumn(headerName = "소유자명", headerWidth = 15, align = ExcelColumn.Align.CENTER)
|
||||
private String ownrNm;
|
||||
|
||||
/** 주민등록번호 */
|
||||
@ExcelColumn(headerName = "주민등록번호", headerWidth = 20, align = ExcelColumn.Align.CENTER)
|
||||
private String rrno;
|
||||
|
||||
/** 자동차명 */
|
||||
@ExcelColumn(headerName = "자동차명", headerWidth = 20, align = ExcelColumn.Align.LEFT)
|
||||
private String carNm;
|
||||
|
||||
/** 자동차종류 */
|
||||
@ExcelColumn(headerName = "자동차종류", headerWidth = 15, align = ExcelColumn.Align.CENTER)
|
||||
private String carKnd;
|
||||
|
||||
/** 자동차용도 */
|
||||
@ExcelColumn(headerName = "자동차용도", headerWidth = 15, align = ExcelColumn.Align.CENTER)
|
||||
private String carUsg;
|
||||
|
||||
/** 검사종료일자 */
|
||||
@ExcelColumn(headerName = "검사종료일자", headerWidth = 15, align = ExcelColumn.Align.CENTER)
|
||||
private String inspEndYmd;
|
||||
|
||||
/** 일수 */
|
||||
@ExcelColumn(headerName = "일수", headerWidth = 10, align = ExcelColumn.Align.RIGHT)
|
||||
private Long daycnt;
|
||||
|
||||
/** 재검여부 */
|
||||
@ExcelColumn(headerName = "재검여부", headerWidth = 12, align = ExcelColumn.Align.CENTER)
|
||||
private String reinspYn;
|
||||
|
||||
/** 과태료금액 */
|
||||
@ExcelColumn(headerName = "과태료금액", headerWidth = 15, align = ExcelColumn.Align.RIGHT)
|
||||
private Long ffnlgAmt;
|
||||
|
||||
/** 최종등록일자 */
|
||||
@ExcelColumn(headerName = "최종등록일자", headerWidth = 15, align = ExcelColumn.Align.CENTER)
|
||||
private String lastRegYmd;
|
||||
|
||||
/** 주소 */
|
||||
@ExcelColumn(headerName = "주소", headerWidth = 40, align = ExcelColumn.Align.LEFT)
|
||||
private String addr;
|
||||
|
||||
/** 유효기간만료일자 */
|
||||
@ExcelColumn(headerName = "유효기간만료일자", headerWidth = 18, align = ExcelColumn.Align.CENTER)
|
||||
private String vldPrdExpryYmd;
|
||||
|
||||
/** 매매상품 */
|
||||
@ExcelColumn(headerName = "매매상품", headerWidth = 15, align = ExcelColumn.Align.CENTER)
|
||||
private String trdGds;
|
||||
|
||||
/** 처리상태 */
|
||||
@ExcelColumn(headerName = "처리상태", headerWidth = 15, align = ExcelColumn.Align.CENTER)
|
||||
private String taskPrcsSttsCdNm;
|
||||
|
||||
/** 처리일자 */
|
||||
@ExcelColumn(headerName = "처리일자", headerWidth = 15, align = ExcelColumn.Align.CENTER)
|
||||
private String taskPrcsYmd;
|
||||
|
||||
/** 비고 */
|
||||
@ExcelColumn(headerName = "비고", headerWidth = 30, align = ExcelColumn.Align.LEFT)
|
||||
private String rmrk;
|
||||
|
||||
/** 비고 상세 */
|
||||
@ExcelColumn(headerName = "비고 상세", headerWidth = 50, align = ExcelColumn.Align.LEFT)
|
||||
private String rmrkDtl;
|
||||
|
||||
/** 기본사항조회성명 */
|
||||
@ExcelColumn(headerName = "기본사항조회성명", headerWidth = 18, align = ExcelColumn.Align.CENTER)
|
||||
private String carBscMttrInqFlnm;
|
||||
|
||||
/** 기본사항조회시군구명 */
|
||||
@ExcelColumn(headerName = "기본사항조회시군구명", headerWidth = 20, align = ExcelColumn.Align.CENTER)
|
||||
private String carBscMttrInqSggNm;
|
||||
|
||||
/** 등록원부변경업무명 */
|
||||
@ExcelColumn(headerName = "등록원부변경업무명", headerWidth = 20, align = ExcelColumn.Align.CENTER)
|
||||
private String carRegFrmbkChgTaskSeNm;
|
||||
|
||||
/** 등록원부변경일자 */
|
||||
@ExcelColumn(headerName = "등록원부변경일자", headerWidth = 18, align = ExcelColumn.Align.CENTER)
|
||||
private String carRegFrmbkChgYmd;
|
||||
|
||||
/** 등록원부상세 */
|
||||
@ExcelColumn(headerName = "등록원부상세", headerWidth = 40, align = ExcelColumn.Align.LEFT)
|
||||
private String carRegFrmbkDtl;
|
||||
|
||||
/** 등록일시 */
|
||||
@ExcelColumn(headerName = "등록일시", headerWidth = 20, align = ExcelColumn.Align.CENTER)
|
||||
private String regDt;
|
||||
|
||||
/** 등록자 */
|
||||
@ExcelColumn(headerName = "등록자", headerWidth = 15, align = ExcelColumn.Align.CENTER)
|
||||
private String rgtrNm;
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
package go.kr.project.carInspectionPenalty.registration.model;
|
||||
|
||||
import go.kr.project.common.model.PagingVO;
|
||||
import lombok.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* packageName : go.kr.project.carInspectionPenalty.registration.model
|
||||
* fileName : CarFfnlgTrgtModifiedDataVO
|
||||
* author : 시스템 관리자
|
||||
* date : 2025-11-28
|
||||
* description : 과태료 대상 수정 데이터를 담는 VO 클래스
|
||||
* ===========================================================
|
||||
* DATE AUTHOR NOTE
|
||||
* -----------------------------------------------------------
|
||||
* 2025-11-28 시스템 관리자 최초 생성
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
public class CarFfnlgTrgtModifiedDataVO extends PagingVO {
|
||||
|
||||
private List<CarFfnlgTrgtVO> createdRows;
|
||||
private List<CarFfnlgTrgtVO> updatedRows;
|
||||
private List<CarFfnlgTrgtVO> deletedRows;
|
||||
|
||||
}
|
||||
@ -1,586 +0,0 @@
|
||||
package go.kr.project.carInspectionPenalty.registration.service.impl;
|
||||
|
||||
import egovframework.util.DateUtil;
|
||||
import egovframework.util.StringUtil;
|
||||
import go.kr.project.api.model.response.NewLedgerResponse;
|
||||
|
||||
/**
|
||||
* 과태료 대상 비교 비고(Remark) 생성 유틸리티 클래스
|
||||
*
|
||||
* <p>각 비교 로직별 비고 문자열을 생성하는 메서드를 제공합니다.</p>
|
||||
*
|
||||
* <p>비고 패턴:</p>
|
||||
* <ul>
|
||||
* <li>1. 상품용: 상품용</li>
|
||||
* <li>2. 명의이전: 명의이전(25.9.5.) 이전소유자 상품용, 시군구명/ 소유자명</li>
|
||||
* <li>3. 이첩-1: 시군구명/ 소유자명, 검사일사용본거지</li>
|
||||
* <li>4. 이첩-2: 시군구명/ 소유자명, 115일 도래지</li>
|
||||
* </ul>
|
||||
*/
|
||||
public class ComparisonRemarkBuilder {
|
||||
|
||||
/**
|
||||
* 상품용 비고 생성
|
||||
* 비고 형식: 상품용
|
||||
*
|
||||
* @return 비고 문자열
|
||||
*/
|
||||
public static String buildProductUseRemark() {
|
||||
return "상품용";
|
||||
}
|
||||
|
||||
/**
|
||||
* 내사종결 - 명의이전 이전소유자 상품용 비고 생성 (31일 이내)
|
||||
* 비고 형식: 명의이전(25.9.11.) 이전소유자 상품용
|
||||
*
|
||||
* @param ledgerRecord 조건에 맞는 갑부 레코드 (명의이전 레코드)
|
||||
* @return 비고 문자열
|
||||
*/
|
||||
public static String buildProductCloseRemark(NewLedgerResponse.Record ledgerRecord) {
|
||||
String chgYmdFormatted = DateUtil.formatToShortDate(ledgerRecord.getChgYmd());
|
||||
return String.format("명의이전(%s) 이전소유자 상품용", chgYmdFormatted);
|
||||
}
|
||||
|
||||
/**
|
||||
* 날짜수정후부과 - 명의이전 이전소유자 상품용 비고 생성 (31일 초과)
|
||||
* 비고 형식: 시군구명/ 소유자명, 미수검명의이전(25.8.19.)
|
||||
*
|
||||
* @param ledgerRecord 조건에 맞는 갑부 레코드 (명의이전 레코드)
|
||||
* @param sggNm 시군구명
|
||||
* @param ownerNm 소유자명
|
||||
* @return 비고 문자열
|
||||
*/
|
||||
public static String buildProductLevyRemark(NewLedgerResponse.Record ledgerRecord,
|
||||
String sggNm, String ownerNm) {
|
||||
String chgYmdFormatted = DateUtil.formatToShortDate(ledgerRecord.getChgYmd());
|
||||
return String.format("%s/ %s, 미수검명의이전(%s)",
|
||||
StringUtil.nvl(sggNm), StringUtil.nvl(ownerNm), chgYmdFormatted);
|
||||
}
|
||||
|
||||
/**
|
||||
* 명의이전 비고 생성
|
||||
* 비고 형식: 명의이전(25.9.5.), 시군구명/ 소유자명
|
||||
*
|
||||
* @param ledgerRecord 조건에 맞는 갑부 레코드 (명의이전 레코드)
|
||||
* @param sggNm 시군구명
|
||||
* @param ownerNm 소유자명
|
||||
* @return 비고 문자열
|
||||
*/
|
||||
public static String buildOwnerChangeRemark(NewLedgerResponse.Record ledgerRecord,
|
||||
String sggNm, String ownerNm) {
|
||||
String chgYmdFormatted = DateUtil.formatToShortDate(ledgerRecord.getChgYmd());
|
||||
return String.format("명의이전(%s), %s/ %s",
|
||||
chgYmdFormatted, StringUtil.nvl(sggNm), StringUtil.nvl(ownerNm));
|
||||
}
|
||||
|
||||
/**
|
||||
* 이첩 비고 생성 - Case 이첩-1 (검사일 사용본거지)
|
||||
* 비고 형식: 시군구명/ 소유자명, 검사일사용본거지
|
||||
*
|
||||
* @param sggNm 시군구명
|
||||
* @param ownerNm 소유자명
|
||||
* @return 비고 문자열
|
||||
*/
|
||||
public static String buildTransferCase1Remark(String sggNm, String ownerNm) {
|
||||
return String.format("%s/ %s, 검사일사용본거지", StringUtil.nvl(sggNm), StringUtil.nvl(ownerNm));
|
||||
}
|
||||
|
||||
/**
|
||||
* 이첩 비고 생성 - Case 이첩-2 (115일 도래지)
|
||||
* 비고 형식: 시군구명/ 소유자명, 115일 도래지
|
||||
*
|
||||
* @param sggNm 시군구명
|
||||
* @param ownerNm 소유자명
|
||||
* @return 비고 문자열
|
||||
*/
|
||||
public static String buildTransferCase2Remark(String sggNm, String ownerNm) {
|
||||
return String.format("%s/ %s, 115일 도래지", StringUtil.nvl(sggNm), StringUtil.nvl(ownerNm));
|
||||
}
|
||||
|
||||
// ========================== 비고 상세 (RMRK_DTL) 생성 메서드 ==========================
|
||||
|
||||
/**
|
||||
* 상품용 비고 상세 생성
|
||||
*
|
||||
* @param vhclno 차량번호
|
||||
* @param inspYmd 검사일자
|
||||
* @param step1OwnerNm Step1 소유자명
|
||||
* @param targetChgYmd 갑부 변경일자
|
||||
* @param step4OwnerNm Step4 소유자명 (명의이전 시점)
|
||||
* @return 비고 상세 문자열
|
||||
*/
|
||||
public static String buildProductUseRemarkDetail(String vhclno, String inspYmd,
|
||||
String step1OwnerNm, String targetChgYmd, String step4OwnerNm) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[상품용 판정 - 지연]\n\n");
|
||||
|
||||
sb.append("=== 기본 정보 ===\n");
|
||||
sb.append("차량번호: ").append(StringUtil.nvl(vhclno)).append("\n");
|
||||
sb.append("검사일자: ").append(DateUtil.formatDateString(inspYmd)).append("\n\n");
|
||||
|
||||
sb.append("=== API 호출 및 비교 과정 ===\n");
|
||||
sb.append("Step1) 자동차기본정보 조회\n");
|
||||
sb.append(" - 조회 기준: 차량번호 + 검사일자(").append(DateUtil.formatDateString(inspYmd)).append(")\n");
|
||||
sb.append(" - 소유자명: ").append(StringUtil.nvl(step1OwnerNm)).append("\n");
|
||||
sb.append(" - 조건 확인: 소유자명에 '상품용' 포함 여부 → O\n\n");
|
||||
|
||||
sb.append("Step2) 자동차기본정보 조회\n");
|
||||
sb.append(" - 조회 기준: 차대번호 + 오늘일자\n");
|
||||
sb.append(" - 목적: 차량번호, 성명, 주민번호, 법정동코드 조회\n\n");
|
||||
|
||||
sb.append("Step3) 자동차등록원부(갑) 조회\n");
|
||||
sb.append(" - 조회 기준: 차량번호 + 성명 + 주민번호 + 법정동코드\n");
|
||||
sb.append(" - 검색 조건:\n");
|
||||
sb.append(" · 변경업무구분코드(CHG_TASK_SE_CD) = '11' (명의이전)\n");
|
||||
sb.append(" · 변경일자(CHG_YMD) ≤ 검사종료일자\n");
|
||||
sb.append(" · 조건 충족하는 레코드 중 가장 마지막 일자 선택\n");
|
||||
sb.append(" - 선택된 갑부 변경일자: ").append(DateUtil.formatDateString(targetChgYmd)).append("\n\n");
|
||||
|
||||
sb.append("Step4) 자동차기본정보 조회\n");
|
||||
sb.append(" - 조회 기준: 차대번호 + 갑부 변경일자(").append(DateUtil.formatDateString(targetChgYmd)).append(")\n");
|
||||
sb.append(" - 변경일 기준 소유자명: ").append(StringUtil.nvl(step4OwnerNm)).append("\n");
|
||||
sb.append(" - 조건 확인: Step1 대표소유자 회원번호 = Step4 대표소유자 회원번호 → 일치\n\n");
|
||||
|
||||
sb.append("=== 판정 근거 ===\n");
|
||||
sb.append("1. 검사일자 기준 소유자명에 '상품용' 포함\n");
|
||||
sb.append("2. 갑부 상세에서 변경업무구분코드 '11'(명의이전) 레코드가 검사종료일자 이내에 존재\n");
|
||||
sb.append("3. 갑부 변경일자 시점의 대표소유자 회원번호와 검사일자 기준 대표소유자 회원번호가 동일\n");
|
||||
sb.append("→ 상품용 판정 (처리상태: 02_상품용)\n");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 내사종결 - 명의이전 이전소유자 상품용 비고 상세 생성
|
||||
*
|
||||
* @param vhclno 차량번호
|
||||
* @param inspYmd 검사일자
|
||||
* @param step1OwnerNm Step1 소유자명
|
||||
* @param targetChgYmd 갑부 명의이전 일자
|
||||
* @param step4OwnerNm Step4 소유자명 (명의이전 전 소유자)
|
||||
* @param daysBetween 검사일과 명의이전일 간 일수차이
|
||||
* @param vldPrdExpryYmd 유효기간만료일
|
||||
* @param inspEndYmd 검사종료일자
|
||||
* @return 비고 상세 문자열
|
||||
*/
|
||||
public static String buildProductCloseLevyRemarkDetail(String vhclno, String inspYmd,
|
||||
String step1OwnerNm, String targetChgYmd,
|
||||
String step4OwnerNm, long daysBetween,
|
||||
String vldPrdExpryYmd, String inspEndYmd) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[내사종결 - 명의이전 이전소유자 상품용 판정 - 지연]\n\n");
|
||||
|
||||
sb.append("=== 기본 정보 ===\n");
|
||||
sb.append("차량번호: ").append(StringUtil.nvl(vhclno)).append("\n");
|
||||
sb.append("검사일자: ").append(DateUtil.formatDateString(inspYmd)).append("\n");
|
||||
sb.append("31일 기준일: ").append(DateUtil.formatDateString(
|
||||
DateUtil.parseDate(inspYmd).plusDays(31).format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd"))
|
||||
)).append("\n\n");
|
||||
|
||||
sb.append("=== API 호출 및 비교 과정 ===\n");
|
||||
sb.append("Step1) 자동차기본정보 조회\n");
|
||||
sb.append(" - 조회 기준: 차량번호 + 검사일자(").append(DateUtil.formatDateString(inspYmd)).append(")\n");
|
||||
sb.append(" - 소유자명: ").append(StringUtil.nvl(step1OwnerNm)).append("\n");
|
||||
sb.append(" - 조건 확인: 소유자명에 '상품용' 포함 여부 → X\n\n");
|
||||
|
||||
sb.append("Step2) 자동차기본정보 조회\n");
|
||||
sb.append(" - 조회 기준: 차대번호 + 오늘일자\n");
|
||||
sb.append(" - 목적: 차량번호, 성명, 주민번호, 법정동코드 조회\n\n");
|
||||
|
||||
sb.append("Step3) 자동차등록원부(갑) 조회\n");
|
||||
sb.append(" - 조회 기준: 차량번호 + 성명 + 주민번호 + 법정동코드\n");
|
||||
sb.append(" - 검색 조건:\n");
|
||||
sb.append(" · 변경업무구분코드(CHG_TASK_SE_CD) = '11' (명의이전)\n");
|
||||
sb.append(" · 유효기간만료일-90일 <= CHG_YMD <= 검사종료일자\n");
|
||||
sb.append(" - 유효기간만료일: ").append(DateUtil.formatDateString(vldPrdExpryYmd)).append("\n");
|
||||
sb.append(" - 유효기간만료일-90일: ").append(DateUtil.formatDateString(
|
||||
DateUtil.parseDate(vldPrdExpryYmd).minusDays(90).format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd"))
|
||||
)).append("\n");
|
||||
sb.append(" - 검사종료일자: ").append(DateUtil.formatDateString(inspEndYmd)).append("\n");
|
||||
sb.append(" - 검색 범위: ").append(DateUtil.formatDateString(
|
||||
DateUtil.parseDate(vldPrdExpryYmd).minusDays(90).format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd"))
|
||||
)).append(" ~ ").append(DateUtil.formatDateString(inspEndYmd)).append("\n");
|
||||
sb.append(" · 조건 충족하는 레코드 중 가장 마지막 일자 선택\n");
|
||||
sb.append(" - 선택된 갑부 명의이전 일자: ").append(DateUtil.formatDateString(targetChgYmd)).append("\n\n");
|
||||
|
||||
sb.append("Step4) 자동차기본정보 조회\n");
|
||||
sb.append(" - 조회 기준: 차대번호 + 명의이전일자-1일(").append(DateUtil.formatDateString(
|
||||
DateUtil.parseDate(targetChgYmd).minusDays(1).format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd"))
|
||||
)).append(")\n");
|
||||
sb.append(" - 명의이전 전 소유자명: ").append(StringUtil.nvl(step4OwnerNm)).append("\n");
|
||||
sb.append(" - 조건 확인: 명의이전 전 소유자명에 '상품용' 포함 → O\n\n");
|
||||
|
||||
sb.append("=== 일수 계산 ===\n");
|
||||
sb.append("검사일~명의이전일 일수: ").append(daysBetween).append("일\n");
|
||||
sb.append("기준일수: 31일\n");
|
||||
sb.append("조건 확인: ").append(daysBetween).append("일 ≤ 31일 → 이내\n\n");
|
||||
|
||||
sb.append("=== 판정 근거 ===\n");
|
||||
sb.append("1. 검사일자 기준 소유자명에 '상품용' 미포함\n");
|
||||
sb.append("2. 갑부 상세에서 변경업무구분코드 '11'(명의이전) 레코드가 검사일자 이내에 존재\n");
|
||||
sb.append("3. 명의이전일자-1일 시점의 소유자명에 '상품용' 포함\n");
|
||||
sb.append("4. 명의이전일이 검사일로부터 31일 이내 (").append(daysBetween).append("일)\n");
|
||||
sb.append("→ 내사종결 - 명의이전 이전소유자 상품용 판정 (처리상태: 04_내사종결)\n");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 내사종결 - 명의이전 비고 상세 생성
|
||||
*
|
||||
* @param vhclno 차량번호
|
||||
* @param inspYmd 검사일자
|
||||
* @param step1OwnerNm Step1 소유자명
|
||||
* @param targetChgYmd 갑부 명의이전 일자
|
||||
* @param step4OwnerNm Step4 소유자명 (명의이전 전 소유자)
|
||||
* @param daysBetween 검사일과 명의이전일 간 일수차이
|
||||
* @return 비고 상세 문자열
|
||||
*/
|
||||
public static String buildOwnerChangeRemarkDetail(String vhclno, String inspYmd,
|
||||
String step1OwnerNm, String targetChgYmd,
|
||||
String step4OwnerNm, long daysBetween) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[내사종결 - 명의이전 판정 - 지연]\n\n");
|
||||
|
||||
sb.append("=== 기본 정보 ===\n");
|
||||
sb.append("차량번호: ").append(StringUtil.nvl(vhclno)).append("\n");
|
||||
sb.append("검사일자: ").append(DateUtil.formatDateString(inspYmd)).append("\n");
|
||||
sb.append("31일 기준일: ").append(DateUtil.formatDateString(
|
||||
DateUtil.parseDate(inspYmd).plusDays(31).format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd"))
|
||||
)).append("\n\n");
|
||||
|
||||
sb.append("=== API 호출 및 비교 과정 ===\n");
|
||||
sb.append("Step1) 자동차기본정보 조회\n");
|
||||
sb.append(" - 조회 기준: 차량번호 + 검사일자(").append(DateUtil.formatDateString(inspYmd)).append(")\n");
|
||||
sb.append(" - 소유자명: ").append(StringUtil.nvl(step1OwnerNm)).append("\n");
|
||||
sb.append(" - 조건 확인: 소유자명에 '상품용' 포함 여부 → X\n\n");
|
||||
|
||||
sb.append("Step2) 자동차기본정보 조회\n");
|
||||
sb.append(" - 조회 기준: 차대번호 + 오늘일자\n");
|
||||
sb.append(" - 목적: 차량번호, 성명, 주민번호, 법정동코드 조회\n\n");
|
||||
|
||||
sb.append("Step3) 자동차등록원부(갑) 조회\n");
|
||||
sb.append(" - 조회 기준: 차량번호 + 성명 + 주민번호 + 법정동코드\n");
|
||||
sb.append(" - 검색 조건:\n");
|
||||
sb.append(" · 변경업무구분코드(CHG_TASK_SE_CD) = '11' (명의이전)\n");
|
||||
sb.append(" · 변경일자(CHG_YMD) ≤ 검사일자\n");
|
||||
sb.append(" · 조건 충족하는 레코드 중 가장 마지막 일자 선택\n");
|
||||
sb.append(" - 선택된 갑부 명의이전 일자: ").append(DateUtil.formatDateString(targetChgYmd)).append("\n\n");
|
||||
|
||||
sb.append("Step4) 자동차기본정보 조회\n");
|
||||
sb.append(" - 조회 기준: 차대번호 + 명의이전일자(").append(DateUtil.formatDateString(targetChgYmd)).append(")\n");
|
||||
sb.append(" - 명의이전 시점 소유자명: ").append(StringUtil.nvl(step4OwnerNm)).append("\n");
|
||||
sb.append(" - 조건 확인: Step1 대표소유자 회원번호 = Step4 대표소유자 회원번호 → 일치\n");
|
||||
sb.append(" - 명의이전 시점 소유자명에 '상품용' 포함 → X\n\n");
|
||||
|
||||
sb.append("=== 일수 계산 ===\n");
|
||||
sb.append("검사일~명의이전일 일수: ").append(daysBetween).append("일\n");
|
||||
sb.append("기준일수: 31일\n");
|
||||
sb.append("조건 확인: ").append(daysBetween).append("일 ≤ 31일 → 이내\n\n");
|
||||
|
||||
sb.append("=== 판정 근거 ===\n");
|
||||
sb.append("1. 검사일자 기준 소유자명에 '상품용' 미포함\n");
|
||||
sb.append("2. 갑부 상세에서 변경업무구분코드 '11'(명의이전) 레코드가 검사일자 이내에 존재\n");
|
||||
sb.append("3. 명의이전 시점의 대표소유자 회원번호와 검사일자 기준 대표소유자 회원번호가 동일 (소유자 변동 없음)\n");
|
||||
sb.append("4. 명의이전 시점 소유자명에 '상품용' 미포함\n");
|
||||
sb.append("5. 명의이전일이 검사일로부터 31일 이내 (").append(daysBetween).append("일)\n");
|
||||
sb.append("→ 내사종결 - 명의이전 판정 (처리상태: 04_내사종결)\n");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 날짜수정후부과 - 명의이전 이전소유자 상품용 비고 상세 생성
|
||||
*
|
||||
* @param vhclno 차량번호
|
||||
* @param inspYmd 검사일자
|
||||
* @param step1OwnerNm Step1 소유자명
|
||||
* @param targetChgYmd 갑부 명의이전 일자
|
||||
* @param step4OwnerNm Step4 소유자명 (명의이전 전 소유자)
|
||||
* @param daysBetween 검사일과 명의이전일 간 일수차이
|
||||
* @param vldPrdExpryYmd 유효기간만료일
|
||||
* @param inspEndYmd 검사종료일자
|
||||
* @return 비고 상세 문자열
|
||||
*/
|
||||
public static String buildProductLevyOver31RemarkDetail(String vhclno, String inspYmd,
|
||||
String step1OwnerNm, String targetChgYmd,
|
||||
String step4OwnerNm, long daysBetween,
|
||||
String vldPrdExpryYmd, String inspEndYmd) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[날짜수정후부과 - 명의이전 이전소유자 상품용 판정 - 지연]\n\n");
|
||||
|
||||
sb.append("=== 기본 정보 ===\n");
|
||||
sb.append("차량번호: ").append(StringUtil.nvl(vhclno)).append("\n");
|
||||
sb.append("검사일자: ").append(DateUtil.formatDateString(inspYmd)).append("\n");
|
||||
sb.append("31일 기준일: ").append(DateUtil.formatDateString(
|
||||
DateUtil.parseDate(inspYmd).plusDays(31).format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd"))
|
||||
)).append("\n\n");
|
||||
|
||||
sb.append("=== API 호출 및 비교 과정 ===\n");
|
||||
sb.append("Step1) 자동차기본정보 조회\n");
|
||||
sb.append(" - 조회 기준: 차량번호 + 검사일자(").append(DateUtil.formatDateString(inspYmd)).append(")\n");
|
||||
sb.append(" - 소유자명: ").append(StringUtil.nvl(step1OwnerNm)).append("\n");
|
||||
sb.append(" - 조건 확인: 소유자명에 '상품용' 포함 여부 → X\n\n");
|
||||
|
||||
sb.append("Step2) 자동차기본정보 조회\n");
|
||||
sb.append(" - 조회 기준: 차대번호 + 오늘일자\n");
|
||||
sb.append(" - 목적: 차량번호, 성명, 주민번호, 법정동코드 조회\n\n");
|
||||
|
||||
sb.append("Step3) 자동차등록원부(갑) 조회\n");
|
||||
sb.append(" - 조회 기준: 차량번호 + 성명 + 주민번호 + 법정동코드\n");
|
||||
sb.append(" - 검색 조건:\n");
|
||||
sb.append(" · 변경업무구분코드(CHG_TASK_SE_CD) = '11' (명의이전)\n");
|
||||
sb.append(" · 유효기간만료일-90일 <= CHG_YMD <= 검사종료일자\n");
|
||||
sb.append(" - 유효기간만료일: ").append(DateUtil.formatDateString(vldPrdExpryYmd)).append("\n");
|
||||
sb.append(" - 유효기간만료일-90일: ").append(DateUtil.formatDateString(
|
||||
DateUtil.parseDate(vldPrdExpryYmd).minusDays(90).format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd"))
|
||||
)).append("\n");
|
||||
sb.append(" - 검사종료일자: ").append(DateUtil.formatDateString(inspEndYmd)).append("\n");
|
||||
sb.append(" - 검색 범위: ").append(DateUtil.formatDateString(
|
||||
DateUtil.parseDate(vldPrdExpryYmd).minusDays(90).format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd"))
|
||||
)).append(" ~ ").append(DateUtil.formatDateString(inspEndYmd)).append("\n");
|
||||
sb.append(" · 조건 충족하는 레코드 중 가장 마지막 일자 선택\n");
|
||||
sb.append(" - 선택된 갑부 명의이전 일자: ").append(DateUtil.formatDateString(targetChgYmd)).append("\n\n");
|
||||
|
||||
sb.append("Step4) 자동차기본정보 조회\n");
|
||||
sb.append(" - 조회 기준: 차대번호 + 명의이전일자-1일(").append(DateUtil.formatDateString(
|
||||
DateUtil.parseDate(targetChgYmd).minusDays(1).format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd"))
|
||||
)).append(")\n");
|
||||
sb.append(" - 명의이전 전 소유자명: ").append(StringUtil.nvl(step4OwnerNm)).append("\n");
|
||||
sb.append(" - 조건 확인: 명의이전 전 소유자명에 '상품용' 포함 → O\n\n");
|
||||
|
||||
sb.append("=== 일수 계산 ===\n");
|
||||
sb.append("검사일~명의이전일 일수: ").append(daysBetween).append("일\n");
|
||||
sb.append("기준일수: 31일\n");
|
||||
sb.append("조건 확인: ").append(daysBetween).append("일 > 31일 → 초과\n\n");
|
||||
|
||||
sb.append("=== 판정 근거 ===\n");
|
||||
sb.append("1. 검사일자 기준 소유자명에 '상품용' 미포함\n");
|
||||
sb.append("2. 갑부 상세에서 변경업무구분코드 '11'(명의이전) 레코드가 검사일자 이내에 존재\n");
|
||||
sb.append("3. 명의이전일자-1일 시점의 소유자명에 '상품용' 포함\n");
|
||||
sb.append("4. 명의이전일이 검사일로부터 31일 초과 (").append(daysBetween).append("일)\n");
|
||||
sb.append("→ 날짜수정후부과 - 명의이전 이전소유자 상품용 판정 (처리상태: 05_날짜수정후부과)\n");
|
||||
sb.append("※ 부과일자를 명의이전일자로 수정하여 재부과 필요\n");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 날짜수정후부과 - 명의이전 비고 상세 생성
|
||||
*
|
||||
* @param vhclno 차량번호
|
||||
* @param inspYmd 검사일자
|
||||
* @param vldPrdExpryYmd 유효기간만료일
|
||||
* @param inspEndYmd 검사종료일자
|
||||
* @param step1OwnerNm Step1 소유자명
|
||||
* @param targetChgYmd 갑부 명의이전 일자
|
||||
* @param step4OwnerNm Step4 소유자명 (명의이전 전 소유자)
|
||||
* @param daysBetween 검사일과 명의이전일 간 일수차이
|
||||
* @return 비고 상세 문자열
|
||||
*/
|
||||
public static String buildOwnerLevyOver31RemarkDetail(String vhclno, String inspYmd, String vldPrdExpryYmd,
|
||||
String inspEndYmd, String step1OwnerNm, String targetChgYmd,
|
||||
String step4OwnerNm, long daysBetween) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[날짜수정후부과 - 명의이전 판정 - 지연]\n\n");
|
||||
|
||||
sb.append("=== 기본 정보 ===\n");
|
||||
sb.append("차량번호: ").append(StringUtil.nvl(vhclno)).append("\n");
|
||||
sb.append("검사일자: ").append(DateUtil.formatDateString(inspYmd)).append("\n");
|
||||
sb.append("유효기간만료일: ").append(DateUtil.formatDateString(vldPrdExpryYmd)).append("\n");
|
||||
sb.append("유효기간만료일 - 90일: ").append(DateUtil.formatDateString(
|
||||
DateUtil.parseDate(vldPrdExpryYmd).minusDays(90).format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd"))
|
||||
)).append("\n");
|
||||
sb.append("검사종료일자: ").append(DateUtil.formatDateString(inspEndYmd)).append("\n");
|
||||
sb.append("31일 기준일: ").append(DateUtil.formatDateString(
|
||||
DateUtil.parseDate(inspYmd).plusDays(31).format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd"))
|
||||
)).append("\n\n");
|
||||
|
||||
sb.append("=== API 호출 및 비교 과정 ===\n");
|
||||
sb.append("Step1) 자동차기본정보 조회\n");
|
||||
sb.append(" - 조회 기준: 차량번호 + 검사일자(").append(DateUtil.formatDateString(inspYmd)).append(")\n");
|
||||
sb.append(" - 소유자명: ").append(StringUtil.nvl(step1OwnerNm)).append("\n");
|
||||
sb.append(" - 조건 확인: 소유자명에 '상품용' 포함 여부 → X\n\n");
|
||||
|
||||
sb.append("Step2) 자동차기본정보 조회\n");
|
||||
sb.append(" - 조회 기준: 차대번호 + 오늘일자\n");
|
||||
sb.append(" - 목적: 차량번호, 성명, 주민번호, 법정동코드 조회\n\n");
|
||||
|
||||
sb.append("Step3) 자동차등록원부(갑) 조회\n");
|
||||
sb.append(" - 조회 기준: 차량번호 + 성명 + 주민번호 + 법정동코드\n");
|
||||
sb.append(" - 검색 조건:\n");
|
||||
sb.append(" · 변경업무구분코드(CHG_TASK_SE_CD) = '11' (명의이전)\n");
|
||||
sb.append(" · 유효기간만료일-90일 ≤ 변경일자(CHG_YMD) ≤ 검사종료일자\n");
|
||||
sb.append(" · 범위: ").append(DateUtil.formatDateString(
|
||||
DateUtil.parseDate(vldPrdExpryYmd).minusDays(90).format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd"))
|
||||
)).append(" ~ ").append(DateUtil.formatDateString(inspEndYmd)).append("\n");
|
||||
sb.append(" · 조건 충족하는 레코드 중 가장 마지막 일자 선택\n");
|
||||
sb.append(" - 선택된 갑부 명의이전 일자: ").append(DateUtil.formatDateString(targetChgYmd)).append("\n\n");
|
||||
|
||||
sb.append("Step4) 자동차기본정보 조회\n");
|
||||
sb.append(" - 조회 기준: 차대번호 + 명의이전일자(").append(DateUtil.formatDateString(targetChgYmd)).append(")\n");
|
||||
sb.append(" - 명의이전 시점 소유자명: ").append(StringUtil.nvl(step4OwnerNm)).append("\n");
|
||||
sb.append(" - 조건 확인: Step1 대표소유자 회원번호 = Step4 대표소유자 회원번호 → 일치\n");
|
||||
sb.append(" - 명의이전 시점 소유자명에 '상품용' 포함 → X\n\n");
|
||||
|
||||
sb.append("=== 일수 계산 ===\n");
|
||||
sb.append("검사일~명의이전일 일수: ").append(daysBetween).append("일\n");
|
||||
sb.append("기준일수: 31일\n");
|
||||
sb.append("조건 확인: ").append(daysBetween).append("일 > 31일 → 초과\n\n");
|
||||
|
||||
sb.append("=== 판정 근거 ===\n");
|
||||
sb.append("1. 검사일자 기준 소유자명에 '상품용' 미포함\n");
|
||||
sb.append("2. 갑부 상세에서 변경업무구분코드 '11'(명의이전) 레코드가 검사기간(유효기간만료일-90일 ~ 검사종료일자) 내에 존재\n");
|
||||
sb.append("3. 명의이전 시점의 대표소유자 회원번호와 검사일자 기준 대표소유자 회원번호가 동일 (소유자 변동 없음)\n");
|
||||
sb.append("4. 명의이전 시점 소유자명에 '상품용' 미포함\n");
|
||||
sb.append("5. 명의이전일이 검사일로부터 31일 초과 (").append(daysBetween).append("일)\n");
|
||||
sb.append("→ 날짜수정후부과 - 명의이전 판정 (처리상태: 05_날짜수정후부과)\n");
|
||||
sb.append("※ 부과일자를 명의이전일자로 수정하여 재부과 필요\n");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 이첩 비고 상세 생성 - Case 이첩-1 (검사일 사용본거지)
|
||||
*
|
||||
* @param vhclno 차량번호
|
||||
* @param inspYmd 검사일자
|
||||
* @param ownerNm 소유자명
|
||||
* @param usgsrhldStdgCd 사용본거지법정동코드
|
||||
* @param sggNm 시군구명
|
||||
* @param userOrgCd 사용자 조직코드
|
||||
* @return 비고 상세 문자열
|
||||
*/
|
||||
public static String buildTransferCase1RemarkDetail(String vhclno, String inspYmd,
|
||||
String ownerNm, String usgsrhldStdgCd,
|
||||
String sggNm, String userOrgCd) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[이첩 판정 - 검사일 사용본거지 (이첩-1) - 지연]\n\n");
|
||||
|
||||
sb.append("=== 기본 정보 ===\n");
|
||||
sb.append("차량번호: ").append(StringUtil.nvl(vhclno)).append("\n");
|
||||
sb.append("검사일자: ").append(DateUtil.formatDateString(inspYmd)).append("\n");
|
||||
sb.append("DAYCNT: 115일 이하\n");
|
||||
sb.append("부과기준일: 검사일자 (DAYCNT ≤ 115이므로)\n\n");
|
||||
|
||||
sb.append("=== API 호출 및 비교 과정 ===\n");
|
||||
sb.append("자동차기본정보 조회\n");
|
||||
sb.append(" - 조회 기준: 차량번호 + 부과기준일(검사일자)(").append(DateUtil.formatDateString(inspYmd)).append(")\n");
|
||||
sb.append(" - 소유자명: ").append(StringUtil.nvl(ownerNm)).append("\n");
|
||||
sb.append(" - 사용본거지법정동코드: ").append(StringUtil.nvl(usgsrhldStdgCd)).append("\n\n");
|
||||
|
||||
sb.append("=== 법정동코드 비교 ===\n");
|
||||
String legalDong4 = usgsrhldStdgCd != null && usgsrhldStdgCd.length() >= 4 ? usgsrhldStdgCd.substring(0, 4) : "";
|
||||
String userOrg4 = userOrgCd != null && userOrgCd.length() >= 4 ? userOrgCd.substring(0, 4) : "";
|
||||
sb.append("사용본거지법정동코드 앞 4자리: ").append(legalDong4).append("\n");
|
||||
sb.append("현재 사용자 조직코드 앞 4자리: ").append(userOrg4).append("\n");
|
||||
sb.append("코드 불일치 → 이첩 대상\n");
|
||||
sb.append("시군구코드: ").append(usgsrhldStdgCd != null && usgsrhldStdgCd.length() >= 5 ? usgsrhldStdgCd.substring(0, 5) : "").append("\n");
|
||||
sb.append("시군구명: ").append(StringUtil.nvl(sggNm)).append("\n\n");
|
||||
|
||||
sb.append("=== 판정 근거 ===\n");
|
||||
sb.append("1. DAYCNT ≤ 115일이므로 부과기준일 = 검사일자\n");
|
||||
sb.append("2. 검사일자 기준 사용본거지법정동코드 앞 4자리와 현재 사용자 조직코드 앞 4자리가 불일치\n");
|
||||
sb.append("→ 이첩 판정 - 검사일 사용본거지 (처리상태: 03_이첩)\n");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 이첩 비고 상세 생성 - Case 이첩-2 (115일 도래지)
|
||||
*
|
||||
* @param vhclno 차량번호
|
||||
* @param inspEndYmd 검사종료일자
|
||||
* @param ownerNm 소유자명
|
||||
* @param usgsrhldStdgCd 사용본거지법정동코드
|
||||
* @param sggNm 시군구명
|
||||
* @param userOrgCd 사용자 조직코드
|
||||
* @param daycnt 일수
|
||||
* @return 비고 상세 문자열
|
||||
*/
|
||||
public static String buildTransferCase2RemarkDetail(String vhclno, String inspEndYmd,
|
||||
String ownerNm, String usgsrhldStdgCd,
|
||||
String sggNm, String userOrgCd, String daycnt) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[이첩 판정 - 115일 도래지 (이첩-2) - 지연]\n\n");
|
||||
|
||||
sb.append("=== 기본 정보 ===\n");
|
||||
sb.append("차량번호: ").append(StringUtil.nvl(vhclno)).append("\n");
|
||||
sb.append("검사종료일자: ").append(DateUtil.formatDateString(inspEndYmd)).append("\n");
|
||||
sb.append("DAYCNT: ").append(StringUtil.nvl(daycnt)).append("일 (115일 초과)\n");
|
||||
sb.append("부과기준일 계산: 검사종료일자 + 115일 = ").append(DateUtil.formatDateString(
|
||||
DateUtil.parseDate(inspEndYmd).plusDays(115).format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd"))
|
||||
)).append("\n\n");
|
||||
|
||||
sb.append("=== API 호출 및 비교 과정 ===\n");
|
||||
sb.append("자동차기본정보 조회\n");
|
||||
sb.append(" - 조회 기준: 차량번호 + 부과기준일(검사종료일자+115일)(").append(DateUtil.formatDateString(
|
||||
DateUtil.parseDate(inspEndYmd).plusDays(115).format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd"))
|
||||
)).append(")\n");
|
||||
sb.append(" - 소유자명: ").append(StringUtil.nvl(ownerNm)).append("\n");
|
||||
sb.append(" - 사용본거지법정동코드: ").append(StringUtil.nvl(usgsrhldStdgCd)).append("\n\n");
|
||||
|
||||
sb.append("=== 법정동코드 비교 ===\n");
|
||||
String legalDong4 = usgsrhldStdgCd != null && usgsrhldStdgCd.length() >= 4 ? usgsrhldStdgCd.substring(0, 4) : "";
|
||||
String userOrg4 = userOrgCd != null && userOrgCd.length() >= 4 ? userOrgCd.substring(0, 4) : "";
|
||||
sb.append("사용본거지법정동코드 앞 4자리: ").append(legalDong4).append("\n");
|
||||
sb.append("현재 사용자 조직코드 앞 4자리: ").append(userOrg4).append("\n");
|
||||
sb.append("코드 불일치 → 이첩 대상\n");
|
||||
sb.append("시군구코드: ").append(usgsrhldStdgCd != null && usgsrhldStdgCd.length() >= 5 ? usgsrhldStdgCd.substring(0, 5) : "").append("\n");
|
||||
sb.append("시군구명: ").append(StringUtil.nvl(sggNm)).append("\n\n");
|
||||
|
||||
sb.append("=== 판정 근거 ===\n");
|
||||
sb.append("1. DAYCNT > 115일(").append(StringUtil.nvl(daycnt)).append("일)이므로 부과기준일 = 검사종료일자 + 115일\n");
|
||||
sb.append("2. 부과기준일 기준 사용본거지법정동코드 앞 4자리와 현재 사용자 조직코드 앞 4자리가 불일치\n");
|
||||
sb.append("→ 이첩 판정 - 115일 도래지 (처리상태: 03_이첩)\n");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 문자열 최대 길이 제한 (한글 3바이트 기준 약 1300자)
|
||||
*
|
||||
* @param str 원본 문자열
|
||||
* @return 제한된 문자열
|
||||
*/
|
||||
private static String truncateToMaxLength(String str) {
|
||||
if (str == null) {
|
||||
return "";
|
||||
}
|
||||
// 4000바이트 / 3(한글) = 약 1333자, 여유있게 1300자로 제한
|
||||
if (str.length() > 1300) {
|
||||
return str.substring(0, 1297) + "...";
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* 등록원부 갑부 레코드 상세 정보 생성
|
||||
*
|
||||
* @param record 갑부 레코드
|
||||
* @return 상세 정보 문자열
|
||||
*/
|
||||
public static String buildLedgerRecordDetail(NewLedgerResponse.Record record) {
|
||||
if (record == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
StringBuilder detail = new StringBuilder();
|
||||
|
||||
StringUtil.appendIfNotEmpty(detail, "변경업무구분코드", record.getChgTaskSeCd());
|
||||
StringUtil.appendIfNotEmpty(detail, "변경업무구분명", record.getChgTaskSeNm());
|
||||
StringUtil.appendIfNotEmpty(detail, "변경일자", DateUtil.formatDateString(record.getChgYmd()));
|
||||
StringUtil.appendIfNotEmpty(detail, "주요번호", record.getMainNo());
|
||||
StringUtil.appendIfNotEmpty(detail, "일련번호", record.getSno());
|
||||
StringUtil.appendIfNotEmpty(detail, "특별사항", record.getSpcablMttr());
|
||||
StringUtil.appendIfNotEmpty(detail, "명의자명", record.getHshldrNm());
|
||||
StringUtil.appendIfNotEmpty(detail, "명의자식별번호", StringUtil.maskIdecno(record.getHshldrIdecno()));
|
||||
StringUtil.appendIfNotEmpty(detail, "신청접수번호", record.getAplyRcptNo());
|
||||
StringUtil.appendIfNotEmpty(detail, "차량관리번호", record.getVhmno());
|
||||
StringUtil.appendIfNotEmpty(detail, "원부그룹번호", record.getLedgerGroupNo());
|
||||
StringUtil.appendIfNotEmpty(detail, "원부개별번호", record.getLedgerIndivNo());
|
||||
StringUtil.appendIfNotEmpty(detail, "상세일련번호", record.getDtlSn());
|
||||
|
||||
return detail.toString();
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue