// +---------------------------------------------------------------------- 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; /** * 构造函数 * @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 => '其他', ]; /* * 开发者提现未处理列表 * @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); 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; $add['status'] = ($promote['auto_review_withdraw_status'] == 1) ? 1 : 0; $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; } 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, interval_closed_status') ->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; if ($promoteGameRatio['interval_closed_status'] == 1) { foreach ($turnoverRatios as $turnoverRatio) { if ($sumAmount >= $turnoverRatio['turnover']) { $ratio = $turnoverRatio['ratio']; break; } } } else { foreach ($turnoverRatios as $turnoverRatio) { 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; $add['status'] = ($promote['auto_review_withdraw_status'] == 1) ? 1 : 0; $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; } 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, interval_closed_status') ->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; if ($promoteGameRatio['interval_closed_status'] == 1) { foreach ($turnoverRatios as $turnoverRatio) { if ($sumAmount >= $turnoverRatio['turnover']) { $ratio = $turnoverRatio['ratio']; break; } } } else { foreach ($turnoverRatios as $turnoverRatio) { 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; $add['status'] = ($promote['auto_review_withdraw_status'] == 1) ? 1 : 0; $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;//补点失败 } return 1; } public function getRecoupAmount($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, interval_closed_status') ->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; if ($promoteGameRatio['interval_closed_status'] == 1) { foreach ($turnoverRatios as $turnoverRatio) { if ($sumAmount >= $turnoverRatio['turnover']) { $ratio = $turnoverRatio['ratio']; break; } } } else { foreach ($turnoverRatios as $turnoverRatio) { 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 = D('promote_game_ratio')->field('game_id, ratio, turnover_ratio, begin_time, end_time, interval_closed_status') ->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; if ($promoteGameRatio['interval_closed_status'] == 1) { foreach ($turnoverRatios as $turnoverRatio) { if ($sumAmount >= $turnoverRatio['turnover']) { $ratio = $turnoverRatio['ratio']; break; } } } else { foreach ($turnoverRatios as $turnoverRatio) { 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; } }