package com.crm.pay.service.impl;

import com.crm.pay.dao.mapper.FinanceWithdrawMapper;
import com.crm.pay.dao.repository.*;
import com.crm.pay.entity.finance.withdraw.FinanceWithdrawApproveChannelEntity;
import com.crm.pay.entity.finance.withdraw.FinanceWithdrawApproveChannelSubmitEntity;
import com.crm.pay.entity.finance.withdraw.automatic.*;
import com.crm.pay.service.*;
import com.crm.rely.backend.configuration.LocaleMessage;
import com.crm.rely.backend.core.constant.*;
import com.crm.rely.backend.core.dto.base.BaseResultDto;
import com.crm.rely.backend.core.dto.base.PageDto;
import com.crm.rely.backend.core.dto.base.ResultWithPagerDto;
import com.crm.rely.backend.core.entity.system.email.SysEmailSendEntity;
import com.crm.rely.backend.core.exception.ServiceException;
import com.crm.rely.backend.core.pojo.table.*;
import com.crm.rely.backend.model.constant.ConfigConstants;
import com.crm.rely.backend.model.constant.EmailTemplateConstants;
import com.crm.rely.backend.model.constant.PayConstants;
import com.crm.rely.backend.model.dto.finance.withdraw.FinanceWithdrawDto;
import com.crm.rely.backend.model.entity.finance.withdraw.*;
import com.crm.rely.backend.model.pojo.table.*;
import com.crm.rely.backend.model.pojo.view.FinanceWithdrawView;
import com.crm.rely.backend.service.EmailService;
import com.crm.rely.backend.service.MqSendService;
import com.crm.rely.backend.util.*;
import com.google.common.base.Strings;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/**
 * @author houn
 */
@Slf4j
@Service
public class FinanceWithdrawServiceImpl implements FinanceWithdrawService {
    @Autowired
    private LocaleMessage localeMessage;

    @Autowired
    private FinanceWithdrawRepository financeWithdrawRepository;
    @Autowired
    private FinanceWithdrawMapper financeWithdrawMapper;
    @Autowired
    private FinanceRateService financeRateService;
    @Autowired
    private CustomInfoRepository customInfoRepository;
    @Autowired
    private CustomInfoService customInfoService;
    @Autowired
    private SysRemitChannelService sysRemitChannelService;
    @Autowired
    private SysChannelBankService sysChannelBankService;
    @Autowired
    private SysConfigService sysConfigService;
    @Autowired
    private MqSendService mqSendService;
    @Autowired
    private EmailService emailService;
    @Autowired
    private ProxpayService proxpayService;
    @Autowired
    private OfaPayService ofaPayService;
    @Autowired
    private CheezeepayService cheezeepayService;
    @Autowired
    private OzowService ozowService;
    @Autowired
    private CwgPayService cwgPayService;
    @Autowired
    private MtPayService mtPayService;
    @Autowired
    private EcomService ecomService;
    @Autowired
    private SysRemitChannelRepository sysRemitChannelRepository;
    @Autowired
    private UcardPayService ucardPayService;
    @Autowired
    private Va5PayService va5PayService;
    @Autowired
    private Pay3PayService pay3PayService;
    @Autowired
    private UGatePayService uGatePayService;
    @Autowired
    private FlashPayService flashPayService;
    @Autowired
    private PartnerPayService partnerPayService;
    @Autowired
    private GoldenCustomBalanceRecordRepository customBalanceRecordRepository;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResultDto save(FinanceWithdrawBaseAddEntity entity) throws Exception {
        if (Strings.isNullOrEmpty(entity.getBankCode())) {
            entity.setBankCode(entity.getPayType());
        }

        //获取通道
        SysRemitChannelTable sysRemitChannelTable = getChannel(entity.getPayType());
        if (!entity.getChannelType().equals(sysRemitChannelTable.getType())) {
            throw new ServiceException(Constants.SYSTEM_ERROR);
        }

        entity.setCurrency(sysRemitChannelTable.getCurrency());

        //获取银行信息
        SysChannelBankTable sysChannelBankTable = getBank(sysRemitChannelTable, entity);

        if (sysChannelBankTable != null) {
            entity.setTransformCurrency(sysChannelBankTable.getCurrency());
        } else {
            entity.setTransformCurrency(sysRemitChannelTable.getTransformCurrency());
        }
        CustomInfoTable customInfoTable = customInfoRepository.findFirstById(entity.getCustomId());
        if (customInfoTable == null) {
            throw new ServiceException(Constants.USER_NOT_EXIST_ERROR);
        }

        String name = customInfoTable.getName();

        //构建实体
        FinanceWithdrawTable financeWithdrawTable = new FinanceWithdrawTable();
        BeanUtils.copyProperties(entity, financeWithdrawTable);

        //计算手续费相关逻辑
        calculateFee(financeWithdrawTable, sysRemitChannelTable, sysChannelBankTable);

        //校验提款次数
        //calculateLimit(financeWithdrawTable.getCId());

        //计算实际打款金额
        calculateTransformAmount(financeWithdrawTable, sysRemitChannelTable, entity);

        //验证最大最小入金
        validated(entity, sysRemitChannelTable, sysChannelBankTable);


        //validDayLimit(financeWithdrawTable.getAmount(), customInfoTable, customLoginTable);


        financeWithdrawTable.setAreaCode(customInfoTable.getAreaCode());
        financeWithdrawTable.setPhone(customInfoTable.getPhone());
        financeWithdrawTable.setWithdrawCurrency(entity.getCurrency());

        financeWithdrawTable.setCallbackMq(entity.getCallbackMq());
        financeWithdrawTable.setExtParam(entity.getExtParam());

        //计算扣款金额
        calculateWithdrawAmount(financeWithdrawTable);

        financeWithdrawTable.setStatus(PayConstants.APPLY_STATUS);
        financeWithdrawTable.setSerial(getOrderNo());
        financeWithdrawTable.setName(name);
        financeWithdrawTable.setWithdrawStatus(PayConstants.MANAGER_PENDING_STATUS);
        financeWithdrawTable.setCallbackStatus(PayConstants.CALLBACE_PROCESSING_STATUS);
        

        financeWithdrawTable.setRemitChannelCode(sysRemitChannelTable.getCode());
        financeWithdrawTable.setRemitChannelCurrency(sysRemitChannelTable.getCurrency());
        financeWithdrawTable.setRemitChannelEnIcon(sysRemitChannelTable.getEnIcon());
        financeWithdrawTable.setRemitChannelEnIntroduce(sysRemitChannelTable.getEnIntroduce());
        financeWithdrawTable.setRemitChannelEnName(sysRemitChannelTable.getEnName());
        financeWithdrawTable.setRemitChannelIcon(sysRemitChannelTable.getIcon());
        financeWithdrawTable.setRemitChannelIntroduce(sysRemitChannelTable.getIntroduce());
        financeWithdrawTable.setRemitChannelName(sysRemitChannelTable.getName());
        financeWithdrawTable.setRemitChannelRequestUrl(sysRemitChannelTable.getRequestUrl());
        financeWithdrawTable.setRemitChannelType(sysRemitChannelTable.getType());
        financeWithdrawTable.setSalesStatus(PayConstants.APPLY_STATUS);
        financeWithdrawTable.setSubmitStatus(PayConstants.APPLY_STATUS);
        financeWithdrawTable.setBackstageStatus(PayConstants.APPLY_STATUS);
        financeWithdrawTable.setInfoStatus(PayConstants.APPLY_STATUS);

        financeWithdrawTable.setCountry(customInfoTable.getCountry());
        financeWithdrawRepository.save(financeWithdrawTable);

        customInfoTable.setBalance(customInfoTable.getBalance().subtract(entity.getAmount()));
        customInfoRepository.save(customInfoTable);

        return BaseResultDto.success(Constants.SUCCESS, financeWithdrawTable.getSerial());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResultDto<Object> cancel(FinanceWithdrawCancelEntity entity) throws Exception {

        FinanceWithdrawTable financeWithdrawTable = financeWithdrawRepository.findFirstById(entity.getId());
        if (financeWithdrawTable == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        if (!PayConstants.APPLY_STATUS.equals(financeWithdrawTable.getStatus())) {
            throw ServiceException.exception(PayConstants.NOT_CANCEL);
        }

        BeanUtils.copyProperties(entity, financeWithdrawTable);
        financeWithdrawTable.setStatus(PayConstants.CANCEL_STATUS);
        financeWithdrawRepository.save(financeWithdrawTable);

        return BaseResultDto.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResultDto<Object> cancelBackstage(FinanceWithdrawCancelEntity entity) throws Exception {

        FinanceWithdrawTable financeWithdrawTable = financeWithdrawRepository.findFirstById(entity.getId());
        if (financeWithdrawTable == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        if (!PayConstants.APPLY_STATUS.equals(financeWithdrawTable.getBackstageStatus())) {
            throw ServiceException.exception(PayConstants.NOT_CANCEL);
        }

        BeanUtils.copyProperties(entity, financeWithdrawTable);
        financeWithdrawTable.setStatus(PayConstants.CANCEL_STATUS);
        financeWithdrawTable.setBackstageStatus(PayConstants.CANCEL_STATUS);
        financeWithdrawRepository.save(financeWithdrawTable);
        refund(financeWithdrawTable);
        return BaseResultDto.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approve(FinanceWithdrawApproveEntity entity) throws ServiceException {//
        FinanceWithdrawTable financeWithdrawTable = financeWithdrawRepository.findFirstById(entity.getId());
        if (financeWithdrawTable == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        if (!PayConstants.MANAGER_PENDING_STATUS.equals(financeWithdrawTable.getWithdrawStatus())
                || !PayConstants.APPLY_STATUS.equals(financeWithdrawTable.getStatus())) {
            throw ServiceException.exception(Constants.CANNOT_APPROVE);
        }

        BeanUtils.copyProperties(entity, financeWithdrawTable);

        financeWithdrawRepository.save(financeWithdrawTable);
        refund(financeWithdrawTable);
        if (PayConstants.REJECTED_STATUS.equals(entity.getStatus())) {
            if (!Strings.isNullOrEmpty(financeWithdrawTable.getCallbackMq())) {
                mqSendService.send(financeWithdrawTable.getCallbackMq(), financeWithdrawTable);
            }
        }
        if (PayConstants.PASSED_STATUS.equals(entity.getStatus())) {
            FinanceWithdrawApproveManagerEntity managerEntity = new FinanceWithdrawApproveManagerEntity();
            managerEntity.setId(entity.getId());
            managerEntity.setWithdrawStatus(2);
            this.approve(managerEntity);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approve(FinanceWithdrawApproveSalesEntity entity) throws ServiceException {
        FinanceWithdrawTable table = financeWithdrawRepository.findFirstById(entity.getId());
        if (table == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        if (!PayConstants.APPLY_STATUS.equals(table.getStatus()) || !PayConstants.APPLY_STATUS.equals(table.getSalesStatus())) {
            throw ServiceException.exception(Constants.CANNOT_APPROVE);
        }

        table.setSalesStatus(entity.getStatus());
        table.setApproveDesc(entity.getApproveDesc());
        table.setApproveTime(entity.getApproveTime());
        table.setApproveUser(entity.getApproveUser());
        table.setModifyIp(entity.getModifyIp());
        table.setModifyTime(entity.getModifyTime());
        table.setModifyUser(entity.getModifyUser());
        if (PayConstants.REJECTED_STATUS.equals(entity.getStatus())) {
            table.setStatus(entity.getStatus());
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approve(FinanceWithdrawApproveManagerEntity entity) throws ServiceException {
        FinanceWithdrawTable financeWithdrawTable = financeWithdrawRepository.findFirstById(entity.getId());
        if (financeWithdrawTable == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        if (!PayConstants.MANAGER_PROCESSING_STATUS.equals(financeWithdrawTable.getWithdrawStatus())
                || !PayConstants.PASSED_STATUS.equals(financeWithdrawTable.getStatus())) {
            throw ServiceException.exception(Constants.CANNOT_APPROVE);
        }

        BeanUtils.copyProperties(entity, financeWithdrawTable);
        if (PayConstants.MANAGER_FAIL_STATUS.equals(entity.getWithdrawStatus())) {
            financeWithdrawTable.setStatus(entity.getWithdrawStatus());
        } else {
            financeWithdrawTable.setBackstageStatus(PayConstants.PASSED_STATUS);
            financeWithdrawTable.setInfoStatus(PayConstants.PASSED_STATUS);
        }

        financeWithdrawRepository.save(financeWithdrawTable);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approve(FinanceWithdrawApproveBackstageEntity entity) throws ServiceException {
        FinanceWithdrawTable financeWithdrawTable = financeWithdrawRepository.findFirstById(entity.getId());
        if (financeWithdrawTable == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        if (!PayConstants.MANAGER_COMPLETED_STATUS.equals(financeWithdrawTable.getWithdrawStatus())
                || !PayConstants.PASSED_STATUS.equals(financeWithdrawTable.getStatus())
                || !PayConstants.APPLY_STATUS.equals(financeWithdrawTable.getBackstageStatus())) {
            throw ServiceException.exception(Constants.CANNOT_APPROVE);
        }
        if (PayConstants.REJECTED_STATUS.equals(entity.getBackstageStatus())) {
            financeWithdrawTable.setStatus(entity.getBackstageStatus());
        }
        BeanUtils.copyProperties(entity, financeWithdrawTable);

        financeWithdrawRepository.save(financeWithdrawTable);

        refund(financeWithdrawTable);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approve(FinanceWithdrawApproveInfoEntity entity) throws ServiceException {
        FinanceWithdrawTable financeWithdrawTable = financeWithdrawRepository.findFirstById(entity.getId());
        if (financeWithdrawTable == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        if (!PayConstants.MANAGER_COMPLETED_STATUS.equals(financeWithdrawTable.getWithdrawStatus())
                || !PayConstants.PASSED_STATUS.equals(financeWithdrawTable.getStatus())
                || !PayConstants.PASSED_STATUS.equals(financeWithdrawTable.getBackstageStatus())
                || !PayConstants.APPLY_STATUS.equals(financeWithdrawTable.getInfoStatus())) {
            throw ServiceException.exception(Constants.CANNOT_APPROVE);
        }
        if (PayConstants.REJECTED_STATUS.equals(entity.getInfoStatus())) {
            financeWithdrawTable.setStatus(entity.getInfoStatus());
        }
        BeanUtils.copyProperties(entity, financeWithdrawTable);

        financeWithdrawRepository.save(financeWithdrawTable);

        refund(financeWithdrawTable);
        
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approve(FinanceWithdrawApproveInfosEntity entity) throws ServiceException {
        List<FinanceWithdrawTable> financeWithdrawTables = financeWithdrawRepository.findAllByIdIn(entity.getIds());
        if (financeWithdrawTables == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        for (FinanceWithdrawTable financeWithdrawTable : financeWithdrawTables) {
            if (!PayConstants.MANAGER_COMPLETED_STATUS.equals(financeWithdrawTable.getWithdrawStatus())
                    || !PayConstants.PASSED_STATUS.equals(financeWithdrawTable.getStatus())
                    || !PayConstants.PASSED_STATUS.equals(financeWithdrawTable.getBackstageStatus())
                    || !PayConstants.APPLY_STATUS.equals(financeWithdrawTable.getInfoStatus())) {
                throw ServiceException.exception(Constants.CANNOT_APPROVE);
            }
            if (PayConstants.REJECTED_STATUS.equals(entity.getInfoStatus())) {
                financeWithdrawTable.setStatus(entity.getInfoStatus());
            }
            BeanUtils.copyProperties(entity, financeWithdrawTable);
        }


        financeWithdrawRepository.save(financeWithdrawTables);

        refunds(financeWithdrawTables);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approve(FinanceWithdrawApproveChannelSubmitEntity entity) throws ServiceException {
        FinanceWithdrawTable financeWithdrawTable = financeWithdrawRepository.findFirstById(entity.getId());
        if (financeWithdrawTable == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }

        if (!PayConstants.MANAGER_COMPLETED_STATUS.equals(financeWithdrawTable.getWithdrawStatus())
                || !PayConstants.PASSED_STATUS.equals(financeWithdrawTable.getStatus())
                || !PayConstants.PASSED_STATUS.equals(financeWithdrawTable.getBackstageStatus())
                || !PayConstants.APPLY_STATUS.equals(financeWithdrawTable.getSubmitStatus())) {
            throw ServiceException.exception(Constants.CANNOT_APPROVE);
        }
        if (PayConstants.REJECTED_STATUS.equals(entity.getSubmitStatus())) {
            financeWithdrawTable.setStatus(entity.getSubmitStatus());
        }
        BeanUtils.copyProperties(entity, financeWithdrawTable);

        financeWithdrawTable.setSubmitTime(new Date());

        financeWithdrawRepository.save(financeWithdrawTable);

        refund(financeWithdrawTable);

        //createWithdrawSubmitSendEmailSysEmailEntity(financeWithdrawTable);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approve(FinanceWithdrawApproveChannelEntity entity) throws ServiceException {
        FinanceWithdrawTable financeWithdrawTable = null;
        if (entity.getId() == null && !Strings.isNullOrEmpty(entity.getSerial())) {

            financeWithdrawTable = financeWithdrawRepository.findFirstBySerial(entity.getSerial());
        } else {
            financeWithdrawTable = financeWithdrawRepository.findFirstById(entity.getId());

        }
        if (financeWithdrawTable == null) {

            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        if (PayConstants.CALLBACE_SUCCESS_STATUS.equals(financeWithdrawTable.getCallbackStatus()) || PayConstants.CALLBACE_FAIL_STATUS.equals(financeWithdrawTable.getCallbackStatus())) {
            return;
        }
        entity.setId(financeWithdrawTable.getId());
        entity.setSerial(financeWithdrawTable.getSerial());
        if (!PayConstants.MANAGER_COMPLETED_STATUS.equals(financeWithdrawTable.getWithdrawStatus())
                || !PayConstants.PASSED_STATUS.equals(financeWithdrawTable.getStatus())
                || !PayConstants.CALLBACE_PROCESSING_STATUS.equals(financeWithdrawTable.getCallbackStatus())
                || !PayConstants.MANAGER_COMPLETED_STATUS.equals(financeWithdrawTable.getSubmitStatus())) {
            return;
        }

        BeanUtils.copyProperties(entity, financeWithdrawTable);
        if (PayConstants.CALLBACE_FAIL_STATUS.equals(entity.getCallbackStatus())) {
            financeWithdrawTable.setStatus(PayConstants.REJECTED_STATUS);
        } else if (PayConstants.CALLBACE_SUCCESS_STATUS.equals(entity.getCallbackStatus())) {
            financeWithdrawTable.setStatus(PayConstants.MANAGER_COMPLETED_STATUS);

            GoldenCustomBalanceRecordTable record = new GoldenCustomBalanceRecordTable();
            record.setCustomId(financeWithdrawTable.getId());
            record.setCId(financeWithdrawTable.getCId());
            record.setAmount(financeWithdrawTable.getAmount());
            record.setType(1);
            record.setAddTime(new Date());
            customBalanceRecordRepository.save(record);

        }
        financeWithdrawTable.setCallbackTime(new Date());
        financeWithdrawRepository.save(financeWithdrawTable);

        refund(financeWithdrawTable);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approve(FinanceWithdrawApproveChannelSubmitsEntity entity) throws ServiceException {
        List<FinanceWithdrawTable> financeWithdrawTables = financeWithdrawRepository.findAllByIdIn(entity.getIds());
        if (financeWithdrawTables == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }

        for (FinanceWithdrawTable financeWithdrawTable : financeWithdrawTables) {
            if (!PayConstants.MANAGER_COMPLETED_STATUS.equals(financeWithdrawTable.getWithdrawStatus())
                    || !PayConstants.PASSED_STATUS.equals(financeWithdrawTable.getStatus())
                    || !PayConstants.PASSED_STATUS.equals(financeWithdrawTable.getBackstageStatus())
                    || !PayConstants.APPLY_STATUS.equals(financeWithdrawTable.getSubmitStatus())) {
                throw ServiceException.exception(Constants.CANNOT_APPROVE);
            }
            if (PayConstants.REJECTED_STATUS.equals(entity.getSubmitStatus())) {
                financeWithdrawTable.setStatus(entity.getSubmitStatus());
            }
            BeanUtils.copyProperties(entity, financeWithdrawTable);

            financeWithdrawTable.setSubmitTime(new Date());
        }


        financeWithdrawRepository.save(financeWithdrawTables);

        refunds(financeWithdrawTables);

        for (FinanceWithdrawTable financeWithdrawTable : financeWithdrawTables) {

            //createWithdrawSubmitSendEmailSysEmailEntity(financeWithdrawTable);

        }


    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approve(FinanceWithdrawApproveChannelsEntity entity) throws ServiceException {
        List<FinanceWithdrawTable> financeWithdrawTables = financeWithdrawRepository.findAllByIdIn(entity.getIds());
        if (financeWithdrawTables == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        for (FinanceWithdrawTable financeWithdrawTable : financeWithdrawTables) {
            if (!PayConstants.MANAGER_COMPLETED_STATUS.equals(financeWithdrawTable.getWithdrawStatus())
                    || !PayConstants.PASSED_STATUS.equals(financeWithdrawTable.getStatus())
                    || !PayConstants.CALLBACE_PROCESSING_STATUS.equals(financeWithdrawTable.getCallbackStatus())
                    || !PayConstants.MANAGER_COMPLETED_STATUS.equals(financeWithdrawTable.getSubmitStatus())) {
                throw ServiceException.exception(Constants.CANNOT_APPROVE);
            }

            BeanUtils.copyProperties(entity, financeWithdrawTable);
            if (PayConstants.CALLBACE_FAIL_STATUS.equals(entity.getCallbackStatus())) {
                financeWithdrawTable.setStatus(PayConstants.REJECTED_STATUS);
            }
            financeWithdrawTable.setCallbackTime(new Date());


        }

        financeWithdrawRepository.save(financeWithdrawTables);

        refunds(financeWithdrawTables);

        /*for (FinanceWithdrawTable financeWithdrawTable : financeWithdrawTables) {
            sendWithdrawCallbackSalesEmail(financeWithdrawTable);

            if (PayConstants.CALLBACE_SUCCESS_STATUS.equals(financeWithdrawTable.getCallbackStatus())) {
                if (!Strings.isNullOrEmpty(financeWithdrawTable.getCallbackMq())) {
                    mqSendService.send(financeWithdrawTable.getCallbackMq(), financeWithdrawTable);
                }
            }
        }*/
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(FinanceWithdrawDeleteEntity entity) throws ServiceException {
        List<FinanceWithdrawTable> allByIdIn = financeWithdrawRepository.findAllByIdIn(entity.getIds());
        if (allByIdIn == null || allByIdIn.size() <= 0) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }

        financeWithdrawRepository.delete(allByIdIn);
    }

    @Override
    public ResultWithPagerDto<FinanceWithdrawDto> searchList(FinanceWithdrawSearchListEntity entity) throws ServiceException {
        Integer count = financeWithdrawMapper.countList(entity);
        PageDto pageDto = PageDto.format(entity, count);
        if (count == null || count <= 0) {
            return ResultWithPagerDto.success(pageDto);
        }
        List<FinanceWithdrawView> financeWithdrawViews = financeWithdrawMapper.pageList(entity);

        if (financeWithdrawViews == null || financeWithdrawViews.size() <= 0) {

            throw new ServiceException(Constants.SYSTEM_ERROR);
        }
        List<FinanceWithdrawDto> financeWithdrawDtos = transform(financeWithdrawViews);

        return ResultWithPagerDto.success(pageDto, financeWithdrawDtos);
    }

    @Override
    public BaseResultDto<List<FinanceWithdrawDto>> searchListExport(FinanceWithdrawSearchListEntity entity) throws ServiceException {

        List<FinanceWithdrawView> financeWithdrawViews = financeWithdrawMapper.pageList(entity);
        List<FinanceWithdrawDto> financeWithdrawDtos = new ArrayList<>(financeWithdrawViews.size());

        for (FinanceWithdrawView view : financeWithdrawViews) {
            FinanceWithdrawDto transform = transform(view);
            financeWithdrawDtos.add(transform);
        }
        return BaseResultDto.success(financeWithdrawDtos);
    }

    @Override
    public BaseResultDto<List<FinanceWithdrawDto>> searcherByIdsExport(FinanceWithdrawSearchByIdsEntity entity) throws ServiceException {
        if (entity == null || entity.getIds() == null || entity.getIds().size() <= 0) {
            return BaseResultDto.success();
        }
        List<FinanceWithdrawView> financeWithdrawViews = financeWithdrawMapper.listByIds(entity.getIds(),
                entity.getStamp());

        if (financeWithdrawViews == null || financeWithdrawViews.size() <= 0) {
            return BaseResultDto.success();
        }
        List<FinanceWithdrawDto> financeWithdrawDtos = new ArrayList<>(financeWithdrawViews.size());

        for (FinanceWithdrawView view : financeWithdrawViews) {
            FinanceWithdrawDto transform = transform(view);
            financeWithdrawDtos.add(transform);
        }
        return BaseResultDto.success(financeWithdrawDtos);
    }

    @Override
    public FinanceWithdrawDto searchSingle(Long id) throws ServiceException {
        FinanceWithdrawView view = financeWithdrawMapper.getOne(id);
        if (view == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        return transform(view);
    }

    @Override
    public FinanceWithdrawTable getById(Long id) throws ServiceException {
        FinanceWithdrawTable table = financeWithdrawRepository.getFirstById(id);
        if (table == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        return table;
    }

    @Override
    public FinanceWithdrawTable getBySerial(String serial) throws ServiceException {
        FinanceWithdrawTable table = financeWithdrawRepository.getFirstBySerial(serial);
        if (table == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        return table;
    }

    private FinanceWithdrawDto transform(FinanceWithdrawView financeWithdrawView) {
        FinanceWithdrawDto dto = new FinanceWithdrawDto();
        BeanUtils.copyProperties(financeWithdrawView, dto);
        return dto;
    }

    private List<FinanceWithdrawDto> transform(List<FinanceWithdrawView> financeWithdrawViews){
        List<FinanceWithdrawDto> dtos = new ArrayList<>();
        for (FinanceWithdrawView financeWithdrawView : financeWithdrawViews) {
            dtos.add(transform(financeWithdrawView));
        }
        return dtos;
    }

    /*private List<FinanceWithdrawDto> transform(List<FinanceWithdrawView> financeWithdrawViews, boolean isBalance,
                                               int com) {
        List<FinanceWithdrawDto> financeWithdrawDtos = new ArrayList<>(financeWithdrawViews.size());

        List<CustomAccountLoginsEntity> customAccountLoginsEntities = new ArrayList<>(financeWithdrawViews.size());
        List<String> serials = new ArrayList<>(financeWithdrawViews.size());
        for (FinanceWithdrawView view : financeWithdrawViews) {
            CustomAccountLoginsEntity customAccountLoginsEntity = new CustomAccountLoginsEntity();
            customAccountLoginsEntity.setLogin(view.getLogin());
            customAccountLoginsEntity.setPlatform(view.getPlatform());
            customAccountLoginsEntities.add(customAccountLoginsEntity);
            serials.add(view.getSerial());
        }
//
        Map<String, AccountBalanceDto> dtoMap = null;
//        //判断是否需要请求信息
//        if (isBalance && customAccountLoginsEntities.size() > 0) {
//            try {
//                dtoMap = accountInfoFeignService.accountGetLogins(customAccountLoginsEntities);
//            } catch (Exception e) {
//                log.error(e.getMessage());
//                e.printStackTrace();
//            }
//        }

        Map<String, List<FinanceCommentDto>> serialsMap = null;
        //判断是否需要请求信息
        if (com > 0 && customAccountLoginsEntities.size() > 0) {
            try {
                serialsMap = financeCommentService.searchListByWithdraw(serials);
            } catch (Exception e) {
                log.error(e.getMessage());
                e.printStackTrace();
            }
        }

        for (FinanceWithdrawView view : financeWithdrawViews) {
            AccountBalanceDto accountBalanceDto = null;
            //判断返回结果是否有值
            if (dtoMap != null) {
                accountBalanceDto = dtoMap.get(String.valueOf(view.getLogin()));
            }

            List<FinanceCommentDto> financeCommentDtos = null;
            if (serialsMap != null) {
                financeCommentDtos = serialsMap.get(view.getSerial());
            }

            FinanceWithdrawDto transform = transform(view, accountBalanceDto, financeCommentDtos);

            financeWithdrawDtos.add(transform);
        }

        return financeWithdrawDtos;
    }

    private FinanceWithdrawDto transform(FinanceWithdrawView financeWithdrawView) {

        return transform(financeWithdrawView, null, null);
    }

    private FinanceWithdrawDto transform(FinanceWithdrawView financeWithdrawView, AccountBalanceDto accountBalanceDto
            , List<FinanceCommentDto> financeCommentDtos) {
        FinanceWithdrawDto dto = new FinanceWithdrawDto();
        BeanUtils.copyProperties(financeWithdrawView, dto);
        if (financeWithdrawView.getStatus() != null) {
            dto.setStatusName(getStatusName(financeWithdrawView));
        }
        if (accountBalanceDto != null) {

            dto.setBalance(accountBalanceDto.getBalance());
            dto.setEquity(accountBalanceDto.getEquity());
            dto.setCredit(accountBalanceDto.getCredit());
            dto.setFloating(accountBalanceDto.getFloating());
            dto.setLeverage(accountBalanceDto.getLeverage());
        }
        if (!Strings.isNullOrEmpty(financeWithdrawView.getActivityNote())) {
            dto.setActivityNote(JSON.parseArray(financeWithdrawView.getActivityNote(),
                    CustomActivityExceptionalManagerActivityNoteDto.class));
        }

        if (!Strings.isNullOrEmpty(financeWithdrawView.getAddressProve())) {
            dto.setAddressProve(Arrays.asList(financeWithdrawView.getAddressProve().split(",")));
        }

        if (Strings.isNullOrEmpty(dto.getApproveDesc())
                && financeCommentDtos != null
                && !financeCommentDtos.isEmpty()) {

            StringBuilder sb = new StringBuilder();

            for (FinanceCommentDto financeCommentDto : financeCommentDtos) {
                if (financeCommentDto == null || Strings.isNullOrEmpty(financeCommentDto.getComment())) {
                    continue;
                }
                if (sb.length() > 0) {
                    sb.append("\n");
                }
                sb.append(financeCommentDto.getComment());
            }

            if (sb.length() > 0) {
                dto.setApproveDesc(sb.toString());
            }
        }


        return dto;
    }

    private String getStatusName(FinanceWithdrawView financeWithdrawView) {
        try {
            return localeMessage.getMessage(TranslateUtil.statusToName(financeWithdrawView.getStatus(),
                    financeWithdrawView.getCallbackStatus(), financeWithdrawView.getWithdrawStatus()));
        } catch (Exception e) {
            return null;
        }
    }*/

    /**
     * 验证数据
     *
     * @param entity
     * @throws ServiceException
     */
    public void validated(FinanceWithdrawBaseAddEntity entity, SysRemitChannelTable sysRemitChannelTable,
                          SysChannelBankTable sysChannelBankTable) throws ServiceException {

        List<String> codes = new ArrayList<>(2);
        BigDecimal max = null;
        BigDecimal min = null;
        //判断银行(货币)通道上是否携带最大最小入金量
        if (sysChannelBankTable != null) {
            if (sysChannelBankTable.getMinAmount() != null) {
                min = sysChannelBankTable.getMinAmount();
            }
            if (sysChannelBankTable.getMaxAmount() != null) {
                max = sysChannelBankTable.getMaxAmount();
            }
        }
        //判断通道上是否携带最大最小入金量
        if (min == null && sysRemitChannelTable.getMinAmount() == null) {
            codes.add(ConfigConstants.FINANCE_WITHDRAW_MIN);
        } else {
            min = sysRemitChannelTable.getMinAmount();
        }
        if (max == null && sysRemitChannelTable.getMinAmount() == null) {
            codes.add(ConfigConstants.FINANCE_WITHDRAW_MAX);
        } else {
            max = sysRemitChannelTable.getMaxAmount();
        }
        if (codes != null && codes.size() > 0) {
            List<SysConfigTable> configTables = sysConfigService.getByCodes(codes);
            if (configTables == null || configTables.size() < codes.size()) {
                throw new ServiceException(Constants.SYSTEM_ERROR);
            }

            for (SysConfigTable configTable : configTables) {

                if (ConfigConstants.FINANCE_WITHDRAW_MAX.equals(configTable.getCode())) {
                    try {
                        max = new BigDecimal(configTable.getValue());
                    } catch (NumberFormatException e) {
                        throw new ServiceException(Constants.SYSTEM_ERROR);
                    }
                }
                if (ConfigConstants.FINANCE_WITHDRAW_MIN.equals(configTable.getCode())) {
                    try {
                        min = new BigDecimal(configTable.getValue());
                    } catch (NumberFormatException e) {
                        throw new ServiceException(Constants.SYSTEM_ERROR);
                    }
                }
            }
        }

        if (entity.getAmount().intValue() < min.intValue()) {
            throw new ServiceException(localeMessage.getMessage(PayConstants.FINANCE_WITHDRAW_AMOUNT_LESS_THAN,
                    PayConstants.FINANCE_WITHDRAW_AMOUNT_LESS_THAN) + min.intValue() + entity.getCurrency());
        }
        if (entity.getAmount().intValue() > max.intValue()) {
            throw new ServiceException(localeMessage.getMessage(PayConstants.FINANCE_WITHDRAW_AMOUNT_GREATER_THAN,
                    PayConstants.FINANCE_WITHDRAW_AMOUNT_GREATER_THAN) + max.intValue() + entity.getCurrency());
        }
    }

    /**
     * 获取通道
     *
     * @param channelCode
     * @return
     * @throws ServiceException
     */
    private SysRemitChannelTable getChannel(String channelCode) throws ServiceException {
        SysRemitChannelTable sysRemitChannelTable = sysRemitChannelService.getSysRemitChannelByCode(channelCode);

        if (sysRemitChannelTable == null) {
            throw new ServiceException(PayConstants.FINANCE_WITHDRAW_CHANNEL_NOT_EMPTY);
        }
        return sysRemitChannelTable;
    }

    /**
     * 获取银行信息
     *
     * @param channelTable
     * @param entity
     * @return
     * @throws ServiceException
     */
    private SysChannelBankTable getBank(SysRemitChannelTable channelTable, FinanceWithdrawBaseAddEntity entity) throws ServiceException {
        if (channelTable.getBankValid() != null && channelTable.getBankValid().equals(1)) {
            SysChannelBankTable sysChannelBankTable = sysChannelBankService.getByCode(entity.getBankCode(),
                    channelTable.getCode());
            if (sysChannelBankTable == null) {
                throw new ServiceException(Constants.SYSTEM_ERROR);
            }
            return sysChannelBankTable;
        }
        return null;
    }

    private void calculateTransformAmount(FinanceWithdrawTable financeWithdrawTable,
                                          SysRemitChannelTable sysRemitChannelTable,
                                          FinanceWithdrawBaseAddEntity entity) throws ServiceException {
        BigDecimal rate;
        try {
            if (sysRemitChannelTable.getRate() != null) {
                rate = sysRemitChannelTable.getRate();
            } else {
                rate = financeRateService.getRate(financeWithdrawTable.getCurrency(),
                        financeWithdrawTable.getTransformCurrency(), 1);
            }

            if (rate == null) {
                throw ServiceException.exception();
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            rate = null;
        }

        // 设置当前提现使用的汇率
        financeWithdrawTable.setRate(rate);

        if (rate != null) {

            // 如果请求中存在固定汇率和固定汇率金额
            // 且当前使用的汇率与固定汇率不一致
            if (entity.getFixedRate() != null
                    && entity.getFixedRateAmount() != null
                    && rate.compareTo(entity.getFixedRate()) != 0) {

                // 根据固定汇率金额反算提现原始金额
                // 计算方式：固定汇率金额 ÷ 汇率
                // 结果保留2位小数，并向上取整
                financeWithdrawTable.setAmount(
                        entity.getFixedRateAmount()
                                .divide(financeWithdrawTable.getRate(), 8, RoundingMode.UP)
                                .setScale(2, BigDecimal.ROUND_UP)
                );
            }

            if (financeWithdrawTable.getFeeAmount() != null && financeWithdrawTable.getFeeReductionAmount() != null && financeWithdrawTable.getFeeAmount().compareTo(financeWithdrawTable.getFeeReductionAmount()) == 0 && entity.getFixedRateAmount() != null) {
                // 计算最终转换金额（到账金额）
                financeWithdrawTable.setTransformAmount(entity.getFixedRateAmount());
            } else {
                // 计算最终转换金额（到账金额）
                // 公式：
                // (提现金额 - 手续费 + 手续费减免) × 当前汇率
                financeWithdrawTable.setTransformAmount(
                        financeWithdrawTable.getAmount()
                                .subtract(financeWithdrawTable.getFeeAmount())
                                .add(financeWithdrawTable.getFeeReductionAmount())
                                .multiply(rate)
                );
            }


        } else {
            // 如果没有汇率，则转换金额置为空
            financeWithdrawTable.setTransformAmount(null);
        }

        if (financeWithdrawTable.getTransformAmount() != null) {
            if ("cny".equals(financeWithdrawTable.getTransformCurrency().toLowerCase())
                    || "thb".equals(financeWithdrawTable.getTransformCurrency().toLowerCase())
                    || "vnd".equals(financeWithdrawTable.getTransformCurrency().toLowerCase())) {

                financeWithdrawTable.setTransformAmount(financeWithdrawTable.getTransformAmount().setScale(0,
                        BigDecimal.ROUND_DOWN));
            }
        }

    }

    /**
     * 获取平台出金金额
     *
     * @param financeWithdrawTable
     * @return
     * @throws ServiceException
     */
    private void calculateWithdrawAmount(FinanceWithdrawTable financeWithdrawTable) throws ServiceException {

        BigDecimal withdrawAmount = null;
        BigDecimal rate = null;
        if (financeWithdrawTable.getWithdrawCurrency().equals(financeWithdrawTable.getCurrency())) {
            withdrawAmount = financeWithdrawTable.getAmount();
        } else {
            //获取汇率 如果特定通道没有汇率 则根据我方设定汇率计算
            rate = financeRateService.getRate(financeWithdrawTable.getCurrency(),
                    financeWithdrawTable.getWithdrawCurrency(), 1);

            if (rate == null) {
                throw ServiceException.exception();
            }
            withdrawAmount = financeWithdrawTable.getAmount().multiply(rate);
        }


        financeWithdrawTable.setWithdrawAmount(withdrawAmount.setScale(2, BigDecimal.ROUND_UP));
    }
    
    private String getOrderNo() {
        /**
         * 生成订单号
         */
        String orderNo = GetRandom.getOrderNoByFormat("yyMMddHHmmssSS", PayConstants.WITHDRAW_HEAD);
        return orderNo;
    }

    @Override
    public void applyDigitalWithdrawSendEmailCode(FinanceApplyDigitalWithdrawSendEmailCodeEntity entity) throws ServiceException {

        //构建实体
       /* SysEmailSendEntity sysEmailSendEntity = createApplyDigitalWithdrawSendEmailSysEmailEntity(entity);

        //发送收据
        emailService.sendCode(sysEmailSendEntity, sysEmailSendEntity.getMap().get(MapConstants.CODE) +
                "applyDigitalWithdrawSendEmailCode");*/
    }

    @Override
    public void applyDigitalWithdrawValidateCode(FinanceWithdrawBaseAddEntity entity) throws ServiceException {

        emailService.validateCode(entity.getEmail(), entity.getEmailCode() +
                "applyDigitalWithdrawSendEmailCode");
    }

    /*@Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResultDto getWebsdkLink(WebsdkLinkAliEntity entity, Long id) throws ServiceException {
        SysConfigTable kycWithdrawConfigTable = sysConfigService.getByCode(ConfigConstants.AUTOMATIC_KYC_WITHDRAW);
        if (kycWithdrawConfigTable == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        SysConfigTable kycFastWithdrawConfigTable =
                sysConfigService.getByCode(ConfigConstants.AUTOMATIC_KYC_FAST_WITHDRAW);
        if (kycFastWithdrawConfigTable == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        if ("0".equals(kycWithdrawConfigTable.getValue()) && "0".equals(kycFastWithdrawConfigTable.getValue())) {
            return BaseResultDto.success();
        }

        CustomInfoTable table = customInfoRepository.findFirstById(id);
        if (table == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        FinanceWithdrawTable withdrawTable = financeWithdrawRepository.findFirstBySerial(entity.getSerial());
        if (withdrawTable == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        SysConfigTable sysConfigTable = sysConfigService.getByCode(ConfigConstants.CUSTOM_VERIFY_KYC_PROPERTY);
        if (sysConfigTable == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        SysKycConfigTable kycConfig = sysKycConfigService.getByCodeAndCountryAndEnable(sysConfigTable.getValue(),
                table.getCountry(), 1);
        if (kycConfig == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }

        if (2 == kycConfig.getKycType() && !Strings.isNullOrEmpty(withdrawTable.getKycVerifyUrl())) {
            return BaseResultDto.success(Constants.SUCCESS, withdrawTable.getKycVerifyUrl());
        }

        CustomKycVerifyRecodeEntity customKycVerifyRecodeEntity = new CustomKycVerifyRecodeEntity();
        customKycVerifyRecodeEntity.setCountry(table.getCountry());
        customKycVerifyRecodeEntity.setConfig(ConfigConstants.CUSTOM_VERIFY_KYC_PROPERTY);
        customKycVerifyRecodeEntity.setCardType(table.getCardType());
        customKycVerifyRecodeEntity.setVerifyId(table.getId());
        customKycVerifyRecodeEntity.setVerifyType(3);
        customKycVerifyRecodeEntity.setOrderSerial(entity.getSerial());
        customKycVerifyRecodeEntity.setCustomAuth(table.getAuthStatus());
        customKycVerifyRecodeEntity.setEndUserId(Strings.isNullOrEmpty(table.getEndUserId()) ?
                UUID.randomUUID().toString() : table.getEndUserId());

        if (3 != kycConfig.getKycType()) {
            withdrawTable.setExternalUserId(UUIDUtil.getUUID());

            customKycVerifyRecodeEntity.setExternalUserId(withdrawTable.getExternalUserId());
            String applicantId = kycFeignService.createApplicant(customKycVerifyRecodeEntity);

            *//*customKycVerifyRecodeEntity.setApplicantId(applicantId);
            List<CustomFileTable> fileList = customFileDao.findFileByType(table.getId());
            if(fileList != null && fileList.size() > 0){
                customKycVerifyRecodeEntity.setVerifyType(1);
                customKycVerifyRecodeEntity.setVerifyFile(fileList.stream().map(CustomFileTable::getPath).collect
                (Collectors.joining(",")));
                kycFeignService.uploadImage(customKycVerifyRecodeEntity);
            }*//*

            withdrawTable.setApplicantId(applicantId);
        }

        withdrawTable.setAuthStatus(0);
        withdrawTable.setExternalUserId(Strings.isNullOrEmpty(customKycVerifyRecodeEntity.getExternalUserId()) ?
                UUIDUtil.getUUID() : customKycVerifyRecodeEntity.getExternalUserId());

        customKycVerifyRecodeEntity.setMetaInfo(entity.getMetaInfo());
        customKycVerifyRecodeEntity.setExternalUserId(withdrawTable.getExternalUserId());
        customKycVerifyRecodeEntity.setApplicantId(withdrawTable.getApplicantId());
        BaseResultDto dto = kycFeignService.getWebsdkLink(customKycVerifyRecodeEntity);
        if (2 == kycConfig.getKycType() && Strings.isNullOrEmpty(withdrawTable.getKycVerifyUrl())) {
            withdrawTable.setKycVerifyUrl(dto.getData().toString());
        }
        financeWithdrawRepository.save(withdrawTable);

        if (Strings.isNullOrEmpty(table.getEndUserId())) {
            table.setEndUserId(customKycVerifyRecodeEntity.getEndUserId());
            customInfoRepository.save(table);
        }

        return dto;
    }*/

    public void fastFinanceWithdraw(FinanceWithdrawTable table) throws Exception {
        log.info(String.format("越南快速出金通道处理:%s", table.getSerial()));

        switch (table.getPayType()) {
            case PayConstants.PROXPAY_PAY_TYPE_REMIT:
                FinanceWithdrawProxpayEntity proxpayEntity = new FinanceWithdrawProxpayEntity();
                proxpayEntity.setName(table.getName());
                proxpayEntity.setBankName(table.getBankName());
                proxpayEntity.setBookBankName(table.getBankUname());
                proxpayEntity.setBookBankNumber(table.getBankCardNum());
                proxpayEntity.setBookBankBranch(table.getBankBranchName());
                proxpayEntity.setAmount(table.getTransformAmount() == null ? null :
                        table.getTransformAmount().setScale(2, BigDecimal.ROUND_DOWN));
                proxpayEntity.setPreferCurrency(table.getTransformCurrency());
                proxpayEntity.setRefCustomerId(String.valueOf(table.getCId()));
                proxpayEntity.setId(table.getId());
                proxpayEntity.setSerial(table.getSerial());
                proxpayEntity.setPayType(table.getPayType());
                proxpayService.withdraw(proxpayEntity);
                break;
            case PayConstants.OFA_PAY_TYPE_REMIT:
                FinanceWithdrawOfaEntity ofapayEntity = new FinanceWithdrawOfaEntity();
                ofapayEntity.setMoney(table.getTransformAmount() == null ? null :
                        table.getTransformAmount().setScale(2, BigDecimal.ROUND_DOWN));
                ofapayEntity.setAccountname(table.getName());
                ofapayEntity.setAccountno(table.getBankCardNum());
                if (!Strings.isNullOrEmpty(table.getBankName())) {
                    String[] sp = table.getBankName().split("-");
                    if (sp.length >= 2) {
                        ofapayEntity.setBankname(sp[0]);
                        ofapayEntity.setBankno(sp[1]);
                    }
                }
                ofapayEntity.setId(table.getId());
                ofapayEntity.setSerial(table.getSerial());
                ofapayEntity.setPayType(table.getPayType());
                ofaPayService.withdraw(ofapayEntity);
                break;

            case PayConstants.CHEEZEEPAY_PAY_TYPE_REMIT:
                FinanceWithdrawCheezeepayEntity cheezeepayEntity = new FinanceWithdrawCheezeepayEntity();
                cheezeepayEntity.setAmount(table.getTransformAmount() == null ? null :
                        table.getTransformAmount().setScale(2, BigDecimal.ROUND_DOWN));
                cheezeepayEntity.setName(table.getName());
                cheezeepayEntity.setAccountNumber(table.getBankCardNum());
                cheezeepayEntity.setIfscCode(table.getCustomBankCode());
                cheezeepayEntity.setBankName(table.getBankName());
                cheezeepayEntity.setBranchName(table.getBankBranchName());
                cheezeepayEntity.setId(table.getId());
                cheezeepayEntity.setSerial(table.getSerial());
                cheezeepayEntity.setPayType(table.getPayType());
                cheezeepayService.withdraw(cheezeepayEntity);
                break;
            case PayConstants.OZOW_PAY_TYPE_REMIT:
                FinanceWithdrawOzowEntity ozowEntity = new FinanceWithdrawOzowEntity();
                ozowEntity.setAmount(table.getTransformAmount() == null ? null :
                        table.getTransformAmount().setScale(2, BigDecimal.ROUND_DOWN));
                ozowEntity.setBankingCode(table.getCustomBankCode());
                ozowEntity.setAccountNumber(table.getBankCardNum());
                ozowEntity.setId(table.getId());
                ozowEntity.setSerial(table.getSerial());
                ozowEntity.setPayType(table.getPayType());
                ozowService.withdraw(ozowEntity);
                break;
            case PayConstants.CWG_UNION_PAY_TYPE_REMIT:
                FinanceWithdrawCwgEntity cwgEntity = new FinanceWithdrawCwgEntity();
                cwgEntity.setAmount(table.getTransformAmount() == null ? null :
                        table.getTransformAmount().setScale(2, BigDecimal.ROUND_DOWN));
                cwgEntity.setBankUname(table.getBankUname());
                cwgEntity.setName(table.getName());
                cwgEntity.setBankCardNum(table.getBankCardNum());
                cwgEntity.setBankBranchName(table.getBankBranchName());
                if (!Strings.isNullOrEmpty(table.getBankName())) {
                    String[] sp = table.getBankName().split("-");
                    cwgEntity.setBankName(sp[0]);
                }
                cwgEntity.setBankAddr(table.getBankAddr());
                cwgEntity.setSwiftCode(table.getSwiftCode());
                cwgEntity.setBankCode(table.getBankCode());
                cwgEntity.setId(table.getId());
                cwgEntity.setSerial(table.getSerial());
                cwgEntity.setPayType(table.getPayType());
                cwgPayService.withdraw(cwgEntity);
            case PayConstants.CWG_PAY_TYPE_REMIT:
                FinanceWithdrawCwgEntity cwgAliEntity = new FinanceWithdrawCwgEntity();
                cwgAliEntity.setAmount(table.getTransformAmount() == null ? null :
                        table.getTransformAmount().setScale(2, BigDecimal.ROUND_DOWN));
                cwgAliEntity.setName(table.getName());
                cwgAliEntity.setWalletAddress(table.getAddress());
                cwgAliEntity.setId(table.getId());
                cwgAliEntity.setSerial(table.getSerial());
                cwgAliEntity.setPayType(table.getPayType());
                cwgPayService.withdraw(cwgAliEntity);
            case PayConstants.MT_PAY_TYPE_REMIT:
                FinanceWithdrawMtpayEntity mtpayEntity = new FinanceWithdrawMtpayEntity();
                mtpayEntity.setRealName(table.getName());
                mtpayEntity.setWithdrawAmount(table.getTransformAmount() == null ? null :
                        table.getTransformAmount().setScale(2, BigDecimal.ROUND_DOWN));
                mtpayEntity.setCardNumber(table.getBankCardNum());
                mtpayEntity.setBankName(table.getBankName());
                mtpayEntity.setBankBranchName(table.getBankBranchName());
                mtpayEntity.setWithdrawCurrency(table.getWithdrawCurrency());
                mtpayEntity.setFiatCurrency(table.getTransformCurrency());
                mtpayEntity.setId(table.getId());
                mtpayEntity.setSerial(table.getSerial());
                mtpayEntity.setPayType(table.getPayType());
                mtPayService.withdraw(mtpayEntity);
                break;
            case PayConstants.PAY_ECOM_REMIT_KEY:
                FinanceWithdrawEcomEntity payEcomEntity = new FinanceWithdrawEcomEntity();
                payEcomEntity.setAmount(table.getTransformAmount() == null ? null :
                        table.getTransformAmount().setScale(2, BigDecimal.ROUND_DOWN));
                payEcomEntity.setBankAccountName(table.getName());
                payEcomEntity.setBankAccountNo(table.getBankCardNum());
                payEcomEntity.setBankCode(table.getBankCode());
                payEcomEntity.setId(table.getId());
                payEcomEntity.setSerial(table.getSerial());
                payEcomEntity.setPayType(table.getPayType());
                ecomService.withdraw(payEcomEntity);
                break;
//            case PayConstants.VA5_PAY_TYPE_USDT_REMIT:
//                FinanceWithdrawVa5PayEntity va5PayUsdtEntity = new FinanceWithdrawVa5PayEntity();
//                va5PayUsdtEntity.setWallet("");
//                va5PayUsdtEntity.setToken(table.getBankCode());
//                va5PayUsdtEntity.setWithdrawalAmount(table.getTransformAmount() == null ? null : table
//                .getTransformAmount().setScale(2, BigDecimal.ROUND_DOWN));
//                va5PayUsdtEntity.setByReceivableAmount(false);
//                va5PayUsdtEntity.setWalletAddress(table.getAddress());
//                va5PayUsdtEntity.setId(table.getId());
//                va5PayUsdtEntity.setSerial(table.getSerial());
//                va5PayUsdtEntity.setPayType(table.getPayType());
//                va5PayService.withdraw(va5PayUsdtEntity);
//                break;
//            case PayConstants.VA5_PAY_TYPE_F2F_REMIT:
//                FinanceWithdrawVa5PayEntity va5PayF2fEntity = new FinanceWithdrawVa5PayEntity();
//
//                va5PayF2fEntity.setWallet("Fiat2Fiat");
//                va5PayF2fEntity.setToken(table.getBankCode());
//                va5PayF2fEntity.setWithdrawalAmount(table.getTransformAmount() == null ? null : table
//                .getTransformAmount().setScale(2, BigDecimal.ROUND_DOWN));
//                va5PayF2fEntity.setByReceivableAmount(false);
//                va5PayF2fEntity.setBeneficiaryName(table.getName());
//                va5PayF2fEntity.setBeneficiaryAccountNumber(table.getBankCardNum());
//                va5PayF2fEntity.setBeneficiaryBank(table.getBankName());
//                va5PayF2fEntity.setBeneficiaryBankAddress(table.getBankAddr());
//                va5PayF2fEntity.setBeneficiaryBankCode(table.getBankCode());
//                va5PayF2fEntity.setBeneficiaryBankSwiftCode(table.getSwiftCode());
//                va5PayF2fEntity.setBeneficiaryPhoneNumber(table.getPhone());
//                va5PayF2fEntity.setIfsc(table.getBankCode());
//                va5PayF2fEntity.setId(table.getId());
//                va5PayF2fEntity.setSerial(table.getSerial());
//                va5PayF2fEntity.setPayType(table.getPayType());
//                va5PayService.withdraw(va5PayF2fEntity);
//                break;
            case PayConstants.PAY3_PAY_TYPE_REMIT:
                FinanceWithdrawPay3payEntity pay3PayEntity = new FinanceWithdrawPay3payEntity();
                pay3PayEntity.setAmount(table.getTransformAmount() == null ? null :
                        table.getTransformAmount().setScale(2, BigDecimal.ROUND_DOWN));
                pay3PayEntity.setCurrency(table.getBankCode());
                pay3PayEntity.setAddress(table.getAddress());
                pay3PayEntity.setId(table.getId());
                pay3PayEntity.setSerial(table.getSerial());
                pay3PayEntity.setPayType(table.getPayType());
                pay3PayService.withdraw(pay3PayEntity);
                break;
            case PayConstants.UCARD_PAY_TYPE_REMIT:
                FinanceWithdrawUcardpayEntity ucardPayEntity = new FinanceWithdrawUcardpayEntity();
                ucardPayEntity.setAmount(table.getTransformAmount() == null ? null :
                        table.getTransformAmount().setScale(2, BigDecimal.ROUND_DOWN));
                ucardPayEntity.setId(table.getId());
                ucardPayEntity.setSerial(table.getSerial());
                ucardPayEntity.setPayType(table.getPayType());
                ucardPayService.withdraw(ucardPayEntity);
                break;
            case PayConstants.UGATE_PAY_TYPE_REMIT:
                FinanceWithdrawUGateEntity uGatePayEntity = new FinanceWithdrawUGateEntity();
                uGatePayEntity.setReceiverName(table.getName());
                uGatePayEntity.setMerchantSellOrderMoney(table.getTransformAmount() == null ? null :
                        table.getTransformAmount().setScale(2, RoundingMode.DOWN).toString());
                uGatePayEntity.setReceiverAccount(table.getBankCardNum());
                uGatePayEntity.setReceiverBankName(table.getBankName());
                uGatePayEntity.setReceiverBankAddress(table.getBankBranchName());
                uGatePayEntity.setId(table.getId());
                uGatePayEntity.setSerial(table.getSerial());
                uGatePayEntity.setPayType(table.getPayType());
                uGatePayService.withdraw(uGatePayEntity);
                break;
            case PayConstants.FLASH_PAY_TYPE_REMIT:
                FinanceWithdrawFlashEntity flashPayEntity = new FinanceWithdrawFlashEntity();
                flashPayEntity.setAmount(table.getTransformAmount() == null ? null :
                        table.getTransformAmount().setScale(2, BigDecimal.ROUND_DOWN));
                flashPayEntity.setBankcardAccountName(table.getName());
                flashPayEntity.setBankcardAccountNo(table.getBankName());
                flashPayEntity.setBankCode(table.getCustomBankCode());

                flashPayEntity.setId(table.getId());
                flashPayEntity.setSerial(table.getSerial());
                flashPayEntity.setPayType(table.getPayType());
                flashPayService.withdraw(flashPayEntity);
                break;
            case PayConstants.PARTNER_PAY_TYPE_REMIT:
                FinanceWithdrawPartnerEntity partnerEntity = new FinanceWithdrawPartnerEntity();
                partnerEntity.setAmount(table.getTransformAmount() == null ? null :
                        table.getTransformAmount().setScale(2, BigDecimal.ROUND_DOWN));
                partnerEntity.setName(table.getName());
                partnerEntity.setBankName(table.getBankUname());
                partnerEntity.setBankBranch(table.getBankBranchName());
                partnerEntity.setBankAccount(table.getBankCardNum());

                partnerEntity.setId(table.getId());
                partnerEntity.setSerial(table.getSerial());
                partnerEntity.setPayType(table.getPayType());
                partnerPayService.withdraw(partnerEntity);
                break;
            default:
                break;
        }
    }


    /*private SysEmailSendEntity createApplyDigitalWithdrawSendEmailSysEmailEntity(FinanceApplyDigitalWithdrawSendEmailCodeEntity entity) throws ServiceException {
        SysEmailSendEntity sysEmailSendEntity = new SysEmailSendEntity();

        Map<String, String> map = new HashMap<>(2);
        String code = GetRandom.getRandom(6);
        map.put(MapConstants.CODE, code);
        Date time = DateUtil.operationMinute(new Date(), Constants.EMAIL_VALIDATECODE_TIME);
        map.put(MapConstants.EXPIRE_TIME, DateUtil.formatTime(time));
        map.put(MapConstants.DATE_TIME, DateUtil.formatTime());

        sysEmailSendEntity.setAddIp(entity.getIp());
        sysEmailSendEntity.setAddTime(entity.getTime());

        sysEmailSendEntity.setUsers(entity.getEmail());
        sysEmailSendEntity.setEmailSendEnum(EmailSendEnum.CUSTOM_APPLY_DIGITAL_WITHDRAW_SEND);
        if (CountryUtil.isCN(entity.getCountry())) {
            sysEmailSendEntity.setTemplateName(EmailTemplateConstants.CUSTOM_APPLY_DIGITAL_WITHDRAW_SEND_CN);
        } else {
            sysEmailSendEntity.setTemplateName(EmailTemplateConstants.CUSTOM_APPLY_DIGITAL_WITHDRAW_SEND_EN);
        }
        sysEmailSendEntity.setMap(map);
        //发送收据
        emailService.sendEmail(sysEmailSendEntity);
        return sysEmailSendEntity;
    }

    private void createWithdrawSubmitSendEmailSysEmailEntity(FinanceWithdrawTable table) throws ServiceException {

        if (!PayConstants.PASSED_STATUS.equals(table.getSubmitStatus())) {
            return;
        }

        try {
            CustomInfoTable customInfoTable = customInfoService.getById(table.getCustomId());
            SysEmailSendEntity sysEmailSendEntity = new SysEmailSendEntity();

            Map<String, String> map = new HashMap<>(2);

            map.put(MapConstants.SERIAL, table.getSerial());

            map.put(MapConstants.NAME, table.getName());
            map.put(MapConstants.DATE_TIME, DateUtil.formatTime());

            sysEmailSendEntity.setUsers(customInfoTable.getEmail());
            sysEmailSendEntity.setEmailSendEnum(EmailSendEnum.CUSTOM_WITHDRAW_SUBMIT_SEND);
            if (CountryUtil.isCN(customInfoTable.getCountry())) {
                sysEmailSendEntity.setTemplateName(EmailTemplateConstants.CUSTOM_WITHDRAW_SUBMIT_SEND_CN);
            } else {
                sysEmailSendEntity.setTemplateName(EmailTemplateConstants.CUSTOM_WITHDRAW_SUBMIT_SEND_EN);
            }
            sysEmailSendEntity.setMap(map);
            emailService.sendEmail(sysEmailSendEntity);

            WebNoticeRecordAndEmailMqEntity mqEntity = new WebNoticeRecordAndEmailMqEntity(sysEmailSendEntity,
                    table.getCId());
            mqSendService.send(Constants.WEB_NOTICE_PUT_RECORD, mqEntity);
        } catch (Exception e) {
            return;
        }

    }*/

    private void refund(FinanceWithdrawTable table) throws ServiceException {
        if ((PayConstants.CALLBACE_FAIL_STATUS.equals(table.getCallbackStatus())
                || PayConstants.REJECTED_STATUS.equals(table.getSubmitStatus())
                || PayConstants.REJECTED_STATUS.equals(table.getBackstageStatus())
                || PayConstants.REJECTED_STATUS.equals(table.getInfoStatus())
                || PayConstants.CANCEL_STATUS.equals(table.getBackstageStatus())
                ||PayConstants.REJECTED_STATUS.equals(table.getStatus()))
                //&& table.getOperationType() != null
                //&& PayConstants.OPERATION_TYPE_AUTOMATIC == table.getOperationType()
                //&& PayConstants.MANAGER_COMPLETED_STATUS.equals(table.getWithdrawStatus())
        ) {

            CustomInfoTable customInfoTable = customInfoRepository.findFirstById(table.getCustomId());
            if (customInfoTable == null) {
                log.error("custom refund error:"+table.getSerial());
            }
            customInfoTable.setBalance(customInfoTable.getBalance().add(table.getAmount()));
            customInfoRepository.save(customInfoTable);

        }
    }

    private void refunds(List<FinanceWithdrawTable> tables) throws ServiceException {
        if (tables == null) {
            return;
        }

        for (FinanceWithdrawTable table : tables) {
            if ((PayConstants.CALLBACE_FAIL_STATUS.equals(table.getCallbackStatus())
                    || PayConstants.REJECTED_STATUS.equals(table.getSubmitStatus())
                    || PayConstants.REJECTED_STATUS.equals(table.getBackstageStatus())
                    || PayConstants.REJECTED_STATUS.equals(table.getInfoStatus())
                    || PayConstants.CANCEL_STATUS.equals(table.getBackstageStatus()))
                    && table.getOperationType() != null
                    && PayConstants.OPERATION_TYPE_AUTOMATIC == table.getOperationType()
                    && PayConstants.MANAGER_COMPLETED_STATUS.equals(table.getWithdrawStatus())) {

                CustomInfoTable customInfoTable = customInfoRepository.findFirstById(table.getCustomId());
                if (customInfoTable == null) {
                    log.error("custom refund error:"+table.getSerial());
                }
                customInfoTable.setBalance(customInfoTable.getBalance().add(table.getAmount()));
                customInfoRepository.save(customInfoTable);

            }
        }
    }

   /* private void validDayLimit(BigDecimal withdrawAmount, CustomInfoTable customInfoTable) throws ServiceException {

        BigDecimal limitAmount = null;
        if (customInfoTable.getDayWithdrawLimit() != null) {
            limitAmount = customInfoTable.getDayWithdrawLimit();
        } else {
            SysConfigTable configTable = sysConfigService.getByCode(ConfigConstants.FINANCE_WITHDRAW_DAY_LIMIT);
            if (Strings.isNullOrEmpty(configTable.getValue())) {
                return;
            }
            limitAmount = new BigDecimal(configTable.getValue());
        }

        //如果小于0 则表示每日出金无限制
        if (limitAmount == null || limitAmount.compareTo(BigDecimal.ZERO) < 0) {
            return;
        }

        Date startDate = DateUtil.parseDate();

        Float amount = financeWithdrawMapper.getCountAmountByDateAndCId(startDate, DateUtil.addDate(startDate, 1),
                customLoginTable.getCId());

        if (amount == null) {
            amount = 0f;
        }
        BigDecimal dayAmount = new BigDecimal(amount);
        if (withdrawAmount.add(new BigDecimal(amount)).compareTo(limitAmount) > 0) {
            throw new ServiceException(String.format(localeMessage.getMessage("finance_withdraw_amount_day_limit"),
                    String.format("%.2f", limitAmount.add(dayAmount.negate()).doubleValue())));
        }
    }*/

    private void calculateFee(FinanceWithdrawTable table, SysRemitChannelTable remitChannelTable,
                              SysChannelBankTable sysChannelBankTable) throws ServiceException {

        // 计算手续费金额
        BigDecimal feeAmount = BigDecimal.ZERO;
        if (sysChannelBankTable == null || sysChannelBankTable.getFeeType() == null) {

            feeAmount = cleFeeAmount(remitChannelTable.getFeeType(), remitChannelTable.getFree(),
                    remitChannelTable.getFeeAmount(), table.getAmount());

        } else {
            feeAmount = cleFeeAmount(sysChannelBankTable.getFeeType(), sysChannelBankTable.getFree(),
                    sysChannelBankTable.getFeeAmount(), table.getAmount());
        }


        table.setFeeAmount(feeAmount);

        if (feeAmount.compareTo(BigDecimal.ZERO) == 0) {
            table.setFeeReduction(0);
            table.setFeeReductionAmount(BigDecimal.ZERO);
            return;
        }

        int reductionNumber = getReductionNumber();

        int count = getMonthNumber(table.getCId());//减免次数

        // 如果出金次数少于减免次数，则减免手续费
        if (count < reductionNumber) {
            table.setFeeReduction(1);
            table.setFeeReductionAmount(feeAmount);
            return;
        }

//        // 根据账号手续费减免次数判断是否减免
//        if (customLoginService.updateWithdrawFeeReduction(table.getLogin(), -1) >= 1) {
//            table.setFeeReduction(1);
//            table.setFeeReductionAmount(feeAmount);
//        } else {
//            table.setFeeReduction(0);
//            table.setFeeReductionAmount(BigDecimal.ZERO);
//        }

        // 根据cid手续费减免次数判断是否减免
        if (customInfoService.updateWithdrawFeeReduction(table.getCId(), -1) >= 1) {
            table.setFeeReduction(1);
            table.setFeeReductionAmount(feeAmount);
        } else {
            table.setFeeReduction(0);
            table.setFeeReductionAmount(BigDecimal.ZERO);
        }
    }

    private BigDecimal cleFeeAmount(Integer feeType, Integer feeRate, BigDecimal feeTypeAmount, BigDecimal amount) {
        BigDecimal feeAmount = BigDecimal.ZERO;
        // 处理费率类型逻辑
        if (feeType != null && feeType.equals(1)) {

            if (feeRate == null) {
                feeRate = 0;
            } else {
                feeAmount = amount
                        .multiply(new BigDecimal(feeRate))
                        .divide(new BigDecimal(100), 5, BigDecimal.ROUND_HALF_UP)
                        .setScale(2, BigDecimal.ROUND_UP);
            }
        } else if (feeType != null && feeType.equals(2)) {
            // 固定金额手续费
            feeAmount = feeTypeAmount == null ? BigDecimal.ZERO : feeTypeAmount;
        } else {
            feeAmount = BigDecimal.ZERO;
        }
        return feeAmount;
    }

    private int getReductionNumber() throws ServiceException {
        // 计算减免次数
        SysConfigTable configTable = sysConfigService.getByCode(ConfigConstants.FINANCE_WITHDRAW_FEE_REDUCTION_NUMBER);

        // 如果减免配置为空，则不减免
        if (Strings.isNullOrEmpty(configTable.getValue())) {
            return 0;
        }

        // 尝试转化减免次数，如果失败则默认减免次数为0
        int reductionNumber = 0;
        try {
            reductionNumber = Integer.parseInt(configTable.getValue());
        } catch (NumberFormatException e) {
            // 忽略异常，使用默认值0
        }
        return reductionNumber;
    }

    private int getMonthNumber(Long cId) {
        // 计算本月的出金次数
        Date startDate = DateUtil.parseMonth();
        Integer count = financeWithdrawMapper.getCountByDateAndCId(startDate, DateUtil.operationMoth(startDate, 1),
                cId, 1);
        count = (count == null) ? 0 : count;
       /* Integer agentCount = financeAgentWithdrawMapper.getCountByDateAndCId(startDate,
                DateUtil.operationMoth(startDate, 1), cId, 1);
        count = (agentCount == null) ? count : count + agentCount;*/
        return count;
    }

    private void calculateLimit(Long cId) throws Exception {
        // 获取次数数量限制
        SysConfigTable configTable = sysConfigService.getByCode(ConfigConstants.FINANCE_WITHDRAW_NUMBER_LIMIT);
        if (Strings.isNullOrEmpty(configTable.getValue())) {
            throw new ServiceException("calculate_number_limit_error");
        }
        int reductionNumber = 0;
        try {
            reductionNumber = Integer.parseInt(configTable.getValue());
        } catch (NumberFormatException e) {
            throw new ServiceException("calculate_number_limit_error");
        }

        // 计算出金次数
        Date startDate = DateUtil.parseDate(DateUtil.formatDate(new Date()));
        Integer count = financeWithdrawMapper.getCountByDateAndCId(startDate, DateUtil.addDate(startDate, 1),
                cId, null);
        count = (count == null) ? 0 : count;
        /*Integer agentCount = financeAgentWithdrawMapper.getCountByDateAndCId(startDate,
                DateUtil.operationMoth(startDate, 1), cId, null);
        count = (agentCount == null) ? count : count + agentCount;*/

        if(count >= reductionNumber){
            throw new ServiceException("calculate_number_limit_error");
        }
    }

    @Override
    public int getRemainingReductionNumber(Long cId) throws ServiceException {
        int withdrawFeeReductionNumber = customInfoService.getWithdrawFeeReduction(cId);

        int reductionNumber = getReductionNumber() - getMonthNumber(cId);

        if (reductionNumber < 0) {
            return withdrawFeeReductionNumber;
        } else {
            return reductionNumber + withdrawFeeReductionNumber;
        }
    }

    /**
     * 快速到账
     */
    @Override
    public void sendFastWithdraw(FinanceWithdrawApproveManagerEntity entity) throws Exception {
        if (PayConstants.MANAGER_COMPLETED_STATUS.equals(entity.getWithdrawStatus())) {
            FinanceWithdrawTable table = financeWithdrawRepository.getFirstById(entity.getId());
            if (exFastWithdraw(table)) {
                FinanceWithdrawUcardpayEntity ucardPayentity = new FinanceWithdrawUcardpayEntity();
                BeanUtils.copyProperties(table, ucardPayentity);
                ucardPayentity.setWithdrawInfoType(1);
                ucardPayentity.setAmount(table.getTransformAmount());
                ucardPayService.withdraw(ucardPayentity);
            }
        }
    }

    @Override
    public boolean exFastWithdraw(FinanceWithdrawTable table) throws ServiceException {

        if (table == null) {
            return false;
        }
        if (PayConstants.MANAGER_COMPLETED_STATUS.equals(table.getWithdrawStatus())) {
            return false;
        }
        SysRemitChannelTable channelTable =
                sysRemitChannelRepository.getFirstByCodeAndValidAndFastChannel(table.getPayType(), 1, 1);
        // 查询当天出金金额总数
        BigDecimal amount =
                financeWithdrawMapper.getWithdrawAmountThatDayByCustomIdAndPayType(table.getCustomId(),
                        table.getPayType());
        // 获取系统配置当日快速出金限制最大金额
        SysConfigTable configTable = sysConfigService.getByCode(PayConstants.UCARD_PAY_WITHDRAW_LIMIT_AMOUNT);
        if (StringUtils.isEmpty(configTable.getValue())) {
            log.error("系统未配置ucard当日快速出金限制最大金额");
            return false;
        }
        BigDecimal maxAmount = new BigDecimal(configTable.getValue());
        if (channelTable != null && table.getPayType().equals(PayConstants.UCARD_PAY_TYPE_REMIT)
                && amount.compareTo(maxAmount) <= 0) {
            return true;
        }
        return false;
    }

    @Override
    public boolean exFastWithdraw(Long id) throws ServiceException {
        FinanceWithdrawTable table = financeWithdrawRepository.getFirstById(id);
        if (table == null) {
            return false;
        }
        return exFastWithdraw(table);
    }

    @Override
    public boolean exVietnamFastWithdraw(FinanceWithdrawTable table) throws ServiceException {

        if (table == null) {
            return false;
        }
        if (!PayConstants.PASSED_STATUS.equals(table.getBackstageStatus())) {
            return false;
        }
        if (!PayConstants.SUBMIT_PROCESSING_STATUS.equals(table.getSubmitStatus())) {
            return false;
        }
        if (!"VN".equals(table.getCountry())) {
            return false;
        }
        if (table.getRemitChannelType().equals(PayConstants.CHANNEL_TYPE_DIGITAL_CURRENCY)) {
            return false;
        }
        SysRemitChannelTable channelTable =
                sysRemitChannelRepository.getFirstByCodeAndValidAndFastChannel(table.getPayType(), 1, 1);
        if (channelTable == null) {
            return false;
        }

        SysConfigTable configTable = sysConfigService.getByCode(PayConstants.VN_WITHDRAW_LIMIT_AMOUNT);
        if (table.getAmount().compareTo(new BigDecimal(configTable.getValue())) <= 0) {
            return true;
        }
        return false;
    }

    /**
     * 越南快速到账
     */
    @Override
    public void vietnamFastWithdraw(Long id) throws Exception {
        FinanceWithdrawTable table = financeWithdrawRepository.getFirstById(id);
        if (exVietnamFastWithdraw(table)) {
            table.setWithdrawStatus(PayConstants.MANAGER_COMPLETED_STATUS);
            table.setOperationType(PayConstants.OPERATION_TYPE_AUTOMATIC);
            table.setInfoStatus(PayConstants.PASSED_STATUS);
            financeWithdrawRepository.save(table);
            try {
                fastFinanceWithdraw(table);
            } catch (Exception e) {
                log.error("越南快速出金异常: serial:{}", table.getSerial(), e);
            }
        }
    }

    @Override
    public FinanceWithdrawTable getByChannelSerial(String channelSerial) throws ServiceException {
        FinanceWithdrawTable table = financeWithdrawRepository.getFirstByChannelSerial(channelSerial);
        if (table == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        return table;
    }

}
