<?php
// +----------------------------------------------------------------------
// | OneThink [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013 http://www.onethink.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: 麦当苗儿 <zuojiazi@vip.qq.com> <http://www.zjzit.cn>
// +----------------------------------------------------------------------

namespace Admin\Model;
use Think\Model;

/**
 * 分类模型
 */
class WithdrawModel extends Model{

    //操作人类型
    const OP_TYPE_PROMOTE = 1;
    const OP_TYPE_ADMIN = 2;
    const OP_TYPE_AUTO = 3;

    //结算类型
    const SETTLEMENT_TYPE_WEEK = 1;
    const SETTLEMENT_TYPE_MONTH = 2;
    const SETTLEMENT_TYPE_RECOUP = 3;
    const SETTLEMENT_TYPE_OTHER = 9;

    //审核模式
    const REVIEW_TYPE_MANUAL = 1;
    const REVIEW_TYPE_AUTO = 2;

	/**
     * 构造函数
     * @param string $name 模型名称
     * @param string $tablePrefix 表前缀
     * @param mixed $connection 数据库连接信息
     */
    public function __construct($name = '', $tablePrefix = '', $connection = '') {
        /* 设置默认的表前缀 */
        $this->tablePrefix ='tab_';
        /* 执行构造方法 */
        parent::__construct($name, $tablePrefix, $connection);
    }
		
    public static $opTypeList = [
        self::OP_TYPE_PROMOTE => '推广员',
        self::OP_TYPE_ADMIN => '管理员',
        self::OP_TYPE_AUTO => '自动',
    ];

    public static $settlementTypeList = [
        self::SETTLEMENT_TYPE_WEEK => '周结',
        self::SETTLEMENT_TYPE_MONTH => '月结',
        self::SETTLEMENT_TYPE_RECOUP => '补点',
        self::SETTLEMENT_TYPE_OTHER => '其他',
    ];

    public static $reviewTypeList = [
        self::REVIEW_TYPE_MANUAL => '人工审核',
        self::REVIEW_TYPE_AUTO => '自动审核',
    ];
	
	/*
	 * 开发者提现未处理列表
	 * @return array   检测结果数据集
	 * @author 鹿文学
	 */
	public function checkDeveloperWithdraw() {
		
		$list = $this->field('tab_withdraw.id,tab_withdraw.settlement_number,tab_developers.account')
		
					->join('tab_developers on (tab_withdraw.developers = tab_developers.id) ','left')
					
					->where(array('tab_withdraw.status'=>0,'tab_withdraw.developers'=>array('gt',0)))->select();
		$type=200;
		if ($list[0]) {
			
			$list = D('check')->dealWithCheckList($type,$list);
			
			if (empty($list[0])) {return '';}
			
			foreach ($list as $k => $v) {
				$data[$k]['info'] = '开发者:'.$v['account'].'申请提现,提现状态:未审核';
				$data[$k]['type'] = $type;
				$data[$k]['url'] = U('Query/cp_withdraw',array('settlement_number'=>$v['settlement_number']));
				$data[$k]['create_time'] = time();
				$data[$k]['status']=0;
				$data[$k]['position'] = $v['id'];
			}
			return $data;
		}else {
			D('check')->dealWithCheckListOnNull($type);
			return '';
		}
		
	}
	
	
	/*
	 * 推广员提现未处理列表
	 * @return array   检测结果数据集
	 * @author 鹿文学
	 */
	public function checkPromoteWithdraw() {
		
		$list = $this->field('tab_withdraw.id,tab_withdraw.settlement_number,tab_promote.account')
		
					->join('tab_promote on (tab_withdraw.promote_id = tab_promote.id) ','left')
					
					->where(array('tab_withdraw.status'=>0,'tab_withdraw.promote_id'=>array('gt',0)))->select();
		$type=201;
		if ($list[0]) {
			
			$list = D('check')->dealWithCheckList($type,$list);
			
			if (empty($list[0])) {return '';}
			
			foreach ($list as $k => $v) {
				$data[$k]['info'] = '推广员:'.$v['account'].'申请提现,提现状态:未审核';
				$data[$k]['type'] = $type;
				$data[$k]['url'] = U('Query/withdraw',array('settlement_number'=>$v['settlement_number']));
				$data[$k]['create_time'] = time();
				$data[$k]['status']=0;
				$data[$k]['position'] = $v['id'];
			}
			return $data;
		}else {
			D('check')->dealWithCheckListOnNull($type);
			return '';
		}
		
	}

    //生成提现单号 $type 1-周结 2-月结 3-补点
    public function produceWithdrawNumber($type = 1)
    {
        $prefix = 'WD_';
        $number = '';
        switch ($type) {
            case 1:
                $prefix = "{$prefix}W_";
                break;
            case 2:
                $prefix = "{$prefix}M_";
                break;
            case 3:
                $prefix = "{$prefix}R_";
                break;
        }
        while (true) {
            $randomNum = rand(10, 99);
            $number = $prefix . time() . $randomNum;
            $map['widthdraw_number'] = $number;
            $res = $this->where($map)->getField('id');
            if (!$res) {
                break;
            }
        }
        return $number;
    }

    //周结
    public function promoteWithdrawWeeklyByPromote($promote, $initial = false, $data = [])
    {
        $promoteIds = $this->getPromoteChildren($promote);
        $settlementType = $promote['settlement_type'];
        $settlementBeginTime = $data['begin_time'] ?? strtotime(date('Y-m-d', strtotime('-7 day', time())));
        $settlementEndTime = $data['end_time'] ?? strtotime(date('Y-m-d')) - 1;

        if ($initial) {
            $settlementType = 9;
            $settlementBeginTime = 0;
        }

        $spendMap['pay_status'] = 1;
        $spendMap['selle_status'] = 0;
        $spendMap['promote_id'] = ['in', $promoteIds];
        $spendMap['pay_time'] = ['between', [$settlementBeginTime, $settlementEndTime]];
        $spendModel = M('spend', 'tab_');

        $balance = $spendModel->field("sum(if(selle_ratio > 0, pay_amount * selle_ratio, 0)) as balance")
            ->where($spendMap)
            ->find()['balance'];
        $balance = $balance ?? 0;
        $balance = bcdiv($balance, 100, 2);

//        addOperationLog(['op_type'=>1,'key'=>$promote['account'].$data['begin_time'].$data['end_time'].$balance,'op_name'=>'推广结算提现','url'=>U('Query/settlement'),'menu'=>'推广员-结算管理-推广结算-推广结算提现']);


        if ($balance < 100) {
            return -2;//余额不足
        }

        if ($initial === false) {
            $beginTime = date('Y-m-d', $settlementBeginTime);
        } else {
            $beginTime = '初始';
        }
        $endTime = date('Y-m-d', $settlementEndTime);
        $gameRatios = $this->getGameRatio($spendMap, $beginTime, $endTime);
        $gameRatios = $gameRatios ? json_encode($gameRatios) : '';

        $thisTime = time();
        $add['sum_money'] = $balance;
        $add['promote_id'] = $promote['id'];
        $add['promote_account'] = $promote['account'];
        $add['create_time'] = $thisTime;
        if ($promote['auto_review_withdraw_status'] == 1) {
            $add['status'] = 1;
            $add['review_type'] = 2;
        } else {
            $add['status'] = 0;
            $add['review_type'] = 1;
        }
        $add['widthdraw_number'] = D('withdraw')->produceWithdrawNumber(1);
        $add['settlement_begin_time'] = $settlementBeginTime;
        $add['settlement_end_time'] = $settlementEndTime;
        $add['spend_ids'] = '';
        $add['op_id'] = $data['op_id'] ?? 0;
        $add['op_type'] = $data['op_type'] ?? 3;
        $add['last_op_id'] = $add['op_id'];
        $add['last_op_type'] = $add['op_type'];
        $add['settlement_type'] = $settlementType;
        $add['game_ratio'] = $gameRatios;

        M()->startTrans();//开启事物
        $withdrawId = D('withdraw')->add($add);
        if (!$withdrawId) {
            M()->rollback();//事物回滚
            return 0;//提现失败
        }

        $save['selle_status'] = 1;
        $save['selle_time'] = $thisTime;
        $save['withdraw_id'] = $withdrawId;
        $res = $spendModel->where($spendMap)->save($save);
        if ($res === false) {
            D('withdraw')->delete($withdrawId);
            M()->rollback();//事物回滚
            return -1;
        }

        addOperationLog(['op_type'=>1,'key'=>$promote['account'].'/'.date('YmdHis',$data['begin_time']).'/'.date('YmdHis',$data['end_time']).'/'.$balance,'op_name'=>'推广结算提现','url'=>U('Query/settlement'),'menu'=>'推广员-结算管理-推广结算-推广结算提现']);

        M()->commit();//事物提交
        return 1;
    }

//月结
    public function promoteWithdrawPerMonthByPromote($promote, $initial = false, $data = [])
    {
        $promoteIds = $this->getPromoteChildren($promote);
        $settlementType = $promote['settlement_type'];
        $settlementBeginTime = $data['begin_time'] ?? strtotime(date('Y-m', strtotime('-1 month', time())));
        $settlementEndTime = $data['end_time'] ?? strtotime(date('Y-m')) - 1;

        if ($initial) {
            $settlementType = 9;
            $settlementBeginTime = 0;
            $beginTime = '初始';
        } else {
            $beginTime = date('Y-m-d', $settlementBeginTime);
        }

        $endTime = date('Y-m-d', $settlementEndTime);
        $spendMap['pay_status'] = 1;
        $spendMap['selle_status'] = 0;
        $spendMap['promote_id'] = ['in', $promoteIds];
        $spendMap['pay_time'] = ['between', [$settlementBeginTime, $settlementEndTime]];
        $spendWhere = $spendMap;
        $spendModel = M('spend', 'tab_');

        $promoteGameRatioMap['status'] = 1;
        $promoteGameRatioMap['promote_id'] = $promote['id'];
        $promoteGameRatios = D('promote_game_ratio')->field('game_id, ratio, turnover_ratio, begin_time, end_time')
            ->where($promoteGameRatioMap)
            ->order('update_time desc')
            ->select();

        $gameRatios = $this->getGameRatio($spendMap, $beginTime, $endTime);

        if (empty($promoteGameRatios) || $initial) {
            $balance = $spendModel->field("sum(if(selle_ratio > 0, pay_amount * selle_ratio, 0)) as balance")
                ->where($spendMap)
                ->find()['balance'];
            $balance = $balance ?? 0;
        } else {
            $balance = 0;
            $notInGameIds = [-1];
            foreach ($promoteGameRatios as $promoteGameRatio) {
                $spendWhere['game_id'] = $promoteGameRatio['game_id'];
                if (!empty($promoteGameRatio['turnover_ratio']) && $promoteGameRatio['begin_time'] <= $settlementBeginTime && (empty($promoteGameRatio['end_time']) || $promoteGameRatio['end_time'] >= $settlementEndTime)) {
                    $notInGameIds[] = $promoteGameRatio['game_id'];
                    $ratio = $promoteGameRatio['ratio'];
                    $promoteGameRatio['turnover_ratio'] = json_decode($promoteGameRatio['turnover_ratio'], true);
                    $turnoverRatios = array_reverse($promoteGameRatio['turnover_ratio']);
                    $sumAmount = $spendModel->field("sum(pay_amount) as sum_amount")
                        ->where($spendWhere)
                        ->find()['sum_amount'];
                    $sumAmount = $sumAmount ?? 0;
                    foreach ($turnoverRatios as $turnoverRatio) {
                        if (empty($turnoverRatio['instanceof']) || $turnoverRatio['instanceof'] == 1) {
                            if ($sumAmount >= $turnoverRatio['turnover']) {
                                $ratio = $turnoverRatio['ratio'];
                                break;
                            }
                        } else {
                            if ($sumAmount > $turnoverRatio['turnover']) {
                                $ratio = $turnoverRatio['ratio'];
                                break;
                            }
                        }
                    }

                    $thisBalance = $spendModel->field("sum(pay_amount * {$ratio}) as balance")
                        ->where($spendWhere)
                        ->find()['balance'];
                    $thisBalance = $thisBalance ?? 0;
                    $balance = bcadd($balance, $thisBalance, 2);

                    $gameRatios[$promoteGameRatio['game_id']] = [];
                    $gameRatios[$promoteGameRatio['game_id']][] = [
                        'selle_ratio' => $ratio,
                        'default_ratio' => $promoteGameRatio['ratio'],
                        'sum_amount' => $sumAmount,
                        'begin_time' => $beginTime,
                        'end_time' => $endTime,
                    ];
                }
            }

            $spendWhere['game_id'] = ['not in', $notInGameIds];
            $otherBalance = $spendModel->field("sum(if(selle_ratio > 0, pay_amount * selle_ratio, 0)) as balance")
                ->where($spendWhere)
                ->find()['balance'];
            $otherBalance = $otherBalance ?? 0;
            $balance = bcadd($balance, $otherBalance, 2);
        }

        $balance = bcdiv($balance, 100, 2);
        if ($balance < 100) {
            return -2;//余额不足
        }

        $gameRatios = $gameRatios ? json_encode($gameRatios) : '';

        $thisTime = time();
        $add['sum_money'] = $balance;
        $add['promote_id'] = $promote['id'];
        $add['promote_account'] = $promote['account'];
        $add['create_time'] = $thisTime;
        if ($promote['auto_review_withdraw_status'] == 1) {
            $add['status'] = 1;
            $add['review_type'] = 2;
        } else {
            $add['status'] = 0;
            $add['review_type'] = 1;
        }
        $add['widthdraw_number'] = D('withdraw')->produceWithdrawNumber(2);
        $add['settlement_begin_time'] = $settlementBeginTime;
        $add['settlement_end_time'] = $settlementEndTime;
        $add['spend_ids'] = '';
        $add['op_id'] = $data['op_id'] ?? 0;
        $add['op_type'] = $data['op_type'] ?? 3;
        $add['last_op_id'] = $add['op_id'];
        $add['last_op_type'] = $add['op_type'];
        $add['settlement_type'] = $settlementType;
        $add['game_ratio'] = $gameRatios;

        M()->startTrans();//开启事物
        $withdrawId = D('withdraw')->add($add);
        if (!$withdrawId) {
            M()->rollback();//事物回滚
            return 0;//提现失败
        }

        $save['selle_status'] = 1;
        $save['selle_time'] = $thisTime;
        $save['withdraw_id'] = $withdrawId;
        $res = $spendModel->where($spendMap)->save($save);
        if ($res === false) {
            D('withdraw')->delete($withdrawId);
            M()->rollback();//事物回滚
            return -1;
        }

        addOperationLog(['op_type'=>1,'key'=>$promote['account'].'/'.date('YmdHis',$data['begin_time']).'/'.date('YmdHis',$data['end_time']).'/'.$balance,'op_name'=>'推广结算提现','url'=>U('Query/settlement'),'menu'=>'推广员-结算管理-推广结算-推广结算提现']);

        M()->commit();//事物提交
        return 1;
    }

    //补点
    public function promoteWithdrawRecoupByPromote($promote, $data = [])
    {
        $promoteGameRatioMap['status'] = 1;
        $promoteGameRatioMap['promote_id'] = $promote['id'];
        $promoteGameRatios = D('promote_game_ratio')->field('game_id, ratio, turnover_ratio, begin_time, end_time')
            ->where($promoteGameRatioMap)
            ->order('update_time desc')
            ->select();
        if (empty($promoteGameRatios)) {
            return -3;
        }

        $promoteIds = $this->getPromoteChildren($promote);
        $settlementType = 3;
        $settlementBeginTime = $data['begin_time'] ?? strtotime(date('Y-m', strtotime('-1 month', time())));
        $settlementEndTime = $data['end_time'] ?? strtotime(date('Y-m')) - 1;

        $withdrawMap['promote_id'] = $promote['id'];
        $withdrawMap['status'] = ['neq', -2];
        $withdrawMap['settlement_begin_time'] = $settlementBeginTime;
        $withdrawMap['settlement_end_time'] = $settlementEndTime;
        $withdraw = D('withdraw')->where($withdrawMap)->find();
        if (!empty($withdraw)) {
            return -4;
        }

        $spendMap['pay_status'] = 1;
        $spendMap['promote_id'] = ['in', $promoteIds];
        $spendMap['pay_time'] = ['between', [$settlementBeginTime, $settlementEndTime]];
        $spendModel = M('spend', 'tab_');

        $balance = 0;
        $gameRatios = [];
        foreach ($promoteGameRatios as $promoteGameRatio) {
            if (!empty($promoteGameRatio['turnover_ratio']) && $promoteGameRatio['begin_time'] <= $settlementBeginTime && (empty($promoteGameRatio['end_time']) || $promoteGameRatio['end_time'] >= $settlementEndTime)) {
                $spendMap['game_id'] = $promoteGameRatio['game_id'];
                $promoteGameRatio['turnover_ratio'] = json_decode($promoteGameRatio['turnover_ratio'], true);
                $turnoverRatios = array_reverse($promoteGameRatio['turnover_ratio']);
                $sumAmount = $spendModel->field("sum(pay_amount) as sum_amount")
                    ->where($spendMap)
                    ->find()['sum_amount'];
                $sumAmount = $sumAmount ?? 0;
                $ratio = 0;
                foreach ($turnoverRatios as $turnoverRatio) {
                    if (empty($turnoverRatio['instanceof']) || $turnoverRatio['instanceof'] == 1) {
                        if ($sumAmount >= $turnoverRatio['turnover']) {
                            $ratio = $turnoverRatio['ratio'];
                            break;
                        }
                    } else {
                        if ($sumAmount > $turnoverRatio['turnover']) {
                            $ratio = $turnoverRatio['ratio'];
                            break;
                        }
                    }
                }

                if ($ratio > 0) {
                    $ratio = bcsub($ratio, $promoteGameRatio['ratio'], 2);
                    $thisBalance = bcdiv(bcmul($sumAmount, $ratio, 2), 100, 2);
                    $balance = bcadd($balance, $thisBalance, 2);

                    $gameRatios[$promoteGameRatio['game_id']][] = [
                        'selle_ratio' => $ratio,
                        'default_ratio' => $promoteGameRatio['ratio'],
                        'sum_amount' => $sumAmount,
                        'begin_time' => date('Y-m-d', $settlementBeginTime),
                        'end_time' => date('Y-m-d', $settlementEndTime),
                    ];
                }
            }
        }

        if ($balance == 0) {
            return -2;//无余额
        }

        $gameRatios = $gameRatios ? json_encode($gameRatios) : '';

        $thisTime = time();
        $add['sum_money'] = $balance;
        $add['promote_id'] = $promote['id'];
        $add['promote_account'] = $promote['account'];
        $add['create_time'] = $thisTime;
        if ($promote['auto_review_withdraw_status'] == 1) {
            $add['status'] = 1;
            $add['review_type'] = 2;
        } else {
            $add['status'] = 0;
            $add['review_type'] = 1;
        }
        $add['widthdraw_number'] = D('withdraw')->produceWithdrawNumber(3);
        $add['settlement_begin_time'] = $settlementBeginTime;
        $add['settlement_end_time'] = $settlementEndTime;
        $add['spend_ids'] = '';
        $add['op_id'] = $data['op_id'] ?? 0;
        $add['op_type'] = $data['op_type'] ?? 3;
        $add['last_op_id'] = $add['op_id'];
        $add['last_op_type'] = $add['op_type'];
        $add['settlement_type'] = $settlementType;
        $add['game_ratio'] = $gameRatios;

        $withdrawId = D('withdraw')->add($add);
        if (!$withdrawId) {
            return 0;//补点失败
        }
        addOperationLog(['op_type'=>1,'key'=>$promote['account'].'/'.date('YmdHis',$data['begin_time']).'/'.date('YmdHis',$data['end_time']).'/'.$balance,'op_name'=>'推广结算提现','url'=>U('Query/settlement'),'menu'=>'推广员-结算管理-推广结算-推广结算提现']);
        return 1;
    }

    public function getRecoupAmount($promote, $data = [])
    {
        $promoteGameRatioMap['status'] = 1;
        $promoteGameRatioMap['promote_id'] = $promote['id'];
        $promoteGameRatios = M('promote_game_ratio', 'tab_')->field('game_id, ratio, turnover_ratio, begin_time, end_time')
            ->where($promoteGameRatioMap)
            ->order('update_time desc')
            ->select();
        if (empty($promoteGameRatios)) {
            return 0;
        }

        $promoteIds = $this->getPromoteChildren($promote);
        $settlementBeginTime = $data['begin_time'] ?? strtotime(date('Y-m', strtotime('-1 month', time())));
        $settlementEndTime = $data['end_time'] ?? strtotime(date('Y-m')) - 1;

        $spendMap['pay_status'] = 1;
        $spendMap['promote_id'] = ['in', $promoteIds];
        $spendMap['pay_time'] = ['between', [$settlementBeginTime, $settlementEndTime]];
        $spendModel = M('spend', 'tab_');

        $balance = 0;
        foreach ($promoteGameRatios as $promoteGameRatio) {
            if (!empty($promoteGameRatio['turnover_ratio']) && $promoteGameRatio['begin_time'] <= $settlementBeginTime && (empty($promoteGameRatio['end_time']) || $promoteGameRatio['end_time'] >= $settlementEndTime)) {
                $spendMap['game_id'] = $promoteGameRatio['game_id'];
                $promoteGameRatio['turnover_ratio'] = json_decode($promoteGameRatio['turnover_ratio'], true);
                $turnoverRatios = array_reverse($promoteGameRatio['turnover_ratio']);
                $sumAmount = $spendModel->field("sum(pay_amount) as sum_amount")
                    ->where($spendMap)
                    ->find()['sum_amount'];
                $sumAmount = $sumAmount ?? 0;
                $ratio = 0;
                foreach ($turnoverRatios as $turnoverRatio) {
                    if (empty($turnoverRatio['instanceof']) || $turnoverRatio['instanceof'] == 1) {
                        if ($sumAmount >= $turnoverRatio['turnover']) {
                            $ratio = $turnoverRatio['ratio'];
                            break;
                        }
                    } else {
                        if ($sumAmount > $turnoverRatio['turnover']) {
                            $ratio = $turnoverRatio['ratio'];
                            break;
                        }
                    }
                }

                if ($ratio > 0) {
                    $ratio = bcsub($ratio, $promoteGameRatio['ratio'], 2);
                    $thisBalance = bcdiv(bcmul($sumAmount, $ratio, 2), 100, 2);
                    $balance = bcadd($balance, $thisBalance, 2);
                }
            }
        }

        return $balance;
    }

    public function getMonthAmount($promote, $data = [])
    {
        $promoteIds = $this->getPromoteChildren($promote);
        $settlementBeginTime = $data['begin_time'] ?? strtotime(date('Y-m', strtotime('-1 month', time())));
        $settlementEndTime = $data['end_time'] ?? strtotime(date('Y-m')) - 1;

        $spendMap['pay_status'] = 1;
        $spendMap['selle_status'] = 0;
        $spendMap['promote_id'] = ['in', $promoteIds];
        $spendMap['pay_time'] = ['between', [$settlementBeginTime, $settlementEndTime]];
        $spendWhere = $spendMap;
        $spendModel = M('spend', 'tab_');

        $promoteGameRatioMap['status'] = 1;
        $promoteGameRatioMap['promote_id'] = $promote['id'];
        $promoteGameRatios = M('promote_game_ratio', 'tab_')->field('game_id, ratio, turnover_ratio, begin_time, end_time')
            ->where($promoteGameRatioMap)
            ->order('update_time desc')
            ->select();

        if (empty($promoteGameRatios)) {
            $balance = $spendModel->field("sum(if(selle_ratio > 0, pay_amount * selle_ratio, 0)) as balance")
                ->where($spendMap)
                ->find()['balance'];
            $balance = $balance ?? 0;
        } else {
            $balance = 0;
            $notInGameIds = [-1];
            foreach ($promoteGameRatios as $promoteGameRatio) {
                $spendWhere['game_id'] = $promoteGameRatio['game_id'];
                if (!empty($promoteGameRatio['turnover_ratio']) && $promoteGameRatio['begin_time'] <= $settlementBeginTime && (empty($promoteGameRatio['end_time']) || $promoteGameRatio['end_time'] >= $settlementEndTime)) {
                    $notInGameIds[] = $promoteGameRatio['game_id'];
                    $ratio = $promoteGameRatio['ratio'];
                    $promoteGameRatio['turnover_ratio'] = json_decode($promoteGameRatio['turnover_ratio'], true);
                    $turnoverRatios = array_reverse($promoteGameRatio['turnover_ratio']);
                    $sumAmount = $spendModel->field("sum(pay_amount) as sum_amount")
                        ->where($spendWhere)
                        ->find()['sum_amount'];
                    $sumAmount = $sumAmount ?? 0;
                    foreach ($turnoverRatios as $turnoverRatio) {
                        if (empty($turnoverRatio['instanceof']) || $turnoverRatio['instanceof'] == 1) {
                            if ($sumAmount >= $turnoverRatio['turnover']) {
                                $ratio = $turnoverRatio['ratio'];
                                break;
                            }
                        } else {
                            if ($sumAmount > $turnoverRatio['turnover']) {
                                $ratio = $turnoverRatio['ratio'];
                                break;
                            }
                        }
                    }

                    $thisBalance = $spendModel->field("sum(pay_amount * {$ratio}) as balance")
                        ->where($spendWhere)
                        ->find()['balance'];
                    $thisBalance = $thisBalance ?? 0;
                    $balance = bcadd($balance, $thisBalance, 2);
                }
            }

            $spendWhere['game_id'] = ['not in', $notInGameIds];
            $otherBalance = $spendModel->field("sum(if(selle_ratio > 0, pay_amount * selle_ratio, 0)) as balance")
                ->where($spendWhere)
                ->find()['balance'];
            $otherBalance = $otherBalance ?? 0;
            $balance = bcadd($balance, $otherBalance, 2);
        }

        $balance = bcdiv($balance, 100, 2);
        return $balance;
    }

    private function getSpendMessageByGame($map)
    {
        $field = 'game_id, selle_ratio, sum(pay_amount) as sum_amount, pay_time';
        $spendModel = M('spend', 'tab_');
        $gameSpendRatios = $spendModel->field($field)
            ->where($map)
            ->group('game_id, selle_ratio')
            ->order('game_id asc, pay_time asc')
            ->select();

        return $gameSpendRatios;
    }

    private function getPromoteChildren($promote) {
        $promoteMap['chain'] = ['like', "{$promote['chain']}{$promote['id']}/%"];
        $promoteIds = M('promote', 'tab_')->where($promoteMap)->getField('id', true);
        $promoteIds[] = $promote['id'];

        return $promoteIds;
    }

    private function getGameRatio($map, $beginTime, $endTime)
    {
        $gameRatios = [];
        $gameSpendRatios = $this->getSpendMessageByGame($map);
        foreach ($gameSpendRatios as $gameSpendRatio) {
            $gameRatios[$gameSpendRatio['game_id']][] = [
                'selle_ratio' => $gameSpendRatio['selle_ratio'],
                'sum_amount' => $gameSpendRatio['sum_amount'],
                'begin_time' => date('Y-m-d', $gameSpendRatio['pay_time']),
                'end_time' => date('Y-m-d', $gameSpendRatio['pay_time']),
            ];
        }
        foreach ($gameRatios as $key => $gameRatio) {
            $gameRatios[$key][0]['begin_time'] = $beginTime;
            $gameRatios[$key][count($gameRatio) - 1]['end_time'] = $endTime;
            if (count($gameRatio) > 1) {
                foreach ($gameRatios[$key] as $childKey => $childList) {
                    $gameRatios[$key][$childKey]['end_time'] = isset($gameRatios[$key][$childKey + 1]) ? $gameRatios[$key][$childKey + 1]['begin_time'] : $gameRatios[$key][$childKey]['end_time'];
                }
            }
        }

        return $gameRatios;
    }
}