Merge remote-tracking branch 'origin/feat/dev_251201' into feat/dev_251201

This commit is contained in:
Harry M. You
2025-12-03 14:47:35 +09:00
40 changed files with 1097 additions and 214 deletions

View File

@@ -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; // 탐지 정확도
}
}

View File

@@ -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) {

View File

@@ -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<List<InferenceResultDto.Clazzes>> getClasses() {
List<Clazzes> list =
Arrays.stream(DetectionClassification.values())
.sorted(Comparator.comparingInt(DetectionClassification::getOrder))
.map(Clazzes::new)
.toList();
return ApiResponseDto.ok(list);
}
}

View File

@@ -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<List<MapSheet>> listGetScenes5k(
@Parameter(description = "분석결과 id", example = "1") @PathVariable Long id) {
List<MapSheet> mapSheets = inferenceResultService.listGetScenes5k(id);
return ApiResponseDto.ok(mapSheets);
}
}

View File

@@ -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

View File

@@ -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<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> 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();
}

View File

@@ -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<Page<InferenceResultDto.DetailListEntity>> 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<Long> 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<InferenceResultDto.DetailListEntity> geomList =
inferenceResultService.listInferenceResultWithGeom(id, searchGeoReq);
return ApiResponseDto.ok(geomList);
}
}

View File

@@ -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 {

View File

@@ -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<InferenceResultDto.DetailListEntity> listInferenceResultWithGeom(
@NotNull Long id, InferenceResultDto.SearchGeoReq searchReq) {
return inferenceResultCoreService.listInferenceResultWithGeom(id, searchReq);
}
/**
* 분석결과 상제 정보 Summary, DashBoard
*
@@ -87,4 +101,8 @@ public class InferenceResultService {
public List<String> getSheets(Long id) {
return inferenceResultCoreService.getSheets(id).stream().map(String::valueOf).toList();
}
public List<MapSheet> listGetScenes5k(Long id) {
return inferenceResultCoreService.listGetScenes5k(id);
}
}

View File

@@ -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<List<FileDto.FolderDto>> getDir(
@RequestBody SrchFoldersDto srchDto
) {
public ApiResponseDto<List<FileDto.FolderDto>> 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<FilesDto> getFiles(
@RequestBody SrchFilesDto srchDto
) {
public ApiResponseDto<FilesDto> getFiles(@RequestBody SrchFilesDto srchDto) {
return ApiResponseDto.createOK(mapSheetMngService.getFilesAll(srchDto));
}
/**
* 오류데이터 목록 조회
*
* @param searchReq
* @return
*/
@PostMapping("/error-list")
public ApiResponseDto<Page<MapSheetMngDto.ErrorDataDto>> 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<Page<MapSheetMngDto.MngDto>> findMapSheetMngList(
@RequestBody
@Valid
MapSheetMngDto.searchReq searchReq
){
@RequestBody @Valid MapSheetMngDto.searchReq searchReq) {
return ApiResponseDto.ok(mapSheetMngService.findMapSheetMngList(searchReq));
}
}

View File

@@ -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

View File

@@ -164,7 +164,8 @@ public class MapSheetMngService {
return mapSheetMngCoreService.findMapSheetErrorList(searchReq);
}
public Page<MapSheetMngDto.MngDto> findMapSheetMngList(MapSheetMngDto.@Valid searchReq searchReq) {
public Page<MapSheetMngDto.MngDto> findMapSheetMngList(
MapSheetMngDto.@Valid searchReq searchReq) {
return mapSheetMngCoreService.findMapSheetMngList(searchReq);
}
}

View File

@@ -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<Long> 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<UUID> 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<UUID> 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<Long> resetPassword(@PathVariable Long memberId) {
adminService.resetPassword(memberId);
return ApiResponseDto.createOK(memberId);
}
}

View File

@@ -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<Page<Basic>> 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<UUID> updateMember(
@PathVariable UUID uuid, @RequestBody MembersDto.UpdateReq updateReq) {
membersService.updateMember(uuid, updateReq);
return ApiResponseDto.createOK(uuid);
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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<Basic> 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);
}
}

View File

@@ -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<InferenceResultDto.DetailListEntity> listInferenceResultWithGeom(
@NotNull Long analyId, InferenceResultDto.SearchGeoReq searchReq) {
// 분석 ID 에 해당하는 dataids를 가져온다.
List<Long> dataIds =
inferenceResultRepository.listAnalyGeom(analyId).stream()
.mapToLong(MapSheetAnalDataEntity::getId)
.boxed()
.toList();
// 해당데이터의 폴리곤데이터를 가져온다
Page<MapSheetAnalDataGeomEntity> mapSheetAnalDataGeomEntities =
inferenceResultRepository.listInferenceResultWithGeom(dataIds, searchReq);
return mapSheetAnalDataGeomEntities.map(MapSheetAnalDataGeomEntity::toEntity);
}
/**
* 추론된 5000:1 도엽 목록
*
@@ -70,4 +99,17 @@ public class InferenceResultCoreService {
public List<Long> getSheets(Long id) {
return inferenceResultRepository.getSheets(id);
}
@Transactional(readOnly = true)
public List<MapSheet> listGetScenes5k(Long analyId) {
List<String> sceneCodes =
inferenceResultRepository.listAnalyGeom(analyId).stream()
.mapToLong(MapSheetAnalDataEntity::getMapSheetNum)
.mapToObj(String::valueOf)
.toList();
return mapInkx5kRepository.listGetScenes5k(sceneCodes).stream()
.map(MapInkx5kEntity::toEntity)
.toList();
}
}

View File

@@ -18,7 +18,8 @@ public class MapSheetMngCoreService {
return mapSheetMngRepository.findMapSheetErrorList(searchReq);
}
public Page<MapSheetMngDto.MngDto> findMapSheetMngList(MapSheetMngDto.@Valid searchReq searchReq) {
public Page<MapSheetMngDto.MngDto> findMapSheetMngList(
MapSheetMngDto.@Valid searchReq searchReq) {
return mapSheetMngRepository.findMapSheetMngList(searchReq);
}
}

View File

@@ -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);
}
/**
* 회원목록 조회
*

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -50,5 +50,4 @@ public class MapSheetMngEntity {
@ColumnDefault("'NULL::character varying'")
@Column(name = "mng_path")
private String mngPath;
}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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<InferenceResultDto.Geom> getInferenceGeomList(
Long id, InferenceResultDto.SearchGeoReq searchGeoReq);
Page<MapSheetAnalDataGeomEntity> listInferenceResultWithGeom(
List<Long> dataIds, SearchGeoReq searchReq);
List<Long> getSheets(Long id);
List<Dashboard> getDashboard(Long id);
List<MapSheetAnalDataEntity> listAnalyGeom(@NotNull Long id);
}

View File

@@ -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<MapSheetAnalDataEntity> listAnalyGeom(Long id) {
QMapSheetAnalDataEntity analy = QMapSheetAnalDataEntity.mapSheetAnalDataEntity;
return queryFactory.selectFrom(analy).where(analy.analUid.eq(id)).fetch();
}
/**
* 분석결과 상세 목록
*
* @param searchReq
* @return
*/
@Override
public Page<MapSheetAnalDataGeomEntity> listInferenceResultWithGeom(
List<Long> ids, SearchGeoReq searchReq) {
// 분석 차수
QMapSheetAnalDataGeomEntity detectedEntity =
QMapSheetAnalDataGeomEntity.mapSheetAnalDataGeomEntity;
Pageable pageable = searchReq.toPageable();
// 검색조건
JPAQuery<MapSheetAnalDataGeomEntity> 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<OrderSpecifier<?>> orders = getOrderSpecifiers(pageable.getSort());
if (orders.isEmpty()) {
orders.add(detectedEntity.createdDttm.desc());
}
List<MapSheetAnalDataGeomEntity> 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<OrderSpecifier<?>> getOrderSpecifiers(Sort sort) {
List<OrderSpecifier<?>> 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<Long> mapSheet) {
if (mapSheet == null || mapSheet.isEmpty()) {
return null;
}
return detectedEntity.mapSheetNum.in(mapSheet);
}
}

View File

@@ -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);

View File

@@ -5,8 +5,8 @@ import jakarta.validation.Valid;
import org.springframework.data.domain.Page;
public interface MapSheetMngRepositoryCustom {
Page<MapSheetMngDto.ErrorDataDto> findMapSheetErrorList(MapSheetMngDto.@Valid searchReq searchReq);
Page<MapSheetMngDto.ErrorDataDto> findMapSheetErrorList(
MapSheetMngDto.@Valid searchReq searchReq);
Page<MapSheetMngDto.MngDto> findMapSheetMngList(MapSheetMngDto.@Valid searchReq searchReq);
}

View File

@@ -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<MapSheetMngDto.ErrorDataDto> findMapSheetErrorList(MapSheetMngDto.@Valid searchReq searchReq) {
public Page<MapSheetMngDto.ErrorDataDto> findMapSheetErrorList(
MapSheetMngDto.@Valid searchReq searchReq) {
Pageable pageable = PageRequest.of(searchReq.getPage(), searchReq.getSize());
List<MapSheetMngDto.ErrorDataDto> 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<MapSheetMngDto.ErrorDataDto> 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<MapSheetMngDto.MngDto> findMapSheetMngList(MapSheetMngDto.@Valid searchReq searchReq) {
public Page<MapSheetMngDto.MngDto> 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<MapSheetMngDto.MngDto> 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<MapSheetMngDto.MngDto> 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<Integer> rowNum(){
return Expressions.numberTemplate(Integer.class, "row_number() over(order by {0} desc)", mapSheetMngHstEntity.createdDate);
private NumberExpression<Integer> 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));
}
}

View File

@@ -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<MemberArchivedEntity, Long>, MembersArchivedRepositoryCustom {}

View File

@@ -0,0 +1,3 @@
package com.kamco.cd.kamcoback.postgres.repository.members;
public interface MembersArchivedRepositoryCustom {}

View File

@@ -0,0 +1,6 @@
package com.kamco.cd.kamcoback.postgres.repository.members;
import org.springframework.stereotype.Repository;
@Repository
public class MembersArchivedRepositoryImpl implements MembersArchivedRepositoryCustom {}

View File

@@ -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<MapInkx5kEntity, Long>, MapInkx5kRepositoryCustom {}

View File

@@ -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<MapInkx5kEntity> listGetScenes5k(List<String> codes);
}

View File

@@ -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<MapInkx5kEntity> listGetScenes5k(List<String> codes) {
QMapInkx5kEntity map5k = QMapInkx5kEntity.mapInkx5kEntity;
return queryFactory
.selectFrom(map5k)
.where(map5k.mapidcdNo.in(codes))
.orderBy(map5k.mapidcdNo.asc())
.fetch();
}
}

View File

@@ -34,3 +34,6 @@ spring:
host: 192.168.2.109
port: 6379
password: kamco
member:
init_password: kamco1234!

View File

@@ -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!

View File

@@ -21,4 +21,7 @@ spring:
minimum-idle: 10
maximum-pool-size: 20
member:
init_password: kamco1234!