| | |
| | | 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.QueryWalletDTO; |
| | | 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.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> |
| | |
| | | @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("供应商不能为空"); |
| | | } |
| | | |
| | | final WalletDO walletDO = walletService.getBySupplierId(); |
| | | 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("钱包金额不足"); |
| | | } |
| | | 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()); |
| | | return save(withdrawRecordDO); |
| | | |
| | | 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(QueryWalletDTO queryWalletDTO, Page page) { |
| | | public Page<WalletWithdrawRecordVO> queryPage(QueryWalletWithdrawDTO queryWalletDTO, Page page) { |
| | | List<WalletWithdrawRecordVO> list = walletWithdrawRecordMapper.queryPage(queryWalletDTO, page); |
| | | page.setRecords(list); |
| | | return page; |