소스 검색

feat:技师端-开通项目

刘学玺 4 달 전
부모
커밋
72970dcebe
4개의 변경된 파일314개의 추가작업 그리고 5개의 파일을 삭제
  1. 110 0
      app/Http/Controllers/Coach/ProjectController.php
  2. 6 3
      app/Models/CoachProject.php
  3. 189 0
      app/Services/Coach/ProjectService.php
  4. 9 2
      routes/api.php

+ 110 - 0
app/Http/Controllers/Coach/ProjectController.php

@@ -0,0 +1,110 @@
+<?php
+
+namespace App\Http\Controllers\Coach;
+
+use App\Http\Controllers\Controller;
+use App\Services\Coach\ProjectService;
+use App\Traits\ResponseTrait;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
+
+/**
+ * @group 技师端
+ *
+ * 项目管理相关的API接口
+ */
+class ProjectController extends Controller
+{
+    use ResponseTrait;
+
+    protected ProjectService $service;
+
+    public function __construct(ProjectService $service)
+    {
+        $this->service = $service;
+    }
+
+    /**
+     * [项目]获取可开通项目列表
+     *
+     * @description 获取技师可以开通的项目列表
+     *
+     * @authenticated
+     *
+     * @response {
+     *   "data": {
+     *     "items": [
+     *       {
+     *         "id": 1,
+     *         "name": "精油推拿",
+     *         "cover": "http://example.com/cover.jpg",
+     *         "price": "188.00",
+     *         "duration": 60,
+     *         "description": "项目描述",
+     *         "qualification_requirements": "资质要求"
+     *       }
+     *     ],
+     *     "total": 10
+     *   }
+     * }
+     */
+    public function getAvailableProjects()
+    {
+        return $this->success($this->service->getAvailableProjects(Auth::user()->id));
+    }
+
+    /**
+     * [项目]开通项目
+     *
+     * @description 技师开通新的服务项目
+     *
+     * @authenticated
+     *
+     * @bodyParam project_id integer required 项目ID Example: 1
+     *
+     * @response {
+     *   "message": "项目开通成功",
+     *   "project_id": 1,
+     *   "project_name": "精油推拿"
+     * }
+     */
+    public function openProject(Request $request)
+    {
+        $data = $request->validate([
+            'project_id' => 'required|integer|exists:project,id',
+        ]);
+
+        return $this->success($this->service->openProject(Auth::user()->id, $data));
+    }
+
+    /**
+     * [项目]获取已开通项目列表
+     *
+     * @description 获取技师已开通的项目列表
+     *
+     * @authenticated
+     *
+     * @response {
+     *   "data": {
+     *     "items": [
+     *       {
+     *         "id": 1,
+     *         "name": "精油推拿",
+     *         "cover": "http://example.com/cover.jpg",
+     *         "price": "188.00",
+     *         "duration": 60,
+     *         "discount_amount": "10.00",
+     *         "traffic_fee": "20.00",
+     *         "is_round_trip": true,
+     *         "opened_at": "2024-03-21 10:00:00"
+     *       }
+     *     ],
+     *     "total": 5
+     *   }
+     * }
+     */
+    public function getOpenedProjects()
+    {
+        return $this->success($this->service->getOpenedProjects(Auth::user()->id));
+    }
+}

+ 6 - 3
app/Models/CoachProject.php

@@ -10,16 +10,19 @@ use Slowlyo\OwlAdmin\Models\BaseModel as Model;
  */
 class CoachProject extends Model
 {
-	use SoftDeletes;
+    use SoftDeletes;
 
-	protected $table = 'coach_project';
+    protected $table = 'coach_project';
+
+    protected $guarded = [];
 
     /**
      * @Author FelixYin
+     *
      * @description 技师开通项目所属服务项目
      */
     public function basicInfo()
     {
         return $this->belongsTo('App\Models\Project', 'project_id');
     }
-}
+}

+ 189 - 0
app/Services/Coach/ProjectService.php

@@ -0,0 +1,189 @@
+<?php
+
+namespace App\Services\Coach;
+
+use App\Enums\ProjectStatus;
+use App\Models\MemberUser;
+use App\Models\Project;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Log;
+
+class ProjectService
+{
+    /**
+     * 获取可开通的项目列表
+     *
+     * @param  int  $userId  技师用户ID
+     */
+    public function getAvailableProjects(int $userId): array
+    {
+        try {
+            // 加载用户和技师信息
+            $user = MemberUser::with(['coach', 'coach.projects'])->findOrFail($userId);
+            abort_if(! $user->coach, 404, '技师信息不存在');
+
+            // 获取所有可开通的项目
+            $projects = Project::where('state', ProjectStatus::OPEN->value)
+                ->select([
+                    'id',
+                    'title',
+                    'subtitle',
+                    'cover',
+                    'price',
+                    'original_price',
+                    'sales',
+                    'duration',
+                    'project_desc',
+                    'service_desc',
+                    'type',
+                ])
+                ->get();
+
+            // 记录日志
+            Log::info('获取可开通项目列表成功', [
+                'user_id' => $userId,
+                'coach_id' => $user->coach->id,
+                'project_count' => $projects->count(),
+            ]);
+
+            return [
+                'items' => $projects,
+                'total' => $projects->count(),
+            ];
+
+        } catch (\Exception $e) {
+            Log::error('获取可开通项目列表失败', [
+                'user_id' => $userId,
+                'error' => $e->getMessage(),
+                'file' => $e->getFile(),
+                'line' => $e->getLine(),
+            ]);
+            throw $e;
+        }
+    }
+
+    /**
+     * 技师开通项目
+     *
+     * @param  int  $userId  技师用户ID
+     * @param  array  $data  开通项目数据
+     */
+    public function openProject(int $userId, array $data): array
+    {
+        return DB::transaction(function () use ($userId, $data) {
+            try {
+                // 加载用户和技师信息
+                $user = MemberUser::with(['coach', 'coach.projects'])->findOrFail($userId);
+                abort_if(! $user->coach, 404, '技师信息不存在');
+
+                // 验证项目是否存在且状态正常
+                $project = Project::where('id', $data['project_id'])
+                    ->where('state', ProjectStatus::OPEN->value)
+                    ->first();
+                abort_if(! $project, 404, '项目不存在或已下架');
+
+                // 检查是否已开通该项目
+                $existingProject = $user->coach->projects()
+                    ->where('project_id', $data['project_id'])
+                    ->first();
+                abort_if($existingProject, 422, '已开通该项目');
+
+                // 创建技师项目关联
+                $coachProject = $user->coach->projects()->create([
+                    // 项目ID
+                    'project_id' => $data['project_id'],
+                    // 项目状态
+                    'state' => ProjectStatus::OPEN->value,
+                    // 优惠金额
+                    'discount_amount' => 0.00,
+                    // 服务性别(0:不限 1:男 2:女)
+                    'service_gender' => 0,
+                    // 服务距离(公里 0:不限)
+                    'service_distance' => 0,
+                    // 收取路费(0:免费 1:单程 2:双程)
+                    'traffic_fee_type' => 2,
+                    // 路费金额
+                    'traffic_fee' => 0,
+                ]);
+
+                // 记录日志
+                Log::info('技师开通项目成功', [
+                    'user_id' => $userId,
+                    'coach_id' => $user->coach->id,
+                    'project_id' => $data['project_id'],
+                    'project_name' => $project->name,
+                ]);
+
+                return [
+                    'message' => '项目开通成功',
+                    'project_id' => $project->id,
+                    'project_name' => $project->name,
+                ];
+
+            } catch (\Exception $e) {
+                Log::error('技师开通项目失败', [
+                    'user_id' => $userId,
+                    'data' => $data,
+                    'error' => $e->getMessage(),
+                    'file' => $e->getFile(),
+                    'line' => $e->getLine(),
+                ]);
+                throw $e;
+            }
+        });
+    }
+
+    /**
+     * 获取技师已开通的项目列表
+     *
+     * @param  int  $userId  技师用户ID
+     */
+    public function getOpenedProjects(int $userId): array
+    {
+        try {
+            // 加载用户和技师信息
+            $user = MemberUser::with(['coach'])->findOrFail($userId);
+            abort_if(! $user->coach, 404, '技师信息不存在');
+
+            // 获取已开通的项目
+            $projects = $user->coach->projects()
+                ->with('project')
+                ->where('state', ProjectStatus::ACTIVE->value)
+                ->get()
+                ->map(function ($coachProject) {
+                    return [
+                        'id' => $coachProject->project->id,
+                        'name' => $coachProject->project->name,
+                        'cover' => $coachProject->project->cover,
+                        'price' => $coachProject->project->price,
+                        'duration' => $coachProject->project->duration,
+                        'discount_amount' => $coachProject->discount_amount,
+                        'traffic_fee' => $coachProject->traffic_fee,
+                        'is_round_trip' => $coachProject->is_round_trip,
+                        'opened_at' => $coachProject->created_at,
+                    ];
+                });
+
+            // 记录日志
+            Log::info('获取已开通项目列表成功', [
+                'user_id' => $userId,
+                'coach_id' => $user->coach->id,
+                'project_count' => $projects->count(),
+            ]);
+
+            return [
+                'items' => $projects,
+                'total' => $projects->count(),
+            ];
+
+        } catch (\Exception $e) {
+            Log::error('获取已开通项目列表失败', [
+                'user_id' => $userId,
+                'error' => $e->getMessage(),
+                'file' => $e->getFile(),
+                'line' => $e->getLine(),
+            ]);
+            throw $e;
+        }
+    }
+}

+ 9 - 2
routes/api.php

@@ -10,6 +10,7 @@ use App\Http\Controllers\Client\UserAddressController;
 use App\Http\Controllers\Client\UserController;
 use App\Http\Controllers\Client\WalletController;
 use App\Http\Controllers\Coach\OrderController as CoachOrderController;
+use App\Http\Controllers\Coach\ProjectController as CoachProjectController;
 use App\Http\Controllers\EnumController;
 use App\Http\Controllers\ScribeController;
 use Illuminate\Support\Facades\Route;
@@ -140,6 +141,8 @@ Route::middleware(['auth:sanctum', 'verified'])->prefix('coach')->group(function
         // 设置位置信息
         Route::post('location', [App\Http\Controllers\Coach\AccountController::class, 'setLocation'])
             ->name('coach.account.location');
+        // 获取技师位置信息
+        Route::get('location', [\App\Http\Controllers\Coach\AccountController::class, 'getLocation']);
     });
 
     // 订单相关路由
@@ -150,6 +153,10 @@ Route::middleware(['auth:sanctum', 'verified'])->prefix('coach')->group(function
         Route::post('/accept/{order_id}', [CoachOrderController::class, 'acceptOrder']);
     });
 
-    // 获取技师位置信息
-    Route::get('location', [\App\Http\Controllers\Coach\AccountController::class, 'getLocation']);
+    // 项目相关路由
+    Route::prefix('projects')->group(function () {
+        Route::get('/available', [CoachProjectController::class, 'getAvailableProjects']);
+        Route::post('/open', [CoachProjectController::class, 'openProject']);
+        Route::get('/opened', [CoachProjectController::class, 'getOpenedProjects']);
+    });
 });