diff --git a/src/main/java/com/kamco/cd/kamcoback/gukyuin/GukYuinApiController.java b/src/main/java/com/kamco/cd/kamcoback/gukyuin/GukYuinApiController.java index 2217b939..dd6efcf7 100644 --- a/src/main/java/com/kamco/cd/kamcoback/gukyuin/GukYuinApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/gukyuin/GukYuinApiController.java @@ -1,6 +1,7 @@ package com.kamco.cd.kamcoback.gukyuin; import com.kamco.cd.kamcoback.config.api.ApiResponseDto; +import com.kamco.cd.kamcoback.config.api.ApiResponseDto.ResponseObj; import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectContDto; import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto; import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.ChnDetectMastReqDto; @@ -51,7 +52,7 @@ public class GukYuinApiController { @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) }) @PostMapping("/chn/mast/regist") - public ApiResponseDto regist( + public ApiResponseDto regist( @RequestBody @Valid ChngDetectMastDto.ChnDetectMastReqDto chnDetectMastReq) { return ApiResponseDto.ok(gukYuinApiService.regist(chnDetectMastReq)); } @@ -133,9 +134,9 @@ public class GukYuinApiController { @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) }) - public ApiResponseDto selectChangeDetectionList( + public ApiResponseDto selectChangeDetectionDetail( @PathVariable String chnDtctMstId) { - return ApiResponseDto.ok(gukYuinApiService.list(chnDtctMstId)); + return ApiResponseDto.ok(gukYuinApiService.detail(chnDtctMstId)); } @Operation(summary = "국유in연동 가능여부 확인", description = "국유in연동 가능여부 확인") @@ -239,4 +240,13 @@ public class GukYuinApiController { @PathVariable String chnDtctObjtId, @PathVariable String lblYn) { return ApiResponseDto.ok(gukYuinApiService.updateChnDtctObjtLabelingYn(chnDtctObjtId, lblYn)); } + + @Operation(summary = "국유in연동 등록", description = "국유in연동 등록") + @PostMapping("/mast/reg/{uuid}") + public ApiResponseDto connectChnMastRegist( + @Parameter(description = "uuid", example = "7a593d0e-76a8-4b50-8978-9af1fbe871af") + @PathVariable + UUID uuid) { + return ApiResponseDto.ok(gukYuinApiService.connectChnMastRegist(uuid)); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/ChngDetectMastDto.java b/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/ChngDetectMastDto.java index 35d1febe..772448c7 100644 --- a/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/ChngDetectMastDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/ChngDetectMastDto.java @@ -66,13 +66,30 @@ public class ChngDetectMastDto { @AllArgsConstructor public static class ChnDetectMastReqDto { - private String cprsYr; // 비교년도 2023 - private String crtrYr; // 기준년도 2024 - private String chnDtctSno; // 차수 (1 | 2 | ...) - private String chnDtctId; // 탐지아이디. UUID를 기반으로 '-'를 제거하고 대문자/숫자로 구성 - private String pathNm; // 탐지결과 절대경로명 /kamco_nas/export/{chnDtctId} - private String reqEpno; // 사원번호 - private String reqIp; // 사원아이피 + @Schema(description = "비교년도", example = "2023") + private String cprsYr; + + @Schema(description = "기준년도", example = "2024") + private String crtrYr; + + @Schema(description = "차수", example = "1") + private String chnDtctSno; + + @Schema( + description = "탐지아이디, UUID를 기반으로 '-'를 제거하고 대문자/숫자로 구성", + example = "D5F192EC76D34F6592035BE63A84F591") + private String chnDtctId; + + @Schema( + description = "탐지결과 절대경로명 /kamco_nas/export/{chnDtctId}", + example = "/kamco-nfs/dataset/export/D5F192EC76D34F6592035BE63A84F591") + private String pathNm; + + @Schema(description = "사원번호", example = "123456") + private String reqEpno; + + @Schema(description = "사원아이피", example = "127.0.0.1") + private String reqIp; } @Getter @@ -158,4 +175,29 @@ public class ChngDetectMastDto { private List result; private Boolean success; } + + @Schema(name = "RegistResDto", description = "reg 등록 후 리턴 형태") + @Getter + @Setter + @NoArgsConstructor + @AllArgsConstructor + public static class RegistResDto { + + private Integer code; + private String message; + private Basic result; + private Boolean success; + } + + @Schema(name = "LearnKeyDto", description = "learn 엔티티 key 정보") + @Getter + @Setter + @NoArgsConstructor + @AllArgsConstructor + public static class LearnKeyDto { + + private Long id; + private String uid; + private String chnDtctMstId; + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/GukYuinDto.java b/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/GukYuinDto.java index d236bfb4..652a00fc 100644 --- a/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/GukYuinDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/GukYuinDto.java @@ -1,21 +1,13 @@ package com.kamco.cd.kamcoback.gukyuin.dto; import com.kamco.cd.kamcoback.common.utils.enums.EnumType; +import java.util.UUID; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; public class GukYuinDto { - @Getter - @Setter - public static class GukYuinLinkableRes { - - private boolean linkable; - // private GukYuinLinkFailCode code; - private String message; - } - /** 실패 코드 enum */ @Getter @AllArgsConstructor @@ -39,10 +31,33 @@ public class GukYuinDto { } } + @Getter + @Setter + public static class GukYuinLinkableRes { + + private boolean linkable; + // private GukYuinLinkFailCode code; + private String message; + } + // Repository가 반환할 Fact(조회 결과) public record GukYuinLinkFacts( boolean existsLearn, boolean isPartScope, boolean hasRunningInference, boolean hasOtherUnfinishedGukYuin) {} + + @Getter + @Setter + @AllArgsConstructor + public static class LearnInfo { + + private Long id; + private UUID uuid; + private Integer compareYyyy; + private Integer targetYyyy; + private Integer stage; + private String uid; + private String applyStatus; + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/GukYuinStatus.java b/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/GukYuinStatus.java index 174e9714..e6472c04 100644 --- a/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/GukYuinStatus.java +++ b/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/GukYuinStatus.java @@ -11,6 +11,7 @@ public enum GukYuinStatus implements EnumType { IN_PROGRESS("진행중"), GUK_COMPLETED("국유인 매핑 완료"), PNU_COMPLETED("PNU 싱크 완료"), + PNU_FAILED("PNU 싱크 중 에러"), CANCELED("취소"); private final String desc; diff --git a/src/main/java/com/kamco/cd/kamcoback/gukyuin/service/GukYuinApiService.java b/src/main/java/com/kamco/cd/kamcoback/gukyuin/service/GukYuinApiService.java index 82fec220..de37d45e 100644 --- a/src/main/java/com/kamco/cd/kamcoback/gukyuin/service/GukYuinApiService.java +++ b/src/main/java/com/kamco/cd/kamcoback/gukyuin/service/GukYuinApiService.java @@ -1,6 +1,10 @@ package com.kamco.cd.kamcoback.gukyuin.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.api.ApiResponseDto.ApiResponseCode; +import com.kamco.cd.kamcoback.config.api.ApiResponseDto.ResponseObj; 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; @@ -8,22 +12,31 @@ 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.ChngDetectContDto.ResultPnuDto; import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto; +import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.ChnDetectMastReqDto; import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.ResReturn; import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.ResultDto; import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.GukYuinLinkFacts; import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.GukYuinLinkFailCode; import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.GukYuinLinkableRes; +import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.LearnInfo; +import com.kamco.cd.kamcoback.log.dto.EventStatus; +import com.kamco.cd.kamcoback.log.dto.EventType; import com.kamco.cd.kamcoback.postgres.core.GukYuinCoreService; +import com.kamco.cd.kamcoback.postgres.entity.AuditLogEntity; +import com.kamco.cd.kamcoback.postgres.repository.log.AuditLogRepository; import java.util.List; import java.util.UUID; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpMethod; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; +@Slf4j @Service -@Transactional(readOnly = true) +@Transactional @RequiredArgsConstructor public class GukYuinApiService { @@ -31,6 +44,9 @@ public class GukYuinApiService { private final ExternalHttpClient externalHttpClient; private final NetUtils netUtils = new NetUtils(); + private final UserUtil userUtil; + private final AuditLogRepository auditLogRepository; + @Value("${spring.profiles.active:local}") private String profile; @@ -41,25 +57,42 @@ public class GukYuinApiService { private String gukyuinCdiUrl; @Transactional - public ChngDetectMastDto.Basic regist(ChngDetectMastDto.ChnDetectMastReqDto chnDetectMastReq) { + public ChngDetectMastDto.RegistResDto regist( + ChngDetectMastDto.ChnDetectMastReqDto chnDetectMastReq) { String url = gukyuinCdiUrl + "/chn/mast/regist"; String myip = netUtils.getLocalIP(); chnDetectMastReq.setReqIp(myip); - chnDetectMastReq.setReqEpno("1234567"); // TODO + chnDetectMastReq.setReqEpno(userUtil.getEmployeeNo()); - ExternalCallResult result = + ExternalCallResult result = externalHttpClient.call( url, HttpMethod.POST, chnDetectMastReq, netUtils.jsonHeaders(), - ChngDetectMastDto.Basic.class); + ChngDetectMastDto.RegistResDto.class); - ChngDetectMastDto.Basic resultBody = result.body(); - gukyuinCoreService.updateGukYuinMastRegResult(resultBody); + ChngDetectMastDto.RegistResDto resultBody = result.body(); + Boolean success = false; + if (resultBody != null) { + ChngDetectMastDto.Basic registRes = resultBody.getResult(); + // 추론 회차에 applyStatus, applyStatusDttm 업데이트 + gukyuinCoreService.updateGukYuinMastRegResult(registRes); + // anal_inference 에도 국유인 반영여부, applyDttm 업데이트 + gukyuinCoreService.updateAnalInferenceApplyDttm(registRes); + success = resultBody.getSuccess(); + } + + this.insertGukyuinAuditLog( + EventType.ADDED.getId(), + myip, + userUtil.getId(), + url.replace(gukyuinUrl, ""), + chnDetectMastReq, + success); return resultBody; } @@ -69,7 +102,7 @@ public class GukYuinApiService { String myip = netUtils.getLocalIP(); chnDetectMastReq.setReqIp(myip); - chnDetectMastReq.setReqEpno("1234567"); // TODO + chnDetectMastReq.setReqEpno(userUtil.getEmployeeNo()); ExternalCallResult result = externalHttpClient.call( @@ -82,11 +115,18 @@ public class GukYuinApiService { ChngDetectMastDto.Basic resultBody = result.body(); gukyuinCoreService.updateGukYuinMastRegRemove(resultBody); + this.insertGukyuinAuditLog( + EventType.REMOVE.getId(), + myip, + userUtil.getId(), + url.replace(gukyuinUrl, ""), + chnDetectMastReq, + true); // TODO : successFail 여부 return new ResReturn("success", "탐지결과 삭제 되었습니다."); } // 등록목록 1개 확인 - public ChngDetectMastDto.ResultDto list(String chnDtctMstId) { + public ChngDetectMastDto.ResultDto detail(String chnDtctMstId) { String url = gukyuinCdiUrl + "/chn/mast/list/" + chnDtctMstId; @@ -94,6 +134,13 @@ public class GukYuinApiService { externalHttpClient.call( url, HttpMethod.GET, null, netUtils.jsonHeaders(), ChngDetectMastDto.ResultDto.class); + this.insertGukyuinAuditLog( + EventType.DETAIL.getId(), + netUtils.getLocalIP(), + userUtil.getId(), + url.replace(gukyuinUrl, ""), + null, + result.body().getSuccess()); return result.body(); } @@ -108,6 +155,13 @@ public class GukYuinApiService { externalHttpClient.call( url, HttpMethod.GET, null, netUtils.jsonHeaders(), ChngDetectMastDto.ResultDto.class); + this.insertGukyuinAuditLog( + EventType.LIST.getId(), + netUtils.getLocalIP(), + userUtil.getId(), + url.replace(gukyuinUrl, ""), + null, + result.body().getSuccess()); return result.body(); } @@ -188,6 +242,14 @@ public class GukYuinApiService { } } + this.insertGukyuinAuditLog( + EventType.LIST.getId(), + netUtils.getLocalIP(), + userUtil.getId(), + url.replace(gukyuinUrl, ""), + null, + result.body().getSuccess()); + return result.body(); } @@ -202,6 +264,14 @@ public class GukYuinApiService { netUtils.jsonHeaders(), ChngDetectContDto.ResultPnuDto.class); + this.insertGukyuinAuditLog( + EventType.DETAIL.getId(), + netUtils.getLocalIP(), + userUtil.getId(), + url.replace(gukyuinUrl, ""), + null, + result.body().getSuccess()); + return result.body(); } @@ -218,6 +288,14 @@ public class GukYuinApiService { ChngDetectContDto.ResultPnuDto dto = result.body(); + this.insertGukyuinAuditLog( + EventType.MODIFIED.getId(), + netUtils.getLocalIP(), + userUtil.getId(), + url.replace(gukyuinUrl, ""), + null, + result.body().getSuccess()); + return new ResReturn(dto.getCode() > 200000 ? "fail" : "success", dto.getMessage()); } @@ -232,6 +310,13 @@ public class GukYuinApiService { netUtils.jsonHeaders(), ChngDetectContDto.ResultContDto.class); + this.insertGukyuinAuditLog( + EventType.LIST.getId(), + netUtils.getLocalIP(), + userUtil.getId(), + url.replace(gukyuinUrl, ""), + null, + result.body().getSuccess()); return result.body(); } @@ -242,6 +327,70 @@ public class GukYuinApiService { externalHttpClient.call( url, HttpMethod.GET, null, netUtils.jsonHeaders(), ChngDetectMastDto.ResultDto.class); + this.insertGukyuinAuditLog( + EventType.DETAIL.getId(), + netUtils.getLocalIP(), + userUtil.getId(), + url.replace(gukyuinUrl, ""), + null, + result.body().getSuccess()); + return result.body(); } + + @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; + } + } + + public ResponseObj connectChnMastRegist(UUID uuid) { + // uuid로 추론 회차 조회 + LearnInfo info = gukyuinCoreService.findMapSheetLearnInfo(uuid); + // if (info.getApplyStatus() != null && + // !info.getApplyStatus().equals(GukYuinStatus.PENDING.getId())) + // { + // return new ResponseObj(ApiResponseCode.DUPLICATE_DATA, "이미 국유인 연동을 한 추론 회차입니다."); + // } + + // 비교년도,기준년도로 전송한 데이터 있는지 확인 후 회차 번호 생성 + Integer maxStage = + gukyuinCoreService.findMapSheetLearnYearStage(info.getCompareYyyy(), info.getTargetYyyy()); + + // reqDto 셋팅 + ChnDetectMastReqDto reqDto = new ChnDetectMastReqDto(); + reqDto.setCprsYr(String.valueOf(info.getCompareYyyy())); + reqDto.setCrtrYr(String.valueOf(info.getTargetYyyy())); + reqDto.setChnDtctSno(String.valueOf(maxStage + 1)); + reqDto.setChnDtctId(info.getUid()); + reqDto.setPathNm("/kamco-nfs/dataset/export/" + info.getUid()); + + // 국유인 /chn/mast/regist 전송 + this.regist(reqDto); + + return new ResponseObj(ApiResponseCode.OK, ""); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/layer/dto/LayerDto.java b/src/main/java/com/kamco/cd/kamcoback/layer/dto/LayerDto.java index 98d18422..4ad12d51 100644 --- a/src/main/java/com/kamco/cd/kamcoback/layer/dto/LayerDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/layer/dto/LayerDto.java @@ -408,4 +408,9 @@ public class LayerDto { @Schema(description = "노출여부 true, false", example = "true") private Boolean isMapYn; } + + public enum MapType { + CHANGE_MAP, + LABELING_MAP + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/layer/dto/WmsLayerInfo.java b/src/main/java/com/kamco/cd/kamcoback/layer/dto/WmsLayerInfo.java index 5fbf0647..03fa3a44 100755 --- a/src/main/java/com/kamco/cd/kamcoback/layer/dto/WmsLayerInfo.java +++ b/src/main/java/com/kamco/cd/kamcoback/layer/dto/WmsLayerInfo.java @@ -2,171 +2,46 @@ package com.kamco.cd.kamcoback.layer.dto; import java.util.ArrayList; import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; /** WMS 레이어 정보를 담는 DTO 클래스 */ +@Data +@NoArgsConstructor +@AllArgsConstructor public class WmsLayerInfo { + private String name; private String title; private String abstractText; - private List keywords; + + private List keywords = new ArrayList<>(); private BoundingBox boundingBox; - private List crs; // 지원하는 좌표계 목록 - @Override - public String toString() { - return "WmsLayerInfo{" - + "name='" - + name - + '\'' - + ", title='" - + title - + '\'' - + ", abstractText='" - + abstractText - + '\'' - + ", keywords=" - + keywords - + ", boundingBox=" - + boundingBox - + ", crs=" - + crs - + '}'; - } + /** 지원하는 좌표계 목록 */ + private List crs = new ArrayList<>(); - public WmsLayerInfo() { - this.keywords = new ArrayList<>(); - this.crs = new ArrayList<>(); - } - - // Getters and Setters - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getAbstractText() { - return abstractText; - } - - public void setAbstractText(String abstractText) { - this.abstractText = abstractText; - } - - public List getKeywords() { - return keywords; - } - - public void setKeywords(List keywords) { - this.keywords = keywords; - } + /* ===== convenience methods ===== */ public void addKeyword(String keyword) { this.keywords.add(keyword); } - public BoundingBox getBoundingBox() { - return boundingBox; - } - - public void setBoundingBox(BoundingBox boundingBox) { - this.boundingBox = boundingBox; - } - - public List getCrs() { - return crs; - } - - public void setCrs(List crs) { - this.crs = crs; - } - public void addCrs(String crsValue) { this.crs.add(crsValue); } /** BoundingBox 정보를 담는 내부 클래스 */ + @Data + @NoArgsConstructor + @AllArgsConstructor public static class BoundingBox { + private String crs; private double minX; private double minY; private double maxX; private double maxY; - - public BoundingBox(String crs, double minX, double minY, double maxX, double maxY) { - this.crs = crs; - this.minX = minX; - this.minY = minY; - this.maxX = maxX; - this.maxY = maxY; - } - - // Getters and Setters - public String getCrs() { - return crs; - } - - public void setCrs(String crs) { - this.crs = crs; - } - - public double getMinX() { - return minX; - } - - public void setMinX(double minX) { - this.minX = minX; - } - - public double getMinY() { - return minY; - } - - public void setMinY(double minY) { - this.minY = minY; - } - - public double getMaxX() { - return maxX; - } - - public void setMaxX(double maxX) { - this.maxX = maxX; - } - - public double getMaxY() { - return maxY; - } - - public void setMaxY(double maxY) { - this.maxY = maxY; - } - - @Override - public String toString() { - return "BoundingBox{" - + "crs='" - + crs - + '\'' - + ", minX=" - + minX - + ", minY=" - + minY - + ", maxX=" - + maxX - + ", maxY=" - + maxY - + '}'; - } } } diff --git a/src/main/java/com/kamco/cd/kamcoback/layer/dto/WmtsLayerInfo.java b/src/main/java/com/kamco/cd/kamcoback/layer/dto/WmtsLayerInfo.java index beb6e4ea..53e5c216 100755 --- a/src/main/java/com/kamco/cd/kamcoback/layer/dto/WmtsLayerInfo.java +++ b/src/main/java/com/kamco/cd/kamcoback/layer/dto/WmtsLayerInfo.java @@ -1,70 +1,48 @@ package com.kamco.cd.kamcoback.layer.dto; -import com.fasterxml.jackson.annotation.JsonProperty; import java.util.ArrayList; import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; /** WMTS 레이어 정보를 담는 DTO 클래스 */ +@Data +@NoArgsConstructor +@AllArgsConstructor public class WmtsLayerInfo { - public String identifier; - public String title; - public String abstractText; - public List keywords = new ArrayList<>(); - public BoundingBox boundingBox; - public List formats = new ArrayList<>(); - public List tileMatrixSetLinks = new ArrayList<>(); - public List resourceUrls = new ArrayList<>(); - public List