gukyuin label-send 커밋

This commit is contained in:
2026-02-25 15:22:05 +09:00
parent 2a32fae177
commit fb3d8a424d
100 changed files with 2784 additions and 626 deletions

View File

@@ -1,27 +0,0 @@
package com.kamco.cd.kamcoback.common.enums;
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 RoleType implements EnumType {
ADMIN("관리자"),
LABELER("라벨러"),
REVIEWER("검수자");
private final String desc;
@Override
public String getId() {
return name();
}
@Override
public String getText() {
return desc;
}
}

View File

@@ -1,27 +0,0 @@
package com.kamco.cd.kamcoback.common.enums;
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 StatusType implements EnumType {
ACTIVE("사용"),
INACTIVE("사용중지"),
PENDING("계정등록");
private final String desc;
@Override
public String getId() {
return name();
}
@Override
public String getText() {
return desc;
}
}

View File

@@ -0,0 +1,15 @@
package com.kamco.cd.kamcoback.config;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
}

View File

@@ -0,0 +1,223 @@
package com.kamco.cd.kamcoback.config.api;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.kamco.cd.kamcoback.common.utils.enums.EnumType;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
import org.springframework.http.HttpStatus;
@Getter
@ToString
public class ApiResponseDto<T> {
private T data;
@JsonInclude(JsonInclude.Include.NON_NULL)
private Error error;
@JsonInclude(JsonInclude.Include.NON_NULL)
private T errorData;
@JsonIgnore private HttpStatus httpStatus;
@JsonIgnore private Long errorLogUid;
public ApiResponseDto(T data) {
this.data = data;
}
private ApiResponseDto(T data, HttpStatus httpStatus) {
this.data = data;
this.httpStatus = httpStatus;
}
public ApiResponseDto(ApiResponseCode code) {
this.error = new Error(code.getId(), code.getMessage());
}
public ApiResponseDto(ApiResponseCode code, String message) {
this.error = new Error(code.getId(), message);
}
public ApiResponseDto(ApiResponseCode code, String message, HttpStatus httpStatus) {
this.error = new Error(code.getId(), message);
this.httpStatus = httpStatus;
}
public ApiResponseDto(
ApiResponseCode code, String message, HttpStatus httpStatus, Long errorLogUid) {
this.error = new Error(code.getId(), message);
this.httpStatus = httpStatus;
this.errorLogUid = errorLogUid;
}
public ApiResponseDto(ApiResponseCode code, String message, T errorData) {
this.error = new Error(code.getId(), message);
this.errorData = errorData;
}
// HTTP 상태 코드가 내장된 ApiResponseDto 반환 메서드들
public static <T> ApiResponseDto<T> createOK(T data) {
return new ApiResponseDto<>(data, HttpStatus.CREATED);
}
public static <T> ApiResponseDto<T> ok(T data) {
return new ApiResponseDto<>(data, HttpStatus.OK);
}
public static <T> ApiResponseDto<ResponseObj> okObject(ResponseObj data) {
if (data.getCode().equals(ApiResponseCode.OK)) {
return new ApiResponseDto<>(data, HttpStatus.NO_CONTENT);
} else {
return new ApiResponseDto<>(data.getCode(), data.getMessage(), HttpStatus.CONFLICT);
}
}
public static <T> ApiResponseDto<T> deleteOk(T data) {
return new ApiResponseDto<>(data, HttpStatus.NO_CONTENT);
}
public static ApiResponseDto<String> createException(ApiResponseCode code) {
return new ApiResponseDto<>(code);
}
public static ApiResponseDto<String> createException(ApiResponseCode code, String message) {
return new ApiResponseDto<>(code, message);
}
public static ApiResponseDto<String> createException(
ApiResponseCode code, String message, HttpStatus httpStatus) {
return new ApiResponseDto<>(code, message, httpStatus);
}
public static ApiResponseDto<String> createException(
ApiResponseCode code, String message, HttpStatus httpStatus, Long errorLogUid) {
return new ApiResponseDto<>(code, message, httpStatus, errorLogUid);
}
public static <T> ApiResponseDto<T> createException(
ApiResponseCode code, String message, T data) {
return new ApiResponseDto<>(code, message, data);
}
@Getter
public static class Error {
private final String code;
private final String message;
public Error(String code, String message) {
this.code = code;
this.message = message;
}
}
/** Error가 아닌 Business상 성공이거나 실패인 경우, 메세지 함께 전달하기 위한 object */
@Getter
public static class ResponseObj {
private final ApiResponseCode code;
private final String message;
public ResponseObj(ApiResponseCode code, String message) {
this.code = code;
this.message = message;
}
}
@Getter
@RequiredArgsConstructor
public enum ApiResponseCode implements EnumType {
// @formatter:off
OK("요청이 성공하였습니다."),
BAD_REQUEST("요청 파라미터가 잘못되었습니다."),
BAD_GATEWAY("네트워크 상태가 불안정합니다."),
ALREADY_EXIST_MALL("이미 등록된 쇼핑센터입니다."),
NOT_FOUND_MAP("지도를 찾을 수 없습니다."),
UNAUTHORIZED("권한이 없습니다."),
CONFLICT("이미 등록된 컨텐츠입니다."),
NOT_FOUND("Resource를 찾을 수 없습니다."),
NOT_FOUND_DATA("데이터를 찾을 수 없습니다."),
NOT_FOUND_WEATHER_DATA("날씨 데이터를 찾을 수 없습니다."),
FAIL_SEND_MESSAGE("메시지를 전송하지 못했습니다."),
TOO_MANY_CONNECTED_MACHINES("연결된 기기가 너무 많습니다."),
UNAUTHENTICATED("인증에 실패하였습니다."),
INVALID_TOKEN("잘못된 토큰입니다."),
EXPIRED_TOKEN("만료된 토큰입니다."),
INTERNAL_SERVER_ERROR("서버에 문제가 발생 하였습니다."),
FORBIDDEN("권한을 확인해주세요."),
INVALID_PASSWORD("잘못된 비밀번호 입니다."),
NOT_FOUND_CAR_IN("입차정보가 없습니다."),
WRONG_STATUS("잘못된 상태입니다."),
FAIL_VERIFICATION("인증에 실패하였습니다."),
INVALID_EMAIL("잘못된 형식의 이메일입니다."),
REQUIRED_EMAIL("이메일은 필수 항목입니다."),
WRONG_PASSWORD("잘못된 패스워드입니다."),
DUPLICATE_EMAIL("이미 가입된 이메일입니다."),
DUPLICATE_DATA("이미 등록되어 있습니다."),
DATA_INTEGRITY_ERROR("데이터 무결성이 위반되어 요청을 처리할수 없습니다."),
FOREIGN_KEY_ERROR("참조 중인 데이터가 있어 삭제할 수 없습니다."),
DUPLICATE_EMPLOYEEID("이미 가입된 사번입니다."),
NOT_FOUND_USER_FOR_EMAIL("이메일로 유저를 찾을 수 없습니다."),
NOT_FOUND_USER("사용자를 찾을 수 없습니다."),
UNPROCESSABLE_ENTITY("이 데이터는 삭제할 수 없습니다."),
LOGIN_ID_NOT_FOUND("아이디를 잘못 입력하셨습니다."),
LOGIN_PASSWORD_MISMATCH("비밀번호를 잘못 입력하셨습니다."),
LOGIN_PASSWORD_EXCEEDED("비밀번호 오류 횟수를 초과하여 이용하실 수 없습니다.\n로그인 오류에 대해 관리자에게 문의하시기 바랍니다."),
INACTIVE_ID("사용할 수 없는 계정입니다."),
INVALID_EMAIL_TOKEN(
"You can only reset your password within 24 hours from when the email was sent.\n"
+ "To reset your password again, please submit a new request through \"Forgot"
+ " Password.\""),
PAYLOAD_TOO_LARGE("업로드 용량 제한을 초과했습니다."),
NOT_FOUND_TARGET_YEAR("기준년도 도엽을 찾을 수 없습니다."),
NOT_FOUND_COMPARE_YEAR("비교년도 도엽을 찾을 수 없습니다."),
FAIL_SAVE_MAP_SHEET("도엽 저장 중 오류가 발생했습니다."),
FAIL_CREATE_MAP_SHEET_FILE("도엽 설정파일 생성 중 오류가 발생했습니다."),
;
// @formatter:on
private final String message;
@Override
public String getId() {
return name();
}
@Override
public String getText() {
return message;
}
public static ApiResponseCode getCode(String name) {
return ApiResponseCode.valueOf(name.toUpperCase());
}
public static String getMessage(String name) {
return ApiResponseCode.valueOf(name.toUpperCase()).getText();
}
public static ApiResponseCode from(String codeName, HttpStatus status) {
if (codeName != null && !codeName.isBlank()) {
try {
return ApiResponseCode.valueOf(codeName.toUpperCase());
} catch (IllegalArgumentException ignore) {
// fallback
}
}
if (status != null) {
try {
return ApiResponseCode.valueOf(status.name());
} catch (IllegalArgumentException ignore) {
// fallback
}
}
return INTERNAL_SERVER_ERROR;
}
}
}

View File

@@ -0,0 +1,43 @@
package com.kamco.cd.kamcoback.enums;
import com.kamco.cd.kamcoback.common.utils.enums.CodeExpose;
import com.kamco.cd.kamcoback.common.utils.enums.EnumType;
import java.util.Arrays;
import lombok.AllArgsConstructor;
import lombok.Getter;
@CodeExpose
@Getter
@AllArgsConstructor
public enum ImageryFitStatus implements EnumType {
FIT("적합"),
UNFIT("부적합");
private final String desc;
@Override
public String getId() {
return name();
}
@Override
public String getText() {
return desc;
}
public static ImageryFitStatus fromCode(String code) {
if (code == null) {
return null;
}
String c = code.trim();
return Arrays.stream(values())
.filter(v -> v.name().equalsIgnoreCase(c))
.findFirst()
.orElse(null);
}
public static String getDescByCode(String code) {
ImageryFitStatus status = fromCode(code);
return status != null ? status.getDesc() : null;
}
}

View File

@@ -114,4 +114,38 @@ public class ChngDetectContDto {
private List<DtoPnuDetectMpng> result;
private Boolean success;
}
@Schema(name = "ResultLabelDto", description = "ResultLabelDto list 리턴 형태")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public static class ResultLabelDto {
private Integer code;
private String message;
private DtoPnuDetectMpng result;
private Boolean success;
}
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public static class ReqInfo {
private String reqIp;
private String reqEpno;
}
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public static class StbltResult {
private String stbltYn;
private String incyCd;
private String incyCmnt;
}
}

View File

@@ -247,45 +247,58 @@ public class ChngDetectMastDto {
@AllArgsConstructor
public static class RlbDtctMastDto {
private String pnuDtctId;
private String pnu;
private String lrmSyncYmd;
private String pnuSyncYmd;
private String mpqdNo; // 도번호
private String pnuDtctId; // PNU탐지ID
private String pnu; // PNU코드(19자리)
private String lrmSyncYmd; // 지적도동기화일자(YYYYMMDD)
private String pnuSyncYmd; // PNU동기화일자(YYYYMMDD)
private String mpqdNo; // 도번호
private String cprsYr; // 비교년도
private String crtrYr; // 기준년도
private String chnDtctSno; // 회차
private String chnDtctId;
private String chnDtctSno; // 회차, 변화탐지순번
private String chnDtctId; // 변화탐지ID(UUID)
private String chnDtctMstId;
private String chnDtctObjtId;
private String chnDtctContId;
private String chnCd;
private String chnDtctProb;
private String chnDtctMstId; // 변화탐지마스터ID
private String chnDtctObjtId; // 변화탐지객체ID
private String chnDtctContId; // 변화탐지내용ID
private String chnCd; // 변화코드
private String chnDtctProb; // 변화탐지정확도(0~1)
private String bfClsCd; // 이전분류코드
private String bfClsProb; // 이전분류정확도
private String bfClsProb; // 이전분류정확도(0~1)
private String afClsCd; // 이후분류코드
private String afClsProb; // 이후분류정확도
private String afClsProb; // 이후분류정확도(0~1)
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 pnuSqms; // PNU면적(㎡)
private String pnuDtctSqms; // PNU탐지면적(㎡)
private String chnDtctSqms; // 변화탐지면적(㎡)
private String stbltYn; // 적합여부(Y/N) - 안정성 (Y:부적합, N:적합)
private String incyCd; // 부적합코드
private String incyRsnCont; // 부적합사유내용
private String lockYn; // 잠금여부(Y/N)
private String lblYn; // 라벨여부(Y/N)
private String chgYn; // 변경여부(Y/N)
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 chgDt; // 변경일시
private String chgEpno; // 변경자사번
private String chgIp; // 변경자IP
private String delYn; // 삭제여부
}
@Schema(name = "RemoveResDto", description = "remove 후 리턴 형태")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public static class RemoveResDto {
private Integer code;
private String message;
private Boolean result;
private Boolean success;
}
}

View File

@@ -0,0 +1,67 @@
package com.kamco.cd.kamcoback.postgres.core;
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.GukYuinDto.LearnInfo;
import com.kamco.cd.kamcoback.postgres.repository.gukyuin.GukYuinRepository;
import java.time.LocalDate;
import java.util.List;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class GukYuinCoreService {
private final GukYuinRepository gukYuinRepository;
public void updateGukYuinMastRegResult(Basic resultBody) {
gukYuinRepository.updateGukYuinMastRegResult(resultBody);
}
public void updateGukYuinMastRegRemove(String chnDtctId) {
gukYuinRepository.updateGukYuinMastRegRemove(chnDtctId);
}
public void updateInferenceGeomDataPnuCnt(String chnDtctObjtId, long pnuCnt) {
gukYuinRepository.updateInferenceGeomDataPnuCnt(chnDtctObjtId, pnuCnt);
}
public Long findMapSheetAnalDataInferenceGeomUid(String chnDtctObjtId) {
return gukYuinRepository.findMapSheetAnalDataInferenceGeomUid(chnDtctObjtId);
}
public void insertGeoUidPnuData(Long geoUid, String[] pnuList, String chnDtctObjtId) {
gukYuinRepository.insertGeoUidPnuData(geoUid, pnuList, chnDtctObjtId);
}
public LearnInfo findMapSheetLearnInfo(UUID uuid) {
return gukYuinRepository.findMapSheetLearnInfo(uuid);
}
public Integer findMapSheetLearnYearStage(Integer compareYyyy, Integer targetYyyy) {
return gukYuinRepository.findMapSheetLearnYearStage(compareYyyy, targetYyyy);
}
public void updateAnalInferenceApplyDttm(Basic registRes) {
gukYuinRepository.updateAnalInferenceApplyDttm(registRes);
}
public List<LabelSendDto> findLabelingCompleteSendList(LocalDate yesterday) {
return gukYuinRepository.findLabelingCompleteSendList(yesterday);
}
public Long findMapSheetLearnInfoByYyyy(
Integer compareYyyy, Integer targetYyyy, Integer maxStage) {
return gukYuinRepository.findMapSheetLearnInfoByYyyy(compareYyyy, targetYyyy, maxStage);
}
public void updateMapSheetLearnGukyuinEndStatus(Long learnId) {
gukYuinRepository.updateMapSheetLearnGukyuinEndStatus(learnId);
}
public void updateMapSheetInferenceLabelEndStatus(Long learnId) {
gukYuinRepository.updateMapSheetInferenceLabelEndStatus(learnId);
}
}

View File

@@ -2,8 +2,10 @@ package com.kamco.cd.kamcoback.postgres.core;
import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.GeomUidDto;
import com.kamco.cd.kamcoback.postgres.repository.gukyuin.GukYuinLabelJobRepository;
import java.time.LocalDate;
import java.util.List;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class GukYuinLabelJobCoreService {
@@ -14,10 +16,11 @@ public class GukYuinLabelJobCoreService {
this.gukYuinLabelRepository = gukYuinLabelRepository;
}
public List<GeomUidDto> findYesterdayLabelingCompleteList() {
return gukYuinLabelRepository.findYesterdayLabelingCompleteList();
public List<GeomUidDto> findYesterdayLabelingCompleteList(LocalDate baseDate) {
return gukYuinLabelRepository.findYesterdayLabelingCompleteList(baseDate);
}
@Transactional
public void updateAnalDataInferenceGeomSendDttm(Long geoUid) {
gukYuinLabelRepository.updateAnalDataInferenceGeomSendDttm(geoUid);
}

View File

@@ -1,22 +0,0 @@
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();
}
}

View File

@@ -1,5 +1,6 @@
package com.kamco.cd.kamcoback.postgres.entity;
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.MapSheet;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
@@ -45,4 +46,8 @@ public class MapInkx50kEntity extends CommonDateEntity {
this.mapidNo = mapidNo;
this.geom = geom;
}
public MapSheet toEntity() {
return new MapSheet(mapidcdNo, mapidNm);
}
}

View File

@@ -3,6 +3,7 @@ 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 com.kamco.cd.kamcoback.scene.dto.MapInkxMngDto.MapListEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
@@ -53,10 +54,6 @@ public class MapInkx5kEntity extends CommonDateEntity {
@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) {
@@ -72,4 +69,18 @@ public class MapInkx5kEntity extends CommonDateEntity {
public void updateUseInference(CommonUseStatus useInference) {
this.useInference = useInference;
}
public InferenceDetailDto.MapSheet toEntity() {
return new MapSheet(mapidcdNo, mapidNm);
}
public MapListEntity toDto() {
return MapListEntity.builder()
.scene5k(this.toEntity())
.scene50k(this.mapInkx50k.toEntity())
.useInference(useInference)
.createdDttm(super.getCreatedDate())
.updatedDttm(super.getModifiedDate())
.build();
}
}

View File

@@ -0,0 +1,167 @@
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 jakarta.validation.constraints.Size;
import java.time.ZonedDateTime;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.ColumnDefault;
@Getter
@Setter
@Entity
@Table(name = "tb_map_sheet_anal_data_inference")
public class MapSheetAnalDataInferenceEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "data_uid", nullable = false)
private Long id;
// @Size(max = 128)
// @Column(name = "data_name", length = 128)
// private String dataName;
//
// @Size(max = 255)
// @Column(name = "data_path")
// private String dataPath;
//
// @Size(max = 128)
// @Column(name = "data_type", length = 128)
// private String dataType;
//
// @Size(max = 128)
// @Column(name = "data_crs_type", length = 128)
// private String dataCrsType;
//
// @Size(max = 255)
// @Column(name = "data_crs_type_name")
// private String dataCrsTypeName;
@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;
@Column(name = "compare_yyyy")
private Integer compareYyyy;
@Column(name = "target_yyyy")
private Integer targetYyyy;
// @Column(name = "data_json", length = Integer.MAX_VALUE)
// private String dataJson;
//
// @Size(max = 20)
// @ColumnDefault("'0'")
// @Column(name = "data_state", length = 20)
// private String dataState;
// @ColumnDefault("now()")
// @Column(name = "data_state_dttm")
// private ZonedDateTime dataStateDttm;
//
// @Column(name = "anal_strt_dttm")
// private ZonedDateTime analStrtDttm;
//
// @Column(name = "anal_end_dttm")
// private ZonedDateTime analEndDttm;
//
// @ColumnDefault("0")
// @Column(name = "anal_sec")
// private Long analSec;
@Size(max = 20)
@Column(name = "anal_state", length = 20)
private String analState;
@Column(name = "anal_uid")
private Long analUid;
@Column(name = "map_sheet_num")
private Long mapSheetNum;
// @ColumnDefault("0")
// @Column(name = "detecting_cnt")
// private Long detectingCnt;
// @ColumnDefault("0")
// @Column(name = "pnu")
// private Long pnu;
// @Size(max = 20)
// @Column(name = "down_state", length = 20)
// private String downState;
//
// @Column(name = "down_state_dttm")
// private ZonedDateTime downStateDttm;
@Size(max = 20)
@Column(name = "fit_state", length = 20)
private String fitState;
@Column(name = "fit_state_dttm")
private ZonedDateTime fitStateDttm;
@Column(name = "labeler_uid")
private Long labelerUid;
@Size(max = 20)
@ColumnDefault("NULL")
@Column(name = "label_state", length = 20)
private String labelState;
@Column(name = "label_state_dttm")
private ZonedDateTime labelStateDttm;
@Column(name = "tester_uid")
private Long testerUid;
@Size(max = 20)
@Column(name = "test_state", length = 20)
private String testState;
@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;
@Column(name = "stage")
private Integer stage;
@Column(name = "file_created_yn")
private Boolean fileCreatedYn;
@Column(name = "file_created_dttm")
private ZonedDateTime fileCreatedDttm;
// @Size(max = 100)
// @Column(name = "m1", length = 100)
// private String m1;
//
// @Size(max = 100)
// @Column(name = "m2", length = 100)
// private String m2;
//
// @Size(max = 100)
// @Column(name = "m3", length = 100)
// private String m3;
}

View File

@@ -12,7 +12,7 @@ import jakarta.persistence.SequenceGenerator;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import java.time.OffsetDateTime;
import java.time.ZonedDateTime;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.ColumnDefault;
@@ -39,7 +39,7 @@ public class PnuEntity {
private String pnu;
@Column(name = "created_dttm")
private OffsetDateTime createdDttm;
private ZonedDateTime createdDttm;
@Column(name = "created_uid")
private Long createdUid;
@@ -47,4 +47,140 @@ public class PnuEntity {
@ColumnDefault("false")
@Column(name = "del_yn")
private Boolean delYn;
@Size(max = 40)
@Column(name = "pnu_dtct_id", length = 40)
private String pnuDtctId;
@Size(max = 10)
@Column(name = "lrm_sync_ymd", length = 10)
private String lrmSyncYmd;
@Size(max = 10)
@Column(name = "pnu_sync_ymd", length = 10)
private String pnuSyncYmd;
@Size(max = 20)
@Column(name = "mpqd_no", length = 20)
private String mpqdNo;
@Size(max = 10)
@Column(name = "cprs_yr", length = 10)
private String cprsYr;
@Size(max = 10)
@Column(name = "crtr_yr", length = 10)
private String crtrYr;
@Size(max = 255)
@Column(name = "chn_dtct_id")
private String chnDtctId;
@Size(max = 10)
@Column(name = "chn_dtct_mst_id", length = 10)
private String chnDtctMstId;
@Size(max = 255)
@Column(name = "chn_dtct_objt_id")
private String chnDtctObjtId;
@Size(max = 255)
@Column(name = "chn_dtct_cont_id")
private String chnDtctContId;
@Size(max = 50)
@Column(name = "chn_cd", length = 50)
private String chnCd;
@Size(max = 50)
@Column(name = "chn_dtct_prob", length = 50)
private String chnDtctProb;
@Size(max = 50)
@Column(name = "bf_cls_cd", length = 50)
private String bfClsCd;
@Size(max = 50)
@Column(name = "bf_cls_prob", length = 50)
private String bfClsProb;
@Size(max = 50)
@Column(name = "af_cls_cd", length = 50)
private String afClsCd;
@Size(max = 50)
@Column(name = "af_cls_prob", length = 50)
private String afClsProb;
@Size(max = 100)
@Column(name = "pnu_sqms", length = 100)
private String pnuSqms;
@Size(max = 100)
@Column(name = "pnu_dtct_sqms", length = 100)
private String pnuDtctSqms;
@Size(max = 100)
@Column(name = "chn_dtct_sqms", length = 100)
private String chnDtctSqms;
@Size(max = 1)
@Column(name = "stblt_yn", length = 1)
private String stbltYn;
@Size(max = 30)
@Column(name = "incy_cd", length = 30)
private String incyCd;
@Size(max = 255)
@Column(name = "incy_rsn_cont")
private String incyRsnCont;
@Size(max = 1)
@Column(name = "lock_yn", length = 1)
private String lockYn;
@Size(max = 1)
@Column(name = "lbl_yn", length = 1)
private String lblYn;
@Size(max = 1)
@Column(name = "chg_yn", length = 1)
private String chgYn;
@Size(max = 50)
@Column(name = "rsatct_no", length = 50)
private String rsatctNo;
@Size(max = 100)
@Column(name = "rmk", length = 100)
private String rmk;
@Size(max = 20)
@Column(name = "crt_dt", length = 20)
private String crtDt;
@Size(max = 20)
@Column(name = "crt_epno", length = 20)
private String crtEpno;
@Size(max = 20)
@Column(name = "crt_ip", length = 20)
private String crtIp;
@Size(max = 20)
@Column(name = "chg_dt", length = 20)
private String chgDt;
@Size(max = 20)
@Column(name = "chg_epno", length = 20)
private String chgEpno;
@Size(max = 20)
@Column(name = "chg_ip", length = 20)
private String chgIp;
@Size(max = 10)
@Column(name = "chn_dtct_sno", length = 10)
private String chnDtctSno;
}

View File

@@ -1,11 +1,12 @@
package com.kamco.cd.kamcoback.postgres.repository.gukyuin;
import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.GeomUidDto;
import java.time.LocalDate;
import java.util.List;
public interface GukYuinLabelJobRepositoryCustom {
List<GeomUidDto> findYesterdayLabelingCompleteList();
List<GeomUidDto> findYesterdayLabelingCompleteList(LocalDate baseDate);
void updateAnalDataInferenceGeomSendDttm(Long geoUid);
}

View File

@@ -13,6 +13,7 @@ import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.List;
@@ -27,16 +28,21 @@ public class GukYuinLabelJobRepositoryImpl implements GukYuinLabelJobRepositoryC
@PersistenceContext private EntityManager em;
@Override
public List<GeomUidDto> findYesterdayLabelingCompleteList() {
public List<GeomUidDto> findYesterdayLabelingCompleteList(LocalDate baseDate) {
ZoneId zone = ZoneId.of("Asia/Seoul");
ZonedDateTime todayStart = ZonedDateTime.now(zone).toLocalDate().atStartOfDay(zone);
ZonedDateTime yesterdayStart = todayStart.minusDays(1);
BooleanExpression isYesterday =
// baseDate가 null이면 기존처럼 "어제"로 처리
LocalDate targetDate =
(baseDate != null) ? baseDate : ZonedDateTime.now(zone).toLocalDate().minusDays(1);
ZonedDateTime targetStart = targetDate.atStartOfDay(zone);
ZonedDateTime nextStart = targetStart.plusDays(1);
BooleanExpression inTargetDay =
labelingAssignmentEntity
.inspectStatDttm
.goe(yesterdayStart)
.and(labelingAssignmentEntity.inspectStatDttm.lt(todayStart));
.goe(targetStart)
.and(labelingAssignmentEntity.inspectStatDttm.lt(nextStart));
return queryFactory
.select(
@@ -56,7 +62,7 @@ public class GukYuinLabelJobRepositoryImpl implements GukYuinLabelJobRepositoryC
mapSheetAnalInferenceEntity.learnId.eq(mapSheetLearnEntity.id),
mapSheetLearnEntity.applyStatus.in(
GukYuinStatus.GUK_COMPLETED.getId(), GukYuinStatus.PNU_COMPLETED.getId()))
.where(labelingAssignmentEntity.inspectState.eq(InspectState.COMPLETE.getId()), isYesterday)
.where(labelingAssignmentEntity.inspectState.eq(InspectState.COMPLETE.getId()), inTargetDay)
.fetch();
}

View File

@@ -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<MapSheetLearnEntity, Long>, GukYuinRepositoryCustom {}

View File

@@ -0,0 +1,48 @@
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(String chnDtctId);
void updateInferenceGeomDataPnuCnt(String chnDtctObjtId, long pnuCnt);
Long findMapSheetAnalDataInferenceGeomUid(String chnDtctObjtId);
void insertGeoUidPnuData(Long geoUid, String[] pnuList, String chnDtctObjtId);
void updateGukYuinApplyStateComplete(Long id, GukYuinStatus status);
List<LearnKeyDto> findGukyuinApplyStatusUidList(List<String> gukYuinStatus);
long upsertMapSheetDataAnalGeomPnu(String uid, String[] pnuList);
LearnInfo findMapSheetLearnInfo(UUID uuid);
Integer findMapSheetLearnYearStage(Integer compareYyyy, Integer targetYyyy);
void updateAnalInferenceApplyDttm(Basic registRes);
List<GeomUidDto> findYesterdayLabelingCompleteList();
void updateAnalDataInferenceGeomSendDttm(Long geoUid);
List<LabelSendDto> findLabelingCompleteSendList(LocalDate yesterday);
Long findMapSheetLearnInfoByYyyy(Integer compareYyyy, Integer targetYyyy, Integer maxStage);
void updateMapSheetLearnGukyuinEndStatus(Long learnId);
void updateMapSheetInferenceLabelEndStatus(Long learnId);
}

View File

@@ -0,0 +1,331 @@
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.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelMngState;
import com.kamco.cd.kamcoback.postgres.entity.PnuEntity;
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(String chnDtctId) {
queryFactory
.update(mapSheetLearnEntity)
.set(mapSheetLearnEntity.applyStatus, GukYuinStatus.CANCELED.getId())
.set(mapSheetLearnEntity.applyStatusDttm, ZonedDateTime.now())
.set(mapSheetLearnEntity.applyYn, false)
.where(mapSheetLearnEntity.uid.eq(chnDtctId))
.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, String chnDtctObjtId) {
for (String pnu : pnuList) {
PnuEntity entity =
queryFactory
.selectFrom(pnuEntity)
.where(
pnuEntity.geo.geoUid.eq(geoUid),
pnuEntity.pnu.eq(pnu),
pnuEntity.chnDtctObjtId.eq(chnDtctObjtId))
.fetchOne();
if (entity == null) {
queryFactory
.insert(pnuEntity)
.columns(
pnuEntity.geo.geoUid, pnuEntity.pnu, pnuEntity.createdDttm, pnuEntity.chnDtctObjtId)
.values(geoUid, pnu, ZonedDateTime.now(), chnDtctObjtId)
.execute();
}
}
}
@Override
public List<LearnKeyDto> findGukyuinApplyStatusUidList(List<String> 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<Integer> 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())
.set(mapSheetAnalInferenceEntity.stage, Integer.parseInt(registRes.getChnDtctSno()))
.where(mapSheetAnalInferenceEntity.learnId.eq(learnId))
.execute();
}
@Override
public List<GeomUidDto> 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<LabelSendDto> 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
public Long findMapSheetLearnInfoByYyyy(
Integer compareYyyy, Integer targetYyyy, Integer maxStage) {
return queryFactory
.select(mapSheetLearnEntity.id)
.from(mapSheetLearnEntity)
.where(
mapSheetLearnEntity.compareYyyy.eq(compareYyyy),
mapSheetLearnEntity.targetYyyy.eq(targetYyyy),
mapSheetLearnEntity.stage.eq(maxStage))
.fetchOne();
}
@Override
public void updateMapSheetLearnGukyuinEndStatus(Long learnId) {
queryFactory
.update(mapSheetLearnEntity)
.set(mapSheetLearnEntity.applyStatus, GukYuinStatus.END.getId())
.set(mapSheetLearnEntity.applyStatusDttm, ZonedDateTime.now())
.where(mapSheetLearnEntity.id.eq(learnId))
.execute();
}
@Override
public void updateMapSheetInferenceLabelEndStatus(Long learnId) {
queryFactory
.update(mapSheetAnalInferenceEntity)
.set(mapSheetAnalInferenceEntity.analState, LabelMngState.FINISH.getId())
.set(mapSheetAnalInferenceEntity.updatedDttm, ZonedDateTime.now())
.where(mapSheetAnalInferenceEntity.learnId.eq(learnId))
.execute();
}
@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();
}
}

View File

@@ -0,0 +1,220 @@
package com.kamco.cd.kamcoback.scene.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.JsonNode;
import com.kamco.cd.kamcoback.enums.ApiConfigEnum.EnumDto;
import com.kamco.cd.kamcoback.enums.CommonUseStatus;
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.persistence.EntityNotFoundException;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import lombok.AllArgsConstructor;
import lombok.Builder;
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 MapInkxMngDto {
// CommonUseStatus class로 통합 20251230
// @CodeExpose
// @Getter
// @AllArgsConstructor
// public enum UseInferenceType implements EnumType {
// USE("사용중"),
// EXCEPT("영구 추론제외");
//
// private final String desc;
//
// @Override
// public String getId() {
// return name();
// }
//
// @Override
// public String getText() {
// return desc;
// }
// }
@Schema(name = "Basic", description = "Basic")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public static class Basic {
private Integer fid;
private String mapidcdNo;
private String mapidNm;
private JsonNode geom;
private String useInference;
private ZonedDateTime createdDttm;
private ZonedDateTime updatedDttm;
}
@Getter
@Schema(name = "MapListEntity", description = "목록 항목")
public static class MapListEntity {
private InferenceDetailDto.MapSheet scene50k;
private InferenceDetailDto.MapSheet scene5k;
private CommonUseStatus useInference;
@JsonFormat(
shape = JsonFormat.Shape.STRING,
pattern = "yyyy-MM-dd'T'HH:mm:ssXXX",
timezone = "Asia/Seoul")
private ZonedDateTime createdDttm;
@JsonFormat(
shape = JsonFormat.Shape.STRING,
pattern = "yyyy-MM-dd'T'HH:mm:ssXXX",
timezone = "Asia/Seoul")
private ZonedDateTime updatedDttm;
public EnumDto<CommonUseStatus> getUseInference() {
EnumDto<CommonUseStatus> enumDto = useInference.getEnumDto();
return enumDto;
}
@Builder
public MapListEntity(
InferenceDetailDto.MapSheet scene50k,
InferenceDetailDto.MapSheet scene5k,
CommonUseStatus useInference,
ZonedDateTime createdDttm,
ZonedDateTime updatedDttm) {
this.scene50k = scene50k;
this.scene5k = scene5k;
this.useInference = useInference;
this.createdDttm = createdDttm;
this.updatedDttm = updatedDttm;
}
}
@Schema(name = "MapList", description = "목록 항목")
@Getter
@Setter
@NoArgsConstructor
public static class MapList {
private Integer rowNum;
private String mapidcdNo5k;
private String mapidcdNo50k;
private String mapidNm;
private String createdDttm;
private String updatedDttm;
private String useInference;
private ZonedDateTime createdDttmTime;
private ZonedDateTime updatedDttmTime;
// 목록 Querydsl 에서 리턴 받는 건 생성자 기준임 -> 쿼리 컬럼 그대로 받고 여기서 Java 형변환 해서 return 하기
public MapList(
Integer rowNum,
String mapidcdNo5k,
String mapidcdNo50k,
String mapidNm,
ZonedDateTime createdDttmTime,
ZonedDateTime updatedDttmTime,
CommonUseStatus useInference) {
this.rowNum = rowNum;
this.mapidcdNo5k = mapidcdNo5k;
this.mapidcdNo50k = mapidcdNo50k;
this.mapidNm = mapidNm;
DateTimeFormatter fmt =
DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(ZoneId.of("Asia/Seoul"));
this.createdDttm = fmt.format(createdDttmTime);
this.updatedDttm = fmt.format(updatedDttmTime);
this.createdDttmTime = createdDttmTime;
this.updatedDttmTime = updatedDttmTime;
this.useInference = useInference.getId();
}
}
@Schema(name = "searchReq", description = "검색 요청")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public static class searchReq {
// 페이징 파라미터
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);
}
}
@Schema(name = "AddMapReq", description = "등록 요청")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public static class AddMapReq {
@Schema(description = "도엽번호", example = "31540687")
private String mapidcdNo;
@Schema(description = "도엽명", example = "공덕")
private String mapidNm;
@Schema(
description = "좌표 목록 (한 줄에 한 점, '경도 위도' 형식)",
example =
"127.17500001632317 36.17499998262991\n"
+ "127.14999995475043 36.17500002877932\n"
+ "127.15000004313612 36.199999984012415\n"
+ "127.1750000466954 36.20000001863179")
private String coordinates;
}
@Schema(name = "UseInferReq", description = "추론제외 업데이트 요청")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public static class UseInferReq {
private String mapidcdNo;
private CommonUseStatus useInference; // 변경하고자하는 상태
public void valid() {
if (mapidcdNo == null || mapidcdNo.isEmpty()) {
throw new IllegalArgumentException("도엽번호는 필수 입력값입니다.");
}
// 공백제거
mapidcdNo = mapidcdNo.trim();
if (!mapidcdNo.matches("^\\d{8}$")) {
throw new EntityNotFoundException("도엽번호는 8자리 숫자로 구성되어야 합니다.");
}
}
}
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public static class Search5kReq {
private String mapidcdNo;
private String useInference;
}
}

View File

@@ -1,18 +1,13 @@
package com.kamco.cd.kamcoback.scheduler.service;
package com.kamco.cd.kamcoback.service;
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.ChngDetectContDto;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectContDto.ResultPnuDto;
import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.GeomUidDto;
import com.kamco.cd.kamcoback.postgres.core.GukYuinLabelJobCoreService;
import java.time.LocalDate;
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
@@ -21,19 +16,11 @@ import org.springframework.stereotype.Service;
public class GukYuinApiLabelJobService {
private final GukYuinLabelJobCoreService gukYuinLabelJobCoreService;
private final ExternalHttpClient externalHttpClient;
private final NetUtils netUtils = new NetUtils();
private final GukYuinApiService gukYuinApiService;
@Value("${spring.profiles.active}")
private String profile;
@Value("${gukyuin.url}")
private String gukyuinUrl;
@Value("${gukyuin.cdi}")
private String gukyuinCdiUrl;
/**
* 실행중인 profile
*
@@ -43,33 +30,29 @@ public class GukYuinApiLabelJobService {
return "local".equalsIgnoreCase(profile);
}
/** 어제 라벨링 검수 완료된 것 -> 국유인에 전송 */
@Scheduled(cron = "0 0 2 * * *")
public void findLabelingCompleteSend() {
if (isLocalProfile()) {
return;
}
// @Scheduled(cron = "0 * * * * *")
public void runTask() {
findLabelingCompleteSend(null);
}
List<GeomUidDto> list = gukYuinLabelJobCoreService.findYesterdayLabelingCompleteList();
/** 어제 라벨링 검수 완료된 것 -> 국유인에 전송 */
public void findLabelingCompleteSend(LocalDate baseDate) {
// if (isLocalProfile()) {
// return;
// }
List<GeomUidDto> list = gukYuinLabelJobCoreService.findYesterdayLabelingCompleteList(baseDate);
if (list.isEmpty()) {
return;
}
for (GeomUidDto gto : list) {
String url = gukyuinCdiUrl + "/rlb/objt/" + gto.getResultUid() + "/lbl/" + "Y";
ExternalCallResult<ResultPnuDto> result =
externalHttpClient.call(
url,
HttpMethod.POST,
null,
netUtils.jsonHeaders(),
ChngDetectContDto.ResultPnuDto.class);
ChngDetectContDto.ResultPnuDto dto = result.body();
// inference_geom 에 label_send_dttm 업데이트 하기
gukYuinLabelJobCoreService.updateAnalDataInferenceGeomSendDttm(gto.getGeoUid());
ChngDetectContDto.ResultLabelDto dto =
gukYuinApiService.updateChnDtctObjtLabelingYn(gto.getResultUid(), "Y", "Y");
if (dto.getSuccess()) {
// inference_geom 에 label_send_dttm 업데이트 하기
gukYuinLabelJobCoreService.updateAnalDataInferenceGeomSendDttm(gto.getGeoUid());
}
}
}
}

View File

@@ -0,0 +1,390 @@
package com.kamco.cd.kamcoback.service;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.kamco.cd.kamcoback.common.utils.NetUtils;
import com.kamco.cd.kamcoback.config.api.ApiResponseDto.ApiResponseCode;
import com.kamco.cd.kamcoback.config.api.ApiResponseDto.ResponseObj;
import com.kamco.cd.kamcoback.config.resttemplate.ExternalHttpClient;
import com.kamco.cd.kamcoback.config.resttemplate.ExternalHttpClient.ExternalCallResult;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectContDto;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectContDto.ContBasic;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectContDto.ReqInfo;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectContDto.ResultContDto;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectContDto.ResultPnuDto;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.ChnDetectMastReqDto;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.ErrorResDto;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.LabelSendDto;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.ResultDto;
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.RlbDtctDto;
import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.GukYuinLinkFacts;
import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.GukYuinLinkFailCode;
import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.LearnInfo;
import com.kamco.cd.kamcoback.postgres.core.GukYuinCoreService;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDate;
import java.util.List;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Slf4j
@Service
@Transactional
@RequiredArgsConstructor
public class GukYuinApiService {
private final GukYuinCoreService gukyuinCoreService;
private final ExternalHttpClient externalHttpClient;
private final NetUtils netUtils = new NetUtils();
private final ObjectMapper objectMapper;
private final String myip = netUtils.getLocalIP();
@Value("${spring.profiles.active:local}")
private String profile;
@Value("${gukyuin.url}")
private String gukyuinUrl;
@Value("${gukyuin.cdi}")
private String gukyuinCdiUrl;
@Value("${file.dataset-dir}")
private String datasetDir;
@Transactional
public ChngDetectMastDto.RegistResDto regist(ChnDetectMastReqDto chnDetectMastReq) {
String url = gukyuinCdiUrl + "/chn/mast/regist";
chnDetectMastReq.setReqIp(myip);
chnDetectMastReq.setReqEpno("BATCH");
ExternalCallResult<ChngDetectMastDto.RegistResDto> result =
externalHttpClient.call(
url,
HttpMethod.POST,
chnDetectMastReq,
netUtils.jsonHeaders(),
ChngDetectMastDto.RegistResDto.class);
ChngDetectMastDto.RegistResDto resultBody = result.body();
boolean success = false;
if (resultBody != null && resultBody.getSuccess() != null) {
ChngDetectMastDto.Basic registRes = resultBody.getResult();
success = resultBody.getSuccess();
// 이미 등록한 경우에는 result가 없음
if (resultBody.getResult() == null) {
return resultBody;
}
// 추론 회차에 applyStatus, applyStatusDttm 업데이트
gukyuinCoreService.updateGukYuinMastRegResult(registRes);
// anal_inference 에도 국유인 반영여부, applyDttm 업데이트
gukyuinCoreService.updateAnalInferenceApplyDttm(registRes);
} else {
String errBody = result.errBody();
ErrorResDto error = null;
try {
error = objectMapper.readValue(errBody, ErrorResDto.class);
return new ChngDetectMastDto.RegistResDto(error.getStatus(), error.getError(), null, false);
} catch (JsonProcessingException e) {
log.error("에러 응답 파싱 실패. rawBody={}", errBody, e);
return new ChngDetectMastDto.RegistResDto(
result.statusCode(), // HTTP status
errBody, // 원문 그대로
null,
false);
}
}
return resultBody;
}
@Transactional
public ChngDetectMastDto.RemoveResDto remove(ChnDetectMastReqDto chnDetectMastReq) {
String url = gukyuinCdiUrl + "/chn/mast/remove";
chnDetectMastReq.setReqIp(myip);
chnDetectMastReq.setReqEpno("BATCH");
boolean success = false;
ExternalCallResult<ChngDetectMastDto.RemoveResDto> result =
externalHttpClient.call(
url,
HttpMethod.POST,
chnDetectMastReq,
netUtils.jsonHeaders(),
ChngDetectMastDto.RemoveResDto.class);
ChngDetectMastDto.RemoveResDto resultBody = result.body();
if (resultBody != null && resultBody.getSuccess() != null) {
success = resultBody.getSuccess();
if (resultBody.getSuccess()) {
gukyuinCoreService.updateGukYuinMastRegRemove(chnDetectMastReq.getChnDtctId());
}
}
return resultBody;
}
// 등록목록 1개 확인
public ResultDto detail(String chnDtctMstId) {
String url =
gukyuinCdiUrl + "/chn/mast/list/" + chnDtctMstId + "?reqIp=" + myip + "&reqEpno=" + "BATCH";
ExternalCallResult<ResultDto> result =
externalHttpClient.call(url, HttpMethod.GET, null, netUtils.jsonHeaders(), ResultDto.class);
return result.body();
}
// 등록목록 비교년도,기준년도,차수 조합해서 n개 확인
public ResultDto listYearStage(ChngDetectMastDto.ChngDetectMastSearchDto searchDto) {
String queryString = netUtils.dtoToQueryString(searchDto, null);
String url =
gukyuinCdiUrl + "/chn/mast" + queryString + "&reqIp=" + myip + "&reqEpno=" + "BATCH";
ExternalCallResult<ResultDto> result =
externalHttpClient.call(url, HttpMethod.GET, null, netUtils.jsonHeaders(), ResultDto.class);
return result.body();
}
private GukYuinLinkFailCode decideCode(GukYuinLinkFacts f) {
if (!f.existsLearn()) {
return GukYuinLinkFailCode.NOT_FOUND;
}
if (f.isPartScope()) {
return GukYuinLinkFailCode.SCOPE_PART_NOT_ALLOWED;
}
if (f.hasRunningInference()) {
return GukYuinLinkFailCode.HAS_RUNNING_INFERENCE;
}
if (f.hasOtherUnfinishedGukYuin()) {
return GukYuinLinkFailCode.OTHER_GUKYUIN_IN_PROGRESS;
}
return GukYuinLinkFailCode.OK;
}
// 탐지객체 리스트 조회
public ResultContDto findChnContList(
String chnDtctId, Integer pageIndex, Integer pageSize, String batchYn) {
String url =
gukyuinCdiUrl
+ "/chn/cont/"
+ chnDtctId
+ "?pageIndex="
+ pageIndex
+ "&pageSize="
+ pageSize
+ "&reqIp="
+ myip
+ "&reqEpno="
+ "BATCH";
ExternalCallResult<ResultContDto> result =
externalHttpClient.call(
url, HttpMethod.GET, null, netUtils.jsonHeaders(), ResultContDto.class);
List<ContBasic> contList = result.body().getResult();
if (contList == null || contList.isEmpty()) {
return new ResultContDto(
result.body().getCode(),
result.body().getMessage(),
result.body().getResult(),
result.body().getSuccess());
}
return result.body();
}
public ResultPnuDto findPnuObjMgmtList(String chnDtctId, String chnDtctObjtId) {
String url =
gukyuinCdiUrl
+ "/chn/pnu/"
+ chnDtctId
+ "/objt/"
+ chnDtctObjtId
+ "?reqIp="
+ myip
+ "&reqEpno="
+ "BATCH";
ExternalCallResult<ResultPnuDto> result =
externalHttpClient.call(
url, HttpMethod.GET, null, netUtils.jsonHeaders(), ResultPnuDto.class);
return result.body();
}
public ChngDetectContDto.ResultLabelDto updateChnDtctObjtLabelingYn(
String chnDtctObjtId, String lblYn, String batchYn) {
String url = gukyuinCdiUrl + "/rlb/objt/" + chnDtctObjtId + "/lbl/" + lblYn;
ReqInfo info = new ReqInfo();
info.setReqIp(myip);
info.setReqEpno("BATCH");
ExternalCallResult<ChngDetectContDto.ResultLabelDto> result =
externalHttpClient.call(
url,
HttpMethod.POST,
info,
netUtils.jsonHeaders(),
ChngDetectContDto.ResultLabelDto.class);
return result.body();
}
public ResultContDto findChnPnuToContList(String chnDtctId, String pnu) {
String url =
gukyuinCdiUrl
+ "/chn/cont/"
+ chnDtctId
+ "/pnu/"
+ pnu
+ "?reqIp="
+ myip
+ "&reqEpno="
+ "BATCH";
ExternalCallResult<ResultContDto> result =
externalHttpClient.call(
url, HttpMethod.GET, null, netUtils.jsonHeaders(), ResultContDto.class);
return result.body();
}
public ResultDto listChnDtctId(String chnDtctId, String batchYn) {
String url =
gukyuinCdiUrl + "/chn/mast/" + chnDtctId + "?reqIp=" + myip + "&reqEpno=" + "BATCH";
ExternalCallResult<ResultDto> result =
externalHttpClient.call(url, HttpMethod.GET, null, netUtils.jsonHeaders(), ResultDto.class);
return result.body();
}
public ResponseObj connectChnMastRegist(UUID uuid) {
// uuid로 추론 회차 조회
LearnInfo info = gukyuinCoreService.findMapSheetLearnInfo(uuid);
if (info.getApplyYn() != null && info.getApplyYn()) {
return new ResponseObj(ApiResponseCode.DUPLICATE_DATA, "이미 국유인 연동을 한 회차입니다.");
}
if (!Files.isDirectory(Path.of("/kamco-nfs/dataset/export/" + info.getUid()))) {
return new ResponseObj(
ApiResponseCode.NOT_FOUND_DATA, "파일 경로에 회차 실행 파일이 생성되지 않았습니다. 확인 부탁드립니다.");
}
// 비교년도,기준년도로 전송한 데이터 있는지 확인 후 회차 번호 생성
Integer maxStage =
gukyuinCoreService.findMapSheetLearnYearStage(info.getCompareYyyy(), info.getTargetYyyy());
// reqDto 셋팅
ChnDetectMastReqDto reqDto = new ChnDetectMastReqDto();
reqDto.setCprsYr(String.valueOf(info.getCompareYyyy()));
reqDto.setCrtrYr(String.valueOf(info.getTargetYyyy()));
reqDto.setChnDtctSno(String.valueOf(maxStage + 1));
reqDto.setChnDtctId(info.getUid());
reqDto.setPathNm("/kamco-nfs/dataset/export/" + info.getUid());
// 1회차를 종료 상태로 처리하고 2회차를 보내야 함
// 추론(learn), 학습데이터(inference) 둘 다 종료 처리
if (maxStage > 0) {
Long learnId =
gukyuinCoreService.findMapSheetLearnInfoByYyyy(
info.getCompareYyyy(), info.getTargetYyyy(), maxStage);
gukyuinCoreService.updateMapSheetLearnGukyuinEndStatus(learnId);
gukyuinCoreService.updateMapSheetInferenceLabelEndStatus(learnId);
}
// 국유인 /chn/mast/regist 전송
ChngDetectMastDto.RegistResDto result = this.regist(reqDto);
if (result.getSuccess()) {
return new ResponseObj(ApiResponseCode.OK, "연동되었습니다.");
} else {
return new ResponseObj(ApiResponseCode.INTERNAL_SERVER_ERROR, result.getMessage());
}
}
public List<LabelSendDto> findLabelingCompleteSendList(LocalDate yesterday) {
return gukyuinCoreService.findLabelingCompleteSendList(yesterday);
}
public ResultContDto findChnPnuToContObject(
String chnDtctId, String chnDtctObjtId, Integer pageIndex, Integer pageSize) {
String url =
gukyuinCdiUrl
+ "/chn/cont/"
+ chnDtctId
+ "/chnDtctObjtId/"
+ chnDtctObjtId
+ "?pageIndex="
+ pageIndex
+ "&pageSize="
+ pageSize
+ "&reqIp="
+ myip
+ "&reqEpno="
+ "BATCH";
ExternalCallResult<ResultContDto> result =
externalHttpClient.call(
url, HttpMethod.GET, null, netUtils.jsonHeaders(), ResultContDto.class);
return result.body();
}
public RlbDtctDto findRlbDtctList(String chnDtctId, String yyyymmdd, String batchYn) {
String url =
gukyuinCdiUrl
+ "/rlb/dtct/"
+ chnDtctId
+ "?reqIp="
+ myip
+ "&reqEpno="
+ "BATCH"
+ "&yyyymmdd="
+ yyyymmdd;
ExternalCallResult<RlbDtctDto> result =
externalHttpClient.call(
url, HttpMethod.GET, null, netUtils.jsonHeaders(), RlbDtctDto.class);
return result.body();
}
public RlbDtctDto findRlbDtctObject(String chnDtctObjtId) {
String url =
gukyuinCdiUrl + "/rlb/objt/" + chnDtctObjtId + "?reqIp=" + myip + "&reqEpno=" + "BATCH";
ExternalCallResult<RlbDtctDto> result =
externalHttpClient.call(
url, HttpMethod.GET, null, netUtils.jsonHeaders(), RlbDtctDto.class);
return result.body();
}
}