| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578 |
- <?php
- // +----------------------------------------------------------------------
- // | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
- // +----------------------------------------------------------------------
- // | 版权所有 2017~2021 LARAVEL研发中心
- // +----------------------------------------------------------------------
- // | 官方网站: http://www.laravel.cn
- // +----------------------------------------------------------------------
- // | Author: laravel开发员 <laravel.qq.com>
- // +----------------------------------------------------------------------
- namespace App\Services\Api;
- use App\Models\GoodsModel;
- use App\Models\MemberModel;
- use App\Models\OrderGoodsModel;
- use App\Models\OrderModel;
- use App\Services\BaseService;
- use App\Services\ConfigService;
- use App\Services\RedisService;
- use Illuminate\Support\Facades\DB;
- use wxkxklmyt\Scws;
- /**
- * 订单-服务类
- * @author laravel开发员
- * @since 2020/11/11
- * @package App\Services\Api
- */
- class OrderService extends BaseService
- {
- // 静态对象
- protected static $instance = null;
- /**
- * 构造函数
- * @author laravel开发员
- * @since 2020/11/11
- */
- public function __construct()
- {
- $this->model = new OrderModel();
- }
- /**
- * 静态入口
- */
- 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];
- $list = $this->model->from('orders as a')->with(['goods','user'])
- ->leftJoin('member as b', 'b.id', '=', 'a.buy_user_id')
- ->where($where)
- ->where(function ($query) use ($params) {
- $keyword = isset($params['keyword']) ? $params['keyword'] : '';
- if ($keyword) {
- $query->where('a.order_no', 'like', "%{$keyword}%")
- ->orWhere('b.username', 'like', "%{$keyword}%")
- ->orWhere('b.nickname', 'like', "%{$keyword}%")
- ->orWhere('b.mobile', 'like', "%{$keyword}%");
- }
- })
- ->where(function ($query) use ($params) {
- $userId = isset($params['user_id']) ? $params['user_id'] : 0;
- if ($userId) {
- $query->where(function($query) use($userId){
- $query->where('a.user_id', $userId)
- ->orWhere('a.buy_user_id', $userId);
- });
- }
- $driverId = isset($params['driver_id']) ? $params['driver_id'] : 0;
- if ($driverId) {
- $query->where('a.driver_id', '=', $driverId);
- }
- $orderType = isset($params['order_type']) ? $params['order_type'] : 0;
- if ($orderType > 0) {
- $query->where('a.order_type', '=', $orderType);
- }
- })
- ->where(function ($query) use ($params) {
- $status = isset($params['status']) ? $params['status'] : 0;
- // 进行中
- if ($status>0) {
- $query->where('a.status', $status);
- }
- })
- ->select(['a.*'])
- ->orderBy('a.status', 'asc')
- ->orderBy('a.create_time', 'desc')
- ->orderBy('a.pay_at', 'desc')
- ->orderBy('a.id', 'desc')
- ->paginate($pageSize > 0 ? $pageSize : 9999999);
- $list = $list ? $list->toArray() : [];
- if ($list) {
- $statusArr = [1 => '待审核', 2 => '待捡货', 3 => '捡货中', 4 => '已发货', 5 => '已送达', 6 => '已结账'];
- foreach ($list['data'] as &$item) {
- $item['create_time'] = $item['create_time'] ? datetime($item['create_time'], 'Y-m-d H:i:s') : '';
- $status = isset($item['status']) ? $item['status'] : 0;
- $item['status_text'] = '待审核';
- if ($status) {
- $item['status_text'] = isset($statusArr[$status]) ? $statusArr[$status] : '';
- }
- $item['goods'] = isset($item['goods']) && $item['goods']? $item['goods'] : [];
- }
- unset($item);
- }
- return [
- 'pageSize' => $pageSize,
- 'total' => isset($list['total']) ? $list['total'] : 0,
- 'list' => isset($list['data']) ? $list['data'] : []
- ];
- }
- /**
- * 订单详情
- * @param $id
- */
- public function getOrderInfo($id)
- {
- $statusArr = [1 => '待审核', 2 => '待捡货', 3 => '捡货中', 4 => '已发货', 5 => '已送达', 6 => '已结账'];
- $info = $this->model->from('orders as a')->with(['goods', 'user'])
- ->leftJoin('member as b', 'b.id', '=', 'a.buy_user_id')
- ->where(['a.id' => $id, 'a.mark' => 1])
- ->select(['a.*'])
- ->first();
- if ($info) {
- $info = $info->toArray();
- $info['create_time'] = $info['create_time'] ? datetime($info['create_time'], 'Y-m-d H:i:s') : '';
- $status = isset($info['status']) ? $info['status'] : 0;
- $info['status_text'] = '待付款';
- if ($status) {
- $info['status_text'] = isset($statusArr[$status]) ? $statusArr[$status] : '';
- }
- $info['goods'] = isset($info['goods'])&&$info['goods']? $info['goods'] : [];
- }
- return $info;
- }
- /**
- * 创建订单
- * @param $userId 用户
- * @param $params 参数
- * @return array|false
- */
- public function createOrder($userId, $params)
- {
- $orderType = isset($params['order_type']) && $params['order_type'] ? intval($params['order_type']) : 1;
- $prePayStatus = isset($params['pre_pay_status']) && $params['pre_pay_status']? intval($params['pre_pay_status']) : 1;
- $prePayMoney = isset($params['pre_pay_money']) && $params['pre_pay_money']? floatval($params['pre_pay_money']) : 0;
- $isAfter = isset($params['is_after']) && $params['is_after']? intval($params['is_after']) : 1;
- $afterType = isset($params['after_type']) && $params['after_type']? intval($params['after_type']) : 0;
- $num = isset($params['num']) ? intval($params['num']) : 0;
- $total = isset($params['total']) ? floatval($params['total']) : 0;
- $buyUserId = isset($params['buy_user_id']) ? floatval($params['buy_user_id']) : 0;
- $stockId = isset($params['stock_id']) ? intval($params['stock_id']) : 0;
- $goods = isset($params['goods']) && $params['goods'] ? $params['goods'] : [];
- $goodsIds = $goods? array_keys($goods) : [];
- $goodsIds = array_filter($goodsIds); // 过滤空
- // 参数验证
- if (!in_array($orderType, [1, 2])) {
- $this->error = 2102;
- return false;
- } else if (empty($goods) || empty($goodsIds) || !is_array($goods) || $num<=0) {
- $this->error = 2103;
- return false;
- } else if ($orderType == 2 && $buyUserId <=0) {
- $this->error = 2104;
- return false;
- }
- if ($prePayStatus > 1 && $prePayMoney<=0) {
- $this->error = 2105;
- return false;
- }
- if ($isAfter > 1 && $afterType<=0) {
- $this->error = 2106;
- return false;
- }
- // 缓存锁
- $cacheLockKey = "caches:orders:submit_lock:{$userId}_{$orderType}";
- if (RedisService::get($cacheLockKey)) {
- $this->error = 2107;
- return false;
- }
- if($stockId<=0){
- $this->error = 2033;
- return false;
- }
- // 验证用户信息
- RedisService::set($cacheLockKey, ['params' => $params, 'user_id' => $userId], rand(2, 3));
- $userInfo = MemberModel::where(['id' => $userId, 'mark' => 1])
- ->select(['id','username', 'mobile', 'nickname', 'address', 'status'])
- ->first();
- $status = isset($userInfo['status']) ? $userInfo['status'] : 0;
- $nickname = isset($userInfo['nickname']) ? trim($userInfo['nickname']) : '';
- $contact = isset($userInfo['mobile']) ? trim($userInfo['mobile']) : '';
- $address = isset($userInfo['address']) ? trim($userInfo['address']) : '';
- if (empty($userInfo) || $status != 1) {
- $this->error = 2015;
- RedisService::clear($cacheLockKey);
- return false;
- }
- if(empty($nickname) || empty($address) || empty($contact)){
- $this->error = "203{$orderType}";
- RedisService::clear($cacheLockKey);
- return false;
- }
- // 验证商品
- $buyGoods = GoodsService::make()->getListByIds($goods, true);
- if(empty($buyGoods)){
- $this->error = 2108;
- RedisService::clear($cacheLockKey);
- return false;
- }
- // 统计购买商品数据
- $buyNum = 0;
- $buyTotal = 0;
- $originalTotal = 0;
- $orderNo = get_order_num('YD');
- $orderGoods = [];
- foreach ($buyGoods as $item){
- $goodsId = isset($item['goods_id'])? $item['goods_id'] : 0;
- $price = isset($item['price'])? $item['price'] : 0;
- $goodsNum = isset($item['num'])? $item['num'] : 0;
- $category = isset($item['category'])? $item['category'] : [];
- $realPrice = isset($item['real_price']) && $item['real_price']>0? floatval($item['real_price']) : $price;
- $goodsTotal = round($realPrice * $goodsNum, 2);
- $goodsOriginalTotal = round($price * $goodsNum, 2);
- if($goodsId && $goodsTotal>0){
- $buyNum++;
- $originalTotal += $goodsOriginalTotal;
- $buyTotal += $goodsTotal;
- $orderGoods[] = [
- 'goods_id'=> $goodsId,
- 'user_id'=> $orderType==2? $buyUserId : $userId,
- 'order_no'=> $orderNo,
- 'price'=> $realPrice,
- 'original_price'=> $price,
- 'goods_name'=> isset($item['goods_name'])? $item['goods_name'] : '',
- 'stock_id'=> $stockId,
- 'brand_id'=> isset($item['brand_id'])? $item['brand_id'] : 0,
- 'cate_id'=> isset($item['cate_id'])? $item['cate_id'] : 0,
- 'cate_name'=> isset($category['cate_name'])? $category['cate_name'] : '',
- 'settle_type'=> isset($item['settle_type'])? $item['settle_type'] : 0,
- 'settle_rate'=> isset($item['settle_rate'])? $item['settle_rate'] : 0,
- 'settle_num'=> isset($item['settle_num'])? $item['settle_num'] : 0,
- 'supplier_name'=> isset($item['supplier_name'])? $item['supplier_name'] : '',
- 'spec'=> isset($item['spec'])? $item['spec'] : '',
- 'thumb'=> isset($item['thumb']) && $item['thumb']? get_image_path($item['thumb']) : '',
- 'unit'=> isset($item['unit'])? $item['unit'] : '',
- 'unit1'=> isset($item['unit1'])? $item['unit1'] : '',
- 'unit1_num'=> isset($item['unit1_num'])? $item['unit1_num'] :0,
- 'num'=> $goodsNum,
- 'create_time'=> time(),
- 'update_time'=> time(),
- 'status'=> 1,
- 'mark'=> 1,
- ];
- }
- }
- if(intval($buyTotal) != intval($total)){
- $this->error = 2115;
- RedisService::clear($cacheLockKey);
- return false;
- }
- // 订单数据
- $order = [
- 'order_no'=> $orderNo,
- 'user_id'=> $userId,
- 'buy_user_id'=> $orderType==2? $buyUserId : $userId,
- 'delivery_user_id'=>$orderType==2? $userId : 0,
- 'order_type'=> $orderType,
- 'stock_id'=> $stockId,
- 'num'=> $buyNum,
- 'total'=> $buyTotal,
- 'original_total'=> $originalTotal,
- 'pay_status'=> 3,
- 'pre_pay_status'=> $prePayStatus,
- 'pre_pay_money'=> $prePayStatus>1?$prePayMoney:0,
- 'pre_pay_remark'=> isset($params['pre_pay_remark']) && $prePayStatus>1? trim($params['pre_pay_remark']) : '',
- 'customer_name'=> $nickname,
- 'customer_contact'=> $contact,
- 'customer_address'=> $address,
- 'is_after'=> $isAfter,
- 'after_type'=> $isAfter>1?$afterType:0,
- 'after_money'=> isset($params['after_money']) && $isAfter>1? floatval($params['after_money']) : 0,
- 'after_remark'=> isset($params['after_remark']) && $isAfter>1? trim($params['after_remark']) : '',
- 'create_time'=> time(),
- 'update_time'=> time(),
- 'updated_at'=> date('Y-m-d H:i:s'),
- 'is_cancel'=> 2,
- 'status'=> 1,
- 'mark'=> 1,
- ];
- // 订单处理
- DB::beginTransaction();
- if(!$orderId = $this->model->insertGetId($order)){
- DB::rollBack();
- $this->error = 2109;
- RedisService::clear($cacheLockKey);
- return false;
- }
- // 订单商品
- if(!OrderGoodsModel::insert($orderGoods)){
- DB::rollBack();
- $this->error = 2110;
- RedisService::clear($cacheLockKey);
- return false;
- }
- DB::commit();
- // 订单下单统计数据处理
- $this->error = "211{$orderType}";
- RedisService::clear($cacheLockKey);
- return ['order_id'=> $orderId,'total'=> $buyTotal,'num'=> $buyNum,'goods'=> $goods];
- }
- /**
- * 收货处理
- * @param $driverId
- * @param $params
- * @return bool
- */
- public function receive($driverId, $params)
- {
- $id = isset($params['id']) ? intval($params['id']) : 0; // 订单ID
- $cacheKey = "caches:orders:receive_lock:{$id}_{$driverId}";
- if (RedisService::get($cacheKey)) {
- $this->error = 1034;
- return false;
- }
- // 缓存锁
- RedisService::set($cacheKey, ['id' => $id, 'driver_id' => $driverId], 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_status', 'pay_status', 'deposit_order_no', 'transaction_id', 'coupon_id', 'service_type', 'pay_style', 'pay_type', 'status'])
- ->first();
- $orderStatus = isset($orderInfo['status']) ? $orderInfo['status'] : 0;
- $payStatus = isset($orderInfo['pay_status']) ? $orderInfo['pay_status'] : 0;
- $depositStatus = isset($orderInfo['deposit_status']) ? $orderInfo['deposit_status'] : 0;
- $payStyle = isset($orderInfo['pay_style']) ? $orderInfo['pay_style'] : 0;
- $serviceType = isset($orderInfo['service_type']) ? $orderInfo['service_type'] : 0;
- $orderUserId = isset($orderInfo['user_id']) ? $orderInfo['user_id'] : 0;
- $orderNo = isset($orderInfo['order_no']) ? $orderInfo['order_no'] : '';
- if (empty($id) || empty($orderInfo)) {
- $this->error = 2128;
- return false;
- }
- // 验证订单状态,到付订单(可未支付,只支付诚意金)或已支付订单
- if (($payStyle == 1 && $payStatus != 1) || ($payStyle == 2 && $depositStatus != 1)) {
- $this->error = 2129;
- return false;
- }
- // 验证状态
- if ($orderStatus != 7) {
- $this->error = 2146;
- return false;
- }
- // 司机信息
- $driverInfo = DriverModel::where(['id' => $driverId, 'mark' => 1])
- ->select(['id', 'mobile', 'realname', 'car_number', 'is_online', 'status'])
- ->first();
- $status = isset($driverInfo['status']) ? $driverInfo['status'] : 0;
- $isOnline = isset($driverInfo['is_online']) ? $driverInfo['is_online'] : 0;
- $realname = isset($driverInfo['realname']) ? $driverInfo['realname'] : '';
- $carNumber = isset($driverInfo['car_number']) ? $driverInfo['car_number'] : '';
- if (empty($driverInfo) || $status != 2) {
- $this->error = 2024;
- return false;
- }
- // 司机未在线
- if ($isOnline != 1) {
- $this->error = 2145;
- return false;
- }
- // 接单处理
- DB::beginTransaction();
- if (!$this->model->where(['id' => $id, 'mark' => 1])->update(['status' => 3, 'update_time' => time()])) {
- DB::rollBack();
- $this->error = $serviceType == 1 ? 2148 : 2147;
- return false;
- }
- DB::commit();
- // 消息推送
- $params = [
- 'title' => $serviceType == 1 ? "订单开始服务通知" : '订单开始配送通知',
- 'description' => "您的订单【{$orderNo}】" . ($serviceType == 1 ? '已开始服务' : '司机已取到货并开始配送') . ",请及时查看订单进度",
- 'type' => 2, // 1-公告通知,2-订单通知,3-交易通知,4-其他
- 'content' => json_encode([
- 'order_no' => ['name' => '订单号', 'text' => $orderNo],
- 'picker_time' => ['name' => '取货时间', 'text' => date('Y-m-d H:i:s')],
- 'realname' => ['name' => '司机', 'text' => $realname],
- 'car_number' => ['name' => '车牌号', 'text' => $carNumber],
- 'status' => ['name' => '状态', 'text' => $serviceType == 1 ? '服务中' : '配送中'],
- ], 256),
- 'bind_id' => $id,
- ];
- // 推送消息处理
- MessageService::make()->pushMessage($orderUserId, $params);
- $this->error = $serviceType == 1 ? 2149 : 2150;
- return true;
- }
- /**
- * 获取用户历史购买商品数据/列表
- * @param $userId
- * @param array $params
- * @param int $pageSize
- * @return array
- */
- public function getHistoryGoods($userId, $params = [], $pageSize = 0)
- {
- $cacheKey = "caches:goods:history:{$userId}_" . ($params ? md5(json_encode($params, 256)) : 0);
- $datas = RedisService::get($cacheKey);
- if (empty($datas)) {
- $showNum = ConfigService::make()->getConfigByCode('show_history_goods_num', 4);
- $pageSize = $pageSize ? $pageSize : $showNum;
- $model = GoodsModel::with(['category'])->from('goods as a')
- ->leftJoin('orders_goods as b', 'a.goods_id', '=', 'b.goods_id')
- ->leftJoin('orders as c', 'b.order_no', '=', 'c.order_no')
- ->leftJoin('goods_categorys as d', 'd.cate_id', '=', 'a.cate_id')
- ->whereIn('c.status', [1, 2, 3, 4, 5, 6])
- ->where(function($query) use($userId){
- $query->where('c.user_id', $userId)
- ->orWhere('c.buy_user_id', $userId);
- })
- ->where([ 'b.mark' => 1,'c.mark'=>1])
- ->where(function ($query) use ($params) {
- // 分类
- $cateId = isset($params['cate_id'])? $params['cate_id'] : 0;
- if($cateId){
- $query->where(function($query) use($cateId){
- $query->where('a.cate_id', $cateId)
- ->orWhere('d.pids','like',"%{$cateId},%");
- });
- }
- $keyword = isset($params['keyword']) ? $params['keyword'] : '';
- if ($keyword) {
- $scws = new Scws();
- $kws = $scws->scws($keyword,3,false);
- if(count($kws) >1){
- $query->where(function ($query) use ($kws) {
- foreach ($kws as $kw) {
- $kw = trim($kw);
- $query->where('a.goods_name', 'like', "%{$kw}%")
- ->where('a.keywords', 'like', "%{$kw}%");
- }
- });
- }else{
- $query->where(function ($query) use ($keyword){
- $query->where('a.goods_name','like',"%{$keyword}%")
- ->orWhere('a.goods_pinyin','like',"%{$keyword}%")
- ->orWhere('a.keywords', 'like', "%{$keyword}%");
- });
- }
- }
- })
- ->select(['a.*', 'a.price as real_price']);
- $sortType = isset($params['sort_type']) ? $params['sort_type'] : 0;
- if ($sortType == 1) {
- $model = $model->orderBy('a.sales', 'desc');
- } else if ($sortType == 2) {
- $model = $model->orderBy('a.sales', 'asc');
- } else if ($sortType == 3) {
- $model = $model->orderBy('a.price', 'desc');
- } else if ($sortType == 4) {
- $model = $model->orderBy('a.price', 'asc');
- } else {
- $model = $model->orderBy('a.create_time', 'desc');
- $model = $model->orderBy('a.goods_id', 'desc');
- }
- $list = $model->orderBy('c.create_time', 'desc')
- ->groupBy('a.goods_id')
- ->orderBy('a.goods_id', 'desc')
- ->paginate($pageSize > 0 ? $pageSize : 9999999);
- $list = $list ? $list->toArray() : [];
- if ($list) {
- foreach ($list['data'] as &$item) {
- $item['real_price'] = GoodsService::make()->getRealPrice($item);
- $item['discount_start_at'] = $item['discount_start_time'] ? date('Y-m-d H:i:s', $item['discount_start_time']) : '';
- $item['discount_end_at'] = $item['discount_end_time'] ? date('Y-m-d H:i:s', $item['discount_end_time']) : '';
- }
- }
- }
- $total = isset($list['total']) ? $list['total'] : 0;
- $result = [
- 'pageSize' => $pageSize,
- 'total' => $total,
- 'list' => isset($list['data']) ? $list['data'] : []
- ];
- if ($total) {
- RedisService::set($cacheKey, $result, rand(3, 5));
- }
- return $result;
- }
- /**
- * 订单统计数据
- * @param $userId
- * @return array|int[]|mixed
- */
- public function getCounts($userId)
- {
- $cacheKey = "caches:orders:counts:u_{$userId}";
- $counts = RedisService::get($cacheKey);
- if(empty($counts)){
- $counts = ['status1'=>0,'status2'=>0,'status3'=>0,'status4'=>0,'status5'=>0];
- $datas = $this->model->where(['user_id'=>$userId,'order_type'=>2,'mark'=>1])
- ->where('create_time','>=', time() - 600)
- ->whereBetween('status',[1,5])
- ->select("status",DB::raw("count(order_id) as count"))
- ->groupBy('status')
- ->get();
- $datas = $datas? $datas->toArray() : [];
- if($datas){
- foreach ($datas as $item){
- $status = isset($item['status'])? $item['status'] : 0;
- $count = isset($item['count'])? $item['count'] : 0;
- if($status>0 && $count>0 && isset($counts["status".$status])){
- $counts["status".$status] = $count;
- }
- }
- RedisService::set($cacheKey, $counts, rand(5, 10));
- }
- }
- return $counts;
- }
- }
|