Browse Source

fixed:技师端-获取订单设置

刘学玺 3 months ago
parent
commit
a816a85303

+ 46 - 10
app/Enums/OrderStatus.php

@@ -7,7 +7,7 @@ namespace App\Enums;
  *
  * 定义了订单从创建到完成的所有可能状态
  * 状态流转顺序:
- * 已创建 -> 已支付 -> 已接单 -> 已出发 -> 已到达 -> 开始服务 -> 服务中 -> 服务结束 -> 撤离中 -> 已完成
+ * 已创建 -> 已支付 -> 已分配 -> 已接单 -> 已出发 -> 已到达 -> 开始服务 -> 服务中 -> 服务结束 -> 撤离中 -> 已撤离 -> 已完成
  * 任意状态都可以变为:已取消
  */
 enum OrderStatus: int
@@ -24,59 +24,83 @@ enum OrderStatus: int
      */
     case PAID = 2;       // 可以进入抢单流程
 
+    /**
+     * 订单状态:已分配
+     * 技师接受订单,准备提供服务
+     */
+    case ASSIGNED = 3;   // 技师已分配
+
     /**
      * 订单状态:已接单
      * 技师接受订单,准备提供服务
      */
-    case ACCEPTED = 3;   // 技师已确认接单
+    case ACCEPTED = 4;   // 技师已确认接单
 
     /**
      * 订单状态:已出发
      * 技师已经出发前往服务地点
      */
-    case DEPARTED = 4;   // 技师开始前往目的地
+    case DEPARTED = 5;   // 技师开始前往目的地
 
     /**
      * 订单状态:已到达
      * 技师已到达服务地点
      */
-    case ARRIVED = 5;    // 技师已到达用户位置
+    case ARRIVED = 6;    // 技师已到达用户位置
 
     /**
      * 订单状态:开始服务
      * 技师开始提供服务
      */
-    case SERVICE_START = 6;  // 正式开始服务
+    case SERVICE_START = 7;  // 正式开始服务
 
     /**
      * 订单状态:服务中
      * 技师正在提供服务
      */
-    case SERVICING = 7;     // 服务进行中
+    case SERVICING = 8;     // 服务进行中
 
     /**
      * 订单状态:服务结束
      * 技师已完成服务内容
      */
-    case SERVICE_END = 8;   // 服务内容已完成
+    case SERVICE_END = 9;   // 服务内容已完成
 
     /**
      * 订单状态:撤离中
      * 技师正在离开服务地点
      */
-    case LEAVING = 9;       // 技师正在返程
+    case LEAVING = 10;       // 技师正在返程
+
+    /**
+     * 订单状态:已撤离
+     * 技师已完成服务并离开服务地点
+     */
+    case LEFT = 11;        // 技师已完成服务并离开服务地点
 
     /**
      * 订单状态:已完成
      * 订单全部流程结束
      */
-    case COMPLETED = 10;    // 订单完成状态
+    case COMPLETED = 12;    // 订单完成状态
 
     /**
      * 订单状态:已取消
      * 订单被取消(可能是用户取消或系统取消)
      */
-    case CANCELLED = 11;    // 订单终止状态
+    case CANCELLED = 13;    // 订单终止状态
+
+    /**
+     * 订单状态:已退款
+     * 订单被取消并已退款
+     */
+    case REFUNDED = 14;    // 订单已退款
+
+    /**
+     * 订单状态:已拒单
+     * 技师拒绝接单
+     */
+    case REJECTED = 15;    // 技师拒单
 
     /**
      * 获取状态的显示文本
@@ -89,6 +113,7 @@ enum OrderStatus: int
         return match ($this) {
             self::CREATED => '已创建',        // 订单创建完成
             self::PAID => '已支付',           // 支付完成
+            self::ASSIGNED => '已分配',       // 技师分配
             self::ACCEPTED => '已接单',       // 技师接单
             self::DEPARTED => '已出发',       // 技师出发
             self::ARRIVED => '已到达',        // 技师到达
@@ -96,8 +121,11 @@ enum OrderStatus: int
             self::SERVICING => '服务中',      // 服务进行中
             self::SERVICE_END => '服务结束',   // 服务完成
             self::LEAVING => '撤离中',        // 技师离开
+            self::LEFT => '已撤离',           // 技师已完成服务并离开服务地点
             self::COMPLETED => '已完成',      // 订单完结
             self::CANCELLED => '已取消',      // 订单取消
+            self::REFUNDED => '已退款',       // 订单已退款
+            self::REJECTED => '已拒单',      // 技师拒单
         };
     }
 
@@ -133,6 +161,7 @@ enum OrderStatus: int
         return match ($value) {
             self::CREATED->value => self::CREATED,
             self::PAID->value => self::PAID,
+            self::ASSIGNED->value => self::ASSIGNED,
             self::ACCEPTED->value => self::ACCEPTED,
             self::DEPARTED->value => self::DEPARTED,
             self::ARRIVED->value => self::ARRIVED,
@@ -140,8 +169,11 @@ enum OrderStatus: int
             self::SERVICING->value => self::SERVICING,
             self::SERVICE_END->value => self::SERVICE_END,
             self::LEAVING->value => self::LEAVING,
+            self::LEFT->value => self::LEFT,
             self::COMPLETED->value => self::COMPLETED,
             self::CANCELLED->value => self::CANCELLED,
+            self::REFUNDED->value => self::REFUNDED,
+            self::REJECTED->value => self::REJECTED,
             default => null
         };
     }
@@ -166,6 +198,7 @@ enum OrderStatus: int
         return [
             self::CREATED->value => self::CREATED->label(),
             self::PAID->value => self::PAID->label(),
+            self::ASSIGNED->value => self::ASSIGNED->label(),
             self::ACCEPTED->value => self::ACCEPTED->label(),
             self::DEPARTED->value => self::DEPARTED->label(),
             self::ARRIVED->value => self::ARRIVED->label(),
@@ -173,8 +206,11 @@ enum OrderStatus: int
             self::SERVICING->value => self::SERVICING->label(),
             self::SERVICE_END->value => self::SERVICE_END->label(),
             self::LEAVING->value => self::LEAVING->label(),
+            self::LEFT->value => self::LEFT->label(),
             self::COMPLETED->value => self::COMPLETED->label(),
             self::CANCELLED->value => self::CANCELLED->label(),
+            self::REFUNDED->value => self::REFUNDED->label(),
+            self::REJECTED->value => self::REJECTED->label(),
         ];
     }
 }

+ 27 - 3
app/Http/Controllers/Coach/OrderController.php

@@ -2,10 +2,10 @@
 
 namespace App\Http\Controllers\Coach;
 
+use Illuminate\Http\Request;
+use App\Traits\ResponseTrait;
 use App\Http\Controllers\Controller;
 use App\Services\Coach\OrderService;
-use App\Traits\ResponseTrait;
-use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Auth;
 
 /**
@@ -142,7 +142,7 @@ class OrderController extends Controller
      *
      * @authenticated
      *
-     * @urlParam order_id integer required ���单ID Example: 1
+     * @urlParam order_id integer required 单ID Example: 1
      *
      * @response {
      *   "message": "接单成功",
@@ -338,4 +338,28 @@ class OrderController extends Controller
             $this->service->setOrder(Auth::user()->id, $data)
         );
     }
+
+    /**
+     * [订单]获取订单设置
+     *
+     * @description 获取技师的订单相关设置,如服务距离等
+     *
+     * @authenticated 需要技师身份认证
+     *
+     * @response 200 {
+     *   "status": true,
+     *   "message": "获取成功",
+     *   "data": {
+     *     "distance": 10,              // 服务距离(公里)
+     *     "distance_max": 40,          // 最大服务距离(公里)
+     *     "distance_min": 1            // 最小服务距离(公里)
+     *   }
+     * }
+     */
+    public function getOrderSettings()
+    {
+        return $this->success(
+            $this->service->getOrderSettings(Auth::user()->coach)
+        );
+    }
 }

+ 63 - 32
app/Services/Coach/OrderService.php

@@ -2,25 +2,25 @@
 
 namespace App\Services\Coach;
 
-use App\Enums\OrderGrabRecordStatus;
-use App\Enums\OrderRecordStatus;
-use App\Enums\OrderStatus;
+use App\Models\Order;
 use App\Enums\OrderType;
-use App\Enums\ProjectStatus;
-use App\Enums\TechnicianAuthStatus;
-use App\Enums\TechnicianLocationType;
-use App\Enums\TechnicianStatus;
-use App\Jobs\AutoFinishOrder;
 use App\Models\CoachUser;
+use App\Enums\OrderStatus;
 use App\Models\MemberUser;
-use App\Models\Order;
-use App\Models\OrderGrabRecord;
 use App\Models\OrderRecord;
+use App\Enums\ProjectStatus;
 use App\Models\SettingGroup;
-use App\Services\SettingItemService;
-use Illuminate\Support\Facades\Cache;
+use App\Jobs\AutoFinishOrder;
+use App\Enums\TechnicianStatus;
+use App\Models\OrderGrabRecord;
+use App\Enums\OrderRecordStatus;
 use Illuminate\Support\Facades\DB;
+use App\Enums\TechnicianAuthStatus;
 use Illuminate\Support\Facades\Log;
+use App\Enums\OrderGrabRecordStatus;
+use App\Services\SettingItemService;
+use App\Enums\TechnicianLocationType;
+use Illuminate\Support\Facades\Cache;
 use Illuminate\Support\Facades\Redis;
 
 class OrderService
@@ -83,7 +83,6 @@ class OrderService
                     'items' => $items,
                     'total' => $paginator->total(),
                 ];
-
             } catch (\Exception $e) {
                 Log::error('获取技师订单列表失败', [
                     'user_id' => $userId,
@@ -141,7 +140,6 @@ class OrderService
                 'page',
                 $params['page'] ?? 1
             );
-
         } catch (\Exception $e) {
             Log::error('获取可抢订单列表失败', [
                 'user_id' => $userId,
@@ -159,9 +157,9 @@ class OrderService
     private function validateCoach(MemberUser $user): array
     {
         $coach = $user->coach;
-        abort_if(! $coach, 404, '技师��存在');
+        abort_if(! $coach, 404, '技师存在');
         abort_if(! $coach->info, 404, '技师信息不存在');
-        abort_if($coach->info->state != TechnicianStatus::ACTIVE->value, 404, '技师状异常');
+        abort_if($coach->info->state != TechnicianStatus::ACTIVE->value, 404, '技师状异常');
         abort_if($coach->real->state != TechnicianAuthStatus::PASSED->value, 404, '技师实名认证未通过');
         abort_if($coach->qual->state != TechnicianAuthStatus::PASSED->value, 404, '技师资质认证未通过');
 
@@ -321,7 +319,7 @@ class OrderService
 
         $order->project->traffic_fee = round($trafficFee, 2);
 
-        // ��程收费
+        // 程收费
         if ($coachProject->is_round_trip) {
             $order->project->traffic_fee *= 2;
         }
@@ -361,7 +359,7 @@ class OrderService
                 // 验证订单状态
                 abort_if($order->state !== OrderStatus::CREATED->value, 400, '订单状态异常,无法抢单');
 
-                // 验���订单类型
+                // 验订单类型
                 abort_if($order->type !== OrderType::GRAB->value, 400, '该订单不是抢单类型');
 
                 // 检查技师是否已参与抢单
@@ -374,8 +372,8 @@ class OrderService
                 // 通过Redis GEO计算订单与技师的距离
                 $distance = Redis::geodist(
                     'order_locations',
-                    'order:'.$order->id,
-                    $location->longitude.','.$location->latitude,
+                    'order:' . $order->id,
+                    $location->longitude . ',' . $location->latitude,
                     'km'
                 ) ?? PHP_FLOAT_MAX;
                 abort_if($distance > self::MAX_DISTANCE, 400, '订单超出服务范围');
@@ -407,7 +405,6 @@ class OrderService
                     'message' => '已参与抢单',
                     'order_id' => $orderId,
                 ];
-
             } catch (\Exception $e) {
                 Log::error('技师参与抢单失败', [
                     'user_id' => $userId,
@@ -466,11 +463,10 @@ class OrderService
                 ]);
 
                 return [
-                    'message' => '��单成功',
+                    'message' => '单成功',
                     'order_id' => $orderId,
                     'order_no' => $order->order_no,
                 ];
-
             } catch (\Exception $e) {
                 Log::error('技师接单失败', [
                     'user_id' => $userId,
@@ -567,7 +563,6 @@ class OrderService
                     'reject_count' => $rejectCount + 1,
                     'max_reject_count' => 5,
                 ];
-
             } catch (\Exception $e) {
                 Log::error('技师拒单失败', [
                     'user_id' => $userId,
@@ -697,7 +692,7 @@ class OrderService
                         'coach_locations',
                         $order->longitude,
                         $order->latitude,
-                        $coach->id.'_'.TechnicianLocationType::CURRENT->value
+                        $coach->id . '_' . TechnicianLocationType::CURRENT->value
                     );
                 } catch (\Exception $e) {
                     Log::error('更新技师位置失败', [
@@ -775,7 +770,7 @@ class OrderService
                 $now = now();
 
                 // 更新订单状态为服务中
-                $order->state = OrderStatus::SERVING->value;
+                $order->state = OrderStatus::SERVICING->value;
                 $order->save();
 
                 // 记录订单状态变更日志
@@ -812,7 +807,6 @@ class OrderService
                         'service_start_time' => $now,
                     ],
                 ];
-
             } catch (\Exception $e) {
                 Log::error('开始服务失败', [
                     'user_id' => $userId,
@@ -852,7 +846,7 @@ class OrderService
         abort_if($now - $qrTimestamp > 300, 400, '二维码已过期');
 
         // 验证签名
-        $correctSign = md5("order_{$order->id}_{$timestamp}_".config('app.key'));
+        $correctSign = md5("order_{$order->id}_{$timestamp}_" . config('app.key'));
         abort_if($sign !== $correctSign, 400, '二维码签名错误');
     }
 
@@ -914,7 +908,6 @@ class OrderService
                         'leave_time' => now(),
                     ],
                 ];
-
             } catch (\Exception $e) {
                 Log::error('技师撤离失败', [
                     'user_id' => $userId,
@@ -975,7 +968,7 @@ class OrderService
         try {
             Redis::zrem(
                 'coach_locations',
-                $coach->id.'_'.TechnicianLocationType::CURRENT->value
+                $coach->id . '_' . TechnicianLocationType::CURRENT->value
             );
         } catch (\Exception $e) {
             Log::error('删除技师位置失败', [
@@ -1044,7 +1037,7 @@ class OrderService
                 // 检查服务距离是否存在,并且是否大于0
                 if (isset($data['distance']) && $data['distance'] > 0) {
                     // 从全局配置中验证服务距离的合理范围
-                    abort_if($data['distance'] > $distanceSettingItem->max_value, 422, '服务距离不能超过'.$distanceSettingItem->max_value.'公里');
+                    abort_if($data['distance'] > $distanceSettingItem->max_value, 422, '服务距离不能超过' . $distanceSettingItem->max_value . '公里');
 
                     // 更新技师服务距离配置
                     $coach->settingValues()->updateOrCreate(
@@ -1066,7 +1059,6 @@ class OrderService
                     'coach_id' => $coach->id,
                     'settings' => $data,
                 ];
-
             } catch (\Exception $e) {
                 Log::error('订单设置更新失败', [
                     'user_id' => $userId,
@@ -1079,4 +1071,43 @@ class OrderService
             }
         });
     }
+
+    /**
+     * 获取订单设置
+     *
+     * 业务流程:
+     * 1. 获取技师的订单设置
+     * 2. 获取系统配置的限制值
+     * 3. 返回设置信息
+     *
+     * @param CoachUser $coach 技师对象
+     * @return array 返回设置信息,包含:
+     *        - distance: float 当前服务距离
+     *        - distance_max: float 最大服务距离
+     *        - distance_min: float 最小服务距离
+     */
+    public function getOrderSettings(CoachUser $coach): array
+    {
+        // 获取订单配置分组
+        $settingGroup = SettingGroup::where('code', 'order')->first();
+        abort_if(!$settingGroup, 404, '订单配置分组不存在');
+
+        // 获取距离配置项
+        $distanceSettingItem = $settingGroup->items()
+            ->where('code', 'distance')
+            ->first();
+        abort_if(!$distanceSettingItem, 404, '距离配置项不存在');
+
+        // 获取技师的距离设置
+        $distanceSetting = $coach->settingValues()
+            ->where('item_id', $distanceSettingItem->id)
+            ->first();
+
+        // 返回设置信息
+        return [
+            'distance' => (float)($distanceSetting?->value ?? $distanceSettingItem->default_value),  // 当前服务距离
+            'distance_max' => (float)$distanceSettingItem->max_value,  // 最大服务距离限制
+            'distance_min' => (float)$distanceSettingItem->min_value,  // 最小服务距离限制
+        ];
+    }
 }

+ 3 - 0
routes/api.php

@@ -132,6 +132,7 @@ Route::prefix('client')->group(function () {
                 ->name('assign-coach');
             // 生成订单核销码
             Route::get('{id}/code', [OrderController::class, 'generateCode']);
+
         });
 
         // 团队管理路由
@@ -235,6 +236,8 @@ Route::middleware(['auth:sanctum', 'coach'])->prefix('coach')->group(function ()
             ->name('coach.orders.leave')
             ->where('order_id', '[0-9]+');
         Route::post('settings', [CoachOrderController::class, 'setOrder'])->name('coach.orders.settings'); // 订单设置
+        // 获取订单设置
+        Route::get('settings', [CoachOrderController::class, 'getOrderSettings'])->name('coach.orders.get-settings');
     });
 
     // 项目相关路由