package org.dromara.payment.bill.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.common.core.constant.Constants;
import org.dromara.common.core.constant.GlobalConstants;
import org.dromara.common.core.enums.BusRole;
import org.dromara.common.core.enums.LoginType;
import org.dromara.common.core.enums.SmsType;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.exception.base.BaseException;
import org.dromara.common.core.exception.user.CaptchaExpireException;
import org.dromara.common.core.exception.user.UserException;
import org.dromara.common.core.service.BaseService;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.MessageUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.excel.core.DefaultExcelResult;
import org.dromara.common.excel.core.ExcelResult;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.payment.bill.domain.MerBill;
import org.dromara.payment.bill.domain.MerBillDetail;
import org.dromara.payment.bill.domain.bo.AddBillBo;
import org.dromara.payment.bill.domain.bo.MerBillBo;
import org.dromara.payment.bill.domain.bo.MerBillDetailBo;
import org.dromara.payment.bill.domain.vo.MerBillDetailVo;
import org.dromara.payment.bill.domain.vo.MerBillVo;
import org.dromara.payment.bill.mapper.MerBillDetailMapper;
import org.dromara.payment.bill.mapper.MerBillMapper;
import org.dromara.payment.bill.service.IMerBillDetailService;
import org.dromara.payment.bill.service.IMerBillService;
import org.dromara.payment.channel.domain.BusChannel;
import org.dromara.payment.channel.domain.BusChannelAccount;
import org.dromara.payment.channel.domain.BusChannelFlows;
import org.dromara.payment.channel.domain.BusChannelProduct;
import org.dromara.payment.channel.mapper.BusChannelAccountMapper;
import org.dromara.payment.channel.mapper.BusChannelFlowsMapper;
import org.dromara.payment.channel.mapper.BusChannelMapper;
import org.dromara.payment.channel.mapper.BusChannelProductMapper;
import org.dromara.payment.channel.service.IBusChannelAccountService;
import org.dromara.payment.common.domain.BusAccounts;
import org.dromara.payment.common.domain.BusOperLog;
import org.dromara.payment.common.domain.TranLog;
import org.dromara.payment.common.domain.vo.BusAccountsVo;
import org.dromara.payment.common.domain.vo.TranLogVo;
import org.dromara.payment.common.mapper.BusAccountsMapper;
import org.dromara.payment.common.mapper.BusOperLogMapper;
import org.dromara.payment.common.mapper.TranLogMapper;
import org.dromara.payment.enums.BusLogType;
import org.dromara.payment.merchant.domain.*;
import org.dromara.payment.merchant.domain.bo.BusMerchantBo;
import org.dromara.payment.merchant.domain.vo.BusMerchantAccountVo;
import org.dromara.payment.merchant.domain.vo.BusMerchantVo;
import org.dromara.payment.merchant.domain.vo.BusOperAndAgentAndMer;
import org.dromara.payment.merchant.mapper.*;
import org.dromara.payment.merchant.service.IBusMerchantAccountService;
import org.dromara.payment.operator.domain.BusOperator;
import org.dromara.payment.operator.domain.BusOperatorAccount;
import org.dromara.payment.operator.domain.BusOperatorFlows;
import org.dromara.payment.operator.domain.BusOperatorProduct;
import org.dromara.payment.operator.domain.vo.BusOperatorAccountVo;
import org.dromara.payment.operator.domain.vo.BusOperatorVo;
import org.dromara.payment.operator.mapper.*;
import org.dromara.payment.operator.service.IBusOperatorAccountService;
import org.dromara.payment.properties.PayPasswordProperties;
import org.dromara.payment.sys.domain.*;
import org.dromara.payment.sys.domain.vo.SysSydVo;
import org.dromara.payment.sys.mapper.*;
import org.dromara.payment.sys.service.ISysSydAccountService;
import org.dromara.payment.task.domain.MerTask;
import org.dromara.payment.task.domain.MerTaskEnroll;
import org.dromara.payment.task.domain.vo.MerTaskVo;
import org.dromara.payment.task.mapper.MerTaskEnrollMapper;
import org.dromara.payment.task.mapper.MerTaskMapper;
import org.dromara.payment.thirdPlatform.base.domain.SysThirdPlatform;
import org.dromara.payment.thirdPlatform.base.mapper.SysThirdPlatformMapper;
import org.dromara.payment.thirdPlatform.xinyujian.service.IXyjService;
import org.dromara.payment.util.MoneyUtils;
import org.dromara.payment.worker.domain.UserWorker;
import org.dromara.payment.worker.domain.UserWorkerAccount;
import org.dromara.payment.worker.domain.bo.UserWorkerAccountBo;
import org.dromara.payment.worker.domain.vo.UserWorkerVo;
import org.dromara.payment.worker.mapper.UserWorkerAccountMapper;
import org.dromara.payment.worker.mapper.UserWorkerMapper;
import org.dromara.payment.worker.service.IIdCardAndOtherService;
import org.dromara.payment.worker.service.IUserWorkerAccountService;
import org.dromara.settlement.api.RemoteAccountService;
import org.dromara.settlement.api.domain.Account;
import org.dromara.settlement.api.domain.Result;
import org.dromara.settlement.api.domain.TransactionLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.time.Duration;
import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 * 账单Service业务层处理
 *
 * @author LionLi
 * @date 2024-04-08
 */
@RequiredArgsConstructor
@Slf4j
@Service
public class MerBillServiceImpl extends BaseService implements IMerBillService {

    private final MerBillMapper baseMapper;

    private final SysSydMapper sydMapper;

    private final MerTaskMapper taskMapper;

    private final BusAccountsMapper accountsMapper;

    private final BusOperatorMapper operatorMapper;

    private final BusOperatorFlowsMapper operatorFlowsMapper;

    private final MerBillDetailMapper billDetailMapper;

    private final MerTaskEnrollMapper taskEnrollMapper;

    private final BusMerchantMapper merchantMapper;

    private final BusMerchantConfigMapper merchantConfigMapper;

    private final BusMerchantFlowsMapper merchantFlowsMapper;

    private final SysSydFlowsMapper sydFlowsMapper;

    private final UserWorkerMapper userWorkerMapper;

    private final BusMerchantMapper  busMerchantMapper;

    private final UserWorkerAccountMapper workerAccountDao;//自雇者账户dao

    private final IUserWorkerAccountService  userWorkerAccountService; //自雇者账户服务

    private final BusMerchantAccountMapper merchantAccountMapper;

    private final IBusMerchantAccountService merchantAccountService;

    private final SysSydAccountMapper sydAccountDao;//结算中心账户dao

    private final ISysSydAccountService sydAccountService;

    private final SysSydConfigMapper sydConfigMapper;

    private final BusChannelMapper channelMapper;

    private final BusChannelProductMapper channelProductMapper;

    private final BusOperatorProductMapper operatorProductMapper;

    private final BusOperatorAccountMapper operatorAccountMapper;

    private final IBusOperatorAccountService operatorAccountService;

    private final BusChannelAccountMapper channelAccountMapper;

    private final IBusChannelAccountService channelAccountService;

    private final BusChannelFlowsMapper channelFlowsMapper;

    private final BusOperLogMapper operLogMapper;

    private final BusMerchantProductMapper busMerchantProductMapper;

    private final TranLogMapper tranLogDao;//交易日志dao

    private final IMerBillDetailService billDetailService;

    private final ReProductInvoiceMapper reProductInvoiceMapper;

    private final MerBillDetailMapper  merBillDetailMapper;
    @Resource
    private UserWorkerAccountMapper userWorkerAccountMapper;

    @Resource(name="tencentIdCardAndOtherServiceImpl")
    public IIdCardAndOtherService tencentIdCardAndOtherService;

    @Resource
    private SysSydProductMapper  sysSydProductMapper;


    @DubboReference
    private RemoteAccountService accountService;//银行账户业务

    @Autowired
    private PayPasswordProperties payPasswordProperties;

    @Autowired
    private IXyjService xyjService;

    @Autowired
    private SysThirdPlatformMapper sysThirdPlatformMapper;
    /**
     * 查询账单
     */
    @Override
    public MerBillVo queryById(Long id){
        MerBillBo where = new MerBillBo();
        where.setId(id);
        List<MerBillVo> details = baseMapper.queryList(buildQueryWrapper(where));
        MerBillVo detail = null;
        if (details.size() > 0){
            detail = details.get(0);
            detail.setLogs(operLogMapper.selectVoList(new LambdaQueryWrapper<BusOperLog>().eq(BusOperLog::getBusId,id).eq(BusOperLog::getBusType, BusLogType.BILL.getId())));
        }
        return detail;
    }


    /**
     * 查询账单
     */
    @Override
    public MerBillVo queryByNo(String no){
        MerBillBo where = new MerBillBo();
        where.setNo(no);
        List<MerBillVo> details = baseMapper.queryList(buildQueryWrapper(where));
        MerBillVo detail = null;
        if (details.size() > 0){
            detail = details.get(0);
            detail.setLogs(operLogMapper.selectVoList(new LambdaQueryWrapper<BusOperLog>().eq(BusOperLog::getBusId,detail.getId()).eq(BusOperLog::getBusType, BusLogType.BILL.getId())));
        }
        return detail;
    }

    /**
     * 查询账单列表
     */
    @Override
    public TableDataInfo<MerBillVo> queryPageList(MerBillBo bo, PageQuery pageQuery) {
        QueryWrapper<MerBill> lqw = buildQueryWrapper(bo);
        Page<MerBillVo> result = baseMapper.queryPageList(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询账单列表
     */
    @Override
    public List<MerBillVo> queryList(MerBillBo bo) {
        QueryWrapper<MerBill> lqw = buildQueryWrapper(bo);
        return baseMapper.queryList(lqw);
    }

    @Override
    public Integer queryListCount(MerBillBo bo) {
        QueryWrapper<MerBill> lqw = buildQueryWrapper(bo);
        return baseMapper.queryListCount(lqw);
    }

    private QueryWrapper<MerBill> buildQueryWrapper(MerBillBo bo) {
        Map<String, Object> params = bo.getParams();
        QueryWrapper<MerBill> lqw = new QueryWrapper<>();
        lqw.eq(bo.getId() != null, "t.id", bo.getId());
        lqw.eq(bo.getTaskId() != null, "t.task_id", bo.getTaskId());
        lqw.eq(StringUtils.isNotBlank(bo.getTaskNo()), "t.task_no", bo.getTaskNo());
        lqw.eq(StringUtils.isNotBlank(bo.getNo()), "t.no", bo.getNo());
        lqw.eq(bo.getServiceChargeType() != null, "t.service_charge_type", bo.getServiceChargeType());
        lqw.eq(bo.getServiceChargeRate() != null, "t.service_charge_rate", bo.getServiceChargeRate());
        lqw.eq(bo.getMoney() != null, "t.money", bo.getMoney());
        lqw.eq(bo.getServiceChargeAmount() != null, "t.service_charge_amount", bo.getServiceChargeAmount());
        lqw.eq(bo.getAmountEnt() != null, "t.amount_ent", bo.getAmountEnt());
        lqw.eq(bo.getStatus() != null, "t.status", bo.getStatus());
        lqw.eq(bo.getPayStatus() != null, "t.pay_status", bo.getPayStatus());
        lqw.eq(bo.getPayTime() != null, "t.pay_time", bo.getPayTime());
        lqw.eq(bo.getGiveUpTime() != null, "t.give_up_time", bo.getGiveUpTime());
        lqw.eq(StringUtils.isNotBlank(bo.getGiveUpBy()), "t.give_up_by", bo.getGiveUpBy());
        lqw.eq(bo.getAddTime() != null, "t.add_time", bo.getAddTime());
        lqw.eq(StringUtils.isNotBlank(bo.getAddBy()), "t.add_by", bo.getAddBy());
        lqw.eq(bo.getVerifyStatus() != null, "t.verify_status", bo.getVerifyStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getVerifyBy()), "t.verify_by", bo.getVerifyBy());
        lqw.eq(bo.getVerifyTime() != null, "t.verify_time", bo.getVerifyTime());
        lqw.eq(StringUtils.isNotBlank(bo.getVerifyReason()), "t.verify_reason", bo.getVerifyReason());
        lqw.eq(StringUtils.isNotBlank(bo.getPassage()), "t.passage", bo.getPassage());
        lqw.eq(bo.getDetailCount() != null, "t.detailCount", bo.getDetailCount());
        lqw.eq(bo.getIsAgencyFee() != null, "t.is_agency_fee", bo.getIsAgencyFee());
        lqw.eq(StringUtils.isNotBlank(bo.getWssph()), "t.wssph", bo.getWssph());
        lqw.eq(StringUtils.isNotBlank(bo.getWtdzgssph()), "t.wtdzgssph", bo.getWtdzgssph());
        lqw.eq(bo.getSphTime() != null, "t.sph_time", bo.getSphTime());
        lqw.eq(StringUtils.isNotBlank(bo.getSphBy()), "t.sph_by", bo.getSphBy());
        lqw.eq(StringUtils.isNotBlank(bo.getOutNo()), "t.out_no", bo.getOutNo());
        lqw.eq(bo.getIsOut() != null, "t.is_out", bo.getIsOut());
        lqw.eq(bo.getSydId() != null, "t.syd_id", bo.getSydId());
        lqw.eq(StringUtils.isNotBlank(bo.getSydNo()), "t.syd_no", bo.getSydNo());
        lqw.eq(StringUtils.isNotBlank(bo.getOpNo()), "t.op_no", bo.getOpNo());
        lqw.eq(bo.getOpId() != null, "t.op_id", bo.getOpId());
        lqw.eq(bo.getChannelId() != null, "t.channel_id", bo.getChannelId());
        lqw.eq(StringUtils.isNotBlank(bo.getChannelNo()), "t.channel_no", bo.getChannelNo());
        lqw.eq(StringUtils.isNotBlank(bo.getChannelCode()), "t.channel_code", bo.getChannelCode());
        lqw.eq(bo.getMerId() != null, "t.mer_id", bo.getMerId());
        lqw.eq(StringUtils.isNotBlank(bo.getMerNo()), "t.mer_no", bo.getMerNo());
        lqw.eq(StringUtils.isNotBlank(bo.getProNo()), "t.pro_no", bo.getProNo());
        lqw.eq(bo.getProId() != null, "t.pro_id", bo.getProId());
        lqw.eq(bo.getSydVerifyStatus() != null, "t.syd_verify_status", bo.getSydVerifyStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getSydVerifyBy()), "t.syd_verify_by", bo.getSydVerifyBy());
        lqw.eq(bo.getSydVerifyTime() != null, "t.syd_verify_time", bo.getSydVerifyTime());
        lqw.eq(StringUtils.isNotBlank(bo.getSydVerifyReason()), "t.syd_verify_reason", bo.getSydVerifyReason());
        lqw.eq(bo.getIsInvoice() != null, "t.is_invoice", bo.getIsInvoice());
        lqw.eq(bo.getBusType() != null, "t.bus_type", bo.getBusType());
        lqw.eq(bo.getSettlementStyle() != null, "t.settlement_style", bo.getSettlementStyle());
        lqw.eq(bo.getMaxMonth() != null, "t.max_month", bo.getMaxMonth());
        lqw.eq(bo.getInvoiceType() != null, "t.invoice_type", bo.getInvoiceType());
        lqw.eq(bo.getChargeMode() != null, "t.charge_mode", bo.getChargeMode());
        if(StringUtils.isNotBlank(bo.getParams().get("begin_time")) && StringUtils.isNotBlank(bo.getParams().get("end_time"))){
            lqw.between("t.add_time",bo.getParams().get("begin_time")+" 00:00:00",bo.getParams().get("end_time")+" 23:59:59");
        }
        if(StringUtils.isNotBlank(bo.getParams().get("syd_name"))){
            lqw.like("t2.gsmc",bo.getParams().get("syd_name"));
        }
        if(StringUtils.isNotBlank(bo.getParams().get("mer_name"))){
            lqw.like("t1.name",bo.getParams().get("mer_name"));
        }
        if(StringUtils.isNotBlank(params.get("channel_no"))){
            lqw.likeRight("t.channel_no",params.get("channel_no"));
        }
        if(StringUtils.isNotBlank(bo.getParams().get("bill_status"))){
            Integer billStatus = Integer.parseInt(bo.getParams().get("bill_status").toString());
            if(billStatus <= 5){
                lqw.eq("t.status",billStatus);
            }else {
                lqw.eq("t.status",3);
                if(billStatus == 6){//发放成功
                    lqw.eq("t.pay_status",1);
                }else if(billStatus == 7){//发放失败
                    lqw.eq("t.pay_status",2);
                }else if(billStatus == 8){//发放部分成功
                    lqw.eq("t.pay_status",3);
                }
            }
        }
        lqw.orderByDesc("t.add_time");
        return lqw;
    }

    /**
     * 生成代发明细项目子编号
     * @param retry 当前重试次数
     * @param maxRetry 最大重试次数
     * @param merNo 商户编号（A10049-B10070-M11312，运营商编号-代理商编号-商户编号）
     * @return
     */
    public String genBillNo(int retry,int maxRetry,String merNo){
        String no = getBillNo(merNo,DateUtils.dateTimeNow(DateUtils.YYYYMMDD)+"-"+RandomUtil.randomNumbers(7));
        LambdaQueryWrapper<MerBill> lqw = Wrappers.lambdaQuery();
        lqw.eq(MerBill::getNo,no);
        MerBill exist = baseMapper.selectOne(lqw);
        if(exist != null){
            if(retry > maxRetry){
                throw new ServiceException("代发批次号生成出错");
            }else {
                no = genBillNo(retry + 1,maxRetry,merNo);
            }
        }
        return no;
    }

    @Override
    public ExcelResult<MerBillDetailBo> qdPaymentImport(AddBillBo bo) {
        return valiPaymentImport(bo);
    }

    @Override
    public ExcelResult<MerBillDetailBo> onlinePaymentImport(AddBillBo bo) {
        String curDate = DateUtils.dateTimeNow(DateUtils.YYYYMMDD);
        if(!bo.getNo().startsWith(curDate)){
            throw new ServiceException("批次号格式不正确！");
        }

        if(bo.getDetails() == null){
            throw new ServiceException("请录入打款信息");
        }

        MerBill exist = baseMapper.selectOne(new LambdaQueryWrapper<MerBill>().eq(MerBill::getNo,getBillNo(bo.getMerNo(),bo.getNo())));
        if(exist != null){
            throw new ServiceException("批次号重复，请勿重复提交！");
        }
        return valiPaymentImport(bo);
    }

    public ExcelResult<MerBillDetailBo> valiPaymentImport(AddBillBo bo) {
        BusMerchantConfig merchantConfig = merchantConfigMapper.selectOne(new LambdaQueryWrapper<BusMerchantConfig>().eq(BusMerchantConfig::getMerId,bo.getMerId()));
        if(merchantConfig == null){
            merchantConfig = new BusMerchantConfig(0,1,1000l,10000000l,120000000l);
            merchantConfig.setIsNothing(0);
        }
        DefaultExcelResult<MerBillDetailBo> rtn = new DefaultExcelResult<>();
        rtn.setAllRecords(bo.getDetails().size());
        List<String> cardIds = bo.getDetails().stream().map(MerBillDetailBo::getCardId).distinct().collect(Collectors.toList());
        List<UserWorkerVo> workers = userWorkerMapper.selectByCardId(cardIds,bo.getPassage(),bo.getSydId(),bo.getMerId(),bo.getBusType());
        List<MerBillDetail> cntBillAmountList = this.merBillDetailMapper.selectAmountByCards(cardIds,bo.getProId().intValue());
        SysSydProduct   sysSydProduct = this.sysSydProductMapper.selectById(bo.getProId());
        if(sysSydProduct == null){
            this.invalidationParamsException("产品参数无效");
        }
        //key:身份证号 value:自雇者
        Map<String,UserWorkerVo> cardIdMap = workers.stream().collect(Collectors.toMap(UserWorkerVo::getCardIdNoHide,userWorkerVo -> userWorkerVo));

        Map<String,MerBillDetail> cardIdAmoutMap = cntBillAmountList.stream().collect(Collectors.toMap(MerBillDetail::getCardId,merBillDetail -> merBillDetail));

        for (MerBillDetailBo detail:
            bo.getDetails()) {

            if(!IdcardUtil.isValidCard(detail.getCardId())){
                detail.setErrorMsg("身份证号无效！");
                rtn.getList().add(detail);
                rtn.getErrorList().add("身份证号无效！");
                continue;
            }


            if(!cardIdMap.containsKey(detail.getCardId())){

                if(merchantConfig.getIsNothing() != null && 1 == merchantConfig.getIsNothing()){


                    //不认证，不签约
                    try{
                        this.tencentIdCardAndOtherService.cardId2(detail.getWorkerName(),detail.getCardId(),bo.getDomain());
                        long id = IdUtil.getSnowflakeNextId();
                        UserWorker userWorkerBo = new UserWorker();
                        userWorkerBo.setId(id);
                        detail.setWorkerId(id);
                        userWorkerBo.setName(detail.getWorkerName());
                        userWorkerBo.setCardId(detail.getCardId());
                        userWorkerBo.setCreateBy(LoginHelper.getUserId());
                        userWorkerBo.setStatus(2);
                        userWorkerBo.setCreateTime(new Date());
                        this.userWorkerMapper.insert(userWorkerBo);
                        detail.setWorkerId(userWorkerBo.getId());
                        UserWorkerVo vo = BeanUtil.copyProperties(userWorkerBo,UserWorkerVo.class);
                        vo.setIsAuthentication(0L);
                        vo.setIsAuth(0L);
                        vo.setIsSign(0L);
                        cardIdMap.put(detail.getCardId(),vo);

                    }catch(BaseException e ){
                        rtn.getList().add(detail);
                        detail.setErrorMsg("身份证校验不通过");
                        rtn.getErrorList().add("身份证校验不通过");
                        continue;
                    }catch(Exception e){
                        e.printStackTrace();
                        rtn.getList().add(detail);
                        detail.setErrorMsg("身份证校验失败");
                        rtn.getErrorList().add("身份证校验失败");
                        continue;
                    }



                }else{
                    detail.setErrorMsg("客户信息不存在！");
                    rtn.getList().add(detail);
                    rtn.getErrorList().add("客户信息不存在！");
                    continue;
                }

            }else{
                detail.setWorkerId(cardIdMap.get(detail.getCardId()).getId());
            }



            if(!cardIdMap.get(detail.getCardId()).getName().equals(detail.getWorkerName())){
                rtn.getList().add(detail);
                detail.setErrorMsg("名字、身份证号不匹配！");
                rtn.getErrorList().add("名字、身份证号不匹配！");
                continue;
            }




            if(cardIdAmoutMap.get(detail.getCardId()) !=null && !sysSydProduct.getMaxMonth().equals(0L)){

                if((cardIdAmoutMap.get(detail.getCardId()).getAmount() + MoneyUtils.getMoneyFen(detail.getMoneyDecimal())) > sysSydProduct.getMaxMonth()){
                    detail.setErrorMsg("每月代发金额不能大于"+MoneyUtils.getMoneyFormatYuan(sysSydProduct.getMaxMonth())+"元！");
                    rtn.getList().add(detail);
                    rtn.getErrorList().add("单笔代发交易金额不能低于"+MoneyUtils.getMoneyFormatYuan(sysSydProduct.getMaxMonth())+"元！");
                    continue;
                }
            }



            if(MoneyUtils.getMoneyFen(detail.getMoneyDecimal()) < merchantConfig.getMinMoney()){
                detail.setErrorMsg("单笔代发交易金额不能低于"+MoneyUtils.getMoneyFormatYuan(merchantConfig.getMinMoney())+"元！");
                rtn.getList().add(detail);
                rtn.getErrorList().add("单笔代发交易金额不能低于"+MoneyUtils.getMoneyFormatYuan(merchantConfig.getMinMoney())+"元！");
                continue;
            }
            if(MoneyUtils.getMoneyFen(detail.getMoneyDecimal()) > merchantConfig.getMaxMoney()){
                detail.setErrorMsg("单笔代发交易金额不能高于"+MoneyUtils.getMoneyFormatYuan(merchantConfig.getMaxMoney())+"元！");
                rtn.getList().add(detail);
                rtn.getErrorList().add("单笔代发交易金额不能高于"+MoneyUtils.getMoneyFormatYuan(merchantConfig.getMaxMoney())+"元！");
                continue;
            }
            if(StringUtils.isNotBlank(cardIdMap.get(detail.getCardId()).getMoneyYearDate())){
                String curYear = DateUtils.dateTimeNow(DateUtils.YYYY);
                if(curYear.equals(cardIdMap.get(detail.getCardId()).getMoneyYearDate()) && cardIdMap.get(detail.getCardId()).getMoneyYear() + MoneyUtils.getMoneyFen(detail.getMoneyDecimal()) > merchantConfig.getMaxMoneyYear()){
                    detail.setErrorMsg("年代发交易金额不能高于"+MoneyUtils.getMoneyFormatYuan(merchantConfig.getMaxMoneyYear())+"元！");

                    rtn.getList().add(detail);
                    rtn.getErrorList().add("年代发交易金额不能高于"+MoneyUtils.getMoneyFormatYuan(merchantConfig.getMaxMoneyYear())+"元！");
                    continue;
                }
            }
            if(cardIdMap.get(detail.getCardId()).getIsAuth() == 0){
                if(merchantConfig.getIsNothing() != null && 1 == merchantConfig.getIsNothing()){

                }else{
                    detail.setErrorMsg("该会员未实名认证！");
                    rtn.getList().add(detail);
                    rtn.getErrorList().add("该会员未实名认证！");
                    continue;
                }

            }
            if(cardIdMap.get(detail.getCardId()).getIsAuthentication() == 0){
                if(merchantConfig.getIsNothing() != null && 1 == merchantConfig.getIsNothing()){
                    //未绑定银行卡
                    if(StringUtils.isEmpty(detail.getBankCard())){
                        detail.setErrorMsg("银行卡不能为空");
                        rtn.getErrorList().add("银行卡不能为空");
                        rtn.getList().add(detail);
                        continue;
                    }

                    if(StringUtils.isEmpty(detail.getBankType())){
                        rtn.getList().add(detail);
                        detail.setErrorMsg("所属银行不能为空");
                        rtn.getErrorList().add("所属银行不能为空");
                        continue;
                    }
                    if(addUserWorkerAccount(bo, detail, cardIdMap, rtn)) continue;

                }else{
                    detail.setErrorMsg("该会员未绑定银行卡,会员号:"+cardIdMap.get(detail.getCardId()).getId());
                    rtn.getList().add(detail);
                    rtn.getErrorList().add("该会员未绑定银行卡,会员号:"+cardIdMap.get(detail.getCardId()).getId());
                    continue;
                }

            }else{
                if(merchantConfig.getIsNothing() != null && 1 == merchantConfig.getIsNothing()){
                    //已绑定银行卡
                    String bankCard = cardIdMap.get(detail.getCardId()).getBankCard();
                    if(StringUtils.isNotEmpty(detail.getBankCard()) && !detail.getBankCard().equals(bankCard)){
                        if(StringUtils.isEmpty(detail.getBankType())){
                            rtn.getList().add(detail);
                            detail.setErrorMsg("所属银行不能为空");
                            rtn.getErrorList().add("所属银行不能为空");
                            continue;
                        }
                        if(addUserWorkerAccount(bo, detail, cardIdMap, rtn)) continue;

                    }
                }


            }

            if(merchantConfig.getValiWorker() == 1 && cardIdMap.get(detail.getCardId()).getIsSign() == 0){
                if(merchantConfig.getIsNothing() != null && 1 == merchantConfig.getIsNothing()){

                }else{
                    detail.setErrorMsg("该会员未签约！");
                    rtn.getList().add(detail);
                    rtn.getErrorList().add("该会员未签约！");
                    continue;
                }

            }
        }
        if(rtn.getErrorList().size() == 0) {
            for (MerBillDetailBo detail:
                bo.getDetails()) {
                detail.setWorkerId(cardIdMap.get(detail.getCardId()).getId());
                detail.setWorkerPhone(cardIdMap.get(detail.getCardId()).getPhoneNoHide());
                detail.setBankType(cardIdMap.get(detail.getCardId()).getBankType());
                detail.setBankCard(cardIdMap.get(detail.getCardId()).getBankCard());
                detail.setBankAccId(cardIdMap.get(detail.getCardId()).getBankAccId());
                detail.setMoney(MoneyUtils.getMoneyFen(detail.getMoneyDecimal()));
                if(bo.getChargeMode() == 1){//个人应得计费
                    if(bo.getServiceChargeType() == 1){//用工企业承担
                        //企业支付
                        BigDecimal qyzf = detail.getMoneyDecimal().multiply(new BigDecimal("1").add(getServiceChargeRate(bo.getServiceChargeRate()))).setScale(2, RoundingMode.HALF_UP);
                        //实际到手金额
                        detail.setAmount(detail.getMoney());
                        detail.setQyzf(MoneyUtils.getMoneyFen(qyzf));
                        //服务费
                        detail.setServiceChargeMoney(MoneyUtils.getMoneyFen(qyzf)-detail.getAmount());
                    }else if(bo.getServiceChargeType() == 2) {//自由职业者承担
                        //个人实得
                        BigDecimal grsd = detail.getMoneyDecimal().multiply(new BigDecimal("1").subtract(getServiceChargeRate(bo.getServiceChargeRate()))).setScale(2, RoundingMode.HALF_UP);
                        //实际到手金额
                        detail.setAmount(MoneyUtils.getMoneyFen(grsd));
                        detail.setQyzf(MoneyUtils.getMoneyFen(detail.getMoneyDecimal()));
                        //服务费
                        detail.setServiceChargeMoney(MoneyUtils.getMoneyFen(detail.getMoneyDecimal())-detail.getAmount());
                    }
                }else if(bo.getChargeMode() == 2){//开票金额计费
                    if(bo.getServiceChargeType() == 1){//用工企业承担
                        //企业支付
                        BigDecimal qyzf = detail.getMoneyDecimal().divide(new BigDecimal("1").subtract(getServiceChargeRate(bo.getServiceChargeRate())),2, RoundingMode.HALF_UP).setScale(2, RoundingMode.HALF_UP);
                        //实际到手金额
                        detail.setAmount(detail.getMoney());
                        detail.setQyzf(MoneyUtils.getMoneyFen(qyzf));
                        //服务费
                        detail.setServiceChargeMoney(MoneyUtils.getMoneyFen(qyzf)-detail.getAmount());
                    }else if(bo.getServiceChargeType() == 2) {//自由职业者承担
                        //个人实得
                        BigDecimal grsd = detail.getMoneyDecimal().multiply(new BigDecimal("1").subtract(getServiceChargeRate(bo.getServiceChargeRate()))).setScale(2, RoundingMode.HALF_UP);
                        //实际到手金额
                        detail.setAmount(MoneyUtils.getMoneyFen(grsd));
                        detail.setQyzf(MoneyUtils.getMoneyFen(detail.getMoneyDecimal()));
                        //服务费
                        detail.setServiceChargeMoney(MoneyUtils.getMoneyFen(detail.getMoneyDecimal())-detail.getAmount());
                    }
                }
                detail.setBillNo(bo.getNo());
                rtn.getList().add(detail);
            }
        }
        return rtn;
    }

    private boolean addUserWorkerAccount(AddBillBo bo, MerBillDetailBo detail, Map<String, UserWorkerVo> cardIdMap, DefaultExcelResult<MerBillDetailBo> rtn) {
        try{
            this.tencentIdCardAndOtherService.bankCard3(detail.getBankCard(), detail.getWorkerName(), detail.getCardId(), bo.getDomain());
//                        Account bankAcc = new Account();
//                        bankAcc.setType((short)2);//2:真实个人账户
//                        bankAcc.setBankCard(detail.getBankCard());
//                        bankAcc.setBankType(detail.getBankType());
//                        bankAcc.setUnitId(0L);
//                        bankAcc.setName(detail.getWorkerName());
//                        Result<Account> result = this.accountService.addAccount(bankAcc);
//                        Integer accountId = result.getRtnData().getId();
//                        if(accountId == null){
//                            this.invalidationParamsException("创建账号失败!");
//                        }

            //添加银行卡
            UserWorkerAccountBo uwab = new UserWorkerAccountBo();
            uwab.setWorkId(detail.getWorkerId());
//                        uwab.setAccId(Long.valueOf(accountId));
            uwab.setBankCard(detail.getBankCard());
            uwab.setPassage(detail.getPassage());
            uwab.setBankType(detail.getBankType());
            uwab.setCreateTime(new Date());
            uwab.setCreateBy(LoginHelper.getUserId());
            uwab.setIsDefault(1L);
            UserWorkerAccount uwa =  this.userWorkerAccountService.rePayMdyWorkerBank(uwab);
            if(uwa == null){
                this.invalidationParamsException("创建会员账户失败");
            }
            cardIdMap.get(detail.getCardId()).setBankCard(detail.getBankCard());
            cardIdMap.get(detail.getCardId()).setBankType(detail.getBankType());
            cardIdMap.get(detail.getCardId()).setBankAccId(uwa.getAccId().intValue());
            cardIdMap.get(detail.getCardId()).setIsAuthentication(1L);

        }catch(BaseException e ){
            e.printStackTrace();
            rtn.getList().add(detail);
            detail.setErrorMsg("银行卡校验不通过"+e.getMessage());
            rtn.getErrorList().add("银行卡校验不通过"+e.getMessage());
            return true;
////                        this.invalidationParamsException("银行卡校验不通过,"+e.getMessage());
////                        throw e;
        }catch(Exception e){
            e.printStackTrace();
            rtn.getList().add(detail);
            detail.setErrorMsg("银行卡校验失败,-"+e.getMessage());
            rtn.getErrorList().add("银行卡校验失败,-"+e.getMessage());
            return true;
        }
        return false;
    }

    /**
     * 获取服务费率(除100后的)
     * @author 张涛
     * @date 2021年12月1日
     * @param rate 服务费率
     * @return
     */
    private BigDecimal getServiceChargeRate(BigDecimal rate) {
        String str = rate.doubleValue()+"";
        int retainNum = 2;
        if (str.indexOf(".") != -1) {
            String scaleStr = str.substring(str.indexOf(".")+1);
            if(Long.parseLong(scaleStr) > 0) {
                retainNum = retainNum + scaleStr.length();
            }
        }
        return rate.divide(new BigDecimal(100), retainNum,RoundingMode.HALF_UP);
    }

    /**
     * 获取账单批次号
     * @param merNo 商户编号（A10049-B10070-M11312，运营商编号-代理商编号-商户编号）
     * @param billNo 填写的批次号
     * @return
     */
    private String getBillNo(String merNo,String billNo){
        String[] mns = merNo.split("-");
        return "P"+mns[mns.length -1]+billNo;
    }

    /**
     * 新增账单
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(AddBillBo bo) {
//        MerBill add = MapstructUtils.convert(bo, MerBill.class);

        BusMerchantBo mer = new BusMerchantBo();
        mer.setNo(LoginHelper.getNo());
        BusOperAndAgentAndMer busOperAndAgentAndMer = this.busMerchantMapper.selOpAndAgentInfosByMerInfo(mer);

        if(busOperAndAgentAndMer == null){
            this.invalidationParamsException("非法请求");
        }
        QueryWrapper  qw = Wrappers.query();
        qw.eq("bus_type",bo.getBusType());
        qw.eq("pro_id",bo.getProId());
        qw.eq("syd_id",bo.getSydId());
        qw.eq("mer_id",bo.getMerId());
        qw.eq("pro_status",1);
        BusMerchantProduct  bmp = this.busMerchantProductMapper.selectOne(qw);

        if(bmp == null){
            this.invalidationParamsException("非法请求");
        }

        bo.setServiceChargeRate(bmp.getServiceCharge());

        bo.setChannelId(busOperAndAgentAndMer.getChannelId());
        bo.setChannelNo(busOperAndAgentAndMer.getChannelNo());
        bo.setOpId(busOperAndAgentAndMer.getOpId());
        bo.setOpNo(busOperAndAgentAndMer.getOpNo());

        MerBill add = BeanUtil.copyProperties(bo, MerBill.class);
        add.setVerifyStatus(1L);
        add.setMoney(0l);
        add.setServiceChargeAmount(0l);
        add.setAmountEnt(0l);
        add.setDetailCount(0l);
        for (MerBillDetailBo detail:
             bo.getDetails()) {
            add.setMoney(add.getMoney()+detail.getMoney());
            add.setServiceChargeAmount(add.getServiceChargeAmount()+detail.getServiceChargeMoney());
            add.setAmountEnt(add.getAmountEnt()+detail.getServiceChargeMoney()+detail.getAmount());
            add.setDetailCount(add.getDetailCount()+1);
        }
        validEntityBeforeSave(add);
        if(merchantAccountService.updateFrozen(add.getSydId(),add.getMerId(),add.getAmountEnt(),add.getPassage()) == 0){
            throw new ServiceException(add.getPassage()+"账户可用余额不足！");
        }
        if(StringUtils.isNotBlank(bo.getNo())) {
            add.setNo(getBillNo(bo.getMerNo(), bo.getNo()));
        }else{
            add.setNo(genBillNo(0,10,bo.getMerNo()));
        }
        add.setAddTime(new Date());
        SysSydConfig sydConfig = sydConfigMapper.selectOne(new LambdaQueryWrapper<SysSydConfig>().eq(SysSydConfig::getSydId,bo.getSydId()));
        if(sydConfig == null){
            sydConfig = new SysSydConfig(0);
        }
        add.setSydVerifyStatus(1);
        if(sydConfig.getAutoApprove() == 1){
            //服务商自动审批
            add.setStatus(1L);
            add.setSydVerifyStatus(3);
            add.setSydVerifyBy("自动审批");
            add.setSydVerifyTime(add.getAddTime());
        }
        boolean flag = baseMapper.insert(add) > 0;
        if (!flag) {
            throw new ServiceException("代发提交失败！");
        }
        //商户总费率
        BigDecimal sh_service_rate = getServiceChargeRate(bo.getServiceChargeRate());
        //服务商费率
        BigDecimal fws_service_rate = null;
        //运营商费率
        BigDecimal yys_service_rate = null;
        //孵化中心费率
        BigDecimal fhzx_service_rate = null;
        Long fhzx_id = null;
        //总监费率
        BigDecimal zj_service_rate = null;
        Long zj_id = null;
        //业务员费率
        BigDecimal ywy_service_rate = null;
        Long ywy_id = null;
        //查询代理商
        BusChannel channel = channelMapper.selectOne(new LambdaQueryWrapper<BusChannel>().eq(BusChannel::getId,bo.getChannelId()));
        //查询代理商产品
        BusChannelProduct channelProduct = channelProductMapper.selectOne(new LambdaQueryWrapper<BusChannelProduct>().eq(BusChannelProduct::getChannelId,bo.getChannelId()).eq(BusChannelProduct::getProStatus,1).eq(BusChannelProduct::getProId,bo.getProId()));
        //查询运营商产品
        BusOperatorProduct operatorProduct = operatorProductMapper.selectOne(new LambdaQueryWrapper<BusOperatorProduct>().eq(BusOperatorProduct::getOpId,bo.getOpId()).eq(BusOperatorProduct::getProStatus,1).eq(BusOperatorProduct::getProId,bo.getProId()));
        if(channel.getDwLevel() == 1){//1:孵化中心
            fhzx_service_rate = getServiceChargeRate(channelProduct.getServiceCharge());
            fhzx_id = channel.getId();
            yys_service_rate = getServiceChargeRate(channelProduct.getCostServiceCharge());
            fws_service_rate = getServiceChargeRate(operatorProduct.getCostServiceCharge());
        }else if(channel.getDwLevel() == 2){//2:总监
            zj_service_rate = getServiceChargeRate(channelProduct.getServiceCharge());
            zj_id = channel.getId();
            if(channel.getPId() != null && channel.getPId() > 0) {
                fhzx_service_rate = getServiceChargeRate(channelProduct.getCostServiceCharge());
                fhzx_id = channel.getPId();
            }
            yys_service_rate = getServiceChargeRate(operatorProduct.getServiceCharge());
            fws_service_rate = getServiceChargeRate(operatorProduct.getCostServiceCharge());
        }else if(channel.getDwLevel() == 3){//3:业务员
            ywy_service_rate = getServiceChargeRate(channelProduct.getServiceCharge());
            ywy_id = channel.getId();
            if(channel.getPId() != null && channel.getPId() > 0) {
                //上级代理商
                BusChannel upChannel = channelMapper.selectOne(new LambdaQueryWrapper<BusChannel>().eq(BusChannel::getId,channel.getPId()));
                if(upChannel.getDwLevel() == 2) {//2:总监
                    zj_service_rate = getServiceChargeRate(channelProduct.getCostServiceCharge());
                    zj_id = upChannel.getId();
                    if(upChannel.getPId() != null && upChannel.getPId() > 0) {
                        BusChannelProduct zjChannelProduct = channelProductMapper.selectOne(new LambdaQueryWrapper<BusChannelProduct>().eq(BusChannelProduct::getChannelId, channel.getPId()).eq(BusChannelProduct::getProStatus, 1).eq(BusChannelProduct::getProId,bo.getProId()));
                        if(zjChannelProduct != null){
                            fhzx_service_rate = getServiceChargeRate(zjChannelProduct.getCostServiceCharge());
                            fhzx_id = upChannel.getPId();
                        }

                    }
                }else if(upChannel.getDwLevel() == 1){//1:孵化中心
                    fhzx_service_rate = getServiceChargeRate(channelProduct.getCostServiceCharge());
                    fhzx_id = upChannel.getId();
                }
            }
            yys_service_rate = getServiceChargeRate(operatorProduct.getServiceCharge());
            fws_service_rate = getServiceChargeRate(operatorProduct.getCostServiceCharge());
        }
        List<MerBillDetail> details = new ArrayList<>();
        List<String> cnos = new ArrayList<>();//已存在的子项目编号列表
        MerTaskVo taskVo = taskMapper.selectVoById(bo.getTaskId());
        for (MerBillDetailBo detail:
            bo.getDetails()) {
            detail.setId(null);
            MerBillDetail d = MapstructUtils.convert(detail,MerBillDetail.class);
            d.setPassage(bo.getPassage());

            if(d.getWorkerEnrollId() != null && StringUtils.isBlank(d.getCno())){
                throw new ServiceException("项目子编码不能为空");
            }
            if(d.getWorkerEnrollId() == null){
                d.setCno(genBillDetailCNo(0,10,cnos));
                cnos.add(d.getCno());
                MerTaskEnroll enroll = new MerTaskEnroll(d.getCno(),taskVo.getNo(),taskVo.getClassify(),taskVo.getId(),d.getWorkerId(),3l,bo.getAddBy(),new Date());
                enroll.setCost(d.getMoney());
                taskEnrollMapper.insert(enroll);
                d.setWorkerEnrollId(enroll.getId());
            }
            String[] mns = bo.getMerNo().split("-");
            d.setBusNo("T"+mns[mns.length - 1]+IdUtil.getSnowflakeNextIdStr());
            d.setBillNo(add.getNo());
            d.setBillId(add.getId());
            d.setAddTime(add.getAddTime());
            d.setPassage(bo.getPassage());
            d.setTaskId(bo.getTaskId());
            d.setTaskNo(bo.getTaskNo());
            d.bind(bo);
            d.setBusType(bo.getBusType());
            d.setProNo(bo.getProNo());
            d.setChargeMode(bo.getChargeMode());
            //平台分润(元)=（运营商费率-服务商费率）*代发金额，四舍五入
            d.setPtServiceChargeMoney(MoneyUtils.getMoneyFen(yys_service_rate.subtract(fws_service_rate).multiply(MoneyUtils.getMoneyYuan(d.getMoney())).setScale(2, RoundingMode.HALF_UP)));
            log.info(d.getBusNo()+"平台费率计算："+yys_service_rate+","+fws_service_rate+","+MoneyUtils.getMoneyYuan(d.getMoney())+"結果:"+d.getPtServiceChargeMoney());
            //服务商分润(元)=商户总服务费-平台服务费-运营商总分润
            //服务商分润(元)=（服务商费率）*代发金额，四舍五入
            d.setSydServiceChargeMoney(MoneyUtils.getMoneyFen(fws_service_rate.multiply(MoneyUtils.getMoneyYuan(d.getMoney())).setScale(2, RoundingMode.HALF_UP)));
            log.info(d.getBusNo()+"服务商费率计算:"+fws_service_rate+",结果:"+d.getSydServiceChargeMoney());
//            d.setSydServiceChargeMoney(d.getServiceChargeMoney()-d.getPtServiceChargeMoney()-MoneyUtils.getMoneyFen(yyszServiceChargeMoney));
            //运营商总分润(元)=（商户总费率-运营商费率）*代发金额，向上取整
            //运营商总分润(元)=商户总服务费-平台服务费-服务商总分润，
//            BigDecimal yyszServiceChargeMoney = sh_service_rate.subtract(yys_service_rate).multiply(MoneyUtils.getMoneyYuan(d.getMoney())).setScale(2, RoundingMode.CEILING);
            BigDecimal yyszServiceChargeMoney = MoneyUtils.getMoneyYuan(d.getServiceChargeMoney()-d.getPtServiceChargeMoney()-d.getSydServiceChargeMoney());
            log.info(d.getBusNo()+"运营商总分润计算:"+yyszServiceChargeMoney);
            d.setSydServiceChargeRate(fws_service_rate.multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP));
            if(fhzx_service_rate != null) {
                d.setFhzxChannelId(fhzx_id);
                d.setFhzxServiceChargeRate(fhzx_service_rate.multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP));
                if (zj_service_rate == null) {
                    if(ywy_service_rate != null){
                        d.setFhzxServiceChargeMoney(MoneyUtils.getMoneyFen(ywy_service_rate.subtract(fhzx_service_rate).multiply(MoneyUtils.getMoneyYuan(d.getMoney())).setScale(2, RoundingMode.HALF_UP)));
                    }else{
                        d.setFhzxServiceChargeMoney(MoneyUtils.getMoneyFen(sh_service_rate.subtract(fhzx_service_rate).multiply(MoneyUtils.getMoneyYuan(d.getMoney())).setScale(2, RoundingMode.HALF_UP)));
                    }

                } else {
                    d.setFhzxServiceChargeMoney(MoneyUtils.getMoneyFen(zj_service_rate.subtract(fhzx_service_rate).multiply(MoneyUtils.getMoneyYuan(d.getMoney())).setScale(2, RoundingMode.HALF_UP)));
                }
            }else{
                d.setFhzxServiceChargeMoney(0l);
            }
            if(zj_service_rate != null) {
                d.setZjChannelId(zj_id);
                d.setZjServiceChargeRate(zj_service_rate.multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP));
                if (ywy_service_rate == null) {
                    d.setZjServiceChargeMoney(MoneyUtils.getMoneyFen(sh_service_rate.subtract(zj_service_rate).multiply(MoneyUtils.getMoneyYuan(d.getMoney())).setScale(2, RoundingMode.HALF_UP)));
                } else {
                    d.setZjServiceChargeMoney(MoneyUtils.getMoneyFen(ywy_service_rate.subtract(zj_service_rate).multiply(MoneyUtils.getMoneyYuan(d.getMoney())).setScale(2, RoundingMode.HALF_UP)));
                }
            }else{
                d.setZjServiceChargeMoney(0l);
            }
            if(ywy_service_rate != null) {
                d.setYwyChannelId(ywy_id);
                d.setYwyServiceChargeRate(ywy_service_rate.multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP));
                d.setYwyServiceChargeMoney(MoneyUtils.getMoneyFen(sh_service_rate.subtract(ywy_service_rate).multiply(MoneyUtils.getMoneyYuan(d.getMoney())).setScale(2, RoundingMode.HALF_UP)));
            }else{
                d.setYwyServiceChargeMoney(0l);
            }
            d.setShServiceChargeRate(sh_service_rate.multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP));
            //运营商分润=运营商总分润-孵化中心收益-总监收益-业务员收益
            d.setOpServiceChargeMoney(MoneyUtils.getMoneyFen(yyszServiceChargeMoney)-d.getFhzxServiceChargeMoney()-d.getZjServiceChargeMoney()-d.getYwyServiceChargeMoney());
            d.setOpServiceChargeMoney(d.getOpServiceChargeMoney() < 0 ? 0 :d.getOpServiceChargeMoney());
            d.setOpServiceChargeRate(yys_service_rate.multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP));
//            d.setFhzxServiceChargeRate(fws_service_rate.multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP));
            details.add(d);
        }
        billDetailMapper.insertBatch(details);
        reProductInvoiceMapper.allocProduct(Arrays.asList(add.getProId()),Arrays.asList(add.getMerId()), BusRole.MERCHANT.getId(),add.getId(),11,add.getCreateBy(),new Date());
        List<BusOperLog> operLogs = new ArrayList<>();//操作日志
        operLogs.add(new BusOperLog("商户提交打款指令", BusRole.MERCHANT,add.getId(),BusLogType.BILL.getId()));
        if(add.getSydVerifyStatus() != null){
            operLogs.add(new BusOperLog("服务商已接单", BusRole.SERVICE,add.getId(),BusLogType.BILL.getId()));
        }
        operLogMapper.insertBatch(operLogs);
        return flag;
    }

    /**
     * 生成代发明细项目子编号
     * @param retry 当前重试次数
     * @param maxRetry 最大重试次数
     * @param exists 已生成的项目子编号
     * @return
     */
    public String genBillDetailCNo(int retry,int maxRetry,List<String> exists){
        String no = "ST"+RandomUtil.randomNumbers(11);
        LambdaQueryWrapper<MerBillDetail> lqw = Wrappers.lambdaQuery();
        lqw.eq(MerBillDetail::getCno,no);
        MerBillDetail exist = billDetailMapper.selectOne(lqw);
        if(exist != null){
            if(retry > maxRetry){
                throw new ServiceException("项目子编号生成出错");
            }else {
                no = genBillDetailCNo(retry + 1,maxRetry,exists);
            }
        }else if(exists != null && exists.contains(no)){
            no = genBillDetailCNo(retry + 1,maxRetry,exists);
        }
        return no;
    }


    public void validateSysSyd(AddBillBo  bo){
        SysSydVo sydVo =  this.sydMapper.selectVoById(bo.getSydId());
        if(sydVo == null){
            this.invalidationParamsException("无效服务商!");
        }
        if(!(sydVo.getStatus() != null && sydVo.getStatus().intValue() == 1)){
            this.invalidationParamsException("服务商停止接单");
        }
    }

    /**
     * 修改账单
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo(MerBillBo bo) {
        MerBill update = MapstructUtils.convert(bo, MerBill.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean orderApproval(MerBillBo bo) {
        MerBill bill = baseMapper.selectOne(new LambdaQueryWrapper<MerBill>().eq(MerBill::getId,bo.getId()));
        if(bill.getSydVerifyStatus() != 1){
            throw new ServiceException("该代发批次已审核，无法重复审核！");
        }
        MerBill update = MapstructUtils.convert(bo, MerBill.class);
        update.setSydVerifyTime(new Date());
        if(bo.getSydVerifyStatus() == 2) {//拒绝
            update.setStatus(5l);
            //解冻代发金额
            if(merchantAccountMapper.updateFrozen(bill.getSydId(),bill.getMerId(),-bill.getAmountEnt(),bill.getPassage()) == 0){
                throw new ServiceException("商户余额解冻失败，请检查该代发批次是否已拒单！");
            }
            operLogMapper.insert(new BusOperLog("服务商已拒单", BusRole.SERVICE,bo.getId(),BusLogType.BILL.getId()));
        }else if(bo.getSydVerifyStatus() == 3) {//通过
            update.setStatus(1l);
            operLogMapper.insert(new BusOperLog("服务商已接单", BusRole.SERVICE,bo.getId(),BusLogType.BILL.getId()));
        }
        return baseMapper.updateById(update) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean paymentApproval(MerBillBo bo) {
        MerBill bill = baseMapper.selectOne(new LambdaQueryWrapper<MerBill>().eq(MerBill::getId,bo.getId()));
        if(bill.getVerifyStatus() != 1){
            throw new ServiceException("该代发批次已审批，无法重复审批！");
        }
        MerBill update = MapstructUtils.convert(bo, MerBill.class);
        update.setVerifyTime(new Date());
        BusMerchant merchant = merchantMapper.selectOne(new LambdaQueryWrapper<BusMerchant>().eq(BusMerchant::getId,bill.getMerId()));
        if(bo.getVerifyStatus() == 2) {//拒绝
            update.setStatus(4l);
            //解冻代发金额
            if(merchantAccountService.updateFrozen(bill.getSydId(),bill.getMerId(),-bill.getAmountEnt(),bill.getPassage()) == 0){
                throw new ServiceException("余额解冻失败，请检查该代发批次是否已撤消！");
            }
            billDetailMapper.update(new LambdaUpdateWrapper<MerBillDetail>().eq(MerBillDetail::getBillId,bill.getId())
                .set(MerBillDetail::getPayStatus,4)
                .set(MerBillDetail::getChannelHalveStatus,4));//取消
            operLogMapper.insert(new BusOperLog("商户拒绝出款", BusRole.MERCHANT,bo.getId(),BusLogType.BILL.getId()));
        }else if(bo.getVerifyStatus() == 3) {//通过
            if(StringUtils.isBlank(bo.getPassword())){
                throw new ServiceException("支付密码不为能空");
            }
            checkPayPassword(BusRole.MERCHANT, bill.getMerId(), () -> {
                if(StringUtils.isBlank(merchant.getPayPassword())){
                    throw new ServiceException("请前往系统管理进行支付密码重置！");
                }
                return !bo.getPassword().equals(merchant.getPayPassword());
            });
            update.setStatus(2l);
            update.setGiveUpBy(update.getVerifyBy());
            update.setGiveUpTime(update.getVerifyTime());
            billDetailMapper.update(new LambdaUpdateWrapper<MerBillDetail>().eq(MerBillDetail::getBillId,bill.getId())
                .eq(MerBillDetail::getPayStatus,0)
                .set(MerBillDetail::getPayStatus,3));//支付中
            operLogMapper.insert(new BusOperLog("商户提交出款指令", BusRole.MERCHANT,bo.getId(),BusLogType.BILL.getId()));
        }

        SysSyd sysSyd = sydMapper.selectSysSydById(bill.getSydId());
        MerTask merTask = taskMapper.selectById(bill.getTaskId());
        BusMerchantAccount account = merchantAccountMapper.selectOne(new LambdaQueryWrapper<BusMerchantAccount>().eq(BusMerchantAccount::getMerId,bill.getMerId()).eq(BusMerchantAccount::getSydId,bill.getSydId()).eq(BusMerchantAccount::getBankType,bill.getPassage()).eq(BusMerchantAccount::getStatus,1));
        List<MerBillDetail> merBillDetails = billDetailMapper.selectList(new LambdaQueryWrapper<MerBillDetail>().eq(MerBillDetail::getBillId,bill.getId()));
        SysThirdPlatform sysThirdPlatform = sysThirdPlatformMapper.selectThirdAppInfo(sysSyd.getThreeId());





        if(Objects.nonNull(sysThirdPlatform) && sysThirdPlatform.getPlatformName().equals("薪遇见")){
         return xyjService.settleBatch(bill, merBillDetails, sysSyd, merchant, merTask, account);
        }else{
            return baseMapper.updateById(update) > 0;
        }

    }

    /**
     * 验证支付密码
     */
    @Override
    public Boolean checkPayPassword(BusRole role,long busId, Supplier<Boolean> supplier) {
        String errorKey = "pwd_err_cnt:"+ role.getId() + ":" + busId;
        Integer maxRetryCount = payPasswordProperties.getMaxRetryCount();
        Integer lockTime = payPasswordProperties.getLockTime();

        // 获取用户登录错误次数，默认为0 (可自定义限制策略 例如: key + username + ip)
        int errorNumber = ObjectUtil.defaultIfNull(RedisUtils.getCacheObject(errorKey), 0);
        // 锁定时间内登录 则踢出
        if (errorNumber >= maxRetryCount) {
            throw new ServiceException("密码输入错误"+maxRetryCount+"次，帐户锁定"+lockTime+"分钟");
        }

        if (supplier.get()) {
            // 错误次数递增
            errorNumber++;
            RedisUtils.setCacheObject(errorKey, errorNumber, Duration.ofMinutes(lockTime));
            // 达到规定错误次数 则锁定
            if (errorNumber >= maxRetryCount) {
                throw new ServiceException("密码输入错误"+maxRetryCount+"次，帐户锁定"+lockTime+"分钟");
            } else {
                // 未达到规定错误次数
                throw new ServiceException("密码错误,剩余"+(maxRetryCount - errorNumber)+"次输入机会!");
            }
        }

        // 登录成功 清空错误次数
        RedisUtils.deleteObject(errorKey);
        return true;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(MerBill entity){
        //TODO 做一些数据校验,如唯一约束
        MerBill exist = baseMapper.selectOne(new LambdaQueryWrapper<MerBill>().eq(MerBill::getNo,getBillNo(entity.getMerNo(),entity.getNo())));
        if(exist != null){
            throw new ServiceException("批次号重复，请勿重复提交！");
        }
        BusMerchantAccount account = merchantAccountMapper.selectOne(new LambdaQueryWrapper<BusMerchantAccount>().eq(BusMerchantAccount::getMerId,entity.getMerId()).eq(BusMerchantAccount::getSydId,entity.getSydId()).eq(BusMerchantAccount::getBankType,entity.getPassage()).eq(BusMerchantAccount::getStatus,1));
        if(account == null){
            throw new ServiceException(entity.getPassage()+"账户未开通！");
        }
        if(account.getBalance()-account.getFrozen()<entity.getAmountEnt()){
            throw new ServiceException(entity.getPassage()+"账户余额不足！");
        }
    }

    /**
     * 批量删除账单
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean paymentToService(int billId) {
        MerBill bill = baseMapper.selectById(billId);
        String busDesc = "转账到服务商";
        if (bill == null) {
            String msg = "代发批次不存在";
            throw new ServiceException(msg).setDetailMessage(busDesc+"，"+msg+"("+billId+")");
        }
        if (bill.getStatus().intValue() == 4) {
            String msg = "代发批次已取消";
            throw new ServiceException(msg).setDetailMessage(busDesc+"，"+msg+"("+billId+")");
        }

        if (bill.getStatus().intValue() == 3) {
            String msg = "代发批次已支付";
            throw new ServiceException(msg).setDetailMessage(busDesc+"，"+msg+"("+billId+")");
        }
        List<BusMerchantAccountVo> accs = merchantAccountMapper.selectByMerIdAndSydId(bill.getSydId(), bill.getMerId(),bill.getPassage());
        List<SysSydAccount> sydAccs = sydAccountDao.selectSysSydAccountBySydId(bill.getSydId(),null,bill.getPassage());
        List<MerBillDetailVo> details = billDetailMapper.selectVoList(new LambdaQueryWrapper<MerBillDetail>().eq(MerBillDetail::getBillId,bill.getId()).eq(MerBillDetail::getPayStatus,3));
        if (details.size() == 0) {
            MerBill upd = new MerBill();
            upd.setId(bill.getId());
            upd.setStatus(3l);
            upd.setPayStatus(2l);
            upd.setPayTime(new Date());
            baseMapper.updateById(upd);
            return false;
        }
        if (accs.size() == 0) {
            String msg = "商户"+bill.getPassage()+"账户不存在";
            throw new ServiceException(msg).setDetailMessage(busDesc+"，"+msg+"(代发批次id-"+bill.getId() + "," +bill.getSydId() +"," + bill.getMerId()+")");
        }
        if (sydAccs.size() == 0) {
            String msg = "服务商"+bill.getPassage()+"账户不存在";
            throw new ServiceException(msg).setDetailMessage(busDesc+"，"+msg+"(代发批次id-"+bill.getId() + "," +bill.getSydId()+")");
        }
        if (accs.get(0).getFrozen() < bill.getAmountEnt()) {
            String msg = "商户"+bill.getPassage()+"账户冻结金额不足";
            throw new ServiceException(msg).setDetailMessage(busDesc+"，"+msg+"(代发批次id-"+bill.getId() + "," +bill.getSydId() +"," + bill.getMerId()+")");
        }
        //商户转账到服务商B2B
        TranLog backLog = new TranLog();
        backLog.setBusType(2l);
        backLog.setBusItem(1l);
        backLog.setTranNo("TR1"+IdUtil.getSnowflakeNextIdStr());
        backLog.setBuisId(bill.getId());
        boolean backOk = tranLogDao.selectByBus(backLog.getBusType().intValue(), backLog.getBuisId().intValue(), backLog.getBusItem()+"",null,null).size() == 0;
        if(backOk) {
            Result<TransactionLog> backRtn = accountService.applyTransfer(accs.get(0).getAccId().intValue(), sydAccs.get(0).getAccId().intValue(),bill.getAmountEnt(), bill.getNo(), "B2B转账");
            String msg = "发送交易申请失败";
            if (backRtn.hasError()) {
                throw new ServiceException(msg).setDetailMessage(busDesc+"，"+msg+"(代发批次id-"+bill.getId() + "," +bill.getSydId() +"," + bill.getMerId()+")："+backRtn.getResult());
            }else if (backRtn.hasTip()) {
                throw new ServiceException(msg).setDetailMessage(busDesc+"，"+msg+"(代发批次id-"+bill.getId() + "," +bill.getSydId() +"," + bill.getMerId()+")："+backRtn.getResult());
            }else if (backRtn.getRtnData() == null) {
                throw new ServiceException(msg).setDetailMessage(busDesc+"，"+msg+"(代发批次id-"+bill.getId() + "," +bill.getSydId() +"," + bill.getMerId()+")");
            }
            backLog.setTranId(backRtn.getRtnData().getId());
            backLog.setAddTime(new Date());
            backLog.setTranResult(backRtn.getRtnData().getResult().intValue());
            backLog.setSourceAccId(backRtn.getRtnData().getSourceAccId().longValue());
            backLog.setSourceAccType(BusRole.MERCHANT.getId());
            backLog.setTargetAccId(backRtn.getRtnData().getTargetAccId().longValue());
            backLog.setTargetAccType(BusRole.SERVICE.getId());
            backLog.setIsCallback(0);
            tranLogDao.insert(backLog);
            billDetailMapper.update(new LambdaUpdateWrapper<MerBillDetail>().eq(MerBillDetail::getBillId,bill.getId())
                .eq(MerBillDetail::getPayStatus,3)
                .set(MerBillDetail::getSydHalveStatus,3));//支付中
            operLogMapper.insert(new BusOperLog("企业转账服务商", BusRole.MERCHANT,bill.getId(),BusLogType.BILL.getId()));
        }
        return true;
    }

    /**
     * 服务商转账到运营商
     * @param bill
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean paymentToOperator(MerBillVo bill) {
        if (bill == null) {
            throw new ServiceException("服务商转账到运营商，代发批次不存在");
        }
        if (bill.getStatus().intValue() == 4) {
            throw new ServiceException("服务商转账到运营商，代发批次已取消("+bill.getId()+")");
        }

        if (bill.getStatus().intValue() == 3) {
            throw new ServiceException("服务商转账到运营商，代发批次已支付("+bill.getId()+")");
        }
        BusOperatorAccountVo accs = operatorAccountMapper.selectVoOne(new LambdaQueryWrapper<BusOperatorAccount>()
            .eq(BusOperatorAccount::getSydId,bill.getSydId())
            .eq(BusOperatorAccount::getOpId,bill.getOpId())
            .eq(BusOperatorAccount::getBankType,bill.getPassage())
            .eq(BusOperatorAccount::getIsDefault,1));
        List<SysSydAccount> sydAccs = sydAccountDao.selectSysSydAccountBySydId(bill.getSydId(),null,bill.getPassage());
        List<MerBillDetailVo> details = billDetailMapper.selectVoList(new LambdaQueryWrapper<MerBillDetail>().eq(MerBillDetail::getBillId,bill.getId()).eq(MerBillDetail::getPayStatus,3));
        if (details.size() == 0) {
            throw new ServiceException("服务商转账到运营商，代发明细不存在("+bill.getId()+")");
        }
        if (accs == null) {
            String msg = "运营商"+bill.getPassage()+"账户不存在";
            throw new ServiceException(msg+"(代发批次id-"+bill.getId() + "," +bill.getSydId().intValue() +"," + bill.getOpId()+")");
        }
        if (sydAccs.size() == 0) {
            String msg = "服务商"+bill.getPassage()+"账户不存在";
            throw new ServiceException(msg+"(代发批次id-"+bill.getId() + "," +bill.getSydId().intValue()+")");
        }

        //运营商总分润(分)
        Long sumOpServiceChargeMoney = 0l;
        for (MerBillDetailVo detail:details) {
            sumOpServiceChargeMoney += detail.getOpServiceChargeMoney();
            sumOpServiceChargeMoney += detail.getFhzxServiceChargeMoney();
            sumOpServiceChargeMoney += detail.getZjServiceChargeMoney();
            sumOpServiceChargeMoney += detail.getYwyServiceChargeMoney();
        }
        if (sydAccs.get(0).getFrozen() < sumOpServiceChargeMoney) {
            String msg = "服务商"+bill.getPassage()+"账户冻结金额不足";
            throw new ServiceException(msg+"(代发批次id-"+bill.getId() + "," +bill.getSydId() +"," + bill.getMerId()+")");
        }
        //服务商转账到运营商
        TranLog backLog = new TranLog();
        backLog.setBusType(2l);
        backLog.setBusItem(2l);
        backLog.setTranNo("T2"+IdUtil.getSnowflakeNextIdStr());
        backLog.setBuisId(bill.getId());
        boolean backOk = tranLogDao.selectByBus(backLog.getBusType().intValue(), backLog.getBuisId().intValue(), backLog.getBusItem()+"",null,null).size() == 0;
        if(backOk) {
            Result<TransactionLog> backRtn = accountService.applyTransfer(sydAccs.get(0).getAccId().intValue(), accs.getAccId().intValue(),sumOpServiceChargeMoney, bill.getNo(), "渠道推广费");
            if (backRtn.hasError()) {
                String msg = "服务商转账到运营商，发送交易申请失败";
                throw new ServiceException(msg+"(代发批次id-"+bill.getId() + "," +bill.getSydId() +"," + bill.getMerId()+")："+backRtn.getResult());
            }else if (backRtn.hasTip()) {
                String msg = "服务商转账到运营商，发送交易申请失败";
                throw new ServiceException(msg+"(代发批次id-"+bill.getId() + "," +bill.getSydId() +"," + bill.getMerId()+")："+backRtn.getResult());
            }else if (backRtn.getRtnData() == null) {
                String msg = "服务商转账到运营商，发送交易申请失败";
                throw new ServiceException(msg+"(代发批次id-"+bill.getId() + "," +bill.getSydId() +"," + bill.getMerId()+")");
            }
            backLog.setTranId(backRtn.getRtnData().getId());
            backLog.setAddTime(new Date());
            backLog.setTranResult(backRtn.getRtnData().getResult().intValue());
            backLog.setSourceAccId(backRtn.getRtnData().getSourceAccId().longValue());
            backLog.setSourceAccType(BusRole.SERVICE.getId());
            backLog.setTargetAccId(backRtn.getRtnData().getTargetAccId().longValue());
            backLog.setTargetAccType(BusRole.OPERATOR.getId());
            backLog.setIsCallback(0);
            tranLogDao.insert(backLog);
            billDetailMapper.update(new LambdaUpdateWrapper<MerBillDetail>()
                .eq(MerBillDetail::getBillId, bill.getId())
                .eq(MerBillDetail::getPayStatus, 3)
                .set(MerBillDetail::getOpHalveStatus, 3));//支付中
            operLogMapper.insert(new BusOperLog("服务商转账运营商", BusRole.SERVICE,bill.getId(),BusLogType.BILL.getId()));
        }
        return true;
    }

    /**
     * 服务商转账到平台
     * @param bill
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean paymentToPlatform(MerBillVo bill) {
        String busDesc = "服务商转账到平台";
        if (bill == null) {
            throw new ServiceException(busDesc+"，代发批次不存在");
        }
        if (bill.getStatus().intValue() == 4) {
            throw new ServiceException(busDesc+"，代发批次已取消("+bill.getId()+")");
        }

        if (bill.getStatus().intValue() == 3) {
            throw new ServiceException(busDesc+"，代发批次已支付("+bill.getId()+")");
        }
        BusAccountsVo accs = accountsMapper.selectVoOne(new LambdaQueryWrapper<BusAccounts>()
            .eq(BusAccounts::getSydId,bill.getSydId())
            .eq(BusAccounts::getUnitId,0)
            .eq(BusAccounts::getBankType,bill.getPassage())
            .eq(BusAccounts::getIsDefault,1));
        List<SysSydAccount> sydAccs = sydAccountDao.selectSysSydAccountBySydId(bill.getSydId(),null,bill.getPassage());
        List<MerBillDetailVo> details = billDetailMapper.selectVoList(new LambdaQueryWrapper<MerBillDetail>().eq(MerBillDetail::getBillId,bill.getId()).eq(MerBillDetail::getPayStatus,3));
        if (details.size() == 0) {
            throw new ServiceException(busDesc+"，代发明细不存在("+bill.getId()+")");
        }
        if (accs == null) {
            String msg = "平台"+bill.getPassage()+"账户不存在";
            throw new ServiceException(msg+"(代发批次id-"+bill.getId() + "," +bill.getSydId() +"," + bill.getOpId()+")");
        }
        if (sydAccs.size() == 0) {
            String msg = "服务商"+bill.getPassage()+"账户不存在";
            throw new ServiceException(msg+"(代发批次id-"+bill.getId() + "," +bill.getSydId()+")");
        }
        //平台分润(分)
        Long ptServiceChargeMoney = details.stream().mapToLong(MerBillDetailVo::getPtServiceChargeMoney).sum();
        if (sydAccs.get(0).getFrozen() < ptServiceChargeMoney) {
            String msg = "服务商"+bill.getPassage()+"账户冻结金额不足";
            throw new ServiceException(msg+"(代发批次id-"+bill.getId() + "," +bill.getSydId() +"," + bill.getMerId()+")");
        }
        //服务商转账到运营商
        TranLog backLog = new TranLog();
        backLog.setBusType(2l);
        backLog.setBusItem(3l);
        backLog.setTranNo("TR5"+IdUtil.getSnowflakeNextIdStr());
        backLog.setBuisId(bill.getId());
        boolean backOk = tranLogDao.selectByBus(backLog.getBusType().intValue(), backLog.getBuisId().intValue(), backLog.getBusItem()+"",null,null).size() == 0;
        if(backOk) {
            Result<TransactionLog> backRtn = accountService.applyTransfer(sydAccs.get(0).getAccId().intValue(), accs.getAccId().intValue(),ptServiceChargeMoney, bill.getNo(), "技术服务费");
            if (backRtn.hasError()) {
                String msg = busDesc+"，发送交易申请失败";
                throw new ServiceException(msg+"(代发批次id-"+bill.getId() + "," +bill.getSydId() +"," + bill.getMerId()+")："+backRtn.getResult());
            }else if (backRtn.hasTip()) {
                String msg = busDesc+"，发送交易申请失败";
                throw new ServiceException(msg+"(代发批次id-"+bill.getId() + "," +bill.getSydId() +"," + bill.getMerId()+")："+backRtn.getResult());
            }else if (backRtn.getRtnData() == null) {
                String msg = busDesc+"，发送交易申请失败";
                throw new ServiceException(msg+"(代发批次id-"+bill.getId() + "," +bill.getSydId() +"," + bill.getMerId()+")");
            }
            backLog.setTranId(backRtn.getRtnData().getId());
            backLog.setAddTime(new Date());
            backLog.setTranResult(backRtn.getRtnData().getResult().intValue());
            backLog.setSourceAccId(backRtn.getRtnData().getSourceAccId().longValue());
            backLog.setSourceAccType(BusRole.SERVICE.getId());
            backLog.setTargetAccId(backRtn.getRtnData().getTargetAccId().longValue());
            backLog.setTargetAccType(BusRole.PLATFORM.getId());
            backLog.setIsCallback(0);
            tranLogDao.insert(backLog);
            billDetailMapper.update(new LambdaUpdateWrapper<MerBillDetail>()
                .eq(MerBillDetail::getBillId, bill.getId())
                .eq(MerBillDetail::getPayStatus, 3)
                .set(MerBillDetail::getPtHalveStatus, 3));//支付中
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean paymentToWorkers(MerBillVo bill) {
        if (bill == null) {
            throw new ServiceException("代发批次不存在");
        }
        if (bill.getStatus().intValue() == 4) {
            throw new ServiceException("代发批次已取消("+bill.getId()+")");
        }
        if (bill.getStatus().intValue() == 3) {
            throw new ServiceException("代发批次已支付("+bill.getId()+")");
        }
        List<MerBillDetail> details = billDetailMapper.selectList(new LambdaQueryWrapper<MerBillDetail>().eq(MerBillDetail::getBillId,bill.getId()).eq(MerBillDetail::getPayStatus,3));
        for (MerBillDetail billDetail:
            details) {
            singlePaymentToWorker(billDetail);
        }
        operLogMapper.insert(new BusOperLog("B2C代发", BusRole.MERCHANT,bill.getId(),BusLogType.BILL.getId()));
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean paymentToWorker(int billDetailId) {
        MerBillDetail billDetail = billDetailMapper.selectById(billDetailId);
        return singlePaymentToWorker(billDetail);
    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean singlePaymentToWorker(MerBillDetail billDetail) {
        String busDesc = "服务商转账到个人B2C";
        if (billDetail == null) {
            String msg = "代发批次明细不存在";
            throw new ServiceException(msg).setDetailMessage(busDesc+"，"+msg);
        }
        if (billDetail.getPayStatus() == 4) {
            String msg = "代发批次明细已取消";
            throw new ServiceException(msg).setDetailMessage(busDesc+"，"+msg+"("+billDetail.getId()+")");
        }
        if (billDetail.getPayStatus() != 0 && billDetail.getPayStatus() != 2 && billDetail.getPayStatus() != 3) {
            String msg = "代发批次明细已支付或支付中";
            throw new ServiceException(msg).setDetailMessage(busDesc+"，"+msg+"("+billDetail.getId()+")");
        }
        List<SysSydAccount> sydAccs = sydAccountDao.selectSysSydAccountBySydId(billDetail.getSydId(),null,billDetail.getPassage());
        if (sydAccs.size() == 0) {
            String msg = "服务商"+billDetail.getPassage()+"账户不存在";
            throw new ServiceException(msg).setDetailMessage(busDesc+"，"+msg+"(代发批次明细id-"+billDetail.getId() + "," +billDetail.getSydId().intValue()+")");
        }
        if(billDetail.getWorkerId() == 0 && billDetail.getIsOut() == 1) {//开放平台-付款账户
            Account bankAcc = new Account();
            bankAcc.setBankType(StringUtils.isNotBlank(billDetail.getBankType()) ? billDetail.getBankType() : "开放平台");
            bankAcc.setBankCard(billDetail.getBankCard());
            bankAcc.setUnitId(0l);
            bankAcc.setName(billDetail.getWorkerName());
            bankAcc.setType((short)2);//2:真实个人账户
            Result<Account> addRtn = accountService.addAccount(bankAcc);
            String msg = "创建交易账号失败";
            if (addRtn.hasError()) {
                throw new ServiceException(msg).setDetailMessage(busDesc+"，"+msg+"(代发批次明细id-"+billDetail.getId() + "," +billDetail.getSydId() +"," + billDetail.getMerId()+")："+addRtn.getResult());
            }else if (addRtn.hasTip()) {
                throw new ServiceException(msg).setDetailMessage(busDesc+"，"+msg+"(代发批次明细id-"+billDetail.getId() + "," +billDetail.getSydId() +"," + billDetail.getMerId()+")："+addRtn.getResult());
            }else if (addRtn.getRtnData() == null) {
                throw new ServiceException(msg);
            }
            billDetailMapper.update(new LambdaUpdateWrapper<MerBillDetail>().eq(MerBillDetail::getId,billDetail.getId())
                .set(MerBillDetail::getBankAccId,addRtn.getRtnData().getId()));
            billDetail.setBankAccId(addRtn.getRtnData().getId());
        }
        //服务商转账到个人B2C
        TranLog backLog = new TranLog();
        backLog.setBusType(2l);
        backLog.setBusItem(4l);
        String no = DateUtils.dateTimeNow(DateUtils.YYYYMMDDHHMMSSSSS)+billDetail.getId();
        int randomLength = 22 - no.length();
        if(randomLength > 0){
            no += RandomUtil.randomNumbers(randomLength);
        }
        backLog.setTranNo(no);
        backLog.setBuisId(billDetail.getId());
        boolean backOk = tranLogDao.selectByBus(backLog.getBusType().intValue(), backLog.getBuisId().intValue(), backLog.getBusItem()+"",null,"-1,1,2").size() == 0;
        if(backOk) {
            Result<TransactionLog> backRtn = accountService.applyTransfer(sydAccs.get(0).getAccId().intValue(), billDetail.getBankAccId(),billDetail.getAmount(), billDetail.getBusNo(), "B2C转账");
            String msg = "发送交易申请失败";
            if (backRtn.hasError()) {
                throw new ServiceException(msg).setDetailMessage(busDesc+"，"+msg+"(代发批次明细id-"+billDetail.getId() + "," +billDetail.getSydId() +"," + billDetail.getMerId()+")："+backRtn.getResult());
            }else if (backRtn.hasTip()) {
                throw new ServiceException(msg).setDetailMessage(busDesc+"，"+msg+"(代发批次明细id-"+billDetail.getId() + "," +billDetail.getSydId() +"," + billDetail.getMerId()+")："+backRtn.getResult());
            }else if (backRtn.getRtnData() == null) {
                throw new ServiceException(msg).setDetailMessage(busDesc+"，"+msg+"(代发批次明细id-"+billDetail.getId() + "," +billDetail.getSydId() +"," + billDetail.getMerId()+")");
            }
            backLog.setTranId(backRtn.getRtnData().getId());
            backLog.setAddTime(new Date());
            backLog.setTranResult(backRtn.getRtnData().getResult().intValue());
            backLog.setSourceAccId(backRtn.getRtnData().getSourceAccId().longValue());
            backLog.setSourceAccType(BusRole.SERVICE.getId());
            backLog.setTargetAccId(backRtn.getRtnData().getTargetAccId().longValue());
            backLog.setTargetAccType(BusRole.WORKER.getId());
            backLog.setIsCallback(0);
            tranLogDao.insert(backLog);
            if(billDetail.getWorkerEnrollId() != null && billDetail.getWorkerEnrollId() > 0) {
                taskEnrollMapper.update(new LambdaUpdateWrapper<MerTaskEnroll>().eq(MerTaskEnroll::getId, billDetail.getWorkerEnrollId())
                    .set(MerTaskEnroll::getSettlementStatus, 2));//结算中
            }
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TranLog billTransaction(TranLogVo tlog, TransactionLog tran) {
        TranLog save = null;
        if (tran.getResult().intValue() == 2 || tran.getResult().intValue() == 3){
            if (tran.getResult().intValue() == 2) {//支付成功
                if(tlog.getBusItem() == 4){//服务商转账到个人B2C
                    String busDesc = "服务商转账到个人B2C";
                    MerBillDetail billDetail = billDetailMapper.selectById(tlog.getBuisId());
                    if (billDetail == null) {
                        throw new ServiceException(busDesc+"时，账单详情不存在（"+tlog.getBuisId()+"）");
                    }
                    if(billDetail.getPayStatus() != 3){
                        //非支付中，直接返回
                        return null;
                    }
                    if(billDetailMapper.update(new LambdaUpdateWrapper<MerBillDetail>()
                        .eq(MerBillDetail::getId, billDetail.getId())
                        .eq(MerBillDetail::getPayStatus, 3)
                        .set(MerBillDetail::getPayStatus, 1)
                        .set(MerBillDetail::getPayTime, new Date())) == 0){
                        throw new ServiceException(busDesc+"时，已代发或已取消（"+tlog.getBuisId()+"）");
                    }
                    if(billDetail.getWorkerEnrollId() != null && billDetail.getWorkerEnrollId() > 0) {
                        //已结算
                        if(taskEnrollMapper.update(new LambdaUpdateWrapper<MerTaskEnroll>().eq(MerTaskEnroll::getId, billDetail.getWorkerEnrollId())
                            .eq(MerTaskEnroll::getSettlementStatus,2)
                            .set(MerTaskEnroll::getSettlementStatus, 1)) == 0){
                            throw new ServiceException(busDesc+"时，已结算或已取消（"+tlog.getBuisId()+","+billDetail.getWorkerEnrollId()+"）");
                        }
                    }
                    if(sydAccountService.updateBalanceByAccId(tran.getSourceAccId(),-tran.getAmount()) == 0){
                        throw new ServiceException(busDesc+"时，"+billDetail.getPassage()+"账户余额不足（"+tlog.getBuisId()+"）");
                    }
                    if(sydAccountService.updateFrozenByAccId(tran.getSourceAccId(),-tran.getAmount()) == 0){
                        throw new ServiceException(busDesc+"时，"+billDetail.getPassage()+"账户冻结金额不足（"+tlog.getBuisId()+"）");
                    }
                    MerBillVo bill = baseMapper.selectVoById(billDetail.getBillId());
                    SysSydVo syd = sydMapper.selectVoById(bill.getSydId());
                    SysSydFlows sydFlow = new SysSydFlows(2,bill.getSydId(),1, bill.getPassage(), bill.getNo(),tran.getTargetBankNo(), -tran.getAmount(), new Date(),bill.getAddBy(),"B2C转账", bill.getNo(), bill.getId(), billDetail.getId(), tlog.getTranNo(), 2, tran.getResult().intValue(), tlog.getSourceAccType(), bill.getSydId(), syd.getGsmc(), tran.getSourceCard(), tran.getSourceAccId().longValue(), tlog.getTargetAccType(), billDetail.getWorkerId(), tran.getTargetAccName(), tran.getTargetCard(), tran.getTargetAccId().longValue(), "", 2);
                    sydFlowsMapper.insertSelective(sydFlow);
                    billDetailService.billResult(bill.getId());
                }else{
                    MerBillVo bill = baseMapper.selectVoById(tlog.getBuisId());
                    if(bill == null){
                        throw new ServiceException("服务商B2B时，代发批次不存在（"+tlog.getBuisId()+"）");
                    }
                    if(bill.getStatus() != 2){
                        //非发放中，直接返回
                        return null;
                    }
                    SysSydVo syd = sydMapper.selectVoById(bill.getSydId());
                    if(tlog.getBusItem() == 1){//商户转账到服务商B2B
                        if(merchantAccountService.updateBalanceByAccId(tran.getSourceAccId(),-tran.getAmount()) == 0){
                            throw new ServiceException("商户转账到服务商B2B时，"+bill.getPassage()+"账户余额不足（"+tlog.getBuisId()+"）");
                        }
                        if(merchantAccountService.updateFrozenByAccId(tran.getSourceAccId(),-tran.getAmount()) == 0){
                            throw new ServiceException("商户转账到服务商B2B时，"+bill.getPassage()+"账户冻结金额不足（"+tlog.getBuisId()+"）");
                        }
                        if(billDetailMapper.update(new LambdaUpdateWrapper<MerBillDetail>()
                            .eq(MerBillDetail::getBillId, bill.getId())
                            .eq(MerBillDetail::getPayStatus, 3)
                            .eq(MerBillDetail::getSydHalveStatus, 3)
                            .set(MerBillDetail::getSydHalveStatus, 1)) == 0){
                            throw new ServiceException("商户转账到服务商B2B时，非支付中（"+tlog.getBuisId()+"）");
                        }
                        BusMerchantVo merchant = merchantMapper.selectVoById(bill.getMerId());
                        BusMerchantFlows merchantFlow = new BusMerchantFlows(2,bill.getMerId(),bill.getSydId(),5, bill.getPassage(), bill.getNo(),tran.getTargetBankNo(), -tran.getAmount(), new Date(),bill.getAddBy(),"B2B转账", bill.getNo(), bill.getId(), null, tlog.getTranNo(), 1, tran.getResult().intValue(), tlog.getSourceAccType(), bill.getMerId(), merchant.getName(), tran.getSourceCard(), tran.getSourceAccId().longValue(), tlog.getTargetAccType(), bill.getSydId(), syd.getGsmc(), tran.getTargetCard(), tran.getTargetAccId().longValue(), "", 1, "");
                        merchantFlowsMapper.insertAll(Arrays.asList(merchantFlow));
                        sydAccountService.updateBalanceByAccId(tran.getTargetAccId(),tran.getAmount());
                        sydAccountService.updateFrozenByAccId(tran.getTargetAccId(),tran.getAmount());
                        sydFlowsMapper.insertSelective(new SysSydFlows(1,bill.getSydId(),merchantFlow.getBusType(),merchantFlow.getChannel(),merchantFlow.getBusNo(),merchantFlow.getBankNo(),tran.getAmount(),merchantFlow.getAddTime(),merchantFlow.getAddBy(),merchantFlow.getBusDesc(),merchantFlow.getBillNo(),merchantFlow.getBillId(),merchantFlow.getBillDetailId(),merchantFlow.getTranNo(),merchantFlow.getTranType(),merchantFlow.getTranStatus(),merchantFlow.getPayerType(),merchantFlow.getPayerId(),merchantFlow.getPayerName(),merchantFlow.getPayerAcc(),merchantFlow.getPayerAccId(),merchantFlow.getPayeeType(),merchantFlow.getPayeeId(),merchantFlow.getPayeeName(),merchantFlow.getPayeeAcc(),merchantFlow.getPayeeAccId(),merchantFlow.getBillNo(),merchantFlow.getPayReceiptType()));
                        paymentToOperator(bill);
                    }else if(tlog.getBusItem() == 2){//服务商转账到运营商
                        BusOperatorVo operatorVo = operatorMapper.selectVoById(bill.getOpId());
                        if(sydAccountService.updateBalanceByAccId(tran.getSourceAccId(),-tran.getAmount()) == 0){
                            throw new ServiceException("服务商转账到运营商时，"+bill.getPassage()+"账户余额不足（"+tlog.getBuisId()+"）");
                        }
                        if(sydAccountService.updateFrozenByAccId(tran.getSourceAccId(),-tran.getAmount()) == 0){
                            throw new ServiceException("服务商转账到运营商时，"+bill.getPassage()+"账户冻结金额不足（"+tlog.getBuisId()+"）");
                        }
                        if(billDetailMapper.update(new LambdaUpdateWrapper<MerBillDetail>()
                            .eq(MerBillDetail::getBillId, bill.getId())
                            .eq(MerBillDetail::getPayStatus, 3)
                            .eq(MerBillDetail::getOpHalveStatus, 3)
                            .set(MerBillDetail::getOpHalveStatus, 1)
                            .set(MerBillDetail::getChannelHalveStatus,3)) == 0){
                            throw new ServiceException("服务商转账到运营商时，非支付中（"+tlog.getBuisId()+"）");
                        }
                        SysSydFlows sydFlow = new SysSydFlows(2,bill.getSydId(),4, bill.getPassage(), bill.getNo(),tran.getTargetBankNo(), -tran.getAmount(), new Date(),bill.getAddBy(),"渠道推广费", bill.getNo(), bill.getId(), null, tlog.getTranNo(), 1, tran.getResult().intValue(), tlog.getSourceAccType(), bill.getSydId(), syd.getGsmc(), tran.getSourceCard(), tran.getSourceAccId().longValue(), tlog.getTargetAccType(), bill.getOpId(), operatorVo.getName(), tran.getTargetCard(), tran.getTargetAccId().longValue(), "", 1);
                        sydFlowsMapper.insertSelective(sydFlow);
                        List<MerBillDetailVo> details = billDetailMapper.selectVoList(new LambdaQueryWrapper<MerBillDetail>().eq(MerBillDetail::getBillId,bill.getId()).eq(MerBillDetail::getPayStatus,3));
                        //运营商分润(分)
                        Long sumOpServiceChargeMoney = 0l;
                        //孵化中心收益(分)
                        Long sumFhzxServiceChargeMoney = 0l;
                        //总监收益(分)
                        Long sumZjServiceChargeMoney = 0l;
                        //业务员收益(分)
                        Long sumYwyServiceChargeMoney = 0l;
                        for(MerBillDetailVo detail : details){
                            sumOpServiceChargeMoney += detail.getOpServiceChargeMoney();
                            sumFhzxServiceChargeMoney += detail.getFhzxServiceChargeMoney();
                            sumZjServiceChargeMoney += detail.getZjServiceChargeMoney();
                            sumYwyServiceChargeMoney += detail.getYwyServiceChargeMoney();
                        }
                        Long yysSumAll = sumOpServiceChargeMoney+sumFhzxServiceChargeMoney+sumZjServiceChargeMoney+sumYwyServiceChargeMoney;
//                        operatorAccountService.updateBalanceByAccId(tran.getTargetAccId(),sumOpServiceChargeMoney);
//                        operatorFlowsMapper.insertSelective(new BusOperatorFlows(1,bill.getOpId(),sydFlow.getBusType(),sydFlow.getChannel(),sydFlow.getBusNo(),sydFlow.getBankNo(),sumOpServiceChargeMoney,sydFlow.getAddTime(),sydFlow.getAddBy(),sydFlow.getBusDesc(),sydFlow.getBillNo(),sydFlow.getBillId(),sydFlow.getBillDetailId(),sydFlow.getTranNo(),sydFlow.getTranType(),sydFlow.getTranStatus(),sydFlow.getPayerType(),sydFlow.getPayerId(),sydFlow.getPayerName(),sydFlow.getPayerAcc(),sydFlow.getPayerAccId(),sydFlow.getPayeeType(),sydFlow.getPayeeId(),sydFlow.getPayeeName(),sydFlow.getPayeeAcc(),sydFlow.getPayeeAccId(),sydFlow.getBillNo(),sydFlow.getPayReceiptType()));
//                        operatorAccountService.updateFrozenByAccId(tran.getTargetAccId(),sumOpServiceChargeMoney);
//                        operatorFlowsMapper.insertSelective(new BusOperatorFlows(0,bill.getOpId(),8,sydFlow.getChannel(),null,null,-sumOpServiceChargeMoney,sydFlow.getAddTime(),sydFlow.getAddBy(),"资金冻结",sydFlow.getBillNo(),sydFlow.getBillId(),sydFlow.getBillDetailId(),"F"+IdUtil.getSnowflakeNextIdStr(),5,sydFlow.getTranStatus(),sydFlow.getPayeeType(),sydFlow.getPayeeId(),sydFlow.getPayeeName(),sydFlow.getPayeeAcc(),sydFlow.getPayeeAccId(),null,null,null,null,null,"",0));
                        operatorAccountService.updateBalanceByAccId(tran.getTargetAccId(),yysSumAll);
                        operatorFlowsMapper.insertSelective(new BusOperatorFlows(1,bill.getOpId(),sydFlow.getBusType(),sydFlow.getChannel(),sydFlow.getBusNo(),sydFlow.getBankNo(),yysSumAll,sydFlow.getAddTime(),sydFlow.getAddBy(),sydFlow.getBusDesc(),sydFlow.getBillNo(),sydFlow.getBillId(),sydFlow.getBillDetailId(),sydFlow.getTranNo(),sydFlow.getTranType(),sydFlow.getTranStatus(),sydFlow.getPayerType(),sydFlow.getPayerId(),sydFlow.getPayerName(),sydFlow.getPayerAcc(),sydFlow.getPayerAccId(),sydFlow.getPayeeType(),sydFlow.getPayeeId(),sydFlow.getPayeeName(),sydFlow.getPayeeAcc(),sydFlow.getPayeeAccId(),sydFlow.getBillNo(),sydFlow.getPayReceiptType()));
                        operatorAccountService.updateFrozenByAccId(tran.getTargetAccId(),yysSumAll);
                        operatorFlowsMapper.insertSelective(new BusOperatorFlows(0,bill.getOpId(),8,sydFlow.getChannel(),null,null,-yysSumAll,sydFlow.getAddTime(),sydFlow.getAddBy(),"资金冻结",sydFlow.getBillNo(),sydFlow.getBillId(),sydFlow.getBillDetailId(),"F"+IdUtil.getSnowflakeNextIdStr(),5,sydFlow.getTranStatus(),sydFlow.getPayeeType(),sydFlow.getPayeeId(),sydFlow.getPayeeName(),sydFlow.getPayeeAcc(),sydFlow.getPayeeAccId(),null,null,null,null,null,"",0));
                        if(sumFhzxServiceChargeMoney > 0) {//孵化中心收益
                            Long channelId = details.get(0).getFhzxChannelId();
                            BusChannel channel = channelMapper.selectById(channelId);
                            BusChannelAccount channelAccount = channelAccountMapper.selectOne(new LambdaQueryWrapper<BusChannelAccount>()
                                .eq(BusChannelAccount::getChannelId,channel.getId())
                                .eq(BusChannelAccount::getIsDefault,1));
                            channelAccountService.updateBalance(channelId, sumFhzxServiceChargeMoney);
                            //operatorFlowsMapper.insertSelective(new BusOperatorFlows(2,bill.getSydId(),12,sydFlow.getChannel(),sydFlow.getBusNo(),sydFlow.getBankNo(),-sumFhzxServiceChargeMoney,sydFlow.getAddTime(),sydFlow.getAddBy(),sydFlow.getBusDesc(),sydFlow.getBillNo(),sydFlow.getBillId(),sydFlow.getBillDetailId(),sydFlow.getTranNo(),sydFlow.getTranType(),sydFlow.getTranStatus(),sydFlow.getPayeeType(),sydFlow.getPayeeId(),sydFlow.getPayeeName(),sydFlow.getPayeeAcc(),sydFlow.getPayeeAccId(),BusRole.AGENT.getId(), channelId,channel.getName(),channelAccount.getBankCard(),channelAccount.getAccId(),sydFlow.getBillNo(),0));
                            channelFlowsMapper.insertSelective(new BusChannelFlows(1,channel.getId(),12,sydFlow.getBusNo(),sumFhzxServiceChargeMoney,sydFlow.getAddTime(),sydFlow.getAddBy(),sydFlow.getBusDesc(),sydFlow.getBillNo(),sydFlow.getBillId(),sydFlow.getBillDetailId(),sydFlow.getTranType(),sydFlow.getPayeeType(),sydFlow.getPayeeId(),sydFlow.getPayeeName(),sydFlow.getPayeeAcc(),sydFlow.getPayeeAccId(),BusRole.AGENT.getId(), channelId,channel.getName(),channelAccount.getBankCard(),channelAccount.getAccId(),""));
                            channelAccountService.updateFrozen(channelId, sumFhzxServiceChargeMoney);
                            channelFlowsMapper.insertSelective(new BusChannelFlows(0,channel.getId(),10,null,-sumFhzxServiceChargeMoney,sydFlow.getAddTime(),sydFlow.getAddBy(),"资金冻结",sydFlow.getBillNo(),sydFlow.getBillId(),sydFlow.getBillDetailId(),5,BusRole.AGENT.getId(), channelId,channel.getName(),channelAccount.getBankCard(),channelAccount.getAccId(),null, null,null,null,null,""));
                        }
                        if(sumZjServiceChargeMoney > 0) {//总监收益
                            Long channelId = details.get(0).getZjChannelId();
                            BusChannel channel = channelMapper.selectById(channelId);
                            BusChannelAccount channelAccount = channelAccountMapper.selectOne(new LambdaQueryWrapper<BusChannelAccount>()
                                .eq(BusChannelAccount::getChannelId,channel.getId())
                                .eq(BusChannelAccount::getIsDefault,1));
                            channelAccountService.updateBalance(channelId, sumZjServiceChargeMoney);
                            //operatorFlowsMapper.insertSelective(new BusOperatorFlows(2,bill.getSydId(),12,sydFlow.getChannel(),sydFlow.getBusNo(),sydFlow.getBankNo(),-sumFhzxServiceChargeMoney,sydFlow.getAddTime(),sydFlow.getAddBy(),sydFlow.getBusDesc(),sydFlow.getBillNo(),sydFlow.getBillId(),sydFlow.getBillDetailId(),sydFlow.getTranNo(),sydFlow.getTranType(),sydFlow.getTranStatus(),sydFlow.getPayeeType(),sydFlow.getPayeeId(),sydFlow.getPayeeName(),sydFlow.getPayeeAcc(),sydFlow.getPayeeAccId(),BusRole.AGENT.getId(), channelId,channel.getName(),channelAccount.getBankCard(),channelAccount.getAccId(),sydFlow.getBillNo(),0));
                            channelFlowsMapper.insertSelective(new BusChannelFlows(1,channel.getId(),12,sydFlow.getBusNo(),sumZjServiceChargeMoney,sydFlow.getAddTime(),sydFlow.getAddBy(),sydFlow.getBusDesc(),sydFlow.getBillNo(),sydFlow.getBillId(),sydFlow.getBillDetailId(),sydFlow.getTranType(),sydFlow.getPayeeType(),sydFlow.getPayeeId(),sydFlow.getPayeeName(),sydFlow.getPayeeAcc(),sydFlow.getPayeeAccId(),BusRole.AGENT.getId(), channelId,channel.getName(),channelAccount.getBankCard(),channelAccount.getAccId(),""));
                            channelAccountService.updateFrozen(channelId, sumZjServiceChargeMoney);
                            channelFlowsMapper.insertSelective(new BusChannelFlows(0,channel.getId(),10,null,-sumZjServiceChargeMoney,sydFlow.getAddTime(),sydFlow.getAddBy(),"资金冻结",sydFlow.getBillNo(),sydFlow.getBillId(),sydFlow.getBillDetailId(),5,BusRole.AGENT.getId(), channelId,channel.getName(),channelAccount.getBankCard(),channelAccount.getAccId(),null, null,null,null,null,""));
                        }
                        if(sumYwyServiceChargeMoney > 0) {//业务员收益
                            Long channelId = details.get(0).getYwyChannelId();
                            BusChannel channel = channelMapper.selectById(channelId);
                            BusChannelAccount channelAccount = channelAccountMapper.selectOne(new LambdaQueryWrapper<BusChannelAccount>()
                                .eq(BusChannelAccount::getChannelId,channel.getId())
                                .eq(BusChannelAccount::getIsDefault,1));
                            channelAccountService.updateBalance(channelId, sumYwyServiceChargeMoney);
                            //operatorFlowsMapper.insertSelective(new BusOperatorFlows(2,bill.getSydId(),12,sydFlow.getChannel(),sydFlow.getBusNo(),sydFlow.getBankNo(),-sumFhzxServiceChargeMoney,sydFlow.getAddTime(),sydFlow.getAddBy(),sydFlow.getBusDesc(),sydFlow.getBillNo(),sydFlow.getBillId(),sydFlow.getBillDetailId(),sydFlow.getTranNo(),sydFlow.getTranType(),sydFlow.getTranStatus(),sydFlow.getPayeeType(),sydFlow.getPayeeId(),sydFlow.getPayeeName(),sydFlow.getPayeeAcc(),sydFlow.getPayeeAccId(),BusRole.AGENT.getId(), channelId,channel.getName(),channelAccount.getBankCard(),channelAccount.getAccId(),sydFlow.getBillNo(),0));
                            channelFlowsMapper.insertSelective(new BusChannelFlows(1,channel.getId(),12,sydFlow.getBusNo(),sumYwyServiceChargeMoney,sydFlow.getAddTime(),sydFlow.getAddBy(),sydFlow.getBusDesc(),sydFlow.getBillNo(),sydFlow.getBillId(),sydFlow.getBillDetailId(),sydFlow.getTranType(),sydFlow.getPayeeType(),sydFlow.getPayeeId(),sydFlow.getPayeeName(),sydFlow.getPayeeAcc(),sydFlow.getPayeeAccId(),BusRole.AGENT.getId(), channelId,channel.getName(),channelAccount.getBankCard(),channelAccount.getAccId(),""));
                            channelAccountService.updateFrozen(channelId, sumYwyServiceChargeMoney);
                            channelFlowsMapper.insertSelective(new BusChannelFlows(0,channel.getId(),10,null,-sumYwyServiceChargeMoney,sydFlow.getAddTime(),sydFlow.getAddBy(),"资金冻结",sydFlow.getBillNo(),sydFlow.getBillId(),sydFlow.getBillDetailId(),5,BusRole.AGENT.getId(), channelId,channel.getName(),channelAccount.getBankCard(),channelAccount.getAccId(),null, null,null,null,null,""));
                        }
                        paymentToPlatform(bill);
                    }else if(tlog.getBusItem() == 3){//服务商转账到平台
                        if(sydAccountService.updateBalanceByAccId(tran.getSourceAccId(),-tran.getAmount()) == 0){
                            throw new ServiceException("服务商转账到平台时，"+bill.getPassage()+"账户余额不足（"+tlog.getBuisId()+"）");
                        }
                        if(sydAccountService.updateFrozenByAccId(tran.getSourceAccId(),-tran.getAmount()) == 0){
                            throw new ServiceException("服务商转账到平台时，"+bill.getPassage()+"账户冻结金额不足（"+tlog.getBuisId()+"）");
                        }
                        if(billDetailMapper.update(new LambdaUpdateWrapper<MerBillDetail>()
                            .eq(MerBillDetail::getBillId, bill.getId())
                            .eq(MerBillDetail::getPayStatus, 3)
                            .eq(MerBillDetail::getPtHalveStatus, 3)
                            .set(MerBillDetail::getPtHalveStatus, 1)) == 0){
                            throw new ServiceException("服务商转账到平台时，非支付中（"+tlog.getBuisId()+"）");
                        }
                        SysSydFlows sydFlow = new SysSydFlows(2,bill.getSydId(),3, bill.getPassage(), bill.getNo(),tran.getTargetBankNo(), -tran.getAmount(), new Date(),bill.getAddBy(),"技术服务费", bill.getNo(), bill.getId(), null, tlog.getTranNo(), 1, tran.getResult().intValue(), tlog.getSourceAccType(), bill.getSydId(), syd.getGsmc(), tran.getSourceCard(), tran.getSourceAccId().longValue(), tlog.getTargetAccType(), 0l, tran.getTargetAccName(), tran.getTargetCard(), tran.getTargetAccId().longValue(), "", 1);
                        List<MerBillDetail> details = billDetailMapper.selectList(new LambdaQueryWrapper<MerBillDetail>().eq(MerBillDetail::getBillId,bill.getId()).eq(MerBillDetail::getPayStatus,3));
                        //服务商分润(分)
                        Long sydServiceChargeMoney = details.stream().mapToLong(MerBillDetail::getSydServiceChargeMoney).sum();
                        sydFlowsMapper.insertSelective(new SysSydFlows(0,bill.getSydId(),6, bill.getPassage(), bill.getNo(),tran.getTargetBankNo(), -sydServiceChargeMoney, new Date(),bill.getAddBy(),"资金冻结", bill.getNo(), bill.getId(), null, "F"+ IdUtil.getSnowflakeNextIdStr(), 5, tran.getResult().intValue(), tlog.getSourceAccType(), bill.getSydId(), syd.getGsmc(), tran.getSourceCard(), tran.getSourceAccId().longValue(), null, null, null, null, null, "", 0));
                        sydFlowsMapper.insertSelective(sydFlow);
                        accountsMapper.updateBalanceByAccId(tran.getTargetAccId(),tran.getAmount());
                        paymentToWorkers(bill);
                    }
                }
                save = new TranLog(tlog.getId(), 2);
            }else if (tran.getResult().intValue() == 3) {//支付失败
                if(tlog.getBusItem() == 4) {//服务商转账到个人B2C
                    String busDesc = "服务商转账到个人B2C";
                    MerBillDetail billDetail = billDetailMapper.selectById(tlog.getBuisId());
                    if (billDetail == null) {
                        throw new ServiceException(busDesc+"失败时，代发批次明细不存在（"+tlog.getBuisId()+"）");
                    }
                    billDetailService.failBillDetail(billDetail.getBillId(),billDetail.getId(),tran.getReason(),0,null);
                    save = new TranLog(tlog.getId(),tran.getResult().intValue(),new Date());
                }else {
                    //记录最后一次失败的时间
                    save = new TranLog(tlog.getId(),null,new Date());
                }
            }
        }
        return save;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean billTransactionCallback(TranLogVo tlog, String callback) {
        if(tlog.getBusItem() == 1){//商户转账到服务商B2B
            billDetailMapper.update(new LambdaUpdateWrapper<MerBillDetail>()
                .eq(MerBillDetail::getBillId,tlog.getBuisId())
                .set(MerBillDetail::getPayReceiptB2b,callback));
            merchantFlowsMapper.update(new LambdaUpdateWrapper<BusMerchantFlows>()
                .eq(BusMerchantFlows::getTranNo,tlog.getTranNo())
                .set(BusMerchantFlows::getPayReceipt,callback));
            sydFlowsMapper.update(new LambdaUpdateWrapper<SysSydFlows>()
                .eq(SysSydFlows::getTranNo,tlog.getTranNo())
                .set(SysSydFlows::getPayReceipt,callback));
        }else if(tlog.getBusItem() == 2){//服务商转账到运营商
            sydFlowsMapper.update(new LambdaUpdateWrapper<SysSydFlows>()
                .eq(SysSydFlows::getTranNo,tlog.getTranNo())
                .set(SysSydFlows::getPayReceipt,callback));
            operatorFlowsMapper.update(new LambdaUpdateWrapper<BusOperatorFlows>()
                .eq(BusOperatorFlows::getTranNo,tlog.getTranNo())
                .set(BusOperatorFlows::getPayReceipt,callback));
        }else if(tlog.getBusItem() == 3){//服务商转账到平台
            sydFlowsMapper.update(new LambdaUpdateWrapper<SysSydFlows>()
                .eq(SysSydFlows::getTranNo,tlog.getTranNo())
                .set(SysSydFlows::getPayReceipt,callback));
        }else if(tlog.getBusItem() == 4){//服务商转账到个人B2C
            billDetailMapper.update(new LambdaUpdateWrapper<MerBillDetail>()
                .eq(MerBillDetail::getId,tlog.getBuisId())
                .set(MerBillDetail::getPayReceipt,callback));
            sydFlowsMapper.update(new LambdaUpdateWrapper<SysSydFlows>()
                .eq(SysSydFlows::getTranNo,tlog.getTranNo())
                .set(SysSydFlows::getPayReceipt,callback));
        }
        return true;
    }
}
