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 transferFailureShouldRemainDistinctFromPendingReview() {
|
GuideWithdrawal withdrawal = pendingWithdrawal();
|
withdrawal.setStatus("TRANSFERRING");
|
when(withdrawalMapper.selectForUpdate(20L)).thenReturn(withdrawal);
|
when(withdrawalMapper.updateById(withdrawal)).thenReturn(1);
|
|
service.markTransferFailed(20L, "主账户余额不足");
|
|
assertThat(withdrawal.getStatus()).isEqualTo("TRANSFER_FAILED");
|
assertThat(withdrawal.getPayoutMessage()).isEqualTo("主账户余额不足");
|
}
|
|
@Test
|
void failedTransferShouldAllowManualRetry() {
|
GuideWithdrawal withdrawal = pendingWithdrawal();
|
withdrawal.setStatus("TRANSFER_FAILED");
|
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");
|
}
|
|
@Test
|
void rejectShouldRefundReservedTeamBalance() {
|
GuideWithdrawal withdrawal = pendingWithdrawal();
|
withdrawal.setTeamId(6L);
|
when(withdrawalMapper.selectForUpdate(20L)).thenReturn(withdrawal);
|
when(withdrawalMapper.updateById(withdrawal)).thenReturn(1);
|
|
service.reject(20L, "资料不完整", "admin");
|
|
verify(balanceService).creditTeam(6L, new BigDecimal("200.00"));
|
}
|
|
@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;
|
}
|
}
|