diff --git a/src/main/java/com/kamco/cd/kamcoback/changedetection/dto/ChangeDetectionDto.java b/src/main/java/com/kamco/cd/kamcoback/changedetection/dto/ChangeDetectionDto.java index c053ffb0..e045186e 100644 --- a/src/main/java/com/kamco/cd/kamcoback/changedetection/dto/ChangeDetectionDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/changedetection/dto/ChangeDetectionDto.java @@ -137,6 +137,7 @@ public class ChangeDetectionDto { private Integer afterYear; // 비교년도 private Double afterConfidence; // 비교 신뢰도(확률) private String afterClass; + private Double cdProb; // 탐지정확도 } @Schema(name = "PointFeature", description = "Geometry 리턴 객체") @@ -177,5 +178,6 @@ public class ChangeDetectionDto { private Integer afterYear; // 비교년도 private Double afterConfidence; // 비교 신뢰도(확률) private String afterClass; // 비교 분류 + private Double cdProb; // 탐지 정확도 } } diff --git a/src/main/java/com/kamco/cd/kamcoback/changedetection/service/ChangeDetectionService.java b/src/main/java/com/kamco/cd/kamcoback/changedetection/service/ChangeDetectionService.java index f037f038..ba3450bb 100644 --- a/src/main/java/com/kamco/cd/kamcoback/changedetection/service/ChangeDetectionService.java +++ b/src/main/java/com/kamco/cd/kamcoback/changedetection/service/ChangeDetectionService.java @@ -5,7 +5,6 @@ import com.kamco.cd.kamcoback.changedetection.dto.ChangeDetectionDto; import com.kamco.cd.kamcoback.postgres.core.ChangeDetectionCoreService; import java.util.List; import lombok.RequiredArgsConstructor; -import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @Service @@ -35,7 +34,6 @@ public class ChangeDetectionService { return changeDetectionCoreService.getChangeDetectionYearList(); } - @Cacheable(value = "changeDetectionPolygon", key = "#analUid + '_' + #mapSheetNum") public ChangeDetectionDto.PolygonFeatureList getChangeDetectionPolygonList( Long analUid, String mapSheetNum) { diff --git a/src/main/java/com/kamco/cd/kamcoback/code/CommonCodeApiController.java b/src/main/java/com/kamco/cd/kamcoback/code/CommonCodeApiController.java index 2c0f7815..d6eb6903 100644 --- a/src/main/java/com/kamco/cd/kamcoback/code/CommonCodeApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/code/CommonCodeApiController.java @@ -2,7 +2,10 @@ package com.kamco.cd.kamcoback.code; import com.kamco.cd.kamcoback.code.dto.CommonCodeDto; import com.kamco.cd.kamcoback.code.service.CommonCodeService; +import com.kamco.cd.kamcoback.common.enums.DetectionClassification; import com.kamco.cd.kamcoback.config.api.ApiResponseDto; +import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto; +import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.Clazzes; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; @@ -10,6 +13,8 @@ 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 jakarta.validation.Valid; +import java.util.Arrays; +import java.util.Comparator; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.DeleteMapping; @@ -206,4 +211,16 @@ public class CommonCodeApiController { String code) { return ApiResponseDto.ok(commonCodeService.findByCode(code)); } + + @GetMapping("/clazz") + public ApiResponseDto> getClasses() { + + List list = + Arrays.stream(DetectionClassification.values()) + .sorted(Comparator.comparingInt(DetectionClassification::getOrder)) + .map(Clazzes::new) + .toList(); + + return ApiResponseDto.ok(list); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/common/api/SceneDemoApiController.java b/src/main/java/com/kamco/cd/kamcoback/common/api/SceneDemoApiController.java new file mode 100644 index 00000000..b70289a2 --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/common/api/SceneDemoApiController.java @@ -0,0 +1,46 @@ +package com.kamco.cd.kamcoback.common.api; + +import com.kamco.cd.kamcoback.config.api.ApiResponseDto; +import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.MapSheet; +import com.kamco.cd.kamcoback.inference.dto.LearningModelResultDto.BatchProcessResponse; +import com.kamco.cd.kamcoback.inference.service.InferenceResultService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +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 java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RequiredArgsConstructor +@RestController +@RequestMapping("/demo/api/scene") +public class SceneDemoApiController { + + private final InferenceResultService inferenceResultService; + + @Operation(summary = "추론된 도엽 목록", description = "추론된 도엽 목록 5000:1") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + description = "검색 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = BatchProcessResponse.class))), + @ApiResponse(responseCode = "400", description = "잘못된 요청", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) + @GetMapping("/sheets/train-set/{id}") + public ApiResponseDto> listGetScenes5k( + @Parameter(description = "분석결과 id", example = "1") @PathVariable Long id) { + List mapSheets = inferenceResultService.listGetScenes5k(id); + return ApiResponseDto.ok(mapSheets); + } +} diff --git a/src/main/java/com/kamco/cd/kamcoback/common/enums/DetectionClassification.java b/src/main/java/com/kamco/cd/kamcoback/common/enums/DetectionClassification.java index a3a2bd7c..42d231bd 100644 --- a/src/main/java/com/kamco/cd/kamcoback/common/enums/DetectionClassification.java +++ b/src/main/java/com/kamco/cd/kamcoback/common/enums/DetectionClassification.java @@ -6,24 +6,25 @@ import lombok.Getter; @Getter @AllArgsConstructor public enum DetectionClassification { - BUILDING("building", "빌딩"), - CONTAINER("container", "컨테이너(창고·적재함)"), - FIELD("field", "경작지 / 들판"), - FOREST("forest", "숲"), - GRASS("grass", "초지 / 잔디지역"), - GREENHOUSE("greenhouse", "비닐하우스"), - LAND("land", "나지"), - ORCHARD("orchard", "과수원"), - ROAD("road", "도로"), - STONE("stone", "암석 / 돌 지역"), - TANK("tank", "탱크(저유탱크 등 저장시설)"), - TUMULUS("tumulus", "고분(무덤)"), - WASTE("waste", "폐기물 적치장 / 황폐지"), - WATER("water", "수체(水域) / 물"), - ETC("ETC", "기타"); // For 'etc' (miscellaneous/other) + BUILDING("building", "건물", 10), + CONTAINER("container", "컨테이너", 20), + FIELD("field", "경작지", 30), + FOREST("forest", "숲", 40), + GRASS("grass", "초지", 50), + GREENHOUSE("greenhouse", "비닐하우스", 60), + LAND("land", "일반토지", 70), + ORCHARD("orchard", "과수원", 80), + ROAD("road", "도로", 90), + STONE("stone", "모래/자갈", 100), + TANK("tank", "물탱크", 110), + TUMULUS("tumulus", "토분(무덤)", 120), + WASTE("waste", "폐기물", 130), + WATER("water", "물", 140), + ETC("ETC", "기타", 200); // For 'etc' (miscellaneous/other) private final String id; private final String desc; + private final int order; /** * Optional: Helper method to get the enum from a String, case-insensitive, or return ETC if not diff --git a/src/main/java/com/kamco/cd/kamcoback/config/RedisConfig.java b/src/main/java/com/kamco/cd/kamcoback/config/RedisConfig.java index f1dde5be..4f03f569 100644 --- a/src/main/java/com/kamco/cd/kamcoback/config/RedisConfig.java +++ b/src/main/java/com/kamco/cd/kamcoback/config/RedisConfig.java @@ -1,5 +1,11 @@ package com.kamco.cd.kamcoback.config; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator; +import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import java.time.Duration; import org.springframework.beans.factory.annotation.Value; import org.springframework.cache.CacheManager; @@ -38,6 +44,17 @@ public class RedisConfig { return new LettuceConnectionFactory(redisConfig); } + @Bean + public ObjectMapper redisObjectMapper() { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); + objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + objectMapper.findAndRegisterModules(); + + return objectMapper; + } + @Bean public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate template = new RedisTemplate<>(); @@ -47,9 +64,11 @@ public class RedisConfig { template.setKeySerializer(new StringRedisSerializer()); template.setHashKeySerializer(new StringRedisSerializer()); - // Value는 JSON으로 직렬화 - template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); - template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); + // Value는 JSON으로 직렬화 (JavaTimeModule 포함) + GenericJackson2JsonRedisSerializer serializer = + new GenericJackson2JsonRedisSerializer(redisObjectMapper()); + template.setValueSerializer(serializer); + template.setHashValueSerializer(serializer); template.afterPropertiesSet(); return template; @@ -58,6 +77,25 @@ public class RedisConfig { // 기본 레디스 캐시 세팅 @Bean public CacheManager cacheManager(RedisConnectionFactory connectionFactory) { + ObjectMapper cacheObjectMapper = new ObjectMapper(); + cacheObjectMapper.registerModule(new JavaTimeModule()); + cacheObjectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + cacheObjectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + cacheObjectMapper.findAndRegisterModules(); + + // 타입 정보 포함 - JAVA_LANG_OBJECT로 제한적으로 적용 + PolymorphicTypeValidator ptv = + BasicPolymorphicTypeValidator.builder() + .allowIfSubType("com.kamco.cd.kamcoback") + .allowIfSubType("org.springframework.data.domain") + .allowIfSubType("java.util") + .allowIfSubType("java.time") + .build(); + cacheObjectMapper.activateDefaultTyping(ptv, ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT); + + GenericJackson2JsonRedisSerializer serializer = + new GenericJackson2JsonRedisSerializer(cacheObjectMapper); + RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofHours(1)) // 기본 TTL 1시간 @@ -65,8 +103,7 @@ public class RedisConfig { RedisSerializationContext.SerializationPair.fromSerializer( new StringRedisSerializer())) .serializeValuesWith( - RedisSerializationContext.SerializationPair.fromSerializer( - new GenericJackson2JsonRedisSerializer())); + RedisSerializationContext.SerializationPair.fromSerializer(serializer)); return RedisCacheManager.builder(connectionFactory).cacheDefaults(config).build(); } diff --git a/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultApiV2Controller.java b/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultApiV2Controller.java new file mode 100644 index 00000000..8b01288e --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultApiV2Controller.java @@ -0,0 +1,69 @@ +package com.kamco.cd.kamcoback.inference; + +import com.kamco.cd.kamcoback.config.api.ApiResponseDto; +import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto; +import com.kamco.cd.kamcoback.inference.service.InferenceResultService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +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 lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.Page; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@Tag(name = "추론관리 분석결과", description = "추론관리 분석결과") +@RequiredArgsConstructor +@RestController +@RequestMapping({"/v2/demo/inf/res"}) +@Slf4j +public class InferenceResultApiV2Controller { + + private final InferenceResultService inferenceResultService; + + @Operation(summary = "추론관리 분석결과 상세 목록 V2", description = "추론관리 분석결과 상세 목록 geojson 데이터 조회") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + description = "검색 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = Page.class))), + @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) + @GetMapping("/geom/{id}") + public ApiResponseDto> listInferenceResultWithGeom( + @Parameter(description = "분석결과 id", example = "1") @PathVariable Long id, + @Parameter(description = "기준년도 분류", example = "land") @RequestParam(required = false) + String targetClass, + @Parameter(description = "비교년도 분류", example = "waste") @RequestParam(required = false) + String compareClass, + @Parameter(description = "5000:1 도협번호 37801011,37801012") @RequestParam(required = false) + List mapSheetNum, + @Parameter(description = "페이지 번호 (0부터 시작)", example = "0") @RequestParam(defaultValue = "0") + int page, + @Parameter(description = "페이지 크기", example = "20") @RequestParam(defaultValue = "20") + int size, + @Parameter(description = "정렬 조건 (형식: 필드명,방향)", example = "name,asc") + @RequestParam(required = false) + String sort) { + InferenceResultDto.SearchGeoReq searchGeoReq = + new InferenceResultDto.SearchGeoReq( + targetClass, compareClass, mapSheetNum, page, size, sort); + + Page geomList = + inferenceResultService.listInferenceResultWithGeom(id, searchGeoReq); + return ApiResponseDto.ok(geomList); + } +} diff --git a/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceResultDto.java b/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceResultDto.java index e093b8c3..d70abb60 100644 --- a/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceResultDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceResultDto.java @@ -1,10 +1,13 @@ package com.kamco.cd.kamcoback.inference.dto; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; import com.kamco.cd.kamcoback.common.enums.DetectionClassification; import com.kamco.cd.kamcoback.common.utils.interfaces.JsonFormatDttm; import io.swagger.v3.oas.annotations.media.Schema; import java.time.ZonedDateTime; import java.util.List; +import java.util.UUID; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @@ -173,6 +176,122 @@ public class InferenceResultDto { } } + // 분석 상세 ROW + @Getter + @AllArgsConstructor + public static class DetailListEntity { + + private Uid code; + private Double detectionScore; + private Clazzes compare; + private Clazzes target; + private MapSheet mapSheet; + private Coordinate center; + @JsonFormatDttm private ZonedDateTime updatedDttm; + + public DetailListEntity( + UUID uuid, + Double detectionScore, + Clazzes compare, + Clazzes target, + MapSheet mapSheet, + Coordinate center, + ZonedDateTime updatedDttm) { + this.code = new Uid(uuid); + this.detectionScore = detectionScore; + this.compare = compare; + this.target = target; + this.mapSheet = mapSheet; + this.center = center; + this.updatedDttm = updatedDttm; + } + } + + @Getter + @AllArgsConstructor + public static class Uid { + + private String shortCode; + private String code; + + public Uid(UUID uuid) { + if (uuid != null) { + this.shortCode = uuid.toString().substring(0, 8).toUpperCase(); + this.code = uuid.toString(); + } + } + } + + // MAP NO + @Getter + @AllArgsConstructor + public static class MapSheet { + + private String number; + private String name; + } + + // classification info + @Getter + public static class Clazz { + + private String code; + private String name; + @JsonIgnore private Double score; + + public Clazz(String code, Double score) { + this.code = code; + this.score = score; + this.name = DetectionClassification.fromString(code).getDesc(); + } + + public Clazz(String code) { + this.code = code; + this.name = DetectionClassification.fromString(code).getDesc(); + } + } + + // classification info + @Getter + public static class Clazzes { + + private DetectionClassification code; + private String name; + + @JsonInclude(JsonInclude.Include.NON_NULL) + private Double score; + + private Integer order; + + public Clazzes(DetectionClassification classification, Double score) { + this.code = classification; + this.name = classification.getDesc(); + this.order = classification.getOrder(); + this.score = score; + } + + public Clazzes(DetectionClassification classification) { + this.code = classification; + this.name = classification.getDesc(); + this.order = classification.getOrder(); + } + } + + // 좌표 정보 point + @Getter + public static class Coordinate { + + private Double lon; // 경도(Longitude) + private Double lat; // 위도(Latitude) + private String srid; // Spatial Reference ID의 약자로, 데이터베이스에서 좌표계를 식별하는 고유 번호 추후enum으로 + + public Coordinate(Double lon, Double lat) { + this.lon = lon; + this.lat = lat; + this.srid = "EPSG:4326"; + } + } + @Getter public static class Geom { diff --git a/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultService.java b/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultService.java index 76490500..45a9ea82 100644 --- a/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultService.java +++ b/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultService.java @@ -3,7 +3,9 @@ package com.kamco.cd.kamcoback.inference.service; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.Dashboard; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.Detail; +import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.MapSheet; import com.kamco.cd.kamcoback.postgres.core.InferenceResultCoreService; +import jakarta.validation.constraints.NotNull; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; @@ -59,6 +61,18 @@ public class InferenceResultService { return inferenceResultCoreService.getInferenceResultGeomList(id, searchGeoReq); } + /** + * 분석결과 상세 목록 + * + * @param searchReq + * @return + */ + public Page listInferenceResultWithGeom( + @NotNull Long id, InferenceResultDto.SearchGeoReq searchReq) { + + return inferenceResultCoreService.listInferenceResultWithGeom(id, searchReq); + } + /** * 분석결과 상제 정보 Summary, DashBoard * @@ -87,4 +101,8 @@ public class InferenceResultService { public List getSheets(Long id) { return inferenceResultCoreService.getSheets(id).stream().map(String::valueOf).toList(); } + + public List listGetScenes5k(Long id) { + return inferenceResultCoreService.listGetScenes5k(id); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/mapsheet/MapSheetMngApiController.java b/src/main/java/com/kamco/cd/kamcoback/mapsheet/MapSheetMngApiController.java index 26ff48b1..28e4f2b9 100644 --- a/src/main/java/com/kamco/cd/kamcoback/mapsheet/MapSheetMngApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/mapsheet/MapSheetMngApiController.java @@ -10,30 +10,18 @@ import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.SrchFoldersDto; import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto; import com.kamco.cd.kamcoback.mapsheet.service.MapSheetMngService; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; 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 jakarta.validation.Valid; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @Tag(name = "영상 관리", description = "영상 관리 API") @@ -59,69 +47,57 @@ public class MapSheetMngApiController { @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) }) @PostMapping("/folder-list") - public ApiResponseDto> getDir( - @RequestBody SrchFoldersDto srchDto - ) { + public ApiResponseDto> getDir(@RequestBody SrchFoldersDto srchDto) { return ApiResponseDto.createOK(mapSheetMngService.getFolderAll(srchDto)); } @Operation(summary = "파일목록 조회", description = "파일목록 조회") @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "조회 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = CommonCodeDto.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 = CommonCodeDto.Basic.class))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) @PostMapping("/file-list") - public ApiResponseDto getFiles( - @RequestBody SrchFilesDto srchDto - ) { + public ApiResponseDto getFiles(@RequestBody SrchFilesDto srchDto) { return ApiResponseDto.createOK(mapSheetMngService.getFilesAll(srchDto)); } /** * 오류데이터 목록 조회 + * * @param searchReq * @return */ @PostMapping("/error-list") public ApiResponseDto> findMapSheetErrorList( - @RequestBody - @Valid - MapSheetMngDto.searchReq searchReq - ){ + @RequestBody @Valid MapSheetMngDto.searchReq searchReq) { return ApiResponseDto.ok(mapSheetMngService.findMapSheetErrorList(searchReq)); } - @Operation(summary = "영상관리목록 조회", description = "영상관리목록 조회") @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "조회 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = CommonCodeDto.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 = CommonCodeDto.Basic.class))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) @PostMapping("/mng-list") public ApiResponseDto> findMapSheetMngList( - @RequestBody - @Valid - MapSheetMngDto.searchReq searchReq - ){ + @RequestBody @Valid MapSheetMngDto.searchReq searchReq) { return ApiResponseDto.ok(mapSheetMngService.findMapSheetMngList(searchReq)); } - - } 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 31b84da8..51d7f94a 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 @@ -62,27 +62,25 @@ public class MapSheetMngDto { private DataState dataState; } - @Schema(name = "MngDto", description = "영상관리 검색 리턴") @Getter @Setter @NoArgsConstructor @AllArgsConstructor - public static class MngDto{ + public static class MngDto { private int rowNum; private int mngYyyy; private String mngState; private String syncState; private String mngStateDttm; private String syncStateDttm; - //private int sheetCnt; - //private int exceptCnt; + // private int sheetCnt; + // private int exceptCnt; private String mngPath; private String createdDttm; private Long createdUid; private String updatedDttm; private Long updatedUid; - } @Getter 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 e1cc4a94..ab9ba5d8 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 @@ -164,7 +164,8 @@ public class MapSheetMngService { return mapSheetMngCoreService.findMapSheetErrorList(searchReq); } - public Page findMapSheetMngList(MapSheetMngDto.@Valid searchReq searchReq) { + public Page findMapSheetMngList( + MapSheetMngDto.@Valid searchReq searchReq) { return mapSheetMngCoreService.findMapSheetMngList(searchReq); } } diff --git a/src/main/java/com/kamco/cd/kamcoback/members/AdminApiController.java b/src/main/java/com/kamco/cd/kamcoback/members/AdminApiController.java index effa1199..e52e2f97 100644 --- a/src/main/java/com/kamco/cd/kamcoback/members/AdminApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/members/AdminApiController.java @@ -12,6 +12,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import java.util.UUID; import lombok.RequiredArgsConstructor; +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; @@ -19,7 +20,7 @@ import org.springframework.web.bind.annotation.RestController; @Tag(name = "회원정보 관리자 관리", description = "회원정보 관리자 관리 API") @RestController -@RequestMapping("/api/admin") +@RequestMapping("/api/admin/members") @RequiredArgsConstructor public class AdminApiController { @@ -39,7 +40,7 @@ public class AdminApiController { @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) }) - @PostMapping("/members/join") + @PostMapping("/join") public ApiResponseDto saveMember( @io.swagger.v3.oas.annotations.parameters.RequestBody( description = "회원가입", @@ -55,7 +56,7 @@ public class AdminApiController { return ApiResponseDto.createOK(adminService.saveMember(addReq)); } - @Operation(summary = "역할 저장", description = "역할 저장") + @Operation(summary = "역할 추가", description = "uuid 기준으로 역할 추가") @ApiResponses( value = { @ApiResponse( @@ -85,7 +86,7 @@ public class AdminApiController { return ApiResponseDto.createOK(rolesDto.getUuid()); } - @Operation(summary = "역할 삭제", description = "역할 삭제") + @Operation(summary = "역할 삭제", description = "uuid 기준으로 역할 삭제") @ApiResponses( value = { @ApiResponse( @@ -114,4 +115,74 @@ public class AdminApiController { adminService.deleteRoles(rolesDto); return ApiResponseDto.createOK(rolesDto.getUuid()); } + + @Operation(summary = "상태 수정", description = "상태 수정") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "201", + description = "상태 수정", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = UUID.class))), + @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) + @PostMapping("/status/update") + public ApiResponseDto updateStatus( + @io.swagger.v3.oas.annotations.parameters.RequestBody( + description = "상태 수정", + required = true, + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = MembersDto.StatusDto.class))) + @RequestBody + @Valid + MembersDto.StatusDto statusDto) { + adminService.updateStatus(statusDto); + return ApiResponseDto.createOK(statusDto.getUuid()); + } + + @Operation(summary = "회원 탈퇴", description = "회원 탈퇴") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "201", + description = "회원 탈퇴", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = UUID.class))), + @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) + @PostMapping("/delete-account") + public ApiResponseDto deleteAccount(MembersDto.StatusDto statusDto) { + adminService.deleteAccount(statusDto); + return ApiResponseDto.createOK(statusDto.getUuid()); + } + + @Operation(summary = "패스워드 초기화", description = "패스워드 초기화") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "201", + description = "패스워드 초기화", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = Long.class))), + @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) + @PostMapping("/{memberId}/password") + public ApiResponseDto resetPassword(@PathVariable Long memberId) { + adminService.resetPassword(memberId); + return ApiResponseDto.createOK(memberId); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/members/MembersApiController.java b/src/main/java/com/kamco/cd/kamcoback/members/MembersApiController.java index 2127f4ed..6d4287b4 100644 --- a/src/main/java/com/kamco/cd/kamcoback/members/MembersApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/members/MembersApiController.java @@ -10,8 +10,10 @@ 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.UUID; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; +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; @@ -42,4 +44,25 @@ public class MembersApiController { public ApiResponseDto> getMemberList(@RequestBody MembersDto.SearchReq searchReq) { return ApiResponseDto.ok(membersService.findByMembers(searchReq)); } + + @Operation(summary = "회원정보 수정", description = "회원정보 수정") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "201", + description = "회원정보 수정", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = UUID.class))), + @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) + @PostMapping("/{uuid}") + public ApiResponseDto updateMember( + @PathVariable UUID uuid, @RequestBody MembersDto.UpdateReq updateReq) { + membersService.updateMember(uuid, updateReq); + return ApiResponseDto.createOK(uuid); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/members/dto/MembersDto.java b/src/main/java/com/kamco/cd/kamcoback/members/dto/MembersDto.java index c5e94ea9..063f4172 100644 --- a/src/main/java/com/kamco/cd/kamcoback/members/dto/MembersDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/members/dto/MembersDto.java @@ -99,9 +99,7 @@ public class MembersDto { @Size(min = 2, max = 100) private String name; - @Schema(description = "패스워드", example = "") - @NotBlank - @Size(max = 255) + @Schema(hidden = true) private String password; @Schema(description = "이메일", example = "gildong@daum.net") @@ -116,12 +114,42 @@ public class MembersDto { } } + @Getter + @Setter + public static class UpdateReq { + + @Schema(description = "사번, 패스워드 변경시 필수 값", example = "11111") + @Size(max = 50) + private String employeeNo; + + @Schema(description = "이름", example = "홍길동") + @Size(min = 2, max = 100) + private String name; + + @Schema(description = "패스워드", example = "") + @Size(max = 255) + private String password; + + @Schema(description = "이메일", example = "gildong@daum.net") + @Size(max = 100) + private String email; + + public UpdateReq(String employeeNo, String name, String password, String email) { + this.employeeNo = employeeNo; + this.name = name; + this.password = password; + this.email = email; + } + } + @Getter @Setter public static class RolesDto { + @Schema(description = "UUID", example = "4e89e487-c828-4a34-a7fc-0d5b0e3b53b5") private UUID uuid; + @Schema(description = "역할 ROLE_ADMIN, ROLE_LABELER, ROLE_REVIEWER", example = "ROLE_ADMIN") @EnumValid(enumClass = RoleType.class) private String roleName; @@ -130,4 +158,19 @@ public class MembersDto { this.roleName = roleName; } } + + @Getter + @Setter + @NoArgsConstructor + @AllArgsConstructor + public static class StatusDto { + + @Schema(description = "UUID", example = "4e89e487-c828-4a34-a7fc-0d5b0e3b53b5") + @NotBlank + private UUID uuid; + + @Schema(description = "변경할 상태값 ACTIVE, INACTIVE, ARCHIVED", example = "ACTIVE") + @NotBlank + private String status; + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/members/service/AdminService.java b/src/main/java/com/kamco/cd/kamcoback/members/service/AdminService.java index 50b57d13..6e5458cb 100644 --- a/src/main/java/com/kamco/cd/kamcoback/members/service/AdminService.java +++ b/src/main/java/com/kamco/cd/kamcoback/members/service/AdminService.java @@ -5,6 +5,7 @@ import com.kamco.cd.kamcoback.members.dto.MembersDto; import com.kamco.cd.kamcoback.postgres.core.MembersCoreService; import lombok.RequiredArgsConstructor; import org.mindrot.jbcrypt.BCrypt; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -15,6 +16,9 @@ public class AdminService { private final MembersCoreService membersCoreService; + @Value("${member.init_password}") + private String password; + /** * 회원가입 * @@ -23,11 +27,11 @@ public class AdminService { */ @Transactional public Long saveMember(MembersDto.AddReq addReq) { - // salt 생성 - String salt = BCryptSaltGenerator.generateSaltWithEmployeeNo(addReq.getEmployeeNo()); + // salt 생성, 사번이 salt + String salt = BCryptSaltGenerator.generateSaltWithEmployeeNo(addReq.getEmployeeNo().trim()); - // 패스워드 암호화 - String hashedPassword = BCrypt.hashpw(addReq.getPassword(), salt); + // 패스워드 암호화, 초기 패스워드 고정 + String hashedPassword = BCrypt.hashpw(password, salt); addReq.setPassword(hashedPassword); return membersCoreService.saveMembers(addReq); } @@ -50,4 +54,31 @@ public class AdminService { public void deleteRoles(MembersDto.RolesDto rolesDto) { membersCoreService.deleteRoles(rolesDto); } + + /** + * 역할 수정 + * + * @param statusDto + */ + public void updateStatus(MembersDto.StatusDto statusDto) { + membersCoreService.updateStatus(statusDto); + } + + /** + * 회원 탈퇴 + * + * @param statusDto + */ + public void deleteAccount(MembersDto.StatusDto statusDto) { + membersCoreService.deleteAccount(statusDto); + } + + /** + * 패스워드 초기화 + * + * @param id + */ + public void resetPassword(Long id) { + membersCoreService.resetPassword(id); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/members/service/MembersService.java b/src/main/java/com/kamco/cd/kamcoback/members/service/MembersService.java index 332c1e44..78587f18 100644 --- a/src/main/java/com/kamco/cd/kamcoback/members/service/MembersService.java +++ b/src/main/java/com/kamco/cd/kamcoback/members/service/MembersService.java @@ -1,10 +1,15 @@ package com.kamco.cd.kamcoback.members.service; +import com.kamco.cd.kamcoback.config.BCryptSaltGenerator; import com.kamco.cd.kamcoback.members.dto.MembersDto; import com.kamco.cd.kamcoback.members.dto.MembersDto.Basic; import com.kamco.cd.kamcoback.postgres.core.MembersCoreService; +import java.util.UUID; import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.StringUtils; +import org.mindrot.jbcrypt.BCrypt; import org.springframework.data.domain.Page; +import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -24,4 +29,30 @@ public class MembersService { public Page findByMembers(MembersDto.SearchReq searchReq) { return membersCoreService.findByMembers(searchReq); } + + /** + * 회원정보 수정 + * + * @param uuid + * @param updateReq + */ + public void updateMember(UUID uuid, MembersDto.UpdateReq updateReq) { + + if (StringUtils.isNotBlank(updateReq.getPassword())) { + + if (StringUtils.isBlank(updateReq.getEmployeeNo())) { + throw new HttpMessageNotReadableException("패스워드 변경시 사번은 필수 값입니다."); + } + + // salt 생성, 사번이 salt + String salt = + BCryptSaltGenerator.generateSaltWithEmployeeNo(updateReq.getEmployeeNo().trim()); + + // 패스워드 암호화, 초기 패스워드 고정 + String hashedPassword = BCrypt.hashpw(updateReq.getPassword(), salt); + updateReq.setPassword(hashedPassword); + } + + membersCoreService.updateMembers(uuid, updateReq); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/InferenceResultCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/InferenceResultCoreService.java index bbf1ea90..c66d5138 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/core/InferenceResultCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/InferenceResultCoreService.java @@ -2,18 +2,26 @@ package com.kamco.cd.kamcoback.postgres.core; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.Dashboard; +import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.MapSheet; +import com.kamco.cd.kamcoback.postgres.entity.MapInkx5kEntity; +import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataEntity; +import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataGeomEntity; import com.kamco.cd.kamcoback.postgres.repository.Inference.InferenceResultRepository; +import com.kamco.cd.kamcoback.postgres.repository.scene.MapInkx5kRepository; import jakarta.persistence.EntityNotFoundException; +import jakarta.validation.constraints.NotNull; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor public class InferenceResultCoreService { private final InferenceResultRepository inferenceResultRepository; + private final MapInkx5kRepository mapInkx5kRepository; /** * 추론관리 > 분석결과 목록 조회 @@ -61,6 +69,27 @@ public class InferenceResultCoreService { return inferenceResultRepository.getInferenceGeomList(id, searchGeoReq); } + /** + * 분석결과 상세 목록 + * + * @param searchReq + * @return + */ + @Transactional(readOnly = true) + public Page listInferenceResultWithGeom( + @NotNull Long analyId, InferenceResultDto.SearchGeoReq searchReq) { + // 분석 ID 에 해당하는 dataids를 가져온다. + List dataIds = + inferenceResultRepository.listAnalyGeom(analyId).stream() + .mapToLong(MapSheetAnalDataEntity::getId) + .boxed() + .toList(); + // 해당데이터의 폴리곤데이터를 가져온다 + Page mapSheetAnalDataGeomEntities = + inferenceResultRepository.listInferenceResultWithGeom(dataIds, searchReq); + return mapSheetAnalDataGeomEntities.map(MapSheetAnalDataGeomEntity::toEntity); + } + /** * 추론된 5000:1 도엽 목록 * @@ -70,4 +99,17 @@ public class InferenceResultCoreService { public List getSheets(Long id) { return inferenceResultRepository.getSheets(id); } + + @Transactional(readOnly = true) + public List listGetScenes5k(Long analyId) { + List sceneCodes = + inferenceResultRepository.listAnalyGeom(analyId).stream() + .mapToLong(MapSheetAnalDataEntity::getMapSheetNum) + .mapToObj(String::valueOf) + .toList(); + + return mapInkx5kRepository.listGetScenes5k(sceneCodes).stream() + .map(MapInkx5kEntity::toEntity) + .toList(); + } } 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 9f8370b2..20c4fd7d 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 @@ -18,7 +18,8 @@ public class MapSheetMngCoreService { return mapSheetMngRepository.findMapSheetErrorList(searchReq); } - public Page findMapSheetMngList(MapSheetMngDto.@Valid searchReq searchReq) { + public Page findMapSheetMngList( + MapSheetMngDto.@Valid searchReq searchReq) { return mapSheetMngRepository.findMapSheetMngList(searchReq); } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/MembersCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/MembersCoreService.java index 2e7bf462..bf565060 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/core/MembersCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/MembersCoreService.java @@ -1,15 +1,21 @@ package com.kamco.cd.kamcoback.postgres.core; +import com.kamco.cd.kamcoback.config.BCryptSaltGenerator; import com.kamco.cd.kamcoback.members.dto.MembersDto; import com.kamco.cd.kamcoback.members.exception.MemberException; import com.kamco.cd.kamcoback.members.exception.MemberException.MemberNotFoundException; +import com.kamco.cd.kamcoback.postgres.entity.MemberArchivedEntity; import com.kamco.cd.kamcoback.postgres.entity.MemberEntity; import com.kamco.cd.kamcoback.postgres.entity.MemberRoleEntity; import com.kamco.cd.kamcoback.postgres.entity.MemberRoleEntityId; +import com.kamco.cd.kamcoback.postgres.repository.members.MembersArchivedRepository; import com.kamco.cd.kamcoback.postgres.repository.members.MembersRepository; import com.kamco.cd.kamcoback.postgres.repository.members.MembersRoleRepository; import java.time.ZonedDateTime; +import java.util.UUID; import lombok.RequiredArgsConstructor; +import org.mindrot.jbcrypt.BCrypt; +import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Page; import org.springframework.stereotype.Service; @@ -19,6 +25,10 @@ public class MembersCoreService { private final MembersRepository membersRepository; private final MembersRoleRepository memberRoleRepository; + private final MembersArchivedRepository memberArchivedRepository; + + @Value("${member.init_password}") + private String password; /** * 회원가입 @@ -46,6 +56,32 @@ public class MembersCoreService { return membersRepository.save(memberEntity).getId(); } + /** + * 회원정보 수정 + * + * @param uuid + * @param updateReq + */ + public void updateMembers(UUID uuid, MembersDto.UpdateReq updateReq) { + MemberEntity memberEntity = + membersRepository.findByUUID(uuid).orElseThrow(() -> new MemberNotFoundException()); + + if (updateReq.getEmployeeNo() != null && !memberEntity.getEmployeeNo().isEmpty()) { + memberEntity.setEmployeeNo(updateReq.getEmployeeNo()); + } + if (updateReq.getName() != null && !updateReq.getName().isEmpty()) { + memberEntity.setName(updateReq.getName()); + } + if (updateReq.getPassword() != null && !updateReq.getPassword().isEmpty()) { + memberEntity.setPassword(updateReq.getPassword()); + } + if (updateReq.getEmail() != null && !updateReq.getEmail().isEmpty()) { + memberEntity.setEmail(updateReq.getEmail()); + } + + membersRepository.save(memberEntity); + } + /** * 역할 추가 * @@ -96,6 +132,74 @@ public class MembersCoreService { memberRoleRepository.delete(memberRoleEntity); } + /** + * 상태 수정 + * + * @param statusDto + */ + public void updateStatus(MembersDto.StatusDto statusDto) { + MemberEntity memberEntity = + membersRepository + .findByUUID(statusDto.getUuid()) + .orElseThrow(() -> new MemberNotFoundException()); + + memberEntity.setStatus(statusDto.getStatus()); + memberEntity.setUpdatedDttm(ZonedDateTime.now()); + membersRepository.save(memberEntity); + } + + /** + * 회원 탈퇴 + * + * @param statusDto + */ + public void deleteAccount(MembersDto.StatusDto statusDto) { + MemberEntity memberEntity = + membersRepository + .findByUUID(statusDto.getUuid()) + .orElseThrow(() -> new MemberNotFoundException()); + + MemberArchivedEntity memberArchivedEntity = new MemberArchivedEntity(); + memberArchivedEntity.setUuid(memberEntity.getUuid()); + memberArchivedEntity.setId(memberEntity.getId()); + memberArchivedEntity.setEmployeeNo(memberEntity.getEmployeeNo()); + memberArchivedEntity.setName(memberEntity.getName()); + memberArchivedEntity.setPassword(memberEntity.getPassword()); + memberArchivedEntity.setEmail(memberEntity.getEmail()); + memberArchivedEntity.setStatus(memberEntity.getStatus()); + memberArchivedEntity.setCreatedDttm(memberEntity.getCreatedDttm()); + memberArchivedEntity.setArchivedDttm(ZonedDateTime.now()); + memberArchivedRepository.save(memberArchivedEntity); + + memberEntity.setStatus("ARCHIVED"); + memberEntity.setName("**********"); + memberEntity.setEmployeeNo("**********"); + memberEntity.setPassword("**********"); + memberEntity.setEmail("**********"); + memberEntity.setUpdatedDttm(ZonedDateTime.now()); + membersRepository.save(memberEntity); + } + + /** + * 패스워드 초기화 + * + * @param id + */ + public void resetPassword(Long id) { + MemberEntity memberEntity = + membersRepository.findById(id).orElseThrow(() -> new MemberNotFoundException()); + + String salt = + BCryptSaltGenerator.generateSaltWithEmployeeNo(memberEntity.getEmployeeNo().trim()); + // 패스워드 암호화, 초기 패스워드 고정 + String hashedPassword = BCrypt.hashpw(password, salt); + + memberEntity.setPassword(hashedPassword); + memberEntity.setStatus("INACTIVE"); + memberEntity.setUpdatedDttm(ZonedDateTime.now()); + membersRepository.save(memberEntity); + } + /** * 회원목록 조회 * diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapInkx5kEntity.java b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapInkx5kEntity.java index 4e16d734..fe95b6d1 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapInkx5kEntity.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapInkx5kEntity.java @@ -1,6 +1,14 @@ package com.kamco.cd.kamcoback.postgres.entity; -import jakarta.persistence.*; +import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto; +import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.MapSheet; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; import lombok.Getter; import lombok.Setter; import org.locationtech.jts.geom.Geometry; @@ -10,6 +18,7 @@ import org.locationtech.jts.geom.Geometry; @Table(name = "tb_map_inkx_5k") @Entity public class MapInkx5kEntity { + @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "tb_map_inkx_5k_fid_seq_gen") @SequenceGenerator( @@ -29,4 +38,8 @@ public class MapInkx5kEntity { @Column(name = "fid_k50") private Long fidK50; + + public InferenceResultDto.MapSheet toEntity() { + return new MapSheet(mapidcdNo, mapidNm); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalDataGeomEntity.java b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalDataGeomEntity.java index 2eb3fd76..ac082886 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalDataGeomEntity.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalDataGeomEntity.java @@ -1,14 +1,21 @@ package com.kamco.cd.kamcoback.postgres.entity; +import com.kamco.cd.kamcoback.common.enums.DetectionClassification; +import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto; +import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.Clazzes; import jakarta.persistence.Column; import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; import jakarta.persistence.SequenceGenerator; import jakarta.persistence.Table; import jakarta.validation.constraints.Size; import java.time.ZonedDateTime; +import java.util.UUID; import lombok.Getter; import lombok.Setter; import org.hibernate.annotations.ColumnDefault; @@ -31,6 +38,9 @@ public class MapSheetAnalDataGeomEntity { @Column(name = "geo_uid", nullable = false) private Long id; + @Column(name = "uuid") + private UUID uuid; + @Column(name = "cd_prob") private Double cdProb; @@ -51,6 +61,10 @@ public class MapSheetAnalDataGeomEntity { @Column(name = "map_sheet_num") private Long mapSheetNum; + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "map_5k_id", referencedColumnName = "fid") + private MapInkx5kEntity map5k; + @Column(name = "compare_yyyy") private Integer compareYyyy; @@ -133,4 +147,21 @@ public class MapSheetAnalDataGeomEntity { @Column(name = "geom_center", columnDefinition = "geometry") private Geometry geomCenter; + + public InferenceResultDto.DetailListEntity toEntity() { + DetectionClassification classification = DetectionClassification.fromString(classBeforeCd); + Clazzes comparedClazz = new Clazzes(classification, classBeforeProb); + DetectionClassification classification1 = DetectionClassification.fromString(classAfterCd); + Clazzes targetClazz = new Clazzes(classification1, classAfterProb); + InferenceResultDto.MapSheet mapSheet = map5k != null ? map5k.toEntity() : null; + + InferenceResultDto.Coordinate coordinate = null; + if (geomCenter != null) { + org.locationtech.jts.geom.Point point = (org.locationtech.jts.geom.Point) geomCenter; + coordinate = new InferenceResultDto.Coordinate(point.getX(), point.getY()); + } + + return new InferenceResultDto.DetailListEntity( + uuid, cdProb, comparedClazz, targetClazz, mapSheet, coordinate, createdDttm); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalEntity.java b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalEntity.java index 440af411..b2aeaf6d 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalEntity.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalEntity.java @@ -9,7 +9,9 @@ import jakarta.persistence.SequenceGenerator; import jakarta.persistence.Table; import jakarta.validation.constraints.Size; import java.time.ZonedDateTime; +import lombok.AccessLevel; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import org.hibernate.annotations.ColumnDefault; @@ -17,6 +19,9 @@ import org.hibernate.annotations.ColumnDefault; @Setter @Entity @Table(name = "tb_map_sheet_anal") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +// TODO SETTER 제거 +// TODO 주석 public class MapSheetAnalEntity { @Id @@ -28,21 +33,24 @@ public class MapSheetAnalEntity { @Column(name = "anal_uid", nullable = false) private Long id; + // TODO UUID + // UK 추가 + @Column(name = "compare_yyyy") - private Integer compareYyyy; + private Integer compareYyyy; // 비교년도 @Column(name = "target_yyyy") - private Integer targetYyyy; + private Integer targetYyyy; // 기분년도 @Column(name = "model_uid") - private Long modelUid; + private Long modelUid; // 모델식별키 ? @Size(max = 100) @Column(name = "server_ids", length = 100) - private String serverIds; + private String serverIds; // 서버ID? @Column(name = "anal_map_sheet", length = Integer.MAX_VALUE) - private String analMapSheet; + private String analMapSheet; // 분석도엽? @Column(name = "anal_strt_dttm") private ZonedDateTime analStrtDttm; @@ -54,15 +62,15 @@ public class MapSheetAnalEntity { private Long analSec; @Column(name = "anal_pred_sec") - private Long analPredSec; + private Long analPredSec; // 예상소요초? @Size(max = 20) @Column(name = "anal_state", length = 20) - private String analState; + private String analState; // enum 으로 관리 @Size(max = 20) @Column(name = "gukyuin_used", length = 20) - private String gukyuinUsed; + private String gukyuinUsed; // Boolean으로 관리 @Column(name = "accuracy") private Double accuracy; @@ -71,17 +79,9 @@ public class MapSheetAnalEntity { @Column(name = "result_url") private String resultUrl; - @ColumnDefault("now()") - @Column(name = "created_dttm") - private ZonedDateTime createdDttm; - @Column(name = "created_uid") private Long createdUid; - @ColumnDefault("now()") - @Column(name = "updated_dttm") - private ZonedDateTime updatedDttm; - @Column(name = "updated_uid") private Long updatedUid; @@ -94,4 +94,13 @@ public class MapSheetAnalEntity { @Column(name = "base_map_sheet_num") private String baseMapSheetNum; + + // TODO CommonDateEntity ? + @ColumnDefault("now()") + @Column(name = "created_dttm") + private ZonedDateTime createdDttm; + + @ColumnDefault("now()") + @Column(name = "updated_dttm") + private ZonedDateTime updatedDttm; } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetMngEntity.java b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetMngEntity.java index 29b6a41e..68adf025 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetMngEntity.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetMngEntity.java @@ -50,5 +50,4 @@ public class MapSheetMngEntity { @ColumnDefault("'NULL::character varying'") @Column(name = "mng_path") private String mngPath; - } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MemberArchivedEntity.java b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MemberArchivedEntity.java index 1f10b518..a4d22886 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MemberArchivedEntity.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MemberArchivedEntity.java @@ -6,7 +6,7 @@ import jakarta.persistence.Id; import jakarta.persistence.Table; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; -import java.time.OffsetDateTime; +import java.time.ZonedDateTime; import java.util.UUID; import lombok.Getter; import lombok.Setter; @@ -20,11 +20,10 @@ public class MemberArchivedEntity { @Id @Column(name = "uuid", nullable = false) - private UUID id; + private UUID uuid; - @NotNull @Column(name = "id", nullable = false) - private Long id1; + private Long id; @Size(max = 50) @Column(name = "employee_no", length = 50) @@ -51,10 +50,10 @@ public class MemberArchivedEntity { @NotNull @Column(name = "created_dttm", nullable = false) - private OffsetDateTime createdDttm; + private ZonedDateTime createdDttm; @NotNull @ColumnDefault("now()") @Column(name = "archived_dttm", nullable = false) - private OffsetDateTime archivedDttm; + private ZonedDateTime archivedDttm; } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MemberEntity.java b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MemberEntity.java index 861c4ab7..744bd78b 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MemberEntity.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MemberEntity.java @@ -50,9 +50,9 @@ public class MemberEntity { private String email; @Size(max = 20) - @ColumnDefault("'ACTIVE'") + @ColumnDefault("'INACTIVE'") @Column(name = "status", length = 20) - private String status = "ACTIVE"; + private String status = "INACTIVE"; @Column(name = "created_dttm", nullable = false, insertable = false) private ZonedDateTime createdDttm; diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepositoryCustom.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepositoryCustom.java index 629d4ef9..7b9ac305 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepositoryCustom.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepositoryCustom.java @@ -2,6 +2,10 @@ package com.kamco.cd.kamcoback.postgres.repository.Inference; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.Dashboard; +import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.SearchGeoReq; +import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataEntity; +import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataGeomEntity; +import jakarta.validation.constraints.NotNull; import java.util.List; import java.util.Optional; import org.springframework.data.domain.Page; @@ -16,7 +20,12 @@ public interface InferenceResultRepositoryCustom { Page getInferenceGeomList( Long id, InferenceResultDto.SearchGeoReq searchGeoReq); + Page listInferenceResultWithGeom( + List dataIds, SearchGeoReq searchReq); + List getSheets(Long id); List getDashboard(Long id); + + List listAnalyGeom(@NotNull Long id); } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepositoryImpl.java index 8582414b..dfcab8d6 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepositoryImpl.java @@ -3,6 +3,8 @@ package com.kamco.cd.kamcoback.postgres.repository.Inference; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.Dashboard; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.SearchGeoReq; +import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataEntity; +import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataGeomEntity; import com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalDataEntity; import com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalDataGeomEntity; import com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalEntity; @@ -10,17 +12,23 @@ import com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalSttcEntity; import com.kamco.cd.kamcoback.postgres.entity.QModelMngEntity; import com.kamco.cd.kamcoback.postgres.entity.QModelVerEntity; import com.querydsl.core.BooleanBuilder; +import com.querydsl.core.types.Order; +import com.querydsl.core.types.OrderSpecifier; import com.querydsl.core.types.Projections; +import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.core.types.dsl.Expressions; import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.JPQLQuery; +import com.querydsl.jpa.impl.JPAQuery; import com.querydsl.jpa.impl.JPAQueryFactory; +import java.util.ArrayList; import java.util.List; import java.util.Optional; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; import org.springframework.stereotype.Repository; @Repository @@ -80,7 +88,7 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC .where(builder) .offset(pageable.getOffset()) .limit(pageable.getPageSize()) - .orderBy(mapSheetAnalEntity.createdDttm.desc()) + .orderBy(mapSheetAnalEntity.id.desc()) .fetch(); long total = @@ -159,6 +167,56 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC .fetch(); } + @Override + public List listAnalyGeom(Long id) { + QMapSheetAnalDataEntity analy = QMapSheetAnalDataEntity.mapSheetAnalDataEntity; + return queryFactory.selectFrom(analy).where(analy.analUid.eq(id)).fetch(); + } + + /** + * 분석결과 상세 목록 + * + * @param searchReq + * @return + */ + @Override + public Page listInferenceResultWithGeom( + List ids, SearchGeoReq searchReq) { + + // 분석 차수 + QMapSheetAnalDataGeomEntity detectedEntity = + QMapSheetAnalDataGeomEntity.mapSheetAnalDataGeomEntity; + Pageable pageable = searchReq.toPageable(); + + // 검색조건 + JPAQuery query = + queryFactory + .selectFrom(detectedEntity) + .where( + detectedEntity.dataUid.in(ids), + eqTargetClass(detectedEntity, searchReq.getTargetClass()), + eqCompareClass(detectedEntity, searchReq.getCompareClass()), + containsMapSheetNum(detectedEntity, searchReq.getMapSheetNum())); + + // count + long total = query.fetchCount(); + + // Pageable에서 정렬 가져오기, 없으면 기본 정렬(createdDttm desc) 사용 + List> orders = getOrderSpecifiers(pageable.getSort()); + if (orders.isEmpty()) { + orders.add(detectedEntity.createdDttm.desc()); + } + + List content = + query + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .orderBy(orders.toArray(new OrderSpecifier[0])) + .fetch(); + + return new PageImpl<>(content, pageable, total); + } + /** * 분석결과 상세 목록 * @@ -252,4 +310,61 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC .groupBy(mapSheetAnalDataEntity.mapSheetNum) .fetch(); } + + /** Pageable의 Sort를 QueryDSL OrderSpecifier로 변환 */ + @SuppressWarnings({"unchecked", "rawtypes"}) + private List> getOrderSpecifiers(Sort sort) { + List> orders = new ArrayList<>(); + + if (sort.isSorted()) { + QMapSheetAnalDataGeomEntity entity = QMapSheetAnalDataGeomEntity.mapSheetAnalDataGeomEntity; + + for (Sort.Order order : sort) { + Order direction = order.isAscending() ? Order.ASC : Order.DESC; + String property = order.getProperty(); + + // 유효한 필드만 처리 + switch (property) { + case "classBeforeCd" -> orders.add(new OrderSpecifier(direction, entity.classBeforeCd)); + case "classBeforeProb" -> + orders.add(new OrderSpecifier(direction, entity.classBeforeProb)); + case "classAfterCd" -> orders.add(new OrderSpecifier(direction, entity.classAfterCd)); + case "classAfterProb" -> orders.add(new OrderSpecifier(direction, entity.classAfterProb)); + case "mapSheetNum" -> orders.add(new OrderSpecifier(direction, entity.mapSheetNum)); + case "compareYyyy" -> orders.add(new OrderSpecifier(direction, entity.compareYyyy)); + case "targetYyyy" -> orders.add(new OrderSpecifier(direction, entity.targetYyyy)); + case "area" -> orders.add(new OrderSpecifier(direction, entity.area)); + case "createdDttm" -> orders.add(new OrderSpecifier(direction, entity.createdDttm)); + case "updatedDttm" -> orders.add(new OrderSpecifier(direction, entity.updatedDttm)); + // 유효하지 않은 필드는 무시 + default -> {} + } + } + } + + return orders; + } + + private BooleanExpression eqTargetClass( + QMapSheetAnalDataGeomEntity detectedEntity, String targetClass) { + return targetClass != null && !targetClass.isEmpty() + ? detectedEntity.classAfterCd.toLowerCase().eq(targetClass.toLowerCase()) + : null; + } + + private BooleanExpression eqCompareClass( + QMapSheetAnalDataGeomEntity detectedEntity, String compareClass) { + return compareClass != null && !compareClass.isEmpty() + ? detectedEntity.classBeforeCd.toLowerCase().eq(compareClass.toLowerCase()) + : null; + } + + private BooleanExpression containsMapSheetNum( + QMapSheetAnalDataGeomEntity detectedEntity, List mapSheet) { + if (mapSheet == null || mapSheet.isEmpty()) { + return null; + } + + return detectedEntity.mapSheetNum.in(mapSheet); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/changedetection/ChangeDetectionRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/changedetection/ChangeDetectionRepositoryImpl.java index 19c68005..cf700729 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/changedetection/ChangeDetectionRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/changedetection/ChangeDetectionRepositoryImpl.java @@ -126,7 +126,8 @@ public class ChangeDetectionRepositoryImpl extends QuerydslRepositorySupport mapSheetAnalDataGeomEntity.classBeforeCd.toUpperCase(), mapSheetAnalDataGeomEntity.targetYyyy, mapSheetAnalDataGeomEntity.classAfterProb, - mapSheetAnalDataGeomEntity.classAfterCd.toUpperCase())) + mapSheetAnalDataGeomEntity.classAfterCd.toUpperCase(), + mapSheetAnalDataGeomEntity.cdProb)) .from(mapSheetAnalDataGeomEntity) .innerJoin(mapSheetAnalDataEntity) .on(mapSheetAnalDataGeomEntity.dataUid.eq(mapSheetAnalDataEntity.id)) @@ -159,7 +160,8 @@ public class ChangeDetectionRepositoryImpl extends QuerydslRepositorySupport data.getBeforeClass(), data.getAfterYear(), data.getAfterConfidence(), - data.getAfterClass()); + data.getAfterClass(), + data.getCdProb()); return new ChangeDetectionDto.PolygonFeature( data.getType(), jsonNode, properties); 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 6f23bb80..40450249 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 @@ -5,8 +5,8 @@ import jakarta.validation.Valid; import org.springframework.data.domain.Page; public interface MapSheetMngRepositoryCustom { - Page findMapSheetErrorList(MapSheetMngDto.@Valid searchReq searchReq); + Page findMapSheetErrorList( + MapSheetMngDto.@Valid searchReq searchReq); Page findMapSheetMngList(MapSheetMngDto.@Valid searchReq searchReq); - } 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 4119a5bc..41669a4c 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 @@ -1,10 +1,13 @@ package com.kamco.cd.kamcoback.postgres.repository.mapsheet; +import static com.kamco.cd.kamcoback.postgres.entity.QMapInkx50kEntity.mapInkx50kEntity; +import static com.kamco.cd.kamcoback.postgres.entity.QMapInkx5kEntity.mapInkx5kEntity; +import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetMngEntity.mapSheetMngEntity; +import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetMngHstEntity.mapSheetMngHstEntity; + import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto; -import com.kamco.cd.kamcoback.members.dto.RoleType; import com.kamco.cd.kamcoback.postgres.entity.MapSheetMngHstEntity; import com.querydsl.core.BooleanBuilder; -import com.querydsl.core.types.Expression; import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.core.types.dsl.Expressions; @@ -12,23 +15,16 @@ import com.querydsl.core.types.dsl.NumberExpression; import com.querydsl.core.types.dsl.StringExpression; import com.querydsl.jpa.impl.JPAQueryFactory; import jakarta.validation.Valid; -import jdk.jfr.Experimental; +import java.util.List; +import java.util.Objects; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport; -import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetMngHstEntity.mapSheetMngHstEntity; -import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetMngEntity.mapSheetMngEntity; -import static com.kamco.cd.kamcoback.postgres.entity.QMapInkx5kEntity.mapInkx5kEntity; -import static com.kamco.cd.kamcoback.postgres.entity.QMapInkx50kEntity.mapInkx50kEntity; - -import java.util.List; -import java.util.Objects; - public class MapSheetMngRepositoryImpl extends QuerydslRepositorySupport - implements MapSheetMngRepositoryCustom { + implements MapSheetMngRepositoryCustom { private final JPAQueryFactory queryFactory; private final StringExpression NULL_STRING = Expressions.stringTemplate("cast(null as text)"); @@ -39,101 +35,112 @@ public class MapSheetMngRepositoryImpl extends QuerydslRepositorySupport } @Override - public Page findMapSheetErrorList(MapSheetMngDto.@Valid searchReq searchReq) { + public Page findMapSheetErrorList( + MapSheetMngDto.@Valid searchReq searchReq) { Pageable pageable = PageRequest.of(searchReq.getPage(), searchReq.getSize()); - List foundContent = queryFactory - .select( - Projections.constructor( - MapSheetMngDto.ErrorDataDto.class, - mapSheetMngHstEntity.hstUid, - rowNum(), - Expressions.stringTemplate("concat({0}, {1})", mapSheetMngHstEntity.mapSheetName, mapInkx50kEntity.mapidcdNo), - Expressions.stringTemplate("concat({0}, substring({1}, {2}, {3}))", mapSheetMngHstEntity.mapSheetName, mapSheetMngHstEntity.mapSheetNum, 6, 8), - mapSheetMngHstEntity.mapSheetCodeSrc, - Expressions.stringTemplate("to_char({0}, 'YYYY-MM-DD')", mapSheetMngHstEntity.createdDate), - mapSheetMngHstEntity.dataState - ) - ) - .from(mapSheetMngHstEntity) - .innerJoin(mapInkx5kEntity) - .on(mapSheetMngHstEntity.mapSheetCode.eq(mapInkx5kEntity.fid)) - .leftJoin(mapInkx50kEntity) - .on(mapInkx5kEntity.fidK50.eq(mapInkx50kEntity.fid.longValue())) - .where( - mapSheetMngHstEntity.mngYyyy.eq(searchReq.getMngYyyy()), - mapSheetMngHstEntity.dataState.eq(MapSheetMngDto.DataState.FAIL), //오류만 검색 - mapSheetErrorSearchValue(searchReq) - ) - .offset(pageable.getOffset()) - .limit(pageable.getPageSize()) - .orderBy(mapSheetMngHstEntity.createdDate.desc()) - .fetch(); + List foundContent = + queryFactory + .select( + Projections.constructor( + MapSheetMngDto.ErrorDataDto.class, + mapSheetMngHstEntity.hstUid, + rowNum(), + Expressions.stringTemplate( + "concat({0}, {1})", + mapSheetMngHstEntity.mapSheetName, mapInkx50kEntity.mapidcdNo), + Expressions.stringTemplate( + "concat({0}, substring({1}, {2}, {3}))", + mapSheetMngHstEntity.mapSheetName, mapSheetMngHstEntity.mapSheetNum, 6, 8), + mapSheetMngHstEntity.mapSheetCodeSrc, + Expressions.stringTemplate( + "to_char({0}, 'YYYY-MM-DD')", mapSheetMngHstEntity.createdDate), + mapSheetMngHstEntity.dataState)) + .from(mapSheetMngHstEntity) + .innerJoin(mapInkx5kEntity) + .on(mapSheetMngHstEntity.mapSheetCode.eq(mapInkx5kEntity.fid)) + .leftJoin(mapInkx50kEntity) + .on(mapInkx5kEntity.fidK50.eq(mapInkx50kEntity.fid.longValue())) + .where( + mapSheetMngHstEntity.mngYyyy.eq(searchReq.getMngYyyy()), + mapSheetMngHstEntity.dataState.eq(MapSheetMngDto.DataState.FAIL), // 오류만 검색 + mapSheetErrorSearchValue(searchReq)) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .orderBy(mapSheetMngHstEntity.createdDate.desc()) + .fetch(); - Long countQuery = queryFactory - .select(mapSheetMngHstEntity.hstUid.count()) - .from(mapSheetMngHstEntity) - .innerJoin(mapInkx5kEntity) - .on(mapSheetMngHstEntity.mapSheetCode.eq(mapInkx5kEntity.fid)) - .leftJoin(mapInkx50kEntity) - .on(mapInkx5kEntity.fidK50.eq(mapInkx50kEntity.fid.longValue())) - .where( - mapSheetMngHstEntity.mngYyyy.eq(searchReq.getMngYyyy()), - mapSheetMngHstEntity.dataState.eq(MapSheetMngDto.DataState.FAIL), //오류만 검색 - mapSheetErrorSearchValue(searchReq) - ) - .fetchOne(); + Long countQuery = + queryFactory + .select(mapSheetMngHstEntity.hstUid.count()) + .from(mapSheetMngHstEntity) + .innerJoin(mapInkx5kEntity) + .on(mapSheetMngHstEntity.mapSheetCode.eq(mapInkx5kEntity.fid)) + .leftJoin(mapInkx50kEntity) + .on(mapInkx5kEntity.fidK50.eq(mapInkx50kEntity.fid.longValue())) + .where( + mapSheetMngHstEntity.mngYyyy.eq(searchReq.getMngYyyy()), + mapSheetMngHstEntity.dataState.eq(MapSheetMngDto.DataState.FAIL), // 오류만 검색 + mapSheetErrorSearchValue(searchReq)) + .fetchOne(); return new PageImpl<>(foundContent, pageable, countQuery); } - @Override - public Page findMapSheetMngList(MapSheetMngDto.@Valid searchReq searchReq) { + public Page findMapSheetMngList( + MapSheetMngDto.@Valid searchReq searchReq) { Pageable pageable = searchReq.toPageable(); BooleanBuilder whereBuilder = new BooleanBuilder(); - if (searchReq.getMngYyyy() != null ) { + if (searchReq.getMngYyyy() != null) { whereBuilder.and(mapSheetMngEntity.id.eq(searchReq.getMngYyyy())); } - List foundContent = queryFactory - .select( - Projections.constructor( - MapSheetMngDto.MngDto.class, - Expressions.numberTemplate(Integer.class, "row_number() over(order by {0} desc)", mapSheetMngEntity.createdDttm), - mapSheetMngEntity.id, - mapSheetMngEntity.mngState, - mapSheetMngEntity.syncState, - Expressions.stringTemplate("to_char({0}, 'YYYY-MM-DD HH24:MI:SS')", mapSheetMngEntity.mngStateDttm), - Expressions.stringTemplate("to_char({0}, 'YYYY-MM-DD HH24:MI:SS')", mapSheetMngEntity.syncStateDttm), - mapSheetMngEntity.mngPath, - Expressions.stringTemplate("to_char({0}, 'YYYY-MM-DD HH24:MI:SS')", mapSheetMngEntity.createdDttm), - mapSheetMngEntity.createdUid, - Expressions.stringTemplate("to_char({0}, 'YYYY-MM-DD HH24:MI:SS')", mapSheetMngEntity.updatedDttm), - mapSheetMngEntity.updatedUid + List foundContent = + queryFactory + .select( + Projections.constructor( + MapSheetMngDto.MngDto.class, + Expressions.numberTemplate( + Integer.class, + "row_number() over(order by {0} desc)", + mapSheetMngEntity.createdDttm), + mapSheetMngEntity.id, + mapSheetMngEntity.mngState, + mapSheetMngEntity.syncState, + Expressions.stringTemplate( + "to_char({0}, 'YYYY-MM-DD HH24:MI:SS')", mapSheetMngEntity.mngStateDttm), + Expressions.stringTemplate( + "to_char({0}, 'YYYY-MM-DD HH24:MI:SS')", mapSheetMngEntity.syncStateDttm), + mapSheetMngEntity.mngPath, + Expressions.stringTemplate( + "to_char({0}, 'YYYY-MM-DD HH24:MI:SS')", mapSheetMngEntity.createdDttm), + mapSheetMngEntity.createdUid, + Expressions.stringTemplate( + "to_char({0}, 'YYYY-MM-DD HH24:MI:SS')", mapSheetMngEntity.updatedDttm), + mapSheetMngEntity.updatedUid)) + .from(mapSheetMngEntity) + .where(whereBuilder) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .orderBy(mapSheetMngEntity.createdDttm.desc()) + .fetch(); - ) - ) - .from(mapSheetMngEntity) - .where(whereBuilder) - .offset(pageable.getOffset()) - .limit(pageable.getPageSize()) - .orderBy(mapSheetMngEntity.createdDttm.desc()) - .fetch(); - - Long countQuery = queryFactory - .select(mapSheetMngEntity.id.count()) - .from(mapSheetMngEntity) - .where(whereBuilder) - .fetchOne(); + Long countQuery = + queryFactory + .select(mapSheetMngEntity.id.count()) + .from(mapSheetMngEntity) + .where(whereBuilder) + .fetchOne(); return new PageImpl<>(foundContent, pageable, countQuery); } - private NumberExpression rowNum(){ - return Expressions.numberTemplate(Integer.class, "row_number() over(order by {0} desc)", mapSheetMngHstEntity.createdDate); + private NumberExpression rowNum() { + return Expressions.numberTemplate( + Integer.class, "row_number() over(order by {0} desc)", mapSheetMngHstEntity.createdDate); } private BooleanExpression mapSheetErrorSearchValue(MapSheetMngDto.searchReq searchReq) { @@ -142,10 +149,11 @@ public class MapSheetMngRepositoryImpl extends QuerydslRepositorySupport } // 검색어 1개 값이 도엽명 or 도엽번호 like 검색 - return Expressions.booleanTemplate("{0} like '%" + searchReq.getSearchValue() + "%'", mapSheetMngHstEntity.mapSheetName) - .or(Expressions.booleanTemplate("{0} like '%" + searchReq.getSearchValue() + "%'", mapSheetMngHstEntity.mapSheetNum)); + return Expressions.booleanTemplate( + "{0} like '%" + searchReq.getSearchValue() + "%'", mapSheetMngHstEntity.mapSheetName) + .or( + Expressions.booleanTemplate( + "{0} like '%" + searchReq.getSearchValue() + "%'", + mapSheetMngHstEntity.mapSheetNum)); } - - - } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/members/MembersArchivedRepository.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/members/MembersArchivedRepository.java new file mode 100644 index 00000000..f674888f --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/members/MembersArchivedRepository.java @@ -0,0 +1,7 @@ +package com.kamco.cd.kamcoback.postgres.repository.members; + +import com.kamco.cd.kamcoback.postgres.entity.MemberArchivedEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface MembersArchivedRepository + extends JpaRepository, MembersArchivedRepositoryCustom {} diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/members/MembersArchivedRepositoryCustom.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/members/MembersArchivedRepositoryCustom.java new file mode 100644 index 00000000..65846fcc --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/members/MembersArchivedRepositoryCustom.java @@ -0,0 +1,3 @@ +package com.kamco.cd.kamcoback.postgres.repository.members; + +public interface MembersArchivedRepositoryCustom {} diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/members/MembersArchivedRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/members/MembersArchivedRepositoryImpl.java new file mode 100644 index 00000000..4802a918 --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/members/MembersArchivedRepositoryImpl.java @@ -0,0 +1,6 @@ +package com.kamco.cd.kamcoback.postgres.repository.members; + +import org.springframework.stereotype.Repository; + +@Repository +public class MembersArchivedRepositoryImpl implements MembersArchivedRepositoryCustom {} diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/scene/MapInkx5kRepository.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/scene/MapInkx5kRepository.java new file mode 100644 index 00000000..0e6e58ee --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/scene/MapInkx5kRepository.java @@ -0,0 +1,7 @@ +package com.kamco.cd.kamcoback.postgres.repository.scene; + +import com.kamco.cd.kamcoback.postgres.entity.MapInkx5kEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface MapInkx5kRepository + extends JpaRepository, MapInkx5kRepositoryCustom {} diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/scene/MapInkx5kRepositoryCustom.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/scene/MapInkx5kRepositoryCustom.java new file mode 100644 index 00000000..e509aaeb --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/scene/MapInkx5kRepositoryCustom.java @@ -0,0 +1,9 @@ +package com.kamco.cd.kamcoback.postgres.repository.scene; + +import com.kamco.cd.kamcoback.postgres.entity.MapInkx5kEntity; +import java.util.List; + +public interface MapInkx5kRepositoryCustom { + + List listGetScenes5k(List codes); +} diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/scene/MapInkx5kRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/scene/MapInkx5kRepositoryImpl.java new file mode 100644 index 00000000..21fe09ea --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/scene/MapInkx5kRepositoryImpl.java @@ -0,0 +1,28 @@ +package com.kamco.cd.kamcoback.postgres.repository.scene; + +import com.kamco.cd.kamcoback.postgres.entity.MapInkx5kEntity; +import com.kamco.cd.kamcoback.postgres.entity.QMapInkx5kEntity; +import com.querydsl.jpa.impl.JPAQueryFactory; +import java.util.List; +import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport; + +public class MapInkx5kRepositoryImpl extends QuerydslRepositorySupport + implements MapInkx5kRepositoryCustom { + + private final JPAQueryFactory queryFactory; + + public MapInkx5kRepositoryImpl(JPAQueryFactory queryFactory) { + super(MapInkx5kEntity.class); + this.queryFactory = queryFactory; + } + + public List listGetScenes5k(List codes) { + QMapInkx5kEntity map5k = QMapInkx5kEntity.mapInkx5kEntity; + + return queryFactory + .selectFrom(map5k) + .where(map5k.mapidcdNo.in(codes)) + .orderBy(map5k.mapidcdNo.asc()) + .fetch(); + } +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 7e6d6dec..bef17c2d 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -34,3 +34,6 @@ spring: host: 192.168.2.109 port: 6379 password: kamco + +member: + init_password: kamco1234! diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index 07d1eaea..cbf7507c 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -16,6 +16,7 @@ spring: datasource: 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: @@ -28,3 +29,6 @@ spring: port: 6379 password: kamco +member: + init_password: kamco1234! + diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index ab445619..7ff30470 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -21,4 +21,7 @@ spring: minimum-idle: 10 maximum-pool-size: 20 +member: + init_password: kamco1234! +