# 자동차 과태료 비교 로직 명세서 ## 개요 자동차 과태료 부과 대상을 검증하기 위한 비교 로직 정의서입니다. ### 기본 설정 - **API 선택**: YML flag 값에 따라 구/신 API 호출 결정 - **통합 모델**: 구/신 API 응답을 통일된 model object로 처리 - 구 API: 자동차기본정보 API - 신 API: 자동차기본정보 API, 자동차등록원부(갑) - **통합 오브젝트**: 자동차기본정보(구, 신)만 필요 ### 처리 규칙 > **중요**: 순서가 중요함! > - 조건에 걸리는 순간 다음 차량번호 비교로 진행 > - 각 비교 로직별로 개별 API 호출 수행 --- ## 비교 로직 상세 ### 1. 상품용 검증 **필요 API**: 자동차등록원부(갑) #### API 호출 순서 | 순서 | API | 입력 파라미터 | 출력 데이터 | |------|-----|--------------|-------------| | 1 | 자동차기본정보 | `차량번호`, `부과일자=검사일` | `차대번호`, `소유자명` | | 2 | 자동차기본정보 | `1.차대번호`, `부과일자=오늘일자` | `차량번호`, `성명`, `민원인주민번호`, `민원인법정동코드` | | 3 | 자동차등록원본(갑) | `2.차량번호`, `2.성명`, `2.민원인주민번호`, `2.민원인법정동코드` | 갑부 상세 List | #### 비교 조건 ```java // 조건 1: 소유자명에 '상품용' 포함 여부 api.MBER_NM.contains("상품용") // 조건 2: 갑부 상세 목록에서 명의이전 이력 확인 for (LedgerRecord record : 갑부상세List) { if (record.CHG_YMD >= TB_CAR_FFNLG_TRGT.유효기간만료일 && record.CHG_YMD <= TB_CAR_FFNLG_TRGT.검사종료일자 && record.CHANGE_JOB_SE_CODE == "11") { // 11 = 명의이전 코드 return true; } } ``` #### 결과 처리 - **비고 컬럼**: `"[상품용] 갑부정보"` --- ### 2. 이첩 검증 (이첩-1, 이첩-2 병합 로직) **필요 API**: 자동차기본정보 #### 부과기준일 결정 ```java int dayCnt = TB_CAR_FFNLG_TRGT.DAYCNT; // textFile 일수 if (dayCnt > 115) { // 이첩-2 부과기준일 = TB_CAR_FFNLG_TRGT.검사종료일자.plusDays(115); } else { // 이첩-1 부과기준일 = TB_CAR_FFNLG_TRGT.검사일자; } ``` #### API 호출 ```java // 부과기준일 기준으로 자동차기본정보 API 호출 BasicResponse response = 자동차기본정보API.call(부과기준일, 차량번호); ``` #### 법정동코드 비교 로직 (공통) ```java /** * 이첩 조건: 법정동코드 불일치 검증 * 사용본거지법정동코드 앞 4자리 != 사용자 조직코드 앞 4자리 */ private boolean checkTransferCondition_LegalDongMismatch( BasicResponse.Record basicInfo, String userId, String vhclno ) { String useStrnghldLegaldongCode = basicInfo.getUseStrnghldLegaldongCode(); // 1. 법정동코드 유효성 검사 if (useStrnghldLegaldongCode == null || useStrnghldLegaldongCode.length() < 4) { log.debug("[이첩] 법정동코드 없음. 차량번호: {}", vhclno); return false; } // 2. 사용자 정보 조회 SystemUserVO userInfo = userMapper.selectUser(userId); if (userInfo == null || userInfo.getOrgCd() == null) { log.debug("[이첩] 사용자 정보 없음. 사용자ID: {}", userId); return false; } // 3. 법정동코드 앞 4자리 vs 사용자 조직코드 앞 4자리 비교 String legalDong4 = useStrnghldLegaldongCode.substring(0, 4); String userOrgCd = userInfo.getOrgCd(); String userOrg4 = userOrgCd.length() >= 4 ? userOrgCd.substring(0, 4) : userOrgCd; // 4. 일치 여부 판단 if (legalDong4.equals(userOrg4)) { log.debug("[이첩] 법정동코드 일치. 차량번호: {}, 법정동: {}, 조직: {}", vhclno, legalDong4, userOrg4); return false; // 일치하면 이첩 대상 아님 } log.info("[이첩] 법정동코드 불일치! 차량번호: {}, 법정동: {}, 조직: {}", vhclno, legalDong4, userOrg4); return true; // 불일치하면 이첩 대상 } ``` #### 결과 처리 | 구분 | 조건 | 비고 컬럼 형식 | |------|------|---------------| | 이첩-1 | `DAYCNT <= 115` | `"서울시 용산구/ 이경호, 검사일사용본거지, [검사대상, 사용자 조직코드 앞 4자리 및 법정동명]"` | | 이첩-2 | `DAYCNT > 115` | `"전라남도 순천시 / 김정대, 115일 도래지, [2개의 api 법정동코드 및 법정동명]"` | --- ## 데이터 모델 ### TB_CAR_FFNLG_TRGT (과태료 대상 테이블) | 컬럼명 | 설명 | 용도 | |--------|------|------| | 검사일 | 검사 기준일 | API 호출 파라미터 | | 검사종료일자 | 검사 종료 일자 | 115일 계산 기준 | | 유효기간만료일 | 유효기간 만료일 | 상품용 갑부 비교 시작일 | | DAYCNT | textFile 일수 | 이첩-1/2 분기 조건 | | 비고 | 검증 결과 메시지 | 결과 저장 | ### 코드 정의 | 코드 | 코드값 | 설명 | |------|--------|------| | CHANGE_JOB_SE_CODE | 11 | 명의이전 | --- ## 처리 흐름도 ``` 시작 │ ▼ [차량번호 조회] │ ▼ [1. 상품용 검증] ──(조건 충족)──> [비고 기록] ──> [다음 차량] │ │ (조건 미충족) ▼ [2. DAYCNT 확인] │ ├─ (> 115) ──> [이첩-2: 115일 도래지 기준] │ └─ (<= 115) ──> [이첩-1: 검사일 기준] │ ▼ [법정동코드 비교] │ ├─ (불일치) ──> [비고 기록] ──> [다음 차량] │ └─ (일치) ──> [다음 차량] ``` --- ## 구현 시 주의사항 1. **API 호출 순서 준수**: 각 검증 단계별로 필요한 API만 호출 2. **조건 우선순위**: 상품용 > 이첩 순서로 검증 3. **조기 종료**: 조건 충족 시 즉시 다음 차량으로 이동 4. **비고 컬럼**: 각 조건별 정해진 형식으로 기록 5. **법정동코드 길이 검증**: 최소 4자리 이상 필요