log = $log; return $this; } /** * @param UserCoupon $coupon */ public function setCoupon($coupon) { if($coupon) { $c = $this->getUser()->coupon()->use()->find($coupon); if (!$c) { throw_user('优惠券不存在'); } $this->user_coupon = $c; } return $this; } public function __construct() { bcscale(2); $this->config=SysConfig::look('price_config',config('process')); } /** * @return User */ public function getUser() { return $this->user; } /** * @param mixed $user */ public function setUser(User $user) { $this->user = $user; $this->coupon = $user->coupon()->use()->select(); return $this; } public function checkArea($area){ $city=tm()->getLocation($area['longitude'],$area['latitude']); return $city['city']; } protected function area(){ $from_area=$this->checkArea($this->order['from_addr']); $to_area=$this->checkArea($this->order['to_addr']); $this->order['from_city']=$from_area; $this->order['to_city']=$to_area; $database_from_area=Area::city()->where('name',$this->order['from_city'])->find(); if(!$database_from_area){ throw_user("数据库未找到取宠城市{$this->order['from_city']}"); } $this->from_area=$database_from_area; $database_to_area=Area::city()->where('name',$this->order['to_city'])->find(); if(!$database_to_area){ throw_user("数据库未找到送宠城市{$this->order['to_city']}"); } $this->to_area=$database_to_area; $this->order['from_longitude']=$this->order['from_addr']['longitude']; $this->order['from_latitude']=$this->order['from_addr']['latitude']; $this->order['to_longitude']=$this->order['to_addr']['longitude']; $this->order['to_latitude']=$this->order['to_addr']['latitude']; $this->recordLog("[{$this->order['from_city']}]-[{$this->order['to_city']}]"); #检查空运有没有设置机场坐标 $noneAir=!$this->hasAir($this->order['pick_up']); if($this->order['freight']==UserOrder::FREIGHT_AIR && $noneAir){ throw_user('未找到机场,无法选择此方式运输'); } } protected function distance(){ $this->order['distance']=ll_distance( $this->order['from_longitude'], $this->order['from_latitude'], $this->order['to_longitude'], $this->order['to_latitude'] ); $this->recordLog("距离:{$this->order['distance']}km"); } public function import(&$data){ list($data['agree_date'],$data['agree_time'])=explode(' ',$data['agree_time']); $this->pet_category=Pet::category()[$data['pet_category']]??null; $data['pet_category']=$this->pet_category['name']??throw_user("宠物类目不存在"); $this->cage_spec=Pet::spec()[$data['spec']]??throw_user('宠具规格不存在'); $data['spec']=$this->cage_spec['name']; if(!empty($data['protect_id'])) { $protect=Pet::protect()[$data['protect_id']]; $data['protect_amount'] = $protect['price']; $data['protect_max'] = $protect['max']; } else{ #防止报错 $data['protect_id']=null; } #没有优惠券置为null if(empty($data['coupon_id'])){ $data['coupon_id']=null; } #没有选配送方式置为null if(!isset($data['freight'])){ $data['freight']=null; } $data['coupon_amount']=0; $data['discount_amount']=0; $data['total_amount']=0; $data['real_amount']=0; $this->order=$data; $this->area(); $this->distance(); return $this; } function prepare(){ $items=[]; $total_amount=0; $freight_amount=0; $freights=UserOrder::$freights; if(!$this->pet_category['allow_air']){ unset($freights[UserOrder::FREIGHT_AIR]); if($this->order['freight']==UserOrder::FREIGHT_AIR){ throw_user('该宠物不支持空运'); } } foreach ($freights as $type=>$_){ $item=[ 'type'=>$type,//类型 'price'=>0,#实付 'total_price'=>0,#单个类型支付总价 //'coupon'=>[],//可用的优惠券列表 ]; $item['total_price']=$this->{$type}(); $item['price']=$item['total_price']; $items[$type]=$item; if($type==$this->order['freight']){ $total_amount=$freight_amount=bcadd($total_amount,$item['total_price']); } } $protect=Pet::protect()[$this->order['protect_id']]??[]; $protect_price=$protect['price']??0; $total_amount=bcadd($total_amount,$protect['price']??0); #用户折扣 $user_level_discount_money=$freight_amount; if($this->order['freight']==UserOrder::FREIGHT_AIR){ $user_level_discount_money=$this->order['first_air_amount']; } $level_amount=bcmul($this->user->level_discount,$user_level_discount_money); $this->order['level_amount']=$level_amount; $this->recordLog("运费:{$freight_amount},折扣:{$this->user->level_discount},用户折扣:{$level_amount}"); $freight_amount=bcsub($freight_amount,$level_amount); #券金额 if($this->user_coupon){ if(!$this->user_coupon->fit($freight_amount)){ throw_user('优惠券不满足使用条件'); } if($this->user->is_vip && $this->order['freight']==UserOrder::FREIGHT_AIR){ throw_user('您已是会员,当空运时无法使用优惠券折扣'); } $this->order['coupon_amount']=$this->user_coupon->amount($freight_amount); $this->recordLog("优惠券:".json_encode($this->user_coupon,JSON_UNESCAPED_UNICODE)); } $freight_amount=bcsub($freight_amount,$this->order['coupon_amount']); #优惠总金额 $this->order['discount_amount']=bcadd($this->order['coupon_amount'],$this->order['level_amount']); $this->order['real_amount']=bcadd($freight_amount,$protect_price); $this->order['total_amount']=$total_amount; $this->order['freights']=$items; #可用的优惠券 $coupon=[]; if($this->order['freight']!=UserOrder::FREIGHT_AIR) { foreach ($this->coupon as $_coupon) { if ($_coupon->fit($this->order['total_amount'])) { $coupon[] = $_coupon; } } } $this->order['allow_coupons']=$coupon; return $this->order; } protected function fast(){ #距离 $distance=$this->order['distance']; $start_kilo=$this->config['fast']['start_kilo']; $start_amount=$this->config['fast']['start_amount']; if($distance<=$start_kilo){ $distance_price=$start_amount; }else{ $out_price=$start_amount; foreach ($this->config['fast']['detail'] as $detail){ if($distance>=$detail['start_kilo'] && $distance<$detail['end_kilo']){ $out_price=bcadd($out_price,bcmul($detail['amount'],$distance)); break; } } $distance_price=$out_price; } #笼子百分比算出运费 $cage_float=$this->cage_spec['per']/100; $cage_float_price=bcmul($distance_price,$cage_float); #宠具+运费 $cage_price=$this->cage(); $total = bcadd($cage_float_price,$cage_price); #件数,多只按百分比算优惠,按笼子数量 $num=$this->order['piece']; $per=$this->config['fast']['out_one_per']; $out_float=bcdiv($per,100); $num_price=bcmul(bcmul($out_float,$cage_float_price),$num-1); $total=bcadd($total,$num_price); $this->recordLog("快车-起步距离:{$start_kilo},起步价:{$start_amount},距离总价:{$distance_price},宠具百分比:{$cage_float}," . "笼子百分比算出的运费:{$cage_float_price},宠具价格:{$cage_price},". "只数:{$num},超出百分比:{$this->config['fast']['out_one_per']},超出一只总价:{$num_price}". "总价:{$total}" ); return $total; } protected function air(){ $total=0; #基础价格 $base_get_price=$this->from_area['first_air_amount']; $base_send_price=0; $start_amount=$this->config['air']['start_amount']??null; if(is_null($base_get_price)){ if(is_null($start_amount)){ throw_user('未设置出港费'); } $base_get_price=$start_amount; } $base_price=bcadd($base_get_price,$base_send_price); $total=bcadd($total,$base_price); #多只出港费半价,按宠物数量 $num=$this->order['num']; $out_one_per=$this->config['air']['out_one_per']; $out_one_float=$out_one_per/100; $first_out_price=bcmul(bcmul($base_price,$out_one_float),$num-1); $total=bcadd($total,$first_out_price); $this->recordLog("空运-出港费设置比例:{$out_one_per}%,额外出港费:{$first_out_price}"); $this->order['first_air_amount']=bcadd($first_out_price,$base_price); #距离 #上门接 $get_price=0; $send_price=0; $get_send_price=0; if($this->order['pick_up']==1 && $this->hasAir(1)) { $get_price=$this->pickup($this->from_area['air_longitude'],$this->from_area['air_latitude'],$this->order['from_longitude'],$this->order['from_latitude']); $total=bcadd($total,$get_price); $get_send_price=$get_price; } #上门送 elseif ($this->order['pick_up']==2 && $this->hasAir(2)){ $send_price=$this->pickup($this->to_area['air_longitude'],$this->to_area['air_latitude'],$this->order['to_longitude'],$this->order['to_latitude']); $total=bcadd($total,$send_price); $get_send_price=$send_price; } #上门接送 elseif ($this->order['pick_up']==4 && $this->hasAir(4)){ $get_price=$this->pickup($this->from_area['air_longitude'],$this->from_area['air_latitude'],$this->order['from_longitude'],$this->order['from_latitude']); $total=bcadd($total,$get_price); $send_price=$this->pickup($this->to_area['air_longitude'],$this->to_area['air_latitude'],$this->order['to_longitude'],$this->order['to_latitude']); $total=bcadd($total,$send_price); $get_send_price=bcadd($get_price,$send_price); } #机场代提费 $take_price=0; if(in_array($this->order['pick_up'],[2,4])){ //$take_price=$this->config['air']['send']['default_amount']; if($this->to_area['second_air_amount']){ $take_price=$this->to_area['second_air_amount']; } $total=bcadd($total,$take_price); } #宠具 $cage_price=$this->cage(); $total=bcadd($total,$cage_price); #重量 $weight=$this->order['weight']; $avgWeight=bcdiv($weight,$num); $base_weight=$this->config['air']['weight']['base_weight']; $out_weight_price=0; $out_price=0; if($avgWeight>$base_weight){ $out_weight=bcsub($weight,$base_weight); $out_weight_price=$this->config['air']['weight']['out_amount']; $out_price=bcmul($out_weight,$out_weight_price); $total=bcadd($total,$out_price); } $this->recordLog("空运-从地区取基础价格(出港费):{$base_price},默认起步价:{$start_amount},上门接:{$get_price},上门送:{$send_price},". "上门接送:{$get_send_price},|地区{$this->to_area['second_air_amount']},". "宠具价格:{$cage_price},重量:{$weight},平均重量:{$avgWeight},基础重量:{$base_weight},超出后每KG价格:{$out_weight_price},重量总价:{$out_price},". "总价:{$total}" ); return $total; } protected function special(){ #距离 $distance=$this->order['distance']; $start_kilo=$this->config['special']['start_kilo']; $start_amount=$this->config['special']['start_amount']; if($distance<=$start_kilo){ $distance_price=$start_amount; }else{ $distance_price=bcmul(bcsub($distance,$start_kilo),$this->config['special']['out_amount']); $distance_price=bcadd($start_amount,$distance_price); } #笼具 $cage_price=$this->cage(); $price=bcadd($distance_price,$cage_price); $this->recordLog("专车-起步距离:{$start_kilo},起步价:{$start_amount},距离价格:{$distance_price},宠具价格:{$cage_price},总价:{$price}"); return $price; } protected function cage(){ if($this->order['has_cage']){ return 0; } $cage_num=$this->order['piece']; return bcmul($cage_num,$this->cage_spec['amount']); } protected function pickup($from_longitude,$from_latitude,$to_longitude,$to_latitude){ $this->recordLog("上门接送:$from_latitude,$from_latitude,$to_longitude,$to_latitude"); $distance=ll_distance($from_longitude,$from_latitude,$to_longitude,$to_latitude); $get_default_price = $this->config['air']['pickup']['start_amount']; $get_default_kilo = $this->config['air']['pickup']['start_distance']; if($distance<=$get_default_kilo){ $get_price=$get_default_price; }else{ $get_price=$get_default_price; $max_kilo=$this->config['air']['pickup']['out_kilo_num']; $every_kilo_amount=$this->config['air']['pickup']['every_kilo_amount']; $out_kilo_amount=$this->config['air']['pickup']['out_kilo_amount']; if($distance<=$max_kilo){ $get_price=bcadd($get_price,bcmul($every_kilo_amount,$distance)); }else{ $get_price=bcadd($get_price,bcmul($every_kilo_amount,$max_kilo)); $get_price=bcadd($get_price,bcmul($out_kilo_amount,bcsub($distance,$max_kilo))); } } return $get_price; } protected function hasAir($pickup){ switch ($pickup){ case 0: return true; case 1: return $this->from_area->has_air_coordinate; case 2: return $this->to_area->has_air_coordinate; case 4: return $this->from_area->has_air_coordinate && $this->to_area->has_air_coordinate; default: throw_user('上门接送类型有误'); } throw_user('上门接送类型有误'); } protected function recordLog($content){ $this->log && $this->log->setContent($content); } public function __destruct() { $this->recordLog("orderInfo:".json_encode($this->order,JSON_UNESCAPED_UNICODE)); $this->log && $this->log->write(); } }