mDirty = false; $this->mRates = []; foreach ($rates as $key => $val) { $val = intval(100 * $val + 0.5); if($val > 0) { $this->mRates[$key] = $val / 100; } } krsort($this->mRates); } public function add_bonuses($items) { foreach ($items as $item) { $bonus = \bonus\user_bonus::create_by_param($item); $rate = $bonus->bonus_rate(); $amount = intval($bonus->remain_amount() * 100 + 0.5); if($amount <= 0) continue; $this->mDirty = true; if(isset($this->mRates[$rate]) == false) { $this->mRates[$rate] = 0.00; } $this->mRates[$rate] += $bonus->remain_amount(); } krsort($this->mRates); } public function resort() { krsort($this->mRates); } public function is_enough(&$rate,$amount) { $amount = intval($amount * 100 + 0.5); foreach ($this->mRates as $key => $val) { $val = intval($val * 100 + 0.5); if($rate == -1) { if($val >= $amount) { $rate = $key; return true; } } else { if($rate == $key) { $rate = $key; if($val >= $amount) { return true; } else { return false; } } } } return false; } public function with_hold($rate,$amount) { if(isset($this->mRates[$rate])) { $this->mDirty = true; $this->mRates[$rate] = $this->mRates[$rate] - $amount; } } public function find_rate($amount) { if(empty($this->mRates)) return false; $rates = $this->mRates; ksort($rates); foreach ($rates as $rate => $money) { $money = intval($money * 100 + 0.5); $amount = intval($amount * 100 + 0.5); if($amount >= $money) { return array('rate' => $rate,'amount' => $money / 100); } else { return array('rate' => $rate,'amount' => $amount / 100); } } return false; } public function format() { $result = []; foreach ($this->mRates as $key => $val) { $val = intval($val * 100 + 0.5); if($val > 0) { $result[$key] = $val / 100; } } return $result; } public function total() { $total = 0.00; foreach ($this->mRates as $key => $amount) { $total += $amount; } return $total; } public function dirty() { return $this->mDirty; } public function clean() { $this->mDirty = false; } public function calc_rates($amount) { $rates = []; $left = intval($amount * 100 + 0.5); foreach ($this->mRates as $rate => $total) { if($left <= 0) break; if($rate > 100) continue; $total = intval($total * 100 + 0.5); if($total <= 0) { continue; } else { if($total >= $left) { $rates[$rate] = $left / 100; $left = 0; } else { $rates[$rate] = $total / 100; $left -= $total; } } } return $rates; } public function calc_money($price,&$rates) { $rates = []; $disc = 0; $left = intval($price * 100 + 0.5); foreach ($this->mRates as $rate => $total) { if($left <= 0) break; if($rate > 100) continue; $total = intval($total * 100 + 0.5); if($total <= 0) { continue; } else { $max_rate = intval($left * $rate / 100 + 0.5); if($total >= $max_rate) { $disc += $max_rate; $left = 0; $rates[$rate] = $max_rate / 100; } else { $disc += $total; $left -= intval($total * 100 / $rate + 0.5); $rates[$rate] = $total / 100; } } } $cur_price = intval($price * 100 + 0.5) - $disc; return $cur_price / 100; } public function calc_price($price,&$rates) { $cur_price = intval($this->calc_money($price,$rates) * 100 + 0.5); return $cur_price / 100; } static function scale() { return (100 - self::PRED_RATE) / 100; } } class predeposit_helper { private $model_pd; private $member_id; private $mRates; private $mBonusState; private $mRateVersion; //用来记录,红包过期带来的红包变化 public function __construct($member_id) { $this->model_pd = Model('predeposit'); $this->member_id = $member_id; $pd_array = Model('member')->getMemberPdInfo($this->member_id); $this->mRateVersion = intval($pd_array['rate_version']); $this->init_rate(); } private function init_rate() { $fUpdate = false; if(isset($_SESSION['bonus_rate_version']) == false) { $fUpdate = true; } else { $version = $_SESSION['bonus_rate_version']; if($version != $this->mRateVersion) { $fUpdate = true; } else { if(isset($_SESSION['bonus_rate']) && isset($_SESSION['bonus_state'])) { $this->mRates = new RateMoney($_SESSION['bonus_rate']); $this->mBonusState = $_SESSION['bonus_state']; } else { $fUpdate = true; } } } if($fUpdate || $this->need_update()) { $mod_bonus = Model('user_bonus'); $this->mRates = new RateMoney(array()); $items = $mod_bonus->getUsableBonus($this->member_id); $this->mRates->add_bonuses($items); $bonus_rate = $this->mRates->format(); $this->mBonusState = []; $querys = array('usable','expiring','used','expired'); foreach ($querys as $state) { $cond = $this->query_cond($state); if($state == 'used') { $sum = $mod_bonus->getSum($cond,'bonus_value'); } else { $sum = $mod_bonus->getSum($cond); } $this->mBonusState[$state] = doubleval($sum); } $this->write_rates($this->mBonusState,$bonus_rate); $this->mRates->clean(); $_SESSION['bonus_update_time'] = time(); } } private function need_update() { if(!isset($_SESSION['bonus_update_time'])) return true; $time = intval($_SESSION['bonus_update_time']); if(time() - $time > 86400) { return true; } else { return false; } } public function __destruct() { if($this->mRates != null && $this->mRates->dirty()) { $this->del_rates(); } } public function bonus_rate() { return $this->mRates; } static public function order_cash($goods_amount, &$rates) { if(isset($_SESSION['bonus_rate']) == false) { $pred = new predeposit_helper($_SESSION['member_id']); $bonus_rate = $pred->bonus_rate(); } else { $bonus_rate = new RateMoney($_SESSION['bonus_rate']); } return $bonus_rate->calc_money($goods_amount,$rates); } static public function login_bonus_price($goods_price, &$rates) { if(session_helper::isLogin()) { if(isset($_SESSION['bonus_rate']) == false) { $pred = new predeposit_helper($_SESSION['member_id']); $bonus_rate = $pred->bonus_rate(); } else { $bonus_rate = new RateMoney($_SESSION['bonus_rate']); } return $bonus_rate->calc_price($goods_price,$rates); } else { return ($goods_price); } } static public function unlogin_bonus_price($goods_price,$rate_moneys,&$rates) { if(!empty($rate_moneys)) { $bonus_rate = new RateMoney($rate_moneys); return $bonus_rate->calc_price($goods_price,$rates); } else { return $goods_price; } } static public function discount_gap($bonus_price,$goods_price) { $bonus_price = intval($bonus_price* 100 + 0.5); $discount = intval($goods_price * 70 + 0.5); if($bonus_price <= $discount) { return 0; } else { return ($bonus_price - $discount) / 100; } } public function bonus_state() { return $this->mBonusState; } private function query_cond($query_state) { static $stQuerys = array('usable','expiring','used','expired'); static $day_secs = 24 * 3600; $cond = array('user_id' => $_SESSION['member_id'],'bonus_status' => 3); if(!empty($query_state) && in_array($query_state,$stQuerys)) { if($query_state == 'usable') { $cond['remain_amount'] = array('gt','0.00'); $cond['expired'] = 0; } elseif ($query_state == 'expiring') { $cond['usable_time'] = array('elt',time() + 5 * $day_secs); $cond['remain_amount'] = array('gt','0.00'); $cond['expired'] = 0; } elseif ($query_state == 'used') { $cond['remain_amount'] = '0.00'; $cond['expired'] = 0; } elseif ($query_state == 'expired') { $cond['expired'] = 1; } else { } } return $cond; } private function write_rates($bonus_state,$bonus_rate) { $_SESSION['bonus_state'] = $bonus_state; $_SESSION['bonus_rate'] = $bonus_rate; $_SESSION['bonus_rate_version'] = $this->mRateVersion; } private function del_rates() { if(isset($_SESSION['bonus_state'])) { unset($_SESSION['bonus_state']); } if(isset($_SESSION['bonus_rate'])) { unset($_SESSION['bonus_rate']); } if(isset($_SESSION['bonus_rate_version'])) { unset($_SESSION['bonus_rate_version']); } } public function topup_bonus($mobile) { $bonuses = bonus_helper::topup_bonus($this,$mobile); if($bonuses != false) { $this->del_rates(); } return $bonuses; } public function total_bonus() { return $this->mRates->total(); } public function is_enough($money) { return intval($this->total_bonus() * 100) >= intval($money * 100); } public function person_enough($money,&$bonus_rate) { if($this->mRates == null) return false; return $this->mRates->is_enough($bonus_rate,$money); } public function rates() { return $this->mRates == null ? false : $this->mRates; } public function makeby_bonus($param, $rate_moneys, $bonus_sn) { $result = bonus_helper::make_bonus($param,$rate_moneys); if($result == false) return false; foreach ($rate_moneys as $item) { $rate = intval($item['rate']); $val = $item['hold_amount']; bonus_helper::withold_bonus($this->member_id,$bonus_sn,$rate,$val,bonus_helper::send_bonus_withold); } $type_sn = $result['type_sn']; $money = $result['money']; $this->handout_bonus($money,$type_sn,session_helper::nickname(),"发送了{$money}元的红包.",\bonus\type::MakeSendType); foreach ($rate_moneys as $item) { $this->mRates->with_hold($item['rate'],$item['amount']); } return $result; } public function make_bonus($param,$rate_moneys) { $result = bonus_helper::make_bonus($param,$rate_moneys); if($result == false) return false; $rates = []; foreach ($rate_moneys as $item) { $rate = intval($item['rate']); $val = $item['hold_amount']; $rates[$rate] = $val; } bonus_helper::withold($this->member_id,$rates,bonus_helper::send_bonus_withold); $type_sn = $result['type_sn']; $money = $result['money']; $this->handout_bonus($money,$type_sn,session_helper::nickname(),"发送了{$money}元的红包.",\bonus\type::MakeSendType); foreach ($rate_moneys as $item) { $this->mRates->with_hold($item['rate'],$item['amount']); } return $result; } public function make_vote_type($param,$rate_moneys) { $result = bonus_helper::make_vote_type($param,$rate_moneys); if($result == false) return false; $rates = []; foreach ($rate_moneys as $item) { $rate = intval($item['rate']); $val = $item['hold_amount']; $rates[$rate] = $val; } bonus_helper::withold($this->member_id,$rates,bonus_helper::send_bonus_withold); $type_sn = $result['type_sn']; $money = $result['money']; $this->handout_bonus($money,$type_sn,session_helper::nickname(),"发送了{$money}元的红包.",\bonus\type::MakeSendType); foreach ($rate_moneys as $item) { $this->mRates->with_hold($item['rate'],$item['amount']); } return $result; } private function base_param($amount,$total_num) { $param = array(); $param['total_amount'] = $amount; $param['total_num'] = $total_num; $param['send_type'] = 1; return $param; } public function share_bonus($bonus_sn,&$msg) { $bonus = bonus\user_bonus::create_by_sn($bonus_sn); if($bonus->spend_over()) { $msg = "该红包现金已经花光了~"; return false; } $amount = $bonus->remain_amount(); $param = $this->base_param($amount,1); $minfo = new member_info($this->member_id); $param['sender_id'] = $this->member_id; $param['sender_mobile'] = $minfo->mobile(); $param['sender_name'] = $minfo->nickname(); $param['make_type'] = \bonus\type::MakeSendType; $name = $minfo->nickname(); $param['type_name'] = "{$name}"; $type = \bonus\type::crate_by_input($param); $rate_moneys = []; $item['amount'] = $type->getTotal_amount(); $item['num'] = $type->getTotal_num(); $item['rate'] = $bonus->bonus_rate(); $rate_moneys[] = $item; $result = bonus_helper::make_bonus($param,$rate_moneys); if($result == false) { return false; } else { if(bonus_helper::withold_bonus($this->member_id,$bonus->bonus_rate(), $bonus_sn,$type->getTotal_amount(),bonus_helper::send_bonus_withold)) { $type_sn = $result['type_sn']; $money = $result['money']; $this->handout_bonus($money,$type_sn,session_helper::nickname(),"发送了{$money}元的红包.",\bonus\type::MakeSendType); } return $result; } } public function admin_make_bonus($param,$rate_moneys) { return bonus_helper::make_bonus($param,$rate_moneys); } public function bonus_expire($bouns) { try { $bonus_obj = bonus\user_bonus::create_by_param($bouns); if($bonus_obj->spend_over()) { return false; } $this->inc_rate_version(); $minfo = new member_info($this->member_id); $data = array(); $data['member_id'] = $this->member_id; $data['member_name'] = $minfo->nickname(); $data['amount'] = $bonus_obj->remain_amount(); $data['order_sn'] = $bonus_obj->bonus_sn(); $data['admin_name'] = "熊猫美妆"; $data['pdr_sn'] = $bonus_obj->bonus_sn(); $data['lg_desc'] = "红包过期扣款"; $this->model_pd->changePd("bonus_expire", $data); return true; } catch (Exception $ex) { return false; } } public function bonus_refund($bonus_type) { $types = bonus\type::create_by_paramer($bonus_type); QueueClient::push('onPredeposit', array('change_type' => 'bonus_refund','buyer_id'=>$types->sender_id(),'order_sn'=>$types->getType_sn())); } public function transform_money($member_id,$name,$amount) { $data = array(); $data['member_id'] = $member_id; $data['member_name'] = is_null($name) ? '' : $name; $data['amount'] = $amount; $order_sn = $this->model_pd->makeSn(); $data['order_sn'] = $order_sn; $data['admin_name'] = '平台管理员'; $data['pdr_sn'] = $order_sn; $data['lg_desc'] = '版本升级,余额迁移.'; $this->model_pd->changePd("sys_add_money",$data); } public function bonus_add_money($amount,$bonus_sn,$sender_name,$info,$make_type = 0) { $minfo = new member_info($this->member_id); $data = array(); $data['member_id'] = $this->member_id; $data['member_name'] = $minfo->nickname(); $data['amount'] = $amount; $data['order_sn'] = $bonus_sn; $data['admin_name'] = $sender_name; $data['pdr_sn'] = $bonus_sn; $data['lg_desc'] = $info; $this->model_pd->changePd("bonus_add_money", $data); } private function send_name($sender_name,$relay_id) { if($relay_id > 0) { $info = new member_info($relay_id); $nick = $info->nickname(); if(!empty($nick)) return $nick; } return $sender_name; } public function add_bonus(bonus\user_bonus $bonus,bonus\type $type) { $this->inc_rate_version(); $minfo = new member_info($this->member_id); $data = array(); $data['member_id'] = $this->member_id; $data['member_name'] = $minfo->nickname(); $data['amount'] = $bonus->bonus_value(); $data['order_sn'] = $bonus->bonus_sn(); $data['admin_name'] = $this->send_name($type->sender_name(),$type->relayer_id()); $data['pdr_sn'] = $bonus->bonus_sn(); $data['lg_desc'] = ""; $data['make_type'] = $type->make_type(); $this->model_pd->changePd("bonus_add_money", $data); } public function reduce_pred($amount) { $minfo = new member_info($this->member_id); $data = array(); $data['member_id'] = $this->member_id; $data['member_name'] = $minfo->nickname(); $data['amount'] = $amount; $data['pdr_sn'] = ''; $data['lg_desc'] = ""; $this->model_pd->changePd("sys_del_money", $data); $this->inc_rate_version(); } public function handout_bonus($amount, $type_sn, $sender_name, $info,$make_type = 0) { $this->inc_rate_version(); $minfo = new member_info($this->member_id); $data = array(); $data['member_id'] = $this->member_id; $data['member_name'] = $minfo->nickname(); $data['amount'] = $amount; $data['order_sn'] = $type_sn; $data['admin_name'] = $sender_name; $data['pdr_sn'] = $type_sn; $data['lg_desc'] = $info; $data['make_type'] = $make_type; $this->model_pd->changePd("hand_out_bonus", $data); } private function filter_sn($lg_desc) { $pos = mb_strpos($lg_desc,':'); if($pos != false) { return mb_substr($lg_desc,$pos + 1); } return ''; } private function filter_make_type($lg_desc) { $reg = '/make_type=(\d+)/i'; $ret = preg_match($reg, $lg_desc, $arr); if($ret > 0) { return intval($arr[1]); } else { return 0; } } private function gen_send_title($sender_name,$make_type) { switch ($make_type) { case bonus\type::MakeSendType: return "发出红包"; case bonus\type::MakeShakeGainType: return "被{$sender_name}摇走的红包"; case bonus\type::MakeShakeLostType: return "摇飞红包到{$sender_name}"; default: return ""; } } private function gen_gain_title($sender_name,$make_type) { switch ($make_type) { case bonus\type::MakeSendType: return "{$sender_name}的红包"; case bonus\type::MakeInviteType: return "{$sender_name}发出的邀请红包"; case bonus\type::MakeBonusRefundType: return "未领红包退款"; case bonus\type::MakeShakeGainType: return "摇到{$sender_name}的红包"; case bonus\type::MakeShakeLostType: return "{$sender_name}摇到你这儿的红包"; case bonus\type::MakePayRefundType: return "购物退款红包"; case bonus\type::MakePayType: return "购物分享红包"; case bonus\type::MakeOrderCancelType: return "订单取消退款"; case bonus\type::MakeRegisterType: return "新人福利"; case bonus\type::MakeEvaluateType: return "评论奖励红包"; case bonus\type::MakeInviteRewardType: return "邀请好友,奖励红包"; case bonus\type::MakeVoteType: return "投票或答题红包"; default: return ""; } } public function filter_pd_log($items) { $pdlogs = []; foreach($items as $val) { $item = array(); $av_amount = $val['lg_av_amount']; $freeze_amount = $val['lg_freeze_amount']; $admin_name = $val['lg_admin_name']; $add_time = $val['lg_add_time']; $type = $val['lg_type']; $sn = $this->filter_sn($val['lg_desc']); $item['av_amount'] = $av_amount; $item['freeze_amount'] = $freeze_amount; $item['add_time'] = $add_time; $fAdd = true; if($type == 'order_pay') { $item['title'] = "支付订单"; $item['sn'] = "订单号:{$sn}"; } else if($type == 'order_freeze') { $item['title'] = "下单扣除红包"; $item['sn'] = "订单号:{$sn}"; } else if($type == 'order_cancel') { $item['title'] = "取消订单,解冻红包"; $item['sn'] = "订单号:{$sn}"; } else if($type == 'order_comb_pay') { $item['title'] = "下单,支付被冻结的红包"; $item['sn'] = "订单号:{$sn}"; $item['av_amount'] = $freeze_amount; } else if($type == 'recharge') { $item['title'] = "充值"; $item['sn'] = "充值单号:{$sn}"; } else if($type == 'refund') { $item['title'] = "确认退款"; } else if($type == 'vr_refund') { $item['title'] = "虚拟兑码退款成功"; } else if($type == 'hand_out_bonus') { $make_type = $this->filter_make_type($val['lg_desc']); $item['title'] = $this->gen_send_title($admin_name,$make_type); $item['sn'] = ''; } else if($type == 'bonus_refund') { $item['title'] = "红包退款"; $item['sn'] = ''; } else if($type == 'bonus_add_money') { $make_type = $this->filter_make_type($val['lg_desc']); $item['title'] = $this->gen_gain_title($admin_name,$make_type); $item['sn'] = ''; } else if($type == 'bonus_expire') { $item['title'] = "红包过期扣款"; $item['sn'] = ''; } else if($type == 'sys_add_money') { $item['title'] = "管理员调节预存款"; $item['sn'] = ''; } else if($type == 'sys_del_money') { $item['title'] = "管理员调节预存款"; $item['sn'] = ''; } else if($type == 'sys_freeze_money') { $item['title'] = "管理员冻结预存款"; $item['sn'] = "充值单号:{$sn}"; } else if($type == 'sys_unfreeze_money') { $item['title'] = "管理员解冻预存款"; $item['sn'] = "充值单号:{$sn}"; } else { $fAdd = false; } if($fAdd) { $pdlogs[] = $item; } } return $pdlogs; } public function calc_rates($order_pd_amount) { $rates = $this->mRates->calc_rates($order_pd_amount); return $rates; } public function calc_pred($order_info,$pd_amount,&$no_cash,&$rates) { $order_id = intval($order_info['order_id']); $mod_order = Model('order'); $pred_amount = 0.00; $goods_list = $mod_order->getOrderGoodsList(array('order_id' => $order_id)); foreach ($goods_list as $goods) { $goods_type = intval($goods['goods_type']); if($goods_type == 1) { $pred_amount += doubleval($goods['goods_pay_price']); } } $pred_amount = $pred_amount - $this->mRates->calc_money($pred_amount,$rates); $cur_used = intval($pred_amount * 100 + 0.5); $cur_used = $cur_used > $pd_amount ? $pd_amount : $cur_used; $order_amount = intval($order_info['order_amount'] * 100 + 0.5); $order_pd_amount = intval($order_info['pd_amount'] * 100 + 0.5); if($order_amount == $cur_used) { $no_cash = true; } else { $no_cash = false; } return $cur_used - $order_pd_amount; } public function pay_bonus($rates) { $ret = bonus_helper::withold($this->member_id,$rates,bonus_helper::pay_order_withold); if($ret == true) { $this->inc_rate_version(); $this->del_rates(); } else { $cent = intval($ret * 100 + 0.5); if($cent > 0) { $this->inc_rate_version(); $this->del_rates(); } } return $ret; } public function find_bonus($amount) { $bonus_rate = $this->bonus_rate(); return $bonus_rate->find_rate($amount); } public function inc_rate_version() { Model('member')->inc_rate_version($this->member_id); } }