모의투자 관리 기능 추가

This commit is contained in:
Macbook
2026-05-31 03:47:07 +09:00
parent 9d7dddfa57
commit 16d0e2c226
78 changed files with 4688 additions and 972 deletions
@@ -0,0 +1,108 @@
package com.goldenchart.service;
import com.goldenchart.dto.PaperLedgerEntryDto;
import com.goldenchart.dto.PaperPageDto;
import com.goldenchart.entity.GcPaperAccount;
import com.goldenchart.entity.GcPaperCashLedger;
import com.goldenchart.entity.GcPaperTrade;
import com.goldenchart.repository.GcPaperCashLedgerRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Service
@RequiredArgsConstructor
@Transactional
public class PaperLedgerService {
public static final String INITIAL = "INITIAL";
public static final String BUY_SETTLE = "BUY_SETTLE";
public static final String SELL_SETTLE = "SELL_SETTLE";
public static final String RESET = "RESET";
private final GcPaperCashLedgerRepository ledgerRepo;
public void recordInitial(GcPaperAccount account, BigDecimal initialCash) {
ledgerRepo.save(GcPaperCashLedger.builder()
.accountId(account.getId())
.entryType(INITIAL)
.amount(initialCash)
.cashBefore(BigDecimal.ZERO)
.cashAfter(initialCash)
.build());
}
public void recordBuySettle(GcPaperAccount account, GcPaperTrade trade, BigDecimal totalCost) {
BigDecimal before = account.getCashBalance().add(totalCost);
ledgerRepo.save(GcPaperCashLedger.builder()
.accountId(account.getId())
.entryType(BUY_SETTLE)
.amount(totalCost.negate())
.cashBefore(before)
.cashAfter(account.getCashBalance())
.refTradeId(trade.getId())
.symbol(trade.getSymbol())
.build());
}
public void recordSellSettle(GcPaperAccount account, GcPaperTrade trade, BigDecimal netProceeds) {
BigDecimal before = account.getCashBalance().subtract(netProceeds);
ledgerRepo.save(GcPaperCashLedger.builder()
.accountId(account.getId())
.entryType(SELL_SETTLE)
.amount(netProceeds)
.cashBefore(before)
.cashAfter(account.getCashBalance())
.refTradeId(trade.getId())
.symbol(trade.getSymbol())
.build());
}
public void recordReset(GcPaperAccount account, BigDecimal cashBefore, BigDecimal newCash) {
ledgerRepo.save(GcPaperCashLedger.builder()
.accountId(account.getId())
.entryType(RESET)
.amount(newCash.subtract(cashBefore))
.cashBefore(cashBefore)
.cashAfter(newCash)
.build());
}
@Transactional(readOnly = true)
public PaperPageDto<PaperLedgerEntryDto> list(Long accountId, LocalDateTime from, LocalDateTime to,
int page, int size) {
PageRequest pr = PageRequest.of(Math.max(0, page), Math.min(100, Math.max(1, size)));
Page<GcPaperCashLedger> result = (from != null || to != null)
? ledgerRepo.findByAccountIdAndCreatedAtBetweenOrderByCreatedAtDesc(
accountId,
from != null ? from : LocalDateTime.of(2000, 1, 1, 0, 0),
to != null ? to : LocalDateTime.now().plusYears(10),
pr)
: ledgerRepo.findByAccountIdOrderByCreatedAtDesc(accountId, pr);
return PaperPageDto.<PaperLedgerEntryDto>builder()
.content(result.getContent().stream().map(this::toDto).toList())
.page(result.getNumber())
.size(result.getSize())
.totalElements(result.getTotalElements())
.totalPages(result.getTotalPages())
.build();
}
private PaperLedgerEntryDto toDto(GcPaperCashLedger e) {
return PaperLedgerEntryDto.builder()
.id(e.getId())
.entryType(e.getEntryType())
.amount(e.getAmount().doubleValue())
.cashBefore(e.getCashBefore().doubleValue())
.cashAfter(e.getCashAfter().doubleValue())
.refTradeId(e.getRefTradeId())
.symbol(e.getSymbol())
.createdAt(e.getCreatedAt() != null ? e.getCreatedAt().toString() : null)
.build();
}
}