|
|
|
|
@ -2,13 +2,16 @@ package go.kr.project.carInspectionPenalty.registration.service.impl;
|
|
|
|
|
|
|
|
|
|
import egovframework.constant.TaskPrcsSttsConstants;
|
|
|
|
|
import egovframework.exception.MessageException;
|
|
|
|
|
import go.kr.project.api.model.VehicleApiResponseVO;
|
|
|
|
|
import go.kr.project.api.model.response.OldBasicResponse;
|
|
|
|
|
import egovframework.util.SessionUtil;
|
|
|
|
|
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.carInspectionPenalty.registration.mapper.CarFfnlgTrgtMapper;
|
|
|
|
|
import go.kr.project.carInspectionPenalty.registration.model.CarFfnlgTrgtVO;
|
|
|
|
|
import go.kr.project.carInspectionPenalty.registration.service.ComparisonService;
|
|
|
|
|
import go.kr.project.system.user.mapper.UserMapper;
|
|
|
|
|
import go.kr.project.system.user.model.SystemUserVO;
|
|
|
|
|
import go.kr.project.login.model.LoginUserVO;
|
|
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
|
|
|
|
|
@ -16,6 +19,7 @@ import org.springframework.stereotype.Service;
|
|
|
|
|
|
|
|
|
|
import java.time.LocalDate;
|
|
|
|
|
import java.time.format.DateTimeFormatter;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 과태료 대상 비교 서비스 구현체
|
|
|
|
|
@ -29,7 +33,7 @@ import java.time.format.DateTimeFormatter;
|
|
|
|
|
public class ComparisonServiceImpl extends EgovAbstractServiceImpl implements ComparisonService {
|
|
|
|
|
|
|
|
|
|
private final CarFfnlgTrgtMapper carFfnlgTrgtMapper;
|
|
|
|
|
private final UserMapper userMapper;
|
|
|
|
|
private final ExternalVehicleApiService apiService;
|
|
|
|
|
|
|
|
|
|
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");
|
|
|
|
|
|
|
|
|
|
@ -39,28 +43,26 @@ public class ComparisonServiceImpl extends EgovAbstractServiceImpl implements Co
|
|
|
|
|
* <p>순차적으로 각 비교 메서드를 실행하고, 하나라도 적용되면 즉시 종료합니다.</p>
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
public String executeComparison(CarFfnlgTrgtVO existingData, VehicleApiResponseVO apiResponse, String userId) {
|
|
|
|
|
public String executeComparison(CarFfnlgTrgtVO existingData) {
|
|
|
|
|
String vhclno = existingData.getVhclno();
|
|
|
|
|
log.info("========== 비교 로직 시작: {} ==========", vhclno);
|
|
|
|
|
|
|
|
|
|
OldBasicResponse.Record basicInfo = apiResponse.getBasicInfo().getRecord().get(0);
|
|
|
|
|
|
|
|
|
|
// ========== 1. 상품용 체크 ==========
|
|
|
|
|
String productUseResult = checkProductUse(existingData, basicInfo);
|
|
|
|
|
String productUseResult = checkProductUse(existingData);
|
|
|
|
|
if (productUseResult != null) {
|
|
|
|
|
log.info("========== 비교 로직 종료 (상품용): {} ==========", vhclno);
|
|
|
|
|
return productUseResult;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ========== 2. 이첩 체크 ==========
|
|
|
|
|
String transferResult = checkTransfer(existingData, basicInfo, userId);
|
|
|
|
|
String transferResult = checkTransfer(existingData);
|
|
|
|
|
if (transferResult != null) {
|
|
|
|
|
log.info("========== 비교 로직 종료 (이첩): {} ==========", vhclno);
|
|
|
|
|
return transferResult;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ========== 3. 향후 추가될 비교 로직들 ==========
|
|
|
|
|
// String investigationClosedResult = checkInvestigationClosed(existingData, basicInfo);
|
|
|
|
|
// String investigationClosedResult = checkInvestigationClosed(existingData);
|
|
|
|
|
// if (investigationClosedResult != null) {
|
|
|
|
|
// return investigationClosedResult;
|
|
|
|
|
// }
|
|
|
|
|
@ -75,172 +77,433 @@ public class ComparisonServiceImpl extends EgovAbstractServiceImpl implements Co
|
|
|
|
|
// ========================================
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 1. 상품용 체크
|
|
|
|
|
* 1. 상품용 검증
|
|
|
|
|
*
|
|
|
|
|
* API 호출 3단계:
|
|
|
|
|
* 1) 자동차기본정보(차량번호, 부과일자=검사일) -> 차대번호, 소유자명
|
|
|
|
|
* 2) 자동차기본정보(차대번호, 부과일자=오늘일자) -> 차량번호, 성명, 민원인주민번호, 민원인법정동코드
|
|
|
|
|
* 3) 자동차등록원부(갑)(차량번호, 성명, 민원인주민번호, 민원인법정동코드) -> 갑부 상세 List
|
|
|
|
|
*
|
|
|
|
|
* <p>조건: 대표소유자성명(MBER_NM)에 "상품용" 문자열 포함</p>
|
|
|
|
|
* <p>처리: TASK_PRCS_STTS_CD = 02, CAR_BSC_MTTR_INQ_FLNM = 소유자명</p>
|
|
|
|
|
* 비교조건:
|
|
|
|
|
* - 소유자명에 "상품용" 포함
|
|
|
|
|
* - 갑부 상세에서 명의이전(코드 11) 이력이 유효기간만료일~검사종료일자 사이에 있는지
|
|
|
|
|
*
|
|
|
|
|
* @return 02 (적용됨) 또는 null (미적용)
|
|
|
|
|
* @param existingData 과태료 대상 데이터
|
|
|
|
|
* @return 02 (상품용) 또는 null (미적용)
|
|
|
|
|
*/
|
|
|
|
|
private String checkProductUse(CarFfnlgTrgtVO existingData, OldBasicResponse.Record basicInfo) {
|
|
|
|
|
private String checkProductUse(CarFfnlgTrgtVO existingData) {
|
|
|
|
|
String vhclno = existingData.getVhclno();
|
|
|
|
|
String mberNm = basicInfo.getMberNm(); // 대표소유자성명
|
|
|
|
|
String inspYmd = existingData.getInspYmd();
|
|
|
|
|
|
|
|
|
|
// 조건 체크
|
|
|
|
|
if (mberNm == null || !mberNm.contains("상품용")) {
|
|
|
|
|
log.debug("[상품용] 조건 미충족. 차량번호: {}, 소유자명: {}", vhclno, mberNm);
|
|
|
|
|
try {
|
|
|
|
|
// Step 1: 자동차기본정보 조회 (차량번호, 부과일자=검사일)
|
|
|
|
|
log.info("[상품용] Step 1: 자동차기본정보 조회 - 차량번호: {}, 검사일: {}", vhclno, inspYmd);
|
|
|
|
|
|
|
|
|
|
NewBasicRequest step1Request = createBasicRequest(vhclno, null, inspYmd);
|
|
|
|
|
NewBasicResponse step1Response = apiService.getBasicInfo(step1Request);
|
|
|
|
|
|
|
|
|
|
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 ownerName = step1Record.getRprsOwnrNm(); // 대표소유자성명
|
|
|
|
|
|
|
|
|
|
log.info("[상품용] Step 1 결과 - 차대번호: {}, 소유자명: {}", vin, ownerName);
|
|
|
|
|
|
|
|
|
|
// 조건 1: 소유자명에 "상품용" 포함 여부 확인
|
|
|
|
|
if (ownerName == null || !ownerName.contains("상품용")) {
|
|
|
|
|
log.debug("[상품용] 소유자명에 '상품용' 미포함 - 차량번호: {}, 소유자명: {}", vhclno, ownerName);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.info("[상품용] 소유자명에 '상품용' 포함 - 차량번호: {}, 소유자명: {}", vhclno, ownerName);
|
|
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
if (step3Response == null) {
|
|
|
|
|
log.warn("[상품용] Step 3 응답 없음 - 차량번호: {}", currentVhclno);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 조건 2: 갑부 상세에서 명의이전 이력 확인
|
|
|
|
|
List<NewLedgerResponse.Record> ledgerRecords = step3Response.getRecord();
|
|
|
|
|
if (ledgerRecords == null || ledgerRecords.isEmpty()) {
|
|
|
|
|
log.debug("[상품용] 갑부 상세 내역 없음 - 차량번호: {}", vhclno);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 유효기간만료일 ~ 검사종료일자 사이에 명의이전(코드 11) 이력이 있는지 확인
|
|
|
|
|
String vldPrdExpryYmd = existingData.getVldPrdExpryYmd();
|
|
|
|
|
String inspEndYmd = existingData.getInspEndYmd();
|
|
|
|
|
|
|
|
|
|
log.info("[상품용] 갑부 상세 비교 기간 - 유효기간만료일: {}, 검사종료일자: {}", vldPrdExpryYmd, inspEndYmd);
|
|
|
|
|
|
|
|
|
|
for (NewLedgerResponse.Record record : ledgerRecords) {
|
|
|
|
|
String chgYmd = record.getChgYmd(); // 변경일자
|
|
|
|
|
String chgTaskSeCd = record.getChgTaskSeCd(); // 변경업무구분코드
|
|
|
|
|
|
|
|
|
|
log.debug("[상품용] 갑부 레코드 - 변경일자: {}, 변경업무구분코드: {}", chgYmd, chgTaskSeCd);
|
|
|
|
|
|
|
|
|
|
// 명의이전 코드 11 확인 및 기간 확인
|
|
|
|
|
if ("11".equals(chgTaskSeCd) && chgYmd != null) {
|
|
|
|
|
if (isDateBetween(chgYmd, vldPrdExpryYmd, inspEndYmd)) {
|
|
|
|
|
log.info("[상품용] 조건 충족! 차량번호: {}, 변경일자: {}, 변경업무: {}", vhclno, chgYmd, chgTaskSeCd);
|
|
|
|
|
|
|
|
|
|
// 비고 생성 - 갑부 상세 정보 포함
|
|
|
|
|
String rmrk = buildProductUseRemark(
|
|
|
|
|
step1Record, step2Record, record,
|
|
|
|
|
vldPrdExpryYmd, inspEndYmd
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// DB 업데이트
|
|
|
|
|
existingData.setTaskPrcsSttsCd(TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_02_PRODUCT_USE);
|
|
|
|
|
existingData.setTaskPrcsYmd(LocalDate.now().format(DATE_FORMATTER));
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.debug("[상품용] 명의이전 이력이 기간 내 없음 - 차량번호: {}", vhclno);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.info("[상품용] 조건 충족! 차량번호: {}, 소유자명: {}", vhclno, mberNm);
|
|
|
|
|
|
|
|
|
|
// DB 업데이트
|
|
|
|
|
existingData.setTaskPrcsSttsCd(TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_02_PRODUCT_USE); // 상품용
|
|
|
|
|
existingData.setTaskPrcsYmd(LocalDate.now().format(DATE_FORMATTER));
|
|
|
|
|
existingData.setCarBscMttrInqFlnm(mberNm); // 소유자명 저장
|
|
|
|
|
existingData.setCarBscMttrInqSggCd(null);
|
|
|
|
|
existingData.setCarBscMttrInqSggNm(null);
|
|
|
|
|
|
|
|
|
|
int updateCount = carFfnlgTrgtMapper.update(existingData);
|
|
|
|
|
if (updateCount == 0) {
|
|
|
|
|
throw new MessageException(String.format("[상품용] 업데이트 실패: %s", vhclno));
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.error("[상품용] 검증 중 오류 발생 - 차량번호: {}", vhclno, e);
|
|
|
|
|
throw new MessageException(String.format("[상품용] 검증 중 오류 발생 - 차량번호: %s", vhclno), e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.info("[상품용] 처리 완료! 차량번호: {}", vhclno);
|
|
|
|
|
return TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_02_PRODUCT_USE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 2. 이첩 체크 (OR 로직: 여러 조건 중 하나라도 만족하면 이첩)
|
|
|
|
|
* 2. 이첩 검증
|
|
|
|
|
*
|
|
|
|
|
* <p>처리: TASK_PRCS_STTS_CD = 03, CAR_BSC_MTTR_INQ_SGG_CD = 시군구코드, CAR_BSC_MTTR_INQ_SGG_NM = 시군구명</p>
|
|
|
|
|
* DAYCNT 기반 부과기준일 계산:
|
|
|
|
|
* - DAYCNT > 115: 이첩-2 (부과기준일 = 검사종료일자 + 115일)
|
|
|
|
|
* - DAYCNT <= 115: 이첩-1 (부과기준일 = 검사일자)
|
|
|
|
|
*
|
|
|
|
|
* @return 03 (적용됨) 또는 null (미적용)
|
|
|
|
|
* 법정동코드 비교:
|
|
|
|
|
* - 사용본거지법정동코드 앞 4자리 != 사용자 조직코드 앞 4자리
|
|
|
|
|
*
|
|
|
|
|
* @param existingData 과태료 대상 데이터
|
|
|
|
|
* @return 03 (이첩) 또는 null (미적용)
|
|
|
|
|
*/
|
|
|
|
|
private String checkTransfer(CarFfnlgTrgtVO existingData, OldBasicResponse.Record basicInfo, String userId) {
|
|
|
|
|
private String checkTransfer(CarFfnlgTrgtVO existingData) {
|
|
|
|
|
String vhclno = existingData.getVhclno();
|
|
|
|
|
|
|
|
|
|
// ========== 이첩 조건들 (OR 로직: 하나라도 만족하면 이첩) ==========
|
|
|
|
|
|
|
|
|
|
// 조건1: 법정동코드 불일치
|
|
|
|
|
if (checkTransferCondition1_LegalDongMismatch(basicInfo, userId, vhclno)) {
|
|
|
|
|
return processTransfer(existingData, basicInfo, vhclno, "법정동코드 불일치");
|
|
|
|
|
try {
|
|
|
|
|
// DAYCNT 가져오기
|
|
|
|
|
String daycntStr = existingData.getDaycnt();
|
|
|
|
|
if (daycntStr == null || daycntStr.isEmpty()) {
|
|
|
|
|
log.debug("[이첩] DAYCNT 없음 - 차량번호: {}", vhclno);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int daycnt = Integer.parseInt(daycntStr);
|
|
|
|
|
log.info("[이첩] DAYCNT: {} - 차량번호: {}", daycnt, vhclno);
|
|
|
|
|
|
|
|
|
|
// 부과기준일 계산
|
|
|
|
|
String levyCrtrYmd;
|
|
|
|
|
String transferType;
|
|
|
|
|
|
|
|
|
|
if (daycnt > 115) {
|
|
|
|
|
// 이첩-2: 부과기준일 = 검사종료일자 + 115일
|
|
|
|
|
String inspEndYmd = existingData.getInspEndYmd();
|
|
|
|
|
LocalDate inspEndDate = LocalDate.parse(inspEndYmd, DATE_FORMATTER);
|
|
|
|
|
LocalDate levyCrtrDate = inspEndDate.plusDays(115);
|
|
|
|
|
levyCrtrYmd = levyCrtrDate.format(DATE_FORMATTER);
|
|
|
|
|
transferType = "이첩-2";
|
|
|
|
|
log.info("[이첩-2] 부과기준일 = 검사종료일자({}) + 115일 = {}", inspEndYmd, levyCrtrYmd);
|
|
|
|
|
} else {
|
|
|
|
|
// 이첩-1: 부과기준일 = 검사일자
|
|
|
|
|
levyCrtrYmd = existingData.getInspYmd();
|
|
|
|
|
transferType = "이첩-1";
|
|
|
|
|
log.info("[이첩-1] 부과기준일 = 검사일자 = {}", levyCrtrYmd);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 자동차기본정보 API 호출 (부과기준일 기준)
|
|
|
|
|
log.info("[{}] 자동차기본정보 조회 - 차량번호: {}, 부과기준일: {}", transferType, vhclno, levyCrtrYmd);
|
|
|
|
|
|
|
|
|
|
NewBasicRequest request = createBasicRequest(vhclno, null, levyCrtrYmd);
|
|
|
|
|
NewBasicResponse response = apiService.getBasicInfo(request);
|
|
|
|
|
|
|
|
|
|
if (response == null || response.getRecord() == null || response.getRecord().isEmpty()) {
|
|
|
|
|
log.warn("[{}] 응답 없음 - 차량번호: {}", transferType, vhclno);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NewBasicResponse.Record record = response.getRecord().get(0);
|
|
|
|
|
String usgsrhldStdgCd = record.getUsgsrhldStdgCd(); // 사용본거지법정동코드
|
|
|
|
|
|
|
|
|
|
log.info("[{}] API 응답 - 사용본거지법정동코드: {}", transferType, usgsrhldStdgCd);
|
|
|
|
|
|
|
|
|
|
// 법정동코드 유효성 검사
|
|
|
|
|
if (usgsrhldStdgCd == null || usgsrhldStdgCd.length() < 4) {
|
|
|
|
|
log.debug("[{}] 법정동코드 없음 - 차량번호: {}", transferType, vhclno);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 세션에서 사용자 정보 조회
|
|
|
|
|
LoginUserVO userInfo = SessionUtil.getLoginUser();
|
|
|
|
|
if (userInfo == null || userInfo.getOrgCd() == null) {
|
|
|
|
|
log.debug("[{}] 사용자 정보 없음", transferType);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 법정동코드 앞 4자리 vs 사용자 조직코드 앞 4자리 비교
|
|
|
|
|
String legalDong4 = usgsrhldStdgCd.substring(0, 4);
|
|
|
|
|
String userOrgCd = userInfo.getOrgCd();
|
|
|
|
|
String userOrg4 = userOrgCd.length() >= 4 ? userOrgCd.substring(0, 4) : userOrgCd;
|
|
|
|
|
|
|
|
|
|
if (legalDong4.equals(userOrg4)) {
|
|
|
|
|
log.debug("[{}] 법정동코드 일치 - 차량번호: {}, 법정동: {}, 조직: {}",
|
|
|
|
|
transferType, vhclno, legalDong4, userOrg4);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.info("[{}] 법정동코드 불일치! 차량번호: {}, 법정동: {}, 조직: {}",
|
|
|
|
|
transferType, vhclno, legalDong4, userOrg4);
|
|
|
|
|
|
|
|
|
|
// 시군구 코드 및 시군구명 조회
|
|
|
|
|
String sggCd = usgsrhldStdgCd.length() >= 5 ? usgsrhldStdgCd.substring(0, 5) : usgsrhldStdgCd;
|
|
|
|
|
String sggNm = carFfnlgTrgtMapper.selectSggNmBySggCd(sggCd);
|
|
|
|
|
if (sggNm == null || sggNm.isEmpty()) {
|
|
|
|
|
log.warn("[{}] 시군구명 조회 실패 - 시군구코드: {}", transferType, sggCd);
|
|
|
|
|
sggNm = "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 비고 생성
|
|
|
|
|
String rmrk;
|
|
|
|
|
if ("이첩-1".equals(transferType)) {
|
|
|
|
|
rmrk = String.format("%s, 검사일사용본거지, [검사대상, 사용자 조직코드 앞 4자리: %s, 법정동명: %s]",
|
|
|
|
|
sggNm, userOrg4, sggNm);
|
|
|
|
|
} else {
|
|
|
|
|
rmrk = String.format("%s, 115일 도래지, [법정동코드: %s, 법정동명: %s]",
|
|
|
|
|
sggNm, legalDong4, sggNm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// DB 업데이트
|
|
|
|
|
existingData.setTaskPrcsSttsCd(TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_03_TRANSFER);
|
|
|
|
|
existingData.setTaskPrcsYmd(LocalDate.now().format(DATE_FORMATTER));
|
|
|
|
|
existingData.setCarBscMttrInqSggCd(sggCd);
|
|
|
|
|
existingData.setCarBscMttrInqSggNm(sggNm);
|
|
|
|
|
existingData.setRmrk(rmrk);
|
|
|
|
|
|
|
|
|
|
int updateCount = carFfnlgTrgtMapper.update(existingData);
|
|
|
|
|
if (updateCount == 0) {
|
|
|
|
|
throw new MessageException(String.format("[%s] 업데이트 실패: %s", transferType, vhclno));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.info("[{}] 처리 완료! 차량번호: {}, 시군구: {}({})", transferType, vhclno, sggNm, sggCd);
|
|
|
|
|
return TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_03_TRANSFER;
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.error("[이첩] 검증 중 오류 발생 - 차량번호: {}", vhclno, e);
|
|
|
|
|
throw new MessageException(String.format("[이첩] 검증 중 오류 발생 - 차량번호: %s", vhclno), e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 조건2: 향후 추가될 이첩 조건들 (예시)
|
|
|
|
|
// if (checkTransferCondition2_OtherReason(basicInfo, userId, vhclno)) {
|
|
|
|
|
// return processTransfer(existingData, basicInfo, vhclno, "다른 사유");
|
|
|
|
|
// }
|
|
|
|
|
// ========================================
|
|
|
|
|
// 헬퍼 메서드들
|
|
|
|
|
// ========================================
|
|
|
|
|
|
|
|
|
|
// 모든 이첩 조건에 해당하지 않음
|
|
|
|
|
log.debug("[이첩] 모든 조건 미충족. 차량번호: {}", vhclno);
|
|
|
|
|
return null;
|
|
|
|
|
/**
|
|
|
|
|
* 자동차기본정보 요청 객체 생성
|
|
|
|
|
*
|
|
|
|
|
* @param vhrno 차량번호 (null 가능)
|
|
|
|
|
* @param vin 차대번호 (null 가능)
|
|
|
|
|
* @param levyCrtrYmd 부과기준일
|
|
|
|
|
* @return NewBasicRequest
|
|
|
|
|
*/
|
|
|
|
|
private NewBasicRequest createBasicRequest(String vhrno, String vin, String levyCrtrYmd) {
|
|
|
|
|
NewBasicRequest request = new NewBasicRequest();
|
|
|
|
|
|
|
|
|
|
NewBasicRequest.Record record = new NewBasicRequest.Record();
|
|
|
|
|
record.setLevyCrtrYmd(levyCrtrYmd);
|
|
|
|
|
|
|
|
|
|
if (vhrno != null) {
|
|
|
|
|
record.setVhrno(vhrno);
|
|
|
|
|
record.setInqSeCd("3"); // 3: 자동차번호
|
|
|
|
|
} else if (vin != null) {
|
|
|
|
|
record.setVin(vin);
|
|
|
|
|
record.setInqSeCd("2"); // 2: 차대번호
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
request.setRecord(java.util.Arrays.asList(record));
|
|
|
|
|
return request;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 이첩 조건1: 법정동코드 불일치
|
|
|
|
|
* 사용본거지법정동코드 앞 4자리 != 사용자 조직코드 앞 4자리
|
|
|
|
|
* 자동차등록원부(갑) 요청 객체 생성
|
|
|
|
|
*
|
|
|
|
|
* @param vhrno 차량번호
|
|
|
|
|
* @param ownerNm 성명
|
|
|
|
|
* @param idecno 주민번호
|
|
|
|
|
* @param legalDongCd 법정동코드
|
|
|
|
|
* @return NewLedgerRequest
|
|
|
|
|
*/
|
|
|
|
|
private boolean checkTransferCondition1_LegalDongMismatch(OldBasicResponse.Record basicInfo, String userId, String vhclno) {
|
|
|
|
|
String useStrnghldLegaldongCode = basicInfo.getUseStrnghldLegaldongCode();
|
|
|
|
|
private NewLedgerRequest createLedgerRequest(String vhrno, String ownerNm, String idecno, String legalDongCd) {
|
|
|
|
|
NewLedgerRequest request = new NewLedgerRequest();
|
|
|
|
|
|
|
|
|
|
// 법정동코드 유효성 검사
|
|
|
|
|
if (useStrnghldLegaldongCode == null || useStrnghldLegaldongCode.length() < 4) {
|
|
|
|
|
log.debug("[이첩][조건1] 법정동코드 없음. 차량번호: {}", vhclno);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// 차량번호
|
|
|
|
|
request.setVhrno(vhrno);
|
|
|
|
|
|
|
|
|
|
// 사용자 정보 조회
|
|
|
|
|
SystemUserVO userInfo = userMapper.selectUser(userId);
|
|
|
|
|
if (userInfo == null || userInfo.getOrgCd() == null) {
|
|
|
|
|
log.debug("[이첩][조건1] 사용자 정보 없음. 사용자ID: {}", userId);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// 민원인 정보
|
|
|
|
|
request.setCvlprNm(ownerNm);
|
|
|
|
|
request.setCvlprIdecno(idecno);
|
|
|
|
|
request.setCvlprStdgCd(legalDongCd);
|
|
|
|
|
|
|
|
|
|
// 법정동코드 앞 4자리 vs 사용자 조직코드 앞 4자리 비교
|
|
|
|
|
String legalDong4 = useStrnghldLegaldongCode.substring(0, 4);
|
|
|
|
|
String userOrgCd = userInfo.getOrgCd();
|
|
|
|
|
String userOrg4 = userOrgCd.length() >= 4 ? userOrgCd.substring(0, 4) : userOrgCd;
|
|
|
|
|
// 개인정보공개 (1:소유자공개)
|
|
|
|
|
request.setPrvcRls("1");
|
|
|
|
|
|
|
|
|
|
if (legalDong4.equals(userOrg4)) {
|
|
|
|
|
log.debug("[이첩][조건1] 법정동코드 일치. 차량번호: {}, 법정동: {}, 조직: {}",
|
|
|
|
|
vhclno, legalDong4, userOrg4);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// 경로구분코드 (고정값 3)
|
|
|
|
|
request.setPathSeCd("3");
|
|
|
|
|
|
|
|
|
|
// 내역표시 (1:전체내역)
|
|
|
|
|
request.setDsctnIndct("1");
|
|
|
|
|
|
|
|
|
|
// 조회구분코드 (1:열람)
|
|
|
|
|
request.setInqSeCd("1");
|
|
|
|
|
|
|
|
|
|
log.info("[이첩][조건1] 법정동코드 불일치! 차량번호: {}, 법정동: {}, 조직: {}",
|
|
|
|
|
vhclno, legalDong4, userOrg4);
|
|
|
|
|
return true;
|
|
|
|
|
return request;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 이첩 처리 (공통 로직)
|
|
|
|
|
* 날짜가 범위 내에 있는지 확인
|
|
|
|
|
*
|
|
|
|
|
* @param targetDate 확인할 날짜
|
|
|
|
|
* @param startDate 시작일
|
|
|
|
|
* @param endDate 종료일
|
|
|
|
|
* @return 범위 내 여부
|
|
|
|
|
*/
|
|
|
|
|
private String processTransfer(CarFfnlgTrgtVO existingData, OldBasicResponse.Record basicInfo,
|
|
|
|
|
String vhclno, String reason) {
|
|
|
|
|
log.info("[이첩] 조건 충족! 차량번호: {}, 사유: {}", vhclno, reason);
|
|
|
|
|
|
|
|
|
|
// 시군구 코드 및 시군구명 조회
|
|
|
|
|
String useStrnghldLegaldongCode = basicInfo.getUseStrnghldLegaldongCode();
|
|
|
|
|
String sggCd = (useStrnghldLegaldongCode != null && useStrnghldLegaldongCode.length() >= 5)
|
|
|
|
|
? useStrnghldLegaldongCode.substring(0, 5)
|
|
|
|
|
: (useStrnghldLegaldongCode != null ? useStrnghldLegaldongCode : "");
|
|
|
|
|
|
|
|
|
|
String sggNm = carFfnlgTrgtMapper.selectSggNmBySggCd(sggCd);
|
|
|
|
|
if (sggNm == null || sggNm.isEmpty()) {
|
|
|
|
|
log.warn("[이첩] 시군구명 조회 실패. 시군구코드: {}", sggCd);
|
|
|
|
|
sggNm = "";
|
|
|
|
|
private boolean isDateBetween(String targetDate, String startDate, String endDate) {
|
|
|
|
|
if (targetDate == null || startDate == null || endDate == null) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// DB 업데이트
|
|
|
|
|
existingData.setTaskPrcsSttsCd(TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_03_TRANSFER); // 이첩
|
|
|
|
|
existingData.setTaskPrcsYmd(LocalDate.now().format(DATE_FORMATTER));
|
|
|
|
|
existingData.setCarBscMttrInqFlnm(null);
|
|
|
|
|
existingData.setCarBscMttrInqSggCd(sggCd); // 시군구 코드
|
|
|
|
|
existingData.setCarBscMttrInqSggNm(sggNm); // 시군구명
|
|
|
|
|
try {
|
|
|
|
|
LocalDate target = LocalDate.parse(targetDate, DATE_FORMATTER);
|
|
|
|
|
LocalDate start = LocalDate.parse(startDate, DATE_FORMATTER);
|
|
|
|
|
LocalDate end = LocalDate.parse(endDate, DATE_FORMATTER);
|
|
|
|
|
|
|
|
|
|
int updateCount = carFfnlgTrgtMapper.update(existingData);
|
|
|
|
|
if (updateCount == 0) {
|
|
|
|
|
throw new MessageException(String.format("[이첩] 업데이트 실패: %s", vhclno));
|
|
|
|
|
return !target.isBefore(start) && !target.isAfter(end);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.error("날짜 비교 중 오류 발생 - target: {}, start: {}, end: {}", targetDate, startDate, endDate, e);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.info("[이첩] 처리 완료! 차량번호: {}, 시군구: {}({}), 사유: {}", vhclno, sggNm, sggCd, reason);
|
|
|
|
|
return TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_03_TRANSFER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 3. 내사종결 체크 (예시 - 향후 추가)
|
|
|
|
|
*
|
|
|
|
|
* <p>조건: 차량이 말소된 경우 등</p>
|
|
|
|
|
* <p>처리: TASK_PRCS_STTS_CD = 04</p>
|
|
|
|
|
* 상품용 비고 생성
|
|
|
|
|
*
|
|
|
|
|
* @return 04 (적용됨) 또는 null (미적용)
|
|
|
|
|
* @param step1Record Step 1 API 응답 (검사일 기준)
|
|
|
|
|
* @param step2Record Step 2 API 응답 (오늘 기준)
|
|
|
|
|
* @param ledgerRecord 조건에 걸린 갑부 레코드
|
|
|
|
|
* @param vldPrdExpryYmd 유효기간만료일
|
|
|
|
|
* @param inspEndYmd 검사종료일자
|
|
|
|
|
* @return 비고 문자열
|
|
|
|
|
*/
|
|
|
|
|
@SuppressWarnings("unused")
|
|
|
|
|
private String checkInvestigationClosed(CarFfnlgTrgtVO existingData, OldBasicResponse.Record basicInfo) {
|
|
|
|
|
String vhclno = existingData.getVhclno();
|
|
|
|
|
String ersrRegistSeCode = basicInfo.getErsrRegistSeCode(); // 말소등록구분코드
|
|
|
|
|
|
|
|
|
|
// 조건 체크: 말소된 차량인지
|
|
|
|
|
if (ersrRegistSeCode == null || ersrRegistSeCode.isEmpty()) {
|
|
|
|
|
log.debug("[내사종결] 조건 미충족. 차량번호: {}", vhclno);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.info("[내사종결] 조건 충족! 차량번호: {}, 말소구분: {}", vhclno, ersrRegistSeCode);
|
|
|
|
|
private String buildProductUseRemark(
|
|
|
|
|
NewBasicResponse.Record step1Record,
|
|
|
|
|
NewBasicResponse.Record step2Record,
|
|
|
|
|
NewLedgerResponse.Record ledgerRecord,
|
|
|
|
|
String vldPrdExpryYmd,
|
|
|
|
|
String inspEndYmd) {
|
|
|
|
|
|
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
|
sb.append("[상품용]\n");
|
|
|
|
|
|
|
|
|
|
// 1. 검사일 기준 정보
|
|
|
|
|
sb.append("■ 검사일 기준 차량정보\n");
|
|
|
|
|
sb.append(" - 차대번호: ").append(nvl(step1Record.getVin())).append("\n");
|
|
|
|
|
sb.append(" - 소유자명: ").append(nvl(step1Record.getRprsOwnrNm())).append("\n");
|
|
|
|
|
|
|
|
|
|
// 2. 현재(오늘) 기준 정보
|
|
|
|
|
sb.append("\n■ 현재 차량정보\n");
|
|
|
|
|
sb.append(" - 차량번호: ").append(nvl(step2Record.getVhrno())).append("\n");
|
|
|
|
|
sb.append(" - 소유자명: ").append(nvl(step2Record.getRprsOwnrNm())).append("\n");
|
|
|
|
|
sb.append(" - 주민번호: ").append(maskIdecno(step2Record.getRprsvOwnrIdecno())).append("\n");
|
|
|
|
|
sb.append(" - 법정동코드: ").append(nvl(step2Record.getUsgsrhldStdgCd())).append("\n");
|
|
|
|
|
|
|
|
|
|
// 3. 갑부 상세 정보 (명의이전 이력)
|
|
|
|
|
sb.append("\n■ 갑부 상세 (명의이전 이력)\n");
|
|
|
|
|
sb.append(" - 변경일자: ").append(formatDateWithHyphen(ledgerRecord.getChgYmd())).append("\n");
|
|
|
|
|
sb.append(" - 변경업무코드: ").append(nvl(ledgerRecord.getChgTaskSeCd())).append("\n");
|
|
|
|
|
sb.append(" - 변경업무명: ").append(nvl(ledgerRecord.getChgTaskSeNm())).append("\n");
|
|
|
|
|
sb.append(" - 접수번호: ").append(nvl(ledgerRecord.getAplyRcptNo())).append("\n");
|
|
|
|
|
sb.append(" - 주번호: ").append(nvl(ledgerRecord.getMainNo())).append("\n");
|
|
|
|
|
sb.append(" - 부번호: ").append(nvl(ledgerRecord.getSno())).append("\n");
|
|
|
|
|
sb.append(" - 사항란: ").append(nvl(ledgerRecord.getSpcablMttr())).append("\n");
|
|
|
|
|
sb.append(" - 세대주명: ").append(nvl(ledgerRecord.getHshldrNm())).append("\n");
|
|
|
|
|
|
|
|
|
|
// 4. 비교 기간
|
|
|
|
|
sb.append("\n■ 비교 기간\n");
|
|
|
|
|
sb.append(" - 유효기간만료일: ").append(formatDateWithHyphen(vldPrdExpryYmd)).append("\n");
|
|
|
|
|
sb.append(" - 검사종료일자: ").append(formatDateWithHyphen(inspEndYmd)).append("\n");
|
|
|
|
|
sb.append(" - 판정: 명의이전일자가 기간 내 존재");
|
|
|
|
|
|
|
|
|
|
return sb.toString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// DB 업데이트
|
|
|
|
|
existingData.setTaskPrcsSttsCd(TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_04_INVESTIGATION_CLOSED); // 내사종결
|
|
|
|
|
existingData.setTaskPrcsYmd(LocalDate.now().format(DATE_FORMATTER));
|
|
|
|
|
// 필요한 추가 필드 설정
|
|
|
|
|
/**
|
|
|
|
|
* null 안전 처리
|
|
|
|
|
*/
|
|
|
|
|
private String nvl(String value) {
|
|
|
|
|
return value != null ? value : "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int updateCount = carFfnlgTrgtMapper.update(existingData);
|
|
|
|
|
if (updateCount == 0) {
|
|
|
|
|
throw new MessageException(String.format("[내사종결] 업데이트 실패: %s", vhclno));
|
|
|
|
|
/**
|
|
|
|
|
* 주민번호 마스킹 (뒤 7자리 마스킹)
|
|
|
|
|
*/
|
|
|
|
|
private String maskIdecno(String idecno) {
|
|
|
|
|
if (idecno == null || idecno.length() < 7) {
|
|
|
|
|
return idecno != null ? idecno : "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.info("[내사종결] 처리 완료! 차량번호: {}", vhclno);
|
|
|
|
|
return TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_04_INVESTIGATION_CLOSED;
|
|
|
|
|
String front = idecno.substring(0, Math.min(6, idecno.length()));
|
|
|
|
|
return front + "*******";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 날짜 형식 변환 (YYYYMMDD → YYYY-MM-DD)
|
|
|
|
|
*/
|
|
|
|
|
private String formatDateWithHyphen(String date) {
|
|
|
|
|
if (date == null || date.isEmpty() || date.length() != 8) {
|
|
|
|
|
return date != null ? date : "";
|
|
|
|
|
}
|
|
|
|
|
return date.substring(0, 4) + "-" + date.substring(4, 6) + "-" + date.substring(6, 8);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|