From e31913ff9a6a389ef0278450e66a46a85bfda24c Mon Sep 17 00:00:00 2001 From: teddy Date: Thu, 29 Jan 2026 12:31:52 +0900 Subject: [PATCH 01/41] =?UTF-8?q?cls=20model=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/service/ModelMngService.java | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/model/service/ModelMngService.java b/src/main/java/com/kamco/cd/kamcoback/model/service/ModelMngService.java index eb4e9df9..aadcce9b 100644 --- a/src/main/java/com/kamco/cd/kamcoback/model/service/ModelMngService.java +++ b/src/main/java/com/kamco/cd/kamcoback/model/service/ModelMngService.java @@ -243,8 +243,6 @@ public class ModelMngService { List files = FIleChecker.getFilesFromAllDepth(dirPath, "*", "pth,py,json", 10, "name", startPos, endPos); - boolean hasPt = false; // pt 파일 존재 여부 - for (Basic dto : files) { // 예: 파일명 출력 및 추가 작업 String foldNm = dto.getFullPath().replace(dto.getFileNm(), ""); @@ -265,17 +263,15 @@ public class ModelMngService { } } - if (!hasPt) { + // cls model 적용 + String defaultPath = ptPath; + String defaultFileName = ptFileName; - String defaultPath = ptPath; - String defaultFileName = ptFileName; + Path ptPath = Paths.get(defaultPath, defaultFileName); - Path ptPath = Paths.get(defaultPath, defaultFileName); - - if (Files.exists(ptPath)) { - modelUploadResDto.setClsModelPath(defaultPath); - modelUploadResDto.setClsModelFileName(defaultFileName); - } + if (Files.exists(ptPath)) { + modelUploadResDto.setClsModelPath(defaultPath); + modelUploadResDto.setClsModelFileName(defaultFileName); } // int fileListPos = 0; From 8563204e59f9475b84178258d9ad8dfa2daf71d7 Mon Sep 17 00:00:00 2001 From: "gayoun.park" Date: Thu, 29 Jan 2026 12:49:16 +0900 Subject: [PATCH 02/41] =?UTF-8?q?=EC=98=81=EC=83=81=EA=B4=80=EB=A6=AC=20fo?= =?UTF-8?q?lder-list=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cd/kamcoback/common/utils/FIleChecker.java | 18 ++++++++++++++---- .../mapsheet/service/MapSheetMngService.java | 8 +++++--- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/common/utils/FIleChecker.java b/src/main/java/com/kamco/cd/kamcoback/common/utils/FIleChecker.java index 89656629..ddee1fe9 100644 --- a/src/main/java/com/kamco/cd/kamcoback/common/utils/FIleChecker.java +++ b/src/main/java/com/kamco/cd/kamcoback/common/utils/FIleChecker.java @@ -30,12 +30,14 @@ import java.util.stream.Stream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import lombok.Getter; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FilenameUtils; import org.geotools.coverage.grid.GridCoverage2D; import org.geotools.gce.geotiff.GeoTiffReader; import org.springframework.util.FileSystemUtils; import org.springframework.web.multipart.MultipartFile; +@Slf4j public class FIleChecker { static SimpleDateFormat dttmFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @@ -138,7 +140,9 @@ public class FIleChecker { // null을 넣으면 전체 영역을 읽지 않고 메타데이터 위주로 체크하여 빠름 GridCoverage2D coverage = reader.read(null); - if (coverage == null) return false; + if (coverage == null) { + return false; + } // 3. GIS 필수 정보(좌표계)가 있는지 확인 // if (coverage.getCoordinateReferenceSystem() == null) { @@ -152,7 +156,9 @@ public class FIleChecker { return false; } finally { // 리소스 해제 (필수) - if (reader != null) reader.dispose(); + if (reader != null) { + reader.dispose(); + } } } @@ -296,7 +302,8 @@ public class FIleChecker { boolean isValid = !NameValidator.containsKorean(folderNm) - && !NameValidator.containsWhitespaceRegex(folderNm); + && !NameValidator.containsWhitespaceRegex(folderNm) + && !parentFolderNm.equals("kamco-nfs"); File file = new File(fullPath); int childCnt = getChildFolderCount(file); @@ -586,7 +593,9 @@ public class FIleChecker { } public static boolean checkExtensions(String fileName, String ext) { - if (fileName == null) return false; + if (fileName == null) { + return false; + } if (!fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase().equals(ext)) { return false; @@ -690,6 +699,7 @@ public class FIleChecker { @Schema(name = "Folder", description = "폴더 정보") @Getter public static class Folder { + private final String folderNm; private final String parentFolderNm; private final String parentPath; diff --git a/src/main/java/com/kamco/cd/kamcoback/mapsheet/service/MapSheetMngService.java b/src/main/java/com/kamco/cd/kamcoback/mapsheet/service/MapSheetMngService.java index a9ee891f..d41f6615 100644 --- a/src/main/java/com/kamco/cd/kamcoback/mapsheet/service/MapSheetMngService.java +++ b/src/main/java/com/kamco/cd/kamcoback/mapsheet/service/MapSheetMngService.java @@ -341,12 +341,14 @@ public class MapSheetMngService { String dirPath = syncRootDir + srchDto.getDirPath(); String sortType = "name desc"; - List folderList = FIleChecker.getFolderAll(dirPath); + List folderList = + FIleChecker.getFolderAll(dirPath).stream() + .filter(dir -> dir.getIsValid().equals(true)) + .toList(); int folderTotCnt = folderList.size(); int folderErrTotCnt = - (int) - folderList.stream().filter(dto -> dto.getIsValid().toString().equals("false")).count(); + (int) folderList.stream().filter(dto -> dto.getIsValid().equals(false)).count(); return new FoldersDto(dirPath, folderTotCnt, folderErrTotCnt, folderList); } From 480b016f332a546e127aa2085dc49b596a84a8a8 Mon Sep 17 00:00:00 2001 From: teddy Date: Thu, 29 Jan 2026 14:42:21 +0900 Subject: [PATCH 03/41] =?UTF-8?q?geoserver=20url=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application-dev.yml | 2 +- src/main/resources/application-prod.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index e99d8520..7085a0b1 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -123,5 +123,5 @@ training-data: geojson-dir: /kamco-nfs/model_output/labeling/ layer: - geoserver-url: https://kamco.geo-dev.gs.dabeeo.com + geoserver-url: https://label-tile.gs.dabeeo.com workspace: cd diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index 9b8819bf..8cee0e13 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -78,5 +78,5 @@ training-data: geojson-dir: /kamco-nfs/model_output/labeling/ layer: - geoserver-url: https://kamco.geo-dev.gs.dabeeo.com + geoserver-url: https://label-tile.gs.dabeeo.com workspace: cd From 23a096a600312dd2f0423b8223ad3e7c5de6c819 Mon Sep 17 00:00:00 2001 From: "gayoun.park" Date: Thu, 29 Jan 2026 16:23:13 +0900 Subject: [PATCH 04/41] =?UTF-8?q?=EB=9D=BC=EB=B2=A8=EB=A7=81=20=ED=88=B4?= =?UTF-8?q?=20pnu=20=EC=A0=95=EB=B3=B4=20list=20string=EC=9C=BC=EB=A1=9C?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TrainingDataLabelRepositoryImpl.java | 14 ++++++++--- .../TrainingDataReviewRepositoryImpl.java | 14 ++++++++--- .../service/TrainingDataReviewJobService.java | 25 ------------------- .../dto/TrainingDataLabelDto.java | 2 +- .../dto/TrainingDataReviewDto.java | 2 +- 5 files changed, 22 insertions(+), 35 deletions(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/trainingdata/TrainingDataLabelRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/trainingdata/TrainingDataLabelRepositoryImpl.java index 88ec9b59..4f295ab6 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/trainingdata/TrainingDataLabelRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/trainingdata/TrainingDataLabelRepositoryImpl.java @@ -6,6 +6,7 @@ import static com.kamco.cd.kamcoback.postgres.entity.QMapInkx5kEntity.mapInkx5kE 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.QMapSheetLearnDataGeomEntity.mapSheetLearnDataGeomEntity; +import static com.kamco.cd.kamcoback.postgres.entity.QPnuEntity.pnuEntity; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -466,6 +467,14 @@ public class TrainingDataLabelRepositoryImpl extends QuerydslRepositorySupport } // 5. DTO 생성 + // pnu list 조회 + List pnuList = + queryFactory + .select(pnuEntity.pnu) + .from(pnuEntity) + .where(pnuEntity.geo.geoUid.eq(mapSheetAnalDataInferenceGeomEntityEntity.getGeoUid())) + .fetch(); + var changeDetectionInfo = ChangeDetectionInfo.builder() .mapSheetInfo(mapSheetEntity != null ? mapSheetEntity.getMapidNm() : "") @@ -507,10 +516,7 @@ public class TrainingDataLabelRepositoryImpl extends QuerydslRepositorySupport mapSheetAnalDataInferenceGeomEntityEntity.getCdProb() != null ? mapSheetAnalDataInferenceGeomEntityEntity.getCdProb() : 0.0) - .pnu( - mapSheetAnalDataInferenceGeomEntityEntity.getPnu() != null - ? mapSheetAnalDataInferenceGeomEntityEntity.getPnu() - : 0L) + .pnu(pnuList) .mapSheetNum( mapSheetAnalDataInferenceGeomEntityEntity.getMapSheetNum() != null ? mapSheetAnalDataInferenceGeomEntityEntity.getMapSheetNum() diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/trainingdata/TrainingDataReviewRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/trainingdata/TrainingDataReviewRepositoryImpl.java index b1875485..8296a683 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/trainingdata/TrainingDataReviewRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/trainingdata/TrainingDataReviewRepositoryImpl.java @@ -7,6 +7,7 @@ import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalDataInferenceG import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalInferenceEntity.mapSheetAnalInferenceEntity; import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetLearnDataGeomEntity.mapSheetLearnDataGeomEntity; import static com.kamco.cd.kamcoback.postgres.entity.QMemberEntity.memberEntity; +import static com.kamco.cd.kamcoback.postgres.entity.QPnuEntity.pnuEntity; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -494,6 +495,14 @@ public class TrainingDataReviewRepositoryImpl extends QuerydslRepositorySupport } // 5. DTO 생성 + // pnu list 조회 + List pnuList = + queryFactory + .select(pnuEntity.pnu) + .from(pnuEntity) + .where(pnuEntity.geo.geoUid.eq(mapSheetAnalDataInferenceGeomEntityEntity.getGeoUid())) + .fetch(); + var changeDetectionInfo = ChangeDetectionInfo.builder() .mapSheetInfo(mapSheetEntity != null ? mapSheetEntity.getMapidNm() : "") @@ -535,10 +544,7 @@ public class TrainingDataReviewRepositoryImpl extends QuerydslRepositorySupport mapSheetAnalDataInferenceGeomEntityEntity.getCdProb() != null ? mapSheetAnalDataInferenceGeomEntityEntity.getCdProb() : 0.0) - .pnu( - mapSheetAnalDataInferenceGeomEntityEntity.getPnu() != null - ? mapSheetAnalDataInferenceGeomEntityEntity.getPnu() - : 0L) + .pnu(pnuList) .mapSheetNum( mapSheetAnalDataInferenceGeomEntityEntity.getMapSheetNum() != null ? mapSheetAnalDataInferenceGeomEntityEntity.getMapSheetNum() diff --git a/src/main/java/com/kamco/cd/kamcoback/scheduler/service/TrainingDataReviewJobService.java b/src/main/java/com/kamco/cd/kamcoback/scheduler/service/TrainingDataReviewJobService.java index c69947e9..7cdca731 100644 --- a/src/main/java/com/kamco/cd/kamcoback/scheduler/service/TrainingDataReviewJobService.java +++ b/src/main/java/com/kamco/cd/kamcoback/scheduler/service/TrainingDataReviewJobService.java @@ -125,31 +125,6 @@ public class TrainingDataReviewJobService { return result; } - // 라벨러 완료,SKIP 시 호출 -> 미사용 - @Transactional - public void assignRealtime(String assignmentUid) { - Tasks task = trainingDataReviewJobCoreService.findAssignmentTask(assignmentUid); - Long analUid = task.getAnalUid(); - - // pending 계산 - List pendings = - trainingDataReviewJobCoreService.findInspectorPendingByRound(analUid); - - if (pendings.isEmpty()) { - return; - } - - List order = pendings.stream().map(InspectorPendingDto::getInspectorUid).toList(); - - trainingDataReviewJobCoreService.lockInspectors(analUid, order); - - trainingDataReviewJobCoreService.assignReviewer(task.getAssignmentUid(), order.getFirst()); - - List geomUids = new ArrayList<>(); - geomUids.add(task.getInferenceUid()); - trainingDataReviewJobCoreService.updateGeomUidTestState(geomUids); - } - @Transactional @Scheduled(cron = "0 0 2 * * *") public void exportGeojsonLabelingGeom() { diff --git a/src/main/java/com/kamco/cd/kamcoback/trainingdata/dto/TrainingDataLabelDto.java b/src/main/java/com/kamco/cd/kamcoback/trainingdata/dto/TrainingDataLabelDto.java index 3f940ccd..a74445dc 100644 --- a/src/main/java/com/kamco/cd/kamcoback/trainingdata/dto/TrainingDataLabelDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/trainingdata/dto/TrainingDataLabelDto.java @@ -358,7 +358,7 @@ public class TrainingDataLabelDto { private Double detectionAccuracy; @Schema(description = "PNU (필지고유번호)", example = "36221202306020") - private Long pnu; + private List pnu; @Schema(description = "도엽번호 (map_sheet_num)", example = "34602057") private Long mapSheetNum; diff --git a/src/main/java/com/kamco/cd/kamcoback/trainingdata/dto/TrainingDataReviewDto.java b/src/main/java/com/kamco/cd/kamcoback/trainingdata/dto/TrainingDataReviewDto.java index d3026009..851a96ff 100644 --- a/src/main/java/com/kamco/cd/kamcoback/trainingdata/dto/TrainingDataReviewDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/trainingdata/dto/TrainingDataReviewDto.java @@ -351,7 +351,7 @@ public class TrainingDataReviewDto { private Double detectionAccuracy; @Schema(description = "PNU (필지고유번호)", example = "36221202306020") - private Long pnu; + private List pnu; @Schema(description = "도엽번호 (map_sheet_num)", example = "34602057") private Long mapSheetNum; From 32cb47cfc2fc0f9d7a888ad6103ad71a94f9e44a Mon Sep 17 00:00:00 2001 From: teddy Date: Thu, 29 Jan 2026 16:23:44 +0900 Subject: [PATCH 05/41] =?UTF-8?q?geojson=20=ED=8C=8C=EC=9D=BC=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20api=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../InferenceResultShpApiController.java | 35 +++++++++++++++++++ .../service/InferenceResultShpService.java | 24 +++++++++++++ 2 files changed, 59 insertions(+) diff --git a/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultShpApiController.java b/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultShpApiController.java index c4571f40..4821941c 100644 --- a/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultShpApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultShpApiController.java @@ -1,5 +1,7 @@ package com.kamco.cd.kamcoback.inference; +import com.kamco.cd.kamcoback.common.exception.CustomApiException; +import com.kamco.cd.kamcoback.common.geometry.GeoJsonFileWriter.Scene; import com.kamco.cd.kamcoback.config.api.ApiResponseDto; import com.kamco.cd.kamcoback.inference.dto.InferenceResultShpDto; import com.kamco.cd.kamcoback.inference.service.InferenceResultShpService; @@ -10,20 +12,28 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; +import java.util.List; +import java.util.Map; import java.util.UUID; import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; +import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @Tag(name = "추론결과 데이터 생성", description = "추론결과 데이터 생성 API") +@Log4j2 @RestController @RequiredArgsConstructor @RequestMapping("/api/inference/shp") public class InferenceResultShpApiController { private final InferenceResultShpService inferenceResultShpService; + public static final String MAP_ID = + "{ \"mapIds\": [\"37716096\",\"37716095\",\"37716094\",\"37716091\",\"37716086\",\"37716085\",\"37716084\",\"37716083\",\"37716076\",\"37716066\",\"37716065\",\"37716064\",\"37716063\",\"37716061\",\"37716051\",\"37716011\"] }"; @Operation(summary = "추론결과 데이터 저장", description = "추론결과 데이터 저장") @ApiResponses( @@ -52,4 +62,29 @@ public class InferenceResultShpApiController { inferenceResultShpService.createShp(uuid); return ApiResponseDto.createOK(null); } + + @Operation(summary = "추론실행에 필요한 geojson 파일 생성", description = "추론실행에 필요한 geojson 파일 생성") + @PostMapping("/geojson/{yyyy}/{mapSheetScope}/{detectOption}") + public ApiResponseDto createGeojson( + @Schema(description = "년도") @PathVariable String yyyy, + @Schema(description = "전체(ALL),부분(PART)", example = "PART") @PathVariable + String mapSheetScope, + @Schema(description = "추론제외(EXCL),이전 년도 도엽 사용(PREV)", example = "EXCL") @PathVariable + String detectOption, + @Schema(description = "5k도엽번호", example = MAP_ID) @RequestBody Map body) { + + Object raw = body.get("mapIds"); + + if (raw == null) { + throw new CustomApiException("BAD_REQUEST", HttpStatus.BAD_REQUEST); + } + + @SuppressWarnings("unchecked") + List mapIds = (List) raw; + + Scene scene = + inferenceResultShpService.createGeojson(yyyy, mapSheetScope, detectOption, mapIds); + + return ApiResponseDto.createOK(scene); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultShpService.java b/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultShpService.java index 3e5cfff2..fc41a727 100644 --- a/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultShpService.java +++ b/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultShpService.java @@ -1,15 +1,20 @@ package com.kamco.cd.kamcoback.inference.service; +import com.kamco.cd.kamcoback.common.geometry.GeoJsonFileWriter.Scene; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.InferenceLearnDto; import com.kamco.cd.kamcoback.inference.dto.InferenceResultShpDto; import com.kamco.cd.kamcoback.postgres.core.InferenceResultCoreService; import com.kamco.cd.kamcoback.postgres.core.InferenceResultShpCoreService; +import com.kamco.cd.kamcoback.postgres.core.MapSheetMngCoreService; import com.kamco.cd.kamcoback.scheduler.service.ShpPipelineService; +import java.util.List; import java.util.Objects; import java.util.UUID; import java.util.stream.Collectors; import java.util.stream.Stream; import lombok.RequiredArgsConstructor; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -19,9 +24,11 @@ import org.springframework.transaction.annotation.Transactional; @Transactional(readOnly = true) public class InferenceResultShpService { + private static final Logger log = LogManager.getLogger(InferenceResultShpService.class); private final InferenceResultShpCoreService coreService; private final InferenceResultCoreService inferenceResultCoreService; private final ShpPipelineService shpPipelineService; + private final MapSheetMngCoreService mapSheetMngCoreService; @Value("${mapsheet.shp.baseurl}") private String baseDir; @@ -59,4 +66,21 @@ public class InferenceResultShpService { // shp 파일 비동기 생성 shpPipelineService.runPipeline(jarPath, datasetDir, batchId, dto.getUid()); } + + /** + * 추론 실행전 geojson 파일 생성 + * + * @param yyyy + * @param mapSheetScope + * @param detectOption + * @param mapIds + * @return + */ + public Scene createGeojson( + String yyyy, String mapSheetScope, String detectOption, List mapIds) { + Scene getSceneInference = + mapSheetMngCoreService.getSceneInference(yyyy, mapIds, mapSheetScope, detectOption); + log.info("getSceneInference: {}", getSceneInference); + return getSceneInference; + } } From 38ad63172a52ca5729dffc5da1094a1a01fa1109 Mon Sep 17 00:00:00 2001 From: teddy Date: Thu, 29 Jan 2026 17:34:15 +0900 Subject: [PATCH 06/41] =?UTF-8?q?ai=20=EC=A3=BC=EC=86=8C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application-dev.yml | 4 ++-- src/main/resources/application-prod.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 7085a0b1..16ca5d35 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -108,8 +108,8 @@ file: pt-FileName: yolov8_6th-6m.pt inference: - url: http://10.100.0.11:8000/jobs - batch-url: http://10.100.0.11:8000/batches + url: http://192.168.2.183:8000/jobs + batch-url: http://192.168.2.183:8000/batches geojson-dir: /kamco-nfs/requests/ jar-path: /kamco-nfs/dataset/shp/shp-exporter-1.0.0.jar inference-server-name: server1,server2,server3,server4 diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index 8cee0e13..caa790bc 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -63,8 +63,8 @@ file: pt-FileName: yolov8_6th-6m.pt inference: - url: http://10.100.0.11:8000/jobs - batch-url: http://10.100.0.11:8000/batches + url: http://192.168.2.183:8000/jobs + batch-url: http://192.168.2.183:8000/batches geojson-dir: /kamco-nfs/requests/ jar-path: /kamco-nfs/dataset/shp/shp-exporter-1.0.0.jar inference-server-name: server1,server2,server3,server4 From e4550d1e71bc80a0ab588b35e6731b649a98de39 Mon Sep 17 00:00:00 2001 From: "gayoun.park" Date: Thu, 29 Jan 2026 19:03:08 +0900 Subject: [PATCH 07/41] =?UTF-8?q?=EC=98=81=EC=83=81=EA=B4=80=EB=A6=AC=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=20=EB=85=84=EB=8F=84=20tile=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/GlobalExceptionHandler.java | 3 +- .../mapsheet/dto/MapSheetMngDto.java | 26 +++++++++ .../postgres/core/MapSheetMngCoreService.java | 3 + .../entity/MapSheetMngTileEntity.java | 55 +++++++++++++++++++ .../mapsheet/MapSheetMngRepositoryCustom.java | 3 + .../mapsheet/MapSheetMngRepositoryImpl.java | 30 ++++++++++ 6 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetMngTileEntity.java diff --git a/src/main/java/com/kamco/cd/kamcoback/config/GlobalExceptionHandler.java b/src/main/java/com/kamco/cd/kamcoback/config/GlobalExceptionHandler.java index 85907d1a..cc9a2b2b 100644 --- a/src/main/java/com/kamco/cd/kamcoback/config/GlobalExceptionHandler.java +++ b/src/main/java/com/kamco/cd/kamcoback/config/GlobalExceptionHandler.java @@ -465,8 +465,7 @@ public class GlobalExceptionHandler { String stackTraceStr = Arrays.stream(stackTrace) .map(StackTraceElement::toString) - .collect(Collectors.joining("\n")) - .substring(0, 255); + .collect(Collectors.joining("\n")); String actionType = HeaderUtil.get(request, "kamco-action-type"); diff --git a/src/main/java/com/kamco/cd/kamcoback/mapsheet/dto/MapSheetMngDto.java b/src/main/java/com/kamco/cd/kamcoback/mapsheet/dto/MapSheetMngDto.java index 02d65de8..7db50900 100644 --- a/src/main/java/com/kamco/cd/kamcoback/mapsheet/dto/MapSheetMngDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/mapsheet/dto/MapSheetMngDto.java @@ -7,6 +7,7 @@ import com.kamco.cd.kamcoback.common.utils.enums.EnumType; import com.kamco.cd.kamcoback.common.utils.enums.Enums; import com.kamco.cd.kamcoback.common.utils.interfaces.JsonFormatDttm; import io.swagger.v3.oas.annotations.media.Schema; +import java.math.BigDecimal; import java.time.ZonedDateTime; import java.util.List; import java.util.UUID; @@ -77,6 +78,31 @@ public class MapSheetMngDto { @Schema(description = "선택폴더경로", example = "D:\\app\\original-images\\2022") private String mngPath; + // Tile 등록 로직 + @Schema(description = "url") + private String url; + + @Schema(description = "좌측상단 경도", example = "126.0") + private BigDecimal minLon; + + @Schema(description = "좌측상단 위도", example = "34.0") + private BigDecimal minLat; + + @Schema(description = "우측하단 경도", example = "130.0") + private BigDecimal maxLon; + + @Schema(description = "우측하단 위도", example = "38.5") + private BigDecimal maxLat; + + @Schema(description = "zoom min", example = "5") + private Short minZoom; + + @Schema(description = "zoom max", example = "18") + private Short maxZoom; + + @Schema(description = "tag") + private String tag; + @JsonIgnore private Long createdUid; } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapSheetMngCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapSheetMngCoreService.java index 233fc813..6b3a83a0 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapSheetMngCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapSheetMngCoreService.java @@ -162,6 +162,9 @@ public class MapSheetMngCoreService { saved.getMngYyyy(), saved.getMngPath()); mapSheetMngRepository.updateYearState(saved.getMngYyyy(), "DONE"); + // 년도별 Tile 정보 등록 + mapSheetMngRepository.insertMapSheetMngTile(addReq); + return hstCnt; } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetMngTileEntity.java b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetMngTileEntity.java new file mode 100644 index 00000000..7e2e1ebf --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetMngTileEntity.java @@ -0,0 +1,55 @@ +package com.kamco.cd.kamcoback.postgres.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import jakarta.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.ZonedDateTime; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.annotations.ColumnDefault; + +@Getter +@Setter +@Entity +@Table(name = "tb_map_sheet_mng_tile") +public class MapSheetMngTileEntity { + + @Id + @Column(name = "mng_yyyy", nullable = false) + private Integer mngYyyy; + + @Column(name = "url", length = Integer.MAX_VALUE) + private String url; + + @Column(name = "min_lon", precision = 10, scale = 7) + private BigDecimal minLon; + + @Column(name = "min_lat", precision = 10, scale = 7) + private BigDecimal minLat; + + @Column(name = "max_lon", precision = 10, scale = 7) + private BigDecimal maxLon; + + @Column(name = "max_lat", precision = 10, scale = 7) + private BigDecimal maxLat; + + @Column(name = "min_zoom") + private Short minZoom; + + @Column(name = "max_zoom") + private Short maxZoom; + + @Column(name = "tag") + private String tag; + + @NotNull + @ColumnDefault("now()") + @Column(name = "created_dttm", nullable = false) + private ZonedDateTime createdDttm = ZonedDateTime.now(); + + @Column(name = "updated_dttm") + private ZonedDateTime updatedDttm; +} diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryCustom.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryCustom.java index 6b985fc1..fa4a8382 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryCustom.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryCustom.java @@ -3,6 +3,7 @@ package com.kamco.cd.kamcoback.postgres.repository.mapsheet; import com.kamco.cd.kamcoback.common.geometry.GeoJsonFileWriter.ImageFeature; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto; import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto; +import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto.AddReq; import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto.MngListDto; import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto.YearSearchReq; import com.kamco.cd.kamcoback.postgres.entity.MapSheetMngHstEntity; @@ -77,4 +78,6 @@ public interface MapSheetMngRepositoryCustom { List getSceneInference(String yyyy, List mapSheetNums); void updateMapSheetMngHstUploadId(Long hstUid, UUID uuid, String uploadId); + + void insertMapSheetMngTile(@Valid AddReq addReq); } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryImpl.java index 86839830..04118275 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryImpl.java @@ -4,6 +4,7 @@ import static com.kamco.cd.kamcoback.postgres.entity.QMapInkx5kEntity.mapInkx5kE import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetMngEntity.mapSheetMngEntity; import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetMngFileEntity.mapSheetMngFileEntity; import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetMngHstEntity.mapSheetMngHstEntity; +import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetMngTileEntity.mapSheetMngTileEntity; import static com.kamco.cd.kamcoback.postgres.entity.QYearEntity.yearEntity; import static com.querydsl.core.types.dsl.Expressions.nullExpression; @@ -12,6 +13,7 @@ import com.kamco.cd.kamcoback.common.geometry.GeoJsonFileWriter.ImageFeature; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.MapSheetScope; import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto; +import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto.AddReq; import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto.MngListDto; import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto.YearSearchReq; import com.kamco.cd.kamcoback.postgres.entity.MapSheetMngHstEntity; @@ -1040,6 +1042,34 @@ public class MapSheetMngRepositoryImpl extends QuerydslRepositorySupport .execute(); } + @Override + public void insertMapSheetMngTile(AddReq addReq) { + long execute = + queryFactory + .insert(mapSheetMngTileEntity) + .columns( + mapSheetMngTileEntity.mngYyyy, + mapSheetMngTileEntity.url, + mapSheetMngTileEntity.minLon, + mapSheetMngTileEntity.minLat, + mapSheetMngTileEntity.maxLon, + mapSheetMngTileEntity.maxLat, + mapSheetMngTileEntity.minZoom, + mapSheetMngTileEntity.maxZoom, + mapSheetMngTileEntity.tag) + .values( + addReq.getMngYyyy(), + addReq.getUrl(), + addReq.getMinLon(), + addReq.getMinLat(), + addReq.getMaxLon(), + addReq.getMaxLat(), + addReq.getMinZoom(), + addReq.getMaxZoom(), + addReq.getTag()) + .execute(); + } + private BooleanExpression eqYearStatus(QYearEntity years, String status) { if (status == null) { return null; From cea1d82bd92e05254d14f8a3b141e19c82b55bc1 Mon Sep 17 00:00:00 2001 From: teddy Date: Thu, 29 Jan 2026 20:12:00 +0900 Subject: [PATCH 08/41] =?UTF-8?q?ai=20=EC=A3=BC=EC=86=8C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application-dev.yml | 2 +- src/main/resources/application-prod.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 16ca5d35..f8bfc625 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -123,5 +123,5 @@ training-data: geojson-dir: /kamco-nfs/model_output/labeling/ layer: - geoserver-url: https://label-tile.gs.dabeeo.com + geoserver-url: http://label-tile.gs.dabeeo.com workspace: cd diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index caa790bc..511840cc 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -78,5 +78,5 @@ training-data: geojson-dir: /kamco-nfs/model_output/labeling/ layer: - geoserver-url: https://label-tile.gs.dabeeo.com + geoserver-url: http://label-tile.gs.dabeeo.com workspace: cd From 9bec466d7cbfcdbf055bc7d1f197a9ed88587281 Mon Sep 17 00:00:00 2001 From: "gayoun.park" Date: Thu, 29 Jan 2026 20:56:14 +0900 Subject: [PATCH 09/41] =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=96=B4=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20-=20=EB=B3=80=ED=99=94=EC=A7=80=EB=8F=84,=EB=9D=BC?= =?UTF-8?q?=EB=B2=A8=EB=A7=81=ED=88=B4=20=EB=A7=B5=20=EB=A6=AC=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cd/kamcoback/config/SecurityConfig.java | 3 +- .../kamcoback/layer/LayerApiController.java | 37 ++++++++ .../cd/kamcoback/layer/dto/LayerDto.java | 93 +++++++++++++++++++ .../kamcoback/layer/service/LayerService.java | 5 + .../postgres/core/MapLayerCoreService.java | 6 ++ .../layer/MapLayerRepositoryCustom.java | 4 + .../layer/MapLayerRepositoryImpl.java | 37 ++++++++ 7 files changed, 184 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/config/SecurityConfig.java b/src/main/java/com/kamco/cd/kamcoback/config/SecurityConfig.java index d89330c5..c0093364 100644 --- a/src/main/java/com/kamco/cd/kamcoback/config/SecurityConfig.java +++ b/src/main/java/com/kamco/cd/kamcoback/config/SecurityConfig.java @@ -85,7 +85,8 @@ public class SecurityConfig { "/api/model/file-chunk-upload", "/api/upload/file-chunk-upload", "/api/upload/chunk-upload-complete", - "/api/change-detection/**") + "/api/change-detection/**", + "/api/layer/map/**") .permitAll() // 로그인한 사용자만 가능 IAM .requestMatchers( diff --git a/src/main/java/com/kamco/cd/kamcoback/layer/LayerApiController.java b/src/main/java/com/kamco/cd/kamcoback/layer/LayerApiController.java index e407e92d..91ebdce0 100644 --- a/src/main/java/com/kamco/cd/kamcoback/layer/LayerApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/layer/LayerApiController.java @@ -2,6 +2,7 @@ package com.kamco.cd.kamcoback.layer; import com.kamco.cd.kamcoback.config.api.ApiResponseDto; import com.kamco.cd.kamcoback.layer.dto.LayerDto; +import com.kamco.cd.kamcoback.layer.dto.LayerDto.LayerMapDto; import com.kamco.cd.kamcoback.layer.dto.LayerDto.OrderReq; import com.kamco.cd.kamcoback.layer.dto.LayerDto.SearchReq; import com.kamco.cd.kamcoback.layer.service.LayerService; @@ -187,4 +188,40 @@ public class LayerApiController { public ApiResponseDto> getWmsTile() { return ApiResponseDto.ok(layerService.getWmsTitle()); } + + @Operation(summary = "변화지도 레이어 조회", description = "변화지도 레이어 조회") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + description = "검색 성공", + content = + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = String.class)))), + @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) + @GetMapping("/map/change-detection") + public ApiResponseDto> changeDetectionMap() { + return ApiResponseDto.ok(layerService.findLayerMapList("change-detection")); + } + + @Operation(summary = "라벨링 툴 레이어 조회", description = "라벨링 툴 레이어 조회") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + description = "검색 성공", + content = + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = String.class)))), + @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) + @GetMapping("/map/labeling") + public ApiResponseDto> labelingMap() { + return ApiResponseDto.ok(layerService.findLayerMapList("labeling")); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/layer/dto/LayerDto.java b/src/main/java/com/kamco/cd/kamcoback/layer/dto/LayerDto.java index 77c9012b..3c5671f8 100644 --- a/src/main/java/com/kamco/cd/kamcoback/layer/dto/LayerDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/layer/dto/LayerDto.java @@ -1,5 +1,9 @@ package com.kamco.cd.kamcoback.layer.dto; +import com.fasterxml.jackson.annotation.JsonIgnore; +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.interfaces.JsonFormatDttm; import io.swagger.v3.oas.annotations.media.Schema; import java.math.BigDecimal; @@ -17,6 +21,7 @@ public class LayerDto { @AllArgsConstructor @Schema(name = "LayerBasic") public static class Basic { + @Schema(description = "uuid") private UUID uuid; @@ -48,6 +53,7 @@ public class LayerDto { @AllArgsConstructor @Schema(name = "LayerDetail") public static class Detail { + @Schema(description = "uuid") private UUID uuid; @@ -153,6 +159,7 @@ public class LayerDto { @AllArgsConstructor @NoArgsConstructor public static class SearchReq { + private String tag; private String layerType; } @@ -162,6 +169,7 @@ public class LayerDto { @AllArgsConstructor @NoArgsConstructor public static class TileAddReqDto { + @Schema(description = "설명", example = "배경지도 입니다.") private String description; @@ -189,4 +197,89 @@ public class LayerDto { @Schema(description = "zoom max", example = "18") private Short max; } + + @Getter + @Setter + @Schema(name = "LayerMapDto") + public static class LayerMapDto { + + @Schema(example = "WMTS", description = "유형 (TILE/GEOJSON/WMTS/WMS)") + private String layerType; + + @Schema(description = "title") + private String title; + + @Schema(description = "설명") + private String description; + + @Schema(description = "태그") + private String tag; + + @Schema(description = "순서") + private Long sortOrder; + + @Schema(description = "url") + private String url; + + @Schema(description = "좌측상단 경도", example = "126.0") + private BigDecimal minLon; + + @Schema(description = "좌측상단 위도", example = "34.0") + private BigDecimal minLat; + + @Schema(description = "우측하단 경도", example = "130.0") + private BigDecimal maxLon; + + @Schema(description = "우측하단 위도", example = "38.5") + private BigDecimal maxLat; + + @Schema(description = "zoom min", example = "5") + private Short minZoom; + + @Schema(description = "zoom max", example = "18") + private Short maxZoom; + + @Schema(description = "bbox") + private JsonNode bbox; + + @JsonIgnore private String bboxGeometry; + + public LayerMapDto( + String layerType, + String tag, + Long sortOrder, + String url, + BigDecimal minLon, + BigDecimal minLat, + BigDecimal maxLon, + BigDecimal maxLat, + Short minZoom, + Short maxZoom, + String bboxGeometry) { + this.layerType = layerType; + this.tag = tag; + this.sortOrder = sortOrder; + this.url = url; + this.minLon = minLon; + this.minLat = minLat; + this.maxLon = maxLon; + this.maxLat = maxLat; + this.minZoom = minZoom; + this.maxZoom = maxZoom; + this.bboxGeometry = bboxGeometry; + + JsonNode geoJson = null; + + if (bboxGeometry != null) { + ObjectMapper mapper = new ObjectMapper(); + try { + geoJson = mapper.readTree(bboxGeometry); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + this.bbox = geoJson; + } + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/layer/service/LayerService.java b/src/main/java/com/kamco/cd/kamcoback/layer/service/LayerService.java index 68db7085..b1bf2c28 100644 --- a/src/main/java/com/kamco/cd/kamcoback/layer/service/LayerService.java +++ b/src/main/java/com/kamco/cd/kamcoback/layer/service/LayerService.java @@ -4,6 +4,7 @@ import com.kamco.cd.kamcoback.common.enums.LayerType; import com.kamco.cd.kamcoback.common.exception.CustomApiException; import com.kamco.cd.kamcoback.layer.dto.LayerDto; import com.kamco.cd.kamcoback.layer.dto.LayerDto.Basic; +import com.kamco.cd.kamcoback.layer.dto.LayerDto.LayerMapDto; import com.kamco.cd.kamcoback.layer.dto.LayerDto.OrderReq; import com.kamco.cd.kamcoback.layer.dto.WmsDto.WmsAddDto; import com.kamco.cd.kamcoback.layer.dto.WmsDto.WmsAddReqDto; @@ -159,4 +160,8 @@ public class LayerService { addDto.setTag(dto.getTag()); return mapLayerCoreService.saveWms(addDto); } + + public List findLayerMapList(String type) { + return mapLayerCoreService.findLayerMapList(type); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapLayerCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapLayerCoreService.java index 7b2b3011..e1d4213f 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapLayerCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapLayerCoreService.java @@ -6,6 +6,7 @@ import com.kamco.cd.kamcoback.common.enums.LayerType; import com.kamco.cd.kamcoback.common.exception.CustomApiException; import com.kamco.cd.kamcoback.common.utils.UserUtil; import com.kamco.cd.kamcoback.layer.dto.LayerDto; +import com.kamco.cd.kamcoback.layer.dto.LayerDto.LayerMapDto; import com.kamco.cd.kamcoback.layer.dto.LayerDto.OrderReq; import com.kamco.cd.kamcoback.layer.dto.WmsDto.WmsAddDto; import com.kamco.cd.kamcoback.layer.dto.WmtsDto.WmtsAddDto; @@ -25,6 +26,7 @@ import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor public class MapLayerCoreService { + private final MapLayerRepository mapLayerRepository; private final UserUtil userUtil; private final ObjectMapper objectMapper; @@ -291,4 +293,8 @@ public class MapLayerCoreService { mapLayerEntity.setTag(addDto.getTag()); return mapLayerRepository.save(mapLayerEntity).getUuid(); } + + public List findLayerMapList(String type) { + return mapLayerRepository.findLayerMapList(type); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryCustom.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryCustom.java index 3bcf5b72..a3546014 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryCustom.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryCustom.java @@ -1,6 +1,7 @@ package com.kamco.cd.kamcoback.postgres.repository.layer; import com.kamco.cd.kamcoback.layer.dto.LayerDto; +import com.kamco.cd.kamcoback.layer.dto.LayerDto.LayerMapDto; import com.kamco.cd.kamcoback.postgres.entity.MapLayerEntity; import java.util.Collection; import java.util.List; @@ -8,6 +9,7 @@ import java.util.Optional; import java.util.UUID; public interface MapLayerRepositoryCustom { + Long findSortOrderDesc(); List findAllLayer(LayerDto.SearchReq searchReq); @@ -15,4 +17,6 @@ public interface MapLayerRepositoryCustom { Optional findDetailByUuid(UUID uuid); List findAllByUuidIn(Collection uuids); + + List findLayerMapList(String type); } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryImpl.java index 58f83231..46dea36d 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryImpl.java @@ -3,9 +3,12 @@ package com.kamco.cd.kamcoback.postgres.repository.layer; import static com.kamco.cd.kamcoback.postgres.entity.QMapLayerEntity.mapLayerEntity; import com.kamco.cd.kamcoback.layer.dto.LayerDto; +import com.kamco.cd.kamcoback.layer.dto.LayerDto.LayerMapDto; import com.kamco.cd.kamcoback.postgres.entity.MapLayerEntity; import com.querydsl.core.BooleanBuilder; import com.querydsl.core.types.Projections; +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.core.types.dsl.Expressions; import com.querydsl.jpa.impl.JPAQueryFactory; import java.util.Collection; import java.util.List; @@ -84,4 +87,38 @@ public class MapLayerRepositoryImpl implements MapLayerRepositoryCustom { .orderBy(mapLayerEntity.order.asc()) .fetch(); } + + @Override + public List findLayerMapList(String type) { + return queryFactory + .select( + Projections.constructor( + LayerMapDto.class, + mapLayerEntity.layerType, + mapLayerEntity.tag, + mapLayerEntity.order, + mapLayerEntity.url, + mapLayerEntity.minLon, + mapLayerEntity.minLat, + mapLayerEntity.maxLon, + mapLayerEntity.maxLat, + mapLayerEntity.minZoom, + mapLayerEntity.maxZoom, + Expressions.stringTemplate( + "ST_AsGeoJSON(ST_MakeEnvelope({0}, {1}, {2}, {3}, 4326))", + mapLayerEntity.minLon, + mapLayerEntity.minLat, + mapLayerEntity.maxLon, + mapLayerEntity.maxLat))) + .from(mapLayerEntity) + .where(layerTypeCondition(type), mapLayerEntity.isDeleted.isFalse()) + .orderBy(mapLayerEntity.order.asc()) + .fetch(); + } + + private BooleanExpression layerTypeCondition(String type) { + return type.equals("change-detection") + ? mapLayerEntity.isChangeMap.isTrue() + : mapLayerEntity.isLabelingMap.isTrue(); + } } From e379c4945333b800e1bf66224894a917ab9b166f Mon Sep 17 00:00:00 2001 From: teddy Date: Fri, 30 Jan 2026 09:50:32 +0900 Subject: [PATCH 10/41] =?UTF-8?q?geoserver=20=EB=93=B1=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/service/ExternalJarRunner.java | 2 +- src/main/resources/application-dev.yml | 2 +- src/main/resources/application-local.yml | 16 ++++++++-------- src/main/resources/application-prod.yml | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/common/service/ExternalJarRunner.java b/src/main/java/com/kamco/cd/kamcoback/common/service/ExternalJarRunner.java index ea436e50..bc5a35a8 100644 --- a/src/main/java/com/kamco/cd/kamcoback/common/service/ExternalJarRunner.java +++ b/src/main/java/com/kamco/cd/kamcoback/common/service/ExternalJarRunner.java @@ -54,7 +54,7 @@ public class ExternalJarRunner { public void run(String jarPath, String register, String layer) { List args = new ArrayList<>(); - addArg(args, "register", register); + addArg(args, "upload-shp", register); addArg(args, "layer", layer); execJar(jarPath, args); diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index f8bfc625..eae767f3 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -111,7 +111,7 @@ inference: url: http://192.168.2.183:8000/jobs batch-url: http://192.168.2.183:8000/batches geojson-dir: /kamco-nfs/requests/ - jar-path: /kamco-nfs/dataset/shp/shp-exporter-1.0.0.jar + jar-path: /kamco-nfs/dataset/shp/shp-exporter.jar inference-server-name: server1,server2,server3,server4 gukyuin: diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index 5409635f..64782c9a 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -15,8 +15,8 @@ spring: format_sql: true # ⚠️ 선택 - SQL 포맷팅 (가독성) datasource: - #url: jdbc:postgresql://192.168.2.127:15432/kamco_cds - url: jdbc:postgresql://localhost:5432/kamco_cds # 로컬호스트 + url: jdbc:postgresql://192.168.2.127:15432/kamco_cds + #url: jdbc:postgresql://localhost:5432/kamco_cds # 로컬호스트 username: kamco_cds password: kamco_cds_Q!W@E#R$ hikari: @@ -84,20 +84,20 @@ file: model-tmp-dir: ${file.model-dir}tmp/ model-file-extention: pth,json,py - pt-path: /kamco-nfs/ckpt/classification/ - pt-FileName: v5-best.pt + pt-path: /kamco-nfs/ckpt/model/v6-cls-checkpoints/ + pt-FileName: yolov8_6th-6m.pt inference: - url: http://10.100.0.11:8000/jobs - batch-url: http://10.100.0.11:8000/batches + url: http://192.168.2.183:8000/jobs + batch-url: http://192.168.2.183:8000/batches geojson-dir: /Users/bokmin/kamco-nfs/requests/ - jar-path: /Users/bokmin/kamco-nfs/dataset/shp/shp-exporter-1.0.0.jar + jar-path: /Users/bokmin/kamco-nfs/dataset/shp/shp-exporter.jar inference-server-name: server1,server2,server3,server4 gukyuin: #url: http://localhost:8080 url: http://192.168.2.129:5301 - mast: ${gukyuin.url}/api/kcd/cdi/chn/mast + cdi: ${gukyuin.url}/api/kcd/cdi training-data: geojson-dir: /Users/bokmin/kamco-nfs/model_output/labeling/ diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index 511840cc..58b73dc2 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -66,7 +66,7 @@ inference: url: http://192.168.2.183:8000/jobs batch-url: http://192.168.2.183:8000/batches geojson-dir: /kamco-nfs/requests/ - jar-path: /kamco-nfs/dataset/shp/shp-exporter-1.0.0.jar + jar-path: /kamco-nfs/dataset/shp/shp-exporter.jar inference-server-name: server1,server2,server3,server4 gukyuin: From 3686f1d24848a2fc8987f937ee9564cfc643609d Mon Sep 17 00:00:00 2001 From: teddy Date: Fri, 30 Jan 2026 10:21:06 +0900 Subject: [PATCH 11/41] =?UTF-8?q?geoserver=20=EB=93=B1=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kamco/cd/kamcoback/common/service/ExternalJarRunner.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/common/service/ExternalJarRunner.java b/src/main/java/com/kamco/cd/kamcoback/common/service/ExternalJarRunner.java index bc5a35a8..b672a792 100644 --- a/src/main/java/com/kamco/cd/kamcoback/common/service/ExternalJarRunner.java +++ b/src/main/java/com/kamco/cd/kamcoback/common/service/ExternalJarRunner.java @@ -55,7 +55,7 @@ public class ExternalJarRunner { List args = new ArrayList<>(); addArg(args, "upload-shp", register); - addArg(args, "layer", layer); +// addArg(args, "layer", layer); execJar(jarPath, args); } From af19ca905bf27d5c557d610ecb363c64b7e8de10 Mon Sep 17 00:00:00 2001 From: teddy Date: Fri, 30 Jan 2026 10:22:39 +0900 Subject: [PATCH 12/41] =?UTF-8?q?geoserver=20=EB=93=B1=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kamco/cd/kamcoback/common/service/ExternalJarRunner.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/common/service/ExternalJarRunner.java b/src/main/java/com/kamco/cd/kamcoback/common/service/ExternalJarRunner.java index b672a792..6739b6de 100644 --- a/src/main/java/com/kamco/cd/kamcoback/common/service/ExternalJarRunner.java +++ b/src/main/java/com/kamco/cd/kamcoback/common/service/ExternalJarRunner.java @@ -55,7 +55,7 @@ public class ExternalJarRunner { List args = new ArrayList<>(); addArg(args, "upload-shp", register); -// addArg(args, "layer", layer); + // addArg(args, "layer", layer); execJar(jarPath, args); } From ceebbdfa5076b9646efb1bfda5e4a2c3313a6442 Mon Sep 17 00:00:00 2001 From: "gayoun.park" Date: Fri, 30 Jan 2026 10:51:22 +0900 Subject: [PATCH 13/41] =?UTF-8?q?=EB=B3=80=ED=99=94=EC=A7=80=EB=8F=84,=20?= =?UTF-8?q?=EB=9D=BC=EB=B2=A8=EB=A7=81=20=EB=A7=B5=20=EB=A6=AC=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20uuid,=20rawjson=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cd/kamcoback/layer/dto/LayerDto.java | 27 ++++++++++++++++--- .../layer/MapLayerRepositoryImpl.java | 4 ++- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/layer/dto/LayerDto.java b/src/main/java/com/kamco/cd/kamcoback/layer/dto/LayerDto.java index 3c5671f8..99914e5d 100644 --- a/src/main/java/com/kamco/cd/kamcoback/layer/dto/LayerDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/layer/dto/LayerDto.java @@ -244,6 +244,14 @@ public class LayerDto { @JsonIgnore private String bboxGeometry; + @Schema(description = "uuid") + private UUID uuid; + + @JsonIgnore private String rawJsonString; + + @Schema(description = "rawJson") + private JsonNode rawJson; + public LayerMapDto( String layerType, String tag, @@ -255,7 +263,9 @@ public class LayerDto { BigDecimal maxLat, Short minZoom, Short maxZoom, - String bboxGeometry) { + String bboxGeometry, + UUID uuid, + String rawJsonString) { this.layerType = layerType; this.tag = tag; this.sortOrder = sortOrder; @@ -267,11 +277,13 @@ public class LayerDto { this.minZoom = minZoom; this.maxZoom = maxZoom; this.bboxGeometry = bboxGeometry; + this.uuid = uuid; + this.rawJsonString = rawJsonString; JsonNode geoJson = null; - + JsonNode rawJson = null; + ObjectMapper mapper = new ObjectMapper(); if (bboxGeometry != null) { - ObjectMapper mapper = new ObjectMapper(); try { geoJson = mapper.readTree(bboxGeometry); } catch (JsonProcessingException e) { @@ -279,6 +291,15 @@ public class LayerDto { } } + if (rawJsonString != null) { + try { + rawJson = mapper.readTree(rawJsonString); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + this.rawJson = rawJson; this.bbox = geoJson; } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryImpl.java index 46dea36d..484171c4 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryImpl.java @@ -109,7 +109,9 @@ public class MapLayerRepositoryImpl implements MapLayerRepositoryCustom { mapLayerEntity.minLon, mapLayerEntity.minLat, mapLayerEntity.maxLon, - mapLayerEntity.maxLat))) + mapLayerEntity.maxLat), + mapLayerEntity.uuid, + Expressions.stringTemplate("cast({0} as text)", mapLayerEntity.rawJson))) .from(mapLayerEntity) .where(layerTypeCondition(type), mapLayerEntity.isDeleted.isFalse()) .orderBy(mapLayerEntity.order.asc()) From babf35142ad620f23ecaab6b44276b728ff88f67 Mon Sep 17 00:00:00 2001 From: "gayoun.park" Date: Fri, 30 Jan 2026 11:04:14 +0900 Subject: [PATCH 14/41] =?UTF-8?q?=EB=85=84=EB=8F=84=EB=B3=84=20=ED=83=80?= =?UTF-8?q?=EC=9D=BC=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kamcoback/layer/LayerApiController.java | 9 ++ .../cd/kamcoback/layer/dto/LayerDto.java | 86 +++++++++++++++++++ .../kamcoback/layer/service/LayerService.java | 4 + .../postgres/core/MapLayerCoreService.java | 4 + .../layer/MapLayerRepositoryCustom.java | 2 + .../layer/MapLayerRepositoryImpl.java | 54 ++++++++++++ 6 files changed, 159 insertions(+) diff --git a/src/main/java/com/kamco/cd/kamcoback/layer/LayerApiController.java b/src/main/java/com/kamco/cd/kamcoback/layer/LayerApiController.java index 91ebdce0..57cce6da 100644 --- a/src/main/java/com/kamco/cd/kamcoback/layer/LayerApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/layer/LayerApiController.java @@ -7,6 +7,7 @@ import com.kamco.cd.kamcoback.layer.dto.LayerDto.OrderReq; import com.kamco.cd.kamcoback.layer.dto.LayerDto.SearchReq; import com.kamco.cd.kamcoback.layer.service.LayerService; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; @@ -224,4 +225,12 @@ public class LayerApiController { public ApiResponseDto> labelingMap() { return ApiResponseDto.ok(layerService.findLayerMapList("labeling")); } + + @Operation(summary = "년도별 tile Url", description = "년도별 tile Url") + @GetMapping("/tile-url") + public ApiResponseDto getChangeDetectionTileUrl( + @Parameter(description = "이전 년도", example = "2023") @RequestParam Integer beforeYear, + @Parameter(description = "이후 년도", example = "2024") @RequestParam Integer afterYear) { + return ApiResponseDto.ok(layerService.getChangeDetectionTileUrl(beforeYear, afterYear)); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/layer/dto/LayerDto.java b/src/main/java/com/kamco/cd/kamcoback/layer/dto/LayerDto.java index 99914e5d..a31883a4 100644 --- a/src/main/java/com/kamco/cd/kamcoback/layer/dto/LayerDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/layer/dto/LayerDto.java @@ -303,4 +303,90 @@ public class LayerDto { this.bbox = geoJson; } } + + @Schema(name = "TileUrlDto", description = "Tile Url 정보") + @Getter + @Setter + @NoArgsConstructor + public static class TileUrlDto { + + @Schema(description = "mngYyyy") + private Integer mngYyyy; + + @Schema(description = "url") + private String url; + + @Schema(description = "태그") + private String tag; + + @Schema(description = "좌측상단 경도", example = "126.0") + private BigDecimal minLon; + + @Schema(description = "좌측상단 위도", example = "34.0") + private BigDecimal minLat; + + @Schema(description = "우측하단 경도", example = "130.0") + private BigDecimal maxLon; + + @Schema(description = "우측하단 위도", example = "38.5") + private BigDecimal maxLat; + + @Schema(description = "zoom min", example = "5") + private Short minZoom; + + @Schema(description = "zoom max", example = "18") + private Short maxZoom; + + @Schema(description = "bbox") + private JsonNode bbox; + + @JsonIgnore private String bboxGeometry; + + public TileUrlDto( + Integer mngYyyy, + String url, + String tag, + BigDecimal minLon, + BigDecimal minLat, + BigDecimal maxLon, + BigDecimal maxLat, + Short minZoom, + Short maxZoom, + String bboxGeometry) { + this.mngYyyy = mngYyyy; + this.url = url; + this.tag = tag; + this.minLon = minLon; + this.minLat = minLat; + this.maxLon = maxLon; + this.maxLat = maxLat; + this.minZoom = minZoom; + this.maxZoom = maxZoom; + this.bboxGeometry = bboxGeometry; + + JsonNode geoJson = null; + + if (bboxGeometry != null) { + ObjectMapper mapper = new ObjectMapper(); + try { + geoJson = mapper.readTree(bboxGeometry); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + this.bbox = geoJson; + } + } + + @Schema(name = "TileUrlDto", description = "Tile Url 정보") + @Getter + @Setter + @NoArgsConstructor + @AllArgsConstructor + public static class YearTileDto { + + private TileUrlDto before; + private TileUrlDto after; + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/layer/service/LayerService.java b/src/main/java/com/kamco/cd/kamcoback/layer/service/LayerService.java index b1bf2c28..52cba7bf 100644 --- a/src/main/java/com/kamco/cd/kamcoback/layer/service/LayerService.java +++ b/src/main/java/com/kamco/cd/kamcoback/layer/service/LayerService.java @@ -164,4 +164,8 @@ public class LayerService { public List findLayerMapList(String type) { return mapLayerCoreService.findLayerMapList(type); } + + public LayerDto.YearTileDto getChangeDetectionTileUrl(Integer beforeYear, Integer afterYear) { + return mapLayerCoreService.getChangeDetectionTileUrl(beforeYear, afterYear); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapLayerCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapLayerCoreService.java index e1d4213f..d8d8f49b 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapLayerCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapLayerCoreService.java @@ -297,4 +297,8 @@ public class MapLayerCoreService { public List findLayerMapList(String type) { return mapLayerRepository.findLayerMapList(type); } + + public LayerDto.YearTileDto getChangeDetectionTileUrl(Integer beforeYear, Integer afterYear) { + return mapLayerRepository.getChangeDetectionTileUrl(beforeYear, afterYear); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryCustom.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryCustom.java index a3546014..39ca2195 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryCustom.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryCustom.java @@ -19,4 +19,6 @@ public interface MapLayerRepositoryCustom { List findAllByUuidIn(Collection uuids); List findLayerMapList(String type); + + LayerDto.YearTileDto getChangeDetectionTileUrl(Integer beforeYear, Integer afterYear); } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryImpl.java index 484171c4..0ff76945 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryImpl.java @@ -1,6 +1,7 @@ package com.kamco.cd.kamcoback.postgres.repository.layer; import static com.kamco.cd.kamcoback.postgres.entity.QMapLayerEntity.mapLayerEntity; +import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetMngTileEntity.mapSheetMngTileEntity; import com.kamco.cd.kamcoback.layer.dto.LayerDto; import com.kamco.cd.kamcoback.layer.dto.LayerDto.LayerMapDto; @@ -118,6 +119,59 @@ public class MapLayerRepositoryImpl implements MapLayerRepositoryCustom { .fetch(); } + @Override + public LayerDto.YearTileDto getChangeDetectionTileUrl(Integer beforeYear, Integer afterYear) { + LayerDto.TileUrlDto before = + queryFactory + .select( + Projections.constructor( + LayerDto.TileUrlDto.class, + mapSheetMngTileEntity.mngYyyy, + mapSheetMngTileEntity.tag, + mapSheetMngTileEntity.url, + mapSheetMngTileEntity.minLon, + mapSheetMngTileEntity.minLat, + mapSheetMngTileEntity.maxLon, + mapSheetMngTileEntity.maxLat, + mapSheetMngTileEntity.minZoom, + mapSheetMngTileEntity.maxZoom, + Expressions.stringTemplate( + "ST_AsGeoJSON(ST_MakeEnvelope({0}, {1}, {2}, {3}, 4326))", + mapSheetMngTileEntity.minLon, + mapSheetMngTileEntity.minLat, + mapSheetMngTileEntity.maxLon, + mapSheetMngTileEntity.maxLat))) + .from(mapSheetMngTileEntity) + .where(mapSheetMngTileEntity.mngYyyy.eq(beforeYear)) + .fetchOne(); + + LayerDto.TileUrlDto after = + queryFactory + .select( + Projections.constructor( + LayerDto.TileUrlDto.class, + mapSheetMngTileEntity.mngYyyy, + mapSheetMngTileEntity.tag, + mapSheetMngTileEntity.url, + mapSheetMngTileEntity.minLon, + mapSheetMngTileEntity.minLat, + mapSheetMngTileEntity.maxLon, + mapSheetMngTileEntity.maxLat, + mapSheetMngTileEntity.minZoom, + mapSheetMngTileEntity.maxZoom, + Expressions.stringTemplate( + "ST_AsGeoJSON(ST_MakeEnvelope({0}, {1}, {2}, {3}, 4326))", + mapSheetMngTileEntity.minLon, + mapSheetMngTileEntity.minLat, + mapSheetMngTileEntity.maxLon, + mapSheetMngTileEntity.maxLat))) + .from(mapSheetMngTileEntity) + .where(mapSheetMngTileEntity.mngYyyy.eq(afterYear)) + .fetchOne(); + + return new LayerDto.YearTileDto(before, after); + } + private BooleanExpression layerTypeCondition(String type) { return type.equals("change-detection") ? mapLayerEntity.isChangeMap.isTrue() From 10ab050a1cb80a9709f66dc2b53ac4b2c86c2d54 Mon Sep 17 00:00:00 2001 From: "gayoun.park" Date: Fri, 30 Jan 2026 11:17:13 +0900 Subject: [PATCH 15/41] =?UTF-8?q?=EB=85=84=EB=8F=84=201=EA=B0=9C=EB=A7=8C?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20=ED=83=80=EC=9D=BC=20?= =?UTF-8?q?API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kamcoback/layer/LayerApiController.java | 9 ++++++- .../kamcoback/layer/service/LayerService.java | 5 ++++ .../postgres/core/MapLayerCoreService.java | 5 ++++ .../layer/MapLayerRepositoryCustom.java | 3 +++ .../layer/MapLayerRepositoryImpl.java | 27 +++++++++++++++++++ 5 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/layer/LayerApiController.java b/src/main/java/com/kamco/cd/kamcoback/layer/LayerApiController.java index 57cce6da..d7bc1313 100644 --- a/src/main/java/com/kamco/cd/kamcoback/layer/LayerApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/layer/LayerApiController.java @@ -226,11 +226,18 @@ public class LayerApiController { return ApiResponseDto.ok(layerService.findLayerMapList("labeling")); } - @Operation(summary = "년도별 tile Url", description = "년도별 tile Url") + @Operation(summary = "년도별 tile Url(before,after 모두 조회)", description = "년도별 tile Url") @GetMapping("/tile-url") public ApiResponseDto getChangeDetectionTileUrl( @Parameter(description = "이전 년도", example = "2023") @RequestParam Integer beforeYear, @Parameter(description = "이후 년도", example = "2024") @RequestParam Integer afterYear) { return ApiResponseDto.ok(layerService.getChangeDetectionTileUrl(beforeYear, afterYear)); } + + @Operation(summary = "년도별 tile Url(년도 1개만 조회)", description = "년도별 tile Url") + @GetMapping("/tile-url-year") + public ApiResponseDto getChangeDetectionTileOneYearUrl( + @Parameter(description = "년도", example = "2023") @RequestParam Integer year) { + return ApiResponseDto.ok(layerService.getChangeDetectionTileOneYearUrl(year)); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/layer/service/LayerService.java b/src/main/java/com/kamco/cd/kamcoback/layer/service/LayerService.java index 52cba7bf..b78dfa8b 100644 --- a/src/main/java/com/kamco/cd/kamcoback/layer/service/LayerService.java +++ b/src/main/java/com/kamco/cd/kamcoback/layer/service/LayerService.java @@ -6,6 +6,7 @@ import com.kamco.cd.kamcoback.layer.dto.LayerDto; import com.kamco.cd.kamcoback.layer.dto.LayerDto.Basic; import com.kamco.cd.kamcoback.layer.dto.LayerDto.LayerMapDto; import com.kamco.cd.kamcoback.layer.dto.LayerDto.OrderReq; +import com.kamco.cd.kamcoback.layer.dto.LayerDto.TileUrlDto; import com.kamco.cd.kamcoback.layer.dto.WmsDto.WmsAddDto; import com.kamco.cd.kamcoback.layer.dto.WmsDto.WmsAddReqDto; import com.kamco.cd.kamcoback.layer.dto.WmsLayerInfo; @@ -168,4 +169,8 @@ public class LayerService { public LayerDto.YearTileDto getChangeDetectionTileUrl(Integer beforeYear, Integer afterYear) { return mapLayerCoreService.getChangeDetectionTileUrl(beforeYear, afterYear); } + + public TileUrlDto getChangeDetectionTileOneYearUrl(Integer year) { + return mapLayerCoreService.getChangeDetectionTileOneYearUrl(year); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapLayerCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapLayerCoreService.java index d8d8f49b..e5053f3b 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapLayerCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapLayerCoreService.java @@ -8,6 +8,7 @@ import com.kamco.cd.kamcoback.common.utils.UserUtil; import com.kamco.cd.kamcoback.layer.dto.LayerDto; import com.kamco.cd.kamcoback.layer.dto.LayerDto.LayerMapDto; import com.kamco.cd.kamcoback.layer.dto.LayerDto.OrderReq; +import com.kamco.cd.kamcoback.layer.dto.LayerDto.TileUrlDto; import com.kamco.cd.kamcoback.layer.dto.WmsDto.WmsAddDto; import com.kamco.cd.kamcoback.layer.dto.WmtsDto.WmtsAddDto; import com.kamco.cd.kamcoback.postgres.entity.MapLayerEntity; @@ -301,4 +302,8 @@ public class MapLayerCoreService { public LayerDto.YearTileDto getChangeDetectionTileUrl(Integer beforeYear, Integer afterYear) { return mapLayerRepository.getChangeDetectionTileUrl(beforeYear, afterYear); } + + public TileUrlDto getChangeDetectionTileOneYearUrl(Integer year) { + return mapLayerRepository.getChangeDetectionTileOneYearUrl(year); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryCustom.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryCustom.java index 39ca2195..2a0e6087 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryCustom.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryCustom.java @@ -2,6 +2,7 @@ package com.kamco.cd.kamcoback.postgres.repository.layer; import com.kamco.cd.kamcoback.layer.dto.LayerDto; import com.kamco.cd.kamcoback.layer.dto.LayerDto.LayerMapDto; +import com.kamco.cd.kamcoback.layer.dto.LayerDto.TileUrlDto; import com.kamco.cd.kamcoback.postgres.entity.MapLayerEntity; import java.util.Collection; import java.util.List; @@ -21,4 +22,6 @@ public interface MapLayerRepositoryCustom { List findLayerMapList(String type); LayerDto.YearTileDto getChangeDetectionTileUrl(Integer beforeYear, Integer afterYear); + + TileUrlDto getChangeDetectionTileOneYearUrl(Integer year); } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryImpl.java index 0ff76945..98145e04 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/layer/MapLayerRepositoryImpl.java @@ -5,6 +5,7 @@ import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetMngTileEntity.mapS import com.kamco.cd.kamcoback.layer.dto.LayerDto; import com.kamco.cd.kamcoback.layer.dto.LayerDto.LayerMapDto; +import com.kamco.cd.kamcoback.layer.dto.LayerDto.TileUrlDto; import com.kamco.cd.kamcoback.postgres.entity.MapLayerEntity; import com.querydsl.core.BooleanBuilder; import com.querydsl.core.types.Projections; @@ -172,6 +173,32 @@ public class MapLayerRepositoryImpl implements MapLayerRepositoryCustom { return new LayerDto.YearTileDto(before, after); } + @Override + public TileUrlDto getChangeDetectionTileOneYearUrl(Integer year) { + return queryFactory + .select( + Projections.constructor( + LayerDto.TileUrlDto.class, + mapSheetMngTileEntity.mngYyyy, + mapSheetMngTileEntity.tag, + mapSheetMngTileEntity.url, + mapSheetMngTileEntity.minLon, + mapSheetMngTileEntity.minLat, + mapSheetMngTileEntity.maxLon, + mapSheetMngTileEntity.maxLat, + mapSheetMngTileEntity.minZoom, + mapSheetMngTileEntity.maxZoom, + Expressions.stringTemplate( + "ST_AsGeoJSON(ST_MakeEnvelope({0}, {1}, {2}, {3}, 4326))", + mapSheetMngTileEntity.minLon, + mapSheetMngTileEntity.minLat, + mapSheetMngTileEntity.maxLon, + mapSheetMngTileEntity.maxLat))) + .from(mapSheetMngTileEntity) + .where(mapSheetMngTileEntity.mngYyyy.eq(year)) + .fetchOne(); + } + private BooleanExpression layerTypeCondition(String type) { return type.equals("change-detection") ? mapLayerEntity.isChangeMap.isTrue() From 2865b075a26f81af13e55493e1f54bca3865a074 Mon Sep 17 00:00:00 2001 From: teddy Date: Fri, 30 Jan 2026 11:54:11 +0900 Subject: [PATCH 16/41] =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=96=B4=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kamcoback/layer/LayerApiController.java | 35 ++++++++++++++++++- .../cd/kamcoback/layer/dto/LayerDto.java | 21 ++++++++++- .../kamcoback/layer/service/LayerService.java | 12 +++++++ .../postgres/core/MapLayerCoreService.java | 22 ++++++++++++ 4 files changed, 88 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/layer/LayerApiController.java b/src/main/java/com/kamco/cd/kamcoback/layer/LayerApiController.java index d7bc1313..5e06afd7 100644 --- a/src/main/java/com/kamco/cd/kamcoback/layer/LayerApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/layer/LayerApiController.java @@ -2,6 +2,7 @@ package com.kamco.cd.kamcoback.layer; import com.kamco.cd.kamcoback.config.api.ApiResponseDto; import com.kamco.cd.kamcoback.layer.dto.LayerDto; +import com.kamco.cd.kamcoback.layer.dto.LayerDto.IsMapYn; import com.kamco.cd.kamcoback.layer.dto.LayerDto.LayerMapDto; import com.kamco.cd.kamcoback.layer.dto.LayerDto.OrderReq; import com.kamco.cd.kamcoback.layer.dto.LayerDto.SearchReq; @@ -78,10 +79,24 @@ public class LayerApiController { }) @PostMapping("/save/{layerType}") public ApiResponseDto save( - @PathVariable String layerType, @RequestBody LayerDto.AddReq dto) { + @Schema(description = "TILE,GEOJSON,WMS,WMTS", example = "GEOJSON") @PathVariable + String layerType, + @RequestBody LayerDto.AddReq dto) { return ApiResponseDto.ok(layerService.saveLayers(layerType, dto)); } + @Operation(summary = "순서 변경", description = "순서 변경 api") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "201", + description = "등록 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = Void.class))), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) @PutMapping("/order") public ApiResponseDto updateOrder(@RequestBody List dto) { layerService.orderUpdate(dto); @@ -154,6 +169,24 @@ public class LayerApiController { return ApiResponseDto.ok(null); } + @Operation(summary = "맵 노출여부 수정", description = "맵 노출여부 수정 api") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "201", + description = "수정 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = Void.class))), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) + @PutMapping("/update-map/{uuid}") + public ApiResponseDto updateIsMap(@PathVariable UUID uuid, @RequestBody IsMapYn isMapYn) { + layerService.updateIsMap(uuid, isMapYn); + return ApiResponseDto.ok(null); + } + @Operation(summary = "wmts tile 조회", description = "wmts tile 조회 api") @ApiResponses( value = { diff --git a/src/main/java/com/kamco/cd/kamcoback/layer/dto/LayerDto.java b/src/main/java/com/kamco/cd/kamcoback/layer/dto/LayerDto.java index a31883a4..98d18422 100644 --- a/src/main/java/com/kamco/cd/kamcoback/layer/dto/LayerDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/layer/dto/LayerDto.java @@ -1,6 +1,7 @@ package com.kamco.cd.kamcoback.layer.dto; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -110,7 +111,7 @@ public class LayerDto { @Schema(name = "LayerAddReq") public static class AddReq { - @Schema(description = "title") + @Schema(description = "title WMS, WMTS 선택한 tile") private String title; @Schema(description = "설명") @@ -302,6 +303,11 @@ public class LayerDto { this.rawJson = rawJson; this.bbox = geoJson; } + + @JsonProperty("workspace") + public String getWorkSpace() { + return "cd"; + } } @Schema(name = "TileUrlDto", description = "Tile Url 정보") @@ -389,4 +395,17 @@ public class LayerDto { private TileUrlDto before; private TileUrlDto after; } + + @Schema(name = "맵 노출 여부", description = "맵 노출 여부") + @Getter + @Setter + @NoArgsConstructor + @AllArgsConstructor + public static class IsMapYn { + @Schema(description = "CHANGE_MAP(변화지도), LABELING_MAP(라벨링지도)", example = "CHANGE_MAP") + private String mapType; + + @Schema(description = "노출여부 true, false", example = "true") + private Boolean isMapYn; + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/layer/service/LayerService.java b/src/main/java/com/kamco/cd/kamcoback/layer/service/LayerService.java index b78dfa8b..055a2877 100644 --- a/src/main/java/com/kamco/cd/kamcoback/layer/service/LayerService.java +++ b/src/main/java/com/kamco/cd/kamcoback/layer/service/LayerService.java @@ -4,6 +4,7 @@ import com.kamco.cd.kamcoback.common.enums.LayerType; import com.kamco.cd.kamcoback.common.exception.CustomApiException; import com.kamco.cd.kamcoback.layer.dto.LayerDto; import com.kamco.cd.kamcoback.layer.dto.LayerDto.Basic; +import com.kamco.cd.kamcoback.layer.dto.LayerDto.IsMapYn; import com.kamco.cd.kamcoback.layer.dto.LayerDto.LayerMapDto; import com.kamco.cd.kamcoback.layer.dto.LayerDto.OrderReq; import com.kamco.cd.kamcoback.layer.dto.LayerDto.TileUrlDto; @@ -126,6 +127,17 @@ public class LayerService { mapLayerCoreService.update(uuid, dto); } + /** + * 맵 노출 여부 수정 + * + * @param uuid + * @param isMapYn + */ + @Transactional + public void updateIsMap(UUID uuid, IsMapYn isMapYn) { + mapLayerCoreService.updateIsMap(uuid, isMapYn); + } + /** * wmts tile 조회 * diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapLayerCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapLayerCoreService.java index e5053f3b..09af8b01 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapLayerCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapLayerCoreService.java @@ -6,6 +6,7 @@ import com.kamco.cd.kamcoback.common.enums.LayerType; import com.kamco.cd.kamcoback.common.exception.CustomApiException; import com.kamco.cd.kamcoback.common.utils.UserUtil; import com.kamco.cd.kamcoback.layer.dto.LayerDto; +import com.kamco.cd.kamcoback.layer.dto.LayerDto.IsMapYn; import com.kamco.cd.kamcoback.layer.dto.LayerDto.LayerMapDto; import com.kamco.cd.kamcoback.layer.dto.LayerDto.OrderReq; import com.kamco.cd.kamcoback.layer.dto.LayerDto.TileUrlDto; @@ -134,6 +135,27 @@ public class MapLayerCoreService { entity.setUpdatedDttm(ZonedDateTime.now()); } + /** + * 맵 노출 여부 + * + * @param uuid + * @param isMapYn + */ + public void updateIsMap(UUID uuid, IsMapYn isMapYn) { + MapLayerEntity entity = + mapLayerRepository + .findDetailByUuid(uuid) + .orElseThrow(() -> new CustomApiException("NOT_FOUND_DATA", HttpStatus.NOT_FOUND)); + + if ("CHANGE_MAP".equals(isMapYn.getMapType())) { + entity.setIsChangeMap(isMapYn.getIsMapYn()); + } else if ("LABELING_MAP".equals(isMapYn.getMapType())) { + entity.setIsLabelingMap(isMapYn.getIsMapYn()); + } else { + throw new CustomApiException("BAD_REQUEST", HttpStatus.BAD_REQUEST); + } + } + /** * 순서 수정 * From f3453ab499f59b017e47103872d2b695e1c4b45b Mon Sep 17 00:00:00 2001 From: teddy Date: Fri, 30 Jan 2026 12:04:11 +0900 Subject: [PATCH 17/41] =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=96=B4=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kamco/cd/kamcoback/layer/dto/LayerDto.java | 5 +++++ .../postgres/core/MapLayerCoreService.java | 15 ++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/layer/dto/LayerDto.java b/src/main/java/com/kamco/cd/kamcoback/layer/dto/LayerDto.java index 98d18422..4ad12d51 100644 --- a/src/main/java/com/kamco/cd/kamcoback/layer/dto/LayerDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/layer/dto/LayerDto.java @@ -408,4 +408,9 @@ public class LayerDto { @Schema(description = "노출여부 true, false", example = "true") private Boolean isMapYn; } + + public enum MapType { + CHANGE_MAP, + LABELING_MAP + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapLayerCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapLayerCoreService.java index 09af8b01..11368382 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapLayerCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapLayerCoreService.java @@ -147,13 +147,18 @@ public class MapLayerCoreService { .findDetailByUuid(uuid) .orElseThrow(() -> new CustomApiException("NOT_FOUND_DATA", HttpStatus.NOT_FOUND)); - if ("CHANGE_MAP".equals(isMapYn.getMapType())) { - entity.setIsChangeMap(isMapYn.getIsMapYn()); - } else if ("LABELING_MAP".equals(isMapYn.getMapType())) { - entity.setIsLabelingMap(isMapYn.getIsMapYn()); - } else { + LayerDto.MapType mapType; + + try { + mapType = LayerDto.MapType.valueOf(isMapYn.getMapType()); + } catch (IllegalArgumentException e) { throw new CustomApiException("BAD_REQUEST", HttpStatus.BAD_REQUEST); } + + switch (mapType) { + case CHANGE_MAP -> entity.setIsChangeMap(isMapYn.getIsMapYn()); + case LABELING_MAP -> entity.setIsLabelingMap(isMapYn.getIsMapYn()); + } } /** From df8bac950b6056268c94ccbac2c3ff49cc153ab2 Mon Sep 17 00:00:00 2001 From: "gayoun.park" Date: Fri, 30 Jan 2026 13:30:13 +0900 Subject: [PATCH 18/41] =?UTF-8?q?=EA=B5=AD=EC=9C=A0=EC=9D=B8=20API=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gukyuin/GukYuinApiController.java | 16 +- .../gukyuin/dto/ChngDetectMastDto.java | 56 +++++- .../cd/kamcoback/gukyuin/dto/GukYuinDto.java | 33 +++- .../kamcoback/gukyuin/dto/GukYuinStatus.java | 1 + .../gukyuin/service/GukYuinApiService.java | 167 +++++++++++++++++- .../postgres/core/GukYuinCoreService.java | 13 ++ .../postgres/core/GukYuinJobCoreService.java | 14 +- .../postgres/entity/MapSheetLearnEntity.java | 3 + .../gukyuin/GukYuinRepositoryCustom.java | 16 +- .../gukyuin/GukYuinRepositoryImpl.java | 101 ++++++++++- .../service/GukYuinApiJobService.java | 83 +++++++-- 11 files changed, 453 insertions(+), 50 deletions(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/gukyuin/GukYuinApiController.java b/src/main/java/com/kamco/cd/kamcoback/gukyuin/GukYuinApiController.java index 2217b939..a7ab2e43 100644 --- a/src/main/java/com/kamco/cd/kamcoback/gukyuin/GukYuinApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/gukyuin/GukYuinApiController.java @@ -1,6 +1,7 @@ package com.kamco.cd.kamcoback.gukyuin; import com.kamco.cd.kamcoback.config.api.ApiResponseDto; +import com.kamco.cd.kamcoback.config.api.ApiResponseDto.ResponseObj; import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectContDto; import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto; import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.ChnDetectMastReqDto; @@ -51,7 +52,7 @@ public class GukYuinApiController { @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) }) @PostMapping("/chn/mast/regist") - public ApiResponseDto regist( + public ApiResponseDto regist( @RequestBody @Valid ChngDetectMastDto.ChnDetectMastReqDto chnDetectMastReq) { return ApiResponseDto.ok(gukYuinApiService.regist(chnDetectMastReq)); } @@ -133,9 +134,9 @@ public class GukYuinApiController { @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) }) - public ApiResponseDto selectChangeDetectionList( + public ApiResponseDto selectChangeDetectionDetail( @PathVariable String chnDtctMstId) { - return ApiResponseDto.ok(gukYuinApiService.list(chnDtctMstId)); + return ApiResponseDto.ok(gukYuinApiService.detail(chnDtctMstId)); } @Operation(summary = "국유in연동 가능여부 확인", description = "국유in연동 가능여부 확인") @@ -239,4 +240,13 @@ public class GukYuinApiController { @PathVariable String chnDtctObjtId, @PathVariable String lblYn) { return ApiResponseDto.ok(gukYuinApiService.updateChnDtctObjtLabelingYn(chnDtctObjtId, lblYn)); } + + @Operation(summary = "국유in연동 등록", description = "국유in연동 등록") + @GetMapping("/mast/reg/{uuid}") + public ApiResponseDto connectChnMastRegist( + @Parameter(description = "uuid", example = "7a593d0e-76a8-4b50-8978-9af1fbe871af") + @PathVariable + UUID uuid) { + return ApiResponseDto.ok(gukYuinApiService.connectChnMastRegist(uuid)); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/ChngDetectMastDto.java b/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/ChngDetectMastDto.java index 35d1febe..772448c7 100644 --- a/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/ChngDetectMastDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/ChngDetectMastDto.java @@ -66,13 +66,30 @@ public class ChngDetectMastDto { @AllArgsConstructor public static class ChnDetectMastReqDto { - private String cprsYr; // 비교년도 2023 - private String crtrYr; // 기준년도 2024 - private String chnDtctSno; // 차수 (1 | 2 | ...) - private String chnDtctId; // 탐지아이디. UUID를 기반으로 '-'를 제거하고 대문자/숫자로 구성 - private String pathNm; // 탐지결과 절대경로명 /kamco_nas/export/{chnDtctId} - private String reqEpno; // 사원번호 - private String reqIp; // 사원아이피 + @Schema(description = "비교년도", example = "2023") + private String cprsYr; + + @Schema(description = "기준년도", example = "2024") + private String crtrYr; + + @Schema(description = "차수", example = "1") + private String chnDtctSno; + + @Schema( + description = "탐지아이디, UUID를 기반으로 '-'를 제거하고 대문자/숫자로 구성", + example = "D5F192EC76D34F6592035BE63A84F591") + private String chnDtctId; + + @Schema( + description = "탐지결과 절대경로명 /kamco_nas/export/{chnDtctId}", + example = "/kamco-nfs/dataset/export/D5F192EC76D34F6592035BE63A84F591") + private String pathNm; + + @Schema(description = "사원번호", example = "123456") + private String reqEpno; + + @Schema(description = "사원아이피", example = "127.0.0.1") + private String reqIp; } @Getter @@ -158,4 +175,29 @@ public class ChngDetectMastDto { private List result; private Boolean success; } + + @Schema(name = "RegistResDto", description = "reg 등록 후 리턴 형태") + @Getter + @Setter + @NoArgsConstructor + @AllArgsConstructor + public static class RegistResDto { + + private Integer code; + private String message; + private Basic result; + private Boolean success; + } + + @Schema(name = "LearnKeyDto", description = "learn 엔티티 key 정보") + @Getter + @Setter + @NoArgsConstructor + @AllArgsConstructor + public static class LearnKeyDto { + + private Long id; + private String uid; + private String chnDtctMstId; + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/GukYuinDto.java b/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/GukYuinDto.java index d236bfb4..652a00fc 100644 --- a/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/GukYuinDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/GukYuinDto.java @@ -1,21 +1,13 @@ package com.kamco.cd.kamcoback.gukyuin.dto; import com.kamco.cd.kamcoback.common.utils.enums.EnumType; +import java.util.UUID; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; public class GukYuinDto { - @Getter - @Setter - public static class GukYuinLinkableRes { - - private boolean linkable; - // private GukYuinLinkFailCode code; - private String message; - } - /** 실패 코드 enum */ @Getter @AllArgsConstructor @@ -39,10 +31,33 @@ public class GukYuinDto { } } + @Getter + @Setter + public static class GukYuinLinkableRes { + + private boolean linkable; + // private GukYuinLinkFailCode code; + private String message; + } + // Repository가 반환할 Fact(조회 결과) public record GukYuinLinkFacts( boolean existsLearn, boolean isPartScope, boolean hasRunningInference, boolean hasOtherUnfinishedGukYuin) {} + + @Getter + @Setter + @AllArgsConstructor + public static class LearnInfo { + + private Long id; + private UUID uuid; + private Integer compareYyyy; + private Integer targetYyyy; + private Integer stage; + private String uid; + private String applyStatus; + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/GukYuinStatus.java b/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/GukYuinStatus.java index 174e9714..e6472c04 100644 --- a/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/GukYuinStatus.java +++ b/src/main/java/com/kamco/cd/kamcoback/gukyuin/dto/GukYuinStatus.java @@ -11,6 +11,7 @@ public enum GukYuinStatus implements EnumType { IN_PROGRESS("진행중"), GUK_COMPLETED("국유인 매핑 완료"), PNU_COMPLETED("PNU 싱크 완료"), + PNU_FAILED("PNU 싱크 중 에러"), CANCELED("취소"); private final String desc; diff --git a/src/main/java/com/kamco/cd/kamcoback/gukyuin/service/GukYuinApiService.java b/src/main/java/com/kamco/cd/kamcoback/gukyuin/service/GukYuinApiService.java index 82fec220..84b2d172 100644 --- a/src/main/java/com/kamco/cd/kamcoback/gukyuin/service/GukYuinApiService.java +++ b/src/main/java/com/kamco/cd/kamcoback/gukyuin/service/GukYuinApiService.java @@ -1,6 +1,10 @@ package com.kamco.cd.kamcoback.gukyuin.service; import com.kamco.cd.kamcoback.common.utils.NetUtils; +import com.kamco.cd.kamcoback.common.utils.UserUtil; +import com.kamco.cd.kamcoback.config.api.ApiLogFunction; +import com.kamco.cd.kamcoback.config.api.ApiResponseDto.ApiResponseCode; +import com.kamco.cd.kamcoback.config.api.ApiResponseDto.ResponseObj; import com.kamco.cd.kamcoback.config.resttemplate.ExternalHttpClient; import com.kamco.cd.kamcoback.config.resttemplate.ExternalHttpClient.ExternalCallResult; import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectContDto; @@ -8,22 +12,31 @@ import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectContDto.ContBasic; import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectContDto.ResultContDto; import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectContDto.ResultPnuDto; import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto; +import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.ChnDetectMastReqDto; import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.ResReturn; import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.ResultDto; import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.GukYuinLinkFacts; import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.GukYuinLinkFailCode; import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.GukYuinLinkableRes; +import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.LearnInfo; +import com.kamco.cd.kamcoback.log.dto.EventStatus; +import com.kamco.cd.kamcoback.log.dto.EventType; import com.kamco.cd.kamcoback.postgres.core.GukYuinCoreService; +import com.kamco.cd.kamcoback.postgres.entity.AuditLogEntity; +import com.kamco.cd.kamcoback.postgres.repository.log.AuditLogRepository; import java.util.List; import java.util.UUID; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpMethod; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; +@Slf4j @Service -@Transactional(readOnly = true) +@Transactional @RequiredArgsConstructor public class GukYuinApiService { @@ -31,6 +44,9 @@ public class GukYuinApiService { private final ExternalHttpClient externalHttpClient; private final NetUtils netUtils = new NetUtils(); + private final UserUtil userUtil; + private final AuditLogRepository auditLogRepository; + @Value("${spring.profiles.active:local}") private String profile; @@ -41,25 +57,42 @@ public class GukYuinApiService { private String gukyuinCdiUrl; @Transactional - public ChngDetectMastDto.Basic regist(ChngDetectMastDto.ChnDetectMastReqDto chnDetectMastReq) { + public ChngDetectMastDto.RegistResDto regist( + ChngDetectMastDto.ChnDetectMastReqDto chnDetectMastReq) { String url = gukyuinCdiUrl + "/chn/mast/regist"; String myip = netUtils.getLocalIP(); chnDetectMastReq.setReqIp(myip); - chnDetectMastReq.setReqEpno("1234567"); // TODO + chnDetectMastReq.setReqEpno(userUtil.getEmployeeNo()); - ExternalCallResult result = + ExternalCallResult result = externalHttpClient.call( url, HttpMethod.POST, chnDetectMastReq, netUtils.jsonHeaders(), - ChngDetectMastDto.Basic.class); + ChngDetectMastDto.RegistResDto.class); - ChngDetectMastDto.Basic resultBody = result.body(); - gukyuinCoreService.updateGukYuinMastRegResult(resultBody); + ChngDetectMastDto.RegistResDto resultBody = result.body(); + Boolean success = null; + if (resultBody != null) { + ChngDetectMastDto.Basic registRes = resultBody.getResult(); + // 추론 회차에 applyStatus, applyStatusDttm 업데이트 + gukyuinCoreService.updateGukYuinMastRegResult(registRes); + // anal_inference 에도 국유인 반영여부, applyDttm 업데이트 + gukyuinCoreService.updateAnalInferenceApplyDttm(registRes); + success = resultBody.getSuccess(); + } + + this.insertGukyuinAuditLog( + EventType.ADDED.getId(), + myip, + userUtil.getId(), + url.replace(gukyuinUrl, ""), + chnDetectMastReq, + success); return resultBody; } @@ -69,7 +102,7 @@ public class GukYuinApiService { String myip = netUtils.getLocalIP(); chnDetectMastReq.setReqIp(myip); - chnDetectMastReq.setReqEpno("1234567"); // TODO + chnDetectMastReq.setReqEpno(userUtil.getEmployeeNo()); ExternalCallResult result = externalHttpClient.call( @@ -82,11 +115,18 @@ public class GukYuinApiService { ChngDetectMastDto.Basic resultBody = result.body(); gukyuinCoreService.updateGukYuinMastRegRemove(resultBody); + this.insertGukyuinAuditLog( + EventType.REMOVE.getId(), + myip, + userUtil.getId(), + url.replace(gukyuinUrl, ""), + chnDetectMastReq, + true); // TODO : successFail 여부 return new ResReturn("success", "탐지결과 삭제 되었습니다."); } // 등록목록 1개 확인 - public ChngDetectMastDto.ResultDto list(String chnDtctMstId) { + public ChngDetectMastDto.ResultDto detail(String chnDtctMstId) { String url = gukyuinCdiUrl + "/chn/mast/list/" + chnDtctMstId; @@ -94,6 +134,13 @@ public class GukYuinApiService { externalHttpClient.call( url, HttpMethod.GET, null, netUtils.jsonHeaders(), ChngDetectMastDto.ResultDto.class); + this.insertGukyuinAuditLog( + EventType.DETAIL.getId(), + netUtils.getLocalIP(), + userUtil.getId(), + url.replace(gukyuinUrl, ""), + null, + result.body().getSuccess()); return result.body(); } @@ -108,6 +155,13 @@ public class GukYuinApiService { externalHttpClient.call( url, HttpMethod.GET, null, netUtils.jsonHeaders(), ChngDetectMastDto.ResultDto.class); + this.insertGukyuinAuditLog( + EventType.LIST.getId(), + netUtils.getLocalIP(), + userUtil.getId(), + url.replace(gukyuinUrl, ""), + null, + result.body().getSuccess()); return result.body(); } @@ -188,6 +242,14 @@ public class GukYuinApiService { } } + this.insertGukyuinAuditLog( + EventType.LIST.getId(), + netUtils.getLocalIP(), + userUtil.getId(), + url.replace(gukyuinUrl, ""), + null, + result.body().getSuccess()); + return result.body(); } @@ -202,6 +264,14 @@ public class GukYuinApiService { netUtils.jsonHeaders(), ChngDetectContDto.ResultPnuDto.class); + this.insertGukyuinAuditLog( + EventType.DETAIL.getId(), + netUtils.getLocalIP(), + userUtil.getId(), + url.replace(gukyuinUrl, ""), + null, + result.body().getSuccess()); + return result.body(); } @@ -218,6 +288,14 @@ public class GukYuinApiService { ChngDetectContDto.ResultPnuDto dto = result.body(); + this.insertGukyuinAuditLog( + EventType.MODIFIED.getId(), + netUtils.getLocalIP(), + userUtil.getId(), + url.replace(gukyuinUrl, ""), + null, + result.body().getSuccess()); + return new ResReturn(dto.getCode() > 200000 ? "fail" : "success", dto.getMessage()); } @@ -232,6 +310,13 @@ public class GukYuinApiService { netUtils.jsonHeaders(), ChngDetectContDto.ResultContDto.class); + this.insertGukyuinAuditLog( + EventType.LIST.getId(), + netUtils.getLocalIP(), + userUtil.getId(), + url.replace(gukyuinUrl, ""), + null, + result.body().getSuccess()); return result.body(); } @@ -242,6 +327,70 @@ public class GukYuinApiService { externalHttpClient.call( url, HttpMethod.GET, null, netUtils.jsonHeaders(), ChngDetectMastDto.ResultDto.class); + this.insertGukyuinAuditLog( + EventType.DETAIL.getId(), + netUtils.getLocalIP(), + userUtil.getId(), + url.replace(gukyuinUrl, ""), + null, + result.body().getSuccess()); + return result.body(); } + + @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = false) + public void insertGukyuinAuditLog( + String actionType, + String myIp, + Long userUid, + String requestUri, + Object requestBody, + boolean successFail) { + try { + AuditLogEntity log = + new AuditLogEntity( + userUid, + EventType.fromName(actionType), + successFail ? EventStatus.SUCCESS : EventStatus.FAILED, + "GUKYUIN", // 메뉴도 국유인으로 하나 따기 + myIp, + requestUri, + requestBody == null ? null : ApiLogFunction.cutRequestBody(requestBody.toString()), + null, + null, + null); + auditLogRepository.save(log); + + } catch (Exception e) { + log.error(e.getMessage()); + throw e; + } + } + + public ResponseObj connectChnMastRegist(UUID uuid) { + // uuid로 추론 회차 조회 + LearnInfo info = gukyuinCoreService.findMapSheetLearnInfo(uuid); + // if (info.getApplyStatus() != null && + // !info.getApplyStatus().equals(GukYuinStatus.PENDING.getId())) + // { + // return new ResponseObj(ApiResponseCode.DUPLICATE_DATA, "이미 국유인 연동을 한 추론 회차입니다."); + // } + + // 비교년도,기준년도로 전송한 데이터 있는지 확인 후 회차 번호 생성 + Integer maxStage = + gukyuinCoreService.findMapSheetLearnYearStage(info.getCompareYyyy(), info.getTargetYyyy()); + + // reqDto 셋팅 + ChnDetectMastReqDto reqDto = new ChnDetectMastReqDto(); + reqDto.setCprsYr(String.valueOf(info.getCompareYyyy())); + reqDto.setCrtrYr(String.valueOf(info.getTargetYyyy())); + reqDto.setChnDtctSno(String.valueOf(maxStage + 1)); + reqDto.setChnDtctId(info.getUid()); + reqDto.setPathNm("/kamco-nfs/dataset/export/" + info.getUid()); + + // 국유인 /chn/mast/regist 전송 + this.regist(reqDto); + + return new ResponseObj(ApiResponseCode.OK, ""); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/GukYuinCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/GukYuinCoreService.java index 49dab3ac..4a924f01 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/core/GukYuinCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/GukYuinCoreService.java @@ -2,6 +2,7 @@ package com.kamco.cd.kamcoback.postgres.core; import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.Basic; import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.GukYuinLinkFacts; +import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.LearnInfo; import com.kamco.cd.kamcoback.postgres.repository.Inference.MapSheetLearnRepository; import com.kamco.cd.kamcoback.postgres.repository.gukyuin.GukYuinRepository; import java.util.UUID; @@ -44,4 +45,16 @@ public class GukYuinCoreService { public void insertGeoUidPnuData(Long geoUid, String[] pnuList) { gukYuinRepository.insertGeoUidPnuData(geoUid, pnuList); } + + 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); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/GukYuinJobCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/GukYuinJobCoreService.java index d0a32e25..8c234dab 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/core/GukYuinJobCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/GukYuinJobCoreService.java @@ -1,5 +1,7 @@ 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; @@ -13,11 +15,15 @@ public class GukYuinJobCoreService { this.gukYuinRepository = gukYuinRepository; } - public List findGukyuinApplyIngUidList() { - return gukYuinRepository.findGukyuinApplyIngUidList(); + public void updateGukYuinApplyStateComplete(Long id, GukYuinStatus status) { + gukYuinRepository.updateGukYuinApplyStateComplete(id, status); } - public void updateGukYuinApplyStateComplete(String uid) { - gukYuinRepository.updateGukYuinApplyStateComplete(uid); + public List findGukyuinApplyStatusUidList(GukYuinStatus gukYuinStatus) { + return gukYuinRepository.findGukyuinApplyStatusUidList(gukYuinStatus); + } + + public void upsertMapSheetDataAnalGeomPnu(String chnDtctObjtId, String[] pnuList) { + gukYuinRepository.upsertMapSheetDataAnalGeomPnu(chnDtctObjtId, pnuList); } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetLearnEntity.java b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetLearnEntity.java index fa6ab43f..a161c05d 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetLearnEntity.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetLearnEntity.java @@ -199,6 +199,9 @@ public class MapSheetLearnEntity { @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, diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/gukyuin/GukYuinRepositoryCustom.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/gukyuin/GukYuinRepositoryCustom.java index ae7763ef..ced7c08c 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/gukyuin/GukYuinRepositoryCustom.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/gukyuin/GukYuinRepositoryCustom.java @@ -1,7 +1,11 @@ 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.LearnKeyDto; +import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.LearnInfo; +import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinStatus; import java.util.List; +import java.util.UUID; public interface GukYuinRepositoryCustom { @@ -15,7 +19,15 @@ public interface GukYuinRepositoryCustom { void insertGeoUidPnuData(Long geoUid, String[] pnuList); - List findGukyuinApplyIngUidList(); + void updateGukYuinApplyStateComplete(Long id, GukYuinStatus status); - void updateGukYuinApplyStateComplete(String uid); + List findGukyuinApplyStatusUidList(GukYuinStatus gukYuinStatus); + + void upsertMapSheetDataAnalGeomPnu(String uid, String[] pnuList); + + LearnInfo findMapSheetLearnInfo(UUID uuid); + + Integer findMapSheetLearnYearStage(Integer compareYyyy, Integer targetYyyy); + + void updateAnalInferenceApplyDttm(Basic registRes); } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/gukyuin/GukYuinRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/gukyuin/GukYuinRepositoryImpl.java index cf7ba85f..281b5f70 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/gukyuin/GukYuinRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/gukyuin/GukYuinRepositoryImpl.java @@ -1,17 +1,24 @@ package com.kamco.cd.kamcoback.postgres.repository.gukyuin; 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.LearnKeyDto; +import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.LearnInfo; import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinStatus; +import com.querydsl.core.types.Projections; +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.ZonedDateTime; import java.util.List; +import java.util.UUID; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; @@ -37,6 +44,7 @@ public class GukYuinRepositoryImpl implements GukYuinRepositoryCustom { .set(mapSheetLearnEntity.stage, stage) .set(mapSheetLearnEntity.applyStatus, status.getId()) .set(mapSheetLearnEntity.applyStatusDttm, ZonedDateTime.now()) + .set(mapSheetLearnEntity.chnDtctMstId, resultBody.getChnDtctMstId()) .where(mapSheetLearnEntity.uid.eq(resultBody.getChnDtctId())) .execute(); } @@ -81,22 +89,103 @@ public class GukYuinRepositoryImpl implements GukYuinRepositoryCustom { } @Override - public List findGukyuinApplyIngUidList() { + public List findGukyuinApplyStatusUidList(GukYuinStatus status) { return queryFactory - .select(mapSheetLearnEntity.uid) + .select( + Projections.constructor( + LearnKeyDto.class, + mapSheetLearnEntity.id, + mapSheetLearnEntity.uid, + mapSheetLearnEntity.chnDtctMstId)) .from(mapSheetLearnEntity) - .where(mapSheetLearnEntity.applyStatus.eq(GukYuinStatus.IN_PROGRESS.getId())) + .where(mapSheetLearnEntity.applyStatus.eq(status.getId())) .fetch(); } + @Override + public void 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(); + + for (int i = 0; i < length; i++) { + queryFactory + .insert(pnuEntity) + .columns(pnuEntity.geo.geoUid, pnuEntity.pnu, pnuEntity.createdDttm) + .values(geoUid, pnuList[i], ZonedDateTime.now()) + .execute(); + } + } + + @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)) + .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()) + .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 @Transactional - public void updateGukYuinApplyStateComplete(String uid) { + public void updateGukYuinApplyStateComplete(Long id, GukYuinStatus status) { queryFactory .update(mapSheetLearnEntity) - .set(mapSheetLearnEntity.applyStatus, GukYuinStatus.PNU_COMPLETED.getId()) + .set(mapSheetLearnEntity.applyStatus, status.getId()) .set(mapSheetLearnEntity.applyStatusDttm, ZonedDateTime.now()) - .where(mapSheetLearnEntity.uid.eq(uid)) + .where(mapSheetLearnEntity.id.eq(id)) .execute(); } } diff --git a/src/main/java/com/kamco/cd/kamcoback/scheduler/service/GukYuinApiJobService.java b/src/main/java/com/kamco/cd/kamcoback/scheduler/service/GukYuinApiJobService.java index 2d7533a8..c537ce90 100644 --- a/src/main/java/com/kamco/cd/kamcoback/scheduler/service/GukYuinApiJobService.java +++ b/src/main/java/com/kamco/cd/kamcoback/scheduler/service/GukYuinApiJobService.java @@ -1,7 +1,11 @@ package com.kamco.cd.kamcoback.scheduler.service; +import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectContDto; +import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectContDto.ResultContDto; import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto; +import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.LearnKeyDto; import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.ResultDto; +import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinStatus; import com.kamco.cd.kamcoback.gukyuin.service.GukYuinApiService; import com.kamco.cd.kamcoback.postgres.core.GukYuinJobCoreService; import java.util.List; @@ -31,23 +35,24 @@ public class GukYuinApiJobService { return "local".equalsIgnoreCase(profile); } - @Scheduled(cron = "0 0/10 * * * *") + @Scheduled(cron = "0 * * * * *") // 0 0/10 * * * * public void findGukYuinMastCompleteYn() { - if (isLocalProfile()) { - return; - } + // if (isLocalProfile()) { + // return; + // } - List list = gukYuinJobCoreService.findGukyuinApplyIngUidList(); + List list = + gukYuinJobCoreService.findGukyuinApplyStatusUidList(GukYuinStatus.IN_PROGRESS); if (list.isEmpty()) { return; } - for (String uid : list) { + for (LearnKeyDto dto : list) { try { - ResultDto result = gukYuinApiService.listChnDtctId(uid); + ResultDto result = gukYuinApiService.detail(dto.getChnDtctMstId()); if (result == null || result.getResult() == null || result.getResult().isEmpty()) { - log.warn("[GUKYUIN] empty result uid={}", uid); + log.warn("[GUKYUIN] empty result chnDtctMstId={}", dto.getChnDtctMstId()); continue; } @@ -56,10 +61,11 @@ public class GukYuinApiJobService { Integer progress = basic.getExcnPgrt() == null ? null : Integer.parseInt(basic.getExcnPgrt().trim()); if (progress != null && progress == 100) { - gukYuinJobCoreService.updateGukYuinApplyStateComplete(uid); + gukYuinJobCoreService.updateGukYuinApplyStateComplete( + dto.getId(), GukYuinStatus.GUK_COMPLETED); } } catch (Exception e) { - log.error("[GUKYUIN] failed uid={}", uid, e); + log.error("[GUKYUIN] failed uid={}", dto.getChnDtctMstId(), e); } } } @@ -69,5 +75,62 @@ public class GukYuinApiJobService { if (isLocalProfile()) { return; } + + List list = + gukYuinJobCoreService.findGukyuinApplyStatusUidList(GukYuinStatus.GUK_COMPLETED); + if (list.isEmpty()) { + return; + } + + for (LearnKeyDto dto : list) { + try { + processUid(dto.getChnDtctMstId(), dto.getUid()); + gukYuinJobCoreService.updateGukYuinApplyStateComplete( + dto.getId(), GukYuinStatus.PNU_COMPLETED); + } catch (Exception e) { + log.error("[GUKYUIN] failed uid={}", dto.getUid(), e); + gukYuinJobCoreService.updateGukYuinApplyStateComplete( + dto.getId(), GukYuinStatus.PNU_FAILED); + } + } + } + + private void processUid(String chnDtctMstId, String uid) { + ResultDto result = gukYuinApiService.detail(chnDtctMstId); + if (result == null || result.getResult() == null || result.getResult().isEmpty()) { + return; + } + + ChngDetectMastDto.Basic basic = result.getResult().get(0); + String chnDtctCnt = basic.getChnDtctCnt(); + if (chnDtctCnt == null || chnDtctCnt.isEmpty()) { + return; + } + + // page 계산 + int pageSize = 100; + int totalCount = Integer.parseInt(chnDtctCnt); + int totalPages = (totalCount + pageSize - 1) / pageSize; + + for (int page = 0; page < totalPages; page++) { + processPage(uid, page, pageSize); + } + } + + private void processPage(String uid, int page, int pageSize) { + ResultContDto cont = gukYuinApiService.findChnContList(uid, page, pageSize); + if (cont == null || cont.getResult().isEmpty()) { + return; // 외부 API 이상 방어 + } + + // pnuList 업데이트 + for (ChngDetectContDto.ContBasic contBasic : cont.getResult()) { + if (contBasic.getPnuList() == null) { + return; + } + + gukYuinJobCoreService.upsertMapSheetDataAnalGeomPnu( + contBasic.getChnDtctObjtId(), contBasic.getPnuList()); + } } } From 29556b6a05a054bcb7e8ddaed8d7340214fd2e30 Mon Sep 17 00:00:00 2001 From: "gayoun.park" Date: Fri, 30 Jan 2026 13:33:00 +0900 Subject: [PATCH 19/41] =?UTF-8?q?=EB=93=B1=EB=A1=9D=20post=EB=A1=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gukyuin/GukYuinApiController.java | 270 +++++++++--------- 1 file changed, 136 insertions(+), 134 deletions(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/gukyuin/GukYuinApiController.java b/src/main/java/com/kamco/cd/kamcoback/gukyuin/GukYuinApiController.java index a7ab2e43..00d81bb0 100644 --- a/src/main/java/com/kamco/cd/kamcoback/gukyuin/GukYuinApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/gukyuin/GukYuinApiController.java @@ -37,63 +37,65 @@ public class GukYuinApiController { private final GukYuinApiService gukYuinApiService; - /** 탐지결과 등록 */ + /** + * 탐지결과 등록 + */ @Operation(summary = "탐지결과 등록", description = "탐지결과 등록") @ApiResponses( - value = { - @ApiResponse( - responseCode = "201", - description = "등록 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = DetectMastReq.class))), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "201", + description = "등록 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = DetectMastReq.class))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) @PostMapping("/chn/mast/regist") public ApiResponseDto regist( - @RequestBody @Valid ChngDetectMastDto.ChnDetectMastReqDto chnDetectMastReq) { + @RequestBody @Valid ChngDetectMastDto.ChnDetectMastReqDto chnDetectMastReq) { return ApiResponseDto.ok(gukYuinApiService.regist(chnDetectMastReq)); } @Operation(summary = "탐지결과 삭제", description = "탐지결과 삭제") @ApiResponses( - value = { - @ApiResponse( - responseCode = "201", - description = "등록 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = ChnDetectMastReqDto.class))), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "201", + description = "등록 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = ChnDetectMastReqDto.class))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) @PostMapping("/chn/mast/remove") public ApiResponseDto remove( - @RequestBody @Valid ChngDetectMastDto.ChnDetectMastReqDto chnDetectMastReq) { + @RequestBody @Valid ChngDetectMastDto.ChnDetectMastReqDto chnDetectMastReq) { return ApiResponseDto.ok(gukYuinApiService.remove(chnDetectMastReq)); } @Operation(summary = "탐지결과 등록목록 조회(년도,차수 조회)", description = "탐지결과 등록목록 조회") @GetMapping("/chn/mast") @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "목록 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = Basic.class))), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "200", + description = "목록 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = Basic.class))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) public ApiResponseDto selectChangeDetectionList( - @RequestParam(required = false) String cprsYr, - @RequestParam(required = false) String crtrYr, - @RequestParam(required = false) String chnDtctSno) { + @RequestParam(required = false) String cprsYr, + @RequestParam(required = false) String crtrYr, + @RequestParam(required = false) String chnDtctSno) { ChngDetectMastSearchDto searchDto = new ChngDetectMastSearchDto(); searchDto.setCprsYr(cprsYr); searchDto.setCrtrYr(crtrYr); @@ -104,149 +106,149 @@ public class GukYuinApiController { @Operation(summary = "탐지결과 등록목록 조회(회차uid)", description = "탐지결과 등록목록 조회") @GetMapping("/chn/mast/{chnDtctId}") @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "목록 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = Basic.class))), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "200", + description = "목록 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = Basic.class))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) public ApiResponseDto selectChangeDetectionDtctIdList( - @RequestParam(required = false) String chnDtctId) { + @RequestParam(required = false) String chnDtctId) { return ApiResponseDto.ok(gukYuinApiService.listChnDtctId(chnDtctId)); } @Operation(summary = "탐지결과 등록목록 조회(1건 조회)", description = "탐지결과 등록목록 조회") @GetMapping("/chn/mast/list/{chnDtctMstId}") @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "목록 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = Basic.class))), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "200", + description = "목록 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = Basic.class))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) public ApiResponseDto selectChangeDetectionDetail( - @PathVariable String chnDtctMstId) { + @PathVariable String chnDtctMstId) { return ApiResponseDto.ok(gukYuinApiService.detail(chnDtctMstId)); } @Operation(summary = "국유in연동 가능여부 확인", description = "국유in연동 가능여부 확인") @GetMapping("/is-link/{uuid}") @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "목록 성공", - content = - @Content( - mediaType = "application/json", - schema = - @Schema( - implementation = GukYuinLinkableRes.class, - description = "TRUE:연동가능, FALSE:연동 불가능"))), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "200", + description = "목록 성공", + content = + @Content( + mediaType = "application/json", + schema = + @Schema( + implementation = GukYuinLinkableRes.class, + description = "TRUE:연동가능, FALSE:연동 불가능"))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) public ApiResponseDto getIsLinkGukYuin( - @Parameter(description = "uuid", example = "5799eb21-4780-48b0-a82e-e58dcbb8806b") - @PathVariable - UUID uuid) { + @Parameter(description = "uuid", example = "5799eb21-4780-48b0-a82e-e58dcbb8806b") + @PathVariable + UUID uuid) { return ApiResponseDto.ok(gukYuinApiService.getIsLinkGukYuin(uuid)); } @Operation(summary = "탐지객체 조회 (탐지객체)", description = "탐지객체 조회 (탐지객체)") @GetMapping("/chn/cont/{chnDtctId}") @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "목록 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = Basic.class))), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "200", + description = "목록 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = Basic.class))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) public ApiResponseDto findChnContList( - @PathVariable String chnDtctId, - @RequestParam(defaultValue = "0") Integer pageIndex, - @RequestParam(defaultValue = "10") Integer pageSize) { + @PathVariable String chnDtctId, + @RequestParam(defaultValue = "0") Integer pageIndex, + @RequestParam(defaultValue = "10") Integer pageSize) { return ApiResponseDto.ok(gukYuinApiService.findChnContList(chnDtctId, pageIndex, pageSize)); } @Operation(summary = "탐지객체 조회 (PNU에 해당하는 탐지객체)", description = "탐지객체 조회 (PNU에 해당하는 탐지객체)") @GetMapping("/chn/cont/{chnDtctId}/pnu/{pnu}") @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "목록 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = Basic.class))), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "200", + description = "목록 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = Basic.class))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) public ApiResponseDto findChnPnuToContList( - @PathVariable String chnDtctId, @PathVariable String pnu) { + @PathVariable String chnDtctId, @PathVariable String pnu) { return ApiResponseDto.ok(gukYuinApiService.findChnPnuToContList(chnDtctId, pnu)); } @Operation(summary = "탐지객체 조회 (탐지객체와 교차하는 PNU)", description = "탐지객체 조회 (탐지객체와 교차하는 PNU)") @GetMapping("/chn/pnu/{chnDtctId}/objt/{chnDtctObjtId}") @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "목록 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = Basic.class))), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "200", + description = "목록 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = Basic.class))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) public ApiResponseDto findPnuObjMgmtList( - @PathVariable String chnDtctId, @PathVariable String chnDtctObjtId) { + @PathVariable String chnDtctId, @PathVariable String chnDtctObjtId) { return ApiResponseDto.ok(gukYuinApiService.findPnuObjMgmtList(chnDtctId, chnDtctObjtId)); } @Operation(summary = "라벨여부 수정", description = "라벨여부 수정") @ApiResponses( - value = { - @ApiResponse( - responseCode = "201", - description = "등록 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = DetectMastReq.class))), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "201", + description = "등록 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = DetectMastReq.class))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) @PostMapping("/rlb/objt/{chnDtctObjtId}/lbl/{lblYn}") public ApiResponseDto updateChnDtctObjtLabelingYn( - @PathVariable String chnDtctObjtId, @PathVariable String lblYn) { + @PathVariable String chnDtctObjtId, @PathVariable String lblYn) { return ApiResponseDto.ok(gukYuinApiService.updateChnDtctObjtLabelingYn(chnDtctObjtId, lblYn)); } @Operation(summary = "국유in연동 등록", description = "국유in연동 등록") - @GetMapping("/mast/reg/{uuid}") + @PostMapping("/mast/reg/{uuid}") public ApiResponseDto connectChnMastRegist( - @Parameter(description = "uuid", example = "7a593d0e-76a8-4b50-8978-9af1fbe871af") - @PathVariable - UUID uuid) { + @Parameter(description = "uuid", example = "7a593d0e-76a8-4b50-8978-9af1fbe871af") + @PathVariable + UUID uuid) { return ApiResponseDto.ok(gukYuinApiService.connectChnMastRegist(uuid)); } } From d95dc364aa51d5de3a5ed2f70520aec0555edf29 Mon Sep 17 00:00:00 2001 From: teddy Date: Fri, 30 Jan 2026 14:10:22 +0900 Subject: [PATCH 20/41] =?UTF-8?q?wmts=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gukyuin/GukYuinApiController.java | 268 ++++++------ .../gukyuin/service/GukYuinApiService.java | 2 +- .../cd/kamcoback/layer/dto/WmtsLayerInfo.java | 78 +++- .../kamcoback/layer/service/WmtsService.java | 403 +++++++++++------- 4 files changed, 462 insertions(+), 289 deletions(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/gukyuin/GukYuinApiController.java b/src/main/java/com/kamco/cd/kamcoback/gukyuin/GukYuinApiController.java index 00d81bb0..dd6efcf7 100644 --- a/src/main/java/com/kamco/cd/kamcoback/gukyuin/GukYuinApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/gukyuin/GukYuinApiController.java @@ -37,65 +37,63 @@ public class GukYuinApiController { private final GukYuinApiService gukYuinApiService; - /** - * 탐지결과 등록 - */ + /** 탐지결과 등록 */ @Operation(summary = "탐지결과 등록", description = "탐지결과 등록") @ApiResponses( - value = { - @ApiResponse( - responseCode = "201", - description = "등록 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = DetectMastReq.class))), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "201", + description = "등록 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = DetectMastReq.class))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) @PostMapping("/chn/mast/regist") public ApiResponseDto regist( - @RequestBody @Valid ChngDetectMastDto.ChnDetectMastReqDto chnDetectMastReq) { + @RequestBody @Valid ChngDetectMastDto.ChnDetectMastReqDto chnDetectMastReq) { return ApiResponseDto.ok(gukYuinApiService.regist(chnDetectMastReq)); } @Operation(summary = "탐지결과 삭제", description = "탐지결과 삭제") @ApiResponses( - value = { - @ApiResponse( - responseCode = "201", - description = "등록 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = ChnDetectMastReqDto.class))), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "201", + description = "등록 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = ChnDetectMastReqDto.class))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) @PostMapping("/chn/mast/remove") public ApiResponseDto remove( - @RequestBody @Valid ChngDetectMastDto.ChnDetectMastReqDto chnDetectMastReq) { + @RequestBody @Valid ChngDetectMastDto.ChnDetectMastReqDto chnDetectMastReq) { return ApiResponseDto.ok(gukYuinApiService.remove(chnDetectMastReq)); } @Operation(summary = "탐지결과 등록목록 조회(년도,차수 조회)", description = "탐지결과 등록목록 조회") @GetMapping("/chn/mast") @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "목록 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = Basic.class))), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "200", + description = "목록 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = Basic.class))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) public ApiResponseDto selectChangeDetectionList( - @RequestParam(required = false) String cprsYr, - @RequestParam(required = false) String crtrYr, - @RequestParam(required = false) String chnDtctSno) { + @RequestParam(required = false) String cprsYr, + @RequestParam(required = false) String crtrYr, + @RequestParam(required = false) String chnDtctSno) { ChngDetectMastSearchDto searchDto = new ChngDetectMastSearchDto(); searchDto.setCprsYr(cprsYr); searchDto.setCrtrYr(crtrYr); @@ -106,149 +104,149 @@ public class GukYuinApiController { @Operation(summary = "탐지결과 등록목록 조회(회차uid)", description = "탐지결과 등록목록 조회") @GetMapping("/chn/mast/{chnDtctId}") @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "목록 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = Basic.class))), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "200", + description = "목록 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = Basic.class))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) public ApiResponseDto selectChangeDetectionDtctIdList( - @RequestParam(required = false) String chnDtctId) { + @RequestParam(required = false) String chnDtctId) { return ApiResponseDto.ok(gukYuinApiService.listChnDtctId(chnDtctId)); } @Operation(summary = "탐지결과 등록목록 조회(1건 조회)", description = "탐지결과 등록목록 조회") @GetMapping("/chn/mast/list/{chnDtctMstId}") @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "목록 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = Basic.class))), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "200", + description = "목록 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = Basic.class))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) public ApiResponseDto selectChangeDetectionDetail( - @PathVariable String chnDtctMstId) { + @PathVariable String chnDtctMstId) { return ApiResponseDto.ok(gukYuinApiService.detail(chnDtctMstId)); } @Operation(summary = "국유in연동 가능여부 확인", description = "국유in연동 가능여부 확인") @GetMapping("/is-link/{uuid}") @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "목록 성공", - content = - @Content( - mediaType = "application/json", - schema = - @Schema( - implementation = GukYuinLinkableRes.class, - description = "TRUE:연동가능, FALSE:연동 불가능"))), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "200", + description = "목록 성공", + content = + @Content( + mediaType = "application/json", + schema = + @Schema( + implementation = GukYuinLinkableRes.class, + description = "TRUE:연동가능, FALSE:연동 불가능"))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) public ApiResponseDto getIsLinkGukYuin( - @Parameter(description = "uuid", example = "5799eb21-4780-48b0-a82e-e58dcbb8806b") - @PathVariable - UUID uuid) { + @Parameter(description = "uuid", example = "5799eb21-4780-48b0-a82e-e58dcbb8806b") + @PathVariable + UUID uuid) { return ApiResponseDto.ok(gukYuinApiService.getIsLinkGukYuin(uuid)); } @Operation(summary = "탐지객체 조회 (탐지객체)", description = "탐지객체 조회 (탐지객체)") @GetMapping("/chn/cont/{chnDtctId}") @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "목록 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = Basic.class))), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "200", + description = "목록 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = Basic.class))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) public ApiResponseDto findChnContList( - @PathVariable String chnDtctId, - @RequestParam(defaultValue = "0") Integer pageIndex, - @RequestParam(defaultValue = "10") Integer pageSize) { + @PathVariable String chnDtctId, + @RequestParam(defaultValue = "0") Integer pageIndex, + @RequestParam(defaultValue = "10") Integer pageSize) { return ApiResponseDto.ok(gukYuinApiService.findChnContList(chnDtctId, pageIndex, pageSize)); } @Operation(summary = "탐지객체 조회 (PNU에 해당하는 탐지객체)", description = "탐지객체 조회 (PNU에 해당하는 탐지객체)") @GetMapping("/chn/cont/{chnDtctId}/pnu/{pnu}") @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "목록 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = Basic.class))), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "200", + description = "목록 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = Basic.class))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) public ApiResponseDto findChnPnuToContList( - @PathVariable String chnDtctId, @PathVariable String pnu) { + @PathVariable String chnDtctId, @PathVariable String pnu) { return ApiResponseDto.ok(gukYuinApiService.findChnPnuToContList(chnDtctId, pnu)); } @Operation(summary = "탐지객체 조회 (탐지객체와 교차하는 PNU)", description = "탐지객체 조회 (탐지객체와 교차하는 PNU)") @GetMapping("/chn/pnu/{chnDtctId}/objt/{chnDtctObjtId}") @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "목록 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = Basic.class))), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "200", + description = "목록 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = Basic.class))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) public ApiResponseDto findPnuObjMgmtList( - @PathVariable String chnDtctId, @PathVariable String chnDtctObjtId) { + @PathVariable String chnDtctId, @PathVariable String chnDtctObjtId) { return ApiResponseDto.ok(gukYuinApiService.findPnuObjMgmtList(chnDtctId, chnDtctObjtId)); } @Operation(summary = "라벨여부 수정", description = "라벨여부 수정") @ApiResponses( - value = { - @ApiResponse( - responseCode = "201", - description = "등록 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = DetectMastReq.class))), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "201", + description = "등록 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = DetectMastReq.class))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) @PostMapping("/rlb/objt/{chnDtctObjtId}/lbl/{lblYn}") public ApiResponseDto updateChnDtctObjtLabelingYn( - @PathVariable String chnDtctObjtId, @PathVariable String lblYn) { + @PathVariable String chnDtctObjtId, @PathVariable String lblYn) { return ApiResponseDto.ok(gukYuinApiService.updateChnDtctObjtLabelingYn(chnDtctObjtId, lblYn)); } @Operation(summary = "국유in연동 등록", description = "국유in연동 등록") @PostMapping("/mast/reg/{uuid}") public ApiResponseDto connectChnMastRegist( - @Parameter(description = "uuid", example = "7a593d0e-76a8-4b50-8978-9af1fbe871af") - @PathVariable - UUID uuid) { + @Parameter(description = "uuid", example = "7a593d0e-76a8-4b50-8978-9af1fbe871af") + @PathVariable + UUID uuid) { return ApiResponseDto.ok(gukYuinApiService.connectChnMastRegist(uuid)); } } diff --git a/src/main/java/com/kamco/cd/kamcoback/gukyuin/service/GukYuinApiService.java b/src/main/java/com/kamco/cd/kamcoback/gukyuin/service/GukYuinApiService.java index 84b2d172..de37d45e 100644 --- a/src/main/java/com/kamco/cd/kamcoback/gukyuin/service/GukYuinApiService.java +++ b/src/main/java/com/kamco/cd/kamcoback/gukyuin/service/GukYuinApiService.java @@ -75,7 +75,7 @@ public class GukYuinApiService { ChngDetectMastDto.RegistResDto.class); ChngDetectMastDto.RegistResDto resultBody = result.body(); - Boolean success = null; + Boolean success = false; if (resultBody != null) { ChngDetectMastDto.Basic registRes = resultBody.getResult(); // 추론 회차에 applyStatus, applyStatusDttm 업데이트 diff --git a/src/main/java/com/kamco/cd/kamcoback/layer/dto/WmtsLayerInfo.java b/src/main/java/com/kamco/cd/kamcoback/layer/dto/WmtsLayerInfo.java index beb6e4ea..a4f30c41 100755 --- a/src/main/java/com/kamco/cd/kamcoback/layer/dto/WmtsLayerInfo.java +++ b/src/main/java/com/kamco/cd/kamcoback/layer/dto/WmtsLayerInfo.java @@ -1,6 +1,5 @@ package com.kamco.cd.kamcoback.layer.dto; -import com.fasterxml.jackson.annotation.JsonProperty; import java.util.ArrayList; import java.util.List; @@ -13,9 +12,32 @@ public class WmtsLayerInfo { public List keywords = new ArrayList<>(); public BoundingBox boundingBox; public List formats = new ArrayList<>(); - public List tileMatrixSetLinks = new ArrayList<>(); + public List tileMatrixSetLinks = new ArrayList<>(); public List resourceUrls = new ArrayList<>(); public List