Skip to content

Commit

Permalink
Merge pull request #96 from SWM-WeLike2Coding/dev_deploy
Browse files Browse the repository at this point in the history
conf: 운영 서버 배포를 위한 머지 작업
  • Loading branch information
kjungw1025 authored Oct 30, 2024
2 parents 240e305 + 587161a commit 1a3437a
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.wl2c.elswhereproductservice.client.analysis.api;

import com.wl2c.elswhereproductservice.client.analysis.dto.response.ResponseAIResultDto;
import com.wl2c.elswhereproductservice.domain.product.model.dto.request.RequestProductIdListDto;
import jakarta.validation.Valid;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.List;

@FeignClient(name = "analysis-service")
public interface AnalysisServiceClient {

@PostMapping("/v1/ai/list")
List<ResponseAIResultDto> getAIResultList(@Valid @RequestBody RequestProductIdListDto requestProductIdListDto);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.wl2c.elswhereproductservice.client.analysis.dto.response;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Getter;

import java.math.BigDecimal;

@Getter
@Builder
public class ResponseAIResultDto {

@Schema(description = "AI 결과 id", example = "1")
private final Long AIResultId;

@Schema(description = "상품 id", example = "1")
private final Long productId;

@Schema(description = "AI가 판단한 스텝다운 상품 안전도", example = "0.76")
private final BigDecimal safetyScore;

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.wl2c.elswhereproductservice.domain.product.controller;

import com.wl2c.elswhereproductservice.domain.product.exception.TodayReceivedProductsNotFoundException;
import com.wl2c.elswhereproductservice.domain.product.model.dto.list.SummarizedOnSaleProductDto;
import com.wl2c.elswhereproductservice.domain.product.model.dto.list.SummarizedProductDto;
import com.wl2c.elswhereproductservice.domain.product.model.dto.list.SummarizedProductForHoldingDto;
import com.wl2c.elswhereproductservice.domain.product.model.dto.request.RequestProductIdListDto;
Expand Down Expand Up @@ -50,14 +51,19 @@ public class ProductController {
* 수익률순 : profit
* 청약 마감일순 : deadline
* </p>
* <p>
* <br/>
* 스텝다운 유형의 상품에 대해서 AI가 분석한 각 상품의 safetyScore를 제공합니다. <br/>
* 스텝다운 유형이 아니거나 스텝다운 유형이지만 분석 정보가 없는 경우에는 null 값으로 제공됩니다. <br/>
* </p>
*
* @param type 정렬 타입
* @return 페이징된 청약 중인 상품 목록
*/
@GetMapping("/on-sale")
public ResponsePage<SummarizedProductDto> listByOnSale(@RequestParam(name = "type") String type,
@ParameterObject Pageable pageable) {
Page<SummarizedProductDto> result = productService.listByOnSale(type, pageable);
public ResponsePage<SummarizedOnSaleProductDto> listByOnSale(@RequestParam(name = "type") String type,
@ParameterObject Pageable pageable) {
Page<SummarizedOnSaleProductDto> result = productService.listByOnSale(type, pageable);
return new ResponsePage<>(result);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.wl2c.elswhereproductservice.domain.product.model.dto.list;

import com.querydsl.core.annotations.QueryProjection;
import com.wl2c.elswhereproductservice.domain.product.model.ProductType;
import com.wl2c.elswhereproductservice.domain.product.model.entity.Product;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;

import java.math.BigDecimal;
import java.time.LocalDate;

@Getter
public class SummarizedOnSaleProductDto {

@Schema(description = "상품 id", example = "1")
private final Long id;

@Schema(description = "발행 회사", example = "oo투자증권")
private final String issuer;

@Schema(description = "상품명", example = "oo투자증권 99999")
private final String name;

@Schema(description = "상품 유형", example = "STEP_DOWN or LIZARD or MONTHLY_PAYMENT or ETC")
private final ProductType productType;

@Schema(description = "기초자산", example = "KOSPI200 Index / HSCEI Index / S&P500 Index")
private final String equities;

@Schema(description = "수익률", example = "20.55")
private final BigDecimal yieldIfConditionsMet;

@Schema(description = "낙인 값", example = "45, 낙인 값이 없을 시 null return")
private final Integer knockIn;

@Schema(description = "청약 시작일", example = "2024-06-14")
private final LocalDate subscriptionStartDate;

@Schema(description = "청약 마감일", example = "2024-06-21")
private final LocalDate subscriptionEndDate;

@Schema(description = "AI가 판단한 상품 안전도", example = "0.89")
private final BigDecimal safetyScore;

public SummarizedOnSaleProductDto(Product product, BigDecimal safetyScore) {
this.id = product.getId();
this.issuer = product.getIssuer();
this.name = product.getName();
this.productType = product.getType();
this.equities = product.getEquities();
this.yieldIfConditionsMet = product.getYieldIfConditionsMet();
this.knockIn = product.getKnockIn();
this.subscriptionStartDate = product.getSubscriptionStartDate();
this.subscriptionEndDate = product.getSubscriptionEndDate();
this.safetyScore = safetyScore;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ public class ResponseProductComparisonTargetDto {
@Schema(description = "청약 마감일", example = "2024-06-21")
private final LocalDate subscriptionEndDate;

public ResponseProductComparisonTargetDto(Product product) {
@Schema(description = "AI가 판단한 상품 안전도", example = "0.89")
private final BigDecimal safetyScore;

public ResponseProductComparisonTargetDto(Product product, BigDecimal safetyScore) {
this.id = product.getId();
this.issuer = product.getIssuer();
this.name = product.getName();
Expand All @@ -59,5 +62,6 @@ public ResponseProductComparisonTargetDto(Product product) {
this.maximumLossRate = product.getMaximumLossRate();
this.subscriptionStartDate = product.getSubscriptionStartDate();
this.subscriptionEndDate = product.getSubscriptionEndDate();
this.safetyScore = safetyScore;
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package com.wl2c.elswhereproductservice.domain.product.service;

import com.wl2c.elswhereproductservice.client.analysis.api.AnalysisServiceClient;
import com.wl2c.elswhereproductservice.client.analysis.dto.response.ResponseAIResultDto;
import com.wl2c.elswhereproductservice.domain.like.service.LikeService;
import com.wl2c.elswhereproductservice.domain.product.exception.NotOnSaleProductException;
import com.wl2c.elswhereproductservice.domain.product.exception.ProductNotFoundException;
import com.wl2c.elswhereproductservice.domain.product.exception.TodayReceivedProductsNotFoundException;
import com.wl2c.elswhereproductservice.domain.product.exception.WrongProductSortTypeException;
import com.wl2c.elswhereproductservice.domain.product.model.ProductType;
import com.wl2c.elswhereproductservice.domain.product.model.dto.list.SummarizedOnSaleProductDto;
import com.wl2c.elswhereproductservice.domain.product.model.dto.list.SummarizedProductDto;
import com.wl2c.elswhereproductservice.domain.product.model.dto.list.SummarizedProductForHoldingDto;
import com.wl2c.elswhereproductservice.domain.product.model.dto.request.RequestProductIdListDto;
import com.wl2c.elswhereproductservice.domain.product.model.dto.request.RequestProductSearchDto;
import com.wl2c.elswhereproductservice.domain.product.model.dto.response.ResponseProductComparisonTargetDto;
import com.wl2c.elswhereproductservice.domain.product.model.dto.response.ResponseSingleProductDto;
Expand All @@ -18,9 +23,12 @@
import com.wl2c.elswhereproductservice.domain.product.repository.TickerSymbolRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.circuitbreaker.CircuitBreaker;
import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

Expand All @@ -29,6 +37,9 @@
@Slf4j
public class ProductService {

private final AnalysisServiceClient analysisServiceClient;
private final CircuitBreakerFactory circuitBreakerFactory;

private final ProductRepository productRepository;
private final TickerSymbolRepository tickerSymbolRepository;
private final ProductSearchRepository productSearchRepository;
Expand All @@ -37,7 +48,7 @@ public class ProductService {
private final LikeService likeService;
private final DailyHotProductService dailyHotProductService;

public Page<SummarizedProductDto> listByOnSale(String type, Pageable pageable) {
public Page<SummarizedOnSaleProductDto> listByOnSale(String type, Pageable pageable) {
Sort sort = switch (type) {
case "latest" -> Sort.by(Sort.Order.desc("subscriptionStartDate"), Sort.Order.desc("lastModifiedAt"));
case "knock-in" -> Sort.by(Sort.Order.asc("knockIn").nullsLast(), Sort.Order.desc("lastModifiedAt"));
Expand All @@ -53,7 +64,28 @@ public Page<SummarizedProductDto> listByOnSale(String type, Pageable pageable) {
Pageable sortedPageable = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), sort);
Page<Product> products = productRepository.listByOnSale(type, sortedPageable);

return products.map(SummarizedProductDto::new);
List<Long> stepDownProductIds = products.getContent().stream()
.filter(product -> product.getType() == ProductType.STEP_DOWN) // STEP_DOWN 타입 필터링
.map(Product::getId)
.toList();
List<ResponseAIResultDto> responseStepDownAIResultDtos = listStepDownAIResult(stepDownProductIds);

// AI 결과 리스트에서 productId를 key로 하는 Map으로 변환
Map<Long, BigDecimal> productSafetyScoreMap = responseStepDownAIResultDtos.stream()
.collect(Collectors.toMap(
ResponseAIResultDto::getProductId,
ResponseAIResultDto::getSafetyScore,
(existing, replacement) -> existing // 중복된 경우 기존 값 사용
));

List<SummarizedOnSaleProductDto> summarizedProducts = products.getContent().stream()
.map(product -> {
BigDecimal safetyScore = productSafetyScoreMap.getOrDefault(product.getId(), null);
return new SummarizedOnSaleProductDto(product, safetyScore);
})
.toList();

return new PageImpl<>(summarizedProducts, pageable, products.getTotalElements());
}

public Page<SummarizedProductDto> listByEndSale(String type, Pageable pageable) {
Expand Down Expand Up @@ -118,17 +150,41 @@ public ResponseSingleProductDto findOne(Long productId, Long userId) {
public Map<String, List<ResponseProductComparisonTargetDto>> findComparisonTargets(Long id) {
Map<String, List<ResponseProductComparisonTargetDto>> result = new HashMap<>();

// 타겟 상품
Product product = productRepository.isItProductOnSale(id).orElseThrow(NotOnSaleProductException::new);
List<TickerSymbol> tickerSymbolEntityList = tickerSymbolRepository.findTickerSymbolList(id);
List<String> tickerSymbolList = tickerSymbolEntityList.stream()
.map(TickerSymbol::getTickerSymbol)
.toList();
List<ResponseProductComparisonTargetDto> target = new ArrayList<>();
target.add(new ResponseProductComparisonTargetDto(product));

// 비교 상품
List<Product> productComparisonResults = productRepository.findComparisonResults(id, product.getEquityCount(), tickerSymbolList);

// 타겟 및 비교 상품들 중 STEP_DOWN 타입 필터링
List<Long> stepDownProductIds = new ArrayList<>(productComparisonResults.stream()
.filter(productComparisonResult -> productComparisonResult.getType() == ProductType.STEP_DOWN)
.map(Product::getId)
.toList());
if (product.getType() == ProductType.STEP_DOWN)
stepDownProductIds.add(product.getId());
List<ResponseAIResultDto> responseStepDownAIResultDtos = listStepDownAIResult(stepDownProductIds);

// AI 결과 리스트에서 productId를 key로 하는 Map으로 변환
Map<Long, BigDecimal> productSafetyScoreMap = responseStepDownAIResultDtos.stream()
.collect(Collectors.toMap(
ResponseAIResultDto::getProductId,
ResponseAIResultDto::getSafetyScore,
(existing, replacement) -> existing // 중복된 경우 기존 값 사용
));

List<ResponseProductComparisonTargetDto> target = new ArrayList<>();
target.add(new ResponseProductComparisonTargetDto(product, productSafetyScoreMap.getOrDefault(product.getId(), null)));

List<ResponseProductComparisonTargetDto> comparisonResults = productComparisonResults.stream()
.map(ResponseProductComparisonTargetDto::new)
.map(productComparisonResult -> new ResponseProductComparisonTargetDto(
productComparisonResult,
productSafetyScoreMap.getOrDefault(productComparisonResult.getId(), null)
))
.toList();

result.put("target", target);
Expand Down Expand Up @@ -187,4 +243,10 @@ public List<SummarizedProductDto> getDailyTop5Products() {

return summarizedProductDtos;
}

private List<ResponseAIResultDto> listStepDownAIResult(List<Long> stepDownProductIds) {
CircuitBreaker circuitBreaker = circuitBreakerFactory.create("aiResultCircuitBreaker");
return circuitBreaker.run(() -> analysisServiceClient.getAIResultList(new RequestProductIdListDto(stepDownProductIds)),
throwable -> new ArrayList<>());
}
}

0 comments on commit 1a3437a

Please sign in to comment.