// +---------------------------------------------------------------------- declare (strict_types=1); namespace app\api\model; use app\api\model\Setting as SettingModel; use app\api\service\User as UserService; use app\api\model\OrderGoods as OrderGoodsModel; use app\common\model\order\RefundHis as RefundHisModel; use app\common\model\order\RefundHis; use app\common\model\OrderRefund as OrderRefundModel; use app\common\enum\order\refund\RefundType as RefundTypeEnum; use app\common\enum\order\refund\AuditStatus as AuditStatusEnum; use app\common\enum\order\refund\RefundStatus as RefundStatusEnum; use app\common\enum\order\refund\FinanceRefundStatus as FinanceRefundStatusEnum; use app\common\exception\BaseException; use app\common\service\Kuaidi as KuaidiService; use app\common\model\Express as ExpressModel; use app\store\model\OrderGoods; /** * 售后单模型 * Class OrderRefund * @package app\api\model */ class OrderRefund extends OrderRefundModel { /** * 隐藏字段 * @var array */ protected $hidden = [ 'store_id', 'update_time' ]; /** * 追加字段 * @var array */ protected $append = [ 'state_text', // 售后单状态 'dfh_time', // 待用户发货倒计时 ]; /** * 售后单状态文字描述 * @param $value * @param $data * @return string */ public function getStateTextAttr($value, $data) { if($data['delivery_type']==10){ // 已完成 if ($data['status'] == RefundStatusEnum::COMPLETED) { return ['value'=>1,'name'=>'退款成功']; } // 已取消 if ($data['status'] == RefundStatusEnum::CANCELLED) { return ['value'=>2,'name'=>'已取消']; } // 已拒绝 if ($data['status'] == RefundStatusEnum::REJECTED) { return ['value'=>3,'name'=>'平台已拒绝']; } //已关闭 -用户超时未退货,系统自动关闭售后单 if ($data['status'] == RefundStatusEnum::CLOSE) { return ['value'=>7,'name'=>'已关闭']; } // 进行中 if ($data['status'] == RefundStatusEnum::NORMAL) { //退货退款 if ($data['type'] == RefundTypeEnum::RETURN) { if (isset($data['audit_status_zg'])&&$data['audit_status_zg'] == AuditStatusEnum::WAIT) { return ['value'=>0,'name'=>'待审核']; } if(isset($data['is_user_send'])&&$data['is_user_send']){ //已发货 if($data['is_receipt']==1){//已收货 return ['value'=>6,'name'=>'待退款']; } if ($data['is_receipt']==2) { return ['value'=>8,'name'=>'仓库拒绝收货']; }else{ return ['value'=>5,'name'=>'待仓库收货']; } }else{ return ['value'=>4,'name'=>'待买家退货']; } }else{ if (isset($data['audit_status'])&&$data['audit_status'] == AuditStatusEnum::WAIT) { //仅退款不需要主管审核 return ['value'=>0,'name'=>'待审核']; } if($data['finance_refund'] == FinanceRefundStatusEnum::WAIT){ return ['value'=>6,'name'=>'待退款']; } } } } if($data['delivery_type']==20){ if ($data['status'] == RefundStatusEnum::COMPLETED) { return ['value'=>1,'name'=>'退款成功']; } //已关闭 -用户超时未退货,系统自动关闭售后单 if ($data['status'] == RefundStatusEnum::CLOSE) { return ['value'=>7,'name'=>'已关闭']; } if ($data['status'] == RefundStatusEnum::NORMAL) { if (isset($data['audit_status'])&&$data['audit_status'] == AuditStatusEnum::WAIT) { return ['value'=>0,'name'=>'待审核']; } if ($data['audit_status'] == AuditStatusEnum::REVIEWED&&$data['finance_refund']==0) { return ['value'=>6,'name'=>'待退款']; } } } return $value; } /** * 待用户发货倒计时时间戳 * @param $value * @param $data * @return int * @author: zjwhust * @Time: 2021/10/8 17:06 */ public function getDfhTimeAttr($value,$data){ if ( $data['type'] == RefundTypeEnum::RETURN && $data['audit_status'] == AuditStatusEnum::REVIEWED && $data['audit_status_zg'] == AuditStatusEnum::REVIEWED && $data['is_user_send'] == 0 && $data['status'] == RefundStatusEnum::NORMAL ) { $now = time(); $delay_time = 86400 * 7;//获取待发货时间 if(env('SERVE_ENV')=='test'){ $delay_time = 300;//测试超时退款5分钟 } if(($now-$data['approved_time'])<$delay_time){ // return $data['approved_time']+$delay_time-$now; } } return 0; } /** * 获取用户售后单列表 * @param int $state 售后单状态 -1为全部 * @return \think\Paginator * @throws \app\common\exception\BaseException * @throws \think\db\exception\DbException */ public function getList(int $state = -1) { // 检索查询条件 $filter = []; // 售后单状态 $state > -1 && $filter[] = ['status', '=', $state]; // 当前用户ID $userId = UserService::getCurrentLoginUserId(); // 查询列表记录 return $this->with(['orderGoods.image', 'orderGoodsAll.image']) ->where($filter) ->where('user_id', '=', $userId) ->order(['create_time' => 'desc']) ->paginate(15) ->each(function($item) { if (!$item['order_goods_id']) { // 整单退款 $orderGoods = $item['orderGoodsAll']; } else { $orderGoods = [$item['orderGoods']]; } unset($item['orderGoods'], $item['orderGoodsAll']); $item['orderGoods'] = $orderGoods; }); } /** * 获取数量 * @return int * @throws BaseException */ public function getCount() { // 当前用户ID $userId = UserService::getCurrentLoginUserId(); return $this->where('user_id', '=', $userId) ->where('status', '=', 0) ->count(); } /** * 获取当前用户的售后单详情 * @param int $orderRefundId 售后单ID * @param bool $isWith 是否关联 * @return static|null * @throws BaseException */ public static function getDetail(int $orderRefundId, $isWith = false) { // 关联查询 $with = $isWith ? ['orderGoods' => ['image'], 'orderGoodsAll' => ['image'], 'address','shops'] : []; // 获取记录 $detail = static::detail([ 'user_id' => UserService::getCurrentLoginUserId(), 'order_refund_id' => $orderRefundId ], $with); // $detail = static::where("order_refund_id",$orderRefundId)->find(); if (empty($detail)) throwError('未找到该售后单'); if (!$detail['order_goods_id']) { // 整单退款 $orderGoods = $detail['orderGoodsAll']; } else { $orderGoods = [$detail['orderGoods']]; } unset($detail['orderGoods'], $detail['orderGoodsAll']); $detail['orderGoods'] = $orderGoods; return $detail; } /** * 订单商品详情 * @param int $orderGoodsId 订单商品ID * @return \app\common\model\OrderGoods|null * @throws BaseException */ public function getRefundGoods(int $orderGoodsId) { $goods = OrderGoodsModel::detail($orderGoodsId); if (isset($goods['refund']) && !empty($goods['refund'])) { throwError('当前商品已申请售后'); } return $goods; } /** * 用户撤销申请 * @param $data * @return false|int */ public function revoke() { $user = UserService::getCurrentLoginUser(true); $type = false; if($this['status'] == RefundStatusEnum::REJECTED){//已拒绝 $type = true; }else{ if($this['status'] == RefundStatusEnum::NORMAL){//进行中&待审核 if($this['delivery_type']==10){ if ($this['type'] == RefundTypeEnum::RETURN) { if ($this['audit_status_zg'] == AuditStatusEnum::WAIT) { $type = true; } }else{ if ($this['audit_status'] == AuditStatusEnum::WAIT) { //仅退款不需要主管审核 $type = true; } } } //自提单 当门店未审核时可以撤回 if($this['delivery_type']==20){ if ($this['audit_status'] == AuditStatusEnum::WAIT) { //仅退款不需要主管审核 $type = true; } } } } if($type){ return $this->transaction(function () use ($user) { if($this['delivery_type']==10){ $this->save([ 'status' => RefundStatusEnum::CANCELLED, ]); } //门店自提单自动关闭 if($this['delivery_type']==20){ $this->save([ 'status' => RefundStatusEnum::CLOSE, ]); } //订单商品解冻 OrderGoodsModel::updateBase(['frozen_status'=>0], ['order_goods_id'=>$this['order_goods_id']]); $json_str = json_encode(["买家已撤销申请,退款已关闭"]); (new RefundHisModel())->add($this['order_refund_id'],$user['nick_name'],4,$json_str,'','买家','撤销申请'); return true; }); } $this->error = '当前售后单不合法,不允许该操作'; return false; } /** * 用户发货 * @param $data * @return false|int */ public function delivery(array $data) { if ( $this['type'] != RefundTypeEnum::RETURN || $this['audit_status_zg'] != AuditStatusEnum::REVIEWED || $this['is_user_send'] != 0 ) { $this->error = '当前售后单不合法,不允许该操作'; return false; } if ($data['expressId'] <= 0) { $this->error = '请选择物流公司'; return false; } if (empty($data['expressNo'])) { $this->error = '请填写物流单号'; return false; } if (empty($data['expressCompany'])) { $this->error = '请填写物流公司名称'; return false; } if (isset($data['expressDesc']) && mb_strlen($data['expressDesc'])>50) { $this->error = '退货字数上限超过了50字'; return false; } $express = ExpressModel::detail($data['expressId']); // 请求快递100订阅接口 $subscribe = KuaidiService::subscribe($data['expressNo'], 2,$express['kuaidi100_code']??''); if(!$subscribe->result){ if(stripos($subscribe->message,"重复订阅") === false){ //重复订阅允许提交物流 $this->error = '物流单号订阅异常:'.$subscribe->message; return false; } } $user = UserService::getCurrentLoginUser(true); return $this->transaction(function () use ($data,$user) { $this->save([ 'is_user_send' => 1, 'send_time' => time(), 'express_id' => (int)$data['expressId'], 'express_no' => $data['expressNo'], 'express_company' => $data['expressCompany'], 'express_desc' => $data['expressDesc']??'', ]); $json_str = json_encode(["买家寄回商品","快递公司:".$data['expressCompany'],"物流单号:".$data['expressNo']]); (new RefundHisModel())->add($this['order_refund_id'],$user['nick_name'],7,$json_str,'','买家','买家填写物流单号'); return true; }); } /** * 门店审核售后单 * @param $data * @return false|int */ public function auditStatus($param,$user){ // 验证订单是否合法 // 条件1: 门店审核状态不在审核中 // 条件2: 售后单状态不在进行中 if ($this['audit_status'] != 0 || $this['status'] != 0) { $this->error = '该售后单已经处理'; return false; } return $this->transaction(function () use ($param,$user) { // 更新售后单状态 $status = $this->save([ 'audit_status' => $param['audit_status'], 'refuse_desc' => $param['audit_status']==20 ? $param['refuse_desc'] : '', 'refuse_images' => $param['audit_status']==20 ? $param['refuse_images']??'' : '', 'status' => $param['audit_status']==20 ? 40 : 0, 'hx_refund_time' => time(), 'hx_refund_user_id' => UserService::getCurrentLoginUserId(), 'is_user_send' => 1, 'is_receipt' => 1, ]); if($this['order_goods_id']>0) { // OrderGoodsModel::where('order_goods_id', $this['order_goods_id'])->update(['frozen_status' => 0]); } if($param['audit_status']==20){ $json_str = json_encode(["处理结果:拒绝","拒绝理由:".$param['refuse_desc'],"门店拒绝退货,退款单关闭"]); $his_type = 13; $name = $this['shops']['shop_name']; $pf_operator = $user['nick_name']."(".$user['mobile'].")"; (new RefundHis())->add($this['order_refund_id'],$name,$his_type,$json_str,$param['refuse_images'],$pf_operator,'拒绝并关闭退货单'); }else{ $json_str = json_encode(["处理结果:同意","门店同意退货,等待财务退款"]); $his_type = 12; $name = $this['shops']['shop_name']; $pf_operator = $user['nick_name']."(".$user['mobile'].")"; (new RefundHis())->add($this['order_refund_id'],$name,$his_type,$json_str,'',$pf_operator,'同意退货并确认收货'); } return $status; }); } /** * 新增售后单记录 * @param int $orderGoodsId 订单商品ID * @param array $data 用户提交的表单数据 * @return mixed * @throws BaseException */ public function apply(int $orderGoodsId, array $data) { // 订单商品详情 $goods = $this->getRefundGoods($orderGoodsId); return $this->transaction(function () use ($orderGoodsId, $data, $goods) { // 新增售后单记录 $this->save([ 'order_goods_id' => $orderGoodsId, 'order_id' => $goods['order_id'], 'user_id' => UserService::getCurrentLoginUserId(), 'type' => $data['type'], 'apply_desc' => $data['content'], 'audit_status' => AuditStatusEnum::WAIT, 'status' => 0, 'store_id' => self::$storeId ]); // 记录凭证图片关系 if (isset($data['images']) && !empty($data['images'])) { $this->saveImages((int)$this['order_refund_id'], $data['images']); } return true; }); } /** * 记录售后单图片 * @param int $orderRefundId 售后单ID * @param array $images 图片列表 * @return bool */ private function saveImages(int $orderRefundId, array $images) { // 生成评价图片数据 $data = []; foreach ($images as $imageId) { $data[] = [ 'order_refund_id' => $orderRefundId, 'image_id' => $imageId, 'store_id' => self::$storeId ]; } return !empty($data) && (new OrderRefundImage)->addAll($data) !== false; } }