123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535 |
- <?php
- namespace App\Services;
- use App\Enums\OrderRecordStatus;
- use App\Enums\OrderStatus;
- use App\Enums\TechnicianWorkStatus;
- use App\Models\CoachLocation;
- use App\Models\Order;
- use App\Models\OrderExcRecord;
- use App\Models\OrderGrabRecord;
- use App\Models\OrderRecord;
- use Illuminate\Support\Facades\Auth;
- use Illuminate\Support\Facades\DB;
- use Illuminate\Support\Facades\Log;
- use Slowlyo\OwlAdmin\Services\AdminService;
- /**
- * 订单
- *
- * @method Order getModel()
- * @method Order|\Illuminate\Database\Query\Builder query()
- */
- class OrderService extends AdminService
- {
- protected string $modelName = Order::class;
- /**
- * 更换订单技师
- *
- * @param array $data 包含 order_id, new_coach_id 和可选的 reason
- */
- public function changeOrderCoach(array $data): array
- {
- try {
- DB::beginTransaction();
- // 获取订单信息
- $order = Order::findOrFail($data['order_id']);
- // 验证订单状态是否允许更换技师
- $allowedStates = [
- OrderStatus::PAID->value,
- OrderStatus::ACCEPTED->value,
- OrderStatus::DEPARTED->value,
- OrderStatus::ARRIVED->value,
- ];
- abort_if(! in_array($order->state, $allowedStates), 422, '当前订单状态不允许更换技师');
- // 记录原技师ID
- $oldCoachId = $order->coach_id;
- // 更新订单技师
- $order->coach_id = $data['new_coach_id'];
- $order->save();
- // 记录技师更换历史
- OrderRecord::create([
- 'order_id' => $order->id,
- 'object_id' => Auth::user()->id,
- 'object_type' => 'admin',
- 'old_coach_id' => $oldCoachId,
- 'new_coach_id' => $data['new_coach_id'],
- 'state' => OrderRecordStatus::CHANGE_COACH->value,
- 'remark' => $data['reason'] ?? null,
- ]);
- DB::commit();
- return [
- 'code' => 200,
- 'message' => '更换技师成功',
- 'data' => null,
- ];
- } catch (\Exception $e) {
- DB::rollBack();
- Log::error('更换订单技师失败', [
- 'order_id' => $data['order_id'],
- 'new_coach_id' => $data['new_coach_id'],
- 'error' => $e->getMessage(),
- 'trace' => $e->getTraceAsString(),
- ]);
- throw $e;
- }
- }
- /**
- * 指定抢单技师
- *
- * @param array $data 包含 order_id, coach_id 和可选的 remark
- */
- public function assignOrderCoach(array $data): array
- {
- try {
- DB::beginTransaction();
- // 获取订单信息
- $order = Order::findOrFail($data['order_id']);
- // 验证订单状态是否为待抢单
- abort_if($order->state !== OrderStatus::CREATED->value, 422, '当前订单状态不允许指定技师');
- // 更新订单技师和状态
- $order->coach_id = $data['coach_id'];
- $order->state = OrderStatus::ASSIGNED->value;
- $order->save();
- // 记录指定技师历史
- OrderRecord::create([
- 'order_id' => $order->id,
- 'object_id' => Auth::user()->id,
- 'object_type' => 'admin',
- 'old_coach_id' => null,
- 'new_coach_id' => $data['coach_id'],
- 'state' => OrderRecordStatus::ASSIGNED->value,
- 'remark' => $data['remark'] ?? '平台指派',
- ]);
- DB::commit();
- return [
- 'code' => 200,
- 'message' => '指定技师成功',
- 'data' => null,
- ];
- } catch (\Exception $e) {
- DB::rollBack();
- Log::error('指定抢单技师失败', [
- 'order_id' => $data['order_id'],
- 'coach_id' => $data['coach_id'],
- 'error' => $e->getMessage(),
- 'trace' => $e->getTraceAsString(),
- ]);
- throw $e;
- }
- }
- /**
- * 获取订单抢单技师列表
- *
- * @param int $orderId 订单ID
- */
- public function getOrderGrabList(int $orderId): array
- {
- try {
- // 获取订单信息
- $order = Order::findOrFail($orderId);
- // 获取抢单记录
- $grabRecords = OrderGrabRecord::with(['coach', 'coach.info'])
- ->where('order_id', $orderId)
- ->orderBy('created_at', 'desc')
- ->get();
- $data = $grabRecords->map(function ($record) {
- return [
- 'id' => $record->id,
- 'coach_id' => $record->coach_id,
- 'nickname' => $record->coach->info->nickname ?? '',
- 'avatar' => $record->coach->info->avatar ?? '',
- 'distance' => $record->distance,
- 'state' => $record->state,
- 'created_at' => $record->created_at->format('Y-m-d H:i:s'),
- ];
- });
- return [
- 'code' => 200,
- 'message' => '获取成功',
- 'data' => $data,
- ];
- } catch (\Exception $e) {
- Log::error('获取订单抢单技师列表失败', [
- 'order_id' => $orderId,
- 'error' => $e->getMessage(),
- 'trace' => $e->getTraceAsString(),
- ]);
- throw $e;
- }
- }
- /**
- * 获取附近技师列表
- *
- * @param int $orderId 订单ID
- * @param int $distance 搜索范围(米)
- */
- public function getNearbyCoaches(int $orderId, int $distance = 5000): array
- {
- try {
- // 获取订单信息
- $order = Order::findOrFail($orderId);
- // 获取附近技师
- // TODO: 优化查询
- $nearbyCoaches = CoachLocation::with(['coach', 'coach.info', 'coach.score'])
- ->selectRaw('*, ST_Distance_Sphere(
- point(longitude, latitude),
- point(?, ?)
- ) as distance', [$order->longitude, $order->latitude])
- ->having('distance', '<=', $distance)
- ->orderBy('distance')
- ->get();
- $data = $nearbyCoaches->map(function ($location) {
- return [
- 'id' => $location->coach->id,
- 'nickname' => $location->coach->info->nickname ?? '',
- 'avatar' => $location->coach->info->avatar ?? '',
- 'distance' => round($location->distance / 1000, 1), // 转换公里
- 'work_status' => $location->coach->work_status,
- 'work_status_text' => TechnicianWorkStatus::fromValue($location->coach->work_status)->label(),
- 'rating' => $location->coach->score->rating_score ?? 5.0,
- 'order_count' => $location->coach->score->order_count ?? 0,
- 'created_at' => $location->coach->created_at->format('Y-m-d H:i:s'),
- ];
- });
- return [
- 'code' => 200,
- 'message' => '获取成功',
- 'data' => $data,
- ];
- } catch (\Exception $e) {
- Log::error('获取附近技师列表失败', [
- 'order_id' => $orderId,
- 'distance' => $distance,
- 'error' => $e->getMessage(),
- 'trace' => $e->getTraceAsString(),
- ]);
- throw $e;
- }
- }
- /**
- * 重置订单技师
- *
- * @param array $data 包含 order_id 和可选的 reason
- */
- public function resetOrderCoach(array $data): array
- {
- // 获取管理员用户ID
- $adminUser = Auth::guard('admin')->user();
- abort_if(!$adminUser, 403, '未获取到管理员信息');
- try {
- DB::beginTransaction();
- // 检查订单ID是否存在
- if (!isset($data['order_id'])) {
- throw new \Exception('订单ID不能为空');
- }
- // 获取订单信息
- $order = Order::find($data['order_id']);
- if (!$order) {
- throw new \Exception('订单不存在');
- }
- // 验证订单状态是否允许重置技师
- $allowedStates = [
- OrderStatus::PAID->value,
- OrderStatus::ACCEPTED->value,
- OrderStatus::DEPARTED->value,
- OrderStatus::ARRIVED->value,
- ];
- abort_if(! in_array($order->state, $allowedStates), 422, '当前订单状态不允许重置技师');
- // 记录原技师ID
- $oldCoachId = $order->coach_id;
- if (!$oldCoachId) {
- throw new \Exception('订单未分配技师');
- }
- // 更新订单信息
- $order->coach_id = null;
- $order->state = OrderStatus::PAID->value; // 重置为支付状态
- $order->save();
- // 记录技师重置历史
- OrderRecord::create([
- 'order_id' => $order->id,
- 'object_id' => $adminUser->id,
- 'object_type' => 'admin',
- 'old_coach_id' => $oldCoachId,
- 'new_coach_id' => null,
- 'state' => OrderRecordStatus::RESET_COACH->value,
- 'remark' => $data['reason'] ?? '平台重置技师',
- ]);
- DB::commit();
- return [
- 'code' => 200,
- 'message' => '重置技师成功',
- 'data' => null,
- ];
- } catch (\Exception $e) {
- DB::rollBack();
- throw $e;
- }
- }
- /**
- * 临时接单
- *
- * @param array $data 包含 order_id 和可选的 reason
- */
- public function temporaryAcceptOrder(array $data): array
- {
- // 获取管理员用户ID
- $adminUser = Auth::guard('admin')->user();
- abort_if(!$adminUser, 403, '未获取到管理员信息');
- try {
- DB::beginTransaction();
- // 获取订单信息
- $order = Order::findOrFail($data['order_id']);
- // 验证订单状态是否为已支付状态
- abort_if($order->state !== OrderStatus::PAID->value, 422, '当前订单状态不允许接单');
- // 验证订单必须已指定技师
- abort_if(empty($order->coach_id), 422, '订单未指定技师');
- // 更新订单信息
- $order->state = OrderStatus::ACCEPTED->value; // 更新为已接单状态
- $order->save();
- // 记录临时接单历史
- OrderRecord::create([
- 'order_id' => $order->id,
- 'object_id' => $adminUser->id,
- 'object_type' => 'admin',
- 'old_coach_id' => null,
- 'new_coach_id' => $order->coach_id,
- 'state' => OrderRecordStatus::TEMPORARY_ACCEPTED->value,
- 'remark' => $data['reason'] ?? '平台临时接单',
- ]);
- DB::commit();
- return [
- 'code' => 200,
- 'message' => '接单成功',
- 'data' => null,
- ];
- } catch (\Exception $e) {
- DB::rollBack();
- Log::error('临时接单失败', [
- 'order_id' => $data['order_id'],
- 'error' => $e->getMessage(),
- 'trace' => $e->getTraceAsString(),
- ]);
- throw $e;
- }
- }
- /**
- * 开始服务
- *
- * @param array $data 包含 order_id 和可选的 reason
- */
- public function startOrderService(array $data): array
- {
- // 获取管理员用户ID
- $adminUser = Auth::guard('admin')->user();
- abort_if(!$adminUser, 403, '未获取到管理员信息');
- try {
- DB::beginTransaction();
- // 获取订单信息
- $order = Order::findOrFail($data['order_id']);
- // 验证订单状态是否允许开始服务
- $allowedStates = [
- OrderStatus::ACCEPTED->value,
- OrderStatus::DEPARTED->value,
- OrderStatus::ARRIVED->value,
- ];
- abort_if(! in_array($order->state, $allowedStates), 422, '当前订单状态不允许开始服务');
- // 更新订单状态
- $order->state = OrderStatus::SERVICE_START->value;
- $order->save();
- // 记录开始服务历史
- OrderRecord::create([
- 'order_id' => $order->id,
- 'object_id' => $adminUser->id,
- 'object_type' => 'admin',
- 'old_coach_id' => $order->coach_id,
- 'new_coach_id' => $order->coach_id,
- 'state' => OrderRecordStatus::STARTED->value,
- 'remark' => $data['reason'] ?? '平台代扫核销码',
- ]);
- DB::commit();
- return [
- 'code' => 200,
- 'message' => '开始服务成功',
- 'data' => null,
- ];
- } catch (\Exception $e) {
- DB::rollBack();
- Log::error('开始服务失败', [
- 'order_id' => $data['order_id'],
- 'error' => $e->getMessage(),
- 'trace' => $e->getTraceAsString(),
- ]);
- throw $e;
- }
- }
- /**
- * 结束服务
- *
- * @param array $data 包含 order_id 和可选的 reason
- */
- public function endOrderService(array $data): array
- {
- // 获取管理员用户ID
- $adminUser = Auth::guard('admin')->user();
- abort_if(!$adminUser, 403, '未获取到管理员信息');
- try {
- DB::beginTransaction();
- // 获取订单信息
- $order = Order::findOrFail($data['order_id']);
- // 验证订单状态是否为已开始服务状态
- abort_if($order->state !== OrderStatus::SERVICE_START->value, 422, '当前订单状态不允许结束服务');
- // 更新订单状态
- $order->state = OrderStatus::LEFT->value;
- $order->save();
- // 记录结束服务历史
- OrderRecord::create([
- 'order_id' => $order->id,
- 'object_id' => $adminUser->id,
- 'object_type' => 'admin',
- 'old_coach_id' => $order->coach_id,
- 'new_coach_id' => $order->coach_id,
- 'state' => OrderRecordStatus::LEFT->value,
- 'remark' => $data['reason'] ?? '平台代确认撤离',
- ]);
- DB::commit();
- return [
- 'code' => 200,
- 'message' => '结束服务成功',
- 'data' => null,
- ];
- } catch (\Exception $e) {
- DB::rollBack();
- Log::error('结束服务失败', [
- 'order_id' => $data['order_id'],
- 'error' => $e->getMessage(),
- 'trace' => $e->getTraceAsString(),
- ]);
- throw $e;
- }
- }
- /**
- * 处理报警
- *
- * @param array $data 包含 exc_record_id 和 handle_result
- */
- public function handleOrderAlarm(array $data): array
- {
- // 获取管理员用户ID
- $adminUser = Auth::guard('admin')->user();
- abort_if(!$adminUser, 403, '未获取到管理员信息');
- try {
- DB::beginTransaction();
- // 获取并验证异常记录
- $excRecord = OrderExcRecord::where('id', $data['exc_record_id'])
- ->firstOrFail();
- // 获取关联的订单信息
- $order = Order::findOrFail($excRecord->order_id);
- // 更新异常记录状态
- $excRecord->handle_result = $data['handle_result'];
- $excRecord->handler_id = $adminUser->id;
- $excRecord->handle_time = now();
- $excRecord->save();
- // 记录处理历史
- OrderRecord::create([
- 'order_id' => $order->id,
- 'object_id' => $adminUser->id,
- 'object_type' => 'admin',
- 'old_coach_id' => $order->coach_id,
- 'new_coach_id' => $order->coach_id,
- 'state' => OrderRecordStatus::ALARM_HANDLED->value,
- 'remark' => $data['handle_result'],
- ]);
- DB::commit();
- return [
- 'code' => 200,
- 'message' => '处理成功',
- 'data' => null,
- ];
- } catch (\Exception $e) {
- DB::rollBack();
- Log::error('处理报警失败', [
- 'exc_record_id' => $data['exc_record_id'],
- 'error' => $e->getMessage(),
- 'trace' => $e->getTraceAsString(),
- ]);
- throw $e;
- }
- }
- }
|