From 26129a1dbc8b7a127c239536c8c5d3e2fa087325 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=84=B1=EC=98=81?= Date: Thu, 4 Dec 2025 14:53:18 +0900 Subject: [PATCH] =?UTF-8?q?=EC=8B=A0=EA=B7=9C=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=83=81=ED=92=88=EC=9A=A9-=EB=B3=80=EA=B2=BD=EB=93=B1?= =?UTF-8?q?=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/샘플용-utf-8-1.txt | 19 ++ .../impl/checker/ProductUseChnageChecker.java | 243 ++++++++++++++++++ 2 files changed, 262 insertions(+) create mode 100644 docs/샘플용-utf-8-1.txt create mode 100644 src/main/java/go/kr/project/carInspectionPenalty/registration/service/impl/checker/ProductUseChnageChecker.java diff --git a/docs/샘플용-utf-8-1.txt b/docs/샘플용-utf-8-1.txt new file mode 100644 index 0000000..f0af3a9 --- /dev/null +++ b/docs/샘플용-utf-8-1.txt @@ -0,0 +1,19 @@ + 유효기간경과 과태료부과대상 리스트 + ------------------------------------ + + + * 최종등록일이 검사일자보다 늦는 경우는 소유자 및 사용본거지 주소를 재확인하여 주시기 바랍니다. (재검여부 = *일수) + * 전출차량( *차번호)인 경우 전출 전의 주소입니다. 소유자 및 사용본거지 주소를 재확인하여 주시기 바랍니다. +------------------------------------------------------------------------------------------------------------------------------------------------- +검사소 검사일자 자동차번호 소유자명 주민등록번호 차 명 차 종 용 도 종료일 일수 과태료 + 최종등록일 주 소 유효기간만료일 매매상품용 +------------------------------------------------------------------------------------------------------------------------------------------------- +H494 2025-09-01 162고6489 (주)지앤티테크 1244110241315 엠뱅크언더리프 특수차구난형소영업용 2025-08-25 7 4만원 + 2025-07-14 경기도 용인시 기흥구 강남로 9, 111-111호(신행동, 진주만프라자) 2020-12-05 + +H494 2025-09-01 271구5475 (주)케이비캐피탈 1301110013499 엠뱅크언더리프 특수차구난형소영업용 2024-09-24 303 60만원 + 2025-07-14 경기도 용인시 기흥구 강남로 9, 111-111호(신행동, 진주만프라자) 2020-12-05 + +H494 2025-09-11 180너6976 (주)기아주식회사 1101110037998 엠뱅크언더리프 특수차구난형소영업용 2025-05-26 109 56만원 + 2025-07-14 경기도 용인시 기흥구 강남로 9, 111-111호(신행동, 진주만프라자) 2020-12-05 + diff --git a/src/main/java/go/kr/project/carInspectionPenalty/registration/service/impl/checker/ProductUseChnageChecker.java b/src/main/java/go/kr/project/carInspectionPenalty/registration/service/impl/checker/ProductUseChnageChecker.java new file mode 100644 index 0000000..8bcf947 --- /dev/null +++ b/src/main/java/go/kr/project/carInspectionPenalty/registration/service/impl/checker/ProductUseChnageChecker.java @@ -0,0 +1,243 @@ +package go.kr.project.carInspectionPenalty.registration.service.impl.checker; + +import egovframework.constant.TaskPrcsSttsConstants; +import egovframework.exception.MessageException; +import egovframework.util.DateUtil; +import go.kr.project.api.model.request.NewBasicRequest; +import go.kr.project.api.model.request.NewLedgerRequest; +import go.kr.project.api.model.response.NewBasicResponse; +import go.kr.project.api.model.response.NewLedgerResponse; +import go.kr.project.api.service.ExternalVehicleApiService; +import go.kr.project.api.service.VmisCarBassMatterInqireLogService; +import go.kr.project.api.service.VmisCarLedgerFrmbkLogService; +import go.kr.project.carInspectionPenalty.registration.mapper.CarFfnlgTrgtMapper; +import go.kr.project.carInspectionPenalty.registration.model.CarFfnlgTrgtVO; +import go.kr.project.carInspectionPenalty.registration.service.impl.ComparisonRemarkBuilder; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.time.LocalDate; +import java.util.List; + +/** + * 1. 상품용-변경등록 체크 + * + *

api-1번호출.소유자명.contains("상품용")

+ */ +@Slf4j +@Component +public class ProductUseChnageChecker extends AbstractComparisonChecker { + + public ProductUseChnageChecker(CarFfnlgTrgtMapper carFfnlgTrgtMapper, + ExternalVehicleApiService apiService, + VmisCarBassMatterInqireLogService bassMatterLogService, + VmisCarLedgerFrmbkLogService ledgerLogService) { + super(carFfnlgTrgtMapper, apiService, bassMatterLogService, ledgerLogService); + } + + @Override + public String check(CarFfnlgTrgtVO existingData) { + String vhclno = existingData.getVhclno(); + String inspYmd = existingData.getInspYmd(); + String vldPrdExpryYmd = existingData.getVldPrdExpryYmd(); + String inspEndYmd = existingData.getInspEndYmd(); + + try { + // ========== Step 1: 자동차기본정보 조회 (차량번호, 부과일자=검사일) ========== + log.info("[상품용-변경등록] Step 1: 자동차기본정보 조회 - 차량번호: {}, 검사일: {}", vhclno, inspYmd); + + NewBasicRequest step1Request = createBasicRequest(vhclno, null, inspYmd); + NewBasicResponse step1Response = apiService.getBasicInfo(step1Request); + bassMatterLogService.updateCarFfnlgTrgtIdByTxIdNewTx(step1Response, existingData.getCarFfnlgTrgtId()); + + if (step1Response == null || step1Response.getRecord() == null || step1Response.getRecord().isEmpty()) { + log.warn("[상품용-변경등록] Step 1 응답 없음 - 차량번호: {}", vhclno); + return null; + } + + NewBasicResponse.Record step1Record = step1Response.getRecord().get(0); + String vin = step1Record.getVin(); // 차대번호 + String step1OwnerName = step1Record.getRprsOwnrNm(); // 검사일 기준 소유자명 + String step1RprsvOwnrIdecno = step1Record.getRprsvOwnrIdecno(); // 검사일 기준 대표소유자 회원번호 + + log.info("[상품용-변경등록] Step 1 결과 - 차대번호: {}, 소유자명: {}", vin, step1OwnerName); + + // 조건 1: 소유자명에 "상품용" 포함 여부 확인 + if (step1OwnerName == null || !step1OwnerName.contains("상품용")) { + log.debug("[상품용-변경등록] 소유자명에 '상품용' 미포함 - 차량번호: {}, 소유자명: {}", vhclno, step1OwnerName); + return null; + } + + log.info("[상품용-변경등록] 소유자명에 '상품용' 포함 확인! - 차량번호: {}, 소유자명: {}", vhclno, step1OwnerName); + + // ========== Step 2: 자동차기본정보 조회 (차대번호, 부과일자=오늘일자) ========== + String today = LocalDate.now().format(DATE_FORMATTER); + log.info("[상품용-변경등록] Step 2: 자동차기본정보 조회 - 차대번호: {}, 오늘일자: {}", vin, today); + + NewBasicRequest step2Request = createBasicRequest(null, vin, today); + NewBasicResponse step2Response = apiService.getBasicInfo(step2Request); + bassMatterLogService.updateCarFfnlgTrgtIdByTxIdNewTx(step2Response, existingData.getCarFfnlgTrgtId()); + + if (step2Response == null || step2Response.getRecord() == null || step2Response.getRecord().isEmpty()) { + log.warn("[상품용-변경등록] Step 2 응답 없음 - 차대번호: {}", vin); + return null; + } + + NewBasicResponse.Record step2Record = step2Response.getRecord().get(0); + String currentVhclno = step2Record.getVhrno(); + String currentOwnerName = step2Record.getRprsOwnrNm(); + String currentIdecno = step2Record.getRprsvOwnrIdecno(); + String currentLegalDongCode = step2Record.getUsgsrhldStdgCd(); + + log.info("[상품용-변경등록] Step 2 결과 - 차량번호: {}, 성명: {}, 주민번호: {}, 법정동코드: {}", + currentVhclno, currentOwnerName, currentIdecno, currentLegalDongCode); + + // ========== Step 3: 자동차등록원부(갑) 조회 ========== + log.info("[상품용-변경등록] Step 3: 자동차등록원부(갑) 조회 - 차량번호: {}, 성명: {}, 주민번호: {}, 법정동코드: {}", + currentVhclno, currentOwnerName, currentIdecno, currentLegalDongCode); + + NewLedgerRequest step3Request = createLedgerRequest(currentVhclno, currentOwnerName, currentIdecno, currentLegalDongCode); + NewLedgerResponse step3Response = apiService.getLedgerInfo(step3Request); + ledgerLogService.updateCarFfnlgTrgtIdByTxIdNewTx(step3Response, existingData.getCarFfnlgTrgtId()); + + if (step3Response == null) { + log.warn("[상품용-변경등록] Step 3 응답 없음 - 차량번호: {}", currentVhclno); + return null; + } + + List ledgerRecords = step3Response.getRecord(); + if (ledgerRecords == null || ledgerRecords.isEmpty()) { + log.debug("[상품용-변경등록] 갑부 상세 내역 없음 - 차량번호: {}", vhclno); + return null; + } + + // ========== 갑부 상세에서 조건에 맞는 레코드 찾기 ========== + log.info("[상품용-변경등록] 갑부 상세 레코드 검색 시작 - 검사일: {}, 검사종료일자: {}", inspYmd, inspEndYmd); + + NewLedgerResponse.Record targetRecord = null; + LocalDate latestChgDate = null; + LocalDate inspDate = DateUtil.parseDate(inspYmd); + + for (NewLedgerResponse.Record record : ledgerRecords) { + String chgYmd = record.getChgYmd(); + String chgTaskSeCd = record.getChgTaskSeCd(); + + // 조건: CHG_TASK_SE_CD == "21" (변경등록) + if (!"21".equals(chgTaskSeCd) || chgYmd == null) { + continue; + } + + LocalDate chgDate = DateUtil.parseDate(chgYmd); + if (chgDate == null) { + continue; + } + + // 조건: CHG_YMD <= 검사종료일자 + LocalDate inspEndDate = DateUtil.parseDate(inspEndYmd); + if (chgDate.isAfter(inspEndDate)) { + log.debug("[상품용-변경등록] CHG_YMD > 검사종료일자 - 변경일자: {}, 검사종료일자: {}", chgYmd, inspEndYmd); + continue; + } + + String spcablMttr = record.getSpcablMttr(); + if( !spcablMttr.contains("성명") ){ + continue; + } + + // 필요없음. 조건: CHG_YMD가 검사일 이전일자 중 가장 마지막 일자, 필요없음. + /* + if (chgDate.isAfter(inspDate)) { + log.debug("[상품용-변경등록] CHG_YMD > 검사일 - 변경일자: {}, 검사일: {}", chgYmd, inspYmd); + continue; + } + */ + + // 가장 마지막 일자 찾기 + if (latestChgDate == null || chgDate.isAfter(latestChgDate)) { + latestChgDate = chgDate; + targetRecord = record; + log.debug("[상품용-변경등록] 조건 충족 레코드 발견 - 변경일자: {}, 변경업무: {}", chgYmd, chgTaskSeCd); + } + } + + if (targetRecord == null) { + log.debug("[상품용-변경등록] 조건에 맞는 명의이전 레코드 없음 - 차량번호: {}", vhclno); + return null; + } + + String targetChgYmd = targetRecord.getChgYmd(); + log.info("[상품용-변경등록] 조건 충족 레코드 선택! 변경일자: {}, 변경업무: {}", targetChgYmd, targetRecord.getChgTaskSeNm()); + + // ========== Step 4: 자동차기본정보 조회 (차대번호, 부과일자=CHG_YMD) ========== + log.info("[상품용-변경등록] Step 4: 자동차기본정보 조회 - 차대번호: {}, 부과일자: {}", vin, targetChgYmd); + + NewBasicRequest step4Request = createBasicRequest(null, vin, targetChgYmd.replace("-", "")); + NewBasicResponse step4Response = apiService.getBasicInfo(step4Request); + bassMatterLogService.updateCarFfnlgTrgtIdByTxIdNewTx(step4Response, existingData.getCarFfnlgTrgtId()); + + if (step4Response == null || step4Response.getRecord() == null || step4Response.getRecord().isEmpty()) { + log.warn("[상품용-변경등록] Step 4 응답 없음 - 차대번호: {}, 부과일자: {}", vin, targetChgYmd); + return null; + } + + NewBasicResponse.Record step4Record = step4Response.getRecord().get(0); + String step4OwnerName = step4Record.getRprsOwnrNm(); // CHG_YMD 시점의 소유자명 + String step4RprsvOwnrIdecno = step4Record.getRprsvOwnrIdecno(); // 대표소유자 회원번호 + + log.info("[상품용-변경등록] Step 4 결과 - 소유자명: {}", step4OwnerName); + + // ========== 소유자명 -> 소유자 회원번호 비교(주민,법인,사업자번호) 비교 ========== + //if (step4OwnerName == null || !step4OwnerName.equals(step1wnerName)) { + //log.debug("[상품용-변경등록] 소유자명 불일치 - Step1 소유자명: {}, Step4 소유자명: {}", step1wnerName, step4OwnerName); + if (step4OwnerName == null || !step4RprsvOwnrIdecno.equals(step1RprsvOwnrIdecno)) { + log.debug("[상품용-변경등록] 소유자명 불일치 - Step1 소유자: {}, Step4 소유자: {}", step1RprsvOwnrIdecno, step4RprsvOwnrIdecno); + return null; + } + + log.info("[상품용-변경등록] 소유자 일치 확인! - 소유자명: {}", step1OwnerName); + + // ========== 필요 없음. + // 어차피 상단에서 TB_CAR_FFNLG_TRGT.검사종료일자 작은것중의 마지막일자를 찾기때문에 + // 최종 조건: CHG_YMD가 유효기간만료일 ~ 검사종료일자 범위 내 ========== + /* + if (!DateUtil.isDateBetween(targetChgYmd, vldPrdExpryYmd, inspEndYmd)) { + log.debug("[상품용-변경등록] CHG_YMD가 기간 범위 밖 - 변경일자: {}, 유효기간만료일: {}, 검사종료일자: {}", + targetChgYmd, vldPrdExpryYmd, inspEndYmd); + return null; + } + */ + + log.info("[상품용-변경등록] 모든 조건 충족! 차량번호: {}, 변경일자: {}", vhclno, targetChgYmd); + + // ========== 비고 생성 ========== + String rmrk = ComparisonRemarkBuilder.buildProductUseChangeRemark( + step1Record, step4Record, targetRecord, + vldPrdExpryYmd, inspEndYmd + ); + + // ========== DB 업데이트 ========== + existingData.setCarBassMatterInqireId(step1Response.getGeneratedId()); + existingData.setCarLedgerFrmbkId(step3Response.getGeneratedId()); + existingData.setTaskPrcsSttsCd(TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_02_PRODUCT_USE); + existingData.setTaskPrcsYmd(LocalDate.now().format(DATE_FORMATTER)); + existingData.setCarBscMttrInqFlnm(step4OwnerName); + existingData.setCarRegFrmbkChgTaskSeCd(targetRecord.getChgTaskSeCd()); + existingData.setCarRegFrmbkChgTaskSeNm(targetRecord.getChgTaskSeNm()); + existingData.setCarRegFrmbkChgYmd(targetRecord.getChgYmd().replace("-", "")); + existingData.setCarRegFrmbkDtl(ComparisonRemarkBuilder.buildLedgerRecordDetail(targetRecord)); + existingData.setRmrk(rmrk); + + int updateCount = carFfnlgTrgtMapper.update(existingData); + if (updateCount == 0) { + throw new MessageException(String.format("[상품용-변경등록] 업데이트 실패: %s", vhclno)); + } + + log.info("[상품용-변경등록] 처리 완료! 차량번호: {}", vhclno); + return TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_02_PRODUCT_USE; + + } catch (Exception e) { + log.error("[상품용-변경등록] 검증 중 오류 발생 - 차량번호: {}", vhclno, e); + throw new MessageException(String.format("[상품용-변경등록] 검증 중 오류 발생 - 차량번호: %s", vhclno), e); + } + } +}