test: ga-common 유틸 + ga-batch CommissionCalculator 단위 테스트 39건

- MoneyUtilTest (10): pct/tax/mul/div HALF_UP, null 안전성
- DateUtilTest (10): 정산월 범위, 윤년/평년, 월 차이/가산
- MaskUtilTest (7): NAME/PHONE/RRN/ACCOUNT/EMAIL 마스킹 규칙
- EncryptUtilTest (6): AES-256 round-trip, 한글, 짧은 키 패딩
- CommissionCalculatorTest (6): 모집/유지수수료 계산 공식, 폴백, agent 누락

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
GA Pro
2026-05-10 20:47:47 +09:00
parent aee9c2c2ca
commit 8a0483cccc
5 changed files with 487 additions and 0 deletions
@@ -0,0 +1,160 @@
package com.ga.batch.settlement.calc;
import com.ga.core.mapper.org.AgentMapper;
import com.ga.core.mapper.rule.RuleMapper;
import com.ga.core.vo.ledger.LedgerVO;
import com.ga.core.vo.org.AgentVO;
import com.ga.core.vo.product.ContractResp;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.math.BigDecimal;
import java.time.LocalDate;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class CommissionCalculatorTest {
@Mock RuleMapper ruleMapper;
@Mock AgentMapper agentMapper;
@InjectMocks CommissionCalculator calculator;
private ContractResp contract;
@BeforeEach
void setUp() {
contract = new ContractResp();
contract.setContractId(100L);
contract.setAgentId(10L);
contract.setProductId(1L);
contract.setPolicyNo("POL-0001");
contract.setCompanyCode("SAMSUNG");
contract.setProductCode("PRD001");
contract.setInsuranceType("WHOLE_LIFE");
contract.setPremium(new BigDecimal("1000000"));
contract.setPayCycle("MONTHLY");
contract.setContractDate(LocalDate.of(2024, 1, 15));
AgentVO agent = new AgentVO();
agent.setAgentId(10L);
agent.setGradeId(5L);
when(agentMapper.selectById(10L)).thenReturn(agent);
}
@Test
@DisplayName("calcRecruitLedger: premium × company_rate × payout_rate, 세금은 3.3%")
void recruit_basic() {
when(ruleMapper.findCompanyRate(eq(1L), eq(1), any(LocalDate.class)))
.thenReturn(new BigDecimal("7.5"));
when(ruleMapper.findPayoutRate(eq(5L), eq("WHOLE_LIFE"), eq(1), any(LocalDate.class)))
.thenReturn(new BigDecimal("60.0"));
LedgerVO led = calculator.calcRecruitLedger(contract, "202405");
assertThat(led).isNotNull();
assertThat(led.getCommissionYear()).isEqualTo(1);
assertThat(led.getSettleMonth()).isEqualTo("202405");
assertThat(led.getStatus()).isEqualTo("CALCULATED");
assertThat(led.getPremium()).isEqualByComparingTo("1000000");
assertThat(led.getCompanyRate()).isEqualByComparingTo("7.5");
assertThat(led.getPayoutRate()).isEqualByComparingTo("60.0");
// 1,000,000 × 7.5% = 75,000.00
assertThat(led.getCompanyAmount()).isEqualByComparingTo("75000.00");
// 75,000 × 60% = 45,000.00
assertThat(led.getAgentAmount()).isEqualByComparingTo("45000.00");
// 45,000 × 3.3% = 1,485.00
assertThat(led.getTaxAmount()).isEqualByComparingTo("1485.00");
assertThat(led.getContractId()).isEqualTo(100L);
assertThat(led.getAgentId()).isEqualTo(10L);
assertThat(led.getPolicyNo()).isEqualTo("POL-0001");
assertThat(led.getCompanyCode()).isEqualTo("SAMSUNG");
assertThat(led.getProductCode()).isEqualTo("PRD001");
assertThat(led.getInsuranceType()).isEqualTo("WHOLE_LIFE");
assertThat(led.getPayMethod()).isEqualTo("MONTHLY");
}
@Test
@DisplayName("calcMaintainLedger: 회차에 따라 commission_year 가 다름")
void maintain_year3() {
when(ruleMapper.findCompanyRate(eq(1L), eq(3), any(LocalDate.class)))
.thenReturn(new BigDecimal("3.0"));
when(ruleMapper.findPayoutRate(eq(5L), eq("WHOLE_LIFE"), eq(3), any(LocalDate.class)))
.thenReturn(new BigDecimal("50.0"));
LedgerVO led = calculator.calcMaintainLedger(contract, "202405", 3);
assertThat(led.getCommissionYear()).isEqualTo(3);
// 1,000,000 × 3% = 30,000
assertThat(led.getCompanyAmount()).isEqualByComparingTo("30000.00");
// 30,000 × 50% = 15,000
assertThat(led.getAgentAmount()).isEqualByComparingTo("15000.00");
// 15,000 × 3.3% = 495
assertThat(led.getTaxAmount()).isEqualByComparingTo("495.00");
}
@Test
@DisplayName("agent 가 존재하지 않으면 null 반환")
void agentNotFound() {
when(agentMapper.selectById(10L)).thenReturn(null);
LedgerVO led = calculator.calcRecruitLedger(contract, "202405");
assertThat(led).isNull();
}
@Test
@DisplayName("규정 누락 시 0 으로 폴백 → 모든 금액 0")
void missingRates_fallbackZero() {
when(ruleMapper.findCompanyRate(any(), any(), any())).thenReturn(null);
when(ruleMapper.findPayoutRate(any(), any(), any(), any())).thenReturn(null);
LedgerVO led = calculator.calcRecruitLedger(contract, "202405");
assertThat(led).isNotNull();
assertThat(led.getCompanyRate()).isEqualByComparingTo("0");
assertThat(led.getPayoutRate()).isEqualByComparingTo("0");
assertThat(led.getCompanyAmount()).isEqualByComparingTo("0.00");
assertThat(led.getAgentAmount()).isEqualByComparingTo("0.00");
assertThat(led.getTaxAmount()).isEqualByComparingTo("0.00");
}
@Test
@DisplayName("contractDate 가 null 이면 오늘 날짜로 대체 (예외 없음)")
void nullContractDate_usesToday() {
contract.setContractDate(null);
when(ruleMapper.findCompanyRate(eq(1L), eq(1), any(LocalDate.class)))
.thenReturn(new BigDecimal("5"));
when(ruleMapper.findPayoutRate(eq(5L), eq("WHOLE_LIFE"), eq(1), any(LocalDate.class)))
.thenReturn(new BigDecimal("100"));
LedgerVO led = calculator.calcRecruitLedger(contract, "202405");
assertThat(led).isNotNull();
// 1,000,000 × 5% × 100% = 50,000
assertThat(led.getAgentAmount()).isEqualByComparingTo("50000.00");
}
@Test
@DisplayName("premium 이 null 이면 0 으로 처리 (HALF_UP 0.00)")
void nullPremium() {
contract.setPremium(null);
when(ruleMapper.findCompanyRate(any(), any(), any())).thenReturn(new BigDecimal("7.5"));
when(ruleMapper.findPayoutRate(any(), any(), any(), any())).thenReturn(new BigDecimal("60"));
LedgerVO led = calculator.calcRecruitLedger(contract, "202405");
assertThat(led.getPremium()).isEqualByComparingTo("0");
assertThat(led.getCompanyAmount()).isEqualByComparingTo("0.00");
assertThat(led.getAgentAmount()).isEqualByComparingTo("0.00");
}
}