package com.goldenchart.service; import com.goldenchart.entity.GcAppSettings; import com.goldenchart.entity.GcPaperAccount; import com.goldenchart.entity.GcPaperSymbolAllocation; import com.goldenchart.repository.GcPaperPositionRepository; import com.goldenchart.repository.GcPaperSymbolAllocationRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import java.math.BigDecimal; import java.util.Optional; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class PaperAllocationServiceTest { @Mock private GcPaperSymbolAllocationRepository allocRepo; @Mock private GcPaperPositionRepository positionRepo; private PaperAllocationService service; @BeforeEach void setUp() { service = new PaperAllocationService(allocRepo, positionRepo); } @Test void validateBuy_rejectsWhenExceedsSymbolLimit() { GcPaperAccount account = GcPaperAccount.builder() .id(1L) .cashBalance(BigDecimal.valueOf(10_000_000)) .reservedCash(BigDecimal.ZERO) .initialCapitalSnapshot(BigDecimal.valueOf(10_000_000)) .build(); GcAppSettings app = new GcAppSettings(); app.setPaperAutoTradeBudgetPct(BigDecimal.valueOf(100)); GcPaperSymbolAllocation alloc = GcPaperSymbolAllocation.builder() .accountId(1L) .symbol("KRW-BTC") .maxInvestKrw(BigDecimal.valueOf(100_000)) .isActive(true) .build(); when(allocRepo.findByAccountIdAndSymbol(1L, "KRW-BTC")).thenReturn(Optional.of(alloc)); when(positionRepo.findByAccountIdAndSymbol(1L, "KRW-BTC")).thenReturn(Optional.empty()); assertThrows(IllegalStateException.class, () -> service.validateBuy(account, app, "KRW-BTC", BigDecimal.valueOf(200_000), false)); } @Test void validateBuy_rejectsInactiveSymbol() { GcPaperAccount account = GcPaperAccount.builder() .id(1L) .cashBalance(BigDecimal.valueOf(10_000_000)) .reservedCash(BigDecimal.ZERO) .initialCapitalSnapshot(BigDecimal.valueOf(10_000_000)) .build(); GcAppSettings app = new GcAppSettings(); GcPaperSymbolAllocation alloc = GcPaperSymbolAllocation.builder() .accountId(1L) .symbol("KRW-BTC") .maxInvestKrw(BigDecimal.valueOf(5_000_000)) .isActive(false) .build(); when(allocRepo.findByAccountIdAndSymbol(1L, "KRW-BTC")).thenReturn(Optional.of(alloc)); assertThrows(IllegalStateException.class, () -> service.validateBuy(account, app, "KRW-BTC", BigDecimal.valueOf(10_000), false)); } }