Files
test/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultApiController.java

498 lines
24 KiB
Java

package com.kamco.cd.kamcoback.inference;
import com.kamco.cd.kamcoback.common.exception.CustomApiException;
import com.kamco.cd.kamcoback.config.api.ApiResponseDto;
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto;
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto;
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.InferenceServerStatusDto;
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.InferenceStatusDetailDto;
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.ResultList;
import com.kamco.cd.kamcoback.inference.service.InferenceResultService;
import com.kamco.cd.kamcoback.log.dto.AuditLogDto;
import com.kamco.cd.kamcoback.log.dto.AuditLogDto.DownloadReq;
import com.kamco.cd.kamcoback.log.dto.AuditLogDto.searchReq;
import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto.MngYyyyDto;
import com.kamco.cd.kamcoback.mapsheet.service.MapSheetMngService;
import com.kamco.cd.kamcoback.model.dto.ModelMngDto;
import com.kamco.cd.kamcoback.model.service.ModelMngService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
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.charset.StandardCharsets;
import java.nio.file.Path;
import java.time.LocalDate;
import java.util.List;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.data.domain.Page;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
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.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.UriUtils;
@Tag(name = "추론관리", description = "추론관리 API")
@RequestMapping("/api/inference")
@RequiredArgsConstructor
@RestController
public class InferenceResultApiController {
private final InferenceResultService inferenceResultService;
private final MapSheetMngService mapSheetMngService;
private final ModelMngService modelMngService;
@Operation(summary = "추론관리 목록", description = "어드민 홈 > 추론관리 > 추론관리 > 추론관리 목록")
@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("/list")
public ApiResponseDto<Page<ResultList>> getInferenceResultList(
@Parameter(description = "국유인 반영 여부", example = "Y") @RequestParam(required = false)
String applyYn,
@Parameter(description = "반영일", example = "2025-01-01") @RequestParam(required = false)
LocalDate strtDttm,
@Parameter(description = "반영일", example = "2026-01-01") @RequestParam(required = false)
LocalDate endDttm,
@Parameter(description = "제목", example = "변화탐지") @RequestParam(required = false) String title,
@Parameter(description = "페이지 번호 (0부터 시작)", example = "0") @RequestParam(defaultValue = "0")
int page,
@Parameter(description = "페이지 크기", example = "20") @RequestParam(defaultValue = "20")
int size) {
InferenceResultDto.SearchListReq req =
new InferenceResultDto.SearchListReq(applyYn, strtDttm, endDttm, title, page, size);
Page<ResultList> analResList = inferenceResultService.getInferenceResultList(req);
return ApiResponseDto.ok(analResList);
}
@Operation(summary = "추론 진행 여부 확인", description = "어드민 홈 > 추론관리 > 추론관리 > 추론관리 목록")
@ApiResponses(
value = {
@ApiResponse(
responseCode = "200",
description = "검색 성공",
content =
@Content(
mediaType = "application/json",
schema =
@Schema(
description = "진행 여부 (UUID 있으면 진행중)",
type = "UUID",
example = "44709877-2e27-4fc5-bacb-8e0328c69b64"))),
@ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
})
@GetMapping("/processing-yn")
public ApiResponseDto<UUID> getProcessing() {
return ApiResponseDto.ok(inferenceResultService.getProcessing());
}
@Operation(summary = "년도 목록 조회", description = "어드민 홈 > 추론관리 > 추론목록 > 변화탐지 실행 정보 입력 > 년도 목록 조회")
@ApiResponses(
value = {
@ApiResponse(
responseCode = "200",
description = "조회 성공",
content =
@Content(
mediaType = "application/json",
array = @ArraySchema(schema = @Schema(implementation = Integer.class)))),
@ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
})
@GetMapping("/years")
public ApiResponseDto<List<MngYyyyDto>> findMapSheetMngDoneYyyyList() {
return ApiResponseDto.ok(mapSheetMngService.findMapSheetMngDoneYyyyList());
}
@Operation(summary = "변화탐지 실행 정보 입력", description = "어드민 홈 > 추론관리 > 추론목록 > 변화탐지 실행 정보 입력")
@ApiResponses(
value = {
@ApiResponse(
responseCode = "201",
description = "변화탐지 실행 정보 생성 성공",
content =
@Content(
mediaType = "application/json",
schema = @Schema(description = "저장 uuid", implementation = UUID.class))),
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
})
@PostMapping("/reg")
public ApiResponseDto<UUID> saveInferenceInfo(
@io.swagger.v3.oas.annotations.parameters.RequestBody(
description = "변화탐지 실행 정보 저장 요청 정보",
required = true)
@RequestBody
@Valid
InferenceResultDto.RegReq req) {
UUID uuid = inferenceResultService.saveInferenceInfo(req);
return ApiResponseDto.ok(uuid);
}
@Operation(summary = "추론 종료", description = "추론 종료")
@ApiResponses(
value = {
@ApiResponse(
responseCode = "201",
description = "종료 성공",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = Page.class))),
@ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
})
@DeleteMapping("/end")
public ApiResponseDto<Void> getInferenceGeomList() {
inferenceResultService.deleteInferenceEnd();
return null;
}
@Operation(summary = "분석 모델 선택 조회", description = "변화탐지 실행 정보 입력 모델선택 팝업 ")
@ApiResponses(
value = {
@ApiResponse(
responseCode = "200",
description = "분석 모델 조회 성공",
content =
@Content(
mediaType = "application/json",
schema = @Schema(description = "분석 모델", implementation = Page.class))),
@ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
})
@GetMapping("/model")
public ApiResponseDto<Page<ModelMngDto.ModelList>> saveInferenceInfo(
@Parameter(description = "모델 생성일 시작", example = "2025-12-01") @RequestParam(required = false)
LocalDate strtDttm,
@Parameter(description = "모델 생성일 종료", example = "2026-01-09") @RequestParam(required = false)
LocalDate endDttm,
@Parameter(description = "키워드 (모델버전)", example = "M1.H1.E28") @RequestParam(required = false)
String searchVal,
@Parameter(description = "타입", example = "M1") @RequestParam(required = false)
String modelType,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size) {
ModelMngDto.searchReq searchReq = new ModelMngDto.searchReq(page, size, null);
Page<ModelMngDto.ModelList> result =
modelMngService.findModelMgmtList(searchReq, strtDttm, endDttm, modelType, searchVal);
return ApiResponseDto.ok(result);
}
// @ApiResponses(
// value = {
// @ApiResponse(
// responseCode = "200",
// description = "검색 성공",
// content =
// @Content(
// mediaType = "application/json",
// schema = @Schema(implementation = InferenceDetailDto.AnalResSummary.class))),
// @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content),
// @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
// })
// @GetMapping("/summary/{id}")
// public ApiResponseDto<InferenceDetailDto.AnalResSummary> getInferenceResultSummary(
// @Parameter(description = "목록 id", example = "53") @PathVariable Long id) {
// return ApiResponseDto.ok(inferenceResultService.getInferenceResultSummary(id));
// }
//
// @Operation(summary = "추론관리 분석결과 상세", description = "분석결과 상제 정보 Summary, DashBoard")
// @ApiResponses(
// value = {
// @ApiResponse(
// responseCode = "200",
// description = "검색 성공",
// content =
// @Content(
// mediaType = "application/json",
// schema = @Schema(implementation = InferenceDetailDto.Detail.class))),
// @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content),
// @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
// })
// @GetMapping("/detail/{id}")
// public ApiResponseDto<InferenceDetailDto.Detail> getInferenceDetail(
// @Parameter(description = "목록 id", example = "53") @PathVariable Long id) {
// return ApiResponseDto.ok(inferenceResultService.getDetail(id));
// }
//
// @Operation(summary = "추론관리 분석결과 상세 목록", 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<InferenceDetailDto.Geom>> getInferenceResultGeomList(
// @Parameter(description = "분석결과 id", example = "53") @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) {
// InferenceDetailDto.SearchGeoReq searchGeoReq =
// new InferenceDetailDto.SearchGeoReq(
// targetClass, compareClass, mapSheetNum, page, size, sort);
// Page<InferenceDetailDto.Geom> geomList =
// inferenceResultService.getInferenceResultGeomList(id, searchGeoReq);
// return ApiResponseDto.ok(geomList);
// }
@Operation(summary = "추론관리 추론진행 서버 현황", description = "추론관리 추론진행 서버 현황")
@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("/serverStatus")
public ApiResponseDto<List<InferenceServerStatusDto>> getInferenceServerStatusList() {
return ApiResponseDto.ok(inferenceResultService.getInferenceServerStatusList());
}
@Operation(summary = "추론관리 진행현황 상세", description = "어드민 홈 > 추론관리 > 추론관리 > 진행현황 상세")
@ApiResponses(
value = {
@ApiResponse(
responseCode = "200",
description = "검색 성공",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = InferenceStatusDetailDto.class))),
@ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
})
@GetMapping("/status/{uuid}")
public ApiResponseDto<InferenceStatusDetailDto> getInferenceStatus(
@io.swagger.v3.oas.annotations.parameters.RequestBody(
description = "추론 진행현황 정보",
required = true)
@PathVariable
UUID uuid) {
return ApiResponseDto.ok(inferenceResultService.getInferenceStatus(uuid));
}
@Operation(summary = "추론결과 기본정보", description = "추론결과 기본정보")
@ApiResponses(
value = {
@ApiResponse(
responseCode = "200",
description = "검색 성공",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = InferenceDetailDto.AnalResSummary.class))),
@ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
})
@GetMapping("/infer-result-info")
public ApiResponseDto<InferenceDetailDto.AnalResultInfo> getInferenceResultInfo(
@Parameter(description = "회차 uuid", example = "f30e8817-9625-4fff-ba43-c1e6ed2067c4")
@RequestParam
UUID uuid) {
return ApiResponseDto.ok(inferenceResultService.getInferenceResultInfo(uuid));
}
@Operation(summary = "추론결과 분류별 탐지 건수", description = "추론결과 분류별 탐지 건수")
@ApiResponses(
value = {
@ApiResponse(
responseCode = "200",
description = "검색 성공",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = InferenceDetailDto.AnalResSummary.class))),
@ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
})
@GetMapping("/infer-class-count")
public ApiResponseDto<List<InferenceDetailDto.Dashboard>> getInferenceClassCountList(
@Parameter(description = "회차 uuid", example = "242750c5-a627-429b-950a-dce5a87c1c01")
@RequestParam
UUID uuid) {
return ApiResponseDto.ok(inferenceResultService.getInferenceClassCountList(uuid));
}
@Operation(summary = "추론관리 분석결과 상세 목록", 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-list")
public ApiResponseDto<Page<InferenceDetailDto.Geom>> getInferenceGeomList(
@Parameter(description = "회차 uuid", example = "242750c5-a627-429b-950a-dce5a87c1c01")
@RequestParam(required = true)
UUID uuid,
@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) {
InferenceDetailDto.SearchGeoReq searchGeoReq =
new InferenceDetailDto.SearchGeoReq(
targetClass, compareClass, mapSheetNum, page, size, sort);
Page<InferenceDetailDto.Geom> geomList =
inferenceResultService.getInferenceGeomList(uuid, searchGeoReq);
return ApiResponseDto.ok(geomList);
}
@Operation(summary = "shp 파일 다운로드", description = "추론관리 분석결과 shp 파일 다운로드")
@ApiResponses(
value = {
@ApiResponse(
responseCode = "200",
description = "shp zip파일 다운로드",
content =
@Content(
mediaType = "application/octet-stream",
schema = @Schema(type = "string", format = "binary"))),
@ApiResponse(responseCode = "404", description = "파일 없음", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
})
@GetMapping(value = "/download/{uuid}", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public ResponseEntity<Resource> downloadShp(
@Parameter(description = "uuid", example = "0192efc6-9ec2-43ee-9a90-5b73e763c09f")
@PathVariable
UUID uuid)
throws IOException {
String path;
try {
path = String.valueOf(inferenceResultService.shpDownloadPath(uuid));
} catch (CustomApiException e) {
// 데이터 없음 등 404
return ResponseEntity.status(e.getStatus()).build();
}
Path zipPath = Path.of(path);
FileSystemResource resource = new FileSystemResource(zipPath);
if (!resource.exists() || !resource.isReadable()) {
return ResponseEntity.notFound().build();
}
String filename = zipPath.getFileName().toString();
String encodedFilename = UriUtils.encode(filename, StandardCharsets.UTF_8);
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.header(
HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + filename + "\"; filename*=UTF-8''" + encodedFilename)
.contentLength(resource.contentLength())
.body((Resource) resource);
}
@Operation(summary = "shp 파일 다운로드 이력", description = "추론관리 분석결과 shp 파일 다운로드 이")
@GetMapping(value = "/download-audit/{uuid}")
@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)
})
public ApiResponseDto<Page<AuditLogDto.DownloadRes>> downloadAudit(
@Parameter(description = "UUID", example = "0192efc6-9ec2-43ee-9a90-5b73e763c09f")
@PathVariable
UUID uuid,
@Parameter(description = "구분-NAME(이름), EMPLOYEE_NO(사번)", example = "NAME")
@RequestParam(required = false)
String type,
@Parameter(description = "다운로드일 시작", example = "2025-01-01") @RequestParam(required = false)
LocalDate strtDttm,
@Parameter(description = "다운로드일 종료", example = "2026-01-01") @RequestParam(required = false)
LocalDate endDttm,
@Parameter(description = "키워드", example = "관리자") @RequestParam(required = false)
String searchValue,
@Parameter(description = "페이지 번호 (0부터 시작)", example = "0") @RequestParam(defaultValue = "0")
int page,
@Parameter(description = "페이지 크기", example = "20") @RequestParam(defaultValue = "20")
int size) {
AuditLogDto.searchReq searchReq = new searchReq();
searchReq.setPage(page);
searchReq.setSize(size);
DownloadReq downloadReq = new DownloadReq();
downloadReq.setUuid(uuid);
downloadReq.setStartDate(strtDttm);
downloadReq.setEndDate(endDttm);
downloadReq.setType(type);
downloadReq.setSearchValue(searchValue);
downloadReq.setMenuId("22");
downloadReq.setRequestUri("/api/inference/download-audit");
return ApiResponseDto.ok(inferenceResultService.getDownloadAudit(searchReq, downloadReq));
}
}