카드 정산 업무 규칙과 전환 불변식 추출 (codex-bais-final3-20260713-192718-BAIS-SPRING-ANA-CARD-001)
This commit is contained in:
parent
68a4df5aaf
commit
b83a09660f
1 changed files with 193 additions and 0 deletions
|
|
@ -0,0 +1,193 @@
|
||||||
|
package com.bais.card.settlement;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SettlementCalculator 단위 테스트
|
||||||
|
* 불변식 검증: BRAND_SETTLEMENT_*, IRD_*, ISSUER_FEE_*, AMOUNT_*, ROUNDING_MODE
|
||||||
|
*/
|
||||||
|
@DisplayName("SettlementCalculator 불변식 테스트")
|
||||||
|
class SettlementCalculatorTest {
|
||||||
|
|
||||||
|
private SettlementCalculator calculator;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
calculator = new SettlementCalculator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("브랜드 정산 불변식 테스트")
|
||||||
|
class BrandSettlementTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("BRAND_SETTLEMENT_FORMULA: 정산금 = 승인금액 - 취소금액 - 수수료")
|
||||||
|
void testSettlementFormula() {
|
||||||
|
BigDecimal approved = new BigDecimal("100000");
|
||||||
|
BigDecimal cancelled = new BigDecimal("10000");
|
||||||
|
BigDecimal rate = new BigDecimal("0.02");
|
||||||
|
|
||||||
|
SettlementCalculator.BrandSettlementResult result =
|
||||||
|
calculator.calculateBrandSettlement(approved, cancelled, rate);
|
||||||
|
|
||||||
|
assertEquals(new BigDecimal("2000.00"), result.getCommission());
|
||||||
|
assertEquals(new BigDecimal("88000.00"), result.getSettlementAmount());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("BRAND_SETTLEMENT_NON_NEGATIVE: 정산금은 0 이상")
|
||||||
|
void testSettlementNonNegative() {
|
||||||
|
SettlementCalculator.BrandSettlementResult result =
|
||||||
|
calculator.calculateBrandSettlement(
|
||||||
|
new BigDecimal("10000"), new BigDecimal("20000"), new BigDecimal("0.02"));
|
||||||
|
assertEquals(BigDecimal.ZERO.setScale(2), result.getSettlementAmount());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("BRAND_COMMISSION_RATE_DEFAULT: 미지정 시 0.02")
|
||||||
|
void testDefaultCommissionRate() {
|
||||||
|
SettlementCalculator.BrandSettlementResult result =
|
||||||
|
calculator.calculateBrandSettlement(
|
||||||
|
new BigDecimal("100000"), BigDecimal.ZERO, null);
|
||||||
|
assertEquals(new BigDecimal("0.02"), result.getCommissionRate());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("IRD 불변식 테스트")
|
||||||
|
class IrdTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("IRD_FORMULA: IRD = 승인금액 * IRD율")
|
||||||
|
void testIrdFormula() {
|
||||||
|
BigDecimal ird = calculator.calculateIRD(
|
||||||
|
new BigDecimal("100000"), new BigDecimal("0.015"));
|
||||||
|
assertEquals(new BigDecimal("1500.00"), ird);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("IRD_RATE_DEFAULT: 미지정 시 0.015")
|
||||||
|
void testDefaultIrdRate() {
|
||||||
|
BigDecimal ird = calculator.calculateIRD(new BigDecimal("100000"), null);
|
||||||
|
assertEquals(new BigDecimal("1500.00"), ird);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("IRD_NON_NEGATIVE: IRD는 0 이상")
|
||||||
|
void testIrdNonNegative() {
|
||||||
|
BigDecimal ird = calculator.calculateIRD(
|
||||||
|
new BigDecimal("100000"), new BigDecimal("-0.015"));
|
||||||
|
assertTrue(ird.compareTo(BigDecimal.ZERO) >= 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("발급사 수수료 불변식 테스트")
|
||||||
|
class IssuerFeeTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("ISSUER_FEE_FORMULA: 발급사 수수료 = IRD * 발급사 수수료율")
|
||||||
|
void testIssuerFeeFormula() {
|
||||||
|
BigDecimal fee = calculator.calculateIssuerFee(
|
||||||
|
new BigDecimal("1500.00"), new BigDecimal("0.005"));
|
||||||
|
assertEquals(new BigDecimal("7.50"), fee);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("ISSUER_FEE_RATE_DEFAULT: 미지정 시 0.005")
|
||||||
|
void testDefaultIssuerFeeRate() {
|
||||||
|
BigDecimal fee = calculator.calculateIssuerFee(new BigDecimal("1500.00"), null);
|
||||||
|
assertEquals(new BigDecimal("7.50"), fee);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("ISSUER_SETTLEMENT_FORMULA: 발급사 정산금 = IRD - 발급사 수수료")
|
||||||
|
void testIssuerSettlementFormula() {
|
||||||
|
SettlementCalculator.IssuerSettlementResult result =
|
||||||
|
calculator.calculateIssuerSettlement(
|
||||||
|
new BigDecimal("1500.00"), new BigDecimal("0.005"));
|
||||||
|
assertEquals(new BigDecimal("7.50"), result.getIssuerFee());
|
||||||
|
assertEquals(new BigDecimal("1492.50"), result.getIssuerSettlement());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("공통 금액 검증 불변식 테스트")
|
||||||
|
class AmountValidationTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("AMOUNT_NOT_NULL: null 시 IllegalArgumentException")
|
||||||
|
void testNullAmount() {
|
||||||
|
assertThrows(IllegalArgumentException.class, () ->
|
||||||
|
calculator.calculateBrandSettlement(null, BigDecimal.ZERO, new BigDecimal("0.02")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("AMOUNT_NON_NEGATIVE: 음수 시 IllegalArgumentException")
|
||||||
|
void testNegativeAmount() {
|
||||||
|
assertThrows(IllegalArgumentException.class, () ->
|
||||||
|
calculator.calculateBrandSettlement(
|
||||||
|
new BigDecimal("-100000"), BigDecimal.ZERO, new BigDecimal("0.02")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("AMOUNT_MAX_LIMIT: 최대 한도 초과 시 IllegalArgumentException")
|
||||||
|
void testAmountExceedsMaxLimit() {
|
||||||
|
BigDecimal exceedsMax = new BigDecimal("999999999999.99").add(BigDecimal.ONE);
|
||||||
|
assertThrows(IllegalArgumentException.class, () ->
|
||||||
|
calculator.calculateBrandSettlement(
|
||||||
|
exceedsMax, BigDecimal.ZERO, new BigDecimal("0.02")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("금액 정밀도 불변식 테스트")
|
||||||
|
class PrecisionTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("AMOUNT_SCALE: 소수점 2자리")
|
||||||
|
void testAmountScale() {
|
||||||
|
SettlementCalculator.BrandSettlementResult result =
|
||||||
|
calculator.calculateBrandSettlement(
|
||||||
|
new BigDecimal("100000"), BigDecimal.ZERO, new BigDecimal("0.023456"));
|
||||||
|
assertEquals(2, result.getCommission().scale());
|
||||||
|
assertEquals(new BigDecimal("2345.60"), result.getCommission());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("ROUNDING_MODE: HALF_UP 반올림")
|
||||||
|
void testHalfUpRounding() {
|
||||||
|
SettlementCalculator.BrandSettlementResult result =
|
||||||
|
calculator.calculateBrandSettlement(
|
||||||
|
new BigDecimal("100000"), BigDecimal.ZERO, new BigDecimal("0.023455"));
|
||||||
|
assertEquals(new BigDecimal("2345.50"), result.getCommission());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("전체 정산 흐름 테스트")
|
||||||
|
class FullSettlementTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("전체 정산 계산 통합 테스트")
|
||||||
|
void testFullSettlement() {
|
||||||
|
SettlementCalculator.FullSettlementResult result =
|
||||||
|
calculator.calculateFullSettlement(
|
||||||
|
new BigDecimal("100000"),
|
||||||
|
new BigDecimal("10000"),
|
||||||
|
new BigDecimal("0.02"),
|
||||||
|
new BigDecimal("0.015"),
|
||||||
|
new BigDecimal("0.005"));
|
||||||
|
|
||||||
|
assertNotNull(result.getBrandSettlement());
|
||||||
|
assertNotNull(result.getIrd());
|
||||||
|
assertNotNull(result.getIssuerSettlement());
|
||||||
|
assertEquals(new BigDecimal("1500.00"), result.getIrd());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue