From 19df7e6686ba433870b5e92325e6b8d08daaad6a Mon Sep 17 00:00:00 2001 From: hek316 Date: Sat, 21 Dec 2024 03:33:24 +0900 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20=EC=8B=A4=EC=8B=9C=EA=B0=84=20?= =?UTF-8?q?=EC=A3=BC=EC=8B=9D=20=EC=8B=9C=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EB=B0=8F=20DB=20=EC=A0=80=EC=9E=A5=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -조회된 실시간 주식시세 데이터를 데이터베이스에 저장하는 로직 추가 --- .../mars/api/controller/StockController.java | 18 ++- .../java/com/flab/mars/client/KISClient.java | 5 +- .../flab/mars/client/KisPriceResponseVO.java | 106 ++++++++++++++++ .../java/com/flab/mars/db/entity/Output.java | 95 +++++++++++++++ .../mars/db/entity/StockPriceChartEntity.java | 48 ++++++++ .../repository/StockPriceChartRepository.java | 7 ++ .../mars/domain/service/StockService.java | 65 +++++++++- .../vo/response/StockPriceResponseVO.java | 113 ++++++++++++++++++ 8 files changed, 445 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/flab/mars/client/KisPriceResponseVO.java create mode 100644 src/main/java/com/flab/mars/db/entity/Output.java create mode 100644 src/main/java/com/flab/mars/db/entity/StockPriceChartEntity.java create mode 100644 src/main/java/com/flab/mars/db/repository/StockPriceChartRepository.java create mode 100644 src/main/java/com/flab/mars/domain/vo/response/StockPriceResponseVO.java diff --git a/src/main/java/com/flab/mars/api/controller/StockController.java b/src/main/java/com/flab/mars/api/controller/StockController.java index daf474b..db80cd9 100644 --- a/src/main/java/com/flab/mars/api/controller/StockController.java +++ b/src/main/java/com/flab/mars/api/controller/StockController.java @@ -5,10 +5,10 @@ import com.flab.mars.api.dto.response.ResultAPIDto; import com.flab.mars.api.dto.response.StockFluctuationResponseDto; import com.flab.mars.domain.service.StockService; -import com.flab.mars.domain.vo.StockPrice; import com.flab.mars.domain.vo.TokenInfo; import com.flab.mars.domain.vo.request.StockFluctuationRequestVO; import com.flab.mars.domain.vo.response.StockFluctuationResponseVO; +import com.flab.mars.domain.vo.response.StockPriceResponseVO; import jakarta.servlet.http.HttpSession; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; @@ -29,8 +29,8 @@ public class StockController { /** * KIS 토큰 발급 요청, 1분당 하나 가능 - * @param request - * @param session + * @param request 한화투자증권으로부터 발급받은 appKey, appSecret 값을 전달 + * @param session 세션 * @return TokenInfo */ @PostMapping({"/accessToken"}) @@ -52,10 +52,16 @@ public ResponseEntity> getAccessToken(@RequestBody ApiCr return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ResultAPIDto.res(HttpStatus.INTERNAL_SERVER_ERROR, "Internal Server Error")); } + /** + * 주식현재가 시세를 조회 및 db 에 저장한다. + * @param stockCode ex) 000660 + * @param session 세션 + * @return 주식현재가 , 누적 거래 대금, 누적 거래량, 주식 시가, 주식 최고가, 주식 최저가 등을 반환 + */ @GetMapping("/quotations/inquire-price") - public ResponseEntity> getStockPrice(@RequestParam(name = "stockCode") String stockCode, HttpSession session) { - StockPrice stockPrice = stockService.getStockPrice(stockCode, session); - return ResponseEntity.ok(ResultAPIDto.res(HttpStatus.OK, "Success", stockPrice)); + public ResponseEntity> getStockPrice(@RequestParam(name = "stockCode") String stockCode, HttpSession session) { + StockPriceResponseVO stockPriceResponseVO = stockService.getStockPrice(stockCode, session); + return ResponseEntity.ok(ResultAPIDto.res(HttpStatus.OK, "Success", stockPriceResponseVO)); } @GetMapping("/domestic-stock/ranking/fluctuation") diff --git a/src/main/java/com/flab/mars/client/KISClient.java b/src/main/java/com/flab/mars/client/KISClient.java index b8d9ff0..26d2033 100644 --- a/src/main/java/com/flab/mars/client/KISClient.java +++ b/src/main/java/com/flab/mars/client/KISClient.java @@ -1,6 +1,5 @@ package com.flab.mars.client; -import com.flab.mars.domain.vo.StockPrice; import com.flab.mars.domain.vo.response.StockFluctuationResponseVO; import lombok.RequiredArgsConstructor; import org.springframework.core.ParameterizedTypeReference; @@ -49,7 +48,7 @@ public String getAccessToken(String appKey, String appSecret, String grantType) } - public StockPrice getStockPrice(String accessToken, String appKey, String appSecret, String stockCode) { + public KisPriceResponseVO getStockPrice(String accessToken, String appKey, String appSecret, String stockCode) { return webClient.get() .uri(uriBuilder -> uriBuilder.path(INQUIRE_PRICE) .queryParam("FID_COND_MRKT_DIV_CODE", "J") @@ -63,7 +62,7 @@ public StockPrice getStockPrice(String accessToken, String appKey, String appSec headers.setContentType(MediaType.APPLICATION_JSON); }) .retrieve() - .bodyToMono(StockPrice.class) + .bodyToMono(KisPriceResponseVO.class) .block(); } diff --git a/src/main/java/com/flab/mars/client/KisPriceResponseVO.java b/src/main/java/com/flab/mars/client/KisPriceResponseVO.java new file mode 100644 index 0000000..6bf7fde --- /dev/null +++ b/src/main/java/com/flab/mars/client/KisPriceResponseVO.java @@ -0,0 +1,106 @@ +package com.flab.mars.client; + + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.flab.mars.domain.vo.response.BaseResponseVO; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + + +@EqualsAndHashCode(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +public class KisPriceResponseVO extends BaseResponseVO { + @JsonProperty("output") + private Output output; + + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class Output { + @JsonProperty("stck_prpr") + private String stckPrpr; // 주식 현재가 + + @JsonProperty("prdy_vrss") + private String prdyVrss; // 전일 대비 + + @JsonProperty("prdy_vrss_sign") + private String prdyVrssSign; // 전일 대비 부호 + + @JsonProperty("prdy_ctrt") + private String prdyCtrt; // 전일 대비율 + + @JsonProperty("acml_tr_pbmn") + private String acmlTrPbmn; // 누적 거래 대금 + + @JsonProperty("acml_vol") + private String acmlVol; // 누적 거래량 + + @JsonProperty("stck_oprc") + private String stckOprc; // 주식 시가 + + @JsonProperty("stck_hgpr") + private String stckHgpr; // 주식 최고가 + + @JsonProperty("stck_lwpr") + private String stckLwpr; // 주식 최저가 + + @JsonProperty("stck_mxpr") + private String stckMxpr; // 주식 상한가 + + @JsonProperty("stck_llam") + private String stckLlam; // 주식 하한가 + + @JsonProperty("stck_sdpr") + private String stckSdpr; // 주식 기준가 + + @JsonProperty("wghn_avrg_stck_prc") + private String wghnAvrgStckPrc; // 가중 평균 주식 가격 + + @JsonProperty("hts_frgn_ehrt") + private String htsFrgnEhrt; // HTS 외국인 소진율 + + @JsonProperty("frgn_ntby_qty") + private String frgnNtbyQty; // 외국인 순매수 수량 + + @JsonProperty("pgtr_ntby_qty") + private String pgtrNtbyQty; // 프로그램매매 순매수 수량 + + @JsonProperty("stck_dryy_hgpr") + private String stckDryyHgpr; // 주식 연중 최고가 + + @JsonProperty("stck_dryy_lwpr") + private String stckDryyLwpr; // 주식 연중 최저가 + + @JsonProperty("w52_hgpr") + private String w52Hgpr; // 52주일 최고가 + + @JsonProperty("w52_lwpr") + private String w52Lwpr; // 52주일 최저가 + + @JsonProperty("whol_loan_rmnd_rate") + private String wholLoanRmndRate; // 전체 융자 잔고 비율 + + @JsonProperty("ssts_yn") + private String sstsYn; // 공매도가능여부 + + @JsonProperty("stck_shrn_iscd") + private String stckShrnIscd; // 주식 단축 종목코드 + + @JsonProperty("invt_caful_yn") + private String invtCafulYn; // 투자유의여부 + + @JsonProperty("mrkt_warn_cls_code") + private String mrktWarnClsCode; // 시장경고코드 + + @JsonProperty("short_over_yn") + private String shortOverYn; // 단기과열여부 + + @JsonProperty("sltr_yn") + private String sltrYn; // 정리매매여부 + } + +} \ No newline at end of file diff --git a/src/main/java/com/flab/mars/db/entity/Output.java b/src/main/java/com/flab/mars/db/entity/Output.java new file mode 100644 index 0000000..856c45c --- /dev/null +++ b/src/main/java/com/flab/mars/db/entity/Output.java @@ -0,0 +1,95 @@ +package com.flab.mars.db.entity; + + +import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; +import lombok.*; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Builder +@Embeddable +public class Output { + + @Column(name = "stck_prpr") + private String stckPrpr; // 주식 현재가 + + @Column(name = "prdy_vrss") + private String prdyVrss; // 전일 대비 + + @Column(name = "prdy_vrss_sign") + private String prdyVrssSign; // 전일 대비 부호 + + @Column(name = "prdy_ctrt") + private String prdyCtrt; // 전일 대비율 + + @Column(name = "acml_tr_pbmn") + private String acmlTrPbmn; // 누적 거래 대금 + + @Column(name = "acml_vol") + private String acmlVol; // 누적 거래량 + + @Column(name = "stck_oprc") + private String stckOprc; // 주식 시가 + + @Column(name = "stck_hgpr") + private String stckHgpr; // 주식 최고가 + + @Column(name = "stck_lwpr") + private String stckLwpr; // 주식 최저가 + + @Column(name = "stck_mxpr") + private String stckMxpr; // 주식 상한가 + + @Column(name = "stck_llam") + private String stckLlam; // 주식 하한가 + + @Column(name = "stck_sdpr") + private String stckSdpr; // 주식 기준가 + + @Column(name = "wghn_avrg_stck_prc") + private String wghnAvrgStckPrc; // 가중 평균 주식 가격 + + @Column(name = "hts_frgn_ehrt") + private String htsFrgnEhrt; // HTS 외국인 소진율 + + @Column(name = "frgn_ntby_qty") + private String frgnNtbyQty; // 외국인 순매수 수량 + + @Column(name = "pgtr_ntby_qty") + private String pgtrNtbyQty; // 프로그램매매 순매수 수량 + + @Column(name = "stck_dryy_hgpr") + private String stckDryyHgpr; // 주식 연중 최고가 + + @Column(name = "stck_dryy_lwpr") + private String stckDryyLwpr; // 주식 연중 최저가 + + @Column(name = "w52_hgpr") + private String w52Hgpr; // 52주일 최고가 + + @Column(name = "w52_lwpr") + private String w52Lwpr; // 52주일 최저가 + + @Column(name = "whol_loan_rmnd_rate") + private String wholLoanRmndRate; // 전체 융자 잔고 비율 + + @Column(name = "ssts_yn") + private String sstsYn; // 공매도가능여부 + + @Column(name = "stck_shrn_iscd") + private String stckShrnIscd; // 주식 단축 종목코드 + + @Column(name = "invt_caful_yn") + private String invtCafulYn; // 투자유의여부 + + @Column(name = "mrkt_warn_cls_code") + private String mrktWarnClsCode; // 시장경고코드 + + @Column(name = "short_over_yn") + private String shortOverYn; // 단기과열여부 + + @Column(name = "sltr_yn") + private String sltrYn; // 정리매매여부 +} diff --git a/src/main/java/com/flab/mars/db/entity/StockPriceChartEntity.java b/src/main/java/com/flab/mars/db/entity/StockPriceChartEntity.java new file mode 100644 index 0000000..75f680e --- /dev/null +++ b/src/main/java/com/flab/mars/db/entity/StockPriceChartEntity.java @@ -0,0 +1,48 @@ +package com.flab.mars.db.entity; + +import jakarta.persistence.*; +import lombok.*; + +import java.time.LocalDateTime; + +@Getter +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Builder +@Table(name = "stock_price_chart") +public class StockPriceChartEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "stock_code", nullable = false) + private String stockCode; // 종목 코드 (예: AAPL, 005930) + + + @Column(name = "rt_cd", nullable = false) + private String rtCd; // 응답 코드 + + @Column(name = "msg1", nullable = false) + private String msg1; // 응답 메시지 + + @Embedded + private Output output; + + @Column(name = "created_at", updatable = false) + private LocalDateTime createdAt; // 생성일 + + @Column(name = "updated_at") + private LocalDateTime updatedAt; // 수정일 + + @PrePersist + protected void onCreate() { + this.createdAt = LocalDateTime.now(); + } + + @PreUpdate + protected void onUpdate() { + this.updatedAt = LocalDateTime.now(); + } +} diff --git a/src/main/java/com/flab/mars/db/repository/StockPriceChartRepository.java b/src/main/java/com/flab/mars/db/repository/StockPriceChartRepository.java new file mode 100644 index 0000000..77e7276 --- /dev/null +++ b/src/main/java/com/flab/mars/db/repository/StockPriceChartRepository.java @@ -0,0 +1,7 @@ +package com.flab.mars.db.repository; + +import com.flab.mars.db.entity.StockPriceChartEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface StockPriceChartRepository extends JpaRepository { +} diff --git a/src/main/java/com/flab/mars/domain/service/StockService.java b/src/main/java/com/flab/mars/domain/service/StockService.java index 45a9bd8..4cfe65d 100644 --- a/src/main/java/com/flab/mars/domain/service/StockService.java +++ b/src/main/java/com/flab/mars/domain/service/StockService.java @@ -2,24 +2,32 @@ import com.flab.mars.client.KISClient; import com.flab.mars.client.KISConfig; -import com.flab.mars.domain.vo.StockPrice; +import com.flab.mars.client.KisPriceResponseVO; +import com.flab.mars.db.entity.*; +import com.flab.mars.db.repository.StockPriceChartRepository; import com.flab.mars.domain.vo.TokenInfo; import com.flab.mars.domain.vo.response.StockFluctuationResponseVO; +import com.flab.mars.domain.vo.response.StockPriceResponseVO; import com.flab.mars.exception.AuthException; import com.flab.mars.support.SessionUtil; import jakarta.servlet.http.HttpSession; + import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor +@Transactional(readOnly = true) public class StockService { private final KISClient kisClient; private final KISConfig kisConfig; + private final StockPriceChartRepository stockPriceChartRepository; + public void getAccessToken(TokenInfo tokenInfo, HttpSession session) { String accessToken = kisClient.getAccessToken(tokenInfo.getAppKey(), tokenInfo.getAppSecret(), kisConfig.getGrantType()); @@ -27,14 +35,65 @@ public void getAccessToken(TokenInfo tokenInfo, HttpSession session) { SessionUtil.setSessionAccessToKenValue(session, tokenInfo); } - public StockPrice getStockPrice(String stockCode, HttpSession session) { + // 실시간 주식 현재가 가져오기 + public StockPriceResponseVO getStockPrice(String stockCode, HttpSession session) { TokenInfo tokenInfo = SessionUtil.getSessionAccessToKenValue(session); + + // TODO userInterceptor 로 빼기 if(tokenInfo == null) { throw new AuthException("로그인에 실패했습니다. ACCESS 토큰을 가져올 수 없습니다."); } + KisPriceResponseVO stockPrice = kisClient.getStockPrice(tokenInfo.getAccessToken(), tokenInfo.getAppKey(), tokenInfo.getAppSecret(), stockCode); + + return insertCurrentStockPrice(stockPrice, stockCode); + } + + @Transactional + public StockPriceResponseVO insertCurrentStockPrice(KisPriceResponseVO stockPrice, String stockCode) { + // Output 객체 생성 + Output output = Output.builder() + .stckPrpr(stockPrice.getOutput().getStckPrpr()) // 주식 현재가 + .prdyVrss(stockPrice.getOutput().getPrdyVrss()) // 전일 대비 + .prdyVrssSign(stockPrice.getOutput().getPrdyVrssSign()) // 전일 대비 부호 + .prdyCtrt(stockPrice.getOutput().getPrdyCtrt()) // 전일 대비율 + .acmlTrPbmn(stockPrice.getOutput().getAcmlTrPbmn()) // 누적 거래 대금 + .acmlVol(stockPrice.getOutput().getAcmlVol()) // 누적 거래량 + .stckOprc(stockPrice.getOutput().getStckOprc()) // 주식 시가 + .stckHgpr(stockPrice.getOutput().getStckHgpr()) // 주식 최고가 + .stckLwpr(stockPrice.getOutput().getStckLwpr()) // 주식 최저가 + .stckMxpr(stockPrice.getOutput().getStckMxpr()) // 주식 상한가 + .stckLlam(stockPrice.getOutput().getStckLlam()) // 주식 하한가 + .stckSdpr(stockPrice.getOutput().getStckSdpr()) // 주식 기준가 + .wghnAvrgStckPrc(stockPrice.getOutput().getWghnAvrgStckPrc()) // 가중 평균 주식 가격 + .htsFrgnEhrt(stockPrice.getOutput().getHtsFrgnEhrt()) // HTS 외국인 소진율 + .frgnNtbyQty(stockPrice.getOutput().getFrgnNtbyQty()) // 외국인 순매수 수량 + .pgtrNtbyQty(stockPrice.getOutput().getPgtrNtbyQty()) // 프로그램매매 순매수 수량 + .stckDryyHgpr(stockPrice.getOutput().getStckDryyHgpr()) // 주식 연중 최고가 + .stckDryyLwpr(stockPrice.getOutput().getStckDryyLwpr()) // 주식 연중 최저가 + .w52Hgpr(stockPrice.getOutput().getW52Hgpr()) // 52주 최고가 + .w52Lwpr(stockPrice.getOutput().getW52Lwpr()) // 52주 최저가 + .wholLoanRmndRate(stockPrice.getOutput().getWholLoanRmndRate()) // 전체 융자 잔고 비율 + .sstsYn(stockPrice.getOutput().getSstsYn()) // 공매도 가능 여부 + .stckShrnIscd(stockPrice.getOutput().getStckShrnIscd()) // 주식 단축 종목코드 + .invtCafulYn(stockPrice.getOutput().getInvtCafulYn()) // 투자유의 여부 + .mrktWarnClsCode(stockPrice.getOutput().getMrktWarnClsCode()) // 시장 경고 코드 + .shortOverYn(stockPrice.getOutput().getShortOverYn()) // 단기과열 여부 + .sltrYn(stockPrice.getOutput().getSltrYn()) // 정리매매 여부 + .build(); + + + StockPriceChartEntity stockPriceChartEntity = StockPriceChartEntity.builder() + .stockCode(stockCode) // 주식 코드 + .rtCd(stockPrice.getRtCd()) // 응답 코드 + .msg1(stockPrice.getMsg1()) // 응답 메시지 + .output(output) // 주식 데이터 + .build(); + + + StockPriceChartEntity savedEntity = stockPriceChartRepository.save(stockPriceChartEntity); - return kisClient.getStockPrice(tokenInfo.getAccessToken(), tokenInfo.getAppKey(), tokenInfo.getAppSecret(), stockCode); + return StockPriceResponseVO.toVO(savedEntity); } public StockFluctuationResponseVO getFluctuationRanking(String url, HttpSession session) { diff --git a/src/main/java/com/flab/mars/domain/vo/response/StockPriceResponseVO.java b/src/main/java/com/flab/mars/domain/vo/response/StockPriceResponseVO.java new file mode 100644 index 0000000..1eb345f --- /dev/null +++ b/src/main/java/com/flab/mars/domain/vo/response/StockPriceResponseVO.java @@ -0,0 +1,113 @@ +package com.flab.mars.domain.vo.response; + + +import com.flab.mars.db.entity.StockPriceChartEntity; +import lombok.*; + + +@EqualsAndHashCode(callSuper = true) +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class StockPriceResponseVO extends BaseResponseVO { + private Output output; + + @Getter + @NoArgsConstructor + @AllArgsConstructor + @Builder + public static class Output { + private String stckPrpr; // 주식 현재가 + + private String prdyVrss; // 전일 대비 + + private String prdyVrssSign; // 전일 대비 부호 + + private String prdyCtrt; // 전일 대비율 + + private String acmlTrPbmn; // 누적 거래 대금 + + private String acmlVol; // 누적 거래량 + + private String stckOprc; // 주식 시가 + + private String stckHgpr; // 주식 최고가 + + private String stckLwpr; // 주식 최저가 + + private String stckMxpr; // 주식 상한가 + + private String stckLlam; // 주식 하한가 + + private String stckSdpr; // 주식 기준가 + + private String wghnAvrgStckPrc; // 가중 평균 주식 가격 + + private String htsFrgnEhrt; // HTS 외국인 소진율 + + private String frgnNtbyQty; // 외국인 순매수 수량 + + private String pgtrNtbyQty; // 프로그램매매 순매수 수량 + + private String stckDryyHgpr; // 주식 연중 최고가 + + private String stckDryyLwpr; // 주식 연중 최저가 + + private String w52Hgpr; // 52주일 최고가 + + private String w52Lwpr; // 52주일 최저가 + + private String wholLoanRmndRate; // 전체 융자 잔고 비율 + + private String sstsYn; // 공매도가능여부 + + private String stckShrnIscd; // 주식 단축 종목코드 + + private String invtCafulYn; // 투자유의여부 + + private String mrktWarnClsCode; // 시장경고코드 + + private String shortOverYn; // 단기과열여부 + + private String sltrYn; // 정리매매여부 + } + + public static StockPriceResponseVO toVO(StockPriceChartEntity stockPriceChart){ + Output output = Output.builder() + .stckPrpr(stockPriceChart.getOutput().getStckPrpr()) + .prdyVrss(stockPriceChart.getOutput().getPrdyVrss()) + .prdyVrssSign(stockPriceChart.getOutput().getPrdyVrssSign()) + .prdyCtrt(stockPriceChart.getOutput().getPrdyCtrt()) + .acmlTrPbmn(stockPriceChart.getOutput().getAcmlTrPbmn()) + .acmlVol(stockPriceChart.getOutput().getAcmlVol()) + .stckOprc(stockPriceChart.getOutput().getStckOprc()) + .stckHgpr(stockPriceChart.getOutput().getStckHgpr()) + .stckLwpr(stockPriceChart.getOutput().getStckLwpr()) + .stckMxpr(stockPriceChart.getOutput().getStckMxpr()) + .stckLlam(stockPriceChart.getOutput().getStckLlam()) + .stckSdpr(stockPriceChart.getOutput().getStckSdpr()) + .wghnAvrgStckPrc(stockPriceChart.getOutput().getWghnAvrgStckPrc()) + .htsFrgnEhrt(stockPriceChart.getOutput().getHtsFrgnEhrt()) + .frgnNtbyQty(stockPriceChart.getOutput().getFrgnNtbyQty()) + .pgtrNtbyQty(stockPriceChart.getOutput().getPgtrNtbyQty()) + .stckDryyHgpr(stockPriceChart.getOutput().getStckDryyHgpr()) + .stckDryyLwpr(stockPriceChart.getOutput().getStckDryyLwpr()) + .w52Hgpr(stockPriceChart.getOutput().getW52Hgpr()) + .w52Lwpr(stockPriceChart.getOutput().getW52Lwpr()) + .wholLoanRmndRate(stockPriceChart.getOutput().getWholLoanRmndRate()) + .sstsYn(stockPriceChart.getOutput().getSstsYn()) + .stckShrnIscd(stockPriceChart.getOutput().getStckShrnIscd()) + .invtCafulYn(stockPriceChart.getOutput().getInvtCafulYn()) + .mrktWarnClsCode(stockPriceChart.getOutput().getMrktWarnClsCode()) + .shortOverYn(stockPriceChart.getOutput().getShortOverYn()) + .sltrYn(stockPriceChart.getOutput().getSltrYn()) + .build(); + + return StockPriceResponseVO.builder() + .output(output) + .build(); + } + + +} \ No newline at end of file From aa36122c1935006bb242d584b7f72dd96e466f6f Mon Sep 17 00:00:00 2001 From: hek316 Date: Sat, 21 Dec 2024 03:34:11 +0900 Subject: [PATCH 2/4] =?UTF-8?q?chore:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20import=EB=AC=B8=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mars/api/controller/StockControllerTest.java | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/test/java/com/flab/mars/api/controller/StockControllerTest.java b/src/test/java/com/flab/mars/api/controller/StockControllerTest.java index f2fce3c..cb7e57b 100644 --- a/src/test/java/com/flab/mars/api/controller/StockControllerTest.java +++ b/src/test/java/com/flab/mars/api/controller/StockControllerTest.java @@ -3,12 +3,10 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.flab.mars.api.dto.request.ApiCredentialsRequestDto; import com.flab.mars.client.KISClient; -import com.flab.mars.client.KISConfig; import com.flab.mars.domain.service.StockService; -import com.flab.mars.domain.vo.StockPrice; import com.flab.mars.domain.vo.TokenInfo; -import com.flab.mars.domain.vo.request.StockFluctuationRequestVO; import com.flab.mars.domain.vo.response.StockFluctuationResponseVO; +import com.flab.mars.domain.vo.response.StockPriceResponseVO; import jakarta.servlet.http.HttpSession; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -47,12 +45,6 @@ class StockControllerTest { @MockitoBean private KISClient kisClient; - @MockitoBean - private KISConfig kisConfig; - - @MockitoBean - private StockFluctuationRequestVO stockFluctuationRequestVO; - @Test public void testGetAccessToken_Success() throws Exception { @@ -84,10 +76,10 @@ public void testGetAccessToken_Success() throws Exception { void testGetStockPrice_Success() throws Exception { // Arrange String stockCode = "12345"; - StockPrice stockPrice = new StockPrice("00", "Success", new StockPrice.Output("100000")); // 예시로 100000 설정 + StockPriceResponseVO stockPriceResponseVO = new StockPriceResponseVO(new StockPriceResponseVO.Output()); // Mock stockService.getStockPrice() 메서드 - when(stockService.getStockPrice(eq(stockCode), any(HttpSession.class))).thenReturn(stockPrice); + when(stockService.getStockPrice(eq(stockCode), any(HttpSession.class))).thenReturn(stockPriceResponseVO); // Act & Assert mockMvc.perform(get("/api/stock/quotations/inquire-price") From a6d0f9d7da1019472483a4a55a71909ce324b794 Mon Sep 17 00:00:00 2001 From: hek316 Date: Sun, 22 Dec 2024 23:20:23 +0900 Subject: [PATCH 3/4] =?UTF-8?q?chore:=20=EC=8B=A4=EC=8B=9C=EA=B0=84=20?= =?UTF-8?q?=EC=A3=BC=EC=8B=9D=20=EC=8B=9C=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EB=B8=94=20=EA=B0=84=EC=86=8C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 불필요한 컬럼 삭제 --- .../mars/api/controller/StockController.java | 10 +- .../dto/response/StockPriceResponseDto.java | 51 ++++++++ .../java/com/flab/mars/db/entity/Output.java | 95 --------------- .../flab/mars/db/entity/PriceDataEntity.java | 39 ++++++ .../flab/mars/db/entity/PriceDataType.java | 9 ++ .../flab/mars/db/entity/StockInfoEntity.java | 21 ++++ .../mars/db/entity/StockPriceChartEntity.java | 48 -------- .../db/repository/PriceDataRepository.java | 7 ++ .../db/repository/StockInfoRepository.java | 7 ++ .../repository/StockPriceChartRepository.java | 7 -- .../mars/domain/service/StockService.java | 62 +++------- .../vo/response/PriceDataResponseVO.java | 52 ++++++++ .../vo/response/StockPriceResponseVO.java | 113 ------------------ .../api/controller/StockControllerTest.java | 7 +- 14 files changed, 213 insertions(+), 315 deletions(-) create mode 100644 src/main/java/com/flab/mars/api/dto/response/StockPriceResponseDto.java delete mode 100644 src/main/java/com/flab/mars/db/entity/Output.java create mode 100644 src/main/java/com/flab/mars/db/entity/PriceDataEntity.java create mode 100644 src/main/java/com/flab/mars/db/entity/PriceDataType.java create mode 100644 src/main/java/com/flab/mars/db/entity/StockInfoEntity.java delete mode 100644 src/main/java/com/flab/mars/db/entity/StockPriceChartEntity.java create mode 100644 src/main/java/com/flab/mars/db/repository/PriceDataRepository.java create mode 100644 src/main/java/com/flab/mars/db/repository/StockInfoRepository.java delete mode 100644 src/main/java/com/flab/mars/db/repository/StockPriceChartRepository.java create mode 100644 src/main/java/com/flab/mars/domain/vo/response/PriceDataResponseVO.java delete mode 100644 src/main/java/com/flab/mars/domain/vo/response/StockPriceResponseVO.java diff --git a/src/main/java/com/flab/mars/api/controller/StockController.java b/src/main/java/com/flab/mars/api/controller/StockController.java index db80cd9..e1c047f 100644 --- a/src/main/java/com/flab/mars/api/controller/StockController.java +++ b/src/main/java/com/flab/mars/api/controller/StockController.java @@ -4,11 +4,12 @@ import com.flab.mars.api.dto.request.StockFluctuationRequestDto; import com.flab.mars.api.dto.response.ResultAPIDto; import com.flab.mars.api.dto.response.StockFluctuationResponseDto; +import com.flab.mars.api.dto.response.StockPriceResponseDto; import com.flab.mars.domain.service.StockService; import com.flab.mars.domain.vo.TokenInfo; import com.flab.mars.domain.vo.request.StockFluctuationRequestVO; +import com.flab.mars.domain.vo.response.PriceDataResponseVO; import com.flab.mars.domain.vo.response.StockFluctuationResponseVO; -import com.flab.mars.domain.vo.response.StockPriceResponseVO; import jakarta.servlet.http.HttpSession; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; @@ -59,9 +60,10 @@ public ResponseEntity> getAccessToken(@RequestBody ApiCr * @return 주식현재가 , 누적 거래 대금, 누적 거래량, 주식 시가, 주식 최고가, 주식 최저가 등을 반환 */ @GetMapping("/quotations/inquire-price") - public ResponseEntity> getStockPrice(@RequestParam(name = "stockCode") String stockCode, HttpSession session) { - StockPriceResponseVO stockPriceResponseVO = stockService.getStockPrice(stockCode, session); - return ResponseEntity.ok(ResultAPIDto.res(HttpStatus.OK, "Success", stockPriceResponseVO)); + public ResponseEntity> getStockPrice(@RequestParam(name = "stockCode") String stockCode, HttpSession session) { + PriceDataResponseVO stockPriceResponseVO = stockService.getStockPrice(stockCode, session); + StockPriceResponseDto responseDto = StockPriceResponseDto.from(stockPriceResponseVO); + return ResponseEntity.ok(ResultAPIDto.res(HttpStatus.OK, "Success", responseDto)); } @GetMapping("/domestic-stock/ranking/fluctuation") diff --git a/src/main/java/com/flab/mars/api/dto/response/StockPriceResponseDto.java b/src/main/java/com/flab/mars/api/dto/response/StockPriceResponseDto.java new file mode 100644 index 0000000..bf525d0 --- /dev/null +++ b/src/main/java/com/flab/mars/api/dto/response/StockPriceResponseDto.java @@ -0,0 +1,51 @@ +package com.flab.mars.api.dto.response; + +import com.flab.mars.db.entity.PriceDataType; +import com.flab.mars.domain.vo.response.PriceDataResponseVO; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.time.LocalDate; + +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Getter +public class StockPriceResponseDto { + + private Long id; + + private String stockId; // StockInfoEntity의 ID와 연결되는 값 + + private PriceDataType dataType; + + private BigDecimal currentPrice; // 현재가 + private BigDecimal openPrice; // 시가 + private BigDecimal closePrice; // 종가 + private BigDecimal highPrice; // 최고가 + private BigDecimal lowPrice; // 최저가 + + private BigDecimal acmlVol; // 누적 거래량 (전체 누적 거래량) + private BigDecimal acmlTrPbmn; // 누적 거래 대금 + + private LocalDate stockBusinessDate; // 주식 영업일자 + + // PriceDataResponseVO 객체를 StockPriceResponseDto로 변환하는 메서드 + public static StockPriceResponseDto from(PriceDataResponseVO responseVO) { + return StockPriceResponseDto.builder() + .id(responseVO.getId()) + .dataType(responseVO.getDataType()) + .currentPrice(responseVO.getCurrentPrice()) + .openPrice(responseVO.getOpenPrice()) + .closePrice(responseVO.getClosePrice()) + .highPrice(responseVO.getHighPrice()) + .lowPrice(responseVO.getLowPrice()) + .acmlVol(responseVO.getAcmlVol()) + .acmlTrPbmn(responseVO.getAcmlTrPbmn()) + .stockBusinessDate(responseVO.getStockBusinessDate()) + .build(); + } +} diff --git a/src/main/java/com/flab/mars/db/entity/Output.java b/src/main/java/com/flab/mars/db/entity/Output.java deleted file mode 100644 index 856c45c..0000000 --- a/src/main/java/com/flab/mars/db/entity/Output.java +++ /dev/null @@ -1,95 +0,0 @@ -package com.flab.mars.db.entity; - - -import jakarta.persistence.Column; -import jakarta.persistence.Embeddable; -import lombok.*; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -@Builder -@Embeddable -public class Output { - - @Column(name = "stck_prpr") - private String stckPrpr; // 주식 현재가 - - @Column(name = "prdy_vrss") - private String prdyVrss; // 전일 대비 - - @Column(name = "prdy_vrss_sign") - private String prdyVrssSign; // 전일 대비 부호 - - @Column(name = "prdy_ctrt") - private String prdyCtrt; // 전일 대비율 - - @Column(name = "acml_tr_pbmn") - private String acmlTrPbmn; // 누적 거래 대금 - - @Column(name = "acml_vol") - private String acmlVol; // 누적 거래량 - - @Column(name = "stck_oprc") - private String stckOprc; // 주식 시가 - - @Column(name = "stck_hgpr") - private String stckHgpr; // 주식 최고가 - - @Column(name = "stck_lwpr") - private String stckLwpr; // 주식 최저가 - - @Column(name = "stck_mxpr") - private String stckMxpr; // 주식 상한가 - - @Column(name = "stck_llam") - private String stckLlam; // 주식 하한가 - - @Column(name = "stck_sdpr") - private String stckSdpr; // 주식 기준가 - - @Column(name = "wghn_avrg_stck_prc") - private String wghnAvrgStckPrc; // 가중 평균 주식 가격 - - @Column(name = "hts_frgn_ehrt") - private String htsFrgnEhrt; // HTS 외국인 소진율 - - @Column(name = "frgn_ntby_qty") - private String frgnNtbyQty; // 외국인 순매수 수량 - - @Column(name = "pgtr_ntby_qty") - private String pgtrNtbyQty; // 프로그램매매 순매수 수량 - - @Column(name = "stck_dryy_hgpr") - private String stckDryyHgpr; // 주식 연중 최고가 - - @Column(name = "stck_dryy_lwpr") - private String stckDryyLwpr; // 주식 연중 최저가 - - @Column(name = "w52_hgpr") - private String w52Hgpr; // 52주일 최고가 - - @Column(name = "w52_lwpr") - private String w52Lwpr; // 52주일 최저가 - - @Column(name = "whol_loan_rmnd_rate") - private String wholLoanRmndRate; // 전체 융자 잔고 비율 - - @Column(name = "ssts_yn") - private String sstsYn; // 공매도가능여부 - - @Column(name = "stck_shrn_iscd") - private String stckShrnIscd; // 주식 단축 종목코드 - - @Column(name = "invt_caful_yn") - private String invtCafulYn; // 투자유의여부 - - @Column(name = "mrkt_warn_cls_code") - private String mrktWarnClsCode; // 시장경고코드 - - @Column(name = "short_over_yn") - private String shortOverYn; // 단기과열여부 - - @Column(name = "sltr_yn") - private String sltrYn; // 정리매매여부 -} diff --git a/src/main/java/com/flab/mars/db/entity/PriceDataEntity.java b/src/main/java/com/flab/mars/db/entity/PriceDataEntity.java new file mode 100644 index 0000000..5b77cb4 --- /dev/null +++ b/src/main/java/com/flab/mars/db/entity/PriceDataEntity.java @@ -0,0 +1,39 @@ +package com.flab.mars.db.entity; + +import jakarta.persistence.*; +import lombok.*; + +import java.time.LocalDate; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Builder +@Getter +@Entity +@Table(name = "price_data") +public class PriceDataEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "stock_info_id") + private StockInfoEntity stockInfoEntity; + + @Enumerated(EnumType.STRING) + private PriceDataType dataType; // 데이터 유형 (DAY, WEEK, MONTH, YEAR) + + private String currentPrice; // 현재가 (데이터 유형이 실기간인 경우 사용) + private String openPrice; // 시가 + private String closePrice; // 종가 + private String highPrice; // 최고가 + private String lowPrice; // 최저가 + + private String acmlVol; // 누적 거래량 (전체 누적 거래량) + private String acmlTrPbmn; // 누적 거래 대금 + + @Column(name = "stock_business_date") + private LocalDate stockBusinessDate; // 주식 영업일자 + + +} diff --git a/src/main/java/com/flab/mars/db/entity/PriceDataType.java b/src/main/java/com/flab/mars/db/entity/PriceDataType.java new file mode 100644 index 0000000..cce866d --- /dev/null +++ b/src/main/java/com/flab/mars/db/entity/PriceDataType.java @@ -0,0 +1,9 @@ +package com.flab.mars.db.entity; + +public enum PriceDataType { + REALTIME, // 실시간 데이터 + DAY, // 일별 데이터 + WEEK, // 주별 데이터 + MONTH, // 월별 데이터 + YEAR // 연별 데이터 +} diff --git a/src/main/java/com/flab/mars/db/entity/StockInfoEntity.java b/src/main/java/com/flab/mars/db/entity/StockInfoEntity.java new file mode 100644 index 0000000..a017198 --- /dev/null +++ b/src/main/java/com/flab/mars/db/entity/StockInfoEntity.java @@ -0,0 +1,21 @@ +package com.flab.mars.db.entity; + +import jakarta.persistence.*; +import lombok.*; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Builder +@Getter +@Entity +@Table(name = "stock_info") +public class StockInfoEntity { + @Id + @GeneratedValue + @Column(name = "stock_info_id") + private Long id; + + private String stockCode; // 주식 코드 + private String stockName; // 주식 이름 + +} diff --git a/src/main/java/com/flab/mars/db/entity/StockPriceChartEntity.java b/src/main/java/com/flab/mars/db/entity/StockPriceChartEntity.java deleted file mode 100644 index 75f680e..0000000 --- a/src/main/java/com/flab/mars/db/entity/StockPriceChartEntity.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.flab.mars.db.entity; - -import jakarta.persistence.*; -import lombok.*; - -import java.time.LocalDateTime; - -@Getter -@Entity -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -@Builder -@Table(name = "stock_price_chart") -public class StockPriceChartEntity { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Column(name = "stock_code", nullable = false) - private String stockCode; // 종목 코드 (예: AAPL, 005930) - - - @Column(name = "rt_cd", nullable = false) - private String rtCd; // 응답 코드 - - @Column(name = "msg1", nullable = false) - private String msg1; // 응답 메시지 - - @Embedded - private Output output; - - @Column(name = "created_at", updatable = false) - private LocalDateTime createdAt; // 생성일 - - @Column(name = "updated_at") - private LocalDateTime updatedAt; // 수정일 - - @PrePersist - protected void onCreate() { - this.createdAt = LocalDateTime.now(); - } - - @PreUpdate - protected void onUpdate() { - this.updatedAt = LocalDateTime.now(); - } -} diff --git a/src/main/java/com/flab/mars/db/repository/PriceDataRepository.java b/src/main/java/com/flab/mars/db/repository/PriceDataRepository.java new file mode 100644 index 0000000..3257011 --- /dev/null +++ b/src/main/java/com/flab/mars/db/repository/PriceDataRepository.java @@ -0,0 +1,7 @@ +package com.flab.mars.db.repository; + +import com.flab.mars.db.entity.PriceDataEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PriceDataRepository extends JpaRepository { +} diff --git a/src/main/java/com/flab/mars/db/repository/StockInfoRepository.java b/src/main/java/com/flab/mars/db/repository/StockInfoRepository.java new file mode 100644 index 0000000..85ca888 --- /dev/null +++ b/src/main/java/com/flab/mars/db/repository/StockInfoRepository.java @@ -0,0 +1,7 @@ +package com.flab.mars.db.repository; + +import com.flab.mars.db.entity.StockInfoEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface StockInfoRepository extends JpaRepository { +} diff --git a/src/main/java/com/flab/mars/db/repository/StockPriceChartRepository.java b/src/main/java/com/flab/mars/db/repository/StockPriceChartRepository.java deleted file mode 100644 index 77e7276..0000000 --- a/src/main/java/com/flab/mars/db/repository/StockPriceChartRepository.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.flab.mars.db.repository; - -import com.flab.mars.db.entity.StockPriceChartEntity; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface StockPriceChartRepository extends JpaRepository { -} diff --git a/src/main/java/com/flab/mars/domain/service/StockService.java b/src/main/java/com/flab/mars/domain/service/StockService.java index 4cfe65d..79edd1f 100644 --- a/src/main/java/com/flab/mars/domain/service/StockService.java +++ b/src/main/java/com/flab/mars/domain/service/StockService.java @@ -3,11 +3,12 @@ import com.flab.mars.client.KISClient; import com.flab.mars.client.KISConfig; import com.flab.mars.client.KisPriceResponseVO; -import com.flab.mars.db.entity.*; -import com.flab.mars.db.repository.StockPriceChartRepository; +import com.flab.mars.db.entity.PriceDataEntity; +import com.flab.mars.db.entity.PriceDataType; +import com.flab.mars.db.repository.PriceDataRepository; import com.flab.mars.domain.vo.TokenInfo; +import com.flab.mars.domain.vo.response.PriceDataResponseVO; import com.flab.mars.domain.vo.response.StockFluctuationResponseVO; -import com.flab.mars.domain.vo.response.StockPriceResponseVO; import com.flab.mars.exception.AuthException; import com.flab.mars.support.SessionUtil; import jakarta.servlet.http.HttpSession; @@ -26,7 +27,7 @@ public class StockService { private final KISConfig kisConfig; - private final StockPriceChartRepository stockPriceChartRepository; + private final PriceDataRepository priceDataRepository; public void getAccessToken(TokenInfo tokenInfo, HttpSession session) { @@ -36,7 +37,7 @@ public void getAccessToken(TokenInfo tokenInfo, HttpSession session) { } // 실시간 주식 현재가 가져오기 - public StockPriceResponseVO getStockPrice(String stockCode, HttpSession session) { + public PriceDataResponseVO getStockPrice(String stockCode, HttpSession session) { TokenInfo tokenInfo = SessionUtil.getSessionAccessToKenValue(session); @@ -50,50 +51,21 @@ public StockPriceResponseVO getStockPrice(String stockCode, HttpSession session) } @Transactional - public StockPriceResponseVO insertCurrentStockPrice(KisPriceResponseVO stockPrice, String stockCode) { - // Output 객체 생성 - Output output = Output.builder() - .stckPrpr(stockPrice.getOutput().getStckPrpr()) // 주식 현재가 - .prdyVrss(stockPrice.getOutput().getPrdyVrss()) // 전일 대비 - .prdyVrssSign(stockPrice.getOutput().getPrdyVrssSign()) // 전일 대비 부호 - .prdyCtrt(stockPrice.getOutput().getPrdyCtrt()) // 전일 대비율 - .acmlTrPbmn(stockPrice.getOutput().getAcmlTrPbmn()) // 누적 거래 대금 + public PriceDataResponseVO insertCurrentStockPrice(KisPriceResponseVO stockPrice, String stockCode) { + + PriceDataEntity priceDataEntity = PriceDataEntity.builder() + .dataType(PriceDataType.REALTIME) // 실시간 + .currentPrice(stockPrice.getOutput().getStckPrpr()) // 현재가 + .openPrice(stockPrice.getOutput().getStckOprc()) // 주식 시가 + .highPrice(stockPrice.getOutput().getStckHgpr()) // 주식 최고가 + .lowPrice(stockPrice.getOutput().getStckLwpr()) // 주식 최저가 .acmlVol(stockPrice.getOutput().getAcmlVol()) // 누적 거래량 - .stckOprc(stockPrice.getOutput().getStckOprc()) // 주식 시가 - .stckHgpr(stockPrice.getOutput().getStckHgpr()) // 주식 최고가 - .stckLwpr(stockPrice.getOutput().getStckLwpr()) // 주식 최저가 - .stckMxpr(stockPrice.getOutput().getStckMxpr()) // 주식 상한가 - .stckLlam(stockPrice.getOutput().getStckLlam()) // 주식 하한가 - .stckSdpr(stockPrice.getOutput().getStckSdpr()) // 주식 기준가 - .wghnAvrgStckPrc(stockPrice.getOutput().getWghnAvrgStckPrc()) // 가중 평균 주식 가격 - .htsFrgnEhrt(stockPrice.getOutput().getHtsFrgnEhrt()) // HTS 외국인 소진율 - .frgnNtbyQty(stockPrice.getOutput().getFrgnNtbyQty()) // 외국인 순매수 수량 - .pgtrNtbyQty(stockPrice.getOutput().getPgtrNtbyQty()) // 프로그램매매 순매수 수량 - .stckDryyHgpr(stockPrice.getOutput().getStckDryyHgpr()) // 주식 연중 최고가 - .stckDryyLwpr(stockPrice.getOutput().getStckDryyLwpr()) // 주식 연중 최저가 - .w52Hgpr(stockPrice.getOutput().getW52Hgpr()) // 52주 최고가 - .w52Lwpr(stockPrice.getOutput().getW52Lwpr()) // 52주 최저가 - .wholLoanRmndRate(stockPrice.getOutput().getWholLoanRmndRate()) // 전체 융자 잔고 비율 - .sstsYn(stockPrice.getOutput().getSstsYn()) // 공매도 가능 여부 - .stckShrnIscd(stockPrice.getOutput().getStckShrnIscd()) // 주식 단축 종목코드 - .invtCafulYn(stockPrice.getOutput().getInvtCafulYn()) // 투자유의 여부 - .mrktWarnClsCode(stockPrice.getOutput().getMrktWarnClsCode()) // 시장 경고 코드 - .shortOverYn(stockPrice.getOutput().getShortOverYn()) // 단기과열 여부 - .sltrYn(stockPrice.getOutput().getSltrYn()) // 정리매매 여부 - .build(); - - - StockPriceChartEntity stockPriceChartEntity = StockPriceChartEntity.builder() - .stockCode(stockCode) // 주식 코드 - .rtCd(stockPrice.getRtCd()) // 응답 코드 - .msg1(stockPrice.getMsg1()) // 응답 메시지 - .output(output) // 주식 데이터 + .acmlTrPbmn(stockPrice.getOutput().getAcmlTrPbmn()) // 누적 거래 대금 .build(); + PriceDataEntity savedpriceDataEntity = priceDataRepository.save(priceDataEntity); - StockPriceChartEntity savedEntity = stockPriceChartRepository.save(stockPriceChartEntity); - - return StockPriceResponseVO.toVO(savedEntity); + return PriceDataResponseVO.toVO(savedpriceDataEntity); } public StockFluctuationResponseVO getFluctuationRanking(String url, HttpSession session) { diff --git a/src/main/java/com/flab/mars/domain/vo/response/PriceDataResponseVO.java b/src/main/java/com/flab/mars/domain/vo/response/PriceDataResponseVO.java new file mode 100644 index 0000000..397f3ea --- /dev/null +++ b/src/main/java/com/flab/mars/domain/vo/response/PriceDataResponseVO.java @@ -0,0 +1,52 @@ +package com.flab.mars.domain.vo.response; + +import com.flab.mars.db.entity.PriceDataEntity; +import com.flab.mars.db.entity.PriceDataType; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.time.LocalDate; + +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Getter +public class PriceDataResponseVO { + + private Long id; + + private String stockInfoId; // StockInfoEntity의 ID와 연결되는 값 + + private PriceDataType dataType; // 데이터 유형 (DAY, WEEK, MONTH, YEAR) + + private BigDecimal currentPrice; // 현재가 + private BigDecimal openPrice; // 시가 + private BigDecimal closePrice; // 종가 + private BigDecimal highPrice; // 최고가 + private BigDecimal lowPrice; // 최저가 + + private BigDecimal acmlVol; // 누적 거래량 (전체 누적 거래량) + private BigDecimal acmlTrPbmn; // 누적 거래 대금 + + private LocalDate stockBusinessDate; // 주식 영업일자 + + + public static PriceDataResponseVO toVO(PriceDataEntity entity) { + return PriceDataResponseVO.builder() + .id(entity.getId()) + //.stockInfoId(entity.getStockInfoEntity().getId().toString()) // TODO : StockPriceInfoEntity의 ID를 문자열로 변환 + .dataType(entity.getDataType()) + .currentPrice(new BigDecimal(entity.getCurrentPrice())) + .openPrice(new BigDecimal(entity.getOpenPrice())) + .closePrice(entity.getClosePrice() != null ? new BigDecimal(entity.getClosePrice()) : BigDecimal.ZERO) // 실시간 가격일 경우 종가 없음 + .highPrice(new BigDecimal(entity.getHighPrice())) + .lowPrice(new BigDecimal(entity.getLowPrice())) + .acmlVol(new BigDecimal(entity.getAcmlVol())) + .acmlTrPbmn(new BigDecimal(entity.getAcmlTrPbmn())) + .stockBusinessDate(entity.getStockBusinessDate()) + .build(); + } +} diff --git a/src/main/java/com/flab/mars/domain/vo/response/StockPriceResponseVO.java b/src/main/java/com/flab/mars/domain/vo/response/StockPriceResponseVO.java deleted file mode 100644 index 1eb345f..0000000 --- a/src/main/java/com/flab/mars/domain/vo/response/StockPriceResponseVO.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.flab.mars.domain.vo.response; - - -import com.flab.mars.db.entity.StockPriceChartEntity; -import lombok.*; - - -@EqualsAndHashCode(callSuper = true) -@Getter -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class StockPriceResponseVO extends BaseResponseVO { - private Output output; - - @Getter - @NoArgsConstructor - @AllArgsConstructor - @Builder - public static class Output { - private String stckPrpr; // 주식 현재가 - - private String prdyVrss; // 전일 대비 - - private String prdyVrssSign; // 전일 대비 부호 - - private String prdyCtrt; // 전일 대비율 - - private String acmlTrPbmn; // 누적 거래 대금 - - private String acmlVol; // 누적 거래량 - - private String stckOprc; // 주식 시가 - - private String stckHgpr; // 주식 최고가 - - private String stckLwpr; // 주식 최저가 - - private String stckMxpr; // 주식 상한가 - - private String stckLlam; // 주식 하한가 - - private String stckSdpr; // 주식 기준가 - - private String wghnAvrgStckPrc; // 가중 평균 주식 가격 - - private String htsFrgnEhrt; // HTS 외국인 소진율 - - private String frgnNtbyQty; // 외국인 순매수 수량 - - private String pgtrNtbyQty; // 프로그램매매 순매수 수량 - - private String stckDryyHgpr; // 주식 연중 최고가 - - private String stckDryyLwpr; // 주식 연중 최저가 - - private String w52Hgpr; // 52주일 최고가 - - private String w52Lwpr; // 52주일 최저가 - - private String wholLoanRmndRate; // 전체 융자 잔고 비율 - - private String sstsYn; // 공매도가능여부 - - private String stckShrnIscd; // 주식 단축 종목코드 - - private String invtCafulYn; // 투자유의여부 - - private String mrktWarnClsCode; // 시장경고코드 - - private String shortOverYn; // 단기과열여부 - - private String sltrYn; // 정리매매여부 - } - - public static StockPriceResponseVO toVO(StockPriceChartEntity stockPriceChart){ - Output output = Output.builder() - .stckPrpr(stockPriceChart.getOutput().getStckPrpr()) - .prdyVrss(stockPriceChart.getOutput().getPrdyVrss()) - .prdyVrssSign(stockPriceChart.getOutput().getPrdyVrssSign()) - .prdyCtrt(stockPriceChart.getOutput().getPrdyCtrt()) - .acmlTrPbmn(stockPriceChart.getOutput().getAcmlTrPbmn()) - .acmlVol(stockPriceChart.getOutput().getAcmlVol()) - .stckOprc(stockPriceChart.getOutput().getStckOprc()) - .stckHgpr(stockPriceChart.getOutput().getStckHgpr()) - .stckLwpr(stockPriceChart.getOutput().getStckLwpr()) - .stckMxpr(stockPriceChart.getOutput().getStckMxpr()) - .stckLlam(stockPriceChart.getOutput().getStckLlam()) - .stckSdpr(stockPriceChart.getOutput().getStckSdpr()) - .wghnAvrgStckPrc(stockPriceChart.getOutput().getWghnAvrgStckPrc()) - .htsFrgnEhrt(stockPriceChart.getOutput().getHtsFrgnEhrt()) - .frgnNtbyQty(stockPriceChart.getOutput().getFrgnNtbyQty()) - .pgtrNtbyQty(stockPriceChart.getOutput().getPgtrNtbyQty()) - .stckDryyHgpr(stockPriceChart.getOutput().getStckDryyHgpr()) - .stckDryyLwpr(stockPriceChart.getOutput().getStckDryyLwpr()) - .w52Hgpr(stockPriceChart.getOutput().getW52Hgpr()) - .w52Lwpr(stockPriceChart.getOutput().getW52Lwpr()) - .wholLoanRmndRate(stockPriceChart.getOutput().getWholLoanRmndRate()) - .sstsYn(stockPriceChart.getOutput().getSstsYn()) - .stckShrnIscd(stockPriceChart.getOutput().getStckShrnIscd()) - .invtCafulYn(stockPriceChart.getOutput().getInvtCafulYn()) - .mrktWarnClsCode(stockPriceChart.getOutput().getMrktWarnClsCode()) - .shortOverYn(stockPriceChart.getOutput().getShortOverYn()) - .sltrYn(stockPriceChart.getOutput().getSltrYn()) - .build(); - - return StockPriceResponseVO.builder() - .output(output) - .build(); - } - - -} \ No newline at end of file diff --git a/src/test/java/com/flab/mars/api/controller/StockControllerTest.java b/src/test/java/com/flab/mars/api/controller/StockControllerTest.java index cb7e57b..a43142f 100644 --- a/src/test/java/com/flab/mars/api/controller/StockControllerTest.java +++ b/src/test/java/com/flab/mars/api/controller/StockControllerTest.java @@ -2,11 +2,12 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.flab.mars.api.dto.request.ApiCredentialsRequestDto; +import com.flab.mars.api.dto.response.StockPriceResponseDto; import com.flab.mars.client.KISClient; import com.flab.mars.domain.service.StockService; import com.flab.mars.domain.vo.TokenInfo; +import com.flab.mars.domain.vo.response.PriceDataResponseVO; import com.flab.mars.domain.vo.response.StockFluctuationResponseVO; -import com.flab.mars.domain.vo.response.StockPriceResponseVO; import jakarta.servlet.http.HttpSession; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -76,10 +77,10 @@ public void testGetAccessToken_Success() throws Exception { void testGetStockPrice_Success() throws Exception { // Arrange String stockCode = "12345"; - StockPriceResponseVO stockPriceResponseVO = new StockPriceResponseVO(new StockPriceResponseVO.Output()); + PriceDataResponseVO priceDataResponseVO = new PriceDataResponseVO(); // Mock stockService.getStockPrice() 메서드 - when(stockService.getStockPrice(eq(stockCode), any(HttpSession.class))).thenReturn(stockPriceResponseVO); + when(stockService.getStockPrice(eq(stockCode), any(HttpSession.class))).thenReturn(priceDataResponseVO); // Act & Assert mockMvc.perform(get("/api/stock/quotations/inquire-price") From 4447d6b752b1e7867c5e90dbac52f83f21dae20f Mon Sep 17 00:00:00 2001 From: hek316 Date: Mon, 30 Dec 2024 18:55:20 +0900 Subject: [PATCH 4/4] =?UTF-8?q?chore:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=9D=91=EB=8B=B5=20=ED=95=84=EB=93=9C=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20(=EB=8F=84=EB=A9=94=EC=9D=B8=EC=97=90=20=20?= =?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=9C=20=EB=8D=B0=EC=9D=B4=ED=84=B0?= =?UTF-8?q?=EB=A7=8C=20=EC=9A=B0=EC=84=A0=20=EC=B7=A8=EA=B8=89)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../flab/mars/client/KisPriceResponseVO.java | 53 ------------------- 1 file changed, 53 deletions(-) diff --git a/src/main/java/com/flab/mars/client/KisPriceResponseVO.java b/src/main/java/com/flab/mars/client/KisPriceResponseVO.java index 6bf7fde..4ecba65 100644 --- a/src/main/java/com/flab/mars/client/KisPriceResponseVO.java +++ b/src/main/java/com/flab/mars/client/KisPriceResponseVO.java @@ -48,59 +48,6 @@ public static class Output { @JsonProperty("stck_lwpr") private String stckLwpr; // 주식 최저가 - @JsonProperty("stck_mxpr") - private String stckMxpr; // 주식 상한가 - - @JsonProperty("stck_llam") - private String stckLlam; // 주식 하한가 - - @JsonProperty("stck_sdpr") - private String stckSdpr; // 주식 기준가 - - @JsonProperty("wghn_avrg_stck_prc") - private String wghnAvrgStckPrc; // 가중 평균 주식 가격 - - @JsonProperty("hts_frgn_ehrt") - private String htsFrgnEhrt; // HTS 외국인 소진율 - - @JsonProperty("frgn_ntby_qty") - private String frgnNtbyQty; // 외국인 순매수 수량 - - @JsonProperty("pgtr_ntby_qty") - private String pgtrNtbyQty; // 프로그램매매 순매수 수량 - - @JsonProperty("stck_dryy_hgpr") - private String stckDryyHgpr; // 주식 연중 최고가 - - @JsonProperty("stck_dryy_lwpr") - private String stckDryyLwpr; // 주식 연중 최저가 - - @JsonProperty("w52_hgpr") - private String w52Hgpr; // 52주일 최고가 - - @JsonProperty("w52_lwpr") - private String w52Lwpr; // 52주일 최저가 - - @JsonProperty("whol_loan_rmnd_rate") - private String wholLoanRmndRate; // 전체 융자 잔고 비율 - - @JsonProperty("ssts_yn") - private String sstsYn; // 공매도가능여부 - - @JsonProperty("stck_shrn_iscd") - private String stckShrnIscd; // 주식 단축 종목코드 - - @JsonProperty("invt_caful_yn") - private String invtCafulYn; // 투자유의여부 - - @JsonProperty("mrkt_warn_cls_code") - private String mrktWarnClsCode; // 시장경고코드 - - @JsonProperty("short_over_yn") - private String shortOverYn; // 단기과열여부 - - @JsonProperty("sltr_yn") - private String sltrYn; // 정리매매여부 } } \ No newline at end of file