ソースを参照

feat: :sparkles: feat (agendamentos default) fluxo de gerar agendamentos default

foi criado o fluxo onde o cliente consegue solicitar um agendamento para o prestador

fase:dev | origin: escopo
Gustavo Zanatta 3 週間 前
コミット
8893c8a903

+ 0 - 11
app/Http/Controllers/DashboardController.php

@@ -26,17 +26,6 @@ class DashboardController extends Controller
     }
   }
 
-  public function buscaPrestadores(Request $request): JsonResponse
-  {
-    try {
-      $dados = $this->service->buscaPrestadores($request->query('name'), $request->query('date'));
-      return $this->successResponse(payload: $dados);
-    } catch (\Exception $e) {
-      Log::error("Erro ao buscar prestadores: " . $e->getMessage());
-      return $this->errorResponse(message: __("messages.error_fetching_data"), code: 500);
-    }
-  }
-
   public function dadosDashboardPrestador(): JsonResponse
   {
     try {

+ 24 - 0
app/Http/Controllers/SearchController.php

@@ -0,0 +1,24 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Services\SearchService;
+use Illuminate\Http\JsonResponse;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Log;
+
+class SearchController extends Controller
+{
+  public function __construct(private readonly SearchService $service) {}
+
+  public function buscaPrestadores(Request $request): JsonResponse
+  {
+    try {
+      $dados = $this->service->buscaPrestadores($request->query('name'), $request->query('date'));
+      return $this->successResponse(payload: $dados);
+    } catch (\Exception $e) {
+      Log::error("Erro ao buscar prestadores: " . $e->getMessage());
+      return $this->errorResponse(message: __("messages.error_fetching_data"), code: 500);
+    }
+  }
+}

+ 2 - 0
app/Http/Requests/ScheduleRequest.php

@@ -26,6 +26,8 @@ class ScheduleRequest extends FormRequest
             'schedules.*.start_time' => 'required|date_format:H:i',
             'schedules.*.end_time' => 'required|date_format:H:i|after:schedules.*.start_time',
             'schedules.*.total_amount' => 'required|numeric|min:0',
+            'schedules.*.offers_meal' => 'nullable|boolean',
+            'offers_meal' => 'sometimes|nullable|boolean',
             'period_type' => 'sometimes|required|in:2,4,6,8',
             'schedule_type' => 'sometimes|in:default,custom',
             'start_time' => 'sometimes|required|date_format:H:i',

+ 1 - 0
app/Http/Resources/DashboardClienteResource.php

@@ -17,6 +17,7 @@ class DashboardClienteResource extends JsonResource
     return [
       'headerBar' => $this['headerBar'],
       'summaryInfos' => $this['summaryInfos'],
+      'pendingSchedules' => $this['pendingSchedules'],
       'nextSchedules' => $this['nextSchedules'],
       'lastDoneSchedules' => $this['lastDoneSchedules'],
       'favoriteProviders' => $this['favoriteProviders'],

+ 1 - 0
app/Http/Resources/ScheduleResource.php

@@ -28,6 +28,7 @@ class ScheduleResource extends JsonResource
             'schedule_type' => $this->schedule_type,
             'start_time' => $this->start_time,
             'end_time' => $this->end_time,
+            'offers_meal' => $this->offers_meal,
             'status' => $this->status,
             'total_amount' => $this->total_amount,
             'code' => $this->code,

+ 2 - 0
app/Models/Schedule.php

@@ -23,12 +23,14 @@ class Schedule extends Model
         'total_amount',
         'code',
         'code_verified',
+        'offers_meal',
     ];
 
     protected $casts = [
         'date' => 'date',
         'code_verified' => 'boolean',
         'total_amount' => 'decimal:2',
+        'offers_meal' => 'boolean',
     ];
 
     public function client()

+ 26 - 66
app/Services/DashboardService.php

@@ -138,9 +138,35 @@ class DashboardService
       )
       ->get();
 
+    $pendingSchedules = Schedule::with('address:district,address,number,source_id,source,id')
+      ->where('schedules.client_id', $cliente->id)
+      ->where('schedules.status', 'pending')
+      ->where('schedules.schedule_type', 'default')
+      ->leftJoin('providers', 'providers.id', '=', 'schedules.provider_id')
+      ->leftJoin('users as provider_user', 'provider_user.id', '=', 'providers.user_id')
+      ->select(
+        'schedules.id',
+        'schedules.provider_id',
+        'provider_user.name as provider_name',
+        'schedules.date',
+        'schedules.start_time',
+        'schedules.end_time',
+        'schedules.period_type',
+        'schedules.address_id',
+        'schedules.status',
+        DB::raw("CASE
+          WHEN (now() - schedules.created_at) < INTERVAL '1 hour' THEN CONCAT(ROUND(EXTRACT(EPOCH FROM (now() - schedules.created_at)) / 60), 'min')
+          WHEN (now() - schedules.created_at) < INTERVAL '1 day' THEN CONCAT(ROUND(EXTRACT(EPOCH FROM (now() - schedules.created_at)) / 3600), 'h')
+          ELSE CONCAT(ROUND(EXTRACT(EPOCH FROM (now() - schedules.created_at)) / 86400), 'd')
+        END as time_since_request"),
+      )
+      ->orderBy('schedules.date', 'asc')
+      ->get();
+
     return [
       'headerBar'        => $headerBar,
       'summaryInfos'     => $summaryInfos,
+      'pendingSchedules' => $pendingSchedules,
       'nextSchedules'    => $nextSchedules,
       'lastDoneSchedules' => $lastDoneSchedules,
       'favoriteProviders' => $favoriteProviders,
@@ -148,72 +174,6 @@ class DashboardService
     ];
   }
 
-  public function buscaPrestadores(?string $name = null, ?string $date = null): array
-  {
-    $user    = Auth::user();
-    $cliente = Client::where('user_id', $user->id)->first();
-
-    $blockedProviderIds       = ScheduleBusinessRules::getBlockedProviderIdsForClient($cliente->id);
-    $providersWithWorkingDays = ScheduleBusinessRules::getProviderIdsWithWorkingDays();
-
-    $clientPrimaryAddress = Address::where('source', 'client')
-      ->where('source_id', $cliente->id)
-      ->orderBy('is_primary', 'desc')
-      ->first();
-
-    return Provider::leftJoin('users as provider_user', 'provider_user.id', '=', 'providers.user_id')
-      ->leftJoin(DB::raw("
-        (
-          SELECT DISTINCT ON (source_id)
-            *
-          FROM addresses
-          WHERE source = 'provider'
-          ORDER BY source_id, is_primary DESC
-        ) as provider_address
-      "), 'provider_address.source_id', '=', 'providers.id')
-      ->whereNotNull('provider_address.id')
-      ->where('provider_address.city_id', $clientPrimaryAddress?->city_id)
-      ->whereNotIn('providers.id', $blockedProviderIds)
-      ->whereIn('providers.id', $providersWithWorkingDays)
-      ->whereNotNull('providers.daily_price_8h')
-      ->whereNotNull('providers.daily_price_6h')
-      ->whereNotNull('providers.daily_price_4h')
-      ->whereNotNull('providers.daily_price_2h')
-      ->when($name, fn($q) => $q->where('provider_user.name', 'ILIKE', "%{$name}%"))
-      ->select(
-        'providers.id as provider_id',
-        'provider_user.name as provider_name',
-        'provider_address.district',
-        'providers.average_rating',
-        'providers.total_services',
-        'providers.daily_price_8h',
-        'providers.daily_price_6h',
-        'providers.daily_price_4h',
-        'providers.daily_price_2h',
-        'providers.created_at',
-        DB::raw("(
-          SELECT COUNT(*)
-          FROM reviews
-          LEFT JOIN schedules ON schedules.id = reviews.schedule_id
-          WHERE reviews.origin = 'provider'
-          AND schedules.provider_id = providers.id
-        ) as total_reviews"),
-      )
-      ->orderBy('providers.average_rating', 'desc')
-      ->get()
-      ->when(
-        $date,
-        fn($collection) => $collection->whereIn(
-          'provider_id',
-          ScheduleBusinessRules::getAvailableProviderIdsForDate(
-            $date,
-            $collection->pluck('provider_id')
-          )->toArray()
-        )->values()
-      )
-      ->toArray();
-  }
-
   public function dadosDashboardPrestador(): array
   {
     $user = Auth::user();

+ 8 - 6
app/Services/ScheduleService.php

@@ -40,19 +40,21 @@ class ScheduleService
 
   public function createSingleOrMultiple(array $baseData, array $schedules)
   {
-    $createdSchedules = [];
-    foreach ($schedules as $schedule) {
-      try {
+    try {
+      DB::beginTransaction();
+      $createdSchedules = [];
+      foreach ($schedules as $schedule) {
         $datasMerged = array_merge($baseData, $schedule);
         $this->validateProviderAvailability($datasMerged, null);
         $scheduleData = array_merge($datasMerged, [
           'code' => str_pad(random_int(0, 9999), 4, '0', STR_PAD_LEFT),
         ]);
         $createdSchedules[] = Schedule::create($scheduleData);
-
-      } catch (\Exception $e) {
-        throw new \Exception(__($e->getMessage()));
       }
+      DB::commit();
+    } catch (\Exception $e) {
+      DB::rollBack();
+      throw new \Exception(__($e->getMessage()));
     }
 
     return $createdSchedules;

+ 87 - 0
app/Services/SearchService.php

@@ -0,0 +1,87 @@
+<?php
+
+namespace App\Services;
+
+use App\Models\Address;
+use App\Models\Client;
+use App\Models\ClientFavoriteProvider;
+use App\Models\Provider;
+use App\Models\Review;
+use App\Models\Schedule;
+use App\Rules\ScheduleBusinessRules;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Log;
+
+class SearchService
+{
+  public function __construct() {}
+
+
+  public function buscaPrestadores(?string $name = null, ?string $date = null): array
+  {
+    $user    = Auth::user();
+    $cliente = Client::where('user_id', $user->id)->first();
+
+    $blockedProviderIds       = ScheduleBusinessRules::getBlockedProviderIdsForClient($cliente->id);
+    $providersWithWorkingDays = ScheduleBusinessRules::getProviderIdsWithWorkingDays();
+
+    $clientPrimaryAddress = Address::where('source', 'client')
+      ->where('source_id', $cliente->id)
+      ->orderBy('is_primary', 'desc')
+      ->first();
+
+    return Provider::leftJoin('users as provider_user', 'provider_user.id', '=', 'providers.user_id')
+      ->leftJoin(DB::raw("
+        (
+          SELECT DISTINCT ON (source_id)
+            *
+          FROM addresses
+          WHERE source = 'provider'
+          ORDER BY source_id, is_primary DESC
+        ) as provider_address
+      "), 'provider_address.source_id', '=', 'providers.id')
+      ->whereNotNull('provider_address.id')
+      ->where('provider_address.city_id', $clientPrimaryAddress?->city_id)
+      ->whereNotIn('providers.id', $blockedProviderIds)
+      ->whereIn('providers.id', $providersWithWorkingDays)
+      ->whereNotNull('providers.daily_price_8h')
+      ->whereNotNull('providers.daily_price_6h')
+      ->whereNotNull('providers.daily_price_4h')
+      ->whereNotNull('providers.daily_price_2h')
+      ->when($name, fn($q) => $q->where('provider_user.name', 'ILIKE', "%{$name}%"))
+      ->select(
+        'providers.id as provider_id',
+        'provider_user.name as provider_name',
+        'provider_address.district',
+        'providers.average_rating',
+        'providers.total_services',
+        'providers.daily_price_8h',
+        'providers.daily_price_6h',
+        'providers.daily_price_4h',
+        'providers.daily_price_2h',
+        'providers.created_at',
+        DB::raw("(
+          SELECT COUNT(*)
+          FROM reviews
+          LEFT JOIN schedules ON schedules.id = reviews.schedule_id
+          WHERE reviews.origin = 'provider'
+          AND schedules.provider_id = providers.id
+        ) as total_reviews"),
+      )
+      ->orderBy('providers.average_rating', 'desc')
+      ->get()
+      ->when(
+        $date,
+        fn($collection) => $collection->whereIn(
+          'provider_id',
+          ScheduleBusinessRules::getAvailableProviderIdsForDate(
+            $date,
+            $collection->pluck('provider_id')
+          )->toArray()
+        )->values()
+      )
+      ->toArray();
+  }
+
+}

+ 28 - 0
database/migrations/2026_04_09_110218_add_offers_meal_to_schedules_table.php

@@ -0,0 +1,28 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+return new class extends Migration
+{
+    /**
+     * Run the migrations.
+     */
+    public function up(): void
+    {
+        Schema::table('schedules', function (Blueprint $table) {
+            $table->boolean('offers_meal')->nullable()->default(null)->after('end_time');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::table('schedules', function (Blueprint $table) {
+            $table->dropColumn('offers_meal');
+        });
+    }
+};

+ 4 - 0
database/seeders/UserTypePermissionSeeder.php

@@ -83,6 +83,10 @@ class UserTypePermissionSeeder extends Seeder
             ['scope' => 'config.provider_payment_method', 'bits' => 271],
             ['scope' => 'config.client_favorite_provider', 'bits' => 271],
             ['scope' => 'config.client_payment_method', 'bits' => 271],
+            ['scope' => 'config.provider_working_day', 'bits' => 271],
+            ['scope' => 'config.provider_blocked_day', 'bits' => 271],
+            ['scope' => 'config.review', 'bits' => 271],
+            ['scope' => 'config.schedule', 'bits' => 271],
           ];
           $this->seedUserTypePermissions($clientPermissions, UserTypeEnum::CLIENT->value);
           break;

+ 1 - 2
routes/authRoutes/dashboard.php

@@ -4,5 +4,4 @@ use App\Http\Controllers\DashboardController;
 use Illuminate\Support\Facades\Route;
 
 Route::get('/dados-dashboard-cliente', [DashboardController::class, 'dadosDashboardCliente'])->middleware('permission:dashboard,view');
-Route::get('/dados-dashboard-prestador', [DashboardController::class, 'dadosDashboardPrestador'])->middleware('permission:dashboard,view');
-Route::get('/prestadores-busca', [DashboardController::class, 'buscaPrestadores'])->middleware('permission:dashboard,view');
+Route::get('/dados-dashboard-prestador', [DashboardController::class, 'dadosDashboardPrestador'])->middleware('permission:dashboard,view');

+ 6 - 0
routes/authRoutes/search.php

@@ -0,0 +1,6 @@
+<?php
+
+use App\Http\Controllers\SearchController;
+use Illuminate\Support\Facades\Route;
+
+Route::get('/prestadores-busca', [SearchController::class, 'buscaPrestadores'])->middleware('permission:dashboard,view');