diff --git a/finance/src/test/java/com/baiyue/finance/FinanceWalletBehaviorTest.java b/finance/src/test/java/com/baiyue/finance/FinanceWalletBehaviorTest.java index e9ea2908e..456f67ed5 100644 --- a/finance/src/test/java/com/baiyue/finance/FinanceWalletBehaviorTest.java +++ b/finance/src/test/java/com/baiyue/finance/FinanceWalletBehaviorTest.java @@ -116,6 +116,81 @@ class FinanceWalletBehaviorTest { assertThat(recharged.availableBalance()).isEqualByComparingTo("55.00"); } + @Test + void deductionNeverConsumesCashReservedByAnActiveHold() { + FinanceWalletService service = service(mock(JdbcTemplate.class), "x", "y"); + WalletAccount initial = service.accountState(new BigDecimal("100.00"), new BigDecimal("50.00"), + new BigDecimal("80.00"), BigDecimal.ZERO, new BigDecimal("20.00"), 4); + + WalletAccount deducted = service.deductAccount(initial, new BigDecimal("80.00")); + + assertThat(deducted.actualBalance()).isEqualByComparingTo("30.00"); + assertThat(deducted.creditUsed()).isEqualByComparingTo("10.00"); + assertThat(deducted.frozenBalance()).isEqualByComparingTo("50.00"); + assertThat(deducted.creditFrozen()).isEqualByComparingTo("20.00"); + assertThat(deducted.availableCredit()).isEqualByComparingTo("50.00"); + assertThat(deducted.availableBalance()).isEqualByComparingTo("50.00"); + } + + @Test + void rechargeRepaysUsedCreditWithoutReleasingFrozenCredit() { + FinanceWalletService service = service(mock(JdbcTemplate.class), "x", "y"); + WalletAccount initial = service.accountState(new BigDecimal("30.00"), new BigDecimal("25.00"), + new BigDecimal("100.00"), new BigDecimal("40.00"), new BigDecimal("20.00"), 5); + + WalletAccount recharged = service.rechargeAccount(initial, new BigDecimal("50.00")); + + assertThat(recharged.actualBalance()).isEqualByComparingTo("40.00"); + assertThat(recharged.creditUsed()).isEqualByComparingTo("0.00"); + assertThat(recharged.creditFrozen()).isEqualByComparingTo("20.00"); + assertThat(recharged.frozenBalance()).isEqualByComparingTo("25.00"); + assertThat(recharged.availableCredit()).isEqualByComparingTo("80.00"); + assertThat(recharged.availableBalance()).isEqualByComparingTo("115.00"); + } + + @Test + void accountStateRejectsCreditUsedAndFrozenAboveTheLimit() { + FinanceWalletService service = service(mock(JdbcTemplate.class), "x", "y"); + + assertThatThrownBy(() -> service.accountState(new BigDecimal("10.00"), new BigDecimal("25.00"), + new BigDecimal("50.00"), new BigDecimal("31.00"), new BigDecimal("20.00"), 1)) + .isInstanceOf(FinanceEventException.class) + .extracting(error -> ((FinanceEventException) error).code()).isEqualTo("FIN-WALLET-409"); + } + + @Test + void accountStateRejectsFrozenCashAboveActualCash() { + FinanceWalletService service = service(mock(JdbcTemplate.class), "x", "y"); + + assertThatThrownBy(() -> service.accountState(new BigDecimal("9.99"), new BigDecimal("10.00"), + new BigDecimal("20.00"), BigDecimal.ZERO, BigDecimal.ZERO, 1)) + .isInstanceOf(FinanceEventException.class) + .extracting(error -> ((FinanceEventException) error).code()).isEqualTo("FIN-WALLET-409"); + } + + @Test + void accountStateRejectsCreditFrozenAboveTotalFrozenAmount() { + FinanceWalletService service = service(mock(JdbcTemplate.class), "x", "y"); + + assertThatThrownBy(() -> service.accountState(new BigDecimal("100.00"), new BigDecimal("10.00"), + new BigDecimal("50.00"), BigDecimal.ZERO, new BigDecimal("10.01"), 1)) + .isInstanceOf(FinanceEventException.class) + .extracting(error -> ((FinanceEventException) error).code()).isEqualTo("FIN-WALLET-409"); + } + + @Test + void invalidDefaultCreditConfigurationFailsClosed() { + assertThatThrownBy(() -> service(mock(JdbcTemplate.class), "x", "y", new BigDecimal("-0.01"))) + .isInstanceOf(FinanceEventException.class) + .extracting(error -> ((FinanceEventException) error).code()).isEqualTo("FIN-REQ-400"); + assertThatThrownBy(() -> service(mock(JdbcTemplate.class), "x", "y", new BigDecimal("1.001"))) + .isInstanceOf(FinanceEventException.class) + .extracting(error -> ((FinanceEventException) error).code()).isEqualTo("FIN-REQ-400"); + assertThatThrownBy(() -> service(mock(JdbcTemplate.class), "x", "y", new BigDecimal("1000000000000.00"))) + .isInstanceOf(FinanceEventException.class) + .extracting(error -> ((FinanceEventException) error).code()).isEqualTo("FIN-REQ-400"); + } + private static FinanceWalletService service(JdbcTemplate jdbc, String wechat, String alipay) { return service(jdbc, wechat, alipay, BigDecimal.ZERO); }