1
0

perf: 股票详情页显示财报

This commit is contained in:
2025-09-12 16:18:39 +08:00
parent 5fa2a4e8e7
commit 338554c523
4 changed files with 159 additions and 6 deletions

View File

@@ -1,11 +1,14 @@
package com.lanyuanxiaoyao.leopard.server.controller;
import com.lanyuanxiaoyao.leopard.core.entity.Stock;
import com.lanyuanxiaoyao.leopard.server.helper.NumberHelper;
import com.lanyuanxiaoyao.leopard.server.service.StockService;
import com.lanyuanxiaoyao.service.template.controller.GlobalResponse;
import com.lanyuanxiaoyao.service.template.controller.SimpleControllerSupport;
import java.time.LocalDate;
import java.util.function.Function;
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;
@@ -16,8 +19,11 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("stock")
public class StockController extends SimpleControllerSupport<Stock, Void, StockController.DetailItem, StockController.DetailItem> {
public StockController(StockService service) {
private final StockService stockService;
public StockController(StockService service, StockService stockService) {
super(service);
this.stockService = stockService;
}
@Override
@@ -25,6 +31,37 @@ public class StockController extends SimpleControllerSupport<Stock, Void, StockC
throw new UnsupportedOperationException();
}
@GetMapping("finance/{id}")
public GlobalResponse<FinanceItem> finance(@PathVariable("id") Long id) {
// 财报默认是上一年的
var year = LocalDate.now().minusYears(1).getYear();
var balanceSheet = stockService.findBalanceSheet(id, year);
var income = stockService.findIncome(id, year);
var cashFlow = stockService.findCashFlow(id, year);
return GlobalResponse.responseSuccess(new FinanceItem(
id,
year,
balanceSheet
.map(bs -> new BalanceSheetItem(
NumberHelper.formatFinanceDouble(bs.getTotalAssets()),
NumberHelper.formatFinanceDouble(bs.getTotalLiabilities())
))
.orElse(new BalanceSheetItem()),
income
.map(ic -> new IncomeItem(
NumberHelper.formatFinanceDouble(ic.getTotalOperatingRevenue()),
NumberHelper.formatFinanceDouble(ic.getTotalOperatingCost()),
NumberHelper.formatFinanceDouble(ic.getTotalProfit())
))
.orElse(new IncomeItem()),
cashFlow
.map(cf -> new CashFlowItem(
NumberHelper.formatFinanceDouble(cf.getNetProfit())
))
.orElse(new CashFlowItem())
));
}
@Override
protected Function<Void, Stock> saveItemMapper() {
throw new UnsupportedOperationException();
@@ -62,4 +99,49 @@ public class StockController extends SimpleControllerSupport<Stock, Void, StockC
LocalDate listedDate
) {
}
public record FinanceItem(
Long id,
Integer year,
BalanceSheetItem balanceSheet,
IncomeItem income,
CashFlowItem cashFlow
) {
}
public record BalanceSheetItem(
String totalAssets,
String totalLiabilities
) {
public BalanceSheetItem() {
this(
NumberHelper.FINANCE_NULL_DOUBLE,
NumberHelper.FINANCE_NULL_DOUBLE
);
}
}
public record IncomeItem(
String totalOperatingRevenue,
String totalOperatingCost,
String totalProfit
) {
public IncomeItem() {
this(
NumberHelper.FINANCE_NULL_DOUBLE,
NumberHelper.FINANCE_NULL_DOUBLE,
NumberHelper.FINANCE_NULL_DOUBLE
);
}
}
public record CashFlowItem(
String netProfit
) {
public CashFlowItem() {
this(
NumberHelper.FINANCE_NULL_DOUBLE
);
}
}
}

View File

@@ -1,9 +1,18 @@
package com.lanyuanxiaoyao.leopard.server.service;
import com.lanyuanxiaoyao.leopard.core.entity.BalanceSheet;
import com.lanyuanxiaoyao.leopard.core.entity.CashFlow;
import com.lanyuanxiaoyao.leopard.core.entity.Income;
import com.lanyuanxiaoyao.leopard.core.entity.QBalanceSheet;
import com.lanyuanxiaoyao.leopard.core.entity.QCashFlow;
import com.lanyuanxiaoyao.leopard.core.entity.QIncome;
import com.lanyuanxiaoyao.leopard.core.entity.Stock;
import com.lanyuanxiaoyao.leopard.core.repository.BalanceSheetRepository;
import com.lanyuanxiaoyao.leopard.core.repository.CashFlowRepository;
import com.lanyuanxiaoyao.leopard.core.repository.IncomeRepository;
import com.lanyuanxiaoyao.leopard.core.repository.StockRepository;
import com.lanyuanxiaoyao.service.template.service.SimpleServiceSupport;
import java.util.List;
import java.util.Optional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -15,13 +24,36 @@ import org.springframework.stereotype.Service;
@Service
public class StockService extends SimpleServiceSupport<Stock> {
private final StockRepository stockRepository;
private final BalanceSheetRepository balanceSheetRepository;
private final IncomeRepository incomeRepository;
private final CashFlowRepository cashFlowRepository;
public StockService(StockRepository repository) {
public StockService(StockRepository repository, BalanceSheetRepository balanceSheetRepository, IncomeRepository incomeRepository, CashFlowRepository cashFlowRepository) {
super(repository);
this.stockRepository = repository;
this.balanceSheetRepository = balanceSheetRepository;
this.incomeRepository = incomeRepository;
this.cashFlowRepository = cashFlowRepository;
}
public List<String> findDistinctIndustries() {
return stockRepository.findDistinctIndustries();
public Optional<BalanceSheet> findBalanceSheet(Long stockId, Integer year) {
return balanceSheetRepository.findOne(
QBalanceSheet.balanceSheet.year.eq(year)
.and(QBalanceSheet.balanceSheet.stock.id.eq(stockId))
);
}
public Optional<Income> findIncome(Long stockId, Integer year) {
return incomeRepository.findOne(
QIncome.income.year.eq(year)
.and(QIncome.income.stock.id.eq(stockId))
);
}
public Optional<CashFlow> findCashFlow(Long stockId, Integer year) {
return cashFlowRepository.findOne(
QCashFlow.cashFlow.year.eq(year)
.and(QCashFlow.cashFlow.stock.id.eq(stockId))
);
}
}

View File

@@ -30,8 +30,12 @@
<logger name="com.zaxxer.hikari" level="ERROR"/>
<!--<logger name="org.hibernate.SQL" level="DEBUG"/>-->
<root level="INFO">
<springProfile name="build">
<appender-ref ref="Console"/>
<appender-ref ref="RollingFile"/>
</springProfile>
<root level="INFO">
<appender-ref ref="Console"/>
</root>
</configuration>