liujie
2026-08-21 a7c8a8f6055e1a03414f2227d12ff2e87ec52d41
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package com.tourguide.modules.finance.service;
 
import com.alibaba.fastjson.JSONObject;
import com.tourguide.common.huifu.biz.DouGongWithdrawBiz;
import com.tourguide.common.huifu.biz.FenZhangUtil;
import com.tourguide.modules.finance.entity.GuideWithdrawal;
import com.tourguide.modules.finance.entity.GuideWithdrawalAccount;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
 
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
 
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
 
class GuideWithdrawalPayoutServiceTest {
    private GuideWithdrawalStateService stateService;
    private GuideSettlementService settlementService;
    private FenZhangUtil fenZhangUtil;
    private DouGongWithdrawBiz withdrawBiz;
    private GuideWithdrawalPayoutService service;
 
    @BeforeEach
    void setUp() {
        stateService = mock(GuideWithdrawalStateService.class);
        settlementService = mock(GuideSettlementService.class);
        fenZhangUtil = mock(FenZhangUtil.class);
        withdrawBiz = mock(DouGongWithdrawBiz.class);
        service = new GuideWithdrawalPayoutService(
                stateService, settlementService, fenZhangUtil, withdrawBiz);
    }
 
    @Test
    void approveShouldTransferFromPlatformBeforeSubmittingCash() throws Exception {
        GuideWithdrawal transferring = withdrawal("TRANSFERRING");
        transferring.setTransferReqSeqId("TF001");
        transferring.setTransferReqDate("20260817");
        GuideWithdrawal cash = withdrawal("PROCESSING");
        cash.setCashReqSeqId("CW001");
        cash.setCashReqDate("20260817");
        GuideWithdrawalAccount account = account();
        when(stateService.prepareTransfer(20L, null, "admin")).thenReturn(transferring);
        when(stateService.prepareCash(20L)).thenReturn(cash);
        when(stateService.find(20L)).thenReturn(cash);
        when(settlementService.requireApprovedCard(8L, 10)).thenReturn(account);
        Map<String, Object> transferResponse = new HashMap<>();
        transferResponse.put("resp_code", "00000000");
        transferResponse.put("trans_stat", "S");
        transferResponse.put("hf_seq_id", "HF-TF-1");
        when(fenZhangUtil.fenzhang("TF001", "20260817", "200.00", "HF100"))
                .thenReturn(transferResponse);
        JSONObject cashResponse = new JSONObject();
        cashResponse.put("resp_code", "00000100");
        cashResponse.put("resp_desc", "受理成功");
        when(withdrawBiz.encashment(new BigDecimal("200.00"), "HF100", "TOKEN100",
                "CW001", "20260817")).thenReturn(cashResponse);
 
        service.approve(20L, null, "admin");
 
        verify(stateService).markTransferred(20L, "HF-TF-1");
        verify(withdrawBiz).encashment(new BigDecimal("200.00"), "HF100", "TOKEN100",
                "CW001", "20260817");
    }
 
    @Test
    void transferFailureShouldNeverSubmitCash() throws Exception {
        GuideWithdrawal transferring = withdrawal("TRANSFERRING");
        transferring.setTransferReqSeqId("TF001");
        transferring.setTransferReqDate("20260817");
        when(stateService.prepareTransfer(20L, null, "admin")).thenReturn(transferring);
        when(stateService.find(20L)).thenReturn(transferring);
        when(settlementService.requireApprovedCard(8L, 10)).thenReturn(account());
        Map<String, Object> response = new HashMap<>();
        response.put("resp_code", "100001");
        response.put("resp_desc", "主账户余额不足");
        when(fenZhangUtil.fenzhang("TF001", "20260817", "200.00", "HF100"))
                .thenReturn(response);
 
        service.approve(20L, null, "admin");
 
        verify(stateService).markTransferFailed(20L, "主账户划账失败:主账户余额不足");
        verify(withdrawBiz, never()).encashment(
                org.mockito.ArgumentMatchers.any(), anyString(), anyString(), anyString(), anyString());
    }
 
    @Test
    void transferredRecordWithCashSequenceShouldQueryOriginalRequestInsteadOfResubmitting() {
        GuideWithdrawal transferred = withdrawal("TRANSFERRED");
        transferred.setCashReqSeqId("CW001");
        transferred.setCashReqDate("20260818");
        GuideWithdrawal processing = withdrawal("PROCESSING");
        processing.setCashReqSeqId("CW001");
        processing.setCashReqDate("20260818");
        when(stateService.find(20L)).thenReturn(transferred);
        when(stateService.resumeCashQuery(20L)).thenReturn(processing);
        when(settlementService.requireApprovedCard(8L, 10)).thenReturn(account());
        JSONObject queryResponse = new JSONObject();
        queryResponse.put("resp_code", "00000000");
        queryResponse.put("trans_stat", "S");
        when(withdrawBiz.query("HF100", "20260818", "CW001")).thenReturn(queryResponse);
 
        service.advance(20L);
 
        verify(stateService).resumeCashQuery(20L);
        verify(withdrawBiz).query("HF100", "20260818", "CW001");
        verify(withdrawBiz, never()).encashment(any(), anyString(), anyString(), anyString(), anyString());
        verify(stateService).markApproved(20L, null);
    }
 
    @Test
    void cashQueryBusinessErrorShouldRemainProcessing() {
        GuideWithdrawal processing = withdrawal("PROCESSING");
        processing.setCashReqSeqId("CW001");
        processing.setCashReqDate("20260818");
        when(stateService.find(20L)).thenReturn(processing);
        when(settlementService.requireApprovedCard(8L, 10)).thenReturn(account());
        JSONObject queryResponse = new JSONObject();
        queryResponse.put("resp_code", "20000100");
        queryResponse.put("resp_desc", "查询服务暂不可用");
        when(withdrawBiz.query("HF100", "20260818", "CW001")).thenReturn(queryResponse);
 
        service.advance(20L);
 
        verify(stateService).markCashPending(20L, null,
                "导游账户取现查询失败:查询服务暂不可用");
        verify(stateService, never()).markCashRetry(any(), anyString());
    }
 
    private GuideWithdrawal withdrawal(String status) {
        GuideWithdrawal withdrawal = new GuideWithdrawal();
        withdrawal.setId(20L);
        withdrawal.setGuideId(8L);
        withdrawal.setBankCardId(10);
        withdrawal.setAmount(new BigDecimal("200.00"));
        withdrawal.setStatus(status);
        return withdrawal;
    }
 
    private GuideWithdrawalAccount account() {
        GuideWithdrawalAccount account = new GuideWithdrawalAccount();
        account.setHuifuId("HF100");
        account.setTokenNo("TOKEN100");
        return account;
    }
}