OrderController.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. <?php
  2. namespace App\Http\Controllers\Client;
  3. use App\Http\Controllers\Controller;
  4. use App\Services\Client\OrderService;
  5. use Illuminate\Http\Request;
  6. class OrderController extends Controller
  7. {
  8. protected OrderService $service;
  9. public function __construct(OrderService $service)
  10. {
  11. $this->service = $service;
  12. }
  13. /**
  14. * 订单初始化
  15. */
  16. public function initialize(Request $request)
  17. {
  18. $userId = Auth::id();
  19. $coachId = $request->input('coach_id');
  20. $areaCode = $request->input('area_code');
  21. $projectId = $request->input('project_id');
  22. return $this->service->initialize($userId, $coachId, $areaCode, $projectId);
  23. }
  24. /**
  25. * 结束订单
  26. */
  27. public function finish(Request $request)
  28. {
  29. $userId = Auth::id();
  30. $orderId = $request->input('order_id');
  31. return $this->service->finishOrder($userId, $orderId);
  32. }
  33. /**
  34. * 确认技师离开
  35. */
  36. public function confirmLeave(Request $request)
  37. {
  38. $userId = Auth::id();
  39. $orderId = $request->input('order_id');
  40. return $this->service->confirmLeave($userId, $orderId);
  41. }
  42. /**
  43. * 取消订单
  44. */
  45. public function cancel(Request $request)
  46. {
  47. $userId = Auth::id();
  48. $orderId = $request->input('order_id');
  49. return $this->service->cancelOrder($userId, $orderId);
  50. }
  51. /**
  52. * 获取订单列表
  53. */
  54. public function list()
  55. {
  56. return $this->service->getOrderList();
  57. }
  58. /**
  59. * 获取订单详情
  60. */
  61. public function detail($id)
  62. {
  63. return $this->service->getOrderDetail($id);
  64. }
  65. /**
  66. * 订单退款
  67. */
  68. public function refund($id)
  69. {
  70. return $this->service->refundOrder($id);
  71. }
  72. /**
  73. * 获取代理商配置
  74. */
  75. public function getAgentConfig(Request $request)
  76. {
  77. $agentId = $request->input('agent_id');
  78. return $this->service->getAgentConfig($agentId);
  79. }
  80. /**
  81. * 获取技师配置
  82. */
  83. public function getCoachConfig(Request $request)
  84. {
  85. $coachId = $request->input('coach_id');
  86. return $this->service->getCoachConfig($coachId);
  87. }
  88. /**
  89. * 计算路费金额
  90. */
  91. public function calculateDeliveryFee(Request $request)
  92. {
  93. $coachId = $request->input('coach_id');
  94. $agentId = $request->input('agent_id');
  95. $distance = $request->input('distance');
  96. $latitude = $request->input('latitude');
  97. $longitude = $request->input('longitude');
  98. if ($agentId) {
  99. return $this->service->calculateDeliveryFee($coachId, $agentId, $distance);
  100. } else {
  101. return $this->service->calculateDeliveryFeeByLocation($coachId, $latitude, $longitude, $distance);
  102. }
  103. }
  104. /**
  105. * 计算订单金额
  106. */
  107. public function calculateOrderAmount(Request $request)
  108. {
  109. $userId = Auth::id();
  110. $addressId = $request->input('address_id');
  111. $coachId = $request->input('coach_id');
  112. $projectId = $request->input('project_id');
  113. $agentId = $request->input('agent_id');
  114. $useBalance = $request->input('use_balance', 0);
  115. return $this->service->calculateOrderAmount($userId, $addressId, $coachId, $projectId, $agentId, $useBalance);
  116. }
  117. /**
  118. * 创建订单
  119. */
  120. public function create(Request $request)
  121. {
  122. $userId = Auth::id();
  123. $projectId = $request->input('project_id');
  124. $addressId = $request->input('address_id');
  125. $coachId = $request->input('coach_id');
  126. $useBalance = $request->input('use_balance', 0);
  127. $orderId = $request->input('order_id');
  128. return $this->service->createOrder($userId, $projectId, $addressId, $coachId, $useBalance, $orderId);
  129. }
  130. /**
  131. * 加钟
  132. */
  133. public function addTime(Request $request, $orderId)
  134. {
  135. $userId = Auth::id();
  136. return $this->service->addTime($userId, $orderId);
  137. }
  138. /**
  139. * 指定技师
  140. */
  141. public function assignCoach(Request $request, $orderId)
  142. {
  143. $userId = Auth::id();
  144. $coachId = $request->input('coach_id');
  145. return $this->service->assignCoach($userId, $orderId, $coachId);
  146. }
  147. /**
  148. * 获取代理商配置
  149. */
  150. public function getAgentConfig($agentId)
  151. {
  152. $agent = AgentInfo::where('id', $agentId)
  153. ->where('state', 'enable')
  154. ->firstOrFail();
  155. $config = AgentConfig::where('agent_id', $agentId)->firstOrFail();
  156. return [
  157. 'min_distance' => $config->min_distance,
  158. 'min_fee' => $config->min_fee,
  159. 'per_km_fee' => $config->per_km_fee
  160. ];
  161. }
  162. /**
  163. * 获取技师配置
  164. */
  165. public function getCoachConfig($coachId)
  166. {
  167. $coach = CoachUser::where('id', $coachId)
  168. ->where('state', 'enable')
  169. ->where('auth_state', 'passed')
  170. ->firstOrFail();
  171. $config = CoachConfig::where('coach_id', $coachId)->firstOrFail();
  172. return [
  173. 'delivery_fee_type' => $config->delivery_fee_type,
  174. 'charge_delivery_fee' => $config->charge_delivery_fee
  175. ];
  176. }
  177. /**
  178. * 计算路费金额
  179. */
  180. public function calculateDeliveryFee($coachId, $agentId, $distance)
  181. {
  182. $coach = CoachUser::where('id', $coachId)
  183. ->where('state', 'enable')
  184. ->where('auth_state', 'passed')
  185. ->firstOrFail();
  186. $coachConfig = CoachConfig::where('coach_id', $coachId)->firstOrFail();
  187. if (!$coachConfig->charge_delivery_fee) {
  188. return 0;
  189. }
  190. $agentConfig = AgentConfig::where('agent_id', $agentId)->firstOrFail();
  191. $fee = 0;
  192. if ($distance <= $agentConfig->min_distance) {
  193. $fee = $agentConfig->min_fee;
  194. } else {
  195. $extraDistance = $distance - $agentConfig->min_distance;
  196. $fee = $agentConfig->min_fee + ($extraDistance * $agentConfig->per_km_fee);
  197. }
  198. return $coachConfig->delivery_fee_type == 'round_trip' ? $fee * 2 : $fee;
  199. }
  200. /**
  201. * 计算订单金额
  202. */
  203. public function calculateOrderAmount($userId, $addressId, $coachId, $projectId, $agentId, $useBalance)
  204. {
  205. // 参数校验
  206. $user = User::where('id', $userId)
  207. ->where('status', 1)
  208. ->firstOrFail();
  209. $address = UserAddress::where('id', $addressId)
  210. ->where('user_id', $userId)
  211. ->firstOrFail();
  212. $coach = CoachUser::where('id', $coachId)
  213. ->where('state', 'enable')
  214. ->where('auth_state', 'passed')
  215. ->firstOrFail();
  216. $project = Project::where('id', $projectId)
  217. ->where('state', 'enable')
  218. ->firstOrFail();
  219. // 计算金额
  220. $projectAmount = $project->price;
  221. $deliveryFee = $this->calculateDeliveryFee($coachId, $agentId, $address->distance);
  222. $tipAmount = request()->has('order_id') ? Order::find(request()->input('order_id'))->tip_amount : 0;
  223. $couponAmount = 0;
  224. if (request()->has('coupon_id')) {
  225. $coupon = Coupon::where('id', request()->input('coupon_id'))
  226. ->where('state', 'enable')
  227. ->firstOrFail();
  228. $couponAmount = $coupon->amount;
  229. }
  230. $totalAmount = $projectAmount + $deliveryFee + $tipAmount - $couponAmount;
  231. $balanceAmount = 0;
  232. $payAmount = $totalAmount;
  233. if ($useBalance) {
  234. $wallet = UserWallet::where('user_id', $userId)->first();
  235. if ($wallet && $wallet->balance >= $totalAmount) {
  236. $balanceAmount = $totalAmount;
  237. $payAmount = 0;
  238. } else if ($wallet) {
  239. $balanceAmount = $wallet->balance;
  240. $payAmount = $totalAmount - $balanceAmount;
  241. }
  242. }
  243. return [
  244. 'total_amount' => $totalAmount,
  245. 'balance_amount' => $balanceAmount,
  246. 'pay_amount' => $payAmount,
  247. 'coupon_amount' => $couponAmount,
  248. 'tip_amount' => $tipAmount,
  249. 'project_amount' => $projectAmount,
  250. 'delivery_fee' => $deliveryFee
  251. ];
  252. }
  253. /**
  254. * 创建订单
  255. */
  256. public function createOrder($userId, $projectId, $addressId, $coachId, $useBalance, $orderId = null)
  257. {
  258. return DB::transaction(function() use ($userId, $projectId, $addressId, $coachId, $useBalance, $orderId) {
  259. // 参数校验
  260. $user = User::where('id', $userId)
  261. ->where('status', 1)
  262. ->firstOrFail();
  263. $address = UserAddress::where('id', $addressId)
  264. ->where('user_id', $userId)
  265. ->firstOrFail();
  266. if (!$orderId) {
  267. $coach = CoachUser::where('id', $coachId)
  268. ->where('state', 'enable')
  269. ->where('auth_state', 'passed')
  270. ->firstOrFail();
  271. }
  272. $project = Project::where('id', $projectId)
  273. ->where('state', 'enable')
  274. ->firstOrFail();
  275. // 创建订单
  276. $orderType = $orderId ? 'add_time' : 'normal';
  277. $amounts = $this->calculateOrderAmount($userId, $addressId, $coachId, $projectId, $project->agent_id, $useBalance);
  278. $order = new Order();
  279. $order->user_id = $userId;
  280. $order->project_id = $projectId;
  281. $order->address_id = $addressId;
  282. $order->coach_id = $coachId;
  283. $order->order_type = $orderType == 'normal' ? 0 : 1;
  284. $order->status = 0;
  285. $order->total_amount = $amounts['total_amount'];
  286. $order->balance_amount = $amounts['balance_amount'];
  287. $order->pay_amount = $amounts['pay_amount'];
  288. $order->coupon_amount = $amounts['coupon_amount'];
  289. $order->tip_amount = $amounts['tip_amount'];
  290. $order->project_amount = $amounts['project_amount'];
  291. $order->delivery_fee = $orderType == 'add_time' ? 0 : $amounts['delivery_fee'];
  292. $order->payment_type = $useBalance && $amounts['pay_amount'] == 0 ? 0 : 1;
  293. $order->save();
  294. // 创建订单历史
  295. if ($orderType == 'add_time') {
  296. OrderHistory::create([
  297. 'order_id' => $order->id,
  298. 'type' => 'add_time',
  299. 'user_id' => $userId
  300. ]);
  301. } else {
  302. OrderHistory::create([
  303. 'order_id' => $order->id,
  304. 'type' => 'create',
  305. 'user_id' => $userId
  306. ]);
  307. }
  308. // 余额支付处理
  309. if ($order->payment_type == 0) {
  310. $order->status = 1;
  311. $order->save();
  312. OrderHistory::create([
  313. 'order_id' => $order->id,
  314. 'type' => 'pay',
  315. 'user_id' => $userId
  316. ]);
  317. CoachSchedule::create([
  318. 'coach_id' => $coachId,
  319. 'date' => date('Y-m-d'),
  320. 'status' => 'busy'
  321. ]);
  322. return $order->id;
  323. }
  324. // 微信支付处理
  325. // TODO: 调用支付接口
  326. return $order->id;
  327. });
  328. }
  329. /**
  330. * 加钟
  331. */
  332. public function addTime($userId, $orderId)
  333. {
  334. $order = Order::where('id', $orderId)
  335. ->where('user_id', $userId)
  336. ->firstOrFail();
  337. return $this->createOrder($userId, $order->project_id, $order->address_id, $order->coach_id, 0, $orderId);
  338. }
  339. /**
  340. * 指定技师
  341. */
  342. public function assignCoach($userId, $orderId, $coachId)
  343. {
  344. return DB::transaction(function() use ($userId, $orderId, $coachId) {
  345. // 参数校验
  346. $user = User::where('id', $userId)
  347. ->where('status', 1)
  348. ->firstOrFail();
  349. $order = Order::where('id', $orderId)
  350. ->where('user_id', $userId)
  351. ->whereIn('status', [0, 1, 6])
  352. ->firstOrFail();
  353. $coach = CoachUser::where('id', $coachId)
  354. ->where('state', 'enable')
  355. ->where('auth_state', 'passed')
  356. ->firstOrFail();
  357. $schedule = CoachSchedule::where('coach_id', $coachId)
  358. ->where('date', date('Y-m-d'))
  359. ->where('status', 'free')
  360. ->firstOrFail();
  361. // 修改订单
  362. $order->coach_id = $coachId;
  363. if ($order->status == 0) {
  364. $amounts = $this->calculateOrderAmount($userId, $order->address_id, $coachId, $order->project_id, $order->agent_id, $order->payment_type == 0);
  365. $order->total_amount = $amounts['total_amount'];
  366. $order->balance_amount = $amounts['balance_amount'];
  367. $order->pay_amount = $amounts['pay_amount'];
  368. $order->coupon_amount = $amounts['coupon_amount'];
  369. $order->tip_amount = $amounts['tip_amount'];
  370. $order->project_amount = $amounts['project_amount'];
  371. $order->delivery_fee = $amounts['delivery_fee'];
  372. if ($order->payment_type == 0) {
  373. $order->status = 1;
  374. }
  375. }
  376. if ($order->status == 1) {
  377. $order->status = 2;
  378. }
  379. $order->save();
  380. // 创建订单历史
  381. OrderHistory::create([
  382. 'order_id' => $order->id,
  383. 'type' => 'assign_coach',
  384. 'user_id' => $userId,
  385. 'coach_id' => $coachId
  386. ]);
  387. OrderHistory::create([
  388. 'order_id' => $order->id,
  389. 'type' => 'accept',
  390. 'user_id' => $userId,
  391. 'coach_id' => $coachId,
  392. 'remark' => '抢单成功'
  393. ]);
  394. // 更新抢单池
  395. GrabOrder::where('order_id', $orderId)
  396. ->update(['status' => 2, 'coach_id' => $coachId]);
  397. // 更新排班
  398. $schedule->status = 'busy';
  399. $schedule->save();
  400. return true;
  401. });
  402. }
  403. }