'申请审核中', self::REFUND_PASS=>'申请通过', self::REFUND_JI=>'用户寄回', self::REFUND_RUNNING=>'售后中', self::REFUND_REFUNDING=>'退款中', self::REFUND_REJECT=>'申请驳回', self::REFUND_CANCEL=>'已取消', self::REFUND_OVER=>'处理完成', ]; protected $type=[ 'address'=>'json', ]; /** * @return string[] */ public static function getRefundStatus(): array { return self::$refundStatus; } const REFUND_TYPE_MONEY=1; const REFUND_TYPE_ALL=2; const REFUND_TYPE_HHBX=5; public static $refundTypes=[ self::REFUND_TYPE_MONEY=>'取消订单', self::REFUND_TYPE_ALL=>'退款退货', self::REFUND_TYPE_HHBX=>'换货/维修', ]; public static $refundTypeGoods=[self::REFUND_TYPE_ALL,self::REFUND_TYPE_HHBX]; public static $refundTypeMoney=[self::REFUND_TYPE_MONEY,self::REFUND_TYPE_ALL]; const REASON_QU=1; public static $reasons=[ self::REASON_QU=>'质量问题', 2=>'7天无理由退货(退回运费需客户承担)', 3=>'协商一致退款', 4=>'快递运输破损', 5=>'其他', ]; const TH_TYPE_NONE=0; const TH_TYPE_SELF_SEND=1; const TH_TYPE_SELF_FEE=2; const TH_TYPE_FREE=3; const TH_TYPE_SENDER=4; public static $goodsTypes=[ //self::TH_TYPE_NONE=>'无需退货', self::TH_TYPE_SELF_SEND=>'自行邮寄', //self::TH_TYPE_SELF_FEE=>'拍维修费', //self::TH_TYPE_FREE=>'一年以内免费保修', self::TH_TYPE_SENDER=>'上门取件', ]; protected $autoWriteTimestamp=true; public function orderInfo(){ return $this->belongsTo(OrderInfo::class); } public function orders(){ return $this->belongsTo(Orders::class,'order_id'); } public function user(){ return $this->belongsTo(User::class); } public function com(){ return $this->belongsTo(LogisticsCompany::class,'user_trans_com_id'); } public function allowCancel(){ return in_array($this['refund_status'],[ self::REFUND_ING, ]); } public function allowApply(){ return in_array($this->refund_status,[ self::REFUND_REJECT, self::REFUND_CANCEL, self::REFUND_OVER, ]); } public function allowEdit(){ return in_array($this->refund_status,[ self::REFUND_ING, ]); } public function makeCancel(){ $this['refund_status']=self::REFUND_CANCEL; $this->save(); } #根据订单状态选择售后 public static function makeRefundConfig(OrderInfo $orderInfo,$inject=true,$delKeys=false){ $order=$orderInfo->orders; $refundConfig=[]; if(!$orderInfo->refund || $orderInfo->refund->allowApply() || $orderInfo->refund->allowEdit()) { #未发货 if (in_array($order['status'], [$order::S_WAIT_SEND])) { $refundConfig['refund_type'] = Arr::only(self::getRefundTypes(), [ self::REFUND_TYPE_MONEY, ]); $refundConfig['type'] = [ self::REFUND_TYPE_MONEY => null, ]; $refundConfig['req_order'] = [ self::REFUND_TYPE_MONEY=>false, ]; $refundConfig['req_address'] = null; $refundConfig['reason'] = array_values(Refund::getReasons()); list($amount_single, $amount_install_single) = RefundService::setOrderInfo($orderInfo, $orderInfo['num'], $orderInfo['num_install'])->amount(); $refundConfig['amount_single'] = $amount_single; $refundConfig['amount_install_single'] = $amount_install_single; $refundConfig['num'] = $orderInfo['num']; $refundConfig['num_install'] = $orderInfo['num_install']; } #已发货 /*elseif(in_array($order['status'],[$order::S_WAIT_REC,$order::S_OVER])){ #七天内可以退货退款 if(time()<$order['send_time']+7*86400){ $refundConfig['refund_type']=[ self::REFUND_TYPE_ALL=>'退款退货', ]; $refundConfig['type']=[ self::TH_TYPE_FREE=>'自行邮寄', ]; $refundConfig['reason']=array_values(Refund::getReasons()); $refundConfig['req_amount']=1; $refundConfig['amount']=RefundService::setOrderInfo($orderInfo,$orderInfo['num'],$orderInfo['num_install'])->amount(true); $refundConfig['req_order']=0; $refundConfig['num']=$orderInfo['num']; $refundConfig['num_install']=$orderInfo['num_install']; } #只能换货保修 else{ $refundConfig['refund_type']=[ self::REFUND_TYPE_HHBX=>'换货保修', ]; $refundConfig['req_order']=0; #一年内 if(time()'一年以内免费保修', ]; }else{ $refundConfig['type']=[ self::TH_TYPE_SELF_FEE=>'拍维修费', ]; $refundConfig['req_order']=1; $refundConfig['req_order_goods']=Goods::getFixGoods(); } $refundConfig['reason']=array_values(Refund::getReasons()); $refundConfig['req_amount']=0; } }*/ elseif (in_array($order['status'], [$order::S_WAIT_REC,$order::S_OVER])) { $gtYear=Carbon::now()->gt(Carbon::createFromTimestamp($order->send_time)->addYear()); if($gtYear){ $refundConfig['refund_type'] = Arr::only(self::getRefundTypes(), [ self::REFUND_TYPE_HHBX, ]); $refundConfig['type'] = [ self::REFUND_TYPE_HHBX => Arr::only(self::getGoodsTypes(), [ self::TH_TYPE_SELF_SEND, self::TH_TYPE_SENDER, ]), ]; $refundConfig['req_order'] = [ self::REFUND_TYPE_HHBX=>$gtYear, ]; }else{ $refundConfig['refund_type'] = Arr::only(self::getRefundTypes(), [ self::REFUND_TYPE_ALL, self::REFUND_TYPE_HHBX, ]); $refundConfig['type'] = [ self::REFUND_TYPE_ALL => Arr::only(self::getGoodsTypes(), [ self::TH_TYPE_SELF_SEND, self::TH_TYPE_SENDER, ]), self::REFUND_TYPE_HHBX => Arr::only(self::getGoodsTypes(), [ self::TH_TYPE_SELF_SEND, self::TH_TYPE_SENDER, ]), ]; $refundConfig['req_order'] = [ self::REFUND_TYPE_ALL=>false, self::REFUND_TYPE_HHBX=>false, ]; } $refundConfig['req_address'] = [ self::TH_TYPE_SELF_SEND=>false, self::TH_TYPE_SENDER=>true, ]; $refundConfig['reason'] = array_values(Refund::getReasons()); list($amount_single, $amount_install_single) = RefundService::setOrderInfo($orderInfo, $orderInfo['num'], $orderInfo['num_install'])->amount(); $refundConfig['amount_single'] = $amount_single; $refundConfig['amount_install_single'] = $amount_install_single; $refundConfig['num'] = $orderInfo['num']; $refundConfig['num_install'] = $orderInfo['num_install']; $refundConfig['req_order_goods']=Goods::getFixGoods(); } } if(empty($refundConfig)){ $refundConfig=null; } if($delKeys && !empty($refundConfig['refund_type'])){ $newArr=[]; foreach ($refundConfig['refund_type'] as $key=>$value){ $newArr[]=compact('key','value'); } $refundConfig['refund_type']=$newArr; } if($inject){ $orderInfo['refund_config']=$refundConfig; } return $refundConfig; } public function allowAudit(){ return $this['refund_status']==self::REFUND_ING; } /** * @return string[] */ public static function getGoodsTypes(): array { return self::$goodsTypes; } #退款相关 /** * 退款金额 */ public function getRefundAmount(){ return $this['amount_last']; } public function refundResult($succ,$remark=''){ if(is_bool($succ)){ $this['pay_status']=$succ?1:2; }else{ $this['pay_status']=$succ; } $this['pay_remark']=$remark; $this->rm_time=time(); $this->over_time=time(); $this->save(); } public function isRefundMoney(){ return in_array($this['refund_type'],self::getRefundTypeMoney()); } #end public function payToUser(){ if($this->amount_last>0) { $payment = $this->orders->payment ?? null; if ($payment) { $this->order_no=order_no('tk'); $this->save(); $refund = new OrderRefundService(); $refund->setPayment($payment); $refund->setRefund($this); $refund->setBody("订单[{$this->orders->order_no}]退款"); $refund->pay(); } } } public function makeAudit($pass,$extend){ $this['refund_status']=$pass?self::REFUND_PASS:self::REFUND_REJECT; if(!empty($extend['audit_remark'])) { $this->audit_remark = $extend['audit_remark']; } if($this->has_money) { $this->amount_last = $extend['amount_last']; } $this->audit_time=time(); if($pass){ if($this->refund_type==self::REFUND_TYPE_MONEY){ $this->payToUser(); $this->orders->makeCancel(); }elseif($this->refund_by==self::TH_TYPE_SENDER){ $this->makeLabelOrder(); } } $this->save(); SiteMsg::sendMsg( $pass?SiteMsg::TYPE_ORDER_REFUND_PASS:SiteMsg::TYPE_ORDER_REFUND_REJECT, $this->user ); #总订单 /*$order=$this->orders; if($order && $order->statusfilterHasUnRefund() ->find(); if(!$has){ $order->makeCancel(); } }*/ } public function makeComplete(){ $refund=$this; $refund->over_time=time(); $refund->refund_status=Refund::REFUND_OVER; return $refund->save(); } public function makeLabelOrder(){ } /** * @return string[] */ public static function getReasons(): array { $reasons=self::$reasons; $arr=[]; foreach ($reasons as $key=>$value){ $arr[$key]=compact('key','value'); } return $arr; } /** * @return string[] */ public static function getRefundBys(): array { $obj=self::$goodsTypes; $arr=[]; foreach ($obj as $key=>$value){ $arr[$key]=compact('key','value'); } return $arr; } /** * @return string[] */ public static function getRefundTypes(): array { return self::$refundTypes; } /** * @return int[] */ public static function getRefundTypeGoods(): array { return self::$refundTypeGoods; } /** * @return int[] */ public static function getRefundTypeMoney(): array { return self::$refundTypeMoney; } /** * 售后中及已售后的 * @param Query $query * @param null $status 1进行中2已完成 */ public function scopeFilterRefund(Query $query,$status=null){ if(is_null($status)) { $query->whereBetween("{$this->getTable()}.refund_status", [self::REFUND_ING, self::REFUND_PASS]); }elseif ($status==1){ $query->where("{$this->getTable()}.refund_status", self::REFUND_ING); }elseif ($status==2){ $query->where("{$this->getTable()}.refund_status", self::REFUND_PASS); } } /** * 投诉类型的售后 * @param Query $query */ public function scopeFilterTs(Query $query){ $query->where("{$this->getTable()}.reason1",self::REASON_QU); } public function getIsWaitAuditAttr($_,$model){ return $model['refund_status']==self::REFUND_ING; } public function gethasMoneyAttr($_,$model){ return $this->isRefundMoney(); } #是否可查看寄回物流 public function getCanViewLogisticsAttr($_,$model){ return $model['user_trans_no']?true:false; } #是否是需要寄回 public function getIsGoodsBackAttr($_,$model){ return $this->refund_status==self::REFUND_PASS && in_array($this->refund_type,self::getRefundTypeGoods()); } #是否自己寄回 public function getSelfBackGoodsAttr($_,$model){ return $this->refund_status==self::REFUND_PASS && $this->refund_type==self::TH_TYPE_SELF_SEND && !$model['user_send_time']; } public function getRefundStatusTextAttr($_,$model){ return Arr::get(self::getRefundStatus(),$model['refund_status']); } public function getRefundTypeTextAttr($_,$model){ return Arr::get(self::getRefundTypes(),$model['refund_type']); } public function getRefundByTextAttr($_,$model){ if(!$model['refund_by']){ return null; } return Arr::get(self::getRefundBys(),$model['refund_by'])['value']; } public function getReasonTextAttr($_,$model){ if(!$model['reason1']){ return null; } return Arr::get(self::getReasons(),$model['reason1'])['value']; } #是否可以已收货 public function getNeedRecAttr($_,$model){ return $this->self_back_goods && $this->user_send_time; } #是否可以退款 public function getNeedTkAttr($_,$model){ return $this->refund_status==self::REFUND_REFUNDING; } #是否需要完成 public function getNeedCompleteAttr($_,$model){ $con1 = $this->refund_type==self::REFUND_TYPE_HHBX; $con2 = $model['refund_status']==self::REFUND_RUNNING; return $con1 && $con2; } public function getTimelineAttr(){ $arr=[ [ 'title'=>'提交申请', 'time' =>self::datetime($this->create_time), 'status'=>1, ], ]; $arr[]=[ 'title'=>'申请审核', 'time' =>self::datetime($this->audit_time), 'status'=>100, ]; switch ($this->refund_type){ case self::REFUND_TYPE_MONEY: $arr[]=['title'=>'退款中','time' =>self::datetime($this->rm_time),'status'=>200,]; $arr[]=['title'=>'已完成','time' =>self::datetime($this->over_time),'status'=>1000,]; break; case self::REFUND_TYPE_ALL: $arr[]=['title'=>'用户寄回','time' =>self::datetime($this->user_send_time),'status'=>300,]; $arr[]=['title'=>'退款中','time' =>self::datetime($this->rm_time),'status'=>200,]; $arr[]=['title'=>'已完成','time' =>self::datetime($this->over_time),'status'=>1000,]; break; case self::REFUND_TYPE_HHBX: $arr[]=['title'=>'用户寄回','time' =>self::datetime($this->user_send_time),'status'=>300,]; $arr[]=['title'=>'售后中','time' =>self::datetime($this->rm_time),'status'=>400,]; $arr[]=['title'=>'已完成','time' =>self::datetime($this->over_time),'status'=>1000,]; break; } return $arr; } #是否已通过 public function getIsPassAttr($_,$model){ return !in_array($model['refund_status'],[ self::REFUND_REJECT, self::REFUND_CANCEL, ]); } public static function datetime($time){ if($time){ return Carbon::createFromTimestamp($time)->toDateTimeString(); } return null; } protected static function init() { self::beforeInsert(function (self $refund){ $refund['refund_status']=self::REFUND_ING; if($refund->refund_type==self::REFUND_TYPE_HHBX){ $refund->fix_order_no=order_no('wx'); } }); self::afterUpdate(function (self $refund){ if($refund->refund_status==self::REFUND_PASS && $refund->isRefundMoney()){ Transaction::addTransaction($refund); } }); } }