Merge branch 'feat/dev_251201' of https://kamco.gitea.gs.dabeeo.com/dabeeo/kamco-dabeeo-backoffice into feat/dev_251201

This commit is contained in:
Moon
2025-12-29 15:49:07 +09:00
12 changed files with 88 additions and 21 deletions

View File

@@ -1,6 +1,7 @@
package com.kamco.cd.kamcoback.common.enums;
import com.kamco.cd.kamcoback.common.utils.enums.CodeExpose;
import com.kamco.cd.kamcoback.common.utils.enums.CodeHidden;
import com.kamco.cd.kamcoback.common.utils.enums.EnumType;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -9,11 +10,13 @@ import lombok.Getter;
@Getter
@AllArgsConstructor
public enum SyncStateType implements EnumType {
@CodeHidden
NOTYET("미처리"),
NOFILE("파일없음"),
NOTPAIR("페어파일누락"),
DUPLICATE("파일중복"),
TYPEERROR("손상파일"),
@CodeHidden
DONE("완료");
private final String desc;

View File

@@ -0,0 +1,10 @@
package com.kamco.cd.kamcoback.common.utils.enums;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface CodeHidden {}

View File

@@ -35,10 +35,19 @@ public class Enums {
return Arrays.stream(enums)
.map(e -> (EnumType) e)
.filter(e -> !isHidden(enumClass, (Enum<?>) e))
.map(e -> new CodeDto(e.getId(), e.getText()))
.toList();
}
private static boolean isHidden(Class<? extends Enum<?>> enumClass, Enum<?> e) {
try {
return enumClass.getField(e.name()).isAnnotationPresent(CodeHidden.class);
} catch (NoSuchFieldException ex) {
return false;
}
}
/** 특정 타입(enum)만 조회 /codes/{type} -> type = RoleType 같은 값 */
public static List<CodeDto> getCodes(String type) {
Class<? extends Enum<?>> enumClass = exposedEnumMap.get(type);

View File

@@ -46,11 +46,18 @@ public class OpenApiConfig {
// profile 별 server url 분기
List<Server> servers = new ArrayList<>();
switch (profile) {
case "prod" -> servers.add(new Server().url(prodUrl).description("운영 서버"));
case "dev" -> servers.add(new Server().url(devUrl).description("개발 서버"));
default ->
servers.add(new Server().url("http://localhost:" + serverPort).description("로컬 개발 서버"));
if ("dev".equals(profile)) {
servers.add(new Server().url(devUrl).description("개발 서버"));
servers.add(new Server().url("http://localhost:" + serverPort).description("로컬 서버"));
// servers.add(new Server().url(prodUrl).description("운영 서버"));
} else if ("prod".equals(profile)) {
// servers.add(new Server().url(prodUrl).description("운영 서버"));
servers.add(new Server().url("http://localhost:" + serverPort).description("로컬 서버"));
servers.add(new Server().url(devUrl).description("개발 서버"));
} else {
servers.add(new Server().url("http://localhost:" + serverPort).description("로컬 서버"));
servers.add(new Server().url(devUrl).description("개발 서버"));
// servers.add(new Server().url(prodUrl).description("운영 서버"));
}
return new OpenAPI()

View File

@@ -71,6 +71,9 @@ public class InferenceResultShpDto {
@NoArgsConstructor
public static class InferenceCntDto {
@Schema(description = "추론 결과(inference_results)를 기준으로 신규 목록 저장 터이터 건수", example = "120")
int sheetAnalDataCnt;
@Schema(description = "추론 결과(inference_results)를 기준으로 신규 저장 데이터 건수", example = "120")
int inferenceCnt;

View File

@@ -273,14 +273,25 @@ public class GeoToolsShpWriter implements ShpWriter {
return b.buildFeatureType();
}
/**
* .shp .shx .dbf .fix 파일 생성 (껍데기 생성)
*
* @param shpFile
* @param schema
* @return
* @throws Exception
*/
private ShapefileDataStore createDataStore(File shpFile, SimpleFeatureType schema)
throws Exception {
Map<String, Serializable> params = new HashMap<>();
params.put("url", shpFile.toURI().toURL());
params.put("create spatial index", Boolean.TRUE);
// .fix 파일 생성 Boolean.TRUE, 미생성 Boolean.FALSE
params.put("create spatial index", Boolean.FALSE);
ShapefileDataStoreFactory factory = new ShapefileDataStoreFactory();
ShapefileDataStore dataStore = (ShapefileDataStore) factory.createNewDataStore(params);
dataStore.setCharset(DBF_CHARSET);

View File

@@ -33,8 +33,10 @@ public class InferenceResultShpService {
@Transactional
public InferenceResultShpDto.FileCntDto createShpFile() {
// TODO 파일 경로는 정해지면 수정, properties 사용
String baseDir = System.getProperty("user.home") + "/export";
// TODO 배치 실행으로 변경 필요
int batchSize = 100;
int geomLimit = 500_000;
@@ -47,7 +49,7 @@ public class InferenceResultShpService {
// 재생성을 위한 생성 상태 초기화
coreService.resetForRegenerate(dataUid);
// 도형 데이터 조회
// 추론 데이터 조회
List<InferenceResultShpDto.Basic> dtoList = coreService.loadGeomDtos(dataUid, geomLimit);
if (dtoList.isEmpty()) {
continue;
@@ -64,7 +66,7 @@ public class InferenceResultShpService {
String geoJsonPath = baseDir + "/geojson/" + baseName + ".geojson";
try {
// 폴더 안 파일을 세지 않고, Writer가 "이번 호출에서 write한 개수"를 반환
// Writer가 "이번 호출에서 write한 개수"를 반환
total = total.plus(shpWriter.writeShp(shpBasePath, dtoList));
total = total.plus(shpWriter.writeGeoJson(geoJsonPath, dtoList));

View File

@@ -6,7 +6,7 @@ import java.util.List;
public interface ShpWriter {
// SHP (.shp/.shx/.dbf)
// SHP (.shp/.shx/.dbf/.fix)
WriteCnt writeShp(String shpBasePath, List<InferenceResultShpDto.Basic> rows);
// GeoJSON (.geojson)

View File

@@ -20,10 +20,12 @@ public class InferenceResultShpCoreService {
*/
@Transactional
public InferenceResultShpDto.InferenceCntDto buildInferenceData() {
int sheetAnalDataCnt = repo.upsertGroupsFromMapSheetAnal();
int inferenceCnt = repo.upsertGroupsFromInferenceResults();
int inferenceGeomCnt = repo.upsertGeomsFromInferenceResults();
InferenceResultShpDto.InferenceCntDto cntDto = new InferenceResultShpDto.InferenceCntDto();
cntDto.setSheetAnalDataCnt(sheetAnalDataCnt);
cntDto.setInferenceCnt(inferenceCnt);
cntDto.setInferenceGeomCnt(inferenceGeomCnt);

View File

@@ -2,7 +2,6 @@ package com.kamco.cd.kamcoback.postgres.core;
import com.kamco.cd.kamcoback.config.api.ApiResponseDto.ApiResponseCode;
import com.kamco.cd.kamcoback.config.api.ApiResponseDto.ResponseObj;
import com.kamco.cd.kamcoback.postgres.entity.MapInkx50kEntity;
import com.kamco.cd.kamcoback.postgres.entity.MapInkx5kEntity;
import com.kamco.cd.kamcoback.postgres.repository.scene.MapInkx50kRepository;
import com.kamco.cd.kamcoback.postgres.repository.scene.MapInkx5kRepository;
@@ -39,21 +38,13 @@ public class MapInkxMngCoreService {
}
Integer fid50k = mapInkx50kRepository.findByMapidCdParentNo(req.getMapidcdNo());
if (fid50k == null || fid50k <= 0) {
// parent도 등록
MapInkx50kEntity parent =
new MapInkx50kEntity(req.getMapidcdNo().substring(0, 5), req.getMapidNm(), "", null);
MapInkx50kEntity result = mapInkx50kRepository.save(parent);
fid50k = result.getFid();
if (fid50k == null) {
return new ResponseObj(ApiResponseCode.NOT_FOUND_DATA, "1:50,000 도엽의 정보가 없습니다. 관리자에게 문의하세요.");
}
MapInkx5kEntity entity =
new MapInkx5kEntity(
req.getMapidcdNo(),
req.getMapidNm(),
map_polygon,
fid50k == null ? null : fid50k.longValue(),
"USE" // 기본은 USE로
req.getMapidcdNo(), req.getMapidNm(), map_polygon, fid50k.longValue(), "USE" // 기본은 USE로
);
mapInkx5kRepository.save(entity);

View File

@@ -5,6 +5,8 @@ import java.util.List;
public interface InferenceResultRepositoryCustom {
int upsertGroupsFromMapSheetAnal();
int upsertGroupsFromInferenceResults();
int upsertGeomsFromInferenceResults();

View File

@@ -31,6 +31,33 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC
// Upsert (Native only)
// ===============================
@Override
public int upsertGroupsFromMapSheetAnal() {
String sql =
"""
INSERT INTO tb_map_sheet_anal_inference (
compare_yyyy,
target_yyyy,
anal_map_sheet,
stage,
anal_title
)
SELECT
r.input1 AS compare_yyyy,
r.input2 AS target_yyyy,
r.map_id AS anal_map_sheet,
r.stage,
CONCAT(r.stage ,'_', r.input1 ,'_', r.input2 ,'_', r.map_id) as anal_title
FROM inference_results r
GROUP BY r.stage, r.input1, r.input2, r.map_id
ON CONFLICT (compare_yyyy, target_yyyy, anal_map_sheet, stage)
DO UPDATE SET
updated_dttm = now()
""";
return em.createNativeQuery(sql).executeUpdate();
}
/**
* inference_results 테이블을 기준으로 분석 데이터 단위(stage, compare_yyyy, target_yyyy, map_sheet_num)를
* 생성/갱신한다.