123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587 |
- <?php
- namespace app\common\model;
- use app\common\service\OrderRefundService;
- use app\common\service\RefundService;
- use Carbon\Carbon;
- use think\db\Query;
- use think\Model;
- use Yansongda\Supports\Arr;
- /**
- * 短信验证码
- * @property Orders orders
- * @property User user
- * @property LogisticsCompany com
- * @property UserAddress address
- * @property OrderInfo order_info
- * @property int refund_status
- * @property int refund_type
- * @property int create_time
- * @property int audit_time
- * @property int over_time
- * @property int rm_time
- * @property int user_send_time
- * @property int user_trans_com_id
- * @property int refund_by
- * @property int num
- * @property int num_install
- * @property string user_trans_no
- * @property bool is_wait_audit
- * @property bool has_money
- * @property bool need_rec
- * @property bool need_tk
- * @property bool need_complete
- * @property bool can_view_logistics
- * @property bool self_back_goods
- * @property string audit_remark
- * @property string order_no
- * @property string fix_order_no
- * @property string refund_type_text
- * @property string refund_by_text
- * @property float amount_last
- * @method static static|Query FilterRefund($status=null)
- * @method static static|Query FilterTs()
- */
- class Refund Extends Model
- {
- protected $name='order_info_refund';
- protected $append=[
- 'timeline',
- 'refund_status_text',
- 'need_rec',
- 'need_tk',
- 'is_pass',
- 'need_complete',
- 'refund_type_text',
- 'refund_by_text',
- 'reason_text',
- 'can_view_logistics',
- ];
- const REFUND_ING=100;
- const REFUND_PASS=200;
- const REFUND_JI=250;
- const REFUND_RUNNING=270;
- const REFUND_REFUNDING=280;
- const REFUND_REJECT=300;
- const REFUND_CANCEL=400;
- const REFUND_OVER=500;
- public static $refundStatus=[
- self::REFUND_ING=>'申请审核中',
- 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()<strtotime('+1year',$order['send_time'])){
- $refundConfig['type']=[
- self::TH_TYPE_FREE=>'一年以内免费保修',
- ];
- }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();
- }
- if($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->status<Orders::S_OVER){
- $has=OrderInfo::where('order_id',$this['order_id'])
- ->filterHasUnRefund()
- ->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(){
- list($res,$data)=logistics()
- ->setLogistics($com=LogisticsCompany::where('name','宅急送')->find())
- ->setUserName($this->orders->logistics->from_username)
- ->setPhone($this->orders->logistics->from_mobile)
- ->setToArea($this->orders->logistics->fullArea())
- ->setFromUsername($this->address['name'])
- ->setFromMobile($this->address['mobile'])
- ->setFromArea($this->address['full_address'])
- ->setCargo($this->order_info->goods_name)
- ->setCount($this->num)
- ->setOrderNo($this->orders->order_no)
- ->labelOrder();
- if(!$res){
- throw_user($data);
- }
- $this->user_trans_no=$data['kuaidinum'];
- $this->user_send_time=time();
- $this->user_trans_com_id=$com['id'];
- $pubname='/uploads/md/'.$this['id'];
- $dir=ROOT_PATH.'public'.$pubname;
- $filename=$dir.'/'.session_create_id().'.png';
- if(!is_dir($dir)){
- @mkdir($dir,0755,true);
- }
- file_put_contents($filename,file_get_contents($data['label']));
- $this->label=request()->domain().$pubname;
- $this->save();
- }
- /**
- * @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->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);
- }
- });
- }
- }
|