Skip to content

Commit

Permalink
refactor: change dependency direction (#87)
Browse files Browse the repository at this point in the history
* chore: add auto generated qclass to .gitignore

* fix: failed test by current time

* refactor: apply dip for package dependency

* chore: update interface name

* test: modify test data

* fix: test code
  • Loading branch information
songyi00 authored Mar 26, 2024
1 parent 834a2f1 commit 0734962
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 167 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,4 @@ out/

**/logs
**/db/data
domain/src/main/generated/nexters/payout/domain/stock/domain/QStock.java
**/src/main/generated/**
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package nexters.payout.apiserver.dividend.application;

import lombok.RequiredArgsConstructor;
import nexters.payout.apiserver.stock.application.StockDividendQueryService;
import nexters.payout.apiserver.stock.application.dto.response.DividendResponse;
import nexters.payout.apiserver.stock.application.dto.response.StockDetailResponse;
import nexters.payout.core.time.InstantProvider;
import nexters.payout.domain.dividend.domain.Dividend;
import nexters.payout.domain.dividend.domain.repository.DividendRepository;
import nexters.payout.domain.stock.domain.Stock;
import nexters.payout.domain.stock.domain.exception.TickerNotFoundException;
import nexters.payout.domain.stock.domain.repository.StockRepository;
import nexters.payout.domain.stock.domain.service.StockDividendAnalysisService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Month;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class StockDividendQueryServiceImpl implements StockDividendQueryService {

private final StockDividendAnalysisService dividendAnalysisService;
private final StockRepository stockRepository;
private final DividendRepository dividendRepository;

public StockDetailResponse getStockByTicker(final String ticker) {
Stock stock = getStock(ticker);

List<Dividend> lastYearDividends = getLastYearDividends(stock);
List<Dividend> thisYearDividends = getThisYearDividends(stock);

if (lastYearDividends.isEmpty() && thisYearDividends.isEmpty()) {
return StockDetailResponse.of(stock, DividendResponse.noDividend());
}

List<Month> dividendMonths = dividendAnalysisService.calculateDividendMonths(stock, lastYearDividends);
Double dividendYield = dividendAnalysisService.calculateDividendYield(stock, lastYearDividends);
Double dividendPerShare = dividendAnalysisService.calculateAverageDividend(
combinedDividends(lastYearDividends, thisYearDividends)
);

return dividendAnalysisService.findUpcomingDividend(lastYearDividends, thisYearDividends)
.map(upcomingDividend -> StockDetailResponse.of(
stock,
DividendResponse.fullDividendInfo(upcomingDividend, dividendYield, dividendMonths)
))
.orElse(StockDetailResponse.of(
stock,
DividendResponse.withoutDividendDates(dividendPerShare, dividendYield, dividendMonths)
));
}

private List<Dividend> combinedDividends(final List<Dividend> lastYearDividends, final List<Dividend> thisYearDividends) {
return Stream.of(lastYearDividends, thisYearDividends)
.flatMap(List::stream)
.collect(Collectors.toList());
}

private Stock getStock(final String ticker) {
return stockRepository.findByTicker(ticker)
.orElseThrow(() -> new TickerNotFoundException(ticker));
}

private List<Dividend> getLastYearDividends(final Stock stock) {
int lastYear = InstantProvider.getLastYear();

return dividendRepository.findAllByStockId(stock.getId())
.stream()
.filter(dividend -> InstantProvider.toLocalDate(dividend.getExDividendDate()).getYear() == lastYear)
.collect(Collectors.toList());
}

private List<Dividend> getThisYearDividends(final Stock stock) {
int thisYear = InstantProvider.getThisYear();

return dividendRepository.findAllByStockId(stock.getId())
.stream()
.filter(dividend -> InstantProvider.toLocalDate(dividend.getExDividendDate()).getYear() == thisYear)
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package nexters.payout.apiserver.stock.application;

import nexters.payout.apiserver.stock.application.dto.response.StockDetailResponse;

public interface StockDividendQueryService {
StockDetailResponse getStockByTicker(final String ticker);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,27 @@
import nexters.payout.apiserver.stock.application.dto.request.TickerShare;
import nexters.payout.apiserver.stock.application.dto.response.*;
import nexters.payout.core.time.InstantProvider;
import nexters.payout.domain.dividend.domain.Dividend;
import nexters.payout.domain.dividend.domain.repository.DividendRepository;
import nexters.payout.domain.stock.domain.Sector;
import nexters.payout.domain.stock.domain.Stock;
import nexters.payout.domain.stock.domain.exception.TickerNotFoundException;
import nexters.payout.domain.stock.domain.repository.StockRepository;
import nexters.payout.domain.stock.domain.service.SectorAnalysisService;
import nexters.payout.domain.stock.domain.service.SectorAnalysisService.SectorInfo;
import nexters.payout.domain.stock.domain.service.SectorAnalysisService.StockShare;
import nexters.payout.domain.stock.domain.service.StockDividendAnalysisService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Month;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class StockQueryService {

private final StockRepository stockRepository;
private final DividendRepository dividendRepository;
private final SectorAnalysisService sectorAnalysisService;
private final StockDividendAnalysisService dividendAnalysisService;
private final StockDividendQueryService stockDividendQueryService;

public List<StockResponse> searchStock(final String keyword, final Integer pageNumber, final Integer pageSize) {
return stockRepository.findStocksByTickerOrNameWithPriority(keyword, pageNumber, pageSize)
Expand All @@ -42,59 +35,7 @@ public List<StockResponse> searchStock(final String keyword, final Integer pageN
}

public StockDetailResponse getStockByTicker(final String ticker) {
Stock stock = getStock(ticker);

List<Dividend> lastYearDividends = getLastYearDividends(stock);
List<Dividend> thisYearDividends = getThisYearDividends(stock);

if (lastYearDividends.isEmpty() && thisYearDividends.isEmpty()) {
return StockDetailResponse.of(stock, DividendResponse.noDividend());
}

List<Month> dividendMonths = dividendAnalysisService.calculateDividendMonths(stock, lastYearDividends);
Double dividendYield = dividendAnalysisService.calculateDividendYield(stock, lastYearDividends);
Double dividendPerShare = dividendAnalysisService.calculateAverageDividend(
combinedDividends(lastYearDividends, thisYearDividends)
);

return dividendAnalysisService.findUpcomingDividend(lastYearDividends, thisYearDividends)
.map(upcomingDividend -> StockDetailResponse.of(
stock,
DividendResponse.fullDividendInfo(upcomingDividend, dividendYield, dividendMonths)
))
.orElse(StockDetailResponse.of(
stock,
DividendResponse.withoutDividendDates(dividendPerShare, dividendYield, dividendMonths)
));
}

private List<Dividend> combinedDividends(final List<Dividend> lastYearDividends, final List<Dividend> thisYearDividends) {
return Stream.of(lastYearDividends, thisYearDividends)
.flatMap(List::stream)
.collect(Collectors.toList());
}

private Stock getStock(final String ticker) {
return stockRepository.findByTicker(ticker)
.orElseThrow(() -> new TickerNotFoundException(ticker));
}

private List<Dividend> getLastYearDividends(final Stock stock) {
int lastYear = InstantProvider.getLastYear();

return dividendRepository.findAllByStockId(stock.getId())
.stream()
.filter(dividend -> InstantProvider.toLocalDate(dividend.getExDividendDate()).getYear() == lastYear)
.collect(Collectors.toList());
}

private List<Dividend> getThisYearDividends(final Stock stock) {
int thisYear = InstantProvider.getThisYear();

return dividendRepository.findAllByStockId(stock.getId())
.stream()
.filter(dividend -> InstantProvider.toLocalDate(dividend.getExDividendDate()).getYear() == thisYear)
.collect(Collectors.toList());
return stockDividendQueryService.getStockByTicker(ticker);
}

public List<SectorRatioResponse> analyzeSectorRatio(final SectorRatioRequest request) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package nexters.payout.apiserver.stock.application;

import nexters.payout.apiserver.dividend.application.StockDividendQueryServiceImpl;
import nexters.payout.apiserver.stock.application.dto.request.SectorRatioRequest;
import nexters.payout.apiserver.stock.application.dto.request.TickerShare;
import nexters.payout.apiserver.stock.application.dto.response.*;
Expand All @@ -19,9 +20,9 @@
import nexters.payout.domain.stock.domain.service.StockDividendAnalysisService;
import nexters.payout.domain.stock.domain.service.SectorAnalysisService;
import nexters.payout.domain.stock.infra.dto.StockDividendYieldDto;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;
Expand All @@ -45,9 +46,7 @@
@ExtendWith(MockitoExtension.class)
class StockQueryServiceTest {

@InjectMocks
private StockQueryService stockQueryService;

@Mock
private StockRepository stockRepository;
@Mock
Expand All @@ -57,6 +56,12 @@ class StockQueryServiceTest {
@Spy
private StockDividendAnalysisService stockDividendAnalysisService;

@BeforeEach
void setUp() {
StockDividendQueryServiceImpl stockDividendQuery = new StockDividendQueryServiceImpl(stockDividendAnalysisService, stockRepository, dividendRepository);
stockQueryService = new StockQueryService(stockRepository, sectorAnalysisService, stockDividendQuery);
}

@Test
void 검색된_종목_정보를_정상적으로_반환한다() {
// given
Expand Down
41 changes: 0 additions & 41 deletions domain/src/main/generated/nexters/payout/domain/QBaseEntity.java

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package nexters.payout.domain.stock.service;

import nexters.payout.core.time.InstantProvider;
import nexters.payout.domain.DividendFixture;
import nexters.payout.domain.StockFixture;
import nexters.payout.domain.dividend.domain.Dividend;
Expand Down Expand Up @@ -76,18 +77,17 @@ class StockDividendAnalysisServiceTest {
@Test
void 공시된_현재_배당금_지급일이_없는_경우_과거데이터를_기반으로_가까운_지급일을_계산한다() {
// given
LocalDate now = LocalDate.now();
LocalDate now = LocalDate.ofInstant(Instant.now(), UTC);

Dividend pastDividend = DividendFixture.createDividendWithExDividendDate(
UUID.randomUUID(),
LocalDate.of(now.getYear() - 1, 1, 10)
LocalDate.of(now.getYear(), now.getMonth().minus(1), now.getDayOfMonth())
.atStartOfDay(ZoneId.systemDefault()).toInstant()
);

Dividend earlistDividend = DividendFixture.createDividendWithExDividendDate(
UUID.randomUUID(),
LocalDate.of(now.getYear() - 1, 3, 10)
.atStartOfDay(ZoneId.systemDefault()).toInstant()
LocalDate.of(now.getYear(), now.getMonth(), now.getDayOfMonth()).atStartOfDay().toInstant(UTC)
);
List<Dividend> lastYearDividends = List.of(pastDividend, earlistDividend);

Expand All @@ -107,7 +107,7 @@ class StockDividendAnalysisServiceTest {
Dividend lastYearDividend = DividendFixture.createDividend(
UUID.randomUUID(),
1.0,
LocalDate.now().plusDays(10)
LocalDate.now().minusDays(10)
.atStartOfDay(ZoneId.systemDefault()).toInstant()
);

Expand Down

0 comments on commit 0734962

Please sign in to comment.