You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
20 KiB
20 KiB
자동차 과태료 비교 로직 명세서 (지연)
개요
자동차 과태료 부과 대상(지연)을 검증하기 위한 비교 로직 정의서입니다.
구현 위치
- Checker 클래스:
src/main/java/go/kr/project/carInspectionPenalty/registration/service/impl/delay_checker/ProductUseChecker.java- 1. 상품용(명의이전)ProductUseChnageChecker.java- 1-1. 상품용(변경등록)ProductCloseWithin31Checker.java- 2. 내사종결(명의이전 이전소유자 상품용, 31일 이내)OwnerCloseWithin31Checker.java- 3. 내사종결(순수 명의이전, 31일 이내)ProductLevyOver31Checker.java- 4. 날짜수정후부과(명의이전 이전소유자 상품용, 31일 초과)OwnerLevyOver31Checker.java- 5. 날짜수정후부과(순수 명의이전, 31일 초과)TransferCase115DayChecker.java- 6. 이첩
기본 설정
- 비교로직에 사용되는 API:
ExternalVehicleApiServiceImpl.getBasicInfo,getLedgerInfo호출 - 날짜 유틸리티:
DateUtil.parseDate(),DateUtil.formatDateString()사용 - 일수 계산 기준:
DAYS_THRESHOLD = 31일
문서 이력
| 일자 | 변경 내용 | 비고 |
|---|---|---|
| 2025-12-08 | delay_checker 소스 기준 전면 재작성 | 실제 코드와 일치하도록 정리 |
| 2025-12-03 | 실제 소스 코드 기준으로 전면 재작성 | Javadoc과 실제 로직 차이 명시 |
| 2025-12-02 | 내사종결 로직 추가 및 상품용 조건 변경 | 명의이전 31일 이내 조건 추가 |
처리 규칙
중요: 순서가 중요함!
- 상품용(명의이전) → 1-1. 상품용(변경등록) → 2. 내사종결(상품용) → 3. 내사종결(명의이전) → 4. 날짜수정(상품용) → 5. 날짜수정(명의이전) → 6. 이첩
- 조건에 걸리는 순간 다음 차량번호 비교로 진행
- 각 비교 로직별로 개별 API 호출 수행
비교 로직 상세
1. 상품용 검증 (ProductUseChecker)
처리상태코드: 02 (상품용)
클래스: ProductUseChecker.java
API 호출 순서
| 순서 | API | 입력 파라미터 | 출력 데이터 | 용도 |
|---|---|---|---|---|
| 1 | 자동차기본정보 | 차량번호, 부과일자=검사일 |
차대번호(vin), 소유자명, 대표소유자회원번호 |
검사일 기준 소유자 확인 |
| 2 | 자동차기본정보 | 1.차대번호, 부과일자=오늘 |
차량번호, 성명, 주민번호, 법정동코드 |
현재 소유자 정보 |
| 3 | 자동차등록원부(갑) | 2.차량번호, 2.성명, 2.주민번호, 2.법정동코드 |
갑부 상세 List | 명의이전 이력 조회 |
| 4 | 자동차기본정보 | 1.차대번호, 부과일자=CHG_YMD |
소유자명, 대표소유자회원번호 |
명의이전 시점 소유자 확인 |
비교 조건
1. Step1 소유자명.contains("상품용") ← 상품용 아니면 return null
2. 갑부에서 명의이전(11) 레코드 찾기
- CHG_TASK_SE_CD == "11"
- CHG_YMD <= 검사종료일자
- 가장 마지막 일자 선택
← 없으면 return null
3. Step4 대표소유자회원번호 == Step1 대표소유자회원번호
← 불일치면 return null
→ 모든 조건 충족: 상품용(02) 처리
DB 업데이트 필드
existingData.setTaskPrcsSttsCd("02"); // 상품용
existingData.setCarBscMttrInqFlnm(step4OwnerName);
existingData.setCarRegFrmbkChgTaskSeCd("11");
existingData.setCarRegFrmbkChgYmd(targetRecord.getChgYmd());
1-1. 상품용-변경등록 검증 (ProductUseChnageChecker)
처리상태코드: 02 (상품용)
클래스: ProductUseChnageChecker.java
API 호출 순서
| 순서 | API | 입력 파라미터 | 출력 데이터 | 용도 |
|---|---|---|---|---|
| 1 | 자동차기본정보 | 차량번호, 부과일자=검사일 |
차대번호(vin), 소유자명, 대표소유자회원번호 |
검사일 기준 소유자 확인 |
| 2 | 자동차기본정보 | 1.차대번호, 부과일자=오늘 |
차량번호, 성명, 주민번호, 법정동코드 |
현재 소유자 정보 |
| 3 | 자동차등록원부(갑) | 2.차량번호, 2.성명, 2.주민번호, 2.법정동코드 |
갑부 상세 List | 변경등록 이력 조회 |
| 4 | 자동차기본정보 | 1.차대번호, 부과일자=CHG_YMD |
소유자명, 대표소유자회원번호 |
변경등록 시점 소유자 확인 |
비교 조건
1. Step1 소유자명.contains("상품용") ← 상품용 아니면 return null
2. 갑부에서 변경등록(21) 레코드 찾기
- CHG_TASK_SE_CD == "21"
- CHG_YMD <= 검사종료일자
- spcablMttr.contains("성명") ← 성명 변경 포함 필수
- 가장 마지막 일자 선택
← 없으면 return null
3. Step4 대표소유자회원번호 == Step1 대표소유자회원번호
← 불일치면 return null
→ 모든 조건 충족: 상품용(02) 처리
DB 업데이트 필드
existingData.setTaskPrcsSttsCd("02"); // 상품용
existingData.setCarBscMttrInqFlnm(step4OwnerName);
existingData.setCarRegFrmbkChgTaskSeCd("21");
existingData.setCarRegFrmbkChgYmd(targetRecord.getChgYmd());
2. 내사종결 - 명의이전 이전소유자 상품용, 31일 이내 (ProductCloseWithin31Checker)
처리상태코드: 04 (내사종결)
클래스: ProductCloseWithin31Checker.java
API 호출 순서
| 순서 | API | 입력 파라미터 | 출력 데이터 | 용도 |
|---|---|---|---|---|
| 1 | 자동차기본정보 | 차량번호, 부과일자=검사일 |
차대번호, 소유자명 |
검사일 기준 소유자 확인 |
| 2 | 자동차기본정보 | 1.차대번호, 부과일자=오늘 |
차량번호, 성명, 주민번호, 법정동코드 |
현재 소유자 정보 |
| 3 | 자동차등록원부(갑) | 2.차량번호, 2.성명, 2.주민번호, 2.법정동코드 |
갑부 상세 List | 명의이전 이력 조회 |
| 4 | 자동차기본정보 | 1.차대번호, 부과일자=CHG_YMD-1일 |
소유자명 |
명의이전 직전 소유자 확인 |
비교 조건
1. Step1 소유자명.contains("상품용") → return null (1번에서 처리됨)
!Step1 소유자명.contains("상품용") → 계속 진행
2. 갑부에서 명의이전(11) 레코드 찾기
- CHG_TASK_SE_CD == "11"
- CHG_YMD <= 검사일
- 가장 마지막 일자 선택
← 없으면 return null
3. 일수 계산: 명의이전일자 ~ 검사일
- 0~31일 이내 → 계속 진행
- 31일 초과 → return null (4번에서 처리)
4. Step4 소유자명.contains("상품용")
← 상품용 아니면 return null
→ 모든 조건 충족: 내사종결(04) 처리
DB 업데이트 필드
existingData.setTaskPrcsSttsCd("04"); // 내사종결
existingData.setCarBscMttrInqFlnm(step4OwnerName); // 명의이전 직전 소유자명
existingData.setCarRegFrmbkChgTaskSeCd("11");
existingData.setCarRegFrmbkChgYmd(targetRecord.getChgYmd());
3. 내사종결 - 순수 명의이전, 31일 이내 (OwnerCloseWithin31Checker)
처리상태코드: 04 (내사종결)
클래스: OwnerCloseWithin31Checker.java
API 호출 순서
| 순서 | API | 입력 파라미터 | 출력 데이터 | 용도 |
|---|---|---|---|---|
| 1 | 자동차기본정보 | 차량번호, 부과일자=검사일 |
차대번호, 소유자명, 대표소유자회원번호 |
검사일 기준 소유자 확인 |
| 2 | 자동차기본정보 | 1.차대번호, 부과일자=오늘 |
차량번호, 성명, 주민번호, 법정동코드 |
현재 소유자 정보 |
| 3 | 자동차등록원부(갑) | 2.차량번호, 2.성명, 2.주민번호, 2.법정동코드 |
갑부 상세 List | 명의이전 이력 조회 |
| 4 | 자동차기본정보 | 1.차대번호, 부과일자=CHG_YMD |
소유자명, 대표소유자회원번호 |
명의이전 시점 소유자 확인 |
비교 조건
1. Step1 소유자명.contains("상품용") → return null (1번에서 처리됨)
!Step1 소유자명.contains("상품용") → 계속 진행
2. 갑부에서 명의이전(11) 레코드 찾기
- CHG_TASK_SE_CD == "11"
- 유효기간만료일-90일 <= CHG_YMD <= 검사종료일자
- 가장 마지막 일자 선택
← 없으면 return null
3. 일수 계산: 명의이전일자 ~ 검사일
- 0~31일 이내 → 계속 진행
- 31일 초과 → return null (5번에서 처리)
4. Step4 대표소유자회원번호 == Step1 대표소유자회원번호
← 불일치면 return null
→ 모든 조건 충족: 내사종결(04) 처리
DB 업데이트 필드
existingData.setTaskPrcsSttsCd("04"); // 내사종결
existingData.setCarBscMttrInqFlnm(step4OwnerName);
existingData.setCarRegFrmbkChgTaskSeCd("11");
existingData.setCarRegFrmbkChgYmd(targetRecord.getChgYmd());
4. 날짜수정후부과 - 명의이전 이전소유자 상품용, 31일 초과 (ProductLevyOver31Checker)
처리상태코드: 05 (날짜 수정 후 부과)
클래스: ProductLevyOver31Checker.java
API 호출 순서
| 순서 | API | 입력 파라미터 | 출력 데이터 | 용도 |
|---|---|---|---|---|
| 1 | 자동차기본정보 | 차량번호, 부과일자=검사일 |
차대번호, 소유자명 |
검사일 기준 소유자 확인 |
| 2 | 자동차기본정보 | 1.차대번호, 부과일자=오늘 |
차량번호, 성명, 주민번호, 법정동코드 |
현재 소유자 정보 |
| 3 | 자동차등록원부(갑) | 2.차량번호, 2.성명, 2.주민번호, 2.법정동코드 |
갑부 상세 List | 명의이전 이력 조회 |
| 4 | 자동차기본정보 | 1.차대번호, 부과일자=CHG_YMD-1일 |
소유자명 |
명의이전 직전 소유자 확인 |
비교 조건
1. Step1 소유자명.contains("상품용") → return null (1번에서 처리됨)
!Step1 소유자명.contains("상품용") → 계속 진행
2. 갑부에서 명의이전(11) 레코드 찾기
- CHG_TASK_SE_CD == "11"
- CHG_YMD <= 검사일
- 가장 마지막 일자 선택
← 없으면 return null
3. 일수 계산: 명의이전일자 ~ 검사일
- 31일 초과 → 계속 진행
- 0~31일 이내 → return null (2번에서 처리)
4. Step4 소유자명.contains("상품용")
← 상품용 아니면 return null
→ 모든 조건 충족: 날짜수정후부과(05) 처리
DB 업데이트 필드
existingData.setTaskPrcsSttsCd("05"); // 날짜수정후부과
existingData.setCarBscMttrInqFlnm(step4OwnerName); // 명의이전 직전 소유자명
existingData.setCarRegFrmbkChgTaskSeCd("11");
existingData.setCarRegFrmbkChgYmd(targetRecord.getChgYmd());
5. 날짜수정후부과 - 순수 명의이전, 31일 초과 (OwnerLevyOver31Checker)
처리상태코드: 05 (날짜 수정 후 부과)
클래스: OwnerLevyOver31Checker.java
API 호출 순서
| 순서 | API | 입력 파라미터 | 출력 데이터 | 용도 |
|---|---|---|---|---|
| 1 | 자동차기본정보 | 차량번호, 부과일자=검사일 |
차대번호, 소유자명, 대표소유자회원번호 |
검사일 기준 소유자 확인 |
| 2 | 자동차기본정보 | 1.차대번호, 부과일자=오늘 |
차량번호, 성명, 주민번호, 법정동코드 |
현재 소유자 정보 |
| 3 | 자동차등록원부(갑) | 2.차량번호, 2.성명, 2.주민번호, 2.법정동코드 |
갑부 상세 List | 명의이전 이력 조회 |
| 4 | 자동차기본정보 | 1.차대번호, 부과일자=CHG_YMD |
소유자명, 대표소유자회원번호 |
명의이전 시점 소유자 확인 |
비교 조건
1. Step1 소유자명.contains("상품용") → return null (1번에서 처리됨)
!Step1 소유자명.contains("상품용") → 계속 진행
2. 갑부에서 명의이전(11) 레코드 찾기
- CHG_TASK_SE_CD == "11"
- 유효기간만료일-90일 <= CHG_YMD <= 검사종료일자
- 가장 마지막 일자 선택
← 없으면 return null
3. 일수 계산: 명의이전일자 ~ 검사일
- 31일 초과 → 계속 진행
- 0~31일 이내 → return null (3번에서 처리)
4. Step4 대표소유자회원번호 == Step1 대표소유자회원번호
← 불일치면 return null
→ 모든 조건 충족: 날짜수정후부과(05) 처리
DB 업데이트 필드
existingData.setTaskPrcsSttsCd("05"); // 날짜수정후부과
existingData.setCarBscMttrInqFlnm(step4OwnerName);
existingData.setCarRegFrmbkChgTaskSeCd("11");
existingData.setCarRegFrmbkChgYmd(targetRecord.getChgYmd());
6. 이첩 검증 (TransferCase115DayChecker)
처리상태코드: 03 (이첩)
클래스: TransferCase115DayChecker.java
API 호출
| API | 입력 파라미터 | 출력 데이터 | 용도 |
|---|---|---|---|
| 자동차기본정보 | 차량번호, 부과일자=부과기준일 |
사용본거지법정동코드 |
부과기준일 기준 사용본거지 확인 |
비교 조건
1. DAYCNT 값으로 부과기준일 계산
- DAYCNT > 115: 이첩-2 (부과기준일 = 검사종료일자 + 115일)
- DAYCNT <= 115: 이첩-1 (부과기준일 = 검사일자)
← DAYCNT 없으면 return null
2. 자동차기본정보(차량번호, 부과기준일) 호출
→ 사용본거지법정동코드 조회
3. 법정동코드 앞 4자리 != 사용자 조직코드 앞 4자리
← 일치하면 return null
→ 불일치: 이첩(03) 처리
결과 처리
| 구분 | 조건 | 비고 컬럼 형식 |
|---|---|---|
| 이첩-1 | DAYCNT <= 115 |
"{시군구명}, 검사일사용본거지, [사용자 조직코드 앞 4자리: {userOrg4}, 법정동명: {sggNm}]" |
| 이첩-2 | DAYCNT > 115 |
"{시군구명}, 115일 도래지, [법정동코드: {legalDong4}, 법정동명: {sggNm}]" |
DB 업데이트 필드
existingData.setTaskPrcsSttsCd("03"); // 이첩
existingData.setCarBscMttrInqFlnm(existingData.getOwnrNm()); // 기존 소유자명 유지
existingData.setCarBscMttrInqSggCd(sggCd);
existingData.setCarBscMttrInqSggNm(sggNm);
처리 흐름도
시작
│
▼
[차량번호 조회]
│
▼
┌──────────────────────────────────────────────┐
│ 1. 상품용-명의이전 (ProductUseChecker) │
│ 조건: 검사일 소유자명.contains("상품용") │
│ + 명의이전(11) 레코드 존재 │
│ → 조건 충족: 상품용(02) │
└──────────────────────────────────────────────┘
│ (조건 미충족)
▼
┌──────────────────────────────────────────────┐
│ 1-1. 상품용-변경등록 (ProductUseChnageChecker)│
│ 조건: 검사일 소유자명.contains("상품용") │
│ + 변경등록(21) + 성명변경 포함 │
│ → 조건 충족: 상품용(02) │
└──────────────────────────────────────────────┘
│ (조건 미충족)
▼
┌──────────────────────────────────────────────┐
│ 2. 내사종결-상품용 (ProductCloseWithin31Checker) │
│ 조건: 31일 이내 + 명의이전 전 상품용 │
│ → 조건 충족: 내사종결(04) │
└──────────────────────────────────────────────┘
│ (조건 미충족)
▼
┌──────────────────────────────────────────────┐
│ 3. 내사종결-명의이전 (OwnerCloseWithin31Checker) │
│ 조건: 31일 이내 + 동일 소유자 │
│ → 조건 충족: 내사종결(04) │
└──────────────────────────────────────────────┘
│ (조건 미충족)
▼
┌──────────────────────────────────────────────┐
│ 4. 날짜수정-상품용 (ProductLevyOver31Checker) │
│ 조건: 31일 초과 + 명의이전 전 상품용 │
│ → 조건 충족: 날짜수정후부과(05) │
└──────────────────────────────────────────────┘
│ (조건 미충족)
▼
┌──────────────────────────────────────────────┐
│ 5. 날짜수정-명의이전 (OwnerLevyOver31Checker) │
│ 조건: 31일 초과 + 동일 소유자 │
│ → 조건 충족: 날짜수정후부과(05) │
└──────────────────────────────────────────────┘
│ (조건 미충족)
▼
┌──────────────────────────────────────────────┐
│ 6. 이첩 (TransferCase115DayChecker) │
│ 조건: 법정동코드 앞4자리 != 조직코드 앞4자리│
│ → 조건 충족: 이첩(03) │
└──────────────────────────────────────────────┘
│ (조건 미충족)
▼
[다음 차량]
요약 정리
처리상태코드 매핑
| 코드 | 상태명 | 처리 로직 | 클래스 |
|---|---|---|---|
| 02 | 상품용 | 검사일 소유자가 상품용 + 명의이전(11) | ProductUseChecker |
| 02 | 상품용 | 검사일 소유자가 상품용 + 변경등록(21) + 성명변경 | ProductUseChnageChecker |
| 04 | 내사종결 | 명의이전 전 상품용 (31일 이내) | ProductCloseWithin31Checker |
| 04 | 내사종결 | 순수 명의이전 (31일 이내) | OwnerCloseWithin31Checker |
| 05 | 날짜수정후부과 | 명의이전 전 상품용 (31일 초과) | ProductLevyOver31Checker |
| 05 | 날짜수정후부과 | 순수 명의이전 (31일 초과) | OwnerLevyOver31Checker |
| 03 | 이첩 | 법정동코드 불일치 | TransferCase115DayChecker |
상품용 vs 순수 명의이전 비교
| 구분 | 상품용 케이스 (2, 4번) | 순수 명의이전 케이스 (3, 5번) |
|---|---|---|
| 검사일 소유자 | 상품용 아님 | 상품용 아님 |
| 명의이전 직전 소유자 | 상품용 포함 | 소유자 회원번호 일치 |
| Step 4 확인사항 | 소유자명.contains("상품용") | 대표소유자회원번호 == Step1 |
| 갑부 검색 조건 | CHG_YMD <= 검사일 | 유효기간만료일-90일 <= CHG_YMD <= 검사종료일자 |
| 일수 기준 | 31일 이내/초과 | 31일 이내/초과 |
| 처리상태코드 | 31일 이내: 04, 초과: 05 | 31일 이내: 04, 초과: 05 |
참고 상수 및 유틸리티
상수
// 일수 기준값
private static final int DAYS_THRESHOLD = 31;
// 처리상태코드
TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_02_PRODUCT_USE = "02"
TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_03_TRANSFER = "03"
TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_04_INVESTIGATION_CLOSED = "04"
TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_05_DATE_MODIFIED_LEVY = "05"
// 변경업무구분코드
"11" = 명의이전
"21" = 변경등록
문서 작성 완료일: 2025-12-08 실제 소스 코드 기준: delay_checker 폴더 내 Checker 클래스들 분석 대상 클래스: 7개 (ProductUseChecker, ProductUseChnageChecker, ProductCloseWithin31Checker, OwnerCloseWithin31Checker, ProductLevyOver31Checker, OwnerLevyOver31Checker, TransferCase115DayChecker)