OrderService.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
  4. // +----------------------------------------------------------------------
  5. // | 版权所有 2017~2021 LARAVEL研发中心
  6. // +----------------------------------------------------------------------
  7. // | 官方网站: http://www.laravel.cn
  8. // +----------------------------------------------------------------------
  9. // | Author: laravel开发员 <laravel.qq.com>
  10. // +----------------------------------------------------------------------
  11. namespace App\Services\Api;
  12. use App\Models\GoodsModel;
  13. use App\Models\MemberModel;
  14. use App\Models\OrderModel;
  15. use App\Services\BaseService;
  16. use App\Services\ConfigService;
  17. use App\Services\RedisService;
  18. use Illuminate\Support\Facades\DB;
  19. /**
  20. * 订单-服务类
  21. * @author laravel开发员
  22. * @since 2020/11/11
  23. * @package App\Services\Api
  24. */
  25. class OrderService extends BaseService
  26. {
  27. // 静态对象
  28. protected static $instance = null;
  29. /**
  30. * 构造函数
  31. * @author laravel开发员
  32. * @since 2020/11/11
  33. */
  34. public function __construct()
  35. {
  36. $this->model = new OrderModel();
  37. }
  38. /**
  39. * 静态入口
  40. */
  41. public static function make()
  42. {
  43. if (!self::$instance) {
  44. self::$instance = new static();
  45. }
  46. return self::$instance;
  47. }
  48. /**
  49. * 订单列表
  50. * @param $params
  51. * @param int $pageSize
  52. * @return array
  53. */
  54. public function getDataList($params, $pageSize = 15)
  55. {
  56. $model = $this->getQuery($params);
  57. // 数据
  58. $list = $model->where(function ($query) use ($params) {
  59. $status = isset($params['status']) ? $params['status'] : 0;
  60. // 进行中
  61. if ($status > 0 && is_array($status)) {
  62. $query->whereIn('a.status', $status);
  63. }else if($status>0){
  64. $query->where('a.status', $status);
  65. }
  66. })->select(['a.*'])
  67. ->orderBy('a.status', 'desc')
  68. ->orderBy('a.create_time', 'desc')
  69. ->orderBy('a.id', 'desc')
  70. ->paginate($pageSize > 0 ? $pageSize : 9999999);
  71. $list = $list ? $list->toArray() : [];
  72. if ($list) {
  73. $statusArr = [1 => '接单中', 2 => '进行中', 3 => '已完成'];
  74. foreach ($list['data'] as &$item) {
  75. $item['create_time'] = $item['create_time'] ? datetime($item['create_time'], 'Y-m-d H:i:s') : '';
  76. $status = isset($item['status']) ? $item['status'] : 0;
  77. $item['status_text'] = '接单中';
  78. if ($status) {
  79. $item['status_text'] = isset($statusArr[$status]) ? $statusArr[$status] : '';
  80. }
  81. $item['goods'] = isset($item['goods']) && $item['goods'] ? $item['goods'] : [];
  82. $item['goods']['shipper_phone_text'] = $item['goods']['shipper_phone']?format_mobile($item['goods']['shipper_phone']) : '';
  83. $item['goods']['receiver_phone_text'] = $item['goods']['receiver_phone']?format_mobile($item['goods']['receiver_phone']) : '';
  84. }
  85. unset($item);
  86. }
  87. return [
  88. 'pageSize' => $pageSize,
  89. 'total' => isset($list['total']) ? $list['total'] : 0,
  90. 'list' => isset($list['data']) ? $list['data'] : []
  91. ];
  92. }
  93. /**
  94. * 查询条件
  95. * @param $params
  96. * @return mixed
  97. */
  98. public function getQuery($params)
  99. {
  100. $where = ['a.mark' => 1];
  101. return $this->model->from('orders as a')->with(['goods'])
  102. ->leftJoin('member as b', 'b.id', '=', 'a.user_id')
  103. ->where($where)
  104. ->where(function($query) use($params){
  105. $userId = isset($params['user_id']) ? intval($params['user_id']) : 0;
  106. if($userId>0){
  107. $query->where('a.user_id', $userId);
  108. }
  109. })
  110. ->where(function ($query) use ($params) {
  111. $keyword = isset($params['keyword']) ? $params['keyword'] : '';
  112. if ($keyword) {
  113. $query->where('a.order_no', 'like', "%{$keyword}%")
  114. ->orWhere('b.nickname', 'like', "%{$keyword}%")
  115. ->orWhere('b.mobile', 'like', "%{$keyword}%");
  116. }
  117. });
  118. }
  119. /**
  120. * 订单详情
  121. * @param $id
  122. */
  123. public function getOrderInfo($id)
  124. {
  125. $statusArr = [1 => '待审核', 2 => '进行中', 3 => '已完成'];
  126. $info = $this->model->from('orders as a')->with(['goods'])
  127. ->leftJoin('member as b', 'b.id', '=', 'a.user_id')
  128. ->where(['a.id' => $id, 'a.mark' => 1])
  129. ->select(['a.*'])
  130. ->first();
  131. if ($info) {
  132. $info = $info->toArray();
  133. $info['create_time'] = $info['create_time'] ? datetime($info['create_time'], 'Y-m-d H:i:s') : '';
  134. $status = isset($info['status']) ? $info['status'] : 0;
  135. $info['status_text'] = '待付款';
  136. if ($status) {
  137. $info['status_text'] = isset($statusArr[$status]) ? $statusArr[$status] : '';
  138. }
  139. $info['goods'] = isset($info['goods']) && $info['goods'] ? $info['goods'] : [];
  140. $info['goods']['shipper_phone_text'] = $info['goods']['shipper_phone']?format_mobile($info['goods']['shipper_phone']) : '';
  141. $info['goods']['receiver_phone_text'] = $info['goods']['receiver_phone']?format_mobile($info['goods']['receiver_phone']) : '';
  142. }
  143. return $info;
  144. }
  145. /**
  146. * 创建订单
  147. * @param $userId 用户
  148. * @param $params 参数
  149. * @return array|false
  150. */
  151. public function createOrder($userId, $params)
  152. {
  153. $goodsId = isset($params['goods_id']) && $params['goods_id'] ? intval($params['goods_id']) : 0;
  154. // 参数验证
  155. if (empty($goodsId)) {
  156. $this->error = 2103;
  157. return false;
  158. }
  159. // 缓存锁
  160. $cacheLockKey = "caches:orders:submit_lock:{$userId}_{$goodsId}";
  161. if (RedisService::get($cacheLockKey)) {
  162. $this->error = 2107;
  163. return false;
  164. }
  165. // 货物信息
  166. RedisService::set($cacheLockKey, ['params' => $params, 'user_id' => $userId], rand(2, 3));
  167. $goodsInfo = GoodsModel::where(['id' => $goodsId,'status'=>1, 'mark' => 1])
  168. ->select(['id','num', 'price','picker_status', 'status'])
  169. ->first();
  170. $pickerStatus = isset($goodsInfo['picker_status']) ? $goodsInfo['picker_status'] : 0;
  171. $price = isset($goodsInfo['price']) ? floatval($goodsInfo['price']) : 0;
  172. $num = isset($goodsInfo['num']) ? intval($goodsInfo['num']) : 0;
  173. if(empty($goodsInfo)){
  174. $this->error = 2201;
  175. RedisService::clear($cacheLockKey);
  176. return false;
  177. }
  178. if(in_array($pickerStatus,[2,3])){
  179. $this->error = "220{$pickerStatus}";
  180. RedisService::clear($cacheLockKey);
  181. return false;
  182. }
  183. if($price<=0){
  184. $this->error = 2204;
  185. RedisService::clear($cacheLockKey);
  186. return false;
  187. }
  188. // 用户信息
  189. $userInfo = MemberModel::where(['id' => $userId, 'mark' => 1])
  190. ->select(['id', 'mobile', 'nickname','realname','deposit','picker_status','confirm_status', 'status'])
  191. ->first();
  192. $status = isset($userInfo['status']) ? $userInfo['status'] : 0;
  193. $nickname = isset($userInfo['nickname']) ? $userInfo['nickname'] : '';
  194. $realname = isset($userInfo['realname']) ? $userInfo['realname'] : '';
  195. $mobile = isset($userInfo['mobile']) ? $userInfo['mobile'] : '';
  196. $confirmStatus = isset($userInfo['confirm_status']) ? $userInfo['confirm_status'] : 0;
  197. $userPickerStatus = isset($userInfo['picker_status']) ? $userInfo['picker_status'] : 0;
  198. $userDeposit = isset($userInfo['deposit']) ? floatval($userInfo['deposit']) : 0;
  199. if(empty($userInfo) || $status != 1){
  200. $this->error = 2016;
  201. RedisService::clear($cacheLockKey);
  202. return false;
  203. }
  204. // 账号审核情况
  205. if($confirmStatus != 1){
  206. $this->error = 2042;
  207. RedisService::clear($cacheLockKey);
  208. return false;
  209. }
  210. if($userPickerStatus != 1){
  211. $this->error = 2205;
  212. RedisService::clear($cacheLockKey);
  213. return false;
  214. }
  215. // 缴纳保证金验证
  216. $depositMoney = ConfigService::make()->getConfigByCode('deposit_money',0);
  217. if($depositMoney>0 && ($userDeposit < $depositMoney)){
  218. $this->error = 2206;
  219. RedisService::clear($cacheLockKey);
  220. return false;
  221. }
  222. // 订单数据
  223. $pickerCount = $this->model->where(['goods_id'=> $goodsId,'mark'=>1])->whereIn('status',[1,2])->count('id');
  224. if($this->model->where(['user_id'=>$userId,'goods_id'=>$goodsId,'mark'=>1])->whereIn('status',[1,2,3])->value('id')){
  225. $this->error = 2209;
  226. RedisService::clear($cacheLockKey);
  227. return false;
  228. }
  229. if($this->model->where(['user_id'=>$userId,'mark'=>1])->whereIn('status',[1,2])->value('id')){
  230. $this->error = 2209;
  231. RedisService::clear($cacheLockKey);
  232. return false;
  233. }
  234. $bonusRate = ConfigService::make()->getConfigByCode('picker_bonus_rate',100);
  235. $bonusRate = $bonusRate>0 && $bonusRate<=100? intval($bonusRate) : 100;
  236. $bonus = moneyFormat($price * $bonusRate/100,2);
  237. $orderNo = get_order_num('PD');
  238. $order = [
  239. 'order_no' => $orderNo,
  240. 'user_id' => $userId,
  241. 'goods_id' => $goodsId,
  242. 'total' => $price,
  243. 'bonus' => $bonus,
  244. 'create_time' => time(),
  245. 'update_time' => time(),
  246. 'status' => 1,
  247. 'mark' => 1,
  248. ];
  249. // 订单处理
  250. DB::beginTransaction();
  251. if (!$orderId = $this->model->insertGetId($order)) {
  252. DB::rollBack();
  253. $this->error = 2207;
  254. RedisService::clear($cacheLockKey);
  255. return false;
  256. }
  257. $title = "用户【{$realname}-{$mobile}】有新的抢单";
  258. $message = [
  259. 'from_uid'=> $userId,
  260. 'to_uid'=> 1,
  261. 'op'=> 'notice',
  262. 'scene'=> 'picker',
  263. 'message'=> '接单消息',
  264. 'type'=> 5,
  265. 'order'=>[
  266. 'title'=> $title.'<span class="ele-text-primary">查看订单</span>',
  267. 'order_no'=> $orderNo,
  268. 'money'=> $bonus,
  269. 'date'=> date('Y-m-d H:i:s'),
  270. 'user_id'=> $userId,
  271. 'type'=> 'deposit',
  272. 'remark'=> '接单消息',
  273. ]
  274. ];
  275. DB::commit();
  276. $pickerCount = $pickerCount+1;
  277. $this->error = lang('2210');
  278. RedisService::clear($cacheLockKey);
  279. RedisService::keyDel("caches:goods:picker*");
  280. return ['order_id' => $orderId,'message'=>$message, 'total' => $price, 'num' => $pickerCount<=3?3:$pickerCount, 'goods' => $goodsId];
  281. }
  282. /**
  283. * 今日数量统计数据
  284. * @param $userId
  285. * @param int $type
  286. * @return array|mixed
  287. */
  288. public function getCountByDay($userId, $status=3)
  289. {
  290. $cacheKey = "caches:orders:count_day_{$userId}_{$status}";
  291. $data = RedisService::get($cacheKey);
  292. if($data){
  293. return $data;
  294. }
  295. $data = $this->model->where(['user_id'=> $userId,'status'=>$status,'mark'=>1])
  296. ->where('create_time','>=', strtotime(date('Y-m-d')))
  297. ->count('id');
  298. if($data){
  299. RedisService::set($cacheKey, $data, rand(5,10));
  300. }
  301. return $data;
  302. }
  303. /**
  304. * 订单数
  305. * @param $userId
  306. * @param int $status
  307. * @return array|mixed
  308. */
  309. public function getCountByStatus($userId, $status=3)
  310. {
  311. $cacheKey = "caches:orders:count_status_{$userId}_{$status}";
  312. $data = RedisService::get($cacheKey);
  313. if($data){
  314. return $data;
  315. }
  316. $data = $this->model->where(['user_id'=> $userId,'status'=>$status,'mark'=>1])
  317. ->count('id');
  318. if($data){
  319. RedisService::set($cacheKey, $data, rand(5,10));
  320. }
  321. return $data;
  322. }
  323. /**
  324. * 获取订单审核状态
  325. * @param $userId
  326. * @return array|mixed
  327. */
  328. public function checkOrderStatus($userId)
  329. {
  330. $cacheKey = "caches:orders:checkOrder:{$userId}";
  331. $data = RedisService::get($cacheKey);
  332. if($data){
  333. return $data;
  334. }
  335. $data = $this->model->with(['confirm'])->where(function($query){
  336. $query->where(function($query){
  337. $query->where('status',2)->where('confirm_at','>=', date('Y-m-d H:i:s', time() - 3600));
  338. })->orWhere(function($query){
  339. $query->where('status', 9)->where('confirm_at','>=', date('Y-m-d H:i:s', time() - 600));
  340. })->orWhere(function($query){
  341. $query->where('status', 3)->where('confirm_at','>=', date('Y-m-d H:i:s', time() - 600));
  342. })->orWhere('status', 1);
  343. })
  344. ->where(['user_id'=> $userId,'mark'=>1])
  345. ->select(['id','order_no','user_id','goods_id','status'])
  346. ->orderBy('id','desc')
  347. ->first();
  348. $data = $data? $data->toArray() : [];
  349. $result = [];
  350. if($data){
  351. $orderId = isset($data['id'])? $data['id'] : 0;
  352. $status = isset($data['status'])? $data['status'] : 0;
  353. $goodsId = isset($data['goods_id'])? $data['goods_id'] : 0;
  354. $confirmOrder = isset($data['confirm'])? $data['confirm'] : [];
  355. $confirmOrderId = isset($confirmOrder['id'])? $confirmOrder['id'] : 0;
  356. $confirmOrderUser = isset($confirmOrder['user'])? $confirmOrder['user'] : [];
  357. $realname = isset($confirmOrderUser['realname'])? $confirmOrderUser['realname'] : '';
  358. if($status==9){
  359. $message = "抱歉,订单已被其他师傅接走";
  360. }else if($status == 2){
  361. $message = "恭喜您,抢单成功,请前往完成订单!";
  362. }else if($status == 3){
  363. $message = "恭喜您,订单已经完成!";
  364. }else {
  365. $pickerCount = $this->model->where(['goods_id'=> $goodsId,'mark'=>1])->whereIn('status',[1,2])->count('id');
  366. $pickerCount = $pickerCount<=3? 3 : $pickerCount;
  367. $message = "<p style='padding: 5px 0;'>正在抢单</p><p>({$pickerCount}位师傅正在抢单中)</p>";
  368. }
  369. $result = ['order_id'=>$orderId,'goods_id'=>$goodsId,'confirm_order_id'=>$confirmOrderId,'status'=>$status, 'message'=> $message];
  370. RedisService::set($cacheKey, $result, rand(10, 20));
  371. }
  372. return $result;
  373. }
  374. }