陶杰
2024-10-23 6244b737b5f12036f7b4b90f9bfd95655e08fc1c
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
152
153
154
155
156
157
158
159
160
161
package com.mzl.flower.service.impl.wallet;
 
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mzl.flower.config.exception.ValidationException;
import com.mzl.flower.config.security.SecurityUtils;
import com.mzl.flower.constant.Constants;
import com.mzl.flower.constant.LockConstants;
import com.mzl.flower.dto.request.wallet.CreateWalletWithdrawRecordDTO;
import com.mzl.flower.dto.request.wallet.QueryWalletWithdrawDTO;
import com.mzl.flower.dto.request.wallet.WalletWithdrawRecordDTO;
import com.mzl.flower.dto.response.supplier.SupplierDTO;
import com.mzl.flower.dto.response.wallet.WalletWithdrawRecordVO;
import com.mzl.flower.entity.wallet.WalletDO;
import com.mzl.flower.entity.wallet.WalletWithdrawRecordDO;
import com.mzl.flower.mapper.wallet.WalletWithdrawRecordMapper;
import com.mzl.flower.service.supplier.SupplierService;
import com.mzl.flower.service.wallet.WalletBillRecordService;
import com.mzl.flower.service.wallet.WalletService;
import com.mzl.flower.service.wallet.WalletWithdrawRecordService;
import lombok.RequiredArgsConstructor;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
 
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;
 
/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author @TaoJie
 * @since 2024-10-22
 */
@Service
@Transactional
@RequiredArgsConstructor
public class WalletWithdrawRecordServiceImpl extends ServiceImpl<WalletWithdrawRecordMapper, WalletWithdrawRecordDO> implements WalletWithdrawRecordService {
 
    private final WalletWithdrawRecordMapper walletWithdrawRecordMapper;
    private final WalletService walletService;
    private final SupplierService supplierService;
 
    private final WalletBillRecordService walletBillRecordService;
 
 
    @Autowired
    RedissonClient redissonClient;
 
    @Transactional
    @Override
    public boolean create(CreateWalletWithdrawRecordDTO dto) {
 
        SupplierDTO supplierDTO = supplierService.getCurrentSupplier();
        if (null == supplierDTO) {
            throw new ValidationException("供应商不能为空");
        }
 
        WalletDO walletDO = walletService.getCurrentSupplier();
        if (null == walletDO) {
            throw new ValidationException("钱包不能为空");
        }
        // 查看钱包的金额是不是大于要提现的金额
        if (null != walletDO.getWithdrawableAmount() && null != dto.getAmount() && walletDO.getWithdrawableAmount().compareTo(dto.getAmount()) < 0) {
            throw new ValidationException("钱包金额不足");
        }
 
        RLock lock = redissonClient.getLock(String.format(LockConstants.WALLET_ID_KEY, walletDO.getId()));
        // 获取锁,最多等待 10 秒,锁自动释放时间 30 秒
        try {
            if (lock.tryLock(10, 30, TimeUnit.SECONDS)) {
                try {
 
                    // 加锁了之后需要二次查询,防止未加锁之前 someone else 已经修改了
                    walletDO = walletService.getCurrentSupplier();
                    if (null == walletDO) {
                        throw new ValidationException("钱包不能为空");
                    }
                    // 查看钱包的金额是不是大于要提现的金额
                    if (null != walletDO.getWithdrawableAmount() && null != dto.getAmount() && walletDO.getWithdrawableAmount().compareTo(dto.getAmount()) < 0) {
                        throw new ValidationException("钱包金额不足");
                    }
 
                    // 1.新增一条余额提现记录
                    WalletWithdrawRecordDO withdrawRecordDO = new WalletWithdrawRecordDO();
                    withdrawRecordDO.setAmount(dto.getAmount());
                    withdrawRecordDO.setSupplierId(supplierDTO.getId());
                    withdrawRecordDO.setWithdrawState(Constants.WALLET_WITHDRAW_STATE.WAITING.name());
                    withdrawRecordDO.setMethod(Constants.WALLET_WITHDRAW_METHOD.WEIXIN.name());
                    withdrawRecordDO.create(SecurityUtils.getUserId());
                    // 保存余额提现记录
                    save(withdrawRecordDO);
 
                    /*
                    // 2.新增一条账单明细
                    WalletBillRecordDO walletBillRecordDO=new WalletBillRecordDO();
                    walletBillRecordDO.setSupplierId(supplierDTO.getId());
                    walletBillRecordDO.setWalletId(walletDO.getId());
                    // 提现
                    walletBillRecordDO.setType(Constants.BILL_CHANGE_TYPE.withdraw.name());
                    walletBillRecordDO.setMethod(Constants.BILL_CHANGE_METHOD.add.name());
                    walletBillRecordDO.setOriginalAmount(walletDO.getWithdrawableAmount());
                    walletBillRecordDO.setChangeAmount(dto.getAmount());
                    walletBillRecordDO.setBalance(walletDO.getWithdrawableAmount().subtract(dto.getAmount()));
 
                    // 保存账单明细
                    walletBillRecordService.save(walletBillRecordDO);
*/
 
                    // 3. 钱包更新
                    // 钱包可提现的钱等于当前钱包可提现的钱-提现的钱
                    walletDO.setWithdrawableAmount(walletDO.getWithdrawableAmount().subtract(dto.getAmount()));
                    // 提现中的钱等于原有可提现的钱+提现的钱
                    walletDO.setWithdrawingAmount(walletDO.getWithdrawingAmount().add(dto.getAmount()));
                    walletDO.update(SecurityUtils.getUserId());
 
                    // 更新钱包
                    return walletService.updateById(walletDO);
 
                } finally {
                    lock.unlock();
                }
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
 
        return false;
    }
 
    @Override
    public Page<WalletWithdrawRecordVO> queryPage(QueryWalletWithdrawDTO queryWalletDTO, Page page) {
        List<WalletWithdrawRecordVO> list = walletWithdrawRecordMapper.queryPage(queryWalletDTO, page);
        page.setRecords(list);
        return page;
    }
 
    @Override
    public void updateWallet(WalletWithdrawRecordDTO walletWithdrawRecordDTO) {
        WalletWithdrawRecordDO withdrawRecordDO = walletWithdrawRecordMapper.selectById(walletWithdrawRecordDTO.getId());
        if (withdrawRecordDO == null) {
            throw new ValidationException("提现记录信息不存在");
        }
        if (StringUtils.isEmpty(walletWithdrawRecordDTO.getApproveState())) {
            throw new ValidationException("审批状态不能为空");
        }
        BeanUtils.copyProperties(walletWithdrawRecordDTO, withdrawRecordDO);
        withdrawRecordDO.update(SecurityUtils.getUserId());
        withdrawRecordDO.setApproveBy(SecurityUtils.getUserId());
        withdrawRecordDO.setApproveTime(LocalDateTime.now());
        walletWithdrawRecordMapper.updateById(withdrawRecordDO);
    }
 
}