국유인 스케줄러 분리

This commit is contained in:
2026-02-02 15:40:17 +09:00
parent 9fb4a25955
commit 9734a5acb2
17 changed files with 1775 additions and 172 deletions

View File

@@ -1,172 +0,0 @@
package com.kamco.cd.kamcoback.scheduler.service;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectContDto;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectContDto.ResultContDto;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.LearnKeyDto;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.ResultDto;
import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.GeomUidDto;
import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinStatus;
import com.kamco.cd.kamcoback.gukyuin.service.GukYuinApiService;
import com.kamco.cd.kamcoback.postgres.core.GukYuinJobCoreService;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
@Log4j2
@Service
@RequiredArgsConstructor
public class GukYuinApiJobService {
private final GukYuinApiService gukYuinApiService;
private final GukYuinJobCoreService gukYuinJobCoreService;
@Value("${spring.profiles.active}")
private String profile;
/**
* 실행중인 profile
*
* @return
*/
private boolean isLocalProfile() {
return "local".equalsIgnoreCase(profile);
}
/** 국유인 연동 후, 100% 되었는지 확인하는 스케줄링 매 10분마다 호출 */
@Scheduled(cron = "0 0/10 * * * *")
public void findGukYuinMastCompleteYn() {
if (isLocalProfile()) {
return;
}
List<LearnKeyDto> list =
gukYuinJobCoreService.findGukyuinApplyStatusUidList(
List.of(GukYuinStatus.IN_PROGRESS.getId()));
if (list.isEmpty()) {
return;
}
for (LearnKeyDto dto : list) {
try {
ResultDto result = gukYuinApiService.detail(dto.getChnDtctMstId());
if (result == null || result.getResult() == null || result.getResult().isEmpty()) {
log.warn("[GUKYUIN] empty result chnDtctMstId={}", dto.getChnDtctMstId());
continue;
}
ChngDetectMastDto.Basic basic = result.getResult().get(0);
Integer progress =
basic.getExcnPgrt() == null ? null : Integer.parseInt(basic.getExcnPgrt().trim());
if (progress != null && progress == 100) {
gukYuinJobCoreService.updateGukYuinApplyStateComplete(
dto.getId(), GukYuinStatus.GUK_COMPLETED);
}
} catch (Exception e) {
log.error("[GUKYUIN] failed uid={}", dto.getChnDtctMstId(), e);
}
}
}
/** 국유인 등록 완료 후, 탐지객체 조회해서 PNU 업데이트 하는 스케줄링 하루 1번 새벽 1시에 실행 */
@Scheduled(cron = "0 0 1 * * *")
public void findGukYuinContListPnuUpdate() {
if (isLocalProfile()) {
return;
}
List<LearnKeyDto> list =
gukYuinJobCoreService.findGukyuinApplyStatusUidList(
List.of(GukYuinStatus.GUK_COMPLETED.getId(), GukYuinStatus.PNU_FAILED.getId()));
if (list.isEmpty()) {
return;
}
for (LearnKeyDto dto : list) {
try {
long succCnt = processUid(dto.getChnDtctMstId(), dto.getUid());
if (succCnt > 0) {
gukYuinJobCoreService.updateGukYuinApplyStateComplete(
dto.getId(), GukYuinStatus.PNU_COMPLETED);
} else {
gukYuinJobCoreService.updateGukYuinApplyStateComplete(
dto.getId(), GukYuinStatus.PNU_FAILED);
}
} catch (Exception e) {
log.error("[GUKYUIN] failed uid={}", dto.getUid(), e);
gukYuinJobCoreService.updateGukYuinApplyStateComplete(
dto.getId(), GukYuinStatus.PNU_FAILED);
}
}
}
private long processUid(String chnDtctMstId, String uid) {
long succCnt = 0;
ResultDto result = gukYuinApiService.detail(chnDtctMstId);
if (result == null || result.getResult() == null || result.getResult().isEmpty()) {
return succCnt;
}
ChngDetectMastDto.Basic basic = result.getResult().get(0);
String chnDtctCnt = basic.getChnDtctCnt();
if (chnDtctCnt == null || chnDtctCnt.isEmpty()) {
return succCnt;
}
// page 계산
int pageSize = 100;
int totalCount = Integer.parseInt(chnDtctCnt);
int totalPages = (totalCount + pageSize - 1) / pageSize;
for (int page = 0; page < totalPages; page++) {
succCnt += processPage(uid, page, pageSize);
}
return succCnt;
}
private long processPage(String uid, int page, int pageSize) {
long result = 0;
ResultContDto cont = gukYuinApiService.findChnContList(uid, page, pageSize);
if (cont == null || cont.getResult().isEmpty()) {
return result; // 외부 API 이상 방어
}
// pnuList 업데이트
for (ChngDetectContDto.ContBasic contBasic : cont.getResult()) {
if (contBasic.getPnuList() == null || contBasic.getChnDtctObjtId() == null) {
return 0;
}
long upsertCnt =
gukYuinJobCoreService.upsertMapSheetDataAnalGeomPnu(
contBasic.getChnDtctObjtId(), contBasic.getPnuList());
result += upsertCnt;
}
return result;
}
/** 어제 라벨링 검수 완료된 것 -> 국유인에 전송 */
@Scheduled(cron = "0 0 1 * * *")
public void findLabelingCompleteSend() {
List<GeomUidDto> list = gukYuinJobCoreService.findYesterdayLabelingCompleteList();
if (list.isEmpty()) {
return;
}
for (GeomUidDto dto : list) {
gukYuinApiService.updateChnDtctObjtLabelingYn(dto.getResultUid(), "Y");
// inference_geom 에 label_send_dttm 업데이트 하기
gukYuinJobCoreService.updateAnalDataInferenceGeomSendDttm(dto.getGeoUid());
}
}
}

View File

@@ -0,0 +1,125 @@
package com.kamco.cd.kamcoback.scheduler.service;
import com.kamco.cd.kamcoback.common.utils.NetUtils;
import com.kamco.cd.kamcoback.common.utils.UserUtil;
import com.kamco.cd.kamcoback.config.api.ApiLogFunction;
import com.kamco.cd.kamcoback.config.resttemplate.ExternalHttpClient;
import com.kamco.cd.kamcoback.config.resttemplate.ExternalHttpClient.ExternalCallResult;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectContDto;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectContDto.ResultPnuDto;
import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.GeomUidDto;
import com.kamco.cd.kamcoback.log.dto.EventStatus;
import com.kamco.cd.kamcoback.log.dto.EventType;
import com.kamco.cd.kamcoback.postgres.core.GukYuinLabelJobCoreService;
import com.kamco.cd.kamcoback.postgres.entity.AuditLogEntity;
import com.kamco.cd.kamcoback.postgres.repository.log.AuditLogRepository;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Log4j2
@Service
@RequiredArgsConstructor
public class GukYuinApiLabelJobService {
private final GukYuinLabelJobCoreService gukYuinLabelJobCoreService;
private final ExternalHttpClient externalHttpClient;
private final NetUtils netUtils = new NetUtils();
private final AuditLogRepository auditLogRepository;
private final UserUtil userUtil;
@Value("${spring.profiles.active}")
private String profile;
@Value("${gukyuin.url}")
private String gukyuinUrl;
@Value("${gukyuin.cdi}")
private String gukyuinCdiUrl;
/**
* 실행중인 profile
*
* @return
*/
private boolean isLocalProfile() {
return "local".equalsIgnoreCase(profile);
}
/**
* 어제 라벨링 검수 완료된 것 -> 국유인에 전송
*/
@Scheduled(cron = "0 0 1 * * *")
public void findLabelingCompleteSend() {
if (isLocalProfile()) {
return;
}
List<GeomUidDto> list = gukYuinLabelJobCoreService.findYesterdayLabelingCompleteList();
if (list.isEmpty()) {
return;
}
for (GeomUidDto gto : list) {
String url = gukyuinCdiUrl + "/rlb/objt/" + gto.getResultUid() + "/lbl/" + "Y";
ExternalCallResult<ResultPnuDto> result =
externalHttpClient.call(
url,
HttpMethod.POST,
null,
netUtils.jsonHeaders(),
ChngDetectContDto.ResultPnuDto.class);
ChngDetectContDto.ResultPnuDto dto = result.body();
this.insertGukyuinAuditLog(
EventType.MODIFIED.getId(),
netUtils.getLocalIP(),
userUtil.getId(),
url.replace(gukyuinUrl, ""),
null,
result.body().getSuccess());
// inference_geom 에 label_send_dttm 업데이트 하기
gukYuinLabelJobCoreService.updateAnalDataInferenceGeomSendDttm(gto.getGeoUid());
}
}
@Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = false)
public void insertGukyuinAuditLog(
String actionType,
String myIp,
Long userUid,
String requestUri,
Object requestBody,
boolean successFail) {
try {
AuditLogEntity log =
new AuditLogEntity(
userUid,
EventType.fromName(actionType),
successFail ? EventStatus.SUCCESS : EventStatus.FAILED,
"GUKYUIN", // 메뉴도 국유인으로 하나 따기
myIp,
requestUri,
requestBody == null ? null : ApiLogFunction.cutRequestBody(requestBody.toString()),
null,
null,
null);
auditLogRepository.save(log);
} catch (Exception e) {
log.error(e.getMessage());
throw e;
}
}
}

View File

@@ -0,0 +1,225 @@
package com.kamco.cd.kamcoback.scheduler.service;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.kamco.cd.kamcoback.common.utils.NetUtils;
import com.kamco.cd.kamcoback.common.utils.UserUtil;
import com.kamco.cd.kamcoback.config.api.ApiLogFunction;
import com.kamco.cd.kamcoback.config.resttemplate.ExternalHttpClient;
import com.kamco.cd.kamcoback.config.resttemplate.ExternalHttpClient.ExternalCallResult;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectContDto;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectContDto.ContBasic;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectContDto.ResultContDto;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.LearnKeyDto;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.ResultDto;
import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinStatus;
import com.kamco.cd.kamcoback.gukyuin.service.GukYuinApiService;
import com.kamco.cd.kamcoback.log.dto.EventStatus;
import com.kamco.cd.kamcoback.log.dto.EventType;
import com.kamco.cd.kamcoback.postgres.core.GukYuinPnuJobCoreService;
import com.kamco.cd.kamcoback.postgres.entity.AuditLogEntity;
import com.kamco.cd.kamcoback.postgres.repository.log.AuditLogRepository;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Log4j2
@Service
@RequiredArgsConstructor
public class GukYuinApiPnuJobService {
private final GukYuinApiService gukYuinApiService;
private final GukYuinPnuJobCoreService gukYuinPnuJobCoreService;
private final ExternalHttpClient externalHttpClient;
private final NetUtils netUtils = new NetUtils();
private final AuditLogRepository auditLogRepository;
private final UserUtil userUtil;
private final ObjectMapper objectMapper;
@Value("${spring.profiles.active}")
private String profile;
@Value("${gukyuin.url}")
private String gukyuinUrl;
@Value("${gukyuin.cdi}")
private String gukyuinCdiUrl;
/**
* 실행중인 profile
*
* @return
*/
private boolean isLocalProfile() {
return "local".equalsIgnoreCase(profile);
}
/** 국유인 등록 완료 후, 탐지객체 조회해서 PNU 업데이트 하는 스케줄링 하루 1번 새벽 1시에 실행 */
@Scheduled(cron = "0 0 1 * * *")
public void findGukYuinContListPnuUpdate() {
if (isLocalProfile()) {
return;
}
List<LearnKeyDto> list =
gukYuinPnuJobCoreService.findGukyuinApplyStatusUidList(
List.of(GukYuinStatus.GUK_COMPLETED.getId(), GukYuinStatus.PNU_FAILED.getId()));
if (list.isEmpty()) {
return;
}
for (LearnKeyDto dto : list) {
try {
long succCnt = processUid(dto.getChnDtctMstId(), dto.getUid());
if (succCnt > 0) {
gukYuinPnuJobCoreService.updateGukYuinApplyStateComplete(
dto.getId(), GukYuinStatus.PNU_COMPLETED);
} else {
gukYuinPnuJobCoreService.updateGukYuinApplyStateComplete(
dto.getId(), GukYuinStatus.PNU_FAILED);
}
} catch (Exception e) {
log.error("[GUKYUIN] failed uid={}", dto.getUid(), e);
gukYuinPnuJobCoreService.updateGukYuinApplyStateComplete(
dto.getId(), GukYuinStatus.PNU_FAILED);
}
}
}
private long processUid(String chnDtctMstId, String uid) {
long succCnt = 0;
String url = gukyuinCdiUrl + "/chn/mast/list/" + chnDtctMstId;
ExternalCallResult<ResultDto> response =
externalHttpClient.call(
url, HttpMethod.GET, null, netUtils.jsonHeaders(), ChngDetectMastDto.ResultDto.class);
this.insertGukyuinAuditLog(
EventType.DETAIL.getId(),
netUtils.getLocalIP(),
userUtil.getId(),
url.replace(gukyuinUrl, ""),
null,
response.body().getSuccess());
ResultDto result = response.body();
if (result == null || result.getResult() == null || result.getResult().isEmpty()) {
return succCnt;
}
ChngDetectMastDto.Basic basic = result.getResult().get(0);
String chnDtctCnt = basic.getChnDtctCnt();
if (chnDtctCnt == null || chnDtctCnt.isEmpty()) {
return succCnt;
}
// page 계산
int pageSize = 100;
int totalCount = Integer.parseInt(chnDtctCnt);
int totalPages = (totalCount + pageSize - 1) / pageSize;
for (int page = 0; page < totalPages; page++) {
succCnt += processPage(uid, page, pageSize);
}
return succCnt;
}
private long processPage(String uid, int page, int pageSize) {
long result = 0;
String url =
gukyuinCdiUrl + "/chn/cont/" + uid + "?pageIndex=" + page + "&pageSize=" + pageSize;
ExternalCallResult<ChngDetectContDto.ResultContDto> response =
externalHttpClient.call(
url,
HttpMethod.GET,
null,
netUtils.jsonHeaders(),
ChngDetectContDto.ResultContDto.class);
List<ContBasic> contList = response.body().getResult();
if (contList == null || contList.isEmpty()) {
return 0;
}
for (ContBasic cont : contList) {
String[] pnuList = cont.getPnuList();
long pnuCnt = pnuList == null ? 0 : pnuList.length;
if (cont.getChnDtctObjtId() != null) {
gukYuinPnuJobCoreService.updateInferenceGeomDataPnuCnt(cont.getChnDtctObjtId(), pnuCnt);
if (pnuCnt > 0) {
Long geoUid =
gukYuinPnuJobCoreService.findMapSheetAnalDataInferenceGeomUid(
cont.getChnDtctObjtId());
gukYuinPnuJobCoreService.insertGeoUidPnuData(geoUid, pnuList);
}
}
}
this.insertGukyuinAuditLog(
EventType.LIST.getId(),
netUtils.getLocalIP(),
userUtil.getId(),
url.replace(gukyuinUrl, ""),
null,
response.body().getSuccess());
ResultContDto cont = response.body();
if (cont == null || cont.getResult().isEmpty()) {
return result; // 외부 API 이상 방어
}
// pnuList 업데이트
for (ChngDetectContDto.ContBasic contBasic : cont.getResult()) {
if (contBasic.getPnuList() == null || contBasic.getChnDtctObjtId() == null) {
return 0;
}
long upsertCnt =
gukYuinPnuJobCoreService.upsertMapSheetDataAnalGeomPnu(
contBasic.getChnDtctObjtId(), contBasic.getPnuList());
result += upsertCnt;
}
return result;
}
@Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = false)
public void insertGukyuinAuditLog(
String actionType,
String myIp,
Long userUid,
String requestUri,
Object requestBody,
boolean successFail) {
try {
AuditLogEntity log =
new AuditLogEntity(
userUid,
EventType.fromName(actionType),
successFail ? EventStatus.SUCCESS : EventStatus.FAILED,
"GUKYUIN", // 메뉴도 국유인으로 하나 따기
myIp,
requestUri,
requestBody == null ? null : ApiLogFunction.cutRequestBody(requestBody.toString()),
null,
null,
null);
auditLogRepository.save(log);
} catch (Exception e) {
log.error(e.getMessage());
throw e;
}
}
}

View File

@@ -0,0 +1,142 @@
package com.kamco.cd.kamcoback.scheduler.service;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.kamco.cd.kamcoback.common.utils.NetUtils;
import com.kamco.cd.kamcoback.common.utils.UserUtil;
import com.kamco.cd.kamcoback.config.api.ApiLogFunction;
import com.kamco.cd.kamcoback.config.resttemplate.ExternalHttpClient;
import com.kamco.cd.kamcoback.config.resttemplate.ExternalHttpClient.ExternalCallResult;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.LearnKeyDto;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.ResultDto;
import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinStatus;
import com.kamco.cd.kamcoback.log.dto.EventStatus;
import com.kamco.cd.kamcoback.log.dto.EventType;
import com.kamco.cd.kamcoback.postgres.core.GukYuinJobCoreService;
import com.kamco.cd.kamcoback.postgres.entity.AuditLogEntity;
import com.kamco.cd.kamcoback.postgres.repository.log.AuditLogRepository;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Log4j2
@Service
@RequiredArgsConstructor
public class GukYuinApiStatusJobService {
private final ExternalHttpClient externalHttpClient;
private final NetUtils netUtils = new NetUtils();
private final GukYuinJobCoreService gukYuinJobCoreService;
private final AuditLogRepository auditLogRepository;
private final UserUtil userUtil;
private final ObjectMapper objectMapper;
@Value("${spring.profiles.active}")
private String profile;
@Value("${gukyuin.url}")
private String gukyuinUrl;
@Value("${gukyuin.cdi}")
private String gukyuinCdiUrl;
/**
* 실행중인 profile
*
* @return
*/
private boolean isLocalProfile() {
return "local".equalsIgnoreCase(profile);
}
/** 국유인 연동 후, 100% 되었는지 확인하는 스케줄링 매 10분마다 호출 */
@Scheduled(cron = "0 0/10 * * * *")
public void findGukYuinMastCompleteYn() {
if (isLocalProfile()) {
return;
}
List<LearnKeyDto> list =
gukYuinJobCoreService.findGukyuinApplyStatusUidList(
List.of(GukYuinStatus.IN_PROGRESS.getId()));
if (list.isEmpty()) {
return;
}
for (LearnKeyDto dto : list) {
try {
String url = gukyuinCdiUrl + "/chn/mast/list/" + dto.getChnDtctMstId();
ExternalCallResult<ResultDto> response =
externalHttpClient.call(
url,
HttpMethod.GET,
null,
netUtils.jsonHeaders(),
ChngDetectMastDto.ResultDto.class);
this.insertGukyuinAuditLog(
EventType.DETAIL.getId(),
netUtils.getLocalIP(),
userUtil.getId(),
url.replace(gukyuinUrl, ""),
null,
response.body().getSuccess());
ResultDto result = response.body();
if (result == null || result.getResult() == null || result.getResult().isEmpty()) {
log.warn("[GUKYUIN] empty result chnDtctMstId={}", dto.getChnDtctMstId());
continue;
}
ChngDetectMastDto.Basic basic = result.getResult().get(0);
Integer progress =
basic.getExcnPgrt() == null ? null : Integer.parseInt(basic.getExcnPgrt().trim());
if (progress != null && progress == 100) {
gukYuinJobCoreService.updateGukYuinApplyStateComplete(
dto.getId(), GukYuinStatus.GUK_COMPLETED);
}
} catch (Exception e) {
log.error("[GUKYUIN] failed uid={}", dto.getChnDtctMstId(), e);
}
}
}
@Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = false)
public void insertGukyuinAuditLog(
String actionType,
String myIp,
Long userUid,
String requestUri,
Object requestBody,
boolean successFail) {
try {
AuditLogEntity log =
new AuditLogEntity(
userUid,
EventType.fromName(actionType),
successFail ? EventStatus.SUCCESS : EventStatus.FAILED,
"GUKYUIN", // 메뉴도 국유인으로 하나 따기
myIp,
requestUri,
requestBody == null ? null : ApiLogFunction.cutRequestBody(requestBody.toString()),
null,
null,
null);
auditLogRepository.save(log);
} catch (Exception e) {
log.error(e.getMessage());
throw e;
}
}
}

View File

@@ -0,0 +1,144 @@
package com.kamco.cd.kamcoback.scheduler.service;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.kamco.cd.kamcoback.common.utils.NetUtils;
import com.kamco.cd.kamcoback.common.utils.UserUtil;
import com.kamco.cd.kamcoback.config.api.ApiLogFunction;
import com.kamco.cd.kamcoback.config.resttemplate.ExternalHttpClient;
import com.kamco.cd.kamcoback.config.resttemplate.ExternalHttpClient.ExternalCallResult;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.LearnKeyDto;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.ResultDto;
import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinStatus;
import com.kamco.cd.kamcoback.log.dto.EventStatus;
import com.kamco.cd.kamcoback.log.dto.EventType;
import com.kamco.cd.kamcoback.postgres.core.GukYuinJobCoreService;
import com.kamco.cd.kamcoback.postgres.entity.AuditLogEntity;
import com.kamco.cd.kamcoback.postgres.repository.log.AuditLogRepository;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Log4j2
@Service
@RequiredArgsConstructor
public class GukYuinApiStbltJobService {
private final ExternalHttpClient externalHttpClient;
private final NetUtils netUtils = new NetUtils();
private final GukYuinJobCoreService gukYuinStbltJobCoreService;
private final AuditLogRepository auditLogRepository;
private final UserUtil userUtil;
private final ObjectMapper objectMapper;
@Value("${spring.profiles.active}")
private String profile;
@Value("${gukyuin.url}")
private String gukyuinUrl;
@Value("${gukyuin.cdi}")
private String gukyuinCdiUrl;
/**
* 실행중인 profile
*
* @return
*/
private boolean isLocalProfile() {
return "local".equalsIgnoreCase(profile);
}
/**
* 국유인 연동 후, 100% 되었는지 확인하는 스케줄링 매 10분마다 호출
*/
@Scheduled(cron = "0 0/10 * * * *")
public void findGukYuinMastCompleteYn() {
if (isLocalProfile()) {
return;
}
List<LearnKeyDto> list =
gukYuinStbltJobCoreService.findGukyuinApplyStatusUidList(
List.of(GukYuinStatus.IN_PROGRESS.getId()));
if (list.isEmpty()) {
return;
}
for (LearnKeyDto dto : list) {
try {
String url = gukyuinCdiUrl + "/chn/mast/list/" + dto.getChnDtctMstId();
ExternalCallResult<ResultDto> response =
externalHttpClient.call(
url,
HttpMethod.GET,
null,
netUtils.jsonHeaders(),
ChngDetectMastDto.ResultDto.class);
this.insertGukyuinAuditLog(
EventType.DETAIL.getId(),
netUtils.getLocalIP(),
userUtil.getId(),
url.replace(gukyuinUrl, ""),
null,
response.body().getSuccess());
ResultDto result = response.body();
if (result == null || result.getResult() == null || result.getResult().isEmpty()) {
log.warn("[GUKYUIN] empty result chnDtctMstId={}", dto.getChnDtctMstId());
continue;
}
ChngDetectMastDto.Basic basic = result.getResult().get(0);
Integer progress =
basic.getExcnPgrt() == null ? null : Integer.parseInt(basic.getExcnPgrt().trim());
if (progress != null && progress == 100) {
gukYuinStbltJobCoreService.updateGukYuinApplyStateComplete(
dto.getId(), GukYuinStatus.GUK_COMPLETED);
}
} catch (Exception e) {
log.error("[GUKYUIN] failed uid={}", dto.getChnDtctMstId(), e);
}
}
}
@Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = false)
public void insertGukyuinAuditLog(
String actionType,
String myIp,
Long userUid,
String requestUri,
Object requestBody,
boolean successFail) {
try {
AuditLogEntity log =
new AuditLogEntity(
userUid,
EventType.fromName(actionType),
successFail ? EventStatus.SUCCESS : EventStatus.FAILED,
"GUKYUIN", // 메뉴도 국유인으로 하나 따기
myIp,
requestUri,
requestBody == null ? null : ApiLogFunction.cutRequestBody(requestBody.toString()),
null,
null,
null);
auditLogRepository.save(log);
} catch (Exception e) {
log.error(e.getMessage());
throw e;
}
}
}