77import io .swagger .v3 .oas .annotations .Parameter ;
88import io .swagger .v3 .oas .annotations .tags .Tag ;
99import lombok .RequiredArgsConstructor ;
10+ import lombok .extern .slf4j .Slf4j ;
1011import org .springframework .http .HttpStatus ;
1112import org .springframework .http .ResponseEntity ;
1213import org .springframework .web .bind .annotation .*;
1314
1415@ RestController
1516@ RequiredArgsConstructor
17+ @ Slf4j
1618@ RequestMapping ("/test/kis" )
1719@ Tag (name = " Test API" , description = "테스트 API 입니다." )
1820public class KisTestController {
@@ -25,6 +27,7 @@ public class KisTestController {
2527 private final KisOhlcvUpdateService kisOhlcvUpdateService ;
2628 private final Kis1dOhlcvUpdateService kis1dOhlcvUpdateService ;
2729 private final Kis1mOhlcvUpdateService kis1mOhlcvUpdateService ;
30+ private final KisPast15mOhlcvUpdateService kisPast15mOhlcvUpdateService ;
2831
2932 @ Hidden
3033 @ Operation (summary = "KIS Access Token API" , description = "KIS의 Access Token 을 발급 또는 로드합니다." )
@@ -239,4 +242,70 @@ public ResponseEntity<?> update5yOhlcvByStockIdRange(
239242 .body (ApiResponse .onFailure ("INTERNAL_ERROR" , "저장 중 오류 발생" , e .getMessage ()));
240243 }
241244 }
245+
246+ @ Operation (summary = "종목 구간 과거 1년간 15분 Ohlcv 업데이트 API" , description = "startId ~ endId 사이 종목들의 1년간의 15분봉 OHLCV를 업데이트합니다." )
247+ @ PostMapping ("/stocks/ohlcv/15m/range" )
248+ public ResponseEntity <?> updatePast15mOhlcvByStockIdRange (
249+ @ Parameter (description = "시작 종목 ID" , required = true )
250+ @ RequestParam Long startId ,
251+
252+ @ Parameter (description = "종료 종목 ID (미입력 시 startId와 동일)" )
253+ @ RequestParam (required = false ) Long endId
254+ ) {
255+ try {
256+ // endId가 null이면 startId로 세팅
257+ if (endId == null ) {
258+ endId = startId ;
259+ }
260+
261+ log .info ("[API] 종목 구간 15m OHLCV 업데이트 호출 - startId={}, endId={}" , startId , endId );
262+
263+ kisPast15mOhlcvUpdateService .updateStocksByIdRange (startId , endId );
264+
265+ return ResponseEntity .ok (
266+ ApiResponse .onSuccess ("STOCK_UPDATE_SUCCESS" ,
267+ String .format ("과거 1년치 15분봉 OHLCV 저장 완료 (ID %d ~ %d)" , startId , endId ))
268+ );
269+ } catch (Exception e ) {
270+ log .error ("[API] 종목 구간 15m OHLCV 업데이트 실패 - startId={}, endId={}" , startId , endId , e );
271+ return ResponseEntity
272+ .status (HttpStatus .INTERNAL_SERVER_ERROR )
273+ .body (ApiResponse .onFailure ("INTERNAL_ERROR" , "저장 중 오류 발생" , e .getMessage ()));
274+ }
275+ }
276+
277+ @ Operation (
278+ summary = "단일 종목 당일 15분 OHLCV 테스트 API" ,
279+ description = "특정 종목 ID에 대해 오늘 하루치 1분봉을 조회하여 15분봉으로 변환 후 저장합니다. "
280+ + "배치 전체가 아닌 단일 종목 테스트 용도로 사용합니다."
281+ )
282+ // @PostMapping("/stocks/ohlcv/15m/test")
283+ public ResponseEntity <?> testSingleStock (
284+ @ Parameter (description = "종목 ID" , required = true )
285+ @ RequestParam Long stockId
286+ ) {
287+ try {
288+ log .info ("[API] 단일 종목 15m OHLCV 테스트 호출 - stockId={}" , stockId );
289+
290+ kisPast15mOhlcvUpdateService .testSingleStockById (stockId );
291+
292+ return ResponseEntity .ok (
293+ ApiResponse .onSuccess (
294+ "STOCK_TEST_SUCCESS" ,
295+ String .format ("종목 ID=%d 오늘 하루치 15분봉 OHLCV 저장 완료" , stockId )
296+ )
297+ );
298+ } catch (IllegalArgumentException e ) {
299+ log .warn ("[API] 단일 종목 테스트 실패 - 잘못된 종목 ID. stockId={}" , stockId , e );
300+ return ResponseEntity
301+ .status (HttpStatus .BAD_REQUEST )
302+ .body (ApiResponse .onFailure ("INVALID_STOCK_ID" , "존재하지 않는 종목 ID" , e .getMessage ()));
303+ } catch (Exception e ) {
304+ log .error ("[API] 단일 종목 15m OHLCV 테스트 실패 - stockId={}" , stockId , e );
305+ return ResponseEntity
306+ .status (HttpStatus .INTERNAL_SERVER_ERROR )
307+ .body (ApiResponse .onFailure ("INTERNAL_ERROR" , "저장 중 오류 발생" , e .getMessage ()));
308+ }
309+ }
310+
242311}
0 commit comments