ShopOrderService.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. <?php
  2. namespace App\Services\Dwbs;
  3. use App\Repositories\Criteria\Dwbs\ShopOrderCriteria;
  4. use App\Repositories\Eloquent\Dwbs\ShopOrderRepositoryEloquent;
  5. use App\Repositories\Enums\CheckStatusEnum;
  6. use App\Repositories\Enums\Dwbs\ShopOrderStatusEnum;
  7. use App\Repositories\Enums\Dwbs\UserJifenTypeEnum;
  8. use App\Repositories\Enums\ModelStatusEnum;
  9. use App\Repositories\Enums\ResponseCodeEnum;
  10. use App\Repositories\Models\Base\User;
  11. use App\Repositories\Models\Dwbs\ShopGood;
  12. use App\Repositories\Models\Dwbs\ShopOrder;
  13. use App\Repositories\Models\Dwbs\ShopOrderGood;
  14. use App\Repositories\Models\Dwbs\UserAddress;
  15. use App\Repositories\Models\Dwbs\UserJifen;
  16. use App\Repositories\Presenters\Dwbs\ShopOrderPresenter;
  17. use Carbon\Carbon;
  18. use Illuminate\Http\Request;
  19. use Illuminate\Support\Facades\Cache;
  20. use Illuminate\Support\Facades\DB;
  21. class ShopOrderService
  22. {
  23. /**
  24. * @var ShopOrderRepositoryEloquent
  25. */
  26. private $repository;
  27. /**
  28. * ShopOrderService constructor.
  29. *
  30. * @param ShopOrderRepositoryEloquent $shopOrderRepositoryEloquent
  31. */
  32. public function __construct(ShopOrderRepositoryEloquent $repository)
  33. {
  34. $this->repository = $repository;
  35. }
  36. /**
  37. * @param Request $request
  38. *
  39. * @return mixed
  40. * @throws \Prettus\Repository\Exceptions\RepositoryException
  41. */
  42. public function handleList(Request $request)
  43. {
  44. $this->repository->pushCriteria(new ShopOrderCriteria($request));
  45. $this->repository->setPresenter(ShopOrderPresenter::class);
  46. return $this->repository->searchListsPage();
  47. }
  48. /**
  49. * @param $id
  50. *
  51. * @return \Illuminate\Database\Eloquent\Model
  52. */
  53. public function handleProfile($id)
  54. {
  55. $this->repository->setPresenter(ShopOrderPresenter::class);
  56. return $this->repository->searchBy($id);
  57. }
  58. /**
  59. * 礼品兑换
  60. * @param array $data
  61. *
  62. * @return mixed
  63. * @throws \Prettus\Validator\Exceptions\ValidatorException
  64. */
  65. public function handleStore($data)
  66. {
  67. //校检积分
  68. $goods = $data['goods'];
  69. $totalJifen = 0;
  70. $totalNums = 0;
  71. $user = User::query()->where('id', $data['user_id'])->where('status', ModelStatusEnum::OK)->select(['id', 'jifen'])->first();
  72. if (!$user) abort(ResponseCodeEnum::SERVICE_OPERATION_ERROR, '找不到该用户');
  73. $address = UserAddress::query()->where('id', $data['address_id'])->where('status', ModelStatusEnum::OK)->where('user_id', $user->id)->first();
  74. if (!$address) abort(ResponseCodeEnum::SERVICE_OPERATION_ERROR, '无效的收货地址');
  75. $com_goods = [];
  76. foreach ($goods as $good) {
  77. $goodModel = ShopGood::byIdGetOrder($good['id']);
  78. if (!$goodModel) abort("找不到该商品");
  79. if ($goodModel->nums < $good['nums']) abort(ResponseCodeEnum::SERVICE_OPERATION_ERROR, "{$goodModel->name}库存不足");
  80. $tj = bcmul($goodModel['jifen'], $good['nums'], 0);
  81. $com_goods[] = [
  82. 'good_id' => $goodModel->id,
  83. 'jifen' => $goodModel->jifen,
  84. 'nums' => $good['nums'],
  85. 'total_jifen' => $tj,
  86. // 'model' => $goodModel
  87. ];
  88. $totalJifen = bcadd($tj, $totalJifen, 0);
  89. $totalNums += (int)$good['nums'];
  90. }
  91. if ((int)$data['jifen'] !== (int)$totalJifen) abort(ResponseCodeEnum::SERVICE_OPERATION_ERROR, '积分计算不正确');
  92. if ((int)$data['nums'] !== (int)$totalNums) abort(ResponseCodeEnum::SERVICE_OPERATION_ERROR, '商品数量计算不正确');
  93. if ($user->jifen < $totalJifen) abort(ResponseCodeEnum::SERVICE_OPERATION_ERROR, '积分不足');
  94. // //检测是否有超库存操作
  95. // Cache::lock("lock:shopOrder:has:kucun")->get(function () use ($com_goods) {
  96. // foreach ($com_goods as $good) {
  97. // $good_id = $good['good_id'];
  98. // //检测商品是否存在缓存
  99. // if (!Cache::has("model:good:nums:{$good_id}")) {
  100. // ShopGood::reloadKuCun($good_id);
  101. // }
  102. // }
  103. // return true;
  104. // });
  105. $isChaoKuCun = true;
  106. $kuCunGoods = [];
  107. foreach ($com_goods as $good) {
  108. $good_id = $good['good_id'];
  109. $good_nums = $good['nums'];
  110. //检测商品是否存在缓存[没有缓存的时候可能会超卖]
  111. // if (!Cache::has("model:good:nums:{$good_id}")) {
  112. // ShopGood::reloadKuCun($good_id);
  113. // }
  114. $isChaoKuCun = Cache::lock("lock:shopOrder:good:{$good_id}")->get(function () use ($good_id, $good_nums) {
  115. $kuCunNums = Cache::get("model:good:nums:{$good_id}", 0);
  116. if (!$kuCunNums || $kuCunNums < $good_nums) {
  117. return false;
  118. }
  119. Cache::decrement("model:good:nums:{$good_id}", $good_nums);
  120. return true;
  121. });
  122. if (!$isChaoKuCun) {
  123. //存在超库时恢复其他商品的库存
  124. foreach ($kuCunGoods as $g) {
  125. $good_id = $g['good_id'];
  126. $good_nums = $g['nums'];
  127. Cache::lock("lock:shopOrder:good:{$good_id}")->get(function () use ($good_id, $good_nums) {
  128. Cache::increment("model:good:nums:{$good_id}", $good_nums);
  129. return true;
  130. });
  131. }
  132. break;
  133. }
  134. $kuCunGoods[] = $good;
  135. }
  136. if (!$isChaoKuCun) abort(ResponseCodeEnum::SERVICE_OPERATION_ERROR, '库存不足');
  137. $order = DB::transaction(function () use ($com_goods, $user, $totalJifen, $totalNums, $data, $address) {
  138. $order = ShopOrder::query()->create([
  139. 'order_no' => ShopOrder::makeNo(),
  140. 'day' => date('Y-m-d'),
  141. 'user_id' => $user['id'],
  142. 'order_time' => Carbon::now()->toDateTimeString(),
  143. 'jifen' => $totalJifen,
  144. 'nums' => $totalNums,
  145. 'address_id' => $address['id'],
  146. 'sjr_name' => $address['name'],
  147. 'sjr_mobile' => $address['mobile'],
  148. 'sjr_mobile_encryption' => $address['mobile_encryption'],
  149. 'sjr_mobile_code' => $address['mobile_code'],
  150. 'sjr_address_province' => $address['province'],
  151. 'sjr_address_city' => $address['city'],
  152. 'sjr_address_area' => $address['area'],
  153. 'sjr_address' => $address['address'],
  154. 'check_status' => CheckStatusEnum::WAIT,
  155. 'status' => ShopOrderStatusEnum::wait_check
  156. ]);
  157. $user = User::query()->where('id', $data['user_id'])->first();
  158. $user->jifen = bcsub($user->jifen, $totalJifen, 0);
  159. $user->xiaofei_jifen = bcadd($user->xiaofei_jifen, $totalJifen, 0);
  160. $user->save();
  161. UserJifen::query()->create([
  162. 'day' => date('Y-m-d'),
  163. 'user_id' => $user->id,
  164. 'jifen' => -$totalJifen,
  165. 'type' => UserJifenTypeEnum::lipinduihuan,
  166. 'source_id' => $order->id,
  167. 'source_type' => ShopOrder::class,
  168. 'user_jifen' => $user->jifen,
  169. 'is_reward' => ModelStatusEnum::PAUSE,
  170. 'status' => ModelStatusEnum::OK,
  171. ]);
  172. foreach ($com_goods as $good) {
  173. ShopOrderGood::query()->create([
  174. 'order_id' => $order->id,
  175. 'user_id' => $order->user_id,
  176. 'good_id' => $good['good_id'],
  177. 'nums' => $good['nums'],
  178. 'total_jifen' => $good['total_jifen'],
  179. 'jifen' => $good['jifen'],
  180. ]);
  181. ShopGood::query()->where('id', $good['good_id'])->decrement('nums', $good['nums']);
  182. ShopGood::query()->where('id', $good['good_id'])->increment('duihuan_nums', $good['nums']);
  183. }
  184. $order['user_jifen'] = $user->jifen;
  185. return $order;
  186. });
  187. return $order;
  188. }
  189. /**
  190. * @param array $data
  191. *
  192. * @return mixed
  193. * @throws \Prettus\Validator\Exceptions\ValidatorException
  194. */
  195. public function handleUpdate($data)
  196. {
  197. $shopOrder = ShopOrder::query()->where('id', $data['id'])->first();
  198. $shopOrder->fill($data);
  199. $shopOrder->save();
  200. return $shopOrder;
  201. }
  202. /**
  203. * @param Request $request
  204. *
  205. * @return mixed
  206. * @throws \Prettus\Validator\Exceptions\ValidatorException
  207. */
  208. public function handleDelete($id)
  209. {
  210. return $this->repository->delete($id);
  211. }
  212. /**
  213. * 选项
  214. * @param Request $request
  215. * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator|\Illuminate\Support\Collection|mixed
  216. * @throws \Prettus\Repository\Exceptions\RepositoryException
  217. */
  218. public function handleSelectOptions(Request $request)
  219. {
  220. $this->repository->pushCriteria(new ShopOrderCriteria($request));
  221. return $this->repository->all(['id', 'name']);
  222. }
  223. /**
  224. * 批量删除
  225. * @param $ids
  226. * @return mixed
  227. */
  228. public function handleBatchDelete($ids)
  229. {
  230. return $this->repository->whereIn('id', $ids)->delete();
  231. }
  232. /**
  233. * @param Request $request
  234. *
  235. * @return mixed
  236. * @throws \Prettus\Repository\Exceptions\RepositoryException
  237. */
  238. public function handleAll(Request $request)
  239. {
  240. $this->repository->pushCriteria(new ShopOrderCriteria($request));
  241. $this->repository->setPresenter(ShopOrderPresenter::class);
  242. return $this->repository->get();
  243. }
  244. /**
  245. * @param Request $request
  246. *
  247. * @return mixed
  248. * @throws \Prettus\Repository\Exceptions\RepositoryException
  249. */
  250. public function handleIds(Request $request)
  251. {
  252. $this->repository->pushCriteria(new ShopOrderCriteria($request));
  253. return $this->repository->pluck('id');
  254. }
  255. /**
  256. * 修改订单地址
  257. * @param $data
  258. * @return true
  259. */
  260. public function handleUpdateAddress($data)
  261. {
  262. $order = ShopOrder::query()->where('id', $data['id'])->where('user_id', login_user_id())->first();
  263. if (!$order) abort(ResponseCodeEnum::SERVICE_OPERATION_ERROR, '找不到该订单');
  264. if ($order->status === ShopOrderStatusEnum::close) abort(ResponseCodeEnum::SERVICE_OPERATION_ERROR, '该订单已关闭');
  265. if ($order->status !== ShopOrderStatusEnum::wait_check) abort(ResponseCodeEnum::SERVICE_OPERATION_ERROR, '该订单已锁定');
  266. $address = UserAddress::query()->where('id', $data['address_id'])->where('status', ModelStatusEnum::OK)->where('user_id', $order->user_id)->first();
  267. if (!$address) abort(ResponseCodeEnum::SERVICE_OPERATION_ERROR, '无效的收货地址');
  268. $order->fill([
  269. 'address_id' => $address['id'],
  270. 'sjr_name' => $address['name'],
  271. 'sjr_mobile' => $address['mobile'],
  272. 'sjr_mobile_encryption' => $address['mobile_encryption'],
  273. 'sjr_mobile_code' => $address['mobile_code'],
  274. 'sjr_address_province' => $address['province'],
  275. 'sjr_address_city' => $address['city'],
  276. 'sjr_address_area' => $address['area'],
  277. 'sjr_address' => $address['address'],
  278. ]);
  279. $order->save();
  280. return true;
  281. }
  282. /**
  283. * 关闭订单
  284. * @param $data
  285. * @return true
  286. */
  287. public function handleCloseOrder($order_id, $close_order_reason)
  288. {
  289. if (isAdminModule()) {
  290. $order = ShopOrder::query()->where('id', $order_id)->first();
  291. } else {
  292. $order = ShopOrder::query()->where('id', $order_id)->where('user_id', login_user_id())->first();
  293. }
  294. if (!$order) abort(ResponseCodeEnum::SERVICE_OPERATION_ERROR, '找不到该订单');
  295. if ($order->status === ShopOrderStatusEnum::close) abort(ResponseCodeEnum::SERVICE_OPERATION_ERROR, '该订单已关闭');
  296. if ($order->status !== ShopOrderStatusEnum::wait_check) abort(ResponseCodeEnum::SERVICE_OPERATION_ERROR, '该订单已锁定');
  297. DB::transaction(function () use ($order, $close_order_reason) {
  298. $order->status = ShopOrderStatusEnum::close;
  299. $order->close_order_reason = $close_order_reason;
  300. $order->save();
  301. $user = User::query()->where('id', $order->user_id)->first();
  302. $user->jifen = bcadd($user->jifen, $order->jifen, 0);
  303. $user->xiaofei_jifen = bcsub($user->xiaofei_jifen, $order->jifen, 0);
  304. $user->save();
  305. UserJifen::query()->create([
  306. 'day' => date('Y-m-d'),
  307. 'user_id' => $user->id,
  308. 'jifen' => $order->jifen,
  309. 'type' => UserJifenTypeEnum::dingdanzuofei,
  310. 'source_id' => $order->id,
  311. 'source_type' => ShopOrder::class,
  312. 'user_jifen' => $user->jifen,
  313. 'is_reward' => ModelStatusEnum::PAUSE,
  314. 'status' => ModelStatusEnum::OK,
  315. ]);
  316. $shopOrderGoods = ShopOrderGood::query()->where('order_id', $order->id)->where('status', ModelStatusEnum::OK)->get();
  317. foreach ($shopOrderGoods as $good) {
  318. $good->status = ModelStatusEnum::PAUSE;
  319. $good->save();
  320. $shopGood = ShopGood::query()->where('id', $good->good_id)->first();
  321. if ($shopGood) {
  322. $shopGood->nums += $good->nums;
  323. $shopGood->duihuan_nums -= $good->nums;
  324. $shopGood->save();
  325. }
  326. }
  327. $order['user_jifen'] = $user->jifen;
  328. });
  329. return true;
  330. }
  331. /**
  332. * 批量审核
  333. * @param $ids
  334. * @param $data
  335. * @return bool
  336. */
  337. public function handleBatchCheck($ids, $data)
  338. {
  339. $db_nums = ShopOrder::query()->whereIn('id', $ids)->where('status', ShopOrderStatusEnum::wait_check)->where('check_status', CheckStatusEnum::WAIT)->count();
  340. if (count($ids) !== (int)$db_nums) {
  341. abort(ResponseCodeEnum::SERVICE_OPERATION_ERROR, '勾选中存在不满足条件的记录');
  342. }
  343. $orders = ShopOrder::query()->whereIn('id', $ids)->where('status', ShopOrderStatusEnum::wait_check)->where('check_status', CheckStatusEnum::WAIT)->get();
  344. $admin_id = login_admin_id();
  345. DB::transaction(function () use ($orders, $data, $admin_id) {
  346. foreach ($orders as $order) {
  347. $order->check_status = $data['check_status'];
  348. $order->check_admin_id = $admin_id;
  349. $order->check_remark = $data['check_remark'];
  350. $order->check_time = Carbon::now()->toDateTimeString();
  351. $order->status = ShopOrderStatusEnum::wait_send;
  352. $order->save();
  353. }
  354. });
  355. return true;
  356. }
  357. }