Detail 다중조회, ploygon 다중저장 수정

This commit is contained in:
DanielLee
2026-01-14 11:57:49 +09:00
parent 5120793933
commit 767bea7da5
4 changed files with 350 additions and 14 deletions

View File

@@ -638,6 +638,16 @@ public class TrainingDataLabelRepositoryImpl extends QuerydslRepositorySupport
+ " new polygon(s) for mapSheetNum: "
+ request.getMapSheetNum());
// mapSheetNum을 Long으로 변환
Long mapSheetNumLong = null;
try {
if (request.getMapSheetNum() != null && !request.getMapSheetNum().isEmpty()) {
mapSheetNumLong = Long.parseLong(request.getMapSheetNum());
}
} catch (NumberFormatException e) {
System.err.println("Invalid mapSheetNum format: " + request.getMapSheetNum());
}
int savedCount = 0;
for (TrainingDataLabelDto.NewPolygonRequest.PolygonFeature feature : request.getFeatures()) {
try {
@@ -650,6 +660,8 @@ public class TrainingDataLabelRepositoryImpl extends QuerydslRepositorySupport
mapSheetAnalDataInferenceGeomEntity.targetYyyy,
mapSheetAnalDataInferenceGeomEntity.classBeforeCd,
mapSheetAnalDataInferenceGeomEntity.classAfterCd,
mapSheetAnalDataInferenceGeomEntity.dataUid,
mapSheetAnalDataInferenceGeomEntity.mapSheetNum,
mapSheetAnalDataInferenceGeomEntity.createdDttm,
mapSheetAnalDataInferenceGeomEntity.updatedDttm,
mapSheetAnalDataInferenceGeomEntity.labelState)
@@ -659,20 +671,25 @@ public class TrainingDataLabelRepositoryImpl extends QuerydslRepositorySupport
request.getTargetYyyy(),
feature.getProperties().getBeforeClass().toLowerCase(),
feature.getProperties().getAfterClass().toLowerCase(),
request.getAnalUid(),
mapSheetNumLong,
ZonedDateTime.now(),
ZonedDateTime.now(),
"DONE")
.execute();
// 2. 생성된 geoUid 조회
// 2. 생성된 geoUid 조회 (가장 최근에 삽입된 레코드)
Long geoUid =
queryFactory
.select(mapSheetAnalDataInferenceGeomEntity.geoUid)
.from(mapSheetAnalDataInferenceGeomEntity)
.where(
mapSheetAnalDataInferenceGeomEntity.geom.eq(feature.getGeometry()),
mapSheetAnalDataInferenceGeomEntity.compareYyyy.eq(request.getCompareYyyy()),
mapSheetAnalDataInferenceGeomEntity.targetYyyy.eq(request.getTargetYyyy()))
mapSheetAnalDataInferenceGeomEntity.targetYyyy.eq(request.getTargetYyyy()),
mapSheetAnalDataInferenceGeomEntity.classBeforeCd.eq(
feature.getProperties().getBeforeClass().toLowerCase()),
mapSheetAnalDataInferenceGeomEntity.classAfterCd.eq(
feature.getProperties().getAfterClass().toLowerCase()))
.orderBy(mapSheetAnalDataInferenceGeomEntity.geoUid.desc())
.fetchFirst();
@@ -710,6 +727,7 @@ public class TrainingDataLabelRepositoryImpl extends QuerydslRepositorySupport
} catch (Exception e) {
System.err.println("Error saving polygon #" + (savedCount + 1) + ": " + e.getMessage());
e.printStackTrace();
// 개별 polygon 저장 실패해도 계속 진행
}
}

View File

@@ -660,6 +660,16 @@ public class TrainingDataReviewRepositoryImpl extends QuerydslRepositorySupport
+ " new polygon(s) for mapSheetNum: "
+ request.getMapSheetNum());
// mapSheetNum을 Long으로 변환
Long mapSheetNumLong = null;
try {
if (request.getMapSheetNum() != null && !request.getMapSheetNum().isEmpty()) {
mapSheetNumLong = Long.parseLong(request.getMapSheetNum());
}
} catch (NumberFormatException e) {
System.err.println("Invalid mapSheetNum format: " + request.getMapSheetNum());
}
int savedCount = 0;
for (TrainingDataReviewDto.NewPolygonRequest.PolygonFeature feature : request.getFeatures()) {
try {
@@ -672,6 +682,8 @@ public class TrainingDataReviewRepositoryImpl extends QuerydslRepositorySupport
mapSheetAnalDataInferenceGeomEntity.targetYyyy,
mapSheetAnalDataInferenceGeomEntity.classBeforeCd,
mapSheetAnalDataInferenceGeomEntity.classAfterCd,
mapSheetAnalDataInferenceGeomEntity.dataUid,
mapSheetAnalDataInferenceGeomEntity.mapSheetNum,
mapSheetAnalDataInferenceGeomEntity.createdDttm,
mapSheetAnalDataInferenceGeomEntity.updatedDttm,
mapSheetAnalDataInferenceGeomEntity.labelState)
@@ -681,20 +693,25 @@ public class TrainingDataReviewRepositoryImpl extends QuerydslRepositorySupport
request.getTargetYyyy(),
feature.getProperties().getBeforeClass().toLowerCase(),
feature.getProperties().getAfterClass().toLowerCase(),
request.getAnalUid(),
mapSheetNumLong,
ZonedDateTime.now(),
ZonedDateTime.now(),
"DONE")
.execute();
// 2. 생성된 geoUid 조회
// 2. 생성된 geoUid 조회 (가장 최근에 삽입된 레코드)
Long geoUid =
queryFactory
.select(mapSheetAnalDataInferenceGeomEntity.geoUid)
.from(mapSheetAnalDataInferenceGeomEntity)
.where(
mapSheetAnalDataInferenceGeomEntity.geom.eq(feature.getGeometry()),
mapSheetAnalDataInferenceGeomEntity.compareYyyy.eq(request.getCompareYyyy()),
mapSheetAnalDataInferenceGeomEntity.targetYyyy.eq(request.getTargetYyyy()))
mapSheetAnalDataInferenceGeomEntity.targetYyyy.eq(request.getTargetYyyy()),
mapSheetAnalDataInferenceGeomEntity.classBeforeCd.eq(
feature.getProperties().getBeforeClass().toLowerCase()),
mapSheetAnalDataInferenceGeomEntity.classAfterCd.eq(
feature.getProperties().getAfterClass().toLowerCase()))
.orderBy(mapSheetAnalDataInferenceGeomEntity.geoUid.desc())
.fetchFirst();
@@ -732,6 +749,7 @@ public class TrainingDataReviewRepositoryImpl extends QuerydslRepositorySupport
} catch (Exception e) {
System.err.println("Error saving polygon #" + (savedCount + 1) + ": " + e.getMessage());
e.printStackTrace();
// 개별 polygon 저장 실패해도 계속 진행
}
}

View File

@@ -132,7 +132,9 @@ public class TrainingDataLabelApiController {
}
}
@Operation(summary = "변화탐지정보 및 실태조사결과 조회", description = "선택한 작업의 변화탐지정보 및 실태조사결과를 조회합니다.")
@Operation(
summary = "변화탐지정보 및 실태조사결과 조회",
description = "선택한 작업의 변화탐지정보 및 실태조사결과를 조회합니다. 저장된 여러 개의 polygon을 조회할 수 있습니다.")
@ApiResponses(
value = {
@ApiResponse(
@@ -141,7 +143,155 @@ public class TrainingDataLabelApiController {
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = TrainingDataLabelDto.DetailRes.class))),
schema = @Schema(implementation = TrainingDataLabelDto.DetailRes.class),
examples = {
@io.swagger.v3.oas.annotations.media.ExampleObject(
name = "단일 polygon 조회",
description = "1개의 polygon이 저장된 경우 응답 예시",
value =
"""
{
"code": "OK",
"message": null,
"data": {
"assignmentUid": "4f9ebc8b-6635-4177-b42f-7efc9c7b4c02",
"changeDetectionInfo": {
"mapSheetInfo": "NI52-3-13-1",
"detectionYear": "2023-2024",
"beforeClass": {
"classification": "waste",
"probability": 0.95
},
"afterClass": {
"classification": "land",
"probability": 0.98
},
"area": 1250.5,
"detectionAccuracy": 0.96,
"pnu": 1234567890
},
"inspectionResultInfo": {
"verificationResult": "완료",
"inappropriateReason": ""
},
"geom": {
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[[126.663, 34.588], [126.662, 34.587], [126.664, 34.589], [126.663, 34.588]]]
},
"properties": {
"beforeClass": "waste",
"afterClass": "land"
}
},
"beforeCogUrl": "https://storage.example.com/cog/2023/NI52-3-13-1.tif",
"afterCogUrl": "https://storage.example.com/cog/2024/NI52-3-13-1.tif",
"mapBox": {
"type": "Polygon",
"coordinates": [[[126.65, 34.58], [126.67, 34.58], [126.67, 34.60], [126.65, 34.60], [126.65, 34.58]]]
},
"learnGeometries": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[[126.663, 34.588], [126.662, 34.587], [126.664, 34.589], [126.663, 34.588]]]
},
"properties": {
"beforeClass": "waste",
"afterClass": "land"
}
}
]
}
}
"""),
@io.swagger.v3.oas.annotations.media.ExampleObject(
name = "여러 polygon 조회",
description = "3개의 polygon이 저장된 경우 응답 예시",
value =
"""
{
"code": "OK",
"message": null,
"data": {
"assignmentUid": "4f9ebc8b-6635-4177-b42f-7efc9c7b4c02",
"changeDetectionInfo": {
"mapSheetInfo": "NI52-3-13-1",
"detectionYear": "2023-2024",
"beforeClass": {
"classification": "waste",
"probability": 0.95
},
"afterClass": {
"classification": "land",
"probability": 0.98
},
"area": 1250.5,
"detectionAccuracy": 0.96,
"pnu": 1234567890
},
"inspectionResultInfo": {
"verificationResult": "완료",
"inappropriateReason": ""
},
"geom": {
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[[126.663, 34.588], [126.662, 34.587], [126.664, 34.589], [126.663, 34.588]]]
},
"properties": {
"beforeClass": "waste",
"afterClass": "land"
}
},
"beforeCogUrl": "https://storage.example.com/cog/2023/NI52-3-13-1.tif",
"afterCogUrl": "https://storage.example.com/cog/2024/NI52-3-13-1.tif",
"mapBox": {
"type": "Polygon",
"coordinates": [[[126.65, 34.58], [126.67, 34.58], [126.67, 34.60], [126.65, 34.60], [126.65, 34.58]]]
},
"learnGeometries": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[[126.663, 34.588], [126.662, 34.587], [126.664, 34.589], [126.663, 34.588]]]
},
"properties": {
"beforeClass": "waste",
"afterClass": "land"
}
},
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[[126.665, 34.585], [126.664, 34.584], [126.666, 34.586], [126.665, 34.585]]]
},
"properties": {
"beforeClass": "forest",
"afterClass": "building"
}
},
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[[126.660, 34.590], [126.659, 34.589], [126.661, 34.591], [126.660, 34.590]]]
},
"properties": {
"beforeClass": "grassland",
"afterClass": "concrete"
}
}
]
}
}
""")
})),
@ApiResponse(responseCode = "400", description = "잘못된 요청", content = @Content),
@ApiResponse(responseCode = "404", description = "데이터를 찾을 수 없음", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
@@ -151,8 +301,8 @@ public class TrainingDataLabelApiController {
@io.swagger.v3.oas.annotations.Parameter(
description = "작업 배정 ID (UUID)",
required = true,
example = "93c56be8-0246-4b22-b976-2476549733cc")
@RequestParam
example = "4f9ebc8b-6635-4177-b42f-7efc9c7b4c02")
@RequestParam(defaultValue = "4f9ebc8b-6635-4177-b42f-7efc9c7b4c02")
java.util.UUID assignmentUid) {
return ApiResponseDto.ok(trainingDataLabelService.getDetail(assignmentUid));
}

View File

@@ -132,7 +132,9 @@ public class TrainingDataReviewApiController {
}
}
@Operation(summary = "변화탐지정보 및 실태조사결과 조회", description = "선택한 작업의 변화탐지정보 및 실태조사결과를 조회합니다.")
@Operation(
summary = "변화탐지정보 및 실태조사결과 조회",
description = "선택한 작업의 변화탐지정보 및 실태조사결과를 조회합니다. 저장된 여러 개의 polygon을 조회할 수 있습니다.")
@ApiResponses(
value = {
@ApiResponse(
@@ -141,7 +143,155 @@ public class TrainingDataReviewApiController {
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = TrainingDataReviewDto.DetailRes.class))),
schema = @Schema(implementation = TrainingDataReviewDto.DetailRes.class),
examples = {
@io.swagger.v3.oas.annotations.media.ExampleObject(
name = "단일 polygon 조회",
description = "1개의 polygon이 저장된 경우 응답 예시",
value =
"""
{
"code": "OK",
"message": null,
"data": {
"operatorUid": "4f9ebc8b-6635-4177-b42f-7efc9c7b4c02",
"changeDetectionInfo": {
"mapSheetInfo": "NI52-3-13-1",
"detectionYear": "2023-2024",
"beforeClass": {
"classification": "waste",
"probability": 0.95
},
"afterClass": {
"classification": "land",
"probability": 0.98
},
"area": 1250.5,
"detectionAccuracy": 0.96,
"pnu": 1234567890
},
"inspectionResultInfo": {
"verificationResult": "완료",
"inappropriateReason": ""
},
"geom": {
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[[126.663, 34.588], [126.662, 34.587], [126.664, 34.589], [126.663, 34.588]]]
},
"properties": {
"beforeClass": "waste",
"afterClass": "land"
}
},
"beforeCogUrl": "https://storage.example.com/cog/2023/NI52-3-13-1.tif",
"afterCogUrl": "https://storage.example.com/cog/2024/NI52-3-13-1.tif",
"mapBox": {
"type": "Polygon",
"coordinates": [[[126.65, 34.58], [126.67, 34.58], [126.67, 34.60], [126.65, 34.60], [126.65, 34.58]]]
},
"learnGeometries": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[[126.663, 34.588], [126.662, 34.587], [126.664, 34.589], [126.663, 34.588]]]
},
"properties": {
"beforeClass": "waste",
"afterClass": "land"
}
}
]
}
}
"""),
@io.swagger.v3.oas.annotations.media.ExampleObject(
name = "여러 polygon 조회",
description = "3개의 polygon이 저장된 경우 응답 예시",
value =
"""
{
"code": "OK",
"message": null,
"data": {
"operatorUid": "4f9ebc8b-6635-4177-b42f-7efc9c7b4c02",
"changeDetectionInfo": {
"mapSheetInfo": "NI52-3-13-1",
"detectionYear": "2023-2024",
"beforeClass": {
"classification": "waste",
"probability": 0.95
},
"afterClass": {
"classification": "land",
"probability": 0.98
},
"area": 1250.5,
"detectionAccuracy": 0.96,
"pnu": 1234567890
},
"inspectionResultInfo": {
"verificationResult": "완료",
"inappropriateReason": ""
},
"geom": {
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[[126.663, 34.588], [126.662, 34.587], [126.664, 34.589], [126.663, 34.588]]]
},
"properties": {
"beforeClass": "waste",
"afterClass": "land"
}
},
"beforeCogUrl": "https://storage.example.com/cog/2023/NI52-3-13-1.tif",
"afterCogUrl": "https://storage.example.com/cog/2024/NI52-3-13-1.tif",
"mapBox": {
"type": "Polygon",
"coordinates": [[[126.65, 34.58], [126.67, 34.58], [126.67, 34.60], [126.65, 34.60], [126.65, 34.58]]]
},
"learnGeometries": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[[126.663, 34.588], [126.662, 34.587], [126.664, 34.589], [126.663, 34.588]]]
},
"properties": {
"beforeClass": "waste",
"afterClass": "land"
}
},
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[[126.665, 34.585], [126.664, 34.584], [126.666, 34.586], [126.665, 34.585]]]
},
"properties": {
"beforeClass": "forest",
"afterClass": "building"
}
},
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[[126.660, 34.590], [126.659, 34.589], [126.661, 34.591], [126.660, 34.590]]]
},
"properties": {
"beforeClass": "grassland",
"afterClass": "concrete"
}
}
]
}
}
""")
})),
@ApiResponse(responseCode = "400", description = "잘못된 요청", content = @Content),
@ApiResponse(responseCode = "404", description = "데이터를 찾을 수 없음", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
@@ -151,8 +301,8 @@ public class TrainingDataReviewApiController {
@io.swagger.v3.oas.annotations.Parameter(
description = "검수 작업 ID (UUID)",
required = true,
example = "93c56be8-0246-4b22-b976-2476549733cc")
@RequestParam
example = "4f9ebc8b-6635-4177-b42f-7efc9c7b4c02")
@RequestParam(defaultValue = "4f9ebc8b-6635-4177-b42f-7efc9c7b4c02")
java.util.UUID operatorUid) {
return ApiResponseDto.ok(trainingDataReviewService.getDetail(operatorUid));
}