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:
@@ -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");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user