{
+
+ private final T enumValue;
+ private final String id;
+ private final String text;
+
+ public EnumDto(T enumValue, String id, String text) {
+ this.enumValue = enumValue;
+ this.id = id;
+ this.text = text;
+ }
+ }
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/enums/CodeDto.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/enums/CodeDto.java
new file mode 100644
index 0000000..ae4bc00
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/enums/CodeDto.java
@@ -0,0 +1,20 @@
+package com.kamco.cd.kamcoback.enums;
+
+public class CodeDto {
+
+ private String code;
+ private String name;
+
+ public CodeDto(String code, String name) {
+ this.code = code;
+ this.name = name;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getName() {
+ return name;
+ }
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/enums/CommonUseStatus.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/enums/CommonUseStatus.java
new file mode 100644
index 0000000..bcd0b39
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/enums/CommonUseStatus.java
@@ -0,0 +1,46 @@
+package com.kamco.cd.kamcoback.enums;
+
+import com.kamco.cd.kamcoback.enums.ApiConfigEnum.EnumDto;
+import com.kamco.cd.kamcoback.inferface.EnumType;
+import java.util.Arrays;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * Common usage status used across the system.
+ *
+ * This enum represents whether a resource is active, excluded from processing, or inactive. It
+ * is commonly used for filtering, business rules, and status management.
+ */
+@Getter
+@AllArgsConstructor
+public enum CommonUseStatus implements EnumType {
+
+ // @formatter:off
+ USE("USE", "사용중", 100)
+ /** Actively used and available */
+ ,
+ EXCEPT("EXCEPT", "영구 추론제외", 200)
+ /** Explicitly excluded from use or processing */
+ ,
+ AUTO_EXCEPT("AUTO_EXCEPT", "자동추론 제외", 300),
+ NOT_USE("NOT_USE", "사용안함", 999)
+/** Not used or disabled */
+;
+ // @formatter:on
+
+ private String id;
+ private String text;
+ private int ordering;
+
+ public static CommonUseStatus getEnumById(String id) {
+ return Arrays.stream(CommonUseStatus.values())
+ .filter(x -> x.getId().equals(id))
+ .findFirst()
+ .orElse(CommonUseStatus.NOT_USE);
+ }
+
+ public EnumDto getEnumDto() {
+ return new EnumDto<>(this, this.id, this.text);
+ }
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/enums/Enums.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/enums/Enums.java
new file mode 100644
index 0000000..c87856e
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/enums/Enums.java
@@ -0,0 +1,86 @@
+package com.kamco.cd.kamcoback.enums;
+
+import com.kamco.cd.kamcoback.inferface.CodeExpose;
+import com.kamco.cd.kamcoback.inferface.CodeHidden;
+import com.kamco.cd.kamcoback.inferface.EnumType;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.reflections.Reflections;
+
+public class Enums {
+
+ private static final String BASE_PACKAGE = "com.kamco.cd.kamcoback";
+
+ /** 노출 가능한 enum만 모아둔 맵 key: enum simpleName (예: RoleType) value: enum Class */
+ private static final Map>> exposedEnumMap = scanExposedEnumMap();
+
+ // code로 enum 찾기
+ public static & EnumType> E fromId(Class enumClass, String id) {
+ if (id == null) {
+ return null;
+ }
+
+ for (E e : enumClass.getEnumConstants()) {
+ if (id.equalsIgnoreCase(e.getId())) {
+ return e;
+ }
+ }
+ return null;
+ }
+
+ // enum -> CodeDto list
+ public static List toList(Class extends Enum>> enumClass) {
+ Object[] enums = enumClass.getEnumConstants();
+
+ return Arrays.stream(enums)
+ .map(e -> (EnumType) e)
+ .filter(e -> !isHidden(enumClass, (Enum>) e))
+ .map(e -> new CodeDto(e.getId(), e.getText()))
+ .toList();
+ }
+
+ private static boolean isHidden(Class extends Enum>> enumClass, Enum> e) {
+ try {
+ return enumClass.getField(e.name()).isAnnotationPresent(CodeHidden.class);
+ } catch (NoSuchFieldException ex) {
+ return false;
+ }
+ }
+
+ /** 특정 타입(enum)만 조회 /codes/{type} -> type = RoleType 같은 값 */
+ public static List getCodes(String type) {
+ Class extends Enum>> enumClass = exposedEnumMap.get(type);
+ if (enumClass == null) {
+ throw new IllegalArgumentException("지원하지 않는 코드 타입: " + type);
+ }
+ return toList(enumClass);
+ }
+
+ /** 전체 enum 코드 조회 */
+ public static Map> getAllCodes() {
+ Map> result = new HashMap<>();
+ for (Map.Entry>> e : exposedEnumMap.entrySet()) {
+ result.put(e.getKey(), toList(e.getValue()));
+ }
+ return result;
+ }
+
+ /** CodeExpose + EnumType 인 enum만 스캔해서 Map 구성 */
+ private static Map>> scanExposedEnumMap() {
+ Reflections reflections = new Reflections(BASE_PACKAGE);
+
+ Set> types = reflections.getTypesAnnotatedWith(CodeExpose.class);
+
+ Map>> result = new HashMap<>();
+
+ for (Class> clazz : types) {
+ if (clazz.isEnum() && EnumType.class.isAssignableFrom(clazz)) {
+ result.put(clazz.getSimpleName(), (Class extends Enum>>) clazz);
+ }
+ }
+ return result;
+ }
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/enums/MngStateType.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/enums/MngStateType.java
new file mode 100644
index 0000000..f5fd245
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/enums/MngStateType.java
@@ -0,0 +1,26 @@
+package com.kamco.cd.kamcoback.enums;
+
+import com.kamco.cd.kamcoback.inferface.EnumType;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum MngStateType implements EnumType {
+ NOTYET("동기화 시작"),
+ PROCESSING("데이터 체크"),
+ DONE("동기화 작업 종료"),
+ TAKINGERROR("오류 데이터 처리중");
+
+ private final String desc;
+
+ @Override
+ public String getId() {
+ return name();
+ }
+
+ @Override
+ public String getText() {
+ return desc;
+ }
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/enums/SyncStateType.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/enums/SyncStateType.java
new file mode 100644
index 0000000..adba1cc
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/enums/SyncStateType.java
@@ -0,0 +1,33 @@
+package com.kamco.cd.kamcoback.enums;
+
+import com.kamco.cd.kamcoback.inferface.CodeExpose;
+import com.kamco.cd.kamcoback.inferface.CodeHidden;
+import com.kamco.cd.kamcoback.inferface.EnumType;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@CodeExpose
+@Getter
+@AllArgsConstructor
+public enum SyncStateType implements EnumType {
+ @CodeHidden
+ NOTYET("미처리"),
+ NOFILE("파일없음"),
+ NOTPAIR("페어파일누락"),
+ DUPLICATE("파일중복"),
+ TYPEERROR("손상파일"),
+ @CodeHidden
+ DONE("완료");
+
+ private final String desc;
+
+ @Override
+ public String getId() {
+ return name();
+ }
+
+ @Override
+ public String getText() {
+ return desc;
+ }
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/ChngDetectContDto.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/ChngDetectContDto.java
new file mode 100644
index 0000000..57df805
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/ChngDetectContDto.java
@@ -0,0 +1,117 @@
+package com.kamco.cd.kamcoback.gukyuin.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import java.util.List;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+public class ChngDetectContDto {
+
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class ContBasic {
+
+ private String chnDtctMstId; // 탐지콘텐츠아이디
+ private String chnDtctContId; // 탐지마스타아이디
+ private String cprsYr; // 비교년도 2023
+ private String crtrYr; // 기준년도 2024
+ private String chnDtctSno; // 차수 (1 | 2 | ...)
+ private String mpqdNo; // 도엽번호
+ private String chnDtctId; // 탐지아이디. UUID를 기반으로 '-'를 제거하고 대문자/숫자로 구성
+ private String chnDtctObjtId; // 탐지객체아이디. UUID를 기반으로 '-'를 제거하고 대문자/숫자로 구성
+ private String chnDtctPolygon; // 탐지객체폴리곤
+ private String chnDtctSqms; // 탐지객체면적
+ private String chnCd; // 변화코드
+ private String chnDtctJson; // 변화탐지JSON
+ private String chnDtctProb; // 변화탐지정확도
+ private String bfClsCd; // 이전부류코드
+ private String bfClsProb; // 이전분류정확도
+ private String afClsCd; // 이후분류코드
+ private String afClsProb; // 이후분류정확도
+ private String crtDt; // 생성일시
+ private String crtEpno; // 생성사원번호
+ private String crtIp; // 생성사원아이피
+ private String delYn; // 삭제여부
+ private String[] pnuList; // pnuList
+ private String reqEpno; // 요청사원번호
+ private String reqIp; // 요청사원아이피
+ }
+
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class ChnDetectContReqDto {
+
+ private String cprsYr; // 비교년도 2023
+ private String crtrYr; // 기준년도 2024
+ private String chnDtctSno; // 차수 (1 | 2 | ...)
+ private String mpqdNo; // 도엽번호
+ private String chnDtctId; // 탐지아이디. UUID를 기반으로 '-'를 제거하고 대문자/숫자로 구성
+ private String chnDtctObjtId; // 탐지객체아이디. UUID를 기반으로 '-'를 제거하고 대문자/숫자로 구성
+ private String reqEpno; // 사원번호
+ private String reqIp;
+ }
+
+ @Schema(name = "ResReturn", description = "수행 후 리턴")
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class ResReturn {
+
+ private String flag;
+ private String message;
+ }
+
+ @Schema(name = "ResultContDto", description = "cont list 리턴 형태")
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class ResultContDto {
+
+ private Integer code;
+ private String message;
+ private List result;
+ private Boolean success;
+ }
+
+ @Schema(name = "DtoPnuDetectMpng", description = "PNU 결과 형태")
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class DtoPnuDetectMpng {
+
+ private String pnuDtctId;
+ private String lrmYmd;
+ private String pnu;
+ private String pnuSqms;
+ private String pnuDtctSqms;
+
+ private String chnDtctSqms;
+ private String chnDtctMstId;
+ private String chnDtctContId;
+ private String chnDtctId;
+ private String chnDtctObjtId;
+ private String crtDt;
+ }
+
+ @Schema(name = "ResultPnuDto", description = "pnu list 리턴 형태")
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class ResultPnuDto {
+
+ private Integer code;
+ private String message;
+ private List result;
+ private Boolean success;
+ }
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/ChngDetectMastDto.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/ChngDetectMastDto.java
new file mode 100644
index 0000000..644b77b
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/ChngDetectMastDto.java
@@ -0,0 +1,291 @@
+package com.kamco.cd.kamcoback.gukyuin.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import java.time.ZonedDateTime;
+import java.util.List;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+public class ChngDetectMastDto {
+
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class Basic {
+
+ private String chnDtctMstId; // 탐지마스터아이디
+ private String cprsYr; // 비교년도 2023
+ private String crtrYr; // 기준년도 2024
+ private String chnDtctSno; // 차수 (1 | 2 | ...)
+ private String chnDtctId; // 탐지아이디. UUID를 기반으로 '-'를 제거하고 대문자/숫자로 구성
+ private String chnDtctCnt; // 탐지객체개수
+ private String pnuMpngCnt; // PNU매핑개수
+ private String lrmYmd; // 지적도일자
+ private String pathNm; // 탐지결과 절대경로명 /kamco_nas/export/{chnDtctId}
+ private List excnList; // 등록진행상태히스토리 (최근것부터 DESC)
+ private String excnStepCd; // 실행단계코드
+ private String excnStep; // 실행단계코드에 해당하는 영문명
+ private String excnPgrt; // 실행단계진행율
+ private String excnBngnDt; // 실행단계시작시간
+ private String excnEndDt; // 실행단계종료시간
+ private String rmk; // 비고
+ private String crtDt; // 생성일시
+ private String crtEpno; // 생성사원번호
+ private String crtIp; // 생성사원아이피
+ private String chgDt; // 변경일시
+ private String chgEpno; // 변경사원번호
+ private String chgIp; // 변경사원아이피
+ private String delYn; // 삭제여부
+ //
+ private String reqEpno; // 요청사원번호
+ private String reqIp; // 요청사원어이피
+ }
+
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class ChnDetectMastExcnStepDto {
+
+ private String srno; // 일련번호
+ private String chnDtctMstId; // 탐지마스터아이디
+ private String excnStepCd; // 실행단계코드
+ private String excnStep; // 실행단계코드에 해당하는 영문명
+ private String excnPgrt; // 실행단계진행율
+ private String excnEndDt; // 실행단계종료시간
+ private String errCd; // 오류코드
+ private String errMsg; // 오류메세지
+ private String crtDt; // 실행단계시작시간
+ }
+
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class ChnDetectMastReqDto {
+
+ @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
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class ChnDetectContDto {
+
+ private String chnDtctMstId; // 탐지콘텐츠아이디
+ private String chnDtctContId; // 탐지마스타아이디
+ private String cprsYr; // 비교년도 2023
+ private String crtrYr; // 기준년도 2024
+ private String chnDtctSno; // 차수 (1 | 2 | ...)
+ private String mpqdNo; // 도엽번호
+ private String chnDtctId; // 탐지아이디. UUID를 기반으로 '-'를 제거하고 대문자/숫자로 구성
+ private String chnDtctObjtId; // 탐지객체아이디. UUID를 기반으로 '-'를 제거하고 대문자/숫자로 구성
+ private String chnDtctPolygon; // 탐지객체폴리곤
+ private String chnDtctSqms; // 탐지객체면적
+ private String chnCd; // 변화코드
+ private String chnDtctJson; // 변화탐지JSON
+ private String chnDtctProb; // 변화탐지정확도
+ private String bfClsCd; // 이전부류코드
+ private String bfClsProb; // 이전분류정확도
+ private String afClsCd; // 이후분류코드
+ private String afClsProb; // 이후분류정확도
+ private String crtDt; // 생성일시
+ private String crtEpno; // 생성사원번호
+ private String crtIp; // 생성사원아이피
+ private String delYn; // 삭제여부
+ //
+ private String reqEpno; // 요청사원번호
+ private String reqIp; // 요청사원아이피
+ }
+
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class ChnDetectContReqDto {
+
+ private String cprsYr; // 비교년도 2023
+ private String crtrYr; // 기준년도 2024
+ private String chnDtctSno; // 차수 (1 | 2 | ...)
+ private String mpqdNo; // 도엽번호
+ private String chnDtctId; // 탐지아이디. UUID를 기반으로 '-'를 제거하고 대문자/숫자로 구성
+ private String chnDtctObjtId; // 탐지객체아이디. UUID를 기반으로 '-'를 제거하고 대문자/숫자로 구성
+ private String reqEpno; // 사원번호
+ private String reqIp;
+ }
+
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class ChngDetectMastSearchDto {
+
+ // private String chnDtctId;
+ private String cprsYr;
+ private String crtrYr;
+ private String chnDtctSno;
+ }
+
+ @Schema(name = "ResReturn", description = "수행 후 리턴")
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class ResReturn {
+
+ private String flag;
+ private String message;
+ }
+
+ @Schema(name = "ResultDto", description = "mast list 리턴 형태")
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class ResultDto {
+
+ private Integer code;
+ private String message;
+ 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;
+ }
+
+ @Schema(name = "LabelSendDto", description = "라벨링 전송한 목록")
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class LabelSendDto {
+
+ private String chnDtctObjtId;
+ private String labelerId;
+ private ZonedDateTime labelerWorkDttm;
+ private String reviewerId;
+ private ZonedDateTime reviewerWorkDttm;
+ private ZonedDateTime labelSendDttm;
+ }
+
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class ErrorResDto {
+
+ private String timestamp;
+ private Integer status;
+ private String error;
+ private String path;
+ }
+
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class RlbDtctDto {
+
+ private Integer code;
+ private String message;
+ private List result;
+ private Boolean success;
+ }
+
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class RlbDtctMastDto {
+
+ private String pnuDtctId;
+ private String pnu;
+ private String lrmSyncYmd;
+ private String pnuSyncYmd;
+ private String mpqdNo; // 도엽번호
+ private String cprsYr; // 비교년도
+ private String crtrYr; // 기준년도
+ private String chnDtctSno; // 회차
+ private String chnDtctId;
+
+ private String chnDtctMstId;
+ private String chnDtctObjtId;
+ private String chnDtctContId;
+ private String chnCd;
+ private String chnDtctProb;
+
+ private String bfClsCd; // 이전분류코드
+ private String bfClsProb; // 이전분류정확도
+ private String afClsCd; // 이후분류코드
+ private String afClsProb; // 이후분류정확도
+
+ private String pnuSqms;
+ private String pnuDtctSqms;
+ private String chnDtctSqms;
+ private String stbltYn;
+ private String incyCd;
+ private String incyRsnCont;
+ private String lockYn;
+ private String lblYn;
+ private String chgYn;
+ private String rsatctNo;
+ private String rmk;
+
+ private String crtDt; // 생성일시
+ private String crtEpno; // 생성사원번호
+ private String crtIp; // 생성사원아이피
+ private String chgDt;
+ private String chgEpno;
+ private String chgIp;
+ private String delYn; // 삭제여부
+ }
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/DetectMastDto.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/DetectMastDto.java
new file mode 100644
index 0000000..59c6e86
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/DetectMastDto.java
@@ -0,0 +1,80 @@
+package com.kamco.cd.kamcoback.gukyuin.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+public class DetectMastDto {
+
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class Basic {
+
+ private Long dtctMstId;
+ private String cprsBfYr;
+ private String cprsAdYr;
+ private Integer dtctSno;
+ private String pathNm;
+ private String crtEpno;
+ private String crtIp;
+ }
+
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class DetectMastReq {
+
+ @NotBlank
+ @Schema(description = "before 연도", example = "2023")
+ private String cprsBfYr;
+
+ @NotBlank
+ @Schema(description = "after 연도", example = "2024")
+ private String cprsAdYr;
+
+ @NotNull
+ @Schema(description = "차수(회차)", example = "4")
+ private Integer dtctSno;
+
+ @NotBlank
+ @Schema(description = "파일경로", example = "/app/detect/result/2023_2024/4")
+ private String pathNm;
+
+ @NotBlank
+ @Schema(description = "사원번호", example = "1234567")
+ private String crtEpno;
+
+ @NotBlank
+ @Schema(description = "아이피", example = "0.0.0.0")
+ private String crtIp;
+ }
+
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class DetectMastSearch {
+
+ private String cprsBfYr;
+ private String cprsAdYr;
+ private Integer dtctSno;
+ private String featureId;
+ }
+
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class FeaturePnuDto {
+
+ private String featureId; // polygon_id
+ private String pnu; // 랜덤 생성
+ }
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/GukYuinDto.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/GukYuinDto.java
new file mode 100644
index 0000000..da25f65
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/GukYuinDto.java
@@ -0,0 +1,77 @@
+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 {
+
+ /** 실패 코드 enum */
+ @Getter
+ @AllArgsConstructor
+ public enum GukYuinLinkFailCode implements EnumType {
+ OK("연동 가능"),
+ NOT_FOUND("대상 회차가 없습니다."),
+ SCOPE_PART_NOT_ALLOWED("부분 도엽은 연동 불가능 합니다."),
+ HAS_RUNNING_INFERENCE("라벨링 진행 중 회차가 있습니다."),
+ OTHER_GUKYUIN_IN_PROGRESS("국유in 연동 진행 중 회차가 있습니다.");
+
+ private final String desc;
+
+ @Override
+ public String getId() {
+ return name();
+ }
+
+ @Override
+ public String getText() {
+ return desc;
+ }
+ }
+
+ @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;
+ private Boolean applyYn;
+
+ public Boolean getApplyYn() {
+ return this.applyYn != null && this.applyYn;
+ }
+ }
+
+ @Getter
+ @Setter
+ @AllArgsConstructor
+ public static class GeomUidDto {
+
+ private Long geoUid;
+ private String resultUid;
+ }
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/GukYuinStatus.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/GukYuinStatus.java
new file mode 100644
index 0000000..16b22e4
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/GukYuinStatus.java
@@ -0,0 +1,29 @@
+package com.kamco.cd.kamcoback.gukyuin.dto;
+
+import com.kamco.cd.kamcoback.common.utils.enums.EnumType;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum GukYuinStatus implements EnumType {
+ PENDING("대기"),
+ IN_PROGRESS("진행중"),
+ GUK_COMPLETED("국유인 매핑 완료"),
+ PNU_COMPLETED("PNU 싱크 완료"),
+ PNU_FAILED("PNU 싱크 중 에러"),
+ END("종료"),
+ CANCELED("취소");
+
+ private final String desc;
+
+ @Override
+ public String getId() {
+ return name();
+ }
+
+ @Override
+ public String getText() {
+ return desc;
+ }
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/inference/dto/DetectionClassification.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/inference/dto/DetectionClassification.java
new file mode 100644
index 0000000..d2a1330
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/inference/dto/DetectionClassification.java
@@ -0,0 +1,56 @@
+package com.kamco.cd.kamcoback.inference.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum DetectionClassification {
+ ROAD("road", "도로", 10),
+ BUILDING("building", "건물", 20),
+ GREENHOUSE("greenhouse", "비닐하우스", 30),
+ FIELD("field", "논/밭", 40),
+ ORCHARD("orchard", "과수원", 50),
+ GRASS("grass", "초지", 60),
+ FOREST("forest", "숲", 70),
+ WATER("water", "물", 80),
+ STONE("stone", "모래/자갈", 90),
+ WASTE("waste", "적치물", 100),
+ CONTAINER("container", "컨테이너", 110),
+ LAND("land", "일반토지", 120),
+ SOLAR("solar", "태양광", 130),
+ TANK("tank", "물탱크", 140),
+ NDC("NDC", "미분류", 150),
+ ETC("ETC", "기타", 160);
+
+ private final String id;
+ private final String desc;
+ private final int order;
+
+ /**
+ * Optional: Helper method to get the enum from a String, case-insensitive, or return ETC if not
+ * found.
+ */
+ public static DetectionClassification fromString(String text) {
+ if (text == null || text.trim().isEmpty()) {
+ return ETC;
+ }
+
+ try {
+ return DetectionClassification.valueOf(text.toUpperCase());
+ } catch (IllegalArgumentException e) {
+ // If the string doesn't match any enum constant name, return ETC
+ return ETC;
+ }
+ }
+
+ /**
+ * Desc 한글명 get 하기
+ *
+ * @return
+ */
+ public static String fromStrDesc(String text) {
+ DetectionClassification dtf = fromString(text);
+ return dtf.getDesc();
+ }
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceDetailDto.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceDetailDto.java
new file mode 100644
index 0000000..4cfe330
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceDetailDto.java
@@ -0,0 +1,561 @@
+package com.kamco.cd.kamcoback.inference.dto;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.kamco.cd.kamcoback.common.utils.enums.ImageryFitStatus;
+import com.kamco.cd.kamcoback.common.utils.interfaces.JsonFormatDttm;
+import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.DetectOption;
+import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.MapSheetScope;
+import io.swagger.v3.oas.annotations.media.Schema;
+import java.time.Duration;
+import java.time.ZonedDateTime;
+import java.util.List;
+import java.util.UUID;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+
+public class InferenceDetailDto {
+
+ @Schema(name = "InferenceResultBasic", description = "분석결과 기본 정보")
+ @Getter
+ public static class Basic {
+
+ private Long id;
+ private String dataName;
+ private Long mapSheepNum;
+ private Long detectingCnt;
+ @JsonFormatDttm private ZonedDateTime analStrtDttm;
+ @JsonFormatDttm private ZonedDateTime analEndDttm;
+ private Long analSec;
+ private String analState;
+
+ public Basic(
+ Long id,
+ String dataName,
+ Long mapSheepNum,
+ Long detectingCnt,
+ ZonedDateTime analStrtDttm,
+ ZonedDateTime analEndDttm,
+ Long analSec,
+ String analState) {
+ this.id = id;
+ this.dataName = dataName;
+ this.mapSheepNum = mapSheepNum;
+ this.detectingCnt = detectingCnt;
+ this.analStrtDttm = analStrtDttm;
+ this.analEndDttm = analEndDttm;
+ this.analSec = analSec;
+ this.analState = analState;
+ }
+ }
+
+ @Schema(name = "AnalysisResultList", description = "분석결과 목록")
+ @Getter
+ public static class AnalResList {
+
+ private Long id;
+ private String analTitle;
+ private Long detectingCnt;
+ @JsonFormatDttm private ZonedDateTime analStrtDttm;
+ @JsonFormatDttm private ZonedDateTime analEndDttm;
+ private Long analSec;
+ private Long analPredSec;
+ private String analState;
+ private String analStateNm;
+ private String gukyuinUsed;
+
+ public AnalResList(
+ Long id,
+ String analTitle,
+ Long detectingCnt,
+ ZonedDateTime analStrtDttm,
+ ZonedDateTime analEndDttm,
+ Long analSec,
+ Long analPredSec,
+ String analState,
+ String analStateNm,
+ String gukyuinUsed) {
+ this.id = id;
+ this.analTitle = analTitle;
+ this.detectingCnt = detectingCnt;
+ this.analStrtDttm = analStrtDttm;
+ this.analEndDttm = analEndDttm;
+ this.analSec = analSec;
+ this.analPredSec = analPredSec;
+ this.analState = analState;
+ this.analStateNm = analStateNm;
+ this.gukyuinUsed = gukyuinUsed;
+ }
+ }
+
+ @Schema(name = "AnalysisResultSummary", description = "분석결과 요약정보")
+ @Getter
+ public static class AnalResSummary {
+
+ private Long id;
+ private String analTitle;
+ private String modelInfo;
+ private Integer targetYyyy;
+ private Integer compareYyyy;
+ @JsonFormatDttm private ZonedDateTime analStrtDttm;
+ @JsonFormatDttm private ZonedDateTime analEndDttm;
+ private Long analSec;
+ private Long analPredSec;
+ private String resultUrl;
+ private Long detectingCnt;
+ private Double accuracy;
+ private String analState;
+ private String analStateNm;
+
+ public AnalResSummary(
+ Long id,
+ String analTitle,
+ String modelInfo,
+ Integer targetYyyy,
+ Integer compareYyyy,
+ ZonedDateTime analStrtDttm,
+ ZonedDateTime analEndDttm,
+ Long analSec,
+ Long analPredSec,
+ String resultUrl,
+ Long detectingCnt,
+ Double accuracy,
+ String analState,
+ String analStateNm) {
+ this.id = id;
+ this.analTitle = analTitle;
+ this.modelInfo = modelInfo;
+ this.targetYyyy = targetYyyy;
+ this.compareYyyy = compareYyyy;
+ this.analStrtDttm = analStrtDttm;
+ this.analEndDttm = analEndDttm;
+ this.analSec = analSec;
+ this.analPredSec = analPredSec;
+ this.resultUrl = resultUrl;
+ this.detectingCnt = detectingCnt;
+ this.accuracy = accuracy;
+ this.analState = analState;
+ this.analStateNm = analStateNm;
+ }
+ }
+
+ @Getter
+ public static class Dashboard {
+
+ String classAfterCd;
+ String classAfterName;
+ Long classAfterCnt;
+
+ public Dashboard(String classAfterCd, Long classAfterCnt) {
+ this.classAfterCd = classAfterCd;
+ this.classAfterName = DetectionClassification.fromString(classAfterCd).getDesc();
+ this.classAfterCnt = classAfterCnt;
+ }
+ }
+
+ @Getter
+ public static class Detail {
+
+ AnalResSummary summary;
+ List dashboard;
+ Long totalCnt;
+
+ public Detail(AnalResSummary summary, List dashboard, Long totalCnt) {
+ this.summary = summary;
+ this.dashboard = dashboard;
+ this.totalCnt = totalCnt;
+ }
+ }
+
+ // 분석 상세 ROW
+ @Getter
+ @AllArgsConstructor
+ public static class DetailListEntity {
+
+ private Uid code;
+ private Double detectionScore;
+ private Clazzes compare;
+ private Clazzes target;
+ private MapSheet mapSheet;
+ private Coordinate center;
+ @JsonFormatDttm private ZonedDateTime updatedDttm;
+
+ public DetailListEntity(
+ UUID uuid,
+ Double detectionScore,
+ Clazzes compare,
+ Clazzes target,
+ MapSheet mapSheet,
+ Coordinate center,
+ ZonedDateTime updatedDttm) {
+ this.code = new Uid(uuid);
+ this.detectionScore = detectionScore;
+ this.compare = compare;
+ this.target = target;
+ this.mapSheet = mapSheet;
+ this.center = center;
+ this.updatedDttm = updatedDttm;
+ }
+ }
+
+ @Getter
+ @AllArgsConstructor
+ public static class Uid {
+
+ private String shortCode;
+ private String code;
+
+ public Uid(UUID uuid) {
+ if (uuid != null) {
+ this.shortCode = uuid.toString().substring(0, 8).toUpperCase();
+ this.code = uuid.toString();
+ }
+ }
+ }
+
+ // MAP NO
+ @Getter
+ @AllArgsConstructor
+ public static class MapSheet {
+
+ private String number;
+ private String name;
+ }
+
+ // classification info
+ @Getter
+ public static class Clazz {
+
+ private String code;
+ private String name;
+ @JsonIgnore private Double score;
+
+ public Clazz(String code, Double score) {
+ this.code = code;
+ this.score = score;
+ this.name = DetectionClassification.fromString(code).getDesc();
+ }
+
+ public Clazz(String code) {
+ this.code = code;
+ this.name = DetectionClassification.fromString(code).getDesc();
+ }
+ }
+
+ // classification info
+ @Getter
+ public static class Clazzes {
+
+ private DetectionClassification code;
+ private String name;
+
+ @JsonInclude(JsonInclude.Include.NON_NULL)
+ private Double score;
+
+ private Integer order;
+
+ public Clazzes(DetectionClassification classification, Double score) {
+ this.code = classification;
+ this.name = classification.getDesc();
+ this.order = classification.getOrder();
+ this.score = score;
+ }
+
+ public Clazzes(DetectionClassification classification) {
+ this.code = classification;
+ this.name = classification.getDesc();
+ this.order = classification.getOrder();
+ }
+ }
+
+ // 좌표 정보 point
+ @Getter
+ public static class Coordinate {
+
+ private Double lon; // 경도(Longitude)
+ private Double lat; // 위도(Latitude)
+ private String srid; // Spatial Reference ID의 약자로, 데이터베이스에서 좌표계를 식별하는 고유 번호 추후enum으로
+
+ public Coordinate(Double lon, Double lat) {
+ this.lon = lon;
+ this.lat = lat;
+ this.srid = "EPSG:4326";
+ }
+ }
+
+ @Getter
+ public static class Geom {
+
+ UUID uuid;
+ String uid;
+ Integer compareYyyy;
+ Integer targetYyyy;
+ Double cdProb;
+ String classBeforeCd;
+ String classBeforeName;
+ Double classBeforeProb;
+ String classAfterCd;
+ String classAfterName;
+ Double classAfterProb;
+ Long mapSheetNum;
+ String mapSheetName;
+ String subUid;
+ String pnu;
+ String fitState;
+
+ public Geom(
+ UUID uuid,
+ String uid,
+ Integer compareYyyy,
+ Integer targetYyyy,
+ Double cdProb,
+ String classBeforeCd,
+ Double classBeforeProb,
+ String classAfterCd,
+ Double classAfterProb,
+ Long mapSheetNum,
+ String mapSheetName,
+ String subUid,
+ String pnu,
+ String fitState) {
+ this.uuid = uuid;
+ this.uid = uid;
+ this.compareYyyy = compareYyyy;
+ this.targetYyyy = targetYyyy;
+ this.cdProb = cdProb;
+ this.classBeforeCd = classBeforeCd;
+ this.classBeforeName = DetectionClassification.fromString(classBeforeCd).getDesc();
+ this.classBeforeProb = classBeforeProb;
+ this.classAfterCd = classAfterCd;
+ this.classAfterName = DetectionClassification.fromString(classAfterCd).getDesc();
+ this.classAfterProb = classAfterProb;
+ this.mapSheetNum = mapSheetNum;
+ this.mapSheetName = mapSheetName;
+ this.subUid = subUid;
+ this.pnu = pnu;
+ this.fitState = fitState;
+ }
+
+ @JsonProperty("fitState")
+ public String getFitState() {
+ return this.fitState == null ? null : this.fitState;
+ }
+
+ // @JsonIgnore String gemoStr;
+ // @JsonIgnore String geomCenterStr;
+ // JsonNode gemo;
+ // JsonNode geomCenter;
+
+ @JsonProperty("fitStateName")
+ public String fitStateName() {
+ return ImageryFitStatus.getDescByCode(this.fitState);
+ }
+ }
+
+ @Schema(name = "InferenceResultSearchReq", description = "분석결과 목록 요청 정보")
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class SearchReq {
+
+ // 검색 조건
+ private String statCode;
+ private String title;
+
+ // 페이징 파라미터
+ private int page = 0;
+ private int size = 20;
+
+ public Pageable toPageable() {
+ return PageRequest.of(page, size);
+ }
+ }
+
+ @Schema(name = "InferenceResultSearchReq", description = "분석결과 목록 요청 정보")
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class SearchGeoReq {
+
+ // 기준년도
+ private String targetClass;
+ // 비교년도
+ private String compareClass;
+ // 분석도엽
+ private Long mapSheetNum;
+
+ // 페이징 파라미터
+ private int page = 0;
+ private int size = 20;
+ private String sort;
+
+ public Pageable toPageable() {
+ if (sort != null && !sort.isEmpty()) {
+ String[] sortParams = sort.split(",");
+ String property = sortParams[0];
+ Sort.Direction direction =
+ sortParams.length > 1 ? Sort.Direction.fromString(sortParams[1]) : Sort.Direction.ASC;
+ return PageRequest.of(page, size, Sort.by(direction, property));
+ }
+ return PageRequest.of(page, size);
+ }
+ }
+
+ @Getter
+ @Setter
+ @AllArgsConstructor
+ @NoArgsConstructor
+ public static class InferenceBatchSheet {
+
+ private Long id;
+ private UUID uuid;
+ private Long m1BatchId;
+ private Long m2BatchId;
+ private Long m3BatchId;
+ private String status;
+ private String runningModelType;
+ private UUID m1ModelUuid;
+ private UUID m2ModelUuid;
+ private UUID m3ModelUuid;
+ private String uid;
+ }
+
+ @Schema(name = "AnalResultInfo", description = "추론결과 기본정보")
+ @Getter
+ @Setter
+ @AllArgsConstructor
+ @NoArgsConstructor
+ public static class AnalResultInfo {
+
+ private String analTitle;
+ private String modelVer1;
+ private String modelVer2;
+ private String modelVer3;
+ private Integer compareYyyy;
+ private Integer targetYyyy;
+ private String detectOption;
+ private String mapSheetScope;
+ @JsonFormatDttm private ZonedDateTime inferStartDttm;
+ @JsonFormatDttm private ZonedDateTime inferEndDttm;
+ private Integer stage;
+ private String elapsedDuration;
+ private String subUid;
+ private Boolean applyYn;
+ @JsonFormatDttm private ZonedDateTime applyDttm;
+
+ private String bboxGeom;
+ private String bboxCenterPoint;
+ private UUID inferenceUuid;
+
+ public AnalResultInfo(
+ String analTitle,
+ String modelVer1,
+ String modelVer2,
+ String modelVer3,
+ Integer compareYyyy,
+ Integer targetYyyy,
+ String detectOption,
+ String mapSheetScope,
+ ZonedDateTime inferStartDttm,
+ ZonedDateTime inferEndDttm,
+ Integer stage,
+ String subUid,
+ Boolean applyYn,
+ ZonedDateTime applyDttm,
+ UUID inferenceUuid) {
+ this.analTitle = analTitle;
+ this.modelVer1 = modelVer1;
+ this.modelVer2 = modelVer2;
+ this.modelVer3 = modelVer3;
+ this.compareYyyy = compareYyyy;
+ this.targetYyyy = targetYyyy;
+ this.detectOption = DetectOption.getDescByCode(detectOption);
+ this.mapSheetScope = MapSheetScope.getDescByCode(mapSheetScope);
+ this.inferStartDttm = inferStartDttm;
+ this.inferEndDttm = inferEndDttm;
+ this.stage = stage;
+ this.subUid = subUid;
+ this.applyYn = applyYn;
+ this.applyDttm = applyDttm;
+ Duration elapsed =
+ (inferStartDttm != null && inferEndDttm != null)
+ ? Duration.between(inferStartDttm, inferEndDttm)
+ : null;
+
+ if (elapsed != null) {
+ long seconds = elapsed.getSeconds();
+ long abs = Math.abs(seconds);
+
+ long h = abs / 3600;
+ long m = (abs % 3600) / 60;
+ long s = abs % 60;
+
+ this.elapsedDuration = String.format("%02d:%02d:%02d", h, m, s);
+ }
+ this.inferenceUuid = inferenceUuid;
+ }
+
+ @JsonProperty("bboxGeom")
+ public JsonNode getBboxGeom() {
+ ObjectMapper mapper = new ObjectMapper();
+ try {
+ if (this.bboxGeom != null) {
+ return mapper.readTree(this.bboxGeom);
+ } else {
+ return null;
+ }
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @JsonProperty("bboxCenterPoint")
+ public JsonNode getBboxCenterPoint() {
+ ObjectMapper mapper = new ObjectMapper();
+ try {
+ if (this.bboxCenterPoint != null) {
+ return mapper.readTree(this.bboxCenterPoint);
+ } else {
+ return null;
+ }
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public Boolean getApplyYn() {
+ return this.applyYn != null && this.applyYn;
+ }
+ }
+
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class BboxPointDto {
+
+ private String bboxGeom;
+ private String bboxCenterPoint;
+ }
+
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class Scene {
+
+ private String path;
+ private Integer size;
+ }
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceResultDto.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceResultDto.java
new file mode 100644
index 0000000..2ee0526
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceResultDto.java
@@ -0,0 +1,679 @@
+package com.kamco.cd.kamcoback.inference.dto;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.kamco.cd.kamcoback.common.utils.enums.EnumType;
+import com.kamco.cd.kamcoback.common.utils.interfaces.EnumValid;
+import com.kamco.cd.kamcoback.common.utils.interfaces.JsonFormatDttm;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import java.time.Duration;
+import java.time.LocalDate;
+import java.time.ZonedDateTime;
+import java.util.Arrays;
+import java.util.List;
+import java.util.UUID;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+
+public class InferenceResultDto {
+
+ /** 분석대상 도엽 enum */
+ @Getter
+ @AllArgsConstructor
+ public enum MapSheetScope implements EnumType {
+ ALL("전체"),
+ PART("부분"),
+ ;
+
+ private final String desc;
+
+ public static MapSheetScope fromCode(String code) {
+ return Arrays.stream(values()).filter(v -> v.name().equals(code)).findFirst().orElse(null);
+ }
+
+ public static String getDescByCode(String code) {
+ return fromCode(code).getDesc();
+ }
+
+ @Override
+ public String getId() {
+ return name();
+ }
+
+ @Override
+ public String getText() {
+ return desc;
+ }
+ }
+
+ /** 탐지 데이터 옵션 dto */
+ @Getter
+ @AllArgsConstructor
+ public enum DetectOption implements EnumType {
+ EXCL("추론제외"),
+ PREV("이전 년도 도엽 사용"),
+ ;
+ private final String desc;
+
+ public static DetectOption fromCode(String code) {
+ return Arrays.stream(values()).filter(v -> v.name().equals(code)).findFirst().orElse(null);
+ }
+
+ public static String getDescByCode(String code) {
+ return fromCode(code).getDesc();
+ }
+
+ @Override
+ public String getId() {
+ return name();
+ }
+
+ @Override
+ public String getText() {
+ return desc;
+ }
+ }
+
+ @Getter
+ @AllArgsConstructor
+ public enum Status implements EnumType {
+ READY("대기"),
+ IN_PROGRESS("진행중"),
+ END("완료"),
+ FORCED_END("강제종료");
+ private final String desc;
+
+ public static Status fromCode(String code) {
+ return Arrays.stream(values()).filter(v -> v.name().equals(code)).findFirst().orElse(null);
+ }
+
+ public static String getDescByCode(String code) {
+ return fromCode(code).getDesc();
+ }
+
+ @Override
+ public String getId() {
+ return name();
+ }
+
+ @Override
+ public String getText() {
+ return desc;
+ }
+ }
+
+ @Getter
+ @AllArgsConstructor
+ public enum ServerStatus implements EnumType {
+ SAFETY("원활"),
+ CAUTION("주의"),
+ FAILUR("장애"),
+ ;
+
+ private final String desc;
+
+ @Override
+ public String getId() {
+ return name();
+ }
+
+ @Override
+ public String getText() {
+ return desc;
+ }
+ }
+
+ /** 목록조회 dto */
+ @Schema(name = "ResultList", description = "추론관리 목록")
+ @Getter
+ @Setter
+ @AllArgsConstructor
+ @NoArgsConstructor
+ public static class ResultList {
+
+ private UUID uuid;
+
+ @Schema(description = "제목")
+ private String title;
+
+ @Schema(description = "회차")
+ private Integer stage;
+
+ @Schema(description = "상태")
+ private String status;
+
+ @Schema(description = "분석 도엽")
+ private String mapSheetCnt;
+
+ @Schema(description = "탐지건수")
+ private Long detectingCnt;
+
+ @Schema(description = "시작일시")
+ @JsonFormatDttm
+ private ZonedDateTime startTime;
+
+ @Schema(description = "종료일시")
+ @JsonFormatDttm
+ private ZonedDateTime endTime;
+
+ @Schema(description = "반영여부")
+ private Boolean applyYn;
+
+ @Schema(description = "반영일시")
+ @JsonFormatDttm
+ private ZonedDateTime applyDttm;
+
+ @Schema(description = "비교년도")
+ private Integer compareYyyy;
+
+ @Schema(description = "기준년도")
+ private Integer targetYyyy;
+
+ @Schema(description = "uid")
+ private String uid;
+
+ @Schema(description = "uid 앞 8자리")
+ @JsonProperty("subUid")
+ public String subUid() {
+ return this.uid.substring(0, 8).toUpperCase();
+ }
+
+ @Schema(description = "상태명")
+ @JsonProperty("statusName")
+ public String statusName() {
+ return Status.getDescByCode(this.status);
+ }
+
+ @Schema(description = "소요시간")
+ @JsonProperty("elapsedTim")
+ public String getElapsedTime() {
+ if (this.startTime == null || this.endTime == null) {
+ return null;
+ }
+ ZonedDateTime start = this.startTime;
+ ZonedDateTime end = this.endTime;
+ Duration d = Duration.between(start, end);
+
+ if (d.isNegative()) {
+ d = d.negated();
+ }
+
+ long s = d.getSeconds();
+ long h = s / 3600;
+ long m = (s % 3600) / 60;
+ long sec = s % 60;
+
+ return String.format("%d시간 %d분 %d초", h, m, sec);
+ }
+ }
+
+ /** 목록조회 검색 조건 dto */
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class SearchListReq {
+
+ // 검색 조건
+ private String applyYn;
+ private LocalDate strtDttm;
+ private LocalDate endDttm;
+ private String title;
+
+ // 페이징 파라미터
+ private int page = 0;
+ private int size = 20;
+
+ public Pageable toPageable() {
+ return PageRequest.of(page, size);
+ }
+ }
+
+ /** 변화탐지 실행 정보 저장 요청 정보 */
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class RegReq {
+
+ @Schema(description = "제목", example = "2023-2024 변화탐지 테스트")
+ @NotBlank
+ private String title;
+
+ @Schema(description = "M1", example = "b40e0f68-c1d8-49fc-93f9-a36270093861")
+ @NotNull
+ private UUID model1Uuid;
+
+ @Schema(description = "M2", example = "ec92b7d2-b5a3-4915-9bdf-35fb3ca8ad27")
+ @NotNull
+ private UUID model2Uuid;
+
+ @Schema(description = "M3", example = "37f45782-8ccf-4cf6-911c-a055a1510d39")
+ @NotNull
+ private UUID model3Uuid;
+
+ @Schema(description = "비교년도", example = "2023")
+ @NotNull
+ private Integer compareYyyy;
+
+ @Schema(description = "탐지년도", example = "2024")
+ @NotNull
+ private Integer targetYyyy;
+
+ @Schema(description = "분석대상 도엽 - 전체(ALL), 부분(PART)", example = "PART")
+ @NotBlank
+ @EnumValid(enumClass = MapSheetScope.class, message = "분석대상 도엽 옵션은 '전체', '부분' 만 사용 가능합니다.")
+ private String mapSheetScope;
+
+ @Schema(description = "탐지 데이터 옵션 - 추론제외(EXCL), 이전 년도 도엽 사용(PREV)", example = "EXCL")
+ @NotBlank
+ @EnumValid(
+ enumClass = DetectOption.class,
+ message = "탐지 데이터 옵션은 '추론제외', '이전 년도 도엽 사용' 만 사용 가능합니다.")
+ private String detectOption;
+
+ @Schema(description = "5k 도협 번호 목록", example = "[33605,33606, 33610, 34802, 35603, 35611]")
+ @NotNull
+ private List mapSheetNum;
+ }
+
+ @Getter
+ @Setter
+ public static class MapSheetNumDto {
+
+ private String mapSheetNum;
+ private String mapSheetName;
+ }
+
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @Schema(name = "InferenceStatusDetailDto", description = "추론(변화탐지) 진행상태")
+ public static class InferenceStatusDetailDto {
+
+ @Schema(description = "탐지대상 도엽수")
+ private Long detectingCnt;
+
+ @Schema(description = "모델1 분석 대기")
+ private Integer m1PendingJobs;
+
+ @Schema(description = "모델2 분석 대기")
+ private Integer m2PendingJobs;
+
+ @Schema(description = "모델3 분석 대기")
+ private Integer m3PendingJobs;
+
+ @Schema(description = "모델1 분석 진행중")
+ private Integer m1RunningJobs;
+
+ @Schema(description = "모델2 분석 진행중")
+ private Integer m2RunningJobs;
+
+ @Schema(description = "모델3 분석 진행중")
+ private Integer m3RunningJobs;
+
+ @Schema(description = "모델1 분석 완료")
+ private Integer m1CompletedJobs;
+
+ @Schema(description = "모델2 분석 완료")
+ private Integer m2CompletedJobs;
+
+ @Schema(description = "모델3 분석 완료")
+ private Integer m3CompletedJobs;
+
+ @Schema(description = "모델1 분석 실패")
+ private Integer m1FailedJobs;
+
+ @Schema(description = "모델2 분석 실패")
+ private Integer m2FailedJobs;
+
+ @Schema(description = "모델3 분석 실패")
+ private Integer m3FailedJobs;
+
+ @Schema(description = "모델1 사용시간 시작일시")
+ @JsonFormatDttm
+ ZonedDateTime m1ModelStartDttm;
+
+ @Schema(description = "모델2 사용시간 시작일시")
+ @JsonFormatDttm
+ ZonedDateTime m2ModelStartDttm;
+
+ @Schema(description = "모델3 사용시간 시작일시")
+ @JsonFormatDttm
+ ZonedDateTime m3ModelStartDttm;
+
+ @Schema(description = "모델1 사용시간 종료일시")
+ @JsonFormatDttm
+ ZonedDateTime m1ModelEndDttm;
+
+ @Schema(description = "모델2 사용시간 종료일시")
+ @JsonFormatDttm
+ ZonedDateTime m2ModelEndDttm;
+
+ @Schema(description = "모델3 사용시간 종료일시")
+ @JsonFormatDttm
+ ZonedDateTime m3ModelEndDttm;
+
+ @Schema(description = "변화탐지 제목")
+ private String title;
+
+ @Schema(description = "비교년도")
+ private Integer compareYyyy;
+
+ @Schema(description = "기준년도")
+ private Integer targetYyyy;
+
+ @Schema(description = "회차")
+ private Integer stage;
+
+ @Schema(description = "변화탐지 시작")
+ @JsonFormatDttm
+ private ZonedDateTime inferStartDttm;
+
+ @Schema(description = "변화탐지 종료")
+ @JsonFormatDttm
+ private ZonedDateTime inferEndDttm;
+
+ @Schema(description = "변화탐지 옵션")
+ private String detectOption;
+
+ @Schema(description = "분석도엽")
+ private String mapSheetScope;
+
+ @Schema(description = "모델1 버전")
+ private String modelVer1;
+
+ @Schema(description = "모델2 버전")
+ private String modelVer2;
+
+ @Schema(description = "모델3 버전")
+ private String modelVer3;
+
+ @Schema(description = "탑지 도엽 수")
+ @JsonIgnore
+ private Long totalJobs;
+
+ public InferenceStatusDetailDto(
+ Long detectingCnt,
+ Integer m1PendingJobs,
+ Integer m2PendingJobs,
+ Integer m3PendingJobs,
+ Integer m1RunningJobs,
+ Integer m2RunningJobs,
+ Integer m3RunningJobs,
+ Integer m1CompletedJobs,
+ Integer m2CompletedJobs,
+ Integer m3CompletedJobs,
+ Integer m1FailedJobs,
+ Integer m2FailedJobs,
+ Integer m3FailedJobs,
+ ZonedDateTime m1ModelStartDttm,
+ ZonedDateTime m2ModelStartDttm,
+ ZonedDateTime m3ModelStartDttm,
+ ZonedDateTime m1ModelEndDttm,
+ ZonedDateTime m2ModelEndDttm,
+ ZonedDateTime m3ModelEndDttm,
+ String title,
+ Integer compareYyyy,
+ Integer targetYyyy,
+ Integer stage,
+ ZonedDateTime inferStartDttm,
+ ZonedDateTime inferEndDttm,
+ String detectOption,
+ String mapSheetScope,
+ String modelVer1,
+ String modelVer2,
+ String modelVer3,
+ Long totalJobs) {
+ this.detectingCnt = detectingCnt;
+ this.m1PendingJobs = m1PendingJobs;
+ this.m2PendingJobs = m2PendingJobs;
+ this.m3PendingJobs = m3PendingJobs;
+ this.m1RunningJobs = m1RunningJobs;
+ this.m2RunningJobs = m2RunningJobs;
+ this.m3RunningJobs = m3RunningJobs;
+ this.m1CompletedJobs = m1CompletedJobs;
+ this.m2CompletedJobs = m2CompletedJobs;
+ this.m3CompletedJobs = m3CompletedJobs;
+ this.m1FailedJobs = m1FailedJobs;
+ this.m2FailedJobs = m2FailedJobs;
+ this.m3FailedJobs = m3FailedJobs;
+ this.m1ModelStartDttm = m1ModelStartDttm;
+ this.m2ModelStartDttm = m2ModelStartDttm;
+ this.m3ModelStartDttm = m3ModelStartDttm;
+ this.m1ModelEndDttm = m1ModelEndDttm;
+ this.m2ModelEndDttm = m2ModelEndDttm;
+ this.m3ModelEndDttm = m3ModelEndDttm;
+ this.title = title;
+ this.compareYyyy = compareYyyy;
+ this.targetYyyy = targetYyyy;
+ this.stage = stage;
+ this.inferStartDttm = inferStartDttm;
+ this.inferEndDttm = inferEndDttm;
+ this.detectOption = detectOption;
+ this.mapSheetScope = mapSheetScope;
+ this.modelVer1 = modelVer1;
+ this.modelVer2 = modelVer2;
+ this.modelVer3 = modelVer3;
+ this.totalJobs = totalJobs;
+ }
+
+ @Schema(description = "진행률")
+ @JsonProperty("progress")
+ private int getProgress() {
+ long tiles = this.totalJobs == null ? 0L : this.totalJobs; // 도엽수
+ int models = 3; // 모델 개수
+ int completed =
+ this.m1CompletedJobs
+ + this.m2CompletedJobs
+ + this.m3CompletedJobs
+ + this.m1FailedJobs
+ + this.m2FailedJobs
+ + this.m3FailedJobs; // 완료수
+
+ long total = tiles * models; // 전체 작업량
+ if (completed >= total) {
+ return 100;
+ }
+ return (int) ((completed * 100L) / total);
+ }
+
+ @Schema(description = "변화탐지 옵션명")
+ @JsonProperty("detectOptionName")
+ private String getDetectOptionName() {
+ return DetectOption.getDescByCode(this.detectOption);
+ }
+
+ @Schema(description = "분석도엽 명")
+ @JsonProperty("mapSheetScopeName")
+ private String getMapSheetScopeName() {
+ return MapSheetScope.getDescByCode(this.mapSheetScope);
+ }
+
+ @Schema(description = "M1 사용시간")
+ @JsonProperty("m1ElapsedTim")
+ public String getM1ElapsedTime() {
+ return formatElapsedTime(this.m1ModelStartDttm, this.m1ModelEndDttm);
+ }
+
+ @Schema(description = "M2 사용시간")
+ @JsonProperty("m2ElapsedTim")
+ public String getM2ElapsedTime() {
+ return formatElapsedTime(this.m2ModelStartDttm, this.m2ModelEndDttm);
+ }
+
+ @Schema(description = "M3 사용시간")
+ @JsonProperty("m3ElapsedTim")
+ public String getM3ElapsedTime() {
+ return formatElapsedTime(this.m3ModelStartDttm, this.m3ModelEndDttm);
+ }
+
+ private String formatElapsedTime(ZonedDateTime start, ZonedDateTime end) {
+ if (start == null || end == null) {
+ return null;
+ }
+
+ Duration d = Duration.between(start, end);
+ if (d.isNegative()) {
+ d = d.negated();
+ }
+
+ long s = d.getSeconds();
+ long h = s / 3600;
+ long m = (s % 3600) / 60;
+ long sec = s % 60;
+
+ return String.format("%d시간 %d분 %d초", h, m, sec);
+ }
+ }
+
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class InferenceServerStatusDto {
+
+ private String serverName;
+ @JsonIgnore private float cpu_user;
+ @JsonIgnore private float cpu_system;
+ @JsonIgnore private float memused;
+ private Long kbmemused;
+ private float gpuUtil;
+
+ // private String cpuStatusName;
+ // private String memStatusName;
+ // private String gpuStatusName;
+ // private float cpu_use_rate;
+ // private float gpu_use_rate;
+ // private float mem_use_rate;
+
+ public float getCpuUseRate() {
+ return this.cpu_user + this.cpu_system;
+ }
+
+ public String getServerStatus() {
+ String enumId = "SAFETY";
+ if (this.cpu_user + this.cpu_system + this.gpuUtil + this.kbmemused == 0) {
+ enumId = "FAILUR";
+ }
+ // if( this.cpu_user+this.cpu_system >= 80 )enumId = "CAUTION";
+ return enumId;
+ }
+
+ public String getServerStatusName() {
+ String enumStr = ServerStatus.SAFETY.getText();
+ if (this.cpu_user + this.cpu_system + this.gpuUtil + this.kbmemused == 0) {
+ enumStr = ServerStatus.FAILUR.getText();
+ }
+ return enumStr;
+ }
+
+ public String getCpuStatus() {
+ String enumId = "SAFETY";
+ if (this.cpu_user + this.cpu_system >= 80) {
+ enumId = "CAUTION";
+ } else if (this.cpu_user + this.cpu_system + this.memused == 0) {
+ enumId = "FAILUR";
+ }
+ return enumId;
+ }
+
+ public String getGpuStatus() {
+ String enumId = "SAFETY";
+ if (this.gpuUtil >= 80) {
+ enumId = "CAUTION";
+ } else if (this.cpu_user + this.cpu_system == 0) {
+ enumId = "FAILUR";
+ }
+ return enumId;
+ }
+
+ public String getMemStatus() {
+ String enumId = "SAFETY";
+ if (this.memused >= 80) {
+ enumId = "CAUTION";
+ } else if (this.cpu_user + this.cpu_system + this.memused == 0) {
+ enumId = "FAILUR";
+ }
+ return enumId;
+ }
+
+ public String getCpuStatusName() {
+ if (this.cpu_user + this.cpu_system >= 80) {
+ return ServerStatus.CAUTION.getText();
+ } else if (this.cpu_user + this.cpu_system + this.memused == 0) {
+ return ServerStatus.FAILUR.getText();
+ }
+ return ServerStatus.SAFETY.getText();
+ }
+
+ public String getGpuStatusName() {
+ if (this.gpuUtil >= 80) {
+ return ServerStatus.CAUTION.getText();
+ } else if (this.cpu_user + this.cpu_system + this.memused == 0) {
+ return ServerStatus.FAILUR.getText();
+ }
+ return ServerStatus.SAFETY.getText();
+ }
+
+ public String getMemStatusName() {
+ if (this.memused >= 80) {
+ return ServerStatus.CAUTION.getText();
+ } else if (this.cpu_user + this.cpu_system + this.memused == 0) {
+ return ServerStatus.FAILUR.getText();
+ }
+ return ServerStatus.SAFETY.getText();
+ }
+ }
+
+ @Getter
+ @Setter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class InferenceStatusDetailDto2 {
+
+ InferenceServerStatusDto serverStatus;
+ }
+
+ @Getter
+ @Setter
+ @AllArgsConstructor
+ @NoArgsConstructor
+ public static class SaveInferenceAiDto {
+
+ private UUID uuid;
+ private Long batchId;
+ private String status;
+ private String type;
+ private ZonedDateTime inferStartDttm;
+ private ZonedDateTime inferEndDttm;
+ private Long detectEndCnt;
+ private String modelComparePath;
+ private String modelTargetPath;
+ private String modelModelPath;
+ private ZonedDateTime modelStartDttm;
+ private ZonedDateTime modelEndDttm;
+ private Long updateUid;
+ private String runningModelType;
+ private Integer pendingJobs;
+ private Integer runningJobs;
+ private Integer completedJobs;
+ private Integer failedJobs;
+ }
+
+ @Getter
+ @Setter
+ public static class InferenceLearnDto {
+
+ private String uid;
+ private Long m1ModelBatchId;
+ private Long m2ModelBatchId;
+ private Long m3ModelBatchId;
+ }
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/inferface/CodeExpose.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/inferface/CodeExpose.java
new file mode 100644
index 0000000..aa50c0e
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/inferface/CodeExpose.java
@@ -0,0 +1,10 @@
+package com.kamco.cd.kamcoback.inferface;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface CodeExpose {}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/inferface/CodeHidden.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/inferface/CodeHidden.java
new file mode 100644
index 0000000..7516dfe
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/inferface/CodeHidden.java
@@ -0,0 +1,10 @@
+package com.kamco.cd.kamcoback.inferface;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface CodeHidden {}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/inferface/EnumType.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/inferface/EnumType.java
new file mode 100644
index 0000000..2fa5f21
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/inferface/EnumType.java
@@ -0,0 +1,8 @@
+package com.kamco.cd.kamcoback.inferface;
+
+public interface EnumType {
+
+ String getId();
+
+ String getText();
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/inferface/JsonFormatDttm.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/inferface/JsonFormatDttm.java
new file mode 100644
index 0000000..aabb352
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/inferface/JsonFormatDttm.java
@@ -0,0 +1,19 @@
+package com.kamco.cd.kamcoback.inferface;
+
+import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.FIELD, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@JacksonAnnotationsInside
+@JsonFormat(
+ shape = JsonFormat.Shape.STRING,
+ pattern = "yyyy-MM-dd'T'HH:mm:ssXXX",
+ timezone = "Asia/Seoul")
+public @interface JsonFormatDttm {}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/log/dto/EventStatus.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/log/dto/EventStatus.java
new file mode 100644
index 0000000..1768945
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/log/dto/EventStatus.java
@@ -0,0 +1,24 @@
+package com.kamco.cd.kamcoback.log.dto;
+
+import com.kamco.cd.kamcoback.common.utils.enums.EnumType;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum EventStatus implements EnumType {
+ SUCCESS("이벤트 결과 성공"),
+ FAILED("이벤트 결과 실패");
+
+ private final String desc;
+
+ @Override
+ public String getId() {
+ return name();
+ }
+
+ @Override
+ public String getText() {
+ return desc;
+ }
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/log/dto/EventType.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/log/dto/EventType.java
new file mode 100644
index 0000000..891429f
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/log/dto/EventType.java
@@ -0,0 +1,42 @@
+package com.kamco.cd.kamcoback.log.dto;
+
+import com.kamco.cd.kamcoback.common.utils.enums.CodeExpose;
+import com.kamco.cd.kamcoback.common.utils.enums.EnumType;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@CodeExpose
+@Getter
+@AllArgsConstructor
+public enum EventType implements EnumType {
+ LIST("목록"),
+ DETAIL("상세"),
+ POPUP("팝업"),
+ STATUS("상태"),
+ ADDED("추가"),
+ MODIFIED("수정"),
+ REMOVE("삭제"),
+ DOWNLOAD("다운로드"),
+ LOGIN("로그인"),
+ OTHER("기타");
+
+ private final String desc;
+
+ public static EventType fromName(String name) {
+ try {
+ return EventType.valueOf(name.toUpperCase());
+ } catch (Exception e) {
+ return OTHER;
+ }
+ }
+
+ @Override
+ public String getId() {
+ return name();
+ }
+
+ @Override
+ public String getText() {
+ return desc;
+ }
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/core/GukYuinJobCoreService.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/core/GukYuinJobCoreService.java
new file mode 100644
index 0000000..c8dbb13
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/core/GukYuinJobCoreService.java
@@ -0,0 +1,25 @@
+package com.kamco.cd.kamcoback.postgres.core;
+
+import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.LearnKeyDto;
+import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinStatus;
+import com.kamco.cd.kamcoback.postgres.repository.gukyuin.GukYuinRepository;
+import java.util.List;
+import org.springframework.stereotype.Service;
+
+@Service
+public class GukYuinJobCoreService {
+
+ private final GukYuinRepository gukYuinRepository;
+
+ public GukYuinJobCoreService(GukYuinRepository gukYuinRepository) {
+ this.gukYuinRepository = gukYuinRepository;
+ }
+
+ public void updateGukYuinApplyStateComplete(Long id, GukYuinStatus status) {
+ gukYuinRepository.updateGukYuinApplyStateComplete(id, status);
+ }
+
+ public List findGukyuinApplyStatusUidList(List gukYuinStatus) {
+ return gukYuinRepository.findGukyuinApplyStatusUidList(gukYuinStatus);
+ }
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/CommonCreateEntity.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/CommonCreateEntity.java
new file mode 100644
index 0000000..94374fe
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/CommonCreateEntity.java
@@ -0,0 +1,22 @@
+package com.kamco.cd.kamcoback.postgres.entity;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.MappedSuperclass;
+import jakarta.persistence.PrePersist;
+import java.time.ZonedDateTime;
+import lombok.Getter;
+import org.springframework.data.annotation.CreatedDate;
+
+@Getter
+@MappedSuperclass
+public class CommonCreateEntity {
+
+ @CreatedDate
+ @Column(name = "created_dttm", updatable = false, nullable = false)
+ private ZonedDateTime createdDate;
+
+ @PrePersist
+ protected void onPersist() {
+ this.createdDate = ZonedDateTime.now();
+ }
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/CommonDateEntity.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/CommonDateEntity.java
new file mode 100644
index 0000000..cb9abe9
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/CommonDateEntity.java
@@ -0,0 +1,34 @@
+package com.kamco.cd.kamcoback.postgres.entity;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.MappedSuperclass;
+import jakarta.persistence.PrePersist;
+import jakarta.persistence.PreUpdate;
+import java.time.ZonedDateTime;
+import lombok.Getter;
+import org.springframework.data.annotation.CreatedDate;
+import org.springframework.data.annotation.LastModifiedDate;
+
+@Getter
+@MappedSuperclass
+public class CommonDateEntity {
+
+ @CreatedDate
+ @Column(name = "created_dttm", updatable = false, nullable = false)
+ private ZonedDateTime createdDate;
+
+ @LastModifiedDate
+ @Column(name = "updated_dttm", nullable = false)
+ private ZonedDateTime modifiedDate;
+
+ @PrePersist
+ protected void onPersist() {
+ this.createdDate = ZonedDateTime.now();
+ this.modifiedDate = ZonedDateTime.now();
+ }
+
+ @PreUpdate
+ protected void onUpdate() {
+ this.modifiedDate = ZonedDateTime.now();
+ }
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/LabelingAssignmentEntity.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/LabelingAssignmentEntity.java
new file mode 100644
index 0000000..0e0abea
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/LabelingAssignmentEntity.java
@@ -0,0 +1,69 @@
+package com.kamco.cd.kamcoback.postgres.entity;
+
+import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import java.time.ZonedDateTime;
+import java.util.UUID;
+
+@Entity
+@Table(name = "tb_labeling_assignment")
+public class LabelingAssignmentEntity extends CommonDateEntity {
+
+ @Id
+ @Column(name = "assignment_uid")
+ private UUID assignmentUid;
+
+ @Column(name = "inference_geom_uid")
+ private Long inferenceGeomUid;
+
+ @Column(name = "worker_uid")
+ private String workerUid;
+
+ @Column(name = "inspector_uid")
+ private String inspectorUid;
+
+ @Column(name = "work_state")
+ private String workState;
+
+ @Column(name = "stagnation_yn")
+ private Character stagnationYn;
+
+ @Column(name = "assign_group_id")
+ private String assignGroupId;
+
+ @Column(name = "learn_geom_uid")
+ private Long learnGeomUid;
+
+ @Column(name = "anal_uid")
+ private Long analUid;
+
+ @Column(name = "inspect_state")
+ private String inspectState;
+
+ @Column(name = "work_stat_dttm")
+ private ZonedDateTime workStatDttm;
+
+ @Column(name = "inspect_stat_dttm")
+ private ZonedDateTime inspectStatDttm;
+
+ public LabelAllocateDto.Basic toDto() {
+ return new LabelAllocateDto.Basic(
+ this.assignmentUid,
+ this.inferenceGeomUid,
+ this.workerUid,
+ this.inspectorUid,
+ this.workState,
+ this.stagnationYn,
+ this.assignGroupId,
+ this.learnGeomUid,
+ this.analUid,
+ super.getCreatedDate(),
+ super.getModifiedDate(),
+ this.inspectState,
+ this.workStatDttm,
+ this.inspectStatDttm);
+ }
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/LabelingInspectorEntity.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/LabelingInspectorEntity.java
new file mode 100644
index 0000000..c378179
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/LabelingInspectorEntity.java
@@ -0,0 +1,32 @@
+package com.kamco.cd.kamcoback.postgres.entity;
+
+import com.kamco.cd.kamcoback.label.dto.LabelInspectorDto;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import java.util.UUID;
+
+@Entity
+@Table(name = "tb_labeling_inspector")
+public class LabelingInspectorEntity extends CommonDateEntity {
+
+ @Id
+ @Column(name = "operator_uid")
+ private UUID operatorUid;
+
+ @Column(name = "anal_uid")
+ private Long analUid;
+
+ @Column(name = "inspector_uid")
+ private String inspectorUid;
+
+ public LabelInspectorDto.Basic toDto() {
+ return new LabelInspectorDto.Basic(
+ this.operatorUid,
+ this.analUid,
+ this.inspectorUid,
+ super.getCreatedDate(),
+ super.getModifiedDate());
+ }
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapInkx50kEntity.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapInkx50kEntity.java
new file mode 100644
index 0000000..c483e5c
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapInkx50kEntity.java
@@ -0,0 +1,48 @@
+package com.kamco.cd.kamcoback.postgres.entity;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.SequenceGenerator;
+import jakarta.persistence.Table;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import org.locationtech.jts.geom.Geometry;
+
+@Getter
+@Setter
+@Table(name = "tb_map_inkx_50k")
+@Entity
+@NoArgsConstructor
+public class MapInkx50kEntity extends CommonDateEntity {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "tb_map_inkx_50k_fid_seq_gen")
+ @SequenceGenerator(
+ name = "tb_map_inkx_50k_fid_seq_gen",
+ sequenceName = "tb_map_inkx_50k_fid_seq",
+ allocationSize = 1)
+ private Integer fid;
+
+ @Column(name = "mapidcd_no")
+ private String mapidcdNo;
+
+ @Column(name = "mapid_nm")
+ private String mapidNm;
+
+ @Column(name = "mapid_no")
+ private String mapidNo;
+
+ @Column(name = "geom")
+ private Geometry geom;
+
+ public MapInkx50kEntity(String mapidcdNo, String mapidNm, String mapidNo, Geometry geom) {
+ this.mapidcdNo = mapidcdNo;
+ this.mapidNm = mapidNm;
+ this.mapidNo = mapidNo;
+ this.geom = geom;
+ }
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapInkx5kEntity.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapInkx5kEntity.java
new file mode 100644
index 0000000..3246924
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapInkx5kEntity.java
@@ -0,0 +1,75 @@
+package com.kamco.cd.kamcoback.postgres.entity;
+
+import com.kamco.cd.kamcoback.enums.CommonUseStatus;
+import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto;
+import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.MapSheet;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EnumType;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.SequenceGenerator;
+import jakarta.persistence.Table;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import org.locationtech.jts.geom.Geometry;
+
+@Getter
+@Setter
+@Table(name = "tb_map_inkx_5k")
+@Entity
+@NoArgsConstructor
+public class MapInkx5kEntity extends CommonDateEntity {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "tb_map_inkx_5k_fid_seq_gen")
+ @SequenceGenerator(
+ name = "tb_map_inkx_5k_fid_seq_gen",
+ sequenceName = "tb_map_inkx_5k_fid_seq",
+ allocationSize = 1)
+ private Integer fid;
+
+ @Column(name = "mapidcd_no")
+ private String mapidcdNo;
+
+ @Column(name = "mapid_nm")
+ private String mapidNm;
+
+ @Column(name = "geom")
+ private Geometry geom;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "fid_k50", referencedColumnName = "fid")
+ private MapInkx50kEntity mapInkx50k;
+
+ // 사용상태 USE,
+ @Column(name = "use_inference")
+ @Enumerated(EnumType.STRING)
+ private CommonUseStatus useInference;
+
+ public InferenceDetailDto.MapSheet toEntity() {
+ return new MapSheet(mapidcdNo, mapidNm);
+ }
+
+ // Constructor
+ public MapInkx5kEntity(
+ String mapidcdNo, String mapidNm, Geometry geom, MapInkx50kEntity mapInkx50k) {
+ this.mapidcdNo = mapidcdNo;
+ this.mapidNm = mapidNm;
+ this.geom = geom;
+ this.mapInkx50k = mapInkx50k;
+ // 생성시 default 사용함 (사용,제외,사용안함)
+ this.useInference = CommonUseStatus.USE;
+ }
+
+ // 변경 사용상태 (추론사용여부)
+ public void updateUseInference(CommonUseStatus useInference) {
+ this.useInference = useInference;
+ }
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalDataInferenceGeomEntity.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalDataInferenceGeomEntity.java
new file mode 100644
index 0000000..c0487a1
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalDataInferenceGeomEntity.java
@@ -0,0 +1,181 @@
+package com.kamco.cd.kamcoback.postgres.entity;
+
+import com.kamco.cd.kamcoback.inference.dto.DetectionClassification;
+import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto;
+import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.Clazzes;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import jakarta.validation.constraints.Size;
+import java.time.ZonedDateTime;
+import java.util.UUID;
+import lombok.Getter;
+import lombok.Setter;
+import org.hibernate.annotations.ColumnDefault;
+import org.locationtech.jts.geom.Geometry;
+
+@Getter
+@Setter
+@Entity
+@Table(name = "tb_map_sheet_anal_data_inference_geom")
+public class MapSheetAnalDataInferenceGeomEntity {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "geo_uid")
+ private Long geoUid;
+
+ @Column(name = "cd_prob")
+ private Double cdProb;
+
+ @Size(max = 40)
+ @Column(name = "class_before_cd", length = 40)
+ private String classBeforeCd;
+
+ @Column(name = "class_before_prob")
+ private Double classBeforeProb;
+
+ @Size(max = 40)
+ @Column(name = "class_after_cd", length = 40)
+ private String classAfterCd;
+
+ @Column(name = "class_after_prob")
+ private Double classAfterProb;
+
+ @Column(name = "map_sheet_num")
+ private Long mapSheetNum;
+
+ @Column(name = "compare_yyyy")
+ private Integer compareYyyy;
+
+ @Column(name = "target_yyyy")
+ private Integer targetYyyy;
+
+ @Column(name = "area")
+ private Double area;
+
+ @Size(max = 100)
+ @Column(name = "geo_type", length = 100)
+ private String geoType;
+
+ @Column(name = "data_uid")
+ private Long dataUid;
+
+ @ColumnDefault("now()")
+ @Column(name = "created_dttm")
+ private ZonedDateTime createdDttm;
+
+ @Column(name = "created_uid")
+ private Long createdUid;
+
+ @ColumnDefault("now()")
+ @Column(name = "updated_dttm")
+ private ZonedDateTime updatedDttm;
+
+ @Column(name = "updated_uid")
+ private Long updatedUid;
+
+ @ColumnDefault("0")
+ @Column(name = "geom_cnt")
+ private Long geomCnt;
+
+ @ColumnDefault("0")
+ @Column(name = "pnu")
+ private Long pnu;
+
+ @Size(max = 20)
+ @Column(name = "fit_state", length = 20)
+ private String fitState;
+
+ @ColumnDefault("now()")
+ @Column(name = "fit_state_dttm")
+ private ZonedDateTime fitStateDttm;
+
+ @Column(name = "labeler_uid")
+ private Long labelerUid;
+
+ @Size(max = 20)
+ @ColumnDefault("'0'")
+ @Column(name = "label_state", length = 20)
+ private String labelState;
+
+ @ColumnDefault("now()")
+ @Column(name = "label_state_dttm")
+ private ZonedDateTime labelStateDttm;
+
+ @Column(name = "tester_uid")
+ private Long testerUid;
+
+ @Size(max = 20)
+ @ColumnDefault("'0'")
+ @Column(name = "test_state", length = 20)
+ private String testState;
+
+ @ColumnDefault("now()")
+ @Column(name = "test_state_dttm")
+ private ZonedDateTime testStateDttm;
+
+ @Column(name = "fit_state_cmmnt", length = Integer.MAX_VALUE)
+ private String fitStateCmmnt;
+
+ @Column(name = "ref_map_sheet_num")
+ private Long refMapSheetNum;
+
+ @ColumnDefault("uuid_generate_v4()")
+ @Column(name = "uuid")
+ private UUID uuid;
+
+ @Column(name = "stage")
+ private Integer stage;
+
+ @Column(name = "file_created_yn")
+ private Boolean fileCreatedYn;
+
+ @Column(name = "geom", columnDefinition = "geometry")
+ private Geometry geom;
+
+ @Column(name = "geom_center", columnDefinition = "geometry")
+ private Geometry geomCenter;
+
+ @Column(name = "before_geom", columnDefinition = "geometry")
+ private Geometry beforeGeom;
+
+ @Column(name = "file_created_dttm")
+ private ZonedDateTime fileCreatedDttm;
+
+ @Column(name = "result_uid")
+ private String resultUid;
+
+ @ManyToOne(fetch = FetchType.EAGER)
+ @JoinColumn(name = "map_5k_id", referencedColumnName = "fid")
+ private MapInkx5kEntity map5k;
+
+ @Column(name = "label_send_dttm")
+ private ZonedDateTime labelSendDttm;
+
+ @Column(name = "lock_yn")
+ private String lockYn;
+
+ public InferenceDetailDto.DetailListEntity toEntity() {
+ DetectionClassification classification = DetectionClassification.fromString(classBeforeCd);
+ Clazzes comparedClazz = new Clazzes(classification, classBeforeProb);
+ DetectionClassification classification1 = DetectionClassification.fromString(classAfterCd);
+ Clazzes targetClazz = new Clazzes(classification1, classAfterProb);
+ InferenceDetailDto.MapSheet mapSheet = map5k != null ? map5k.toEntity() : null;
+
+ InferenceDetailDto.Coordinate coordinate = null;
+ if (geomCenter != null) {
+ org.locationtech.jts.geom.Point point = (org.locationtech.jts.geom.Point) geomCenter;
+ coordinate = new InferenceDetailDto.Coordinate(point.getX(), point.getY());
+ }
+
+ return new InferenceDetailDto.DetailListEntity(
+ uuid, cdProb, comparedClazz, targetClazz, mapSheet, coordinate, createdDttm);
+ }
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalInferenceEntity.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalInferenceEntity.java
new file mode 100644
index 0000000..cfbbf42
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalInferenceEntity.java
@@ -0,0 +1,165 @@
+package com.kamco.cd.kamcoback.postgres.entity;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.SequenceGenerator;
+import jakarta.persistence.Table;
+import jakarta.validation.constraints.Size;
+import java.time.ZonedDateTime;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import lombok.Getter;
+import lombok.Setter;
+import org.hibernate.annotations.ColumnDefault;
+import org.hibernate.annotations.JdbcTypeCode;
+import org.hibernate.type.SqlTypes;
+
+@Getter
+@Setter
+@Entity
+@Table(name = "tb_map_sheet_anal_inference")
+public class MapSheetAnalInferenceEntity {
+
+ @Id
+ @GeneratedValue(
+ strategy = GenerationType.SEQUENCE,
+ generator = "tb_map_sheet_anal_inference_id_gen")
+ @SequenceGenerator(
+ name = "tb_map_sheet_anal_inference_id_gen",
+ sequenceName = "tb_map_sheet_anal_inference_uid",
+ allocationSize = 1)
+ @Column(name = "anal_uid", nullable = false)
+ private Long id;
+
+ @Column(name = "compare_yyyy")
+ private Integer compareYyyy;
+
+ @Column(name = "target_yyyy")
+ private Integer targetYyyy;
+
+ @Column(name = "model_uid")
+ private Long modelUid;
+
+ @Size(max = 100)
+ @Column(name = "server_ids", length = 100)
+ private String serverIds;
+
+ @Column(name = "anal_strt_dttm")
+ private ZonedDateTime analStrtDttm;
+
+ @Column(name = "anal_end_dttm")
+ private ZonedDateTime analEndDttm;
+
+ @Column(name = "anal_sec")
+ private Long analSec;
+
+ @Size(max = 20)
+ @Column(name = "anal_state", length = 20)
+ private String analState;
+
+ @Size(max = 20)
+ @Column(name = "gukyuin_used", length = 20)
+ private String gukyuinUsed;
+
+ @Column(name = "accuracy")
+ private Double accuracy;
+
+ @Size(max = 255)
+ @Column(name = "result_url")
+ private String resultUrl;
+
+ @ColumnDefault("now()")
+ @Column(name = "created_dttm")
+ private ZonedDateTime createdDttm;
+
+ @Column(name = "created_uid")
+ private Long createdUid;
+
+ @ColumnDefault("now()")
+ @Column(name = "updated_dttm")
+ private ZonedDateTime updatedDttm;
+
+ @Column(name = "updated_uid")
+ private Long updatedUid;
+
+ @Size(max = 255)
+ @Column(name = "anal_title")
+ private String analTitle;
+
+ @Column(name = "detecting_cnt")
+ private Long detectingCnt;
+
+ @Column(name = "anal_pred_sec")
+ private Long analPredSec;
+
+ @Column(name = "model_ver_uid")
+ private Long modelVerUid;
+
+ @Column(name = "hyper_params")
+ @JdbcTypeCode(SqlTypes.JSON)
+ private Map hyperParams;
+
+ @Column(name = "tranning_rate")
+ private List tranningRate;
+
+ @Column(name = "validation_rate")
+ private List validationRate;
+
+ @Column(name = "test_rate", length = Integer.MAX_VALUE)
+ private String testRate;
+
+ @Size(max = 128)
+ @Column(name = "detecting_description", length = 128)
+ private String detectingDescription;
+
+ @Size(max = 12)
+ @Column(name = "base_map_sheet_num", length = 12)
+ private String baseMapSheetNum;
+
+ @ColumnDefault("gen_random_uuid()")
+ @Column(name = "uuid")
+ private UUID uuid;
+
+ @Size(max = 50)
+ @Column(name = "model_m1_ver", length = 50)
+ private String modelM1Ver;
+
+ @Size(max = 50)
+ @Column(name = "model_m2_ver", length = 50)
+ private String modelM2Ver;
+
+ @Size(max = 50)
+ @Column(name = "model_m3_ver", length = 50)
+ private String modelM3Ver;
+
+ @Size(max = 20)
+ @Column(name = "anal_target_type", length = 20)
+ private String analTargetType;
+
+ @Column(name = "gukyuin_apply_dttm")
+ private ZonedDateTime gukyuinApplyDttm;
+
+ @Size(max = 20)
+ @Column(name = "detection_data_option", length = 20)
+ private String detectionDataOption;
+
+ @Column(name = "stage")
+ private Integer stage;
+
+ @Size(max = 1)
+ @ColumnDefault("'N'")
+ @Column(name = "labeling_closed_yn", length = 1)
+ private String labelingClosedYn = "N";
+
+ @Size(max = 1)
+ @ColumnDefault("'N'")
+ @Column(name = "inspection_closed_yn", length = 1)
+ private String inspectionClosedYn = "N";
+
+ @Column(name = "learn_id")
+ private Long learnId;
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetLearnDataGeomEntity.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetLearnDataGeomEntity.java
new file mode 100644
index 0000000..d560d54
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetLearnDataGeomEntity.java
@@ -0,0 +1,45 @@
+package com.kamco.cd.kamcoback.postgres.entity;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import lombok.Getter;
+import lombok.Setter;
+import org.locationtech.jts.geom.Geometry;
+
+/** 라벨링 툴에서 그린 폴리곤 저장 테이블 */
+@Getter
+@Setter
+@Entity
+@Table(name = "tb_map_sheet_learn_data_geom")
+public class MapSheetLearnDataGeomEntity extends CommonDateEntity {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "geo_uid", nullable = false)
+ private Long geoUid;
+
+ @Column(name = "after_yyyy")
+ private Integer afterYyyy;
+
+ @Column(name = "area")
+ private Double area;
+
+ @Column(name = "before_yyyy")
+ private Integer beforeYyyy;
+
+ @Column(name = "class_after_cd")
+ private String classAfterCd;
+
+ @Column(name = "class_before_cd")
+ private String classBeforeCd;
+
+ @Column(name = "geom")
+ private Geometry geom;
+
+ @Column(name = "file_create_yn")
+ private Boolean fileCreateYn;
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetLearnEntity.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetLearnEntity.java
new file mode 100644
index 0000000..a161c05
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetLearnEntity.java
@@ -0,0 +1,221 @@
+package com.kamco.cd.kamcoback.postgres.entity;
+
+import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinStatus;
+import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.SequenceGenerator;
+import jakarta.persistence.Table;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import java.time.ZonedDateTime;
+import java.util.UUID;
+import lombok.Getter;
+import lombok.Setter;
+import org.hibernate.annotations.ColumnDefault;
+
+@Getter
+@Setter
+@Entity
+@Table(name = "tb_map_sheet_learn")
+public class MapSheetLearnEntity {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "tb_map_sheet_learn_id_gen")
+ @SequenceGenerator(
+ name = "tb_map_sheet_learn_id_gen",
+ sequenceName = "tb_map_sheet_learn_uid",
+ allocationSize = 1)
+ @Column(name = "id", nullable = false)
+ private Long id;
+
+ @ColumnDefault("gen_random_uuid()")
+ @Column(name = "uuid")
+ private UUID uuid = UUID.randomUUID();
+
+ @Size(max = 200)
+ @NotNull
+ @Column(name = "title", nullable = false, length = 200)
+ private String title;
+
+ @Size(max = 20)
+ @Column(name = "status", length = 10)
+ private String status;
+
+ @Column(name = "m1_model_uuid")
+ private UUID m1ModelUuid;
+
+ @Column(name = "m2_model_uuid")
+ private UUID m2ModelUuid;
+
+ @Column(name = "m3_model_uuid")
+ private UUID m3ModelUuid;
+
+ @Column(name = "compare_yyyy")
+ private Integer compareYyyy;
+
+ @Column(name = "target_yyyy")
+ private Integer targetYyyy;
+
+ @Size(max = 20)
+ @Column(name = "detect_option", length = 20)
+ private String detectOption;
+
+ @Size(max = 100)
+ @Column(name = "map_sheet_cnt", length = 100)
+ private String mapSheetCnt;
+
+ @Size(max = 20)
+ @Column(name = "map_sheet_scope", length = 20)
+ private String mapSheetScope;
+
+ @Column(name = "detecting_cnt")
+ private Long detectingCnt;
+
+ @Column(name = "infer_start_dttm")
+ private ZonedDateTime inferStartDttm;
+
+ @Column(name = "infer_end_dttm")
+ private ZonedDateTime inferEndDttm;
+
+ @Column(name = "elapsed_time")
+ private ZonedDateTime elapsedTime;
+
+ @Column(name = "apply_yn")
+ private Boolean applyYn;
+
+ @Column(name = "apply_dttm")
+ private ZonedDateTime applyDttm;
+
+ @org.hibernate.annotations.CreationTimestamp
+ @Column(name = "created_dttm")
+ private ZonedDateTime createdDttm;
+
+ @Column(name = "created_uid")
+ private Long createdUid;
+
+ @ColumnDefault("now()")
+ @Column(name = "updated_dttm")
+ private ZonedDateTime updatedDttm;
+
+ @Column(name = "updated_uid")
+ private Long updatedUid;
+
+ @Column(name = "running_model_type")
+ private String runningModelType;
+
+ @Column(name = "detect_end_cnt")
+ private Long detectEndCnt;
+
+ @Column(name = "model_compare_path")
+ private String modelComparePath;
+
+ @Column(name = "model_target_path")
+ private String modelTargetPath;
+
+ @Column(name = "stage")
+ private Integer stage;
+
+ /* ===================== M1 ===================== */
+
+ @Column(name = "m1_model_batch_id")
+ private Long m1ModelBatchId;
+
+ @Column(name = "m1_model_start_dttm")
+ private ZonedDateTime m1ModelStartDttm;
+
+ @Column(name = "m1_model_end_dttm")
+ private ZonedDateTime m1ModelEndDttm;
+
+ @Column(name = "m1_pending_jobs", nullable = false)
+ private int m1PendingJobs = 0;
+
+ @Column(name = "m1_running_jobs", nullable = false)
+ private int m1RunningJobs = 0;
+
+ @Column(name = "m1_completed_jobs", nullable = false)
+ private int m1CompletedJobs = 0;
+
+ @Column(name = "m1_failed_jobs", nullable = false)
+ private int m1FailedJobs = 0;
+
+ /* ===================== M2 ===================== */
+
+ @Column(name = "m2_model_batch_id")
+ private Long m2ModelBatchId;
+
+ @Column(name = "m2_model_start_dttm")
+ private ZonedDateTime m2ModelStartDttm;
+
+ @Column(name = "m2_model_end_dttm")
+ private ZonedDateTime m2ModelEndDttm;
+
+ @Column(name = "m2_pending_jobs", nullable = false)
+ private int m2PendingJobs = 0;
+
+ @Column(name = "m2_running_jobs", nullable = false)
+ private int m2RunningJobs = 0;
+
+ @Column(name = "m2_completed_jobs", nullable = false)
+ private int m2CompletedJobs = 0;
+
+ @Column(name = "m2_failed_jobs", nullable = false)
+ private int m2FailedJobs = 0;
+
+ /* ===================== M3 ===================== */
+ @Column(name = "m3_model_batch_id")
+ private Long m3ModelBatchId;
+
+ @Column(name = "m3_model_start_dttm")
+ private ZonedDateTime m3ModelStartDttm;
+
+ @Column(name = "m3_model_end_dttm")
+ private ZonedDateTime m3ModelEndDttm;
+
+ @Column(name = "m3_pending_jobs", nullable = false)
+ private int m3PendingJobs = 0;
+
+ @Column(name = "m3_running_jobs", nullable = false)
+ private int m3RunningJobs = 0;
+
+ @Column(name = "m3_completed_jobs", nullable = false)
+ private int m3CompletedJobs = 0;
+
+ @Column(name = "m3_failed_jobs", nullable = false)
+ private int m3FailedJobs = 0;
+
+ @Column(name = "apply_status")
+ private String applyStatus = GukYuinStatus.PENDING.getId();
+
+ @Column(name = "apply_status_dttm")
+ private ZonedDateTime applyStatusDttm;
+
+ @Column(name = "uid", nullable = false)
+ private String uid = UUID.randomUUID().toString().replace("-", "").toUpperCase();
+
+ @Column(name = "total_jobs")
+ private Long totalJobs;
+
+ @Column(name = "chn_dtct_mst_id")
+ private String chnDtctMstId;
+
+ public InferenceResultDto.ResultList toDto() {
+ return new InferenceResultDto.ResultList(
+ this.uuid,
+ this.title,
+ this.stage,
+ this.status,
+ this.mapSheetCnt,
+ this.detectingCnt,
+ this.inferStartDttm,
+ this.inferEndDttm,
+ this.applyYn,
+ this.applyDttm,
+ this.compareYyyy,
+ this.targetYyyy,
+ this.uid);
+ }
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/PnuEntity.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/PnuEntity.java
new file mode 100644
index 0000000..46daada
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/entity/PnuEntity.java
@@ -0,0 +1,50 @@
+package com.kamco.cd.kamcoback.postgres.entity;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.SequenceGenerator;
+import jakarta.persistence.Table;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import java.time.OffsetDateTime;
+import lombok.Getter;
+import lombok.Setter;
+import org.hibernate.annotations.ColumnDefault;
+
+@Getter
+@Setter
+@Entity
+@Table(name = "tb_pnu")
+public class PnuEntity {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "tb_pnu_id_gen")
+ @SequenceGenerator(name = "tb_pnu_id_gen", sequenceName = "tb_pnu_uid", allocationSize = 1)
+ @Column(name = "id", nullable = false)
+ private Long id;
+
+ @NotNull
+ @ManyToOne(fetch = FetchType.LAZY, optional = false)
+ @JoinColumn(name = "geo_uid", nullable = false)
+ private MapSheetAnalDataInferenceGeomEntity geo;
+
+ @Size(max = 19)
+ @Column(name = "pnu", length = 19)
+ private String pnu;
+
+ @Column(name = "created_dttm")
+ private OffsetDateTime createdDttm;
+
+ @Column(name = "created_uid")
+ private Long createdUid;
+
+ @ColumnDefault("false")
+ @Column(name = "del_yn")
+ private Boolean delYn;
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/repository/gukyuin/GukYuinRepository.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/repository/gukyuin/GukYuinRepository.java
new file mode 100644
index 0000000..83a1e07
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/repository/gukyuin/GukYuinRepository.java
@@ -0,0 +1,7 @@
+package com.kamco.cd.kamcoback.postgres.repository.gukyuin;
+
+import com.kamco.cd.kamcoback.postgres.entity.MapSheetLearnEntity;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface GukYuinRepository
+ extends JpaRepository, GukYuinRepositoryCustom {}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/repository/gukyuin/GukYuinRepositoryCustom.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/repository/gukyuin/GukYuinRepositoryCustom.java
new file mode 100644
index 0000000..25d5ad4
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/repository/gukyuin/GukYuinRepositoryCustom.java
@@ -0,0 +1,42 @@
+package com.kamco.cd.kamcoback.postgres.repository.gukyuin;
+
+import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.Basic;
+import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.LabelSendDto;
+import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.LearnKeyDto;
+import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.GeomUidDto;
+import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.LearnInfo;
+import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinStatus;
+import java.time.LocalDate;
+import java.util.List;
+import java.util.UUID;
+
+public interface GukYuinRepositoryCustom {
+
+ void updateGukYuinMastRegResult(Basic resultBody);
+
+ void updateGukYuinMastRegRemove(Basic resultBody);
+
+ void updateInferenceGeomDataPnuCnt(String chnDtctObjtId, long pnuCnt);
+
+ Long findMapSheetAnalDataInferenceGeomUid(String chnDtctObjtId);
+
+ void insertGeoUidPnuData(Long geoUid, String[] pnuList);
+
+ void updateGukYuinApplyStateComplete(Long id, GukYuinStatus status);
+
+ List findGukyuinApplyStatusUidList(List gukYuinStatus);
+
+ long upsertMapSheetDataAnalGeomPnu(String uid, String[] pnuList);
+
+ LearnInfo findMapSheetLearnInfo(UUID uuid);
+
+ Integer findMapSheetLearnYearStage(Integer compareYyyy, Integer targetYyyy);
+
+ void updateAnalInferenceApplyDttm(Basic registRes);
+
+ List findYesterdayLabelingCompleteList();
+
+ void updateAnalDataInferenceGeomSendDttm(Long geoUid);
+
+ List findLabelingCompleteSendList(LocalDate yesterday);
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/repository/gukyuin/GukYuinRepositoryImpl.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/repository/gukyuin/GukYuinRepositoryImpl.java
new file mode 100644
index 0000000..946c7a4
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/postgres/repository/gukyuin/GukYuinRepositoryImpl.java
@@ -0,0 +1,282 @@
+package com.kamco.cd.kamcoback.postgres.repository.gukyuin;
+
+import static com.kamco.cd.kamcoback.postgres.entity.QLabelingAssignmentEntity.labelingAssignmentEntity;
+import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalDataInferenceGeomEntity.mapSheetAnalDataInferenceGeomEntity;
+import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalInferenceEntity.mapSheetAnalInferenceEntity;
+import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetLearnEntity.mapSheetLearnEntity;
+import static com.kamco.cd.kamcoback.postgres.entity.QPnuEntity.pnuEntity;
+
+import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.Basic;
+import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.LabelSendDto;
+import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.LearnKeyDto;
+import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.GeomUidDto;
+import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.LearnInfo;
+import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinStatus;
+import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.InspectState;
+import com.querydsl.core.types.Projections;
+import com.querydsl.core.types.dsl.BooleanExpression;
+import com.querydsl.core.types.dsl.Expressions;
+import com.querydsl.core.types.dsl.NumberExpression;
+import com.querydsl.jpa.impl.JPAQueryFactory;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.PersistenceContext;
+import jakarta.transaction.Transactional;
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.util.List;
+import java.util.UUID;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Repository;
+
+@Repository
+@RequiredArgsConstructor
+public class GukYuinRepositoryImpl implements GukYuinRepositoryCustom {
+
+ private final JPAQueryFactory queryFactory;
+ @PersistenceContext private EntityManager em;
+
+ @Override
+ public void updateGukYuinMastRegResult(Basic resultBody) {
+
+ int excnPgrt = Integer.parseInt(resultBody.getExcnPgrt());
+ int stage = Integer.parseInt(resultBody.getChnDtctSno());
+ GukYuinStatus status = GukYuinStatus.IN_PROGRESS;
+ if (excnPgrt == 100) {
+ status = GukYuinStatus.GUK_COMPLETED;
+ }
+
+ queryFactory
+ .update(mapSheetLearnEntity)
+ .set(mapSheetLearnEntity.stage, stage)
+ .set(mapSheetLearnEntity.applyStatus, status.getId())
+ .set(mapSheetLearnEntity.applyStatusDttm, ZonedDateTime.now())
+ .set(mapSheetLearnEntity.chnDtctMstId, resultBody.getChnDtctMstId())
+ .set(mapSheetLearnEntity.applyYn, true)
+ .set(mapSheetLearnEntity.applyDttm, ZonedDateTime.now())
+ .where(mapSheetLearnEntity.uid.eq(resultBody.getChnDtctId()))
+ .execute();
+ }
+
+ @Override
+ public void updateGukYuinMastRegRemove(Basic resultBody) {
+ queryFactory
+ .update(mapSheetLearnEntity)
+ .set(mapSheetLearnEntity.applyStatus, GukYuinStatus.CANCELED.getId())
+ .set(mapSheetLearnEntity.applyStatusDttm, ZonedDateTime.now())
+ .where(mapSheetLearnEntity.uid.eq(resultBody.getChnDtctId()))
+ .execute();
+ }
+
+ @Override
+ public void updateInferenceGeomDataPnuCnt(String chnDtctObjtId, long pnuCnt) {
+ queryFactory
+ .update(mapSheetAnalDataInferenceGeomEntity)
+ .set(mapSheetAnalDataInferenceGeomEntity.pnu, pnuCnt)
+ .where(mapSheetAnalDataInferenceGeomEntity.resultUid.eq(chnDtctObjtId))
+ .execute();
+ }
+
+ @Override
+ public Long findMapSheetAnalDataInferenceGeomUid(String chnDtctObjtId) {
+ return queryFactory
+ .select(mapSheetAnalDataInferenceGeomEntity.geoUid)
+ .from(mapSheetAnalDataInferenceGeomEntity)
+ .where(mapSheetAnalDataInferenceGeomEntity.resultUid.eq(chnDtctObjtId))
+ .fetchOne();
+ }
+
+ @Override
+ public void insertGeoUidPnuData(Long geoUid, String[] pnuList) {
+ for (String pnu : pnuList) {
+ queryFactory
+ .insert(pnuEntity)
+ .columns(pnuEntity.geo.geoUid, pnuEntity.pnu, pnuEntity.createdDttm)
+ .values(geoUid, pnu, ZonedDateTime.now())
+ .execute();
+ }
+ }
+
+ @Override
+ public List findGukyuinApplyStatusUidList(List status) {
+ return queryFactory
+ .select(
+ Projections.constructor(
+ LearnKeyDto.class,
+ mapSheetLearnEntity.id,
+ mapSheetLearnEntity.uid,
+ mapSheetLearnEntity.chnDtctMstId))
+ .from(mapSheetLearnEntity)
+ .where(mapSheetLearnEntity.applyStatus.in(status))
+ .fetch();
+ }
+
+ @Override
+ public long upsertMapSheetDataAnalGeomPnu(String chnDtctObjtId, String[] pnuList) {
+ long length = pnuList.length;
+ queryFactory
+ .update(mapSheetAnalDataInferenceGeomEntity)
+ .set(mapSheetAnalDataInferenceGeomEntity.pnu, length)
+ .where(mapSheetAnalDataInferenceGeomEntity.resultUid.eq(chnDtctObjtId))
+ .execute();
+
+ Long geoUid =
+ queryFactory
+ .select(mapSheetAnalDataInferenceGeomEntity.geoUid)
+ .from(mapSheetAnalDataInferenceGeomEntity)
+ .where(mapSheetAnalDataInferenceGeomEntity.resultUid.eq(chnDtctObjtId))
+ .fetchOne();
+
+ long succCnt = 0;
+ for (String pnu : pnuList) {
+ long result =
+ queryFactory
+ .insert(pnuEntity)
+ .columns(pnuEntity.geo.geoUid, pnuEntity.pnu, pnuEntity.createdDttm)
+ .values(geoUid, pnu, ZonedDateTime.now())
+ .execute();
+ if (result > 0) {
+ succCnt++;
+ }
+ }
+ return succCnt;
+ }
+
+ @Override
+ public LearnInfo findMapSheetLearnInfo(UUID uuid) {
+ return queryFactory
+ .select(
+ Projections.constructor(
+ LearnInfo.class,
+ mapSheetLearnEntity.id,
+ mapSheetLearnEntity.uuid,
+ mapSheetLearnEntity.compareYyyy,
+ mapSheetLearnEntity.targetYyyy,
+ mapSheetLearnEntity.stage,
+ mapSheetLearnEntity.uid,
+ mapSheetLearnEntity.applyStatus,
+ mapSheetLearnEntity.applyYn))
+ .from(mapSheetLearnEntity)
+ .where(mapSheetLearnEntity.uuid.eq(uuid))
+ .fetchOne();
+ }
+
+ @Override
+ public Integer findMapSheetLearnYearStage(Integer compareYyyy, Integer targetYyyy) {
+ NumberExpression stageExpr =
+ Expressions.numberTemplate(Integer.class, "coalesce({0}, 0)", mapSheetLearnEntity.stage);
+
+ return queryFactory
+ .select(stageExpr.max().coalesce(0))
+ .from(mapSheetLearnEntity)
+ .where(
+ mapSheetLearnEntity.compareYyyy.eq(compareYyyy),
+ mapSheetLearnEntity.targetYyyy.eq(targetYyyy),
+ mapSheetLearnEntity.applyStatus.isNotNull(),
+ mapSheetLearnEntity.applyStatus.ne(GukYuinStatus.PENDING.getId()))
+ .fetchOne();
+ }
+
+ @Override
+ public void updateAnalInferenceApplyDttm(Basic registRes) {
+ Long learnId =
+ queryFactory
+ .select(mapSheetLearnEntity.id)
+ .from(mapSheetLearnEntity)
+ .where(mapSheetLearnEntity.uid.eq(registRes.getChnDtctId()))
+ .fetchOne();
+
+ queryFactory
+ .update(mapSheetAnalInferenceEntity)
+ .set(mapSheetAnalInferenceEntity.gukyuinUsed, "Y")
+ .set(mapSheetAnalInferenceEntity.gukyuinApplyDttm, ZonedDateTime.now())
+ .where(mapSheetAnalInferenceEntity.learnId.eq(learnId))
+ .execute();
+ }
+
+ @Override
+ public List findYesterdayLabelingCompleteList() {
+ ZoneId zone = ZoneId.of("Asia/Seoul");
+ ZonedDateTime todayStart = ZonedDateTime.now(zone).toLocalDate().atStartOfDay(zone);
+ ZonedDateTime yesterdayStart = todayStart.minusDays(1);
+
+ BooleanExpression isYesterday =
+ labelingAssignmentEntity
+ .inspectStatDttm
+ .goe(yesterdayStart)
+ .and(labelingAssignmentEntity.inspectStatDttm.lt(todayStart));
+
+ return queryFactory
+ .select(
+ Projections.constructor(
+ GeomUidDto.class,
+ labelingAssignmentEntity.inferenceGeomUid,
+ mapSheetAnalDataInferenceGeomEntity.resultUid))
+ .from(labelingAssignmentEntity)
+ .innerJoin(mapSheetAnalDataInferenceGeomEntity)
+ .on(
+ labelingAssignmentEntity.inferenceGeomUid.eq(
+ mapSheetAnalDataInferenceGeomEntity.geoUid))
+ .innerJoin(mapSheetAnalInferenceEntity)
+ .on(labelingAssignmentEntity.analUid.eq(mapSheetAnalInferenceEntity.id))
+ .innerJoin(mapSheetLearnEntity)
+ .on(
+ mapSheetAnalInferenceEntity.learnId.eq(mapSheetLearnEntity.id),
+ mapSheetLearnEntity.applyStatus.in(
+ GukYuinStatus.GUK_COMPLETED.getId(), GukYuinStatus.PNU_COMPLETED.getId()))
+ .where(labelingAssignmentEntity.inspectState.eq(InspectState.COMPLETE.getId()), isYesterday)
+ .fetch();
+ }
+
+ @Override
+ public void updateAnalDataInferenceGeomSendDttm(Long geoUid) {
+ queryFactory
+ .update(mapSheetAnalDataInferenceGeomEntity)
+ .set(mapSheetAnalDataInferenceGeomEntity.labelSendDttm, ZonedDateTime.now())
+ .where(mapSheetAnalDataInferenceGeomEntity.geoUid.eq(geoUid))
+ .execute();
+ }
+
+ @Override
+ public List findLabelingCompleteSendList(LocalDate yesterday) {
+
+ ZoneId zone = ZoneId.of("Asia/Seoul");
+ ZonedDateTime from = yesterday.atStartOfDay(zone);
+ ZonedDateTime to = from.plusDays(1);
+
+ BooleanExpression isYesterday =
+ labelingAssignmentEntity
+ .inspectStatDttm
+ .goe(from)
+ .and(labelingAssignmentEntity.inspectStatDttm.lt(to));
+
+ return queryFactory
+ .select(
+ Projections.constructor(
+ LabelSendDto.class,
+ mapSheetAnalDataInferenceGeomEntity.resultUid,
+ labelingAssignmentEntity.workerUid,
+ labelingAssignmentEntity.workStatDttm,
+ labelingAssignmentEntity.inspectorUid,
+ labelingAssignmentEntity.inspectStatDttm,
+ mapSheetAnalDataInferenceGeomEntity.labelSendDttm))
+ .from(labelingAssignmentEntity)
+ .innerJoin(mapSheetAnalDataInferenceGeomEntity)
+ .on(
+ labelingAssignmentEntity.inferenceGeomUid.eq(
+ mapSheetAnalDataInferenceGeomEntity.geoUid))
+ .where(labelingAssignmentEntity.inspectState.eq(InspectState.COMPLETE.getId()), isYesterday)
+ .fetch();
+ }
+
+ @Override
+ @Transactional
+ public void updateGukYuinApplyStateComplete(Long id, GukYuinStatus status) {
+ queryFactory
+ .update(mapSheetLearnEntity)
+ .set(mapSheetLearnEntity.applyStatus, status.getId())
+ .set(mapSheetLearnEntity.applyStatusDttm, ZonedDateTime.now())
+ .where(mapSheetLearnEntity.id.eq(id))
+ .execute();
+ }
+}
diff --git a/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/service/GukYuinApiStatusJobService.java b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/service/GukYuinApiStatusJobService.java
new file mode 100644
index 0000000..351000f
--- /dev/null
+++ b/gukyuin/state-check/src/main/java/com/kamco/cd/kamcoback/service/GukYuinApiStatusJobService.java
@@ -0,0 +1,95 @@
+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.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.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.http.HttpMethod;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+
+@Log4j2
+@Service
+@RequiredArgsConstructor
+public class GukYuinApiStatusJobService {
+
+ private final ExternalHttpClient externalHttpClient;
+ private final NetUtils netUtils = new NetUtils();
+ private final GukYuinJobCoreService gukYuinJobCoreService;
+
+ 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