feat: 차량 정보 조회 기능 추가

- VehicleInquiryController 신설: 차량 통합 조회, 기본정보 조회, 등록원부(갑) 조회 기능 제공
  - `/getIntegratedInfo.do`: 차량 통합 조회 엔드포인트 추가
  - `/getBasicInfo.do`: 차량 기본정보 조회 엔드포인트 추가
  - `/getLedgerInfo.do`: 차량 등록원부(갑) 조회 엔드포인트 추가
  - Swagger API 문서화 추가

- 차량 정보 조회 화면 JSP 파일 추가: `/WEB-INF/views/carInspectionPenalty/callApi/inquiry.jsp`
  - 조회 필드 및 조회 결과 표시 UI 구현
  - 차량 통합 조회, 기본 조회, 등록원부 조회 옵션 제공
  - 입력값 유효성 검증 및 초기화 버튼 기능 구현
  - AJAX 기반 API 요청/응답 처리 로직 추가

- 서비스 계층 VehicleInfoService 의존성 주입하여 통합 로직 처리

 새로운 차량 조회 기능 제공 및 사용자 편의성 개선
internalApi
박성영 1 month ago
parent aa73fff2de
commit 6bdfc0001f

@ -1,5 +1,6 @@
package go.kr.project.api.external.service.impl;
import egovframework.exception.MessageException;
import go.kr.project.api.config.ApiConstant;
import go.kr.project.api.external.service.ExternalVehicleApiService;
import go.kr.project.api.model.request.BasicRequest;
@ -170,7 +171,7 @@ public class ExternalVehicleApiServiceImpl implements ExternalVehicleApiService
} catch (Exception e) {
log.error("차량 기본정보 조회 API 호출 실패 - 차량번호: {}", request.getVhrno(), e);
throw new RuntimeException("차량 기본정보 조회 실패: " + e.getMessage(), e);
throw new MessageException("차량 기본정보 조회 실패: " + e.getMessage(), e);
}
}
@ -215,7 +216,7 @@ public class ExternalVehicleApiServiceImpl implements ExternalVehicleApiService
} catch (Exception e) {
log.error("자동차 등록원부 조회 API 호출 실패 - 차량번호: {}", request.getVhrno(), e);
throw new RuntimeException("자동차 등록원부 조회 실패: " + e.getMessage(), e);
throw new MessageException("자동차 등록원부 조회 실패: " + e.getMessage(), e);
}
}
}

@ -0,0 +1,137 @@
package go.kr.project.carInspectionPenalty.callApi.controller;
import egovframework.constant.TilesConstants;
import egovframework.util.ApiResponseUtil;
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 io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
/**
*
* , , .
*/
@Controller
@RequestMapping("/carInspectionPenalty/callApi")
@RequiredArgsConstructor
@Slf4j
@Tag(name = "차량 정보 조회", description = "차량 정보 조회 API")
public class VehicleInquiryController {
private final VehicleInfoService vehicleInfoService;
/**
*
*/
@GetMapping("/inquiry.do")
public String inquiryPage(Model model) {
log.debug("차량 정보 조회 화면 진입");
return "carInspectionPenalty/callApi/inquiry" + TilesConstants.BASE;
}
/**
* ( + )
*
* @param request
* @return
*/
@PostMapping("/getIntegratedInfo.do")
@ResponseBody
@Operation(summary = "자동차 통합 조회", description = "차량 기본정보와 등록원부 정보를 함께 조회합니다.")
public ResponseEntity<?> getIntegratedInfo(@RequestBody BasicRequest request) {
log.info("========== 자동차 통합 조회 시작 ==========");
log.info("요청 차량번호: {}", request.getVhrno());
log.info("부과기준일: {}", request.getLevyStdde());
log.info("조회구분코드: {}", request.getInqireSeCode());
log.info("차대번호: {}", request.getVin());
// 입력값 검증
if (!StringUtils.hasText(request.getVhrno())) {
log.warn("차량번호가 입력되지 않았습니다.");
return ApiResponseUtil.error("차량번호를 입력해주세요.");
}
// 차량 정보 조회
VehicleApiResponseVO response = vehicleInfoService.getVehicleInfo(request);
if(!response.isSuccess()) {
log.warn("자동차 통합 조회 실패 - 차량번호: {}, 메시지: {}", request.getVhrno(), response.getMessage());
log.warn("========== 자동차 통합 조회 실패 ==========");
return ApiResponseUtil.error(response.getMessage());
}
log.info("자동차 통합 조회 성공 - 차량번호: {}", request.getVhrno());
log.info("========== 자동차 통합 조회 완료 ==========");
return ApiResponseUtil.success(response, "자동차 통합 조회가 완료되었습니다.");
}
/**
* ()
*
* @param request
* @return
*/
@PostMapping("/getBasicInfo.do")
@ResponseBody
@Operation(summary = "자동차 기본사항 조회", description = "차량 기본정보만 조회합니다.")
public ResponseEntity<?> getBasicInfo(@RequestBody BasicRequest request) {
log.info("========== 자동차 기본사항 조회 시작 ==========");
log.info("요청 차량번호: {}", request.getVhrno());
log.info("부과기준일: {}", request.getLevyStdde());
log.info("조회구분코드: {}", request.getInqireSeCode());
log.info("차대번호: {}", request.getVin());
// 입력값 검증
if (!StringUtils.hasText(request.getVhrno())) {
log.warn("차량번호가 입력되지 않았습니다.");
return ApiResponseUtil.error("차량번호를 입력해주세요.");
}
// 차량 기본정보 조회
BasicResponse response = vehicleInfoService.getBasicInfo(request);
log.info("자동차 기본사항 조회 성공 - 차량번호: {}", request.getVhrno());
log.info("========== 자동차 기본사항 조회 완료 ==========");
return ApiResponseUtil.success(response, "자동차 기본사항 조회가 완료되었습니다.");
}
/**
* () ()
*
* @param request
* @return
*/
@PostMapping("/getLedgerInfo.do")
@ResponseBody
@Operation(summary = "자동차 등록원부(갑) 조회", description = "차량 등록원부 정보만 조회합니다.")
public ResponseEntity<?> getLedgerInfo(@RequestBody LedgerRequest request) {
log.info("========== 자동차 등록원부(갑) 조회 시작 ==========");
log.info("요청 차량번호: {}", request.getVhrno());
log.info("조회구분코드: {}", request.getInqireSeCode());
log.info("민원인성명: {}", request.getCpttrNm());
// 입력값 검증
if (!StringUtils.hasText(request.getVhrno())) {
log.warn("차량번호가 입력되지 않았습니다.");
return ApiResponseUtil.error("차량번호를 입력해주세요.");
}
// 차량 등록원부 조회
LedgerResponse response = vehicleInfoService.getLedgerInfo(request);
log.info("자동차 등록원부(갑) 조회 성공 - 차량번호: {}", request.getVhrno());
log.info("========== 자동차 등록원부(갑) 조회 완료 ==========");
return ApiResponseUtil.success(response, "자동차 등록원부(갑) 조회가 완료되었습니다.");
}
}

@ -1,4 +1,4 @@
package go.kr.project.carInspectionPenalty.search.Controller;
package go.kr.project.carInspectionPenalty.search.controller;
import egovframework.constant.TilesConstants;
import egovframework.util.ApiResponseUtil;

@ -192,20 +192,20 @@ vmis:
# GPKI 암호화 설정 (개발 환경: 비활성화)
gpki:
enabled: "N" # 개발 환경에서는 암호화 미사용
useSign: true
charset: "UTF-8"
certServerId: "SVR5640020001"
targetServerId: "SVR1500000015"
ldap: true
gpkiLicPath: "src/GPKI/conf"
certFilePath: "src/GPKI/certs"
envCertFilePathName: "src/GPKI/certs/SVR5640020001_env.cer"
envPrivateKeyFilePathName: "src/GPKI/certs/SVR5640020001_env.key"
envPrivateKeyPasswd: "*sbm204221"
sigCertFilePathName: "src/GPKI/certs/SVR5640020001_sig.cer"
sigPrivateKeyFilePathName: "src/GPKI/certs/SVR5640020001_sig.key"
sigPrivateKeyPasswd: "*sbm204221"
enabled: "N" # GPKI 사용 여부 (개발환경에서는 비활성화)
useSign: true # 서명 사용 여부
charset: "UTF-8" # 문자셋 인코딩
certServerId: "SVR5640020001" # 인증서 서버 ID (요청 시스템)
targetServerId: "SVR1611000006" # 대상 서버 ID (차세대교통안전공단)
ldap: true # LDAP 사용 여부
gpkiLicPath: "C:\\GPKI\\Lic" # GPKI 라이선스 파일 경로
certFilePath: "c:\\GPKI\\Certificate\\class1" # 인증서 파일 디렉토리 경로
envCertFilePathName: "c:\\GPKI\\Certificate\\class1\\SVR5640020001_env.cer" # 암호화용 인증서 파일 경로
envPrivateKeyFilePathName: "c:\\GPKI\\Certificate\\class1\\SVR5640020001_env.key" # 암호화용 개인키 파일 경로
envPrivateKeyPasswd: "*sbm204221" # 암호화용 개인키 비밀번호
sigCertFilePathName: "c:\\GPKI\\Certificate\\class1\\SVR5640020001_sig.cer" # 서명용 인증서 파일 경로
sigPrivateKeyFilePathName: "c:\\GPKI\\Certificate\\class1\\SVR5640020001_sig.key" # 서명용 개인키 파일 경로
sigPrivateKeyPasswd: "*sbm204221" # 서명용 개인키 비밀번호
# 정부 API 연동 설정 (개발 행정망)
# 타임아웃 설정은 공통 rest-template 설정 사용

@ -160,7 +160,7 @@ juso:
key: "devU01TX0FVVEgyMDI1MDkyMjEyMTM1NzExNjI0NzE="
url: "https://business.juso.go.kr/addrlink/addrLinkApiJsonp.do"
# ===== VMIS 통합 설정 (Local 환경) =====
# ===== VMIS 통합 설정 (Dev 환경) =====
vmis:
integration:
mode: external # internal: 내부 VMIS 모듈 직접 호출, external: 외부 REST API 호출
@ -192,29 +192,29 @@ vmis:
# Internal Mode 설정 (내부 VMIS 모듈 사용 시)
system:
infoSysId: "41-345" # 정보시스템 ID
infoSysIp: "${SERVER_IP:105.19.10.135}" # 시스템 IP
infoSysIp: "105.19.10.135" # 시스템 IP
sigunguCode: "41460" # 시군구 코드
departmentCode: "" # 부서 코드
chargerId: "" # 담당자 ID
chargerIp: "" # 담당자 IP
chargerNm: "" # 담당자명
# GPKI 암호화 설정 (로컬 환경: 비활성화)
# GPKI 암호화 설정 (개발 환경: 비활성화)
gpki:
enabled: "N" # 로컬 환경에서는 암호화 미사용
useSign: true
charset: "UTF-8"
certServerId: "SVR5640020001"
targetServerId: "SVR1500000015"
ldap: true
gpkiLicPath: "src/GPKI/conf"
certFilePath: "src/GPKI/certs"
envCertFilePathName: "src/GPKI/certs/SVR5640020001_env.cer"
envPrivateKeyFilePathName: "src/GPKI/certs/SVR5640020001_env.key"
envPrivateKeyPasswd: "${GPKI_ENV_PASSWORD:*sbm204221}"
sigCertFilePathName: "src/GPKI/certs/SVR5640020001_sig.cer"
sigPrivateKeyFilePathName: "src/GPKI/certs/SVR5640020001_sig.key"
sigPrivateKeyPasswd: "${GPKI_SIG_PASSWORD:*sbm204221}"
enabled: "N" # GPKI 사용 여부 (개발환경에서는 비활성화)
useSign: true # 서명 사용 여부
charset: "UTF-8" # 문자셋 인코딩
certServerId: "SVR5640020001" # 인증서 서버 ID (요청 시스템)
targetServerId: "SVR1611000006" # 대상 서버 ID (차세대교통안전공단)
ldap: true # LDAP 사용 여부
gpkiLicPath: "C:\\GPKI\\Lic" # GPKI 라이선스 파일 경로
certFilePath: "c:\\GPKI\\Certificate\\class1" # 인증서 파일 디렉토리 경로
envCertFilePathName: "c:\\GPKI\\Certificate\\class1\\SVR5640020001_env.cer" # 암호화용 인증서 파일 경로
envPrivateKeyFilePathName: "c:\\GPKI\\Certificate\\class1\\SVR5640020001_env.key" # 암호화용 개인키 파일 경로
envPrivateKeyPasswd: "*sbm204221" # 암호화용 개인키 비밀번호
sigCertFilePathName: "c:\\GPKI\\Certificate\\class1\\SVR5640020001_sig.cer" # 서명용 인증서 파일 경로
sigPrivateKeyFilePathName: "c:\\GPKI\\Certificate\\class1\\SVR5640020001_sig.key" # 서명용 개인키 파일 경로
sigPrivateKeyPasswd: "*sbm204221" # 서명용 개인키 비밀번호
# 정부 API 연동 설정 (개발 행정망)
# 타임아웃 설정은 공통 rest-template 설정 사용
@ -226,13 +226,13 @@ vmis:
basic: # 시군구연계 자동차기본사항조회
path: "/SignguCarBassMatterInqireService"
cntcInfoCode: "AC1_FD11_01"
apiKey: "${GOV_API_KEY_BASIC:05e8d748fb366a0831dce71a32424460746a72d591cf483ccc130534dd51e394}"
cvmisApikey: "${GOV_CVMIS_API_KEY_BASIC:014F9215-B6D9A3B6-4CED5225-68408C46}"
apiKey: "05e8d748fb366a0831dce71a32424460746a72d591cf483ccc130534dd51e394"
cvmisApikey: "014F9215-B6D9A3B6-4CED5225-68408C46"
ledger: # 시군구연계 자동차등록원부(갑)
path: "/SignguCarLedgerFrmbkService"
cntcInfoCode: "AC1_FD11_02"
apiKey: "${GOV_API_KEY_LEDGER:1beeb01857c2e7e9b41c002b007ccb9754d9c272f66d4bb64fc45b302c69e529}"
cvmisApikey: "${GOV_CVMIS_API_KEY_LEDGER:63DF159B-7B9C64C5-86CCB15C-5F93E750}"
apiKey: "1beeb01857c2e7e9b41c002b007ccb9754d9c272f66d4bb64fc45b302c69e529"
cvmisApikey: "63DF159B-7B9C64C5-86CCB15C-5F93E750"
# External Mode 설정 (외부 REST API 사용 시)
# 타임아웃 설정은 공통 rest-template 설정 사용

@ -200,20 +200,20 @@ vmis:
# GPKI 암호화 설정 (운영 환경: 활성화)
gpki:
enabled: "Y" # 운영 환경에서는 암호화 사용
useSign: true
charset: "UTF-8"
certServerId: "SVR5640020001" # 운영 인증서 ID로 교체 필요
targetServerId: "SVR1500000015"
ldap: true
gpkiLicPath: "src/GPKI/conf"
certFilePath: "src/GPKI/certs"
envCertFilePathName: "src/GPKI/certs/SVR5640020001_env.cer"
envPrivateKeyFilePathName: "src/GPKI/certs/SVR5640020001_env.key"
envPrivateKeyPasswd: "*sbm204221"
sigCertFilePathName: "src/GPKI/certs/SVR5640020001_sig.cer"
sigPrivateKeyFilePathName: "src/GPKI/certs/SVR5640020001_sig.key"
sigPrivateKeyPasswd: "*sbm204221"
enabled: "Y" # GPKI 사용 여부 (운영환경에서는 활성화)
useSign: true # 서명 사용 여부
charset: "UTF-8" # 문자셋 인코딩
certServerId: "SVR5640020001" # 인증서 서버 ID (요청 시스템)
targetServerId: "SVR1611000006" # 대상 서버 ID (차세대교통안전공단)
ldap: true # LDAP 사용 여부
gpkiLicPath: "C:\\GPKI\\Lic" # GPKI 라이선스 파일 경로
certFilePath: "c:\\GPKI\\Certificate\\class1" # 인증서 파일 디렉토리 경로
envCertFilePathName: "c:\\GPKI\\Certificate\\class1\\SVR5640020001_env.cer" # 암호화용 인증서 파일 경로
envPrivateKeyFilePathName: "c:\\GPKI\\Certificate\\class1\\SVR5640020001_env.key" # 암호화용 개인키 파일 경로
envPrivateKeyPasswd: "*sbm204221" # 암호화용 개인키 비밀번호
sigCertFilePathName: "c:\\GPKI\\Certificate\\class1\\SVR5640020001_sig.cer" # 서명용 인증서 파일 경로
sigPrivateKeyFilePathName: "c:\\GPKI\\Certificate\\class1\\SVR5640020001_sig.key" # 서명용 개인키 파일 경로
sigPrivateKeyPasswd: "*sbm204221" # 서명용 개인키 비밀번호
# 정부 API 연동 설정 (운영 행정망)
# 타임아웃 설정은 공통 rest-template 설정 사용

@ -0,0 +1,576 @@
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="dateUtil" uri="http://egovframework.go.kr/functions/date-util" %>
<!-- Main body -->
<div class="main_body">
<section id="section8" class="main_bars">
<div class="bgs-main">
<section id="section5">
<div class="sub_title"></div>
</section>
</div>
</section>
<div class="contants_body">
<div class="gs_b_top">
<ul class="lef">
<li class="th">조회 구분</li>
<li>
<select id="inqryType" name="inqryType" class="input" style="width: 250px;">
<option value="integrated">자동차 통합 조회 (기본+등록원부)</option>
<option value="basic">자동차 기본사항 조회 (단독)</option>
<option value="ledger">자동차 등록원부(갑) 조회 (단독)</option>
</select>
</li>
<li class="th"><span class="essential">*</span> 차량번호</li>
<li>
<input type="text" id="vhrno" name="vhrno" class="input" style="width: 150px;" placeholder="예: 12가3456" maxlength="10" autocomplete="off"/>
</li>
<li class="th basicField" style="display: inline;">부과기준일</li>
<li class="basicField" style="display: inline;">
<input type="text" id="levyStdde" name="levyStdde" class="input datepicker calender" style="width: 150px;" autocomplete="off" value="${dateUtil:getCurrentDateTime('yyyy-MM-dd')}"/>
</li>
<li class="th basicField" style="display: inline;">조회구분</li>
<li class="basicField" style="display: inline;">
<select id="inqireSeCode" name="inqireSeCode" class="input" style="width: 100px;">
<option value="1" selected>열람</option>
<option value="2">발급</option>
</select>
</li>
<li class="th basicField" style="display: inline;">차대번호</li>
<li class="basicField" style="display: inline;">
<input type="text" id="vin" name="vin" class="input" style="width: 200px;" placeholder="예: KMHAB812345678901" maxlength="17" autocomplete="off"/>
</li>
<li class="th ledgerField" style="display: none;">민원인성명</li>
<li class="ledgerField" style="display: none;">
<input type="text" id="cpttrNm" name="cpttrNm" class="input" style="width: 150px;" placeholder="민원인성명" autocomplete="off"/>
</li>
<li class="th ledgerField" style="display: none;">민원인주민번호</li>
<li class="ledgerField" style="display: none;">
<input type="text" id="cpttrIhidnum" name="cpttrIhidnum" class="input" style="width: 200px;" placeholder="민원인주민번호" maxlength="13" autocomplete="off"/>
</li>
</ul>
<ul class="rig2">
<li><button type="button" id="search_btn" class="newbtnss bg1">조회</button></li>
<li><button type="button" id="reset_btn" class="newbtnss bg5" style="margin-left: 5px;">초기화</button></li>
</ul>
</div>
<div class="gs_booking">
<div class="row">
<div class="col-sm-12">
<div class="box_column">
<ul class="box_title" style="display: flex; justify-content: space-between; align-items: center;">
<li class="tit">조회 결과</li>
<li class="rig">
<button type="button" id="btnResultClose" class="newbtn bg5" style="display: none;">닫기</button>
</li>
</ul>
<div class="containers" style="padding: 20px;">
<div id="resultContent" class="result-empty">
조회 버튼을 클릭하여 차량 정보를 조회하세요.
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- /Main body -->
<style>
.essential {
color: red;
font-weight: bold;
margin-right: 3px;
}
.result-empty {
text-align: center;
padding: 40px;
color: #999;
font-size: 14px;
}
.result-detail-table {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
}
.result-detail-table th {
background-color: #f5f5f5;
padding: 12px;
border: 1px solid #ddd;
text-align: left;
font-weight: bold;
width: 20%;
color: #333;
}
.result-detail-table td {
padding: 12px;
border: 1px solid #ddd;
width: 30%;
color: #555;
}
.result-section-title {
background-color: #2c5aa0;
color: white;
padding: 10px 15px;
margin-top: 20px;
margin-bottom: 10px;
font-weight: bold;
border-radius: 4px;
}
.result-section-title:first-child {
margin-top: 0;
}
</style>
<script type="text/javascript">
/**
* 차량 정보 조회 모듈
*/
(function(window, $) {
'use strict';
var VehicleInquiry = {
/**
* 조회 구분 변경 시 필드 표시/숨김
*/
onInqryTypeChange: function() {
var inqryType = $("#inqryType").val();
// 모든 필드 초기화
$(".basicField").hide();
$(".ledgerField").hide();
// 조회 구분에 따른 필드 표시
if (inqryType === "integrated" || inqryType === "basic") {
$(".basicField").show();
}
if (inqryType === "ledger") {
$(".ledgerField").show();
}
},
/**
* 조회 실행
*/
executeSearch: function() {
var self = this;
var inqryType = $("#inqryType").val();
var vhrno = $.trim($("#vhrno").val());
// 차량번호 검증
if (!vhrno) {
alert("차량번호를 입력해주세요.");
$("#vhrno").focus();
return;
}
// 조회 타입에 따라 처리
if (inqryType === "integrated") {
self.callIntegratedApi();
} else if (inqryType === "basic") {
self.callBasicApi();
} else if (inqryType === "ledger") {
self.callLedgerApi();
}
},
/**
* 통합 조회 API 호출
*/
callIntegratedApi: function() {
var self = this;
var vhrno = $.trim($("#vhrno").val());
var levyStdde = $.trim($("#levyStdde").val()).replace(/-/g, '');
var inqireSeCode = $("#inqireSeCode").val();
var vin = $.trim($("#vin").val());
// BasicRequest의 @JsonProperty에 맞춰 대문자 키 사용
var params = {
VHRNO: vhrno,
LEVY_STDDE: levyStdde,
INQIRE_SE_CODE: inqireSeCode
};
if (vin) {
params.VIN = vin;
}
$.ajax({
url: '/carInspectionPenalty/callApi/getIntegratedInfo.do',
type: 'POST',
contentType: 'application/json; charset=UTF-8',
data: JSON.stringify(params),
dataType: 'json',
success: function(response) {
if (response.success) {
console.log("통합 조회 성공:", response.data);
self.displayIntegratedResult(response.data);
$("#btnResultClose").show();
} else {
alert("조회 실패\n\n" + (response.message || "알 수 없는 오류가 발생했습니다."));
$("#resultContent").html('<div class="result-empty">조회된 데이터가 없습니다.</div>');
}
},
error: function(xhr, status, error) {
$("#resultContent").html('<div class="result-empty">조회 중 오류가 발생했습니다.</div>');
}
});
},
/**
* 기본사항 조회 API 호출
*/
callBasicApi: function() {
var self = this;
var vhrno = $.trim($("#vhrno").val());
var levyStdde = $.trim($("#levyStdde").val()).replace(/-/g, '');
var inqireSeCode = $("#inqireSeCode").val();
var vin = $.trim($("#vin").val());
// BasicRequest의 @JsonProperty에 맞춰 대문자 키 사용
var params = {
VHRNO: vhrno,
LEVY_STDDE: levyStdde,
INQIRE_SE_CODE: inqireSeCode
};
if (vin) {
params.VIN = vin;
}
$.ajax({
url: '/carInspectionPenalty/callApi/getBasicInfo.do',
type: 'POST',
contentType: 'application/json; charset=UTF-8',
data: JSON.stringify(params),
dataType: 'json',
success: function(response) {
if (response.success) {
console.log("기본사항 조회 성공:", response.data);
self.displayBasicResult(response.data);
$("#btnResultClose").show();
} else {
alert("조회 실패\n\n" + (response.message || "알 수 없는 오류가 발생했습니다."));
$("#resultContent").html('<div class="result-empty">조회된 데이터가 없습니다.</div>');
}
},
error: function(xhr, status, error) {
$("#resultContent").html('<div class="result-empty">조회 중 오류가 발생했습니다.</div>');
}
});
},
/**
* 등록원부 조회 API 호출
*/
callLedgerApi: function() {
var self = this;
var vhrno = $.trim($("#vhrno").val());
var inqireSeCode = $("#inqireSeCode").val() || "1";
var cpttrNm = $.trim($("#cpttrNm").val());
var cpttrIhidnum = $.trim($("#cpttrIhidnum").val());
// LedgerRequest의 @JsonProperty에 맞춰 대문자 키 사용
var params = {
VHRNO: vhrno,
INQIRE_SE_CODE: inqireSeCode
};
if (cpttrNm) {
params.CPTTR_NM = cpttrNm;
}
if (cpttrIhidnum) {
params.CPTTR_IHIDNUM = cpttrIhidnum;
}
$.ajax({
url: '/carInspectionPenalty/callApi/getLedgerInfo.do',
type: 'POST',
contentType: 'application/json; charset=UTF-8',
data: JSON.stringify(params),
dataType: 'json',
success: function(response) {
if (response.success) {
console.log("등록원부 조회 성공:", response.data);
self.displayLedgerResult(response.data);
$("#btnResultClose").show();
} else {
alert("조회 실패\n\n" + (response.message || "알 수 없는 오류가 발생했습니다."));
$("#resultContent").html('<div class="result-empty">조회된 데이터가 없습니다.</div>');
}
},
error: function(xhr, status, error) {
$("#resultContent").html('<div class="result-empty">조회 중 오류가 발생했습니다.</div>');
}
});
},
/**
* 통합 조회 결과 표시
*/
displayIntegratedResult: function(data) {
var html = '';
// 기본 정보
if (data.basicInfo) {
html += '<div class="result-section-title">자동차 기본 정보</div>';
html += '<table class="result-detail-table">';
html += '<colgroup><col style="width:20%"><col style="width:30%"><col style="width:20%"><col style="width:30%"></colgroup>';
html += '<tr><th>차량번호</th><td>' + this.nvl(data.vhrno) + '</td>';
html += '<th>차대번호</th><td>' + this.nvl(data.basicInfo.vin) + '</td></tr>';
html += '<tr><th>차명</th><td>' + this.nvl(data.basicInfo.cnm) + '</td>';
html += '<th>연식</th><td>' + this.nvl(data.basicInfo.prye) + '</td></tr>';
html += '<tr><th>등록일</th><td>' + this.nvl(data.basicInfo.registDe) + '</td>';
html += '<th>배기량</th><td>' + this.nvl(data.basicInfo.dsplvl) + '</td></tr>';
html += '<tr><th>차종종별명</th><td>' + this.nvl(data.basicInfo.vhctyAsortNm) + '</td>';
html += '<th>차종유형명</th><td>' + this.nvl(data.basicInfo.vhctyTyNm) + '</td></tr>';
html += '<tr><th>차종분류명</th><td>' + this.nvl(data.basicInfo.vhctySeNm) + '</td>';
html += '<th>용도구분코드</th><td>' + this.nvl(data.basicInfo.prposSeCode) + '</td></tr>';
html += '<tr><th>색상명</th><td>' + this.nvl(data.basicInfo.colorNm) + '</td>';
html += '<th>형식</th><td>' + this.nvl(data.basicInfo.fomNm) + '</td></tr>';
html += '<tr><th>대표소유자성명</th><td>' + this.nvl(data.basicInfo.mberNm) + '</td>';
html += '<th>대표소유자전화번호</th><td>' + this.nvl(data.basicInfo.telno) + '</td></tr>';
html += '<tr><th>사용본거지전체주소</th><td colspan="3">' + this.nvl(data.basicInfo.usgsrhldAdresFull) + '</td></tr>';
html += '<tr><th>소유자전체주소</th><td colspan="3">' + this.nvl(data.basicInfo.ownrWholaddr) + '</td></tr>';
html += '<tr><th>검사유효기간</th><td>' + this.nvl(data.basicInfo.insptValidPdBgnde) + ' ~ ' + this.nvl(data.basicInfo.insptValidPdEndde) + '</td>';
html += '<th>말소등록구분명</th><td>' + this.nvl(data.basicInfo.ersrRegistSeNm) + '</td></tr>';
html += '</table>';
}
// 등록원부 정보
if (data.ledgerInfo) {
html += '<div class="result-section-title">자동차 등록원부 정보</div>';
html += '<table class="result-detail-table">';
html += '<colgroup><col style="width:20%"><col style="width:30%"><col style="width:20%"><col style="width:30%"></colgroup>';
html += '<tr><th>원부그룹번호</th><td>' + this.nvl(data.ledgerInfo.ledgerGroupNo) + '</td>';
html += '<th>원부개별번호</th><td>' + this.nvl(data.ledgerInfo.ledgerIndvdlzNo) + '</td></tr>';
html += '<tr><th>차량관리번호</th><td>' + this.nvl(data.ledgerInfo.vhmno) + '</td>';
html += '<th>차량등록번호</th><td>' + this.nvl(data.ledgerInfo.vhrno) + '</td></tr>';
html += '<tr><th>등록상세명</th><td>' + this.nvl(data.ledgerInfo.registDetailNm) + '</td>';
html += '<th>최초등록일</th><td>' + this.nvl(data.ledgerInfo.frstRegistDe) + '</td></tr>';
html += '<tr><th>차령종료일</th><td>' + this.nvl(data.ledgerInfo.caagEndde) + '</td>';
html += '<th>연식</th><td>' + this.nvl(data.ledgerInfo.prye) + '</td></tr>';
html += '<tr><th>번호판규격명</th><td>' + this.nvl(data.ledgerInfo.nmplStndrdNm) + '</td>';
html += '<th>색상명</th><td>' + this.nvl(data.ledgerInfo.colorNm) + '</td></tr>';
html += '<tr><th>검사유효기간</th><td>' + this.nvl(data.ledgerInfo.insptValidPdBgnde) + ' ~ ' + this.nvl(data.ledgerInfo.insptValidPdEndde) + '</td>';
html += '<th>점검유효기간</th><td>' + this.nvl(data.ledgerInfo.chckValidPdBgnde) + ' ~ ' + this.nvl(data.ledgerInfo.chckValidPdEndde) + '</td></tr>';
html += '<tr><th>대표소유자성명</th><td>' + this.nvl(data.ledgerInfo.mberNm) + '</td>';
html += '<th>대표소유자전화번호</th><td>' + this.nvl(data.ledgerInfo.telno) + '</td></tr>';
html += '<tr><th>사용본거지주소</th><td colspan="3">' + this.nvl(data.ledgerInfo.adres1) + ' ' + this.nvl(data.ledgerInfo.adresNm1) + '</td></tr>';
html += '<tr><th>소유자주소</th><td colspan="3">' + this.nvl(data.ledgerInfo.adres) + ' ' + this.nvl(data.ledgerInfo.adresNm) + '</td></tr>';
html += '<tr><th>저당수</th><td>' + this.nvl(data.ledgerInfo.mrtgcnt) + '</td>';
html += '<th>압류건수</th><td>' + this.nvl(data.ledgerInfo.vhclecnt) + '</td></tr>';
html += '</table>';
}
$("#resultContent").html(html);
},
/**
* 기본사항 조회 결과 표시
*/
displayBasicResult: function(data) {
var html = '<table class="result-detail-table">';
html += '<colgroup><col style="width:20%"><col style="width:30%"><col style="width:20%"><col style="width:30%"></colgroup>';
html += '<tr><th>차량번호</th><td>' + this.nvl(data.vhclno) + '</td>';
html += '<th>차대번호</th><td>' + this.nvl(data.vin) + '</td></tr>';
html += '<tr><th>차명</th><td>' + this.nvl(data.cnm) + '</td>';
html += '<th>연식</th><td>' + this.nvl(data.prye) + '</td></tr>';
html += '<tr><th>등록일</th><td>' + this.nvl(data.registDe) + '</td>';
html += '<th>배기량</th><td>' + this.nvl(data.dsplvl) + '</td></tr>';
html += '<tr><th>차종종별명</th><td>' + this.nvl(data.vhctyAsortNm) + '</td>';
html += '<th>차종유형명</th><td>' + this.nvl(data.vhctyTyNm) + '</td></tr>';
html += '<tr><th>차종분류명</th><td>' + this.nvl(data.vhctySeNm) + '</td>';
html += '<th>용도구분코드</th><td>' + this.nvl(data.prposSeCode) + '</td></tr>';
html += '<tr><th>색상명</th><td>' + this.nvl(data.colorNm) + '</td>';
html += '<th>형식</th><td>' + this.nvl(data.fomNm) + '</td></tr>';
html += '<tr><th>원동기형식명</th><td>' + this.nvl(data.mtrsFomNm) + '</td>';
html += '<th>최대적재량</th><td>' + this.nvl(data.mxmmLdg) + '</td></tr>';
html += '<tr><th>승차정원수</th><td>' + this.nvl(data.tkcarPscapCo) + '</td>';
html += '<th>차량총중량</th><td>' + this.nvl(data.vhcleTotWt) + '</td></tr>';
html += '<tr><th>대표소유자성명</th><td>' + this.nvl(data.mberNm) + '</td>';
html += '<th>대표소유자전화번호</th><td>' + this.nvl(data.telno) + '</td></tr>';
html += '<tr><th>사용본거지전체주소</th><td colspan="3">' + this.nvl(data.usgsrhldAdresFull) + '</td></tr>';
html += '<tr><th>소유자전체주소</th><td colspan="3">' + this.nvl(data.ownrWholaddr) + '</td></tr>';
html += '<tr><th>검사유효기간</th><td>' + this.nvl(data.insptValidPdBgnde) + ' ~ ' + this.nvl(data.insptValidPdEndde) + '</td>';
html += '<th>최초등록일</th><td>' + this.nvl(data.frstRegistDe) + '</td></tr>';
html += '<tr><th>말소등록구분명</th><td>' + this.nvl(data.ersrRegistSeNm) + '</td>';
html += '<th>말소등록일</th><td>' + this.nvl(data.ersrRegistDe) + '</td></tr>';
html += '<tr><th>저당수</th><td>' + this.nvl(data.mrtgCo) + '</td>';
html += '<th>압류건수</th><td>' + this.nvl(data.seizrCo) + '</td></tr>';
html += '</table>';
$("#resultContent").html(html);
},
/**
* 등록원부 조회 결과 표시
*/
displayLedgerResult: function(data) {
var html = '<div class="result-section-title">등록원부 기본 정보</div>';
html += '<table class="result-detail-table">';
html += '<colgroup><col style="width:20%"><col style="width:30%"><col style="width:20%"><col style="width:30%"></colgroup>';
html += '<tr><th>차량등록번호</th><td>' + this.nvl(data.vhrno) + '</td>';
html += '<th>차대번호</th><td>' + this.nvl(data.vin) + '</td></tr>';
html += '<tr><th>원부그룹번호</th><td>' + this.nvl(data.ledgerGroupNo) + '</td>';
html += '<th>원부개별번호</th><td>' + this.nvl(data.ledgerIndvdlzNo) + '</td></tr>';
html += '<tr><th>차량관리번호</th><td>' + this.nvl(data.vhmno) + '</td>';
html += '<th>차명</th><td>' + this.nvl(data.cnm) + '</td></tr>';
html += '<tr><th>차종종별명</th><td>' + this.nvl(data.vhctyAsortNm) + '</td>';
html += '<th>용도구분명</th><td>' + this.nvl(data.prposSeNm) + '</td></tr>';
html += '<tr><th>등록상세명</th><td>' + this.nvl(data.registDetailNm) + '</td>';
html += '<th>최초등록일</th><td>' + this.nvl(data.frstRegistDe) + '</td></tr>';
html += '<tr><th>차령종료일</th><td>' + this.nvl(data.caagEndde) + '</td>';
html += '<th>연식</th><td>' + this.nvl(data.prye) + '</td></tr>';
html += '<tr><th>색상명</th><td>' + this.nvl(data.colorNm) + '</td>';
html += '<th>번호판규격명</th><td>' + this.nvl(data.nmplStndrdNm) + '</td></tr>';
html += '<tr><th>원동기형식명</th><td>' + this.nvl(data.mtrsFomNm) + '</td>';
html += '<th>형식명</th><td>' + this.nvl(data.fomNm) + '</td></tr>';
html += '<tr><th>제작년월일</th><td>' + this.nvl(data.yblMd) + '</td>';
html += '<th>주행거리</th><td>' + this.nvl(data.trvlDstnc) + '</td></tr>';
html += '<tr><th>검사유효기간</th><td>' + this.nvl(data.insptValidPdBgnde) + ' ~ ' + this.nvl(data.insptValidPdEndde) + '</td>';
html += '<th>점검유효기간</th><td>' + this.nvl(data.chckValidPdBgnde) + ' ~ ' + this.nvl(data.chckValidPdEndde) + '</td></tr>';
html += '<tr><th>대표소유자성명</th><td>' + this.nvl(data.mberNm) + '</td>';
html += '<th>대표소유자전화번호</th><td>' + this.nvl(data.telno) + '</td></tr>';
html += '<tr><th>대표소유자회원구분코드</th><td>' + this.nvl(data.mberSeCode) + '</td>';
html += '<th>대표소유자회원번호</th><td>' + this.nvl(data.mberSeNo) + '</td></tr>';
html += '<tr><th>사용본거지주소</th><td colspan="3">' + this.nvl(data.adres1) + ' ' + this.nvl(data.adresNm1) + '</td></tr>';
html += '<tr><th>소유자주소</th><td colspan="3">' + this.nvl(data.adres) + ' ' + this.nvl(data.adresNm) + '</td></tr>';
html += '<tr><th>말소등록구분명</th><td>' + this.nvl(data.ersrRegistSeNm) + '</td>';
html += '<th>말소등록일</th><td>' + this.nvl(data.ersrRegistDe) + '</td></tr>';
html += '<tr><th>저당수</th><td>' + this.nvl(data.mrtgcnt) + '</td>';
html += '<th>압류건수</th><td>' + this.nvl(data.vhclecnt) + '</td></tr>';
html += '<tr><th>구조변경수</th><td>' + this.nvl(data.stmdcnt) + '</td>';
html += '<th>번호판영치여부</th><td>' + this.nvl(data.nmplCsdyAt) + '</td></tr>';
html += '</table>';
// 등록원부 변경 이력 (record 리스트)
if (data.record && data.record.length > 0) {
html += '<div class="result-section-title" style="margin-top: 30px;">등록원부 변경 이력 (' + data.record.length + '건)</div>';
html += '<table class="result-detail-table">';
html += '<colgroup><col style="width:5%"><col style="width:8%"><col style="width:8%"><col style="width:8%"><col style="width:8%"><col style="width:10%"><col style="width:10%"><col style="width:auto"></colgroup>';
html += '<thead>';
html += '<tr style="background-color: #e8e8e8;">';
html += '<th style="text-align: center;">번호</th>';
html += '<th style="text-align: center;">주번호</th>';
html += '<th style="text-align: center;">부번호</th>';
html += '<th style="text-align: center;">변경일자</th>';
html += '<th style="text-align: center;">구분명</th>';
html += '<th style="text-align: center;">원부그룹번호</th>';
html += '<th style="text-align: center;">원부개별번호</th>';
html += '<th style="text-align: center;">상세내역</th>';
html += '</tr>';
html += '</thead>';
html += '<tbody>';
for (var i = 0; i < data.record.length; i++) {
var rec = data.record[i];
html += '<tr>';
html += '<td style="text-align: center;">' + (i + 1) + '</td>';
html += '<td style="text-align: center;">' + this.nvl(rec.mainno) + '</td>';
html += '<td style="text-align: center;">' + this.nvl(rec.subno) + '</td>';
html += '<td style="text-align: center;">' + this.nvl(rec.changeDe) + '</td>';
html += '<td style="text-align: center;">' + this.nvl(rec.gubunNm) + '</td>';
html += '<td style="text-align: center;">' + this.nvl(rec.ledgerGroupNo) + '</td>';
html += '<td style="text-align: center;">' + this.nvl(rec.ledgerIndvdlzNo) + '</td>';
html += '<td>' + this.nvl(rec.dtls) + '</td>';
html += '</tr>';
}
html += '</tbody>';
html += '</table>';
}
$("#resultContent").html(html);
},
/**
* null 값 처리
*/
nvl: function(value, defaultValue) {
if (value === null || value === undefined || value === '') {
return defaultValue || '-';
}
return value;
},
/**
* 이벤트 핸들러 설정
*/
eventBindEvents: function() {
var self = this;
// 조회 구분 변경 이벤트
$("#inqryType").on('change', function() {
self.onInqryTypeChange();
});
// 조회 버튼 클릭 이벤트
$("#search_btn").on('click', function() {
self.executeSearch();
});
// 초기화 버튼 클릭 이벤트
$("#reset_btn").on('click', function() {
$("#vhrno").val("");
$("#levyStdde").val("${dateUtil:getCurrentDateTime('yyyy-MM-dd')}");
$("#inqireSeCode").val("1");
$("#vin").val("");
$("#cpttrNm").val("");
$("#cpttrIhidnum").val("");
$("#resultContent").html('<div class="result-empty">조회 버튼을 클릭하여 차량 정보를 조회하세요.</div>');
$("#btnResultClose").hide();
});
// 결과 닫기 버튼 클릭 이벤트
$("#btnResultClose").on('click', function() {
$("#resultContent").html('<div class="result-empty">조회 버튼을 클릭하여 차량 정보를 조회하세요.</div>');
$(this).hide();
});
// 엔터키 검색
$("#vhrno, #vin, #cpttrNm, #cpttrIhidnum").on('keypress', function(e) {
if (e.which === 13) {
e.preventDefault();
$("#search_btn").trigger('click');
}
});
},
/**
* 모듈 초기화
*/
init: function() {
console.log("차량 정보 조회 모듈 초기화");
// 초기 필드 표시/숨김 설정
this.onInqryTypeChange();
// 이벤트 핸들러 설정
this.eventBindEvents();
}
};
// DOM 준비 완료 시 초기화
$(document).ready(function() {
VehicleInquiry.init();
});
// 전역 네임스페이스에 모듈 노출
window.VehicleInquiry = VehicleInquiry;
})(window, jQuery);
</script>
Loading…
Cancel
Save