package com.tourguide.modules.finance.service; import com.tourguide.modules.finance.entity.GuideWithdrawal; import com.tourguide.modules.finance.mapper.GuideWithdrawalMapper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.math.BigDecimal; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; class GuideWithdrawalStateServiceTest { private GuideWithdrawalMapper withdrawalMapper; private GuideWithdrawableBalanceService balanceService; private GuideWithdrawalStateService service; @BeforeEach void setUp() { withdrawalMapper = mock(GuideWithdrawalMapper.class); balanceService = mock(GuideWithdrawableBalanceService.class); service = new GuideWithdrawalStateService(withdrawalMapper, balanceService); } @Test void rejectShouldRefundReservedLocalBalance() { GuideWithdrawal withdrawal = pendingWithdrawal(); when(withdrawalMapper.selectForUpdate(20L)).thenReturn(withdrawal); when(withdrawalMapper.updateById(withdrawal)).thenReturn(1); service.reject(20L, "资料不完整", "admin"); verify(balanceService).credit(8L, new BigDecimal("200.00")); assertThat(withdrawal.getStatus()).isEqualTo("REJECTED"); } @Test void prepareTransferShouldPersistIdempotentRequestIdentity() { GuideWithdrawal withdrawal = pendingWithdrawal(); when(withdrawalMapper.selectForUpdate(20L)).thenReturn(withdrawal); when(withdrawalMapper.updateById(withdrawal)).thenReturn(1); service.prepareTransfer(20L, null, "admin"); assertThat(withdrawal.getStatus()).isEqualTo("TRANSFERRING"); assertThat(withdrawal.getTransferReqSeqId()).startsWith("TF"); assertThat(withdrawal.getTransferReqDate()).hasSize(8); assertThat(withdrawal.getUpdatedAt()).isNotNull(); } @Test void cashFailureShouldClearPersistedRequestIdentity() { GuideWithdrawal withdrawal = pendingWithdrawal(); withdrawal.setStatus("PROCESSING"); withdrawal.setCashReqSeqId("CW001"); withdrawal.setCashReqDate("20260817"); withdrawal.setCashHfSeqId("HF001"); when(withdrawalMapper.selectForUpdate(20L)).thenReturn(withdrawal); when(withdrawalMapper.resetCashForRetry(any(), any(), any(), any())).thenReturn(1); service.markCashRetry(20L, "取现失败"); verify(withdrawalMapper).resetCashForRetry(any(), any(), any(), any()); assertThat(withdrawal.getStatus()).isEqualTo("TRANSFERRED"); assertThat(withdrawal.getCashReqSeqId()).isNull(); } private GuideWithdrawal pendingWithdrawal() { GuideWithdrawal withdrawal = new GuideWithdrawal(); withdrawal.setId(20L); withdrawal.setGuideId(8L); withdrawal.setAmount(new BigDecimal("200.00")); withdrawal.setStatus("PENDING"); return withdrawal; } }