diff --git a/build.gradle b/build.gradle index 82198f5..09007b7 100644 --- a/build.gradle +++ b/build.gradle @@ -17,8 +17,8 @@ repositories { } dependencies { - implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'org.springframework.boot:spring-boot-starter-web:3.3.4' + implementation 'org.springframework.boot:spring-boot-starter-validation:3.3.4' // OpenAPI/Swagger UI implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.6.0' @@ -30,7 +30,7 @@ dependencies { implementation files('lib/libgpkiapi_jni_1.5.jar') // Configuration metadata - annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' + annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor:3.3.4' // Lombok compileOnly 'org.projectlombok:lombok:1.18.34' @@ -38,7 +38,7 @@ dependencies { testCompileOnly 'org.projectlombok:lombok:1.18.34' testAnnotationProcessor 'org.projectlombok:lombok:1.18.34' - testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'org.springframework.boot:spring-boot-starter-test:3.3.4' } tasks.withType(Test).configureEach { diff --git a/src/main/java/com/vmis/interfaceapp/client/GovernmentApi.java b/src/main/java/com/vmis/interfaceapp/client/GovernmentApi.java index bf79d42..6432f03 100644 --- a/src/main/java/com/vmis/interfaceapp/client/GovernmentApi.java +++ b/src/main/java/com/vmis/interfaceapp/client/GovernmentApi.java @@ -1,5 +1,7 @@ package com.vmis.interfaceapp.client; +import com.vmis.interfaceapp.model.basic.NewBasicRequest; +import com.vmis.interfaceapp.model.basic.NewBasicResponse; import com.vmis.interfaceapp.model.basic.OldBasicRequest; import com.vmis.interfaceapp.model.basic.OldBasicResponse; import com.vmis.interfaceapp.model.common.Envelope; @@ -18,6 +20,9 @@ public interface GovernmentApi { // 구버전 자동차기본사항조회 ResponseEntity> callOldBasic(Envelope envelope); + // 신버전 자동차기본사항조회 + ResponseEntity> callNewBasic(Envelope envelope); + // 신버전 자동차등록원부(갑) ResponseEntity> callNewLedger(Envelope envelope); } diff --git a/src/main/java/com/vmis/interfaceapp/client/GovernmentApiClient.java b/src/main/java/com/vmis/interfaceapp/client/GovernmentApiClient.java index d0373c1..618cb40 100644 --- a/src/main/java/com/vmis/interfaceapp/client/GovernmentApiClient.java +++ b/src/main/java/com/vmis/interfaceapp/client/GovernmentApiClient.java @@ -9,6 +9,8 @@ import com.vmis.interfaceapp.config.properties.OldVmisProperties; import com.vmis.interfaceapp.gpki.GpkiService; import com.vmis.interfaceapp.model.basic.OldBasicRequest; import com.vmis.interfaceapp.model.basic.OldBasicResponse; +import com.vmis.interfaceapp.model.basic.NewBasicRequest; +import com.vmis.interfaceapp.model.basic.NewBasicResponse; import com.vmis.interfaceapp.model.common.Envelope; import com.vmis.interfaceapp.model.ledger.NewLedgerRequest; import com.vmis.interfaceapp.model.ledger.NewLedgerResponse; @@ -169,6 +171,10 @@ public class GovernmentApiClient implements GovernmentApi { * Old Basic service type (구버전 자동차기본사항조회). */ OLD_BASIC, + /** + * New Basic service type (신버전 자동차기본사항조회). + */ + NEW_BASIC, /** * New Ledger service type (신버전 자동차등록원부(갑)). */ @@ -252,7 +258,8 @@ public class GovernmentApiClient implements GovernmentApi { *
  • 각 서비스(BASIC, LEDGER)마다 별도의 API 키 사용 가능
  • * * - * @param svc 서비스 설정 객체 (API 키, 경로 등 포함) + * @param apiKey 서비스별 API 인증 키 + * @param cvmisApikey CVMIS 시스템 API 키 * @param txId 이번 요청의 트랜잭션 ID * @return HttpHeaders 구성된 HTTP 헤더 객체 */ @@ -334,6 +341,19 @@ public class GovernmentApiClient implements GovernmentApi { return callModel(ServiceType.OLD_BASIC, envelope, new TypeReference>(){}); } + /** + * 신버전 자동차 기본사항 조회 API 호출 + * + *

    신규 규격의 자동차 기본사항 조회를 호출합니다. 공통 템플릿 메서드({@link #callModel})에 + * 서비스 타입과 제네릭 응답 타입 정보를 전달하여 실제 통신을 수행합니다.

    + * + * @param envelope 자동차 기본사항 조회 요청(신버전)을 담은 Envelope + * @return ResponseEntity 형태의 Envelope 래퍼 응답 + */ + public ResponseEntity> callNewBasic(Envelope envelope) { + return callModel(ServiceType.NEW_BASIC, envelope, new TypeReference>(){}); + } + /** * 자동차 등록원부(갑) 조회 API 호출 * @@ -486,6 +506,12 @@ public class GovernmentApiClient implements GovernmentApi { url = gov.buildServiceUrl(svc.getPath()); apiKey = svc.getApiKey(); cvmisApikey = svc.getCvmisApikey(); + } else if (type == ServiceType.NEW_BASIC) { + NewVmisProperties.GovProps gov = newProps.getGov(); + NewVmisProperties.GovProps.Service svc = gov.getServices().getBasic(); + url = gov.buildServiceUrl(svc.getPath()); + apiKey = svc.getApiKey(); + cvmisApikey = svc.getCvmisApikey(); } else if (type == ServiceType.NEW_LEDGER) { NewVmisProperties.GovProps gov = newProps.getGov(); NewVmisProperties.GovProps.Service svc = gov.getServices().getLedger(); diff --git a/src/main/java/com/vmis/interfaceapp/controller/VehicleInterfaceController.java b/src/main/java/com/vmis/interfaceapp/controller/VehicleInterfaceController.java index ffff0c0..4235c37 100644 --- a/src/main/java/com/vmis/interfaceapp/controller/VehicleInterfaceController.java +++ b/src/main/java/com/vmis/interfaceapp/controller/VehicleInterfaceController.java @@ -1,5 +1,7 @@ package com.vmis.interfaceapp.controller; +import com.vmis.interfaceapp.model.basic.NewBasicRequest; +import com.vmis.interfaceapp.model.basic.NewBasicResponse; import com.vmis.interfaceapp.model.basic.OldBasicRequest; import com.vmis.interfaceapp.model.basic.OldBasicResponse; import com.vmis.interfaceapp.model.common.Envelope; @@ -131,6 +133,78 @@ public class VehicleInterfaceController { return service.oldBasic(envelope); } + /** + * 자동차 기본사항 조회 API + * + *

    차량번호, 소유자 정보 등 자동차의 기본적인 정보를 조회하는 API입니다.

    + * + *

    요청 처리 흐름:

    + *
      + *
    1. 클라이언트로부터 JSON 형식의 요청 수신
    2. + *
    3. 요청 바디가 Envelope<BasicRequest> 객체로 역직렬화됨
    4. + *
    5. Spring의 @RequestBody 어노테이션이 자동으로 JSON을 객체로 변환
    6. + *
    7. 변환된 요청 객체를 GovernmentApiClient로 전달
    8. + *
    9. GovernmentApiClient가 정부 시스템과 통신 수행
    10. + *
    11. 응답 데이터를 Envelope<BasicResponse>로 감싸서 반환
    12. + *
    13. Spring이 자동으로 응답 객체를 JSON으로 직렬화하여 클라이언트에게 전송
    14. + *
    + * + *

    HTTP 메서드 및 경로:

    + *
      + *
    • 메서드: POST
    • + *
    • 경로: /api/v1/vehicles/basic
    • + *
    • Content-Type: application/json (요청)
    • + *
    • Accept: application/json (응답)
    • + *
    + * + *

    데이터 구조:

    + *
      + *
    • Envelope: 공통 헤더 정보(전문 ID, 전송 시각 등)와 실제 데이터를 감싸는 래퍼 객체
    • + *
    • BasicRequest: 자동차 기본사항 조회를 위한 요청 데이터 (차량번호 등)
    • + *
    • BasicResponse: 자동차 기본사항 조회 결과 데이터 (소유자, 차종, 연식 등)
    • + *
    + * + *

    에러 처리:

    + *
      + *
    • JSON 파싱 오류 시 400 Bad Request 반환 (Spring 자동 처리)
    • + *
    • 정부 API 호출 실패 시 해당 HTTP 상태 코드 그대로 반환
    • + *
    • 네트워크 오류나 기타 예외 발생 시 RuntimeException으로 래핑되어 처리
    • + *
    + * + * @param envelope 자동차 기본사항 조회 요청을 담은 Envelope 객체 공통 헤더(header)와 실제 요청 데이터(data)로 구성됨 + * @return ResponseEntity<Envelope<BasicResponse>> 조회 결과를 담은 응답 객체 HTTP 상태 코드, 헤더, 응답 바디를 포함 + */ + @PostMapping(value = "/new-basic", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @Operation( + summary = "자동차기본사항조회 - 신버전", + description = "시군구연계 자동차기본사항조회 인터페이스. 요청 바디를 모델로 받아 정부시스템으로 전달합니다.", + requestBody = @RequestBody( + content = @Content( + mediaType = MediaType.APPLICATION_JSON_VALUE, + examples = @ExampleObject( + name = "기본사항조회 예제", + value = """ + { + "data": [{ + "record": [{ + "LEVY_STDDE": "20250101", + "VHRNO": "차량번호", + "VIN": null + }] + }] + } + """ + ) + ) + ) + ) + public ResponseEntity> newBasic( + @jakarta.validation.Valid @org.springframework.web.bind.annotation.RequestBody Envelope envelope + ) { + // 서비스에서 요청 보강/로깅/호출을 모두 오케스트레이션 + return service.newBasic(envelope); + } + /** * 자동차 등록원부(갑) 조회 API * diff --git a/src/main/java/com/vmis/interfaceapp/model/basic/NewBasicRequest.java b/src/main/java/com/vmis/interfaceapp/model/basic/NewBasicRequest.java new file mode 100644 index 0000000..d949012 --- /dev/null +++ b/src/main/java/com/vmis/interfaceapp/model/basic/NewBasicRequest.java @@ -0,0 +1,71 @@ +package com.vmis.interfaceapp.model.basic; + +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 { + + // 본문 공통 메타 (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; + + @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; + } + +} diff --git a/src/main/java/com/vmis/interfaceapp/model/basic/NewBasicResponse.java b/src/main/java/com/vmis/interfaceapp/model/basic/NewBasicResponse.java new file mode 100644 index 0000000..a170b20 --- /dev/null +++ b/src/main/java/com/vmis/interfaceapp/model/basic/NewBasicResponse.java @@ -0,0 +1,130 @@ +package com.vmis.interfaceapp.model.basic; + +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; + +/** + * 자동차기본사항조회 응답 모델 (신버전) + * + *

    + * 국토교통부 → 지자체 응답 규격을 매핑한 모델입니다. 상위에 연계결과 정보가 오고, + * 상세 데이터는 record 배열로 전달됩니다. + *

    + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +@Schema(description = "자동차기본사항조회 응답 모델 (신버전)") +@Getter +@Setter +public class NewBasicResponse { + + /** 연계결과코드 (성공/실패 코드) */ + @JsonProperty("LINK_RSLT_CD") + private String linkRsltCd; + + /** 연계결과상세 (에러 메시지 등 상세 사유) */ + @JsonProperty("LINK_RSLT_DTL") + private String linkRsltDtl; + + /** 응답 레코드 목록 */ + @JsonProperty("record") + private List 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; // 압류건수 + } +} diff --git a/src/main/java/com/vmis/interfaceapp/model/basic/OldBasicResponse.java b/src/main/java/com/vmis/interfaceapp/model/basic/OldBasicResponse.java index 34b3deb..dbc1bb6 100644 --- a/src/main/java/com/vmis/interfaceapp/model/basic/OldBasicResponse.java +++ b/src/main/java/com/vmis/interfaceapp/model/basic/OldBasicResponse.java @@ -9,6 +9,14 @@ import lombok.Setter; import java.util.List; +/** + * 자동차기본사항조회 응답 모델 (구버전) + * + *

    + * 구 규격(도로교통공단/교통안전공단 구버전) 응답을 매핑한 모델입니다. + * 상단에 연계 결과코드/상세가 오고, 상세 데이터는 record 배열로 내려옵니다. + *

    + */ @JsonInclude(JsonInclude.Include.NON_NULL) @JsonIgnoreProperties(ignoreUnknown = true) @Schema(description = "자동차기본사항조회 응답 모델 (구버전)") @@ -16,12 +24,15 @@ import java.util.List; @Setter public class OldBasicResponse { + /** 연계결과코드 */ @JsonProperty("CNTC_RESULT_CODE") private String cntcResultCode; + /** 연계결과상세 */ @JsonProperty("CNTC_RESULT_DTLS") private String cntcResultDtls; + /** 응답 레코드 목록 */ @JsonProperty("record") private List record; @@ -32,90 +43,90 @@ public class OldBasicResponse { @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; + @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; // 전기복합연료소비율 } } diff --git a/src/main/java/com/vmis/interfaceapp/model/common/RequestEnricher.java b/src/main/java/com/vmis/interfaceapp/model/common/RequestEnricher.java index 7f20953..89c4d44 100644 --- a/src/main/java/com/vmis/interfaceapp/model/common/RequestEnricher.java +++ b/src/main/java/com/vmis/interfaceapp/model/common/RequestEnricher.java @@ -2,6 +2,7 @@ package com.vmis.interfaceapp.model.common; import com.vmis.interfaceapp.config.properties.NewVmisProperties; import com.vmis.interfaceapp.config.properties.OldVmisProperties; +import com.vmis.interfaceapp.model.basic.NewBasicRequest; import com.vmis.interfaceapp.model.basic.OldBasicRequest; import com.vmis.interfaceapp.model.ledger.NewLedgerRequest; import lombok.extern.slf4j.Slf4j; @@ -77,6 +78,45 @@ public class RequestEnricher { sys.getInfoSysId(), sys.getInfoSysIp(), sys.getSigunguCode(), cntc); } + public void enrichNewBasic(Envelope envelope) { + if (envelope == null || envelope.getData() == null) return; + NewVmisProperties.SystemProps sys = newProps.getSystem(); + String linkInfoCd = oldProps.getGov().getServices().getBasic().getCntcInfoCode(); + for (NewBasicRequest req : envelope.getData()) { + if (req == null) continue; + // 메타 필드 보강 (data level) + req.setInfoSysId(sys.getInfoSysId()); + req.setInfoSysIpAddr(sys.getInfoSysIpAddr()); + req.setSggCd(sys.getSggCd()); + req.setLinkInfoCd(linkInfoCd); + req.setPicId(sys.getPicId()); + req.setPicIpAddr(sys.getPicIpAddr()); + req.setPicNm(sys.getPicNm()); + + // record 배열이 없으면 생성 (최소 1개) + java.util.List records = req.getRecord(); + if (records == null || records.isEmpty()) { + NewBasicRequest.Record r = new NewBasicRequest.Record(); + java.util.ArrayList list = new java.util.ArrayList<>(); + list.add(r); + req.setRecord(list); + records = list; + } + + // 자동차 기본사항 조회 시 INQIRE_SE_CODE 자동 설정 + // VHRNO(차량번호) not null → 3:자동차번호, VIN(차대번호) not null → 2:차대번호 + for (NewBasicRequest.Record record : records) { + if (record.getVhrno() != null && !record.getVhrno().trim().isEmpty()) { + record.setInqSeCd("3"); + } else if (record.getVin() != null && !record.getVin().trim().isEmpty()) { + record.setInqSeCd("2"); + } + } + } + log.debug("[ENRICH] newBasic: applied INFO_SYS_ID={}, INFO_SYS_IP_ADDR={}, SGG_CD={}, LINK_INFO_CD={}", + sys.getInfoSysId(), sys.getInfoSysIpAddr(), sys.getSggCd(), linkInfoCd); + } + public void enrichNewLedger(Envelope envelope) { if (envelope == null || envelope.getData() == null) return; NewVmisProperties.SystemProps sys = newProps.getSystem(); diff --git a/src/main/java/com/vmis/interfaceapp/service/VehicleInterfaceService.java b/src/main/java/com/vmis/interfaceapp/service/VehicleInterfaceService.java index 5bc6876..fd8a069 100644 --- a/src/main/java/com/vmis/interfaceapp/service/VehicleInterfaceService.java +++ b/src/main/java/com/vmis/interfaceapp/service/VehicleInterfaceService.java @@ -1,6 +1,8 @@ package com.vmis.interfaceapp.service; import com.vmis.interfaceapp.client.GovernmentApi; +import com.vmis.interfaceapp.model.basic.NewBasicRequest; +import com.vmis.interfaceapp.model.basic.NewBasicResponse; import com.vmis.interfaceapp.model.basic.OldBasicRequest; import com.vmis.interfaceapp.model.basic.OldBasicResponse; import com.vmis.interfaceapp.model.common.Envelope; @@ -32,6 +34,14 @@ public class VehicleInterfaceService { return response; } + public ResponseEntity> newBasic(Envelope envelope) { + // 1) 요청 보강 + enricher.enrichNewBasic(envelope); + // 2) 외부 API 호출 + ResponseEntity> response = governmentApi.callNewBasic(envelope); + return response; + } + public ResponseEntity> newLedger(Envelope envelope) { // 1) 요청 보강