OrderService.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600
  1. <?php
  2. namespace app\common\Service;
  3. use app\common\Enum\GoodsEnum;
  4. use app\common\model\Order;
  5. use app\common\model\OrderGoods;
  6. use app\common\model\OrderAction;
  7. use app\common\model\Address;
  8. use app\common\model\UserCoupon;
  9. use app\common\model\Goods;
  10. use app\common\model\Sku;
  11. use app\common\model\Freight;
  12. use app\common\model\Coupon;
  13. use app\common\model\Carts;
  14. use think\Db;
  15. use think\Exception;
  16. use app\common\model\OrderAddress;
  17. use app\common\Enum\OrderEnum;
  18. /**
  19. * 订单服务类
  20. * 封装订单创建相关逻辑
  21. */
  22. class OrderService
  23. {
  24. /**
  25. * 根据商品列表计算订单明细
  26. * @param array $orderInfo 订单基础信息
  27. * @param array $goods_list 商品列表
  28. * @param int $user_id 用户ID
  29. * @param int $area_id 地区ID
  30. * @param int $user_coupon_id 优惠券ID
  31. * @return array
  32. * @throws Exception
  33. */
  34. protected static function computeGoods(&$orderInfo, $goodsList, $userId, $areaId, $userCouponId = 0)
  35. {
  36. $config = get_addon_config('shop');
  37. $orderInfo['amount'] = 0;
  38. $orderInfo['goods_price'] = 0;
  39. $orderInfo['goods_num'] = 0;
  40. $orderInfo['express_fee'] = 0;
  41. $orderInfo['discount_fee'] = 0;
  42. $orderInfo['coupon_discount_fee'] = 0;
  43. $orderInfo['order_amount'] = 0;
  44. $orderItem = [];
  45. $shippingTemp = [];
  46. $userCoupon = null;
  47. $processedGoodsList = []; // 处理后的商品列表,避免与参数$goodsList冲突
  48. // 校验优惠券
  49. if ($userCouponId) {
  50. $userCouponModel = new UserCoupon();
  51. $userCoupon = $userCouponModel->checkUserOrUse($userCouponId, $userId);
  52. $orderInfo['user_coupon_id'] = $userCouponId;
  53. }
  54. // 提取所有商品ID和SKU ID,进行批量查询
  55. $goodsIds = array_column($goodsList, 'goods_id');
  56. $skuIds = [];
  57. foreach ($goodsList as $index => $item) {
  58. if (isset($item['goods_sku_id']) && $item['goods_sku_id'] > 0) {
  59. $skuIds[] = $item['goods_sku_id'];
  60. }
  61. }
  62. // 批量查询商品信息
  63. $goodsData = [];
  64. if (!empty($goodsIds)) {
  65. $goodsCollection = Goods::with(['brand'])
  66. ->where('id', 'in', $goodsIds)
  67. ->where('status', GoodsEnum::STATUS_ON_SALE)
  68. ->select();
  69. foreach ($goodsCollection as $goods) {
  70. $goodsData[$goods->id] = $goods;
  71. }
  72. }
  73. // 批量查询SKU信息
  74. $skuData = [];
  75. $multiSpecSkuIds = []; // 用于存储多规格商品的SKU ID
  76. if (!empty($skuIds)) {
  77. $skuCollection = Sku::where('id', 'in', $skuIds)->select();
  78. foreach ($skuCollection as $sku) {
  79. $skuData[$sku->id] = $sku;
  80. // 过滤出有规格值的SKU ID(spec_value_ids不为空)
  81. if (!empty($sku->spec_value_ids)) {
  82. $multiSpecSkuIds[] = $sku->id;
  83. }
  84. }
  85. }
  86. // 批量查询规格属性字符串(只查询多规格商品的SKU)
  87. $skuAttrData = [];
  88. if (!empty($multiSpecSkuIds)) {
  89. $skuAttrData = \app\common\Service\SkuSpec::getSkuAttrs($multiSpecSkuIds);
  90. }
  91. // 验证并构建商品数据
  92. foreach ($goodsList as $item) {
  93. $goods_id = $item['goods_id'];
  94. $goods_sku_id = $item['goods_sku_id']; // 现在所有商品都应该有SKU ID
  95. $nums = $item['nums'];
  96. if ($nums <= 0) {
  97. throw new Exception("商品数量必须大于0");
  98. }
  99. // 检查商品是否存在
  100. if (!isset($goodsData[$goods_id])) {
  101. throw new Exception("商品已下架");
  102. }
  103. $goods = $goodsData[$goods_id];
  104. // 所有商品都必须有SKU(包括单规格商品的默认SKU)
  105. if (empty($skuData) || !isset($skuData[$goods_sku_id])) {
  106. throw new Exception("商品规格不存在");
  107. }
  108. $sku = $skuData[$goods_sku_id];
  109. // 验证SKU是否属于该商品
  110. if ($sku->goods_id != $goods_id) {
  111. throw new Exception("商品规格不匹配");
  112. }
  113. // 获取规格属性字符串(单规格商品的sku_attr为空)
  114. $sku_attr = $skuAttrData[$goods_sku_id] ?? '';
  115. // 构建商品对象,模拟购物车数据结构
  116. $goodsItem = (object)[
  117. 'goods_id' => $goods_id,
  118. 'goods_sku_id' => $goods_sku_id,
  119. 'nums' => $nums,
  120. 'goods' => $goods,
  121. 'sku' => $sku,
  122. 'sku_attr' => $sku_attr
  123. ];
  124. $processedGoodsList[] = $goodsItem;
  125. }
  126. // 计算商品价格和运费(统一使用SKU进行计算)
  127. foreach ($processedGoodsList as $item) {
  128. $goodsItemData = [];
  129. if (empty($item->goods) || empty($item->sku)) {
  130. throw new Exception("商品已下架");
  131. }
  132. // 库存验证(统一使用SKU库存)
  133. if ($item->sku->stocks < $item->nums) {
  134. throw new Exception("商品库存不足,请重新修改数量");
  135. }
  136. // 统一使用SKU数据进行计算
  137. $goodsItemData['image'] = !empty($item->sku->image) ? $item->sku->image : $item->goods->image;
  138. $goodsItemData['price'] = $item->sku->price;
  139. // $goodsItemData['lineation_price'] = $item->sku->lineation_price;
  140. $goodsItemData['sku_sn'] = $item->sku->sku_sn;
  141. $amount = bcmul($item->sku->price, $item->nums, 2);
  142. $goodsItemData['amount'] = $amount;
  143. // 订单应付金额
  144. $orderInfo['amount'] = bcadd($orderInfo['amount'], $amount, 2);
  145. // 商品总价
  146. $orderInfo['goods_price'] = bcadd($orderInfo['goods_price'], $amount, 2);
  147. // 商品数量累计
  148. $orderInfo['goods_num'] += $item->nums;
  149. $freight_id = $item->goods->express_template_id;
  150. // 计算邮费【合并运费模板】
  151. if (!isset($shippingTemp[$freight_id])) {
  152. $shippingTemp[$freight_id] = [
  153. 'nums' => $item->nums,
  154. 'weight' => $item->sku->weight,
  155. 'amount' => $amount
  156. ];
  157. } else {
  158. $shippingTemp[$freight_id] = [
  159. 'nums' => bcadd($shippingTemp[$freight_id]['nums'], $item->nums, 2),
  160. 'weight' => bcadd($shippingTemp[$freight_id]['weight'], $item->sku->weight, 2),
  161. 'amount' => bcadd($shippingTemp[$freight_id]['amount'], $amount, 2)
  162. ];
  163. }
  164. // 创建订单商品数据 (基于正确的表结构)
  165. $orderItemData = [
  166. 'user_id' => $userId,
  167. 'order_sn' => '', // 将在订单创建后补充
  168. 'goods_sn' => $item->goods->goods_sn ?: '', // 商品货号
  169. 'sku_sn' => $item->sku->sku_sn ?: '', // SKU编号
  170. 'goods_type' => $item->goods->type ?: 0, // 商品类型
  171. 'goods_id' => $item->goods->id,
  172. 'goods_sku_attr' => $item->sku->sku_attr,
  173. 'goods_spec_value_ids' => $item->sku->spec_value_ids,
  174. 'goods_sku_id' => $item->sku->id,
  175. 'goods_title' => $item->goods->title,
  176. 'goods_market_price' => $item->sku->market_price ?: 0, // 市场价
  177. 'goods_original_price' => $item->sku->price, // 商城售价
  178. 'goods_price' => $amount, // 实付金额
  179. 'goods_image' => $goodsItemData['image'],
  180. 'goods_weight' => $item->sku->weight ?: 0,
  181. 'nums' => $item->nums,
  182. 'sale_status' => 0, // 销售状态:0=待申请
  183. 'comment_status' => 0, // 评论状态:0=未评论
  184. 'status' => 1, // 状态
  185. // 添加分类和品牌信息用于优惠券计算 (临时字段,不会保存到数据库)
  186. // 'category_id' => $item->goods->category_ids,
  187. 'brand_id' => $item->goods->brand_id,
  188. ];
  189. $orderItem[] = $orderItemData;
  190. }
  191. // 按运费模板计算
  192. foreach ($shippingTemp as $key => $item) {
  193. $shippingfee = Freight::calculate($key, $areaId, $item['nums'], $item['weight'], $item['amount']);
  194. $orderInfo['express_fee'] = bcadd($orderInfo['express_fee'], $shippingfee, 2);
  195. }
  196. // 订单金额(商品价格+运费)
  197. $orderInfo['order_amount'] = bcadd($orderInfo['goods_price'], $orderInfo['express_fee'], 2);
  198. // 订单应付金额(暂时等于订单金额,后续会减去优惠)
  199. $orderInfo['amount'] = $orderInfo['order_amount'];
  200. // if (!empty($userCoupon)) {
  201. // // 校验优惠券
  202. // $goods_ids = array_column($orderItem, 'goods_id');
  203. // $category_ids = array_column($orderItem, 'category_id');
  204. // $brand_ids = array_column($orderItem, 'brand_id');
  205. // $couponModel = new Coupon();
  206. // $coupon = $couponModel->getCoupon($userCoupon['coupon_id'])
  207. // ->checkCoupon()
  208. // ->checkOpen()
  209. // ->checkUseTime($userCoupon['createtime'])
  210. // ->checkConditionGoods($goods_ids, $userId, $category_ids, $brand_ids);
  211. // // 计算折扣金额,判断是使用不含运费,还是含运费的金额
  212. // $amount = !isset($config['shippingfeecoupon']) || $config['shippingfeecoupon'] == 0 ? $orderInfo['goods_price'] : $orderInfo['order_amount'];
  213. // list($new_money, $coupon_money) = $coupon->doBuy($amount);
  214. // // 判断优惠金额是否超出总价,超出则直接设定优惠金额为总价
  215. // $orderInfo['coupon_discount_fee'] = $coupon_money > $amount ? $amount : $coupon_money;
  216. // $orderInfo['discount_fee'] = $orderInfo['coupon_discount_fee'];
  217. // }
  218. // 计算最终应付金额【订单金额减去折扣】
  219. $orderInfo['amount'] = max(0, bcsub($orderInfo['order_amount'], $orderInfo['discount_fee'], 2));
  220. $orderInfo['pay_amount'] = $orderInfo['amount']; // 实际付款金额等于应付金额
  221. $orderInfo['discount_fee'] = bcadd($orderInfo['discount_fee'], 0, 2);
  222. return [
  223. $orderItem,
  224. $processedGoodsList,
  225. $userCoupon
  226. ];
  227. }
  228. /**
  229. * 统一的创建订单方法
  230. * @param int $address_id 地址ID
  231. * @param int $user_id 用户ID
  232. * @param array $goods_list 标准化的商品列表
  233. * @param int $user_coupon_id 优惠券ID
  234. * @param string $memo 备注
  235. * @param array $cart_ids 购物车ID数组(如果是购物车模式需要清空)
  236. * @return Order
  237. * @throws Exception
  238. */
  239. public static function createOrder($addressId, $userId, $goodsList, $userCouponId = 0, $remark = '')
  240. {
  241. $address = Address::get($addressId);
  242. if (!$address || $address['user_id'] != $userId) {
  243. throw new Exception("地址未找到");
  244. }
  245. if (empty($goodsList)) {
  246. throw new Exception("商品列表不能为空");
  247. }
  248. $config = get_addon_config('shop');
  249. $orderSn = date("Ymdhis") . sprintf("%08d", $userId) . mt_rand(1000, 9999);
  250. // 订单主表信息 (基于新表结构)
  251. $orderInfo = [
  252. 'type' => 1, // 1:普通订单
  253. 'source' => 'H5', // 订单来源 (暂定H5,可根据实际情况调整)
  254. 'order_sn' => $orderSn,
  255. 'user_id' => $userId,
  256. 'amount' => 0, // 订单应付金额
  257. 'goods_price' => 0, // 商品总费用
  258. 'goods_num' => 0, // 商品数量
  259. 'discount_fee' => 0, // 优惠金额
  260. 'coupon_discount_fee' => 0, // 优惠券金额
  261. 'promo_discount_fee' => 0, // 营销金额
  262. 'order_amount' => 0, // 订单金额
  263. 'pay_amount' => 0, // 实际付款金额
  264. 'pay_type' => '', // 支付方式
  265. 'pay_time' => null, // 支付时间
  266. 'delivery_type' => 1, // 发货方式
  267. 'express_name' => '', // 快递名称
  268. 'express_no' => '', // 快递单号
  269. 'express_fee' => 0, // 配送费用
  270. 'expire_time' => time() + $config['order_timeout'], // 过期时间
  271. 'order_status' => OrderEnum::STATUS_CREATE, // 待付款
  272. 'invoice_status' => 0, // 发票开具状态
  273. 'remark' => $remark, // 用户备注
  274. 'user_coupon_id' => $userCouponId ?: null,
  275. 'ip' => request()->ip(), // IP地址
  276. 'status' => 'normal'
  277. ];
  278. // 通过商品列表计算订单明细
  279. list($orderItem, $calculatedGoodsList, $userCoupon) = self::computeGoods($orderInfo, $goodsList, $userId, $address->area_id, $userCouponId);
  280. // 创建订单
  281. $order = self::createOrderWithTransaction($orderInfo, $orderItem, $calculatedGoodsList, $userCoupon, $address);
  282. return $order;
  283. }
  284. /**
  285. * 在事务中创建订单
  286. * @param array $orderInfo 订单信息
  287. * @param array $orderItem 订单商品列表
  288. * @param array $goodsList 商品列表
  289. * @param object $userCoupon 优惠券
  290. * @param object $address 地址信息
  291. * @return Order
  292. * @throws Exception
  293. */
  294. protected static function createOrderWithTransaction($orderInfo, $orderItem, $goodsList, $userCoupon, $address)
  295. {
  296. $order = null;
  297. Db::startTrans();
  298. try {
  299. // 创建订单
  300. $order = Order::create($orderInfo, true);
  301. // 为每个订单商品添加订单ID和订单号
  302. foreach ($orderItem as &$item) {
  303. $item['order_id'] = $order->id;
  304. $item['order_sn'] = $order->order_sn;
  305. // 移除临时字段
  306. unset($item['category_id'], $item['brand_id']);
  307. }
  308. unset($item);
  309. // 创建订单地址信息
  310. $orderAddressData = [
  311. 'order_id' => $order->id,
  312. 'user_id' => $orderInfo['user_id'],
  313. 'consignee' => $address->receiver,
  314. 'mobile' => $address->mobile,
  315. 'province_name' => $address->province->name ?? '',
  316. 'city_name' => $address->city->name ?? '',
  317. 'district_name' => $address->area->name ?? '',
  318. 'address' => $address->address,
  319. 'province_id' => $address->province_id,
  320. 'city_id' => $address->city_id,
  321. 'district_id' => $address->area_id,
  322. ];
  323. OrderAddress::create($orderAddressData);
  324. // 减库存
  325. foreach ($goodsList as $index => $item) {
  326. if ($item->sku) {
  327. $item->sku->setDec('stocks', $item->nums);
  328. }
  329. $item->goods->setDec("stocks", $item->nums);
  330. }
  331. // 计算单个商品折扣后的价格 (基于新字段名)
  332. $saleamount = bcsub($order['amount'], $order['express_fee'], 2);
  333. $saleratio = $order['goods_price'] > 0 ? bcdiv($saleamount, $order['goods_price'], 10) : 1;
  334. $saleremains = $saleamount;
  335. foreach ($orderItem as $index => &$item) {
  336. if (!isset($orderItem[$index + 1])) {
  337. $saleprice = $saleremains;
  338. } else {
  339. $saleprice = $order['discount_fee'] == 0 ? bcmul($item['goods_original_price'], $item['nums'], 2) : bcmul(bcmul($item['goods_original_price'], $item['nums'], 2), $saleratio, 2);
  340. }
  341. $saleremains = bcsub($saleremains, $saleprice, 2);
  342. $item['goods_price'] = $saleprice;
  343. }
  344. unset($item);
  345. // 批量创建订单商品数据
  346. if (!empty($orderItem)) {
  347. (new OrderGoods())->saveAll($orderItem);
  348. }
  349. // 修改地址使用次数
  350. if ($address) {
  351. $address->setInc('used_nums');
  352. }
  353. // 优惠券已使用
  354. if (!empty($userCoupon)) {
  355. $userCoupon->save(['is_used' => 2]);
  356. }
  357. // 提交事务
  358. Db::commit();
  359. } catch (Exception $e) {
  360. Db::rollback();
  361. throw new Exception($e->getMessage());
  362. }
  363. // 记录操作
  364. OrderAction::push($orderInfo['order_sn'], '系统', '订单创建成功');
  365. // 订单应付金额为0时直接结算
  366. if ($order['amount'] == 0) {
  367. Order::settle($order->order_sn, 0);
  368. $order = Order::get($order->id);
  369. }
  370. return $order;
  371. }
  372. /**
  373. * 验证商品规格参数
  374. * @param array $goods_list 商品列表
  375. * @throws Exception
  376. */
  377. public static function validateGoodsList($goods_list)
  378. {
  379. if (empty($goods_list) || !is_array($goods_list)) {
  380. throw new Exception("商品列表不能为空");
  381. }
  382. foreach ($goods_list as $item) {
  383. if (!isset($item['goods_id']) || !is_numeric($item['goods_id']) || $item['goods_id'] <= 0) {
  384. throw new Exception("商品ID无效");
  385. }
  386. if (!isset($item['nums']) || !is_numeric($item['nums']) || $item['nums'] <= 0) {
  387. throw new Exception("商品数量必须大于0");
  388. }
  389. if (isset($item['goods_sku_id']) && !is_numeric($item['goods_sku_id'])) {
  390. throw new Exception("商品规格ID无效");
  391. }
  392. }
  393. }
  394. /**
  395. * 统一的订单计算方法(用于预览订单)
  396. * @param array $goods_list 标准化的商品列表
  397. * @param int $user_id 用户ID
  398. * @param int $area_id 地区ID
  399. * @param int $user_coupon_id 优惠券ID
  400. * @return array
  401. * @throws Exception
  402. */
  403. public static function calculateOrder($goodsList, $userId, $areaId = 0, $userCouponId = 0)
  404. {
  405. if (empty($goodsList)) {
  406. throw new Exception("商品列表不能为空");
  407. }
  408. // 验证商品列表格式
  409. self::validateGoodsList($goodsList);
  410. // 订单基础信息(用于计算,不包含订单号)
  411. $orderInfo = [
  412. 'amount' => 0, // 应付金额
  413. 'goods_price' => 0, // 商品金额 (不含运费)
  414. 'goods_num' => 0, // 商品数量
  415. 'discount_fee' => 0, // 总优惠金额
  416. 'coupon_discount_fee' => 0, // 优惠券金额
  417. 'promo_discount_fee' => 0, // 营销金额
  418. 'order_amount' => 0, // 总金额 (含运费)
  419. 'express_fee' => 0, // 运费
  420. ];
  421. // 计算商品明细
  422. list($orderItem, $calculatedGoodsList, $userCoupon) = self::computeGoods($orderInfo, $goodsList, $userId, $areaId, $userCouponId);
  423. return [
  424. 'orderItem' => $orderItem,
  425. 'goodsList' => $calculatedGoodsList,
  426. 'orderInfo' => $orderInfo,
  427. 'userCoupon' => $userCoupon
  428. ];
  429. }
  430. /**
  431. * 订单列表
  432. *
  433. * @param $param
  434. * @return \think\Paginator
  435. */
  436. public static function getOrderList($userId = 0, $param =[],$status = [])
  437. {
  438. $pageSize = 15;
  439. if (!empty($param['pageSize'])) {
  440. $pageSize = $param['pageSize'];
  441. }
  442. return Order::with(['orderGoods'])
  443. ->where(function ($query) use ($param,$userId,$status) {
  444. if (!empty($userId)) {
  445. $query->where('user_id', $userId);
  446. }
  447. if (!empty($status)) {
  448. $query->whereIn('order_status', $status );
  449. }
  450. if (isset($param['keywords']) && $param['keywords'] != '') {
  451. $query->where('order_sn', 'in', function ($query) use ($param) {
  452. return $query->name('shop_order_goods')->where('order_sn|goods_title', 'like', '%' . $param['q'] . '%')->field('order_sn');
  453. });
  454. }
  455. })
  456. ->order('createtime desc')
  457. ->paginate($pageSize, false, ['query' => request()->get()]);
  458. }
  459. /**
  460. *
  461. * @ 订单信息
  462. * @param $orderId
  463. * @param $userId
  464. * @return array|false|\PDOStatement|string|Model
  465. */
  466. public static function getDetail($orderId, $userId)
  467. {
  468. return Order::with(['orderGoods'])
  469. ->where('id', $orderId)
  470. ->where('user_id', $userId)
  471. ->find();
  472. }
  473. // 查询地址信息
  474. public static function getAddressInfo($orderId)
  475. {
  476. return OrderAddress::where('order_id', $orderId)->find();
  477. }
  478. /**
  479. * 判断订单是否失效
  480. * @param $order_sn
  481. * @return bool
  482. */
  483. public static function isExpired($orderSn)
  484. {
  485. $orderInfo = self::getByOrderSn($orderSn);
  486. //订单过期
  487. if (!$orderInfo['orderstate'] && !$orderInfo['paystate'] && time() > $orderInfo['expiretime']) {
  488. // 启动事务
  489. Db::startTrans();
  490. try {
  491. $orderInfo->save(['orderstate' => 2]);
  492. //库存恢复
  493. OrderGoods::setGoodsStocksInc($orderInfo->order_sn);
  494. //恢复优惠券
  495. UserCoupon::resetUserCoupon($orderInfo->user_coupon_id, $orderInfo->order_sn);
  496. // 提交事务
  497. Db::commit();
  498. } catch (\Exception $e) {
  499. // 回滚事务
  500. Db::rollback();
  501. }
  502. return true;
  503. }
  504. return false;
  505. }
  506. public static function getByOrderSn($orderSn)
  507. {
  508. return Order::where('order_sn', $orderSn)->find();
  509. }
  510. public static function getByOrderId($orderId)
  511. {
  512. return Order::where('id', $orderId)->find();
  513. }
  514. // 获取状态订单统计
  515. public static function getOrderStatusCount($userId = 0)
  516. {
  517. $info = [];
  518. $info['unpay'] = Order::where('user_id', $userId)->where('order_status',OrderEnum::STATUS_CREATE)->count();
  519. $info['unsend'] = Order::where('user_id', $userId)->where('order_status',OrderEnum::STATUS_PAY)->count();
  520. $info['unrec'] = Order::where('user_id', $userId)->where('order_status',OrderEnum::STATUS_SHIP)->count();
  521. $info['uneva'] = Order::where('user_id', $userId)->where('order_status',OrderEnum::STATUS_CONFIRM)->count();
  522. return $info;
  523. }
  524. }