diff --git a/docs/RELEASE-NOTES.md b/docs/RELEASE-NOTES.md index ca92665..ad36c9b 100644 --- a/docs/RELEASE-NOTES.md +++ b/docs/RELEASE-NOTES.md @@ -27,6 +27,7 @@ - 자동 재수집 및 재수집 프로세스 전면 개선 (#30) - 배치 작업 목록 UX 개선: 상태 필터, 카드/테이블 뷰, 정렬, 실행 중 강조 (#33) - 재시도 초과 레코드 초기화 API/UI 추가 +- IMO 기반 Risk 상세 조회 bypass API 추가 (#39) ### 수정 - 자동 재수집 JobParameter 오버플로우 수정 (VARCHAR 2500 제한 해결) diff --git a/src/main/java/com/snp/batch/global/config/SwaggerConfig.java b/src/main/java/com/snp/batch/global/config/SwaggerConfig.java index 3e056b9..8cb1a22 100644 --- a/src/main/java/com/snp/batch/global/config/SwaggerConfig.java +++ b/src/main/java/com/snp/batch/global/config/SwaggerConfig.java @@ -47,6 +47,9 @@ public class SwaggerConfig { new Server() .url("http://211.208.115.83:" + serverPort + contextPath) .description("중계 서버"), + new Server() + .url("https://guide.gc-si.dev" + contextPath) + .description("중계 서버 도메인"), new Server() .url("http://10.187.58.58:" + serverPort + contextPath) .description("운영 서버"), @@ -90,4 +93,4 @@ public class SwaggerConfig { .name("Apache 2.0") .url("https://www.apache.org/licenses/LICENSE-2.0")); } -} \ No newline at end of file +} diff --git a/src/main/java/com/snp/batch/jobs/risk/web/controller/RiskController.java b/src/main/java/com/snp/batch/jobs/risk/web/controller/RiskController.java new file mode 100644 index 0000000..9113622 --- /dev/null +++ b/src/main/java/com/snp/batch/jobs/risk/web/controller/RiskController.java @@ -0,0 +1,56 @@ +package com.snp.batch.jobs.risk.web.controller; + +import com.snp.batch.common.web.ApiResponse; +import com.snp.batch.jobs.risk.batch.dto.RiskDto; +import com.snp.batch.jobs.risk.web.service.RiskBypassService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +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; +import org.springframework.web.reactive.function.client.WebClientResponseException; + +import java.util.List; + +/** + * Risk 상세 조회 bypass API + * S&P Maritime API에서 Risk 데이터를 실시간 조회하여 그대로 반환 + */ +@Slf4j +@RestController +@RequestMapping("/api/risk") +@RequiredArgsConstructor +@Tag(name = "Risk", description = "선박 Risk 상세 정보 bypass API") +public class RiskController { + + private final RiskBypassService riskBypassService; + + @Operation( + summary = "IMO 기반 Risk 상세 조회", + description = "S&P API에 IMO 번호로 Risk 상세 데이터를 요청하고 응답을 그대로 반환합니다." + ) + @GetMapping("/{imo}") + public ResponseEntity>> getRiskDetailByImo( + @Parameter(description = "IMO 번호", example = "9321483") + @PathVariable String imo + ) { + try { + List riskData = riskBypassService.getRiskDetailByImo(imo); + return ResponseEntity.ok(ApiResponse.success(riskData)); + } catch (WebClientResponseException e) { + log.error("S&P Risk API 호출 실패 - IMO: {}, status: {}, body: {}", + imo, e.getStatusCode(), e.getResponseBodyAsString()); + return ResponseEntity.status(e.getStatusCode()) + .body(ApiResponse.error("S&P API 호출 실패: " + e.getMessage())); + } catch (Exception e) { + log.error("Risk 상세 조회 중 오류 - IMO: {}", imo, e); + return ResponseEntity.internalServerError() + .body(ApiResponse.error("Risk 조회 실패: " + e.getMessage())); + } + } +} diff --git a/src/main/java/com/snp/batch/jobs/risk/web/service/RiskBypassService.java b/src/main/java/com/snp/batch/jobs/risk/web/service/RiskBypassService.java new file mode 100644 index 0000000..5162dc9 --- /dev/null +++ b/src/main/java/com/snp/batch/jobs/risk/web/service/RiskBypassService.java @@ -0,0 +1,56 @@ +package com.snp.batch.jobs.risk.web.service; + +import com.snp.batch.jobs.risk.batch.dto.RiskDto; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; + +import java.util.List; + +/** + * S&P Risk API bypass 서비스 + * 외부 Maritime API에서 Risk 상세 데이터를 실시간 조회하여 그대로 반환 + */ +@Slf4j +@Service +public class RiskBypassService { + + private static final String RISK_API_PATH = "/RiskAndCompliance/RisksByImos"; + + private final WebClient webClient; + + public RiskBypassService( + @Qualifier("maritimeServiceApiWebClient") WebClient webClient + ) { + this.webClient = webClient; + } + + /** + * IMO 번호로 S&P Risk 상세 데이터를 조회합니다. + * + * @param imo IMO 번호 + * @return Risk 상세 데이터 목록 + */ + public List getRiskDetailByImo(String imo) { + log.info("S&P Risk API 호출 - IMO: {}", imo); + + List response = webClient.get() + .uri(uriBuilder -> uriBuilder + .path(RISK_API_PATH) + .queryParam("imos", imo) + .build()) + .retrieve() + .bodyToMono(new ParameterizedTypeReference>() {}) + .block(); + + if (response == null || response.isEmpty()) { + log.warn("S&P Risk API 응답 없음 - IMO: {}", imo); + return List.of(); + } + + log.info("S&P Risk API 응답 완료 - IMO: {}, 건수: {}", imo, response.size()); + return response; + } +}