// +---------------------------------------------------------------------- namespace App\Services\Common; use App\Models\AccountModel; use App\Models\ActionLogModel; use App\Models\DriverModel; use App\Models\GoodsModel; use App\Models\MemberModel; use App\Models\OrderFreightModel; use App\Models\OrderModel; use App\Models\ScoreGoodsModel; use App\Services\Api\MessageService; use App\Services\BaseService; use App\Services\ConfigService; use App\Services\RedisService; use Illuminate\Support\Facades\DB; /** * 积分商城订单管理-服务类 * @author laravel开发员 * @since 2020/11/11 * Class OrderService * @package App\Services\Common */ class OrderService extends BaseService { // 静态对象 protected static $instance = null; /** * 构造函数 * @author laravel开发员 * @since 2020/11/11 * OrderService constructor. */ public function __construct() { $this->model = new OrderModel(); } /** * 静态入口 * @return static|null */ public static function make() { if (!self::$instance) { self::$instance = (new static()); } return self::$instance; } /** * @param $params * @param int $pageSize * @return array */ public function getDataList($params, $pageSize = 15) { $where = ['a.mark' => 1]; $status = isset($params['status']) ? $params['status'] : 0; $userId = isset($params['user_id']) ? $params['user_id'] : 0; $serviceType = isset($params['service_type']) ? $params['service_type'] : 0; $deliveryType = isset($params['delivery_type']) ? $params['delivery_type'] : 0; $travelType = isset($params['travel_type']) ? $params['travel_type'] : 0; $driverId = isset($params['driver_id']) ? $params['driver_id'] : 0; $payStyle = isset($params['pay_style']) ? $params['pay_style'] : 0; $type = isset($params['type']) ? $params['type'] : 0; if ($driverId > 0) { $where['a.driver_id'] = $driverId; } if ($status > 0) { $where['a.status'] = $status; } if ($type > 0) { $where['a.type'] = $type; } if ($payStyle > 0) { $where['a.pay_style'] = $payStyle; } if ($serviceType > 0) { $where['a.service_type'] = $serviceType; } if ($deliveryType > 0) { $where['a.delivery_type'] = $deliveryType; } if ($travelType > 0) { $where['a.travel_type'] = $travelType; } $model = $this->model->with(['agent','carCategory','payUser'])->from('orders as a') ->leftJoin('member as b', 'a.user_id', '=', 'b.id') ->leftJoin('driver as c', 'c.id', '=', 'a.driver_id') ->leftJoin('agent as d', 'd.id', '=', 'a.agent_id') ->where($where) ->where(function ($query) use ($params) { $keyword = isset($params['keyword']) ? $params['keyword'] : ''; if ($keyword) { $query->where('a.order_no', 'like', "%{$keyword}%")->orWhere('a.deposit_order_no', 'like', "%{$keyword}%"); } }) ->where(function ($query) use ($params) { $account = isset($params['account']) ? $params['account'] : ''; if ($account) { $query->where('b.nickname', 'like', "%{$account}%")->orWhere('b.mobile', 'like', "%{$account}%"); } }) ->where(function ($query) use ($params) { $driver = isset($params['driver']) ? $params['driver'] : ''; if ($driver) { $query->where('c.realname', 'like', "%{$driver}%")->orWhere('c.mobile', 'like', "%{$driver}%"); } }) ->where(function ($query) use ($params) { $agent = isset($params['agent']) ? $params['agent'] : ''; if ($agent) { $query->where('d.realname', 'like', "%{$agent}%")->orWhere('d.mobile', 'like', "%{$agent}%"); } }) ->where(function ($query) use ($userId) { if($userId){ $query->where('a.user_id', '=', $userId); } }) ->select(['a.*', 'b.nickname as buy_nickname', 'b.mobile as buy_mobile', 'c.realname as driver_name', 'c.mobile as driver_mobile','c.car_number']) ->orderBy('a.create_time', 'desc') ->orderBy('a.pay_time', 'desc') ->orderBy('a.id', 'desc'); $countModel = clone $model; $countModel1 = clone $model; $counts = [ 'total'=> $countModel->count('a.pay_money'), 'count'=> $countModel1->count('a.id'), ]; $list = $model->paginate($pageSize > 0 ? $pageSize : 9999999); $list = $list ? $list->toArray() : []; if ($list) { foreach ($list['data'] as &$item) { $item['create_time'] = $item['create_time'] ? datetime($item['create_time'], 'Y-m-d H:i:s') : ''; $item['pay_time'] = $item['pay_time'] ? datetime($item['pay_time'], 'Y-m-d H:i:s') : ''; $item['delivery_distance'] = $item['delivery_distance'] ? moneyFormat($item['delivery_distance']/1000,2) : '0.00'; $item['freight'] = []; if($item['service_type'] == 2){ $item['freight'] = $this->getFreightList($item['order_no']); } $payUser = $item['pay_user']? $item['pay_user'] : []; $item['receipt_nickname'] = isset($payUser['nickname'])? $payUser['nickname'] : ''; $item['receipt_mobile'] = isset($payUser['mobile'])? $payUser['mobile'] : ''; } } return [ 'pageSize' => $pageSize, 'total' => isset($counts['count']) ? $counts['count'] : 0, 'counts' => $counts, 'list' => isset($list['data']) ? $list['data'] : [] ]; } /** * 订单货物列表 * @param $orderNo * @return array|mixed */ public function getFreightList($orderNo) { $cacheKey = "caches:orders:freight:{$orderNo}"; $datas = RedisService::get($cacheKey); if($datas){ return $datas; } $datas = OrderFreightModel::with(['package','spec'])->where(['order_no'=> $orderNo,'mark'=>1]) ->select(['id','goods_name','package_id','price','total','spec_id','thumb','albums','accept_albums','num','volume','length','height','weight','car_remark']) ->get(); $datas = $datas? $datas->toArray() : []; if($datas){ foreach ($datas as &$item){ $item['thumb'] = $item['thumb']? get_image_url($item['thumb']): ''; $item['albums'] = $item['albums']? get_images_preview($item['albums']): []; $item['accept_albums'] = $item['accept_albums']? get_images_preview($item['accept_albums']): []; } unset($item); RedisService::set($cacheKey, $datas, rand(300,600)); } return $datas; } /** * 按日期统计订单数 * @param string $beginAt 开始时间 * @param string $endAt 结束时间 * @param int[] $status 状态:数组或数值 * @return mixed */ public function getCountByTime($beginAt='', $endAt='', $status=4, $serviceType=0) { $where = ['mark' => 1]; return $this->model->where($where)->where(function($query) use($beginAt,$endAt,$status,$serviceType){ if($beginAt && $endAt){ $query->whereBetween('create_time', [strtotime($beginAt), strtotime($endAt)]); }else if($beginAt){ $query->where('create_time','>=', strtotime($beginAt)); } if($status && is_array($status)){ $query->whereIn('status',$status); }else if($status){ $query->where('status',$status); } // 订单服务类型 if($serviceType){ $query->where('service_type',$serviceType); } })->count('id'); } /** * 待处理订单数 * @return int[] */ public function countByWait() { $cacheKey = "caches:orders:counts"; $counts = RedisService::get($cacheKey); if($counts){ return $counts; } $counts = [ 'travel'=> 0, // 出行订单,待处理数量 'freight'=> 0, // 快运订单,待处理数 ]; $type = request()->post('service_type', 0); if($type == 0 || $type == 1){ $counts['travel'] = $this->model->whereIn('status',[1,2,3,4,7])->where(function($query){ $query->where('pay_status',1)->orWhere('deposit_status',1); })->where(['service_type'=>1,'mark'=>1])->where('create_time','>=',time() - 600)->count('id'); } if($type == 0 || $type == 2){ $counts['freight'] = $this->model->whereIn('status',[1,2,3,4,7])->where(function($query){ $query->where('pay_status',1)->orWhere('deposit_status',1); })->where(['service_type'=>2,'mark'=>1])->where('create_time','>=',time() - 600)->count('id'); } RedisService::set($cacheKey, $counts, rand(2,5)); return $counts; } /** * 添加或编辑 * @return array * @since 2020/11/11 * @author laravel开发员 */ public function edit() { $params = request()->post(); $data = [ 'id'=> isset($params['id'])? intval($params['id']) : 0, 'update_time'=> time(), ]; if(isset($params['status'])){ $data['status'] = intval($params['status']); } if(isset($params['exception_remark'])){ $data['exception_remark'] = intval($params['exception_remark']); } if(isset($params['cancel_type'])){ $data['cancel_type'] = intval($params['cancel_type']); } if(isset($params['remark'])){ $data['remark'] = intval($params['remark']); } if(isset($params['driver_id'])){ $data['driver_id'] = intval($params['driver_id']); } $status = isset($data['status'])? $data['status'] : 0; $deiverId = isset($data['driver_id'])? $data['driver_id'] : 0; if($status>=3 && $deiverId<=0){ return message('该订单未接单,状态不可修改未接单后状态',false); } return parent::edit($data); // TODO: Change the autogenerated stub } /** * 异常 * @return bool */ public function exception() { $params = request()->all(); $id = isset($params['id'])? intval($params['id']) : 0; // 订单ID $remark = isset($params['exception_remark'])? trim($params['exception_remark']) : ''; // 异常备注 $cacheKey = "caches:orders:exception_lock:{$id}"; if(RedisService::get($cacheKey)){ $this->error = 1034; return false; } // 缓存锁 RedisService::set($cacheKey, ['id'=> $id], rand(2,3)); $orderInfo = $this->model->with(['member','driver','payment'])->where(['id'=> $id,'mark'=>1]) ->select(['id','order_no','pay_money','user_id','driver_id','deposit','deposit_order_no','transaction_id','coupon_id','service_type','pay_style','pay_type','status']) ->first(); $orderStatus = isset($orderInfo['status'])? $orderInfo['status'] : 0; $orderUserId = isset($orderInfo['user_id'])? $orderInfo['user_id'] : 0; $orderDriverId = isset($orderInfo['driver_id'])? $orderInfo['driver_id'] : 0; $orderNo = isset($orderInfo['order_no'])? $orderInfo['order_no'] : ''; if(empty($id) || empty($orderInfo)){ $this->error = 2128; return false; } // 接单订单状态 if(!in_array($orderStatus,[3,7])){ $this->error = 2129; return false; } // 司机信息 $driverInfo = DriverModel::where(['id'=> $orderDriverId, 'mark'=>1]) ->select(['id','mobile','realname','car_number','status']) ->first(); $status = isset($driverInfo['status'])? $driverInfo['status'] : 0; $realname = isset($driverInfo['realname'])? $driverInfo['realname'] : ''; // 订单处理 DB::beginTransaction(); if(!$this->model->where(['id'=> $id,'mark'=>1])->update(['status'=> 6,'exception_remark'=> $remark,'update_time'=>time()])){ DB::rollBack(); $this->error = 1003; return false; } DB::commit(); // 消息推送给用户 $memberInfo = isset($orderInfo['member'])? $orderInfo['member'] : []; $nickname = isset($memberInfo['nickname'])? $memberInfo['nickname'] : ''; if($memberInfo){ $params = [ 'title' => "订单异常通知", 'description' => "您的订单【{$orderNo}】已被平台处理为异常订单,请及时查看订单进度", 'type' => 2, // 1-公告通知,2-订单通知,3-交易通知,4-其他 'content' => json_encode([ 'order_no' => ['name' => '订单号', 'text' => $orderNo], 'catch_time' => ['name' => '处理时间', 'text' => date('Y-m-d H:i:s')], 'realname' => ['name' => '司机', 'text' => $realname], 'remark' => ['name' => '异常备注', 'text' => $remark], 'status' => ['name' => '状态', 'text' => '订单异常'], ], 256), 'bind_id' => $id, ]; // 推送消息给用户处理 MessageService::make()->pushMessage($orderUserId, $params); } // 消息推送给司机 if($driverInfo){ $params = [ 'title' => "订单异常通知", 'description' => "您的订单【{$orderNo}】已被平台处理为异常订单,请及时查看订单进度", 'type' => 2, // 1-公告通知,2-订单通知,3-交易通知,4-其他 'content' => json_encode([ 'order_no' => ['name' => '订单号', 'text' => $orderNo], 'catch_time' => ['name' => '处理时间', 'text' => date('Y-m-d H:i:s')], 'nickname' => ['name' => '用户', 'text' => $nickname], 'remark' => ['name' => '异常备注', 'text' => $remark], 'status' => ['name' => '状态', 'text' => '订单异常'], ], 256), 'bind_id' => $id, ]; // 推送消息给用户处理 MessageService::make()->pushMessage($orderDriverId, $params, 2); } // 设置日志标题 ActionLogModel::setTitle("订单异常处理"); ActionLogModel::record(); // 更新校验数据 $cacheCheckKey = "caches:orders:check:{$id}"; $data = [ 'status'=> 6, 'order_no'=> $orderNo, 'pay_money'=> $orderInfo['pay_money'], 'cancel_type'=> 3, ]; RedisService::set($cacheCheckKey, $data, rand(10,20)); $this->error = 1002; return true; } /** * 订单取消 * @return bool */ public function cancel() { $params = request()->post(); if(!\App\Services\Api\OrderService::make()->cancel(0, $params,4)){ $this->error = \App\Services\Api\OrderService::make()->getError(); return false; }else{ // 设置日志标题 ActionLogModel::setTitle("订单取消处理"); ActionLogModel::record(); $this->error = \App\Services\Api\OrderService::make()->getError(); return true; } } /** * 订单完成 * @return bool */ public function complete() { $params = request()->post(); if(!\App\Services\Api\OrderService::make()->complete(0, $params,4)){ $this->error = \App\Services\Api\OrderService::make()->getError(); return false; }else{ // 设置日志标题 ActionLogModel::setTitle("订单完成处理"); ActionLogModel::record(); $this->error = \App\Services\Api\OrderService::make()->getError(); return true; } } /** * 删除 * @return array */ public function delete() { RedisService::keyDel("caches:orders:check*"); return parent::delete(); // TODO: Change the autogenerated stub } }