init : 개발시 연계테스트를 위한 테스트 api

1. 차적 인서트(랜덤값), 조회
master
Kurt92 2 weeks ago
commit 10423829ab

3
.gitattributes vendored

@ -0,0 +1,3 @@
/gradlew text eol=lf
*.bat text eol=crlf
*.jar binary

37
.gitignore vendored

@ -0,0 +1,37 @@
HELP.md
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/

@ -0,0 +1,56 @@
plugins {
id 'java'
id 'org.springframework.boot' version '3.5.0'
id 'io.spring.dependency-management' version '1.1.7'
}
group = 'org.api'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
// === Spring Boot Starters ===
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-webflux'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
// === Lombok ===
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
// === DevTools ===
developmentOnly 'org.springframework.boot:spring-boot-devtools'
// === DB Driver ===
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
// === QueryDSL ( ) ===
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
annotationProcessor 'com.querydsl:querydsl-apt:5.0.0:jakarta'
annotationProcessor 'jakarta.annotation:jakarta.annotation-api'
annotationProcessor 'jakarta.persistence:jakarta.persistence-api'
// === Tests ===
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
tasks.named('test') {
useJUnitPlatform()
}

Binary file not shown.

@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

248
gradlew vendored

@ -0,0 +1,248 @@
#!/bin/sh
#
# Copyright © 2015 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

93
gradlew.bat vendored

@ -0,0 +1,93 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:execute
@rem Setup the command line
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

@ -0,0 +1 @@
rootProject.name = 'api-test'

@ -0,0 +1,13 @@
package org.api.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ApiTestApplication {
public static void main(String[] args) {
SpringApplication.run(ApiTestApplication.class, args);
}
}

@ -0,0 +1,66 @@
package org.api.test.biz.carInfo.controller;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.api.test.biz.carInfo.dto.CarInfoDto;
import org.api.test.biz.carInfo.service.CarInfoService;
import org.api.test.domain.CarInfo;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequiredArgsConstructor
@Slf4j
public class CarInfoController {
private final CarInfoService carInfoService;
@PostMapping("/api/test/carInfo/basic")
public ResponseEntity<CarInfoDto.Response> getCarInfo(
@RequestHeader(name = "api_key", required = false) String apiKey,
@RequestHeader(name = "cert_server_id", required = false) String certServerId,
@RequestHeader(name = "tx_id", required = false) String txId,
@RequestHeader(name = "gpki_yn", required = false) String gpkiYn,
@RequestHeader(name = "cvmis_apikey", required = false) String cvmisApikey,
@RequestBody CarInfoDto.Request.BodyWrapper req
) {
log.info("[CAR-INFO] tx_id={}, api_key={}, cert_server_id={}, gpki_yn={}, cvmis_apikey={}",
txId, apiKey, certServerId, gpkiYn, cvmisApikey);
List<CarInfo> resultRecords = carInfoService.findCarInfo(req);
// data 배열 안의 각 Body 순회
// 조회 결과에 따라 코드 세팅 (간단 버전)
String code = resultRecords.isEmpty() ? "0001" : "0000";
String msg = resultRecords.isEmpty() ? "조회된 차량 정보가 없습니다." : "정상";
CarInfoDto.Response response = CarInfoDto.Response.builder()
.LINK_RSLT_CD(code)
.LINK_RSLT_DTL(msg)
.record(resultRecords)
.build();
return ResponseEntity.ok(response);
}
@PostMapping("/api/test/carInfo/insert")
public ResponseEntity<?> carInfoRandomInsert(@RequestBody List<String> vhrnoList) {
carInfoService.carInfoRandomInsert(vhrnoList);
return ResponseEntity.ok("success");
};
}

@ -0,0 +1,194 @@
package org.api.test.biz.carInfo.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonUnwrapped;
import lombok.*;
import org.api.test.domain.CarInfo;
import java.util.List;
public class CarInfoDto {
public static class Request {
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class BodyWrapper {
@JsonProperty("data")
private List<Body> data;
}
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class Body {
// ===== 헤더 영역 =====
@JsonProperty("INFO_SYS_ID")
private String infoSysId;
@JsonProperty("INFO_SYS_IP")
private String infoSysIp;
@JsonProperty("SIGUNGU_CODE")
private String sigunguCode;
@JsonProperty("CNTC_INFO_CODE")
private String cntcInfoCode;
@JsonProperty("CHARGER_ID")
private String chargerId;
@JsonProperty("CHARGER_IP")
private String chargerIp;
@JsonProperty("CHARGER_NM")
private String chargerNm;
// record 배열
@JsonProperty("record")
private List<IfBody> record;
}
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class IfBody {
@JsonProperty("VHRNO")
private String vhrno; // 자동차등록번호
@JsonProperty("VIN")
private String vin; // 차대번호
@JsonProperty("LEVY_STDDE")
private String levyStdde; // 부과기준일
@JsonProperty("INQIRE_SE_CODE")
private String inqireSeCode; // 조회구분코드
}
}
@Getter
@Setter
@Builder
public static class Response {
private String LINK_RSLT_CD;
private String LINK_RSLT_DTL;
private List<CarInfo> record;
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public static class CarInfoIfBody {
private String VHRNO;
private String ATMB_NM;
private String RPRS_OWNR_NM;
private String RPRSV_OWNR_IDECNO;
private String ERSR_REG_YMD;
private String PRCS_IMPRTY_RSN_CD;
private String PRCS_IMPRTY_RSN_DTLS;
private String YRIDNW;
private String VIN;
private String CARMDL_ASORT_NM;
private String FRST_REG_YMD;
private String COLOR_NM;
private String STRCT_CHG_CNT;
private String NOPLT_CSDY_YN;
private String NOPLT_CSDY_AVTSMT_YMD;
private String INSP_VLD_PD_BGNG_YMD;
private String INSP_VLD_PD_END_YMD;
private String SPMNNO;
private String DRVNG_DSTNC;
private String FOM_NM;
private String DSPLVL;
private String CARMDL_CLSF_NM;
private String FBCTN_YMD;
private String USGSRHLD_ADDR_NM;
private String MTRS_FOM_NM;
private String RDCPCT_CNT;
private String FRST_REG_APLY_RCPT_NO;
private String OGNZ_NM;
private String ERSR_REG_SE_NM;
private String BFR_VHRNO;
private String USE_FUEL_CD;
private String RPRS_OWNR_MBR_SE_CD;
private String RPRS_OWNR_TELNO;
private String OWNR_STDG_CD;
private String OWNR_WHOL_ADDR;
private String VHCL_TOTL_WT;
private String MXMM_LDG;
private String CBD_LT;
private String CBD_BT;
private String CBD_HG;
private String CARMDL_ASORT_CD;
private String CARMDL_TYPE_CD;
private String FUEL_CNSMPRT;
private String ERSR_REG_SE_CD;
private String REG_DTL_CD;
private String USGSRHLD_STDG_CD;
private String USGSRHLD_DONG_CD;
private String USGSRHLD_MTN_YN;
private String USGSRHLD_LNBR;
private String USGSRHLD_HO;
private String USGSRHLD_ROAD_NM_CD;
private String USGSRHLD_UDGD_BLDG_SE_CD;
private String USGSRHLD_BMNO;
private String USGSRHLD_BSNO;
private String OWNR_DONG_CD;
private String OWNR_MTN_YN;
private String OWNR_LNBR;
private String OWNR_HO;
private String OWNR_ADDR_NM;
private String OWNR_ROAD_NM_CD;
private String OWNR_UDGD_BLDG_SE_CD;
private String OWNR_BMNO;
private String OWNR_BSNO;
private String REAR_VHRNO;
private String USG_SE_CD;
private String VEAG_END_YMD;
private String CHG_YMD;
private String CARMDL_SE_CD;
private String CARMDL_TYPE_NM;
private String ACQS_YMD;
private String ACQS_END_YMD;
private String TRANSR_REG_YMD;
private String SPCF_REG_STTS_CD;
private String SRC_SE_CD;
private String NOPLT_SPCFCT_CD;
private String ACQS_AMT;
private String USGSRHLD_GRC_CD;
private String VLNT_ERSR_PRVNTC_AVTSMT_YMD;
private String FRST_MXMM_LDG;
private String REG_YMD;
private String ELCTY_CMPND_FUEL_CNSMPRT;
private String USGSRHLD_WHOL_ADDR;
private String MRTG_CNT;
private String SZR_CNT;
}
}
}

@ -0,0 +1,44 @@
package org.api.test.biz.carInfo.repository;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import org.api.test.biz.carInfo.dto.CarInfoDto;
import org.springframework.stereotype.Repository;
import java.util.List;
import static org.api.test.domain.QCarInfo.carInfo;
@Repository
@RequiredArgsConstructor
public class CarInfoQueryDslRepository {
private final JPAQueryFactory queryFactory;
// public List<CarInfoDto.Response.CarInfoIfBody> findCarsInfo(CarInfoDto.Request.Body req) {
//
//
// List<CarInfoDto.Response.CarInfoIfBody> result = queryFactory
// .select(
// Projections.fields(
// CarInfoDto.Response.CarInfoIfBody.class,
// carInfo.vhrno.as("VHRNO")
// )
//
// )
// .from(carInfo)
// .where()
// .fetch();
//
//
//
//
// return null;
// }
}

@ -0,0 +1,201 @@
package org.api.test.biz.carInfo.service;
import org.api.test.domain.CarInfo;
import org.springframework.stereotype.Service;
import java.security.SecureRandom;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Random;
@Service
public class CarInfoMock {
private static final Random RANDOM = new SecureRandom();
private static final DateTimeFormatter YMD = DateTimeFormatter.ofPattern("yyyyMMdd");
public CarInfo createRandom(String vhrno) {
String FRST_REGIST_DE = randomYmdBetween(2000, 2023); // CHAR(8)
String YBL_MD = randomYmdBetween(1995, 2023); // CHAR(8)
return CarInfo.builder()
// 1) 차량번호 / 이전·이후 차량번호 (VARCHAR(20))
.VHRNO(vhrno)
.AFTR_VHRNO(vhrno) // 신차량번호 = 현재 번호
.FRNT_VHRNO(randomNullablePlate())
// 2) 연식 / 등록정보
.PRYE(FRST_REGIST_DE.substring(0, 4)) // 연식 = 최초등록 연도
.FRST_REGIST_DE(FRST_REGIST_DE) // 최초등록일
.REGIST_DE(randomYmdBetween(2000, 2025)) // 등록(변경)일
.ERSR_REGIST_SE_CODE(randomNullableCode())
.ERSR_REGIST_SE_NM(randomNullableFrom("일반말소", "수출말소", "폐차말소"))
.ERSR_REGIST_DE(randomNullableYmd()) // 말소일
.REGIST_DETAIL_CODE(randomFrom("10", "20", "30"))
// 3) 제원 / 차종
// DSPLVL VARCHAR(6)
.DSPLVL(randomNumeric(4))
.VHCTY_ASORT_CODE(randomFrom("01", "02", "03"))
.VHCTY_ASORT_NM(randomFrom("승용", "승합", "화물"))
.VHCTY_TY_CODE(randomFrom("A", "B", "C"))
.VHCTY_TY_NM(randomFrom("소형", "중형", "대형"))
.VHCTY_SE_CODE(randomFrom("1", "2"))
.VHCTY_SE_NM(randomFrom("개인", "영업용"))
.MXMM_LDG(randomNumeric(4)) // 최대적재량 (4자리, 10 이하)
.FRST_MXMM_LDG(randomNullableNumeric(4)) // 최초최대적재량
.YBL_MD(YBL_MD) // 제작년월일
.FOM_NM(randomFrom("세단", "SUV", "해치백"))
// 4) 차량 기본 정보
.CNM(randomFrom("쏘나타", "K5", "그랜저", "아반떼", "스파크", "레이"))
.VIN(randomNumeric(10) + "VIN") // 최대 13자 → 30 이내
.COLOR_NM(randomFrom("흰색", "검정", "은색", "파란색", "빨간색", "회색"))
.USE_FUEL_CODE(randomFrom("01", "02", "03")) // 연료코드
.PRPOS_SE_CODE(randomFrom("01", "02", "03")) // 용도구분
.MTRS_FOM_NM(randomFrom("가솔린", "디젤", "전기", "하이브리드"))
.VHCTLE_TOT_WT(randomNumeric(4)) // 4자리(<=6)
// 5) 취득 / 검사 / 예고통지
.ACQS_DE(randomYmdBetween(2000, 2020))
.ACQS_END_DE(randomNullableYmd())
.ACQS_AMOUNT(randomNumeric(18)) // ★ DDL 길이 맞춤
.INSPT_VALID_PD_BGNDE(randomYmdBetween(2023, 2025))
.INSPT_VALID_PD_ENDDE(randomYmdBetween(2025, 2029))
.VLNT_ERSR_PRVNTC_NTICE_DE(randomNullableYmd()) // 예고통지일
.CAAG_ENDDE(randomNullableYmd()) // 차량만료일자
.CHANGE_DE(randomNullableYmd()) // 번호변경시기
// 6) 사용본거지
.USE_STRNGHLD_LEGALDONG_CODE(randomNumeric(10))
.USE_STRNGHLD_ADSTRD_CODE(randomNumeric(10))
.USE_STRNGHLD_MNTN(randomYn()) // 산 여부
.USE_STRNGHLD_LNBR(randomNumeric(4))
.USE_STRNGHLD_HO(randomNumeric(4))
.USE_STRNGHLD_ADRES_NM(randomAddr()) // 샘플 주소 150자 이내
.USE_STRNGHLD_ROAD_NM_CODE(randomNumeric(12))
.USGSRHLD_UNDGRND_BULD_SE_CODE(randomFrom("0", "1"))
.USE_STRNGHLD_BULD_MAIN_NO(randomNumeric(5))
.USE_STRNGHLD_BULD_SUB_NO(randomNumeric(5))
.USGSRHLD_ADRES_FULL(randomAddr())
.USE_STRNGHLD_GRC_CODE(randomFrom("1", "2", "3"))
// 7) 소유자 정보
.MBER_SE_CODE(randomFrom("01", "02")) // VARCHAR(2)
.MBER_NM(randomFrom("양의지", "안우진", "김하성", "박병호")) // VARCHAR(50)
.MBER_SE_NO(randomNumeric(13)) // VARCHAR(13)
.TELNO(randomPhone()) // VARCHAR(20)
.OWNER_LEGALDONG_CODE(randomNumeric(10))
.OWNER_ADSTRD_CODE(randomNumeric(10))
.OWNER_MNTN(randomYn())
.OWNER_LNBR(randomNumeric(4))
.OWNER_HO(randomNumeric(4))
.OWNER_ADRES_NM(randomAddr()) // 150 이내
.OWNER_ROAD_NM_CODE(randomNumeric(12))
.OWNER_UNDGRND_BULD_SE_CODE(randomFrom("0", "1"))
.OWNER_BULD_MAIN_NO(randomNumeric(5))
.OWNER_BULD_SUB_NO(randomNumeric(5))
.OWNER_ADRES_FULL(randomAddr()) // 500 이내
// 8) 번호판 / 상태
.NMPL_CSDY_AT(randomYn()) // CHAR(1)
.NMPL_CSDY_REMNR_DE(randomNullableYmd()) // CHAR(8)
.ORIGIN_SE_CODE(randomFrom("01", "02")) // VARCHAR(6) 안쪽
.NMPL_STNDRD_CODE(randomFrom("01", "02", "03")) // VARCHAR(10)
.SPCF_REGIST_STTUS_CODE(randomFrom("0", "1", "2"))
.MRTG_CO(randomNumeric(1))
.SEIZR_CO(randomNumeric(1))
.STMD_CO(randomNumeric(1))
.PROCESS_IMPRTY_RESN_CODE(randomNullableCode()) // VARCHAR(10)
.PROCESS_IMPRTY_RESN_DTLS( // VARCHAR(180)
randomNullableFrom("말소 차량", "압류 차량", "번호판 영치 대상")
)
// 9) 각종 수치/제원
.TKCAR_PSCAP_CO(randomNumeric(2)) // 2자리 (정원 2~99) → 3 이내
.SPMNNO(randomNumeric(17))
.TRVL_DSTNC(randomNumeric(6)) // 6자리 주행거리, 10 이내
.FRST_REGIST_RQRCNO(randomNumeric(20))
.CBD_LT(randomNumeric(3)) // 차체길이
.CBD_BT(randomNumeric(3)) // 차체너비
.CBD_HG(randomNumeric(3)) // 차체높이
.FUEL_CNSMP_RT(randomNumeric(2)) // 연비
.ELCTY_CMPND_FUEL_CNSMP_RT(randomNullableNumeric(2))
// 10) 기관명 등
.REGIST_INSTT_NM(randomFrom("성동구청", "화성시청", "강서구청"))
.build();
}
// ===================== 헬퍼 메서드 =====================
private static String randomFrom(String... values) {
return values[RANDOM.nextInt(values.length)];
}
private static String randomNullableFrom(String... values) {
if (RANDOM.nextInt(4) == 0) return null; // 25% 확률로 null
return randomFrom(values);
}
private static String randomNumeric(int length) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++) sb.append(RANDOM.nextInt(10));
return sb.toString();
}
private static String randomNullableNumeric(int length) {
if (RANDOM.nextBoolean()) return null;
return randomNumeric(length);
}
private static String randomYmdBetween(int startYear, int endYear) {
int year = startYear + RANDOM.nextInt(endYear - startYear + 1);
int month = 1 + RANDOM.nextInt(12);
int day = 1 + RANDOM.nextInt(28);
return LocalDate.of(year, month, day).format(YMD);
}
private static String randomNullableYmd() {
if (RANDOM.nextBoolean()) return null;
return randomYmdBetween(2000, 2025);
}
private static String randomYn() {
return RANDOM.nextBoolean() ? "Y" : "N";
}
private static String randomPhone() {
// TELNO VARCHAR(20) 이라 "010" + 8자리면 11자리라 여유 충분
return "010" + randomNumeric(8);
}
private static String randomNullablePlate() {
if (RANDOM.nextInt(10) < 3) return randomPlate();
return null;
}
private static String randomPlate() {
// "12가3456" 형식 (최대 7~8자) → AFTR/FRNT_VHRNO VARCHAR(20) 이내
String[] chosung = {"가", "나", "다", "라", "마", "바", "사"};
return randomNumeric(2) + chosung[RANDOM.nextInt(chosung.length)] + randomNumeric(4);
}
private static String randomNullableCode() {
if (RANDOM.nextInt(5) == 0) return null; // 20% 확률 null
return randomFrom("01", "02", "03", "99");
}
private static String randomAddr() {
// USE_STRNGHLD_ADRES_NM(150), *_FULL(500) 기준으로 충분히 짧게
return randomFrom(
"서울시 강서구 양천로 400",
"서울시 송파구 잠실동 234-56",
"서울특별시 송파구 올림픽로 300",
"경기도 성남시 분당구 정자동 111-22"
);
}
}

@ -0,0 +1,52 @@
package org.api.test.biz.carInfo.service;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.api.test.biz.carInfo.dto.CarInfoDto;
import org.api.test.biz.carInfo.repository.CarInfoQueryDslRepository;
import org.api.test.domain.CarInfo;
import org.api.test.domain.CarInfoRepository;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
@RequiredArgsConstructor
public class CarInfoService {
private final CarInfoRepository carInfoRepository;
private final CarInfoQueryDslRepository carInfoQueryDslRepository;
private final CarInfoMock carInfoMock;
public List<CarInfo> findCarInfo(CarInfoDto.Request.BodyWrapper req) {
// 차량번호 추출
List<String> vhrnos = new ArrayList<>();
for (CarInfoDto.Request.Body body : req.getData()) {
for (CarInfoDto.Request.IfBody rec : body.getRecord()) {
if (rec.getVhrno() != null && !rec.getVhrno().isBlank()) {
vhrnos.add(rec.getVhrno());
}
}
}
// 중복 제거
vhrnos = vhrnos.stream().distinct().toList();
return carInfoRepository.findByVHRNOIn(vhrnos);
}
// 차량 번호를 받아 랜덤한 내용을 밀어넣어 인서트 한다. (테스트용)
@Transactional
public void carInfoRandomInsert(List<String> vhrnoList) {
vhrnoList.forEach(item -> {
CarInfo entity = carInfoMock.createRandom(item);
carInfoRepository.save(entity);
});
}
}

@ -0,0 +1,7 @@
package org.api.test.biz.coverInfo.controller;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class CoverInfoController {
}

@ -0,0 +1,7 @@
package org.api.test.biz.coverInfo.repository;
import org.springframework.stereotype.Repository;
@Repository
public class CoverInfoRepository {
}

@ -0,0 +1,7 @@
package org.api.test.biz.coverInfo.service;
import org.springframework.stereotype.Service;
@Service
public class CoverInfoService {
}

@ -0,0 +1,76 @@
package org.api.test.biz.taxelse.controller;
import lombok.RequiredArgsConstructor;
import org.api.test.biz.taxelse.dto.TaxelseDto;
import org.api.test.biz.taxelse.service.TaxelseService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequiredArgsConstructor
public class TaxelseController {
private final TaxelseService taxelseService;
// 사전부과
@PostMapping("/api/test/lavy")
public ResponseEntity<TaxelseDto.Response> preNoticeInsert() {
TaxelseDto.Response.ResultSunapBody resultBody = TaxelseDto.Response.ResultSunapBody.builder()
.build();
TaxelseDto.Response response = TaxelseDto.Response.builder()
.state("0000")
.code("성공")
.result("정상 처리되었습니다.")
.body(resultBody)
.build();
return ResponseEntity.ok(response);
}
// 매치정보(가상계좌)
@PostMapping("/api/test/lavy/match")
public ResponseEntity<TaxelseDto.Response> matchInfoReturn() {
TaxelseDto.Response.ResultSunapBody resultBody = TaxelseDto.Response.ResultSunapBody.builder()
// .pyrNm()
.build();
TaxelseDto.Response response = TaxelseDto.Response.builder()
.state("0000")
.code("성공")
.result("정상 처리되었습니다.")
.body(resultBody)
.build();
return ResponseEntity.ok(response);
}
// 수납정보
@PostMapping("api/test/sunap")
public ResponseEntity<TaxelseDto.Response> taxSunapInfoReturn() {
TaxelseDto.Response.ResultSunapBody resultBody = TaxelseDto.Response.ResultSunapBody.builder()
// .pyrNm()
.build();
TaxelseDto.Response response = TaxelseDto.Response.builder()
.state("0000")
.code("성공")
.result("정상 처리되었습니다.")
.body(resultBody)
.build();
return ResponseEntity.ok(response);
}
}

@ -0,0 +1,175 @@
package org.api.test.biz.taxelse.dto;
import lombok.*;
public class TaxelseDto {
public static class Request {
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class RecvReq {
private Header header;
private Body body;
}
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class Header {
private String ifDate;
private String ifMsgKEy;
private String ifId;
private String source;
private String target;
private String ifType;
private String ifFormat;
private String retName;
private String retCode;
}
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class Body {
private String dmndSeCd;
private String sgbCd;
private String dptCd;
private String spacBizCd;
private String fyr;
private String actSeCd;
private String rprsTxmCd;
private String lvyNo;
private String itmSn;
}
}
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class Response<T> {
private String state;
private String code;
private String result;
private T body;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class ResultMatchBody {
private String aaa;
}
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class ResultSunapBody {
private String sgbCd; // 지방자치단체코드
private String lvyKey; // 부과키
private String dptNm; // 부서명
private String dptCd; // 부서코드
private String spacBizCd; // 특별회계사업코드
private String fyr; // 회계연도
private String actSeCd; // 회계구분코드
private String rprsTxmCd; // 대표세입과목코드
private String rprsTxmNm; // 대표세입과목명
private String lvyNo; // 부과번호
private String itmSn; // 분납일련번호
private String rcvmtSn; // 수납일련번호
private String rcvmtYmd; // 수납일자
private String rcvmtPctAmt; // 수납본세금액
private String rcvmtAdtnAmt; // 수납가산금액
private String itmIntrAmt; // 분납이자금액
private String rcvmtBank; // 수납은행
private String rcvmtTyCd; // 수납유형코드
private String rcvmtTyNm; // 수납유형명
private String actYmd; // 회계일자
private String pmkYmd; // 소인일자
private String frstPidYmd; // 최초납기일자
private String lvyYmd; // 부과일자
private String glNm; // 물건지명
private String vtlacBankNm1;
private String vrActno1;
private String vtlacBankNm2;
private String vrActno2;
private String vtlacBankNm3;
private String vrActno3;
private String vtlacBankNm4;
private String vrActno4;
private String vtlacBankNm5;
private String vrActno5;
private String vtlacBankNm6;
private String vrActno6;
private String vtlacBankNm7;
private String vrActno7;
private String vtlacBankNm8;
private String vrActno8;
private String vtlacBankNm9;
private String vrActno9;
private String vtlacBankNm10;
private String vrActno10;
private String vtlacBankNm11;
private String vrActno11;
private String vtlacBankNm12;
private String vrActno12;
private String vtlacBankNm13;
private String vrActno13;
private String vtlacBankNm14;
private String vrActno14;
private String vtlacBankNm15;
private String vrActno15;
private String vtlacBankNm16;
private String vrActno16;
private String vtlacBankNm17;
private String vrActno17;
private String vtlacBankNm18;
private String vrActno18;
private String vtlacBankNm19;
private String vrActno19;
private String vtlacBankNm20;
private String vrActno20;
private String epayNo; // 전자납부번호
private String pyrNo; // 납부자번호
private String pyrNm; // 납부자명
private String rcvmtSeCd; // 수납구분코드
private String rcvmtSttSeCd; // 수납구분
private String taxnNo; // 과세번호
private String glMngNo; // 물건지관리번호
private String glAddr; // 물건지주소
private String pyrAddr; // 납부자주소
private String linkRstCd; // 연계 결과 코드
private String linkRstMsg; // 연계 결과 메시지
}
}
}

@ -0,0 +1,4 @@
package org.api.test.biz.taxelse.repository;
public class TaxelseRepository {
}

@ -0,0 +1,24 @@
package org.api.test.biz.taxelse.service;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class TaxelseService {
// 수납 인서트
public void insertSunap() {
// cp_match에서 mmcode 조회
// cp_match에서
}
}

@ -0,0 +1,22 @@
package org.api.test.biz.view;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class ViewController {
@GetMapping("/")
public String home() {
return "home";
}
@GetMapping("/logs")
public String logs() {
return "logs";
}
}

@ -0,0 +1,43 @@
package org.api.test.conf.jpa;
import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.PersistenceContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.orm.jpa.JpaTransactionManager;
@Configuration
public class JPAConfig {
@PersistenceContext
private EntityManager em;
/** QueryDSL용 JPAQueryFactory */
@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(em);
}
/**
*
*/
@Bean(name = "transactionManager")
@Primary
public JpaTransactionManager transactionManager(EntityManagerFactory emf) {
return new JpaTransactionManager(emf);
}
// 필요하면 나중에 다시 켜서 쓰면 됨
// @Bean
// public JpaVendorAdapter jpaVendorAdapter() {
// HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
// adapter.setShowSql(false);
// adapter.setGenerateDdl(false);
// adapter.setDatabasePlatform("org.hibernate.dialect.MySQLDialect");
// return adapter;
// }
}

@ -0,0 +1,363 @@
package org.api.test.domain;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.Comment;
@Entity
@Table(name = "CAR_INFO") // 실제 테이블명에 맞게 조정
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class CarInfo {
// ===== 기본 키 =====
@Id
@Column(name = "VHRNO")
@Comment("차량번호")
private String VHRNO;
// ===== 상단 (연식 / 등록정보 / 사용본거지) =====
@Column(name = "PRYE")
@Comment("연식")
private String PRYE;
@Column(name = "REGIST_DE")
@Comment("등록일(변경일)")
private String REGIST_DE;
@Column(name = "ERSR_REGIST_SE_CODE")
@Comment("말소등록구분코드")
private String ERSR_REGIST_SE_CODE;
@Column(name = "ERSR_REGIST_SE_NM")
@Comment("말소등록구분명")
private String ERSR_REGIST_SE_NM;
@Column(name = "ERSR_REGIST_DE")
@Comment("말소등록일")
private String ERSR_REGIST_DE;
@Column(name = "REGIST_DETAIL_CODE")
@Comment("등록상세코드")
private String REGIST_DETAIL_CODE;
@Column(name = "DSPLVL")
@Comment("배기량")
private String DSPLVL;
@Column(name = "USE_STRNGHLD_LEGALDONG_CODE")
@Comment("사용본거지법정동코드")
private String USE_STRNGHLD_LEGALDONG_CODE;
@Column(name = "USE_STRNGHLD_ADSTRD_CODE")
@Comment("사용본거지행정동코드")
private String USE_STRNGHLD_ADSTRD_CODE;
@Column(name = "USE_STRNGHLD_MNTN")
@Comment("사용본거지산")
private String USE_STRNGHLD_MNTN;
@Column(name = "USE_STRNGHLD_LNBR")
@Comment("사용본거지번지")
private String USE_STRNGHLD_LNBR;
@Column(name = "USE_STRNGHLD_HO")
@Comment("사용본거지호")
private String USE_STRNGHLD_HO;
@Column(name = "USE_STRNGHLD_ADRES_NM")
@Comment("사용본거지상세주소")
private String USE_STRNGHLD_ADRES_NM;
@Column(name = "USE_STRNGHLD_ROAD_NM_CODE")
@Comment("사용본거지도로명코드")
private String USE_STRNGHLD_ROAD_NM_CODE;
@Column(name = "USGSRHLD_UNDGRND_BULD_SE_CODE")
@Comment("사용본거지지하건물구분코드")
private String USGSRHLD_UNDGRND_BULD_SE_CODE;
@Column(name = "USE_STRNGHLD_BULD_MAIN_NO")
@Comment("사용본거지건물주요번호")
private String USE_STRNGHLD_BULD_MAIN_NO;
@Column(name = "USE_STRNGHLD_BULD_SUB_NO")
@Comment("사용본거지건물부번호")
private String USE_STRNGHLD_BULD_SUB_NO;
@Column(name = "USGSRHLD_ADRES_FULL")
@Comment("사용본거지전체주소")
private String USGSRHLD_ADRES_FULL;
// ===== 대표소유자/소유자 정보 =====
@Column(name = "MBER_SE_CODE")
@Comment("대표소유자회원구분코드")
private String MBER_SE_CODE;
@Column(name = "MBER_NM")
@Comment("대표소유자성명")
private String MBER_NM;
@Column(name = "MBER_SE_NO")
@Comment("대표소유자회원번호")
private String MBER_SE_NO;
@Column(name = "TELNO")
@Comment("대표소유자전화번호")
private String TELNO;
@Column(name = "OWNER_LEGALDONG_CODE")
@Comment("소유자법정동코드")
private String OWNER_LEGALDONG_CODE;
@Column(name = "OWNER_ADSTRD_CODE")
@Comment("소유자행정동코드")
private String OWNER_ADSTRD_CODE;
@Column(name = "OWNER_MNTN")
@Comment("소유자산")
private String OWNER_MNTN;
@Column(name = "OWNER_LNBR")
@Comment("소유자번지")
private String OWNER_LNBR;
@Column(name = "OWNER_HO")
@Comment("소유자호")
private String OWNER_HO;
@Column(name = "OWNER_ADRES_NM")
@Comment("소유자상세주소")
private String OWNER_ADRES_NM;
@Column(name = "OWNER_ROAD_NM_CODE")
@Comment("소유자도로명코드")
private String OWNER_ROAD_NM_CODE;
@Column(name = "OWNER_UNDGRND_BULD_SE_CODE")
@Comment("소유자지하건물구분코드")
private String OWNER_UNDGRND_BULD_SE_CODE;
@Column(name = "OWNER_BULD_MAIN_NO")
@Comment("소유자건물주요번호")
private String OWNER_BULD_MAIN_NO;
@Column(name = "OWNER_BULD_SUB_NO")
@Comment("소유자건물부번호")
private String OWNER_BULD_SUB_NO;
@Column(name = "OWNER_ADRES_FULL")
@Comment("소유자전체주소")
private String OWNER_ADRES_FULL;
// ===== 차량번호/차량 기본 =====
@Column(name = "AFTR_VHRNO")
@Comment("신차량번호")
private String AFTR_VHRNO;
@Column(name = "FRNT_VHRNO")
@Comment("이전차량번호")
private String FRNT_VHRNO;
@Column(name = "VIN")
@Comment("차대번호")
private String VIN;
@Column(name = "CNM")
@Comment("차명")
private String CNM;
@Column(name = "VHCTLE_TOT_WT")
@Comment("차량총중량")
private String VHCTLE_TOT_WT;
@Column(name = "CAAG_ENDDE")
@Comment("차량만료일자")
private String CAAG_ENDDE;
@Column(name = "CHANGE_DE")
@Comment("차변변경시기")
private String CHANGE_DE;
@Column(name = "USE_FUEL_CODE")
@Comment("사용연료코드")
private String USE_FUEL_CODE;
@Column(name = "PRPOS_SE_CODE")
@Comment("용도구분코드")
private String PRPOS_SE_CODE;
@Column(name = "MTRS_FOM_NM")
@Comment("원동기형식명")
private String MTRS_FOM_NM;
// ===== 차종/제원 관련 =====
@Column(name = "VHCTY_ASORT_CODE")
@Comment("차종종별코드")
private String VHCTY_ASORT_CODE;
@Column(name = "VHCTY_TY_CODE")
@Comment("차종유형코드")
private String VHCTY_TY_CODE;
@Column(name = "VHCTY_SE_CODE")
@Comment("차종분류코드")
private String VHCTY_SE_CODE;
@Column(name = "MXMM_LDG")
@Comment("최대적재량")
private String MXMM_LDG;
@Column(name = "VHCTY_ASORT_NM")
@Comment("차종종별명")
private String VHCTY_ASORT_NM;
@Column(name = "VHCTY_TY_NM")
@Comment("차종유형명")
private String VHCTY_TY_NM;
@Column(name = "VHCTY_SE_NM")
@Comment("차종분류명")
private String VHCTY_SE_NM;
@Column(name = "FRST_REGIST_DE")
@Comment("최초등록일")
private String FRST_REGIST_DE;
@Column(name = "FOM_NM")
@Comment("형식")
private String FOM_NM;
@Column(name = "ACQS_DE")
@Comment("취득일자")
private String ACQS_DE;
@Column(name = "ACQS_END_DE")
@Comment("취득종료일자")
private String ACQS_END_DE;
@Column(name = "YBL_MD")
@Comment("제작년월일")
private String YBL_MD;
@Column(name = "TRANSR_REGIST_DE")
@Comment("이전등록일(양수일)")
private String TRANSR_REGIST_DE;
// ===== 상태/금액/검사 등 =====
@Column(name = "SPCF_REGIST_STTUS_CODE")
@Comment("제원등록상태코드")
private String SPCF_REGIST_STTUS_CODE;
@Column(name = "COLOR_NM")
@Comment("색상명")
private String COLOR_NM;
@Column(name = "MRTG_CO")
@Comment("저당수")
private String MRTG_CO;
@Column(name = "SEIZR_CO")
@Comment("압류건수")
private String SEIZR_CO;
@Column(name = "STMD_CO")
@Comment("구조변경수")
private String STMD_CO;
@Column(name = "NMPL_CSDY_AT")
@Comment("번호판영치여부")
private String NMPL_CSDY_AT;
@Column(name = "NMPL_CSDY_REMNR_DE")
@Comment("번호판영치최고일")
private String NMPL_CSDY_REMNR_DE;
@Column(name = "ORIGIN_SE_CODE")
@Comment("출처구분코드")
private String ORIGIN_SE_CODE;
@Column(name = "NMPL_STNDRD_CODE")
@Comment("번호판규격코드")
private String NMPL_STNDRD_CODE;
@Column(name = "ACQS_AMOUNT")
@Comment("취득금액(최종/최초)")
private String ACQS_AMOUNT;
@Column(name = "INSPT_VALID_PD_BGNDE")
@Comment("검사유효기간시작일")
private String INSPT_VALID_PD_BGNDE;
@Column(name = "INSPT_VALID_PD_ENDDE")
@Comment("검사유효기간종료일")
private String INSPT_VALID_PD_ENDDE;
@Column(name = "USE_STRNGHLD_GRC_CODE")
@Comment("사용본거지관청코드")
private String USE_STRNGHLD_GRC_CODE;
@Column(name = "TKCAR_PSCAP_CO")
@Comment("승차정원수")
private String TKCAR_PSCAP_CO;
@Column(name = "SPMNNO")
@Comment("제원관리번호")
private String SPMNNO;
@Column(name = "TRVL_DSTNC")
@Comment("주행거리")
private String TRVL_DSTNC;
@Column(name = "FRST_REGIST_RQRCNO")
@Comment("최초등록접수번호")
private String FRST_REGIST_RQRCNO;
@Column(name = "VLNT_ERSR_PRVNTC_NTICE_DE")
@Comment("예고통지일")
private String VLNT_ERSR_PRVNTC_NTICE_DE;
@Column(name = "REGIST_INSTT_NM")
@Comment("등록기관명")
private String REGIST_INSTT_NM;
@Column(name = "PROCESS_IMPRTY_RESN_CODE")
@Comment("처리불가사유코드")
private String PROCESS_IMPRTY_RESN_CODE;
@Column(name = "PROCESS_IMPRTY_RESN_DTLS")
@Comment("처리불가사유명세")
private String PROCESS_IMPRTY_RESN_DTLS;
@Column(name = "CBD_LT")
@Comment("차체길이")
private String CBD_LT;
@Column(name = "CBD_BT")
@Comment("차체너비")
private String CBD_BT;
@Column(name = "CBD_HG")
@Comment("차체높이")
private String CBD_HG;
@Column(name = "FRST_MXMM_LDG")
@Comment("최초최대적재량")
private String FRST_MXMM_LDG;
@Column(name = "FUEL_CNSMP_RT")
@Comment("연료소비율")
private String FUEL_CNSMP_RT;
@Column(name = "ELCTY_CMPND_FUEL_CNSMP_RT")
@Comment("전기복합연료소비율")
private String ELCTY_CMPND_FUEL_CNSMP_RT;
}

@ -0,0 +1,10 @@
package org.api.test.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface CarInfoRepository extends JpaRepository<CarInfo, String> {
List<CarInfo> findByVHRNOIn(List<String> vhrnos);
}

@ -0,0 +1,31 @@
package org.api.test.domain;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Entity
@Table(name="COVER_INFO")
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class CoverInfo {
@Id
@Column(name = "COVER_INFO_ID")
private int coverInfoId;
}

@ -0,0 +1,245 @@
package org.api.test.domain;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.*;
@Entity
@Table(name = "SUNAP")
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Sunap {
@Id
@Column(name = "SUNAP_ID")
private int sunapId;
@Column(name = "SGB_CD")
private String sgbCd;
@Column(name = "LVY_KEY")
private String lvyKey;
@Column(name = "DPT_NM")
private String dptNm;
@Column(name = "DPT_CD")
private String dptCd;
@Column(name = "SPAC_BIZ_CD")
private String spacBizCd;
@Column(name = "FYR")
private String fyr;
@Column(name = "ACT_SE_CD")
private String actSeCd;
@Column(name = "RPRS_TXM_CD")
private String rprsTxmCd;
@Column(name = "RPRS_TXM_NM")
private String rprsTxmNm;
@Column(name = "LVY_NO")
private String lvyNo;
@Column(name = "ITM_SN")
private String itmSn;
@Column(name = "RCVMT_SN")
private String rcvmtSn;
@Column(name = "RCVMT_YMD")
private String rcvmtYmd;
@Column(name = "RCVMT_PCT_AMT")
private String rcvmtPctAmt;
@Column(name = "RCVMT_ADTN_AMT")
private String rcvmtAdtnAmt;
@Column(name = "ITM_INTR_AMT")
private String itmIntrAmt;
@Column(name = "RCVMT_BANK")
private String rcvmtBank;
@Column(name = "RCVMT_TY_CD")
private String rcvmtTyCd;
@Column(name = "RCVMT_TY_NM")
private String rcvmtTyNm;
@Column(name = "ACT_YMD")
private String actYmd;
@Column(name = "PMK_YMD")
private String pmkYmd;
@Column(name = "FRST_PID_YMD")
private String frstPidYmd;
@Column(name = "LVY_YMD")
private String lvyYmd;
@Column(name = "GL_NM")
private String glNm;
@Column(name = "VTLAC_BANK_NM1")
private String vtlacBankNm1;
@Column(name = "VR_ACTNO1")
private String vrActno1;
@Column(name = "VTLAC_BANK_NM2")
private String vtlacBankNm2;
@Column(name = "VR_ACTNO2")
private String vrActno2;
@Column(name = "VTLAC_BANK_NM3")
private String vtlacBankNm3;
@Column(name = "VR_ACTNO3")
private String vrActno3;
@Column(name = "VTLAC_BANK_NM4")
private String vtlacBankNm4;
@Column(name = "VR_ACTNO4")
private String vrActno4;
@Column(name = "VTLAC_BANK_NM5")
private String vtlacBankNm5;
@Column(name = "VR_ACTNO5")
private String vrActno5;
@Column(name = "VTLAC_BANK_NM6")
private String vtlacBankNm6;
@Column(name = "VR_ACTNO6")
private String vrActno6;
@Column(name = "VTLAC_BANK_NM7")
private String vtlacBankNm7;
@Column(name = "VR_ACTNO7")
private String vrActno7;
@Column(name = "VTLAC_BANK_NM8")
private String vtlacBankNm8;
@Column(name = "VR_ACTNO8")
private String vrActno8;
@Column(name = "VTLAC_BANK_NM9")
private String vtlacBankNm9;
@Column(name = "VR_ACTNO9")
private String vrActno9;
@Column(name = "VTLAC_BANK_NM10")
private String vtlacBankNm10;
@Column(name = "VR_ACTNO10")
private String vrActno10;
@Column(name = "VTLAC_BANK_NM11")
private String vtlacBankNm11;
@Column(name = "VR_ACTNO11")
private String vrActno11;
@Column(name = "VTLAC_BANK_NM12")
private String vtlacBankNm12;
@Column(name = "VR_ACTNO12")
private String vrActno12;
@Column(name = "VTLAC_BANK_NM13")
private String vtlacBankNm13;
@Column(name = "VR_ACTNO13")
private String vrActno13;
@Column(name = "VTLAC_BANK_NM14")
private String vtlacBankNm14;
@Column(name = "VR_ACTNO14")
private String vrActno14;
@Column(name = "VTLAC_BANK_NM15")
private String vtlacBankNm15;
@Column(name = "VR_ACTNO15")
private String vrActno15;
@Column(name = "VTLAC_BANK_NM16")
private String vtlacBankNm16;
@Column(name = "VR_ACTNO16")
private String vrActno16;
@Column(name = "VTLAC_BANK_NM17")
private String vtlacBankNm17;
@Column(name = "VR_ACTNO17")
private String vrActno17;
@Column(name = "VTLAC_BANK_NM18")
private String vtlacBankNm18;
@Column(name = "VR_ACTNO18")
private String vrActno18;
@Column(name = "VTLAC_BANK_NM19")
private String vtlacBankNm19;
@Column(name = "VR_ACTNO19")
private String vrActno19;
@Column(name = "VTLAC_BANK_NM20")
private String vtlacBankNm20;
@Column(name = "VR_ACTNO20")
private String vrActno20;
@Column(name = "EPAY_NO")
private String epayNo;
@Column(name = "PYR_NO")
private String pyrNo;
@Column(name = "PYR_NM")
private String pyrNm;
@Column(name = "RCVMT_SE_CD")
private String rcvmtSeCd;
@Column(name = "RCVMT_STT_SE_CD")
private String rcvmtSttSeCd;
@Column(name = "TAXN_NO")
private String taxnNo;
@Column(name = "GL_MNG_NO")
private String glMngNo;
@Column(name = "GL_ADDR")
private String glAddr;
@Column(name = "PYR_ADDR")
private String pyrAddr;
@Column(name = "LINK_RST_CD")
private String linkRstCd;
@Column(name = "LINK_RST_MSG")
private String linkRstMsg;
}

@ -0,0 +1,22 @@
server:
port: 8440
spring:
datasource:
url: jdbc:mariadb://211.119.124.122:53306/api_test?useUnicode=true&characterEncoding=utf8
username: root
password: xit5811807
driver-class-name: org.mariadb.jdbc.Driver
hikari:
initialization-fail-timeout: -1
validation-timeout: 2000
connection-timeout: 3000
maximum-pool-size: 5
jpa:
show-sql: false
hibernate:
ddl-auto: none
properties:
hibernate:
format_sql: true
dialect: org.hibernate.dialect.MySQLDialect

@ -0,0 +1,33 @@
body {
font-family: Arial, sans-serif;
margin: 20px;
}
#tabs {
width: 900px;
}
.tab-section {
margin-top: 20px;
}
.btn-insert {
padding: 8px 16px;
border: 1px solid #555;
background-color: #f5f5f5;
cursor: pointer;
border-radius: 4px;
}
.btn-insert:hover {
background-color: #e0e0e0;
}
.result-box {
margin-top: 10px;
padding: 8px;
border: 1px solid #ccc;
background-color: #fafafa;
white-space: pre-wrap;
min-height: 40px;
}

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head th:fragment="common-head(title)">
<meta charset="UTF-8">
<title th:text="${title}">기본 타이틀</title>
<!-- jQuery & jQuery UI CDN -->
<link rel="stylesheet" href="https://code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css">
<!-- jQuery 라이브러리 -->
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<!-- jQuery UI -->
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.min.js"></script>
<!-- 프로젝트 공통 CSS -->
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
</body>
</html>

@ -0,0 +1,96 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head th:replace="~{fragments/common :: common-head('API 테스트 - 샘플 데이터 인서트')}"></head>
<body>
<h1>API 테스트 - 샘플 데이터 인서트</h1>
<div id="tabs">
<ul>
<li><a href="#tab-chajeok">차적</a></li>
<li><a href="#tab-pyoji">표지</a></li>
<li><a href="#tab-bugua">부과</a></li>
<li><a href="#tab-sunap">수납</a></li>
</ul>
<div id="tab-chajeok" class="tab-section">
<h2>차적 샘플</h2>
<button type="button" class="btn-insert" id="btn-insert-chajeok">
차적 샘플데이터 인서트
</button>
<div id="result-chajeok" class="result-box"></div>
</div>
<div id="tab-pyoji" class="tab-section">
<h2>표지 샘플</h2>
<button type="button" class="btn-insert" id="btn-insert-pyoji">
표지 샘플데이터 인서트
</button>
<div id="result-pyoji" class="result-box"></div>
</div>
<div id="tab-bugua" class="tab-section">
<h2>부과 샘플</h2>
<div> 부과는 각 시스템에서 api 인서트 요청후 결과를 받는다. 수동으로 미리 넣어놓을 필요가 없다. </div>
<button type="button" class="btn-insert" id="btn-insert-bugua">
표지 샘플데이터 인서트
</button>
<div id="result-bugua" class="result-box"></div>
</div>
<div id="tab-sunap" class="tab-section">
<h2>수납 샘플</h2>
<div> 해당 mmcode로 인서트를 실행시키면 수납이 된것과 같은 프로세스이다. </div>
<div id="result-sunap" class="result-box">
<textarea id="commentContent" placeholder="mmCodes" rows="2"></textarea>
</div>
<button type="button" class="btn-insert" id="btn-insert-sunap">
수납 샘플데이터 인서트
</button>
</div>
</div>
</body>
</html>
<script>
$(function () {
// jQuery UI Tabs 초기화
$("#tabs").tabs();
// 공통 AJAX 호출 함수
function callInsertApi(url, $resultBox) {
$.ajax({
url: url,
type: "POST",
success: function (res) {
console.log(res);
$resultBox.text(JSON.stringify(res, null, 2));
},
error: function (xhr, status, error) {
$resultBox.text("ERROR: " + status + " / " + error);
}
});
}
// 차적 샘플 인서트
$("#btn-insert-chajeok").on("click", function () {
callInsertApi("/api/sample/chajeok", $("#result-chajeok"));
});
// 표지 샘플 인서트
$("#btn-insert-pyoji").on("click", function () {
callInsertApi("/api/sample/pyoji", $("#result-pyoji"));
});
// 수납 샘플 인서트
$("#bugua").on("click", function () {
callInsertApi("/api/sample/bugua", $("#result-bugua"));
});
// 수납 샘플 인서트
$("#btn-insert-sunap").on("click", function () {
callInsertApi("/api/sample/sunap", $("#result-sunap"));
});
});
</script>

@ -0,0 +1,13 @@
//package org.api.test;
//
//import org.junit.jupiter.api.Test;
//import org.springframework.boot.test.context.SpringBootTest;
//
//@SpringBootTest
//class ApiTestApplicationTests {
//
// @Test
// void contextLoads() {
// }
//
//}
Loading…
Cancel
Save