Преглед изворни кода

fix: :bug: fix(ajustes) Foi ajustado a questão do script de invalidacao de agendamentos

Foi implementado um script de invalidação automática de agendamentos, responsável por identificar serviços com a data ou horário já expirados e atualizar seu status para cancelado. A rotina foi configurada para execução automática por meio de Job, Queue e Scheduler.

origin: bug-interno
kayo henrique пре 1 дан
родитељ
комит
fb3467783e
3 измењених фајлова са 202 додато и 141 уклоњено
  1. 47 0
      app/Jobs/InvalidateExpiredSchedules.php
  2. 151 141
      app/Services/DashboardService.php
  3. 4 0
      routes/console.php

+ 47 - 0
app/Jobs/InvalidateExpiredSchedules.php

@@ -0,0 +1,47 @@
+<?php
+
+namespace App\Jobs;
+
+use App\Models\Schedule;
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Foundation\Bus\Dispatchable;
+use Illuminate\Queue\InteractsWithQueue;
+use Illuminate\Queue\SerializesModels;
+
+class InvalidateExpiredSchedules implements ShouldQueue
+{
+    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+
+    public function handle(): void
+    {
+        $today = today();
+        $now = now();
+
+        // Agendamentos aceitos cuja data já passou.
+        Schedule::query()
+            ->where('status', 'accepted')
+            ->whereDate('date', '<', $today)
+            ->update([
+                'status' => 'cancelled',
+            ]);
+
+        // Agendamentos pendentes cuja data já passou.
+        Schedule::query()
+            ->where('status', 'pending')
+            ->whereDate('date', '<', $today)
+            ->update([
+                'status' => 'cancelled',
+            ]);
+
+        // Agendamentos pendentes de hoje cujo horário já terminou.
+        Schedule::query()
+            ->where('status', 'pending')
+            ->whereDate('date', $today)
+            ->whereNotNull('end_time')
+            ->whereRaw("CAST(end_time AS time) < ?", [$now->format('H:i:s')])
+            ->update([
+                'status' => 'cancelled',
+            ]);
+    }
+}

+ 151 - 141
app/Services/DashboardService.php

@@ -94,7 +94,7 @@ class DashboardService
                 'schedules.address_id',
                 'custom_schedules.address_type as custom_address_type',
 
-                    DB::raw("
+                DB::raw("
                 (
                     SELECT spi.service_package_id
                     FROM service_package_items spi
@@ -103,7 +103,7 @@ class DashboardService
                 ) AS service_package_id
             "),
 
-                    DB::raw("
+                DB::raw("
                 (
                     SELECT COUNT(*)
                     FROM service_package_items spi_count
@@ -118,10 +118,10 @@ class DashboardService
                     )
                 ) AS service_package_items_count
             "),
-                )
-                ->orderBy('schedules.date', 'asc')
-                ->limit(5)
-                ->get();
+            )
+            ->orderBy('schedules.date', 'asc')
+            ->limit(5)
+            ->get();
 
         $nextSchedules->each(function ($item) {
             $item->gender_label = GenderEnum::labelFor($item->gender);
@@ -135,25 +135,25 @@ class DashboardService
         $lastDoneSchedules = Schedule::joinSub($latestPerProvider, 'latest', function ($join) {
             $join->on('schedules.id', '=', 'latest.max_id');
         })
-                ->leftJoin('providers', 'providers.id', '=', 'schedules.provider_id')
-                ->leftJoin('users as provider_user', 'provider_user.id', '=', 'providers.user_id')
-                ->leftJoinSub(
-                    Address::preferredForProvider(),
-                    'provider_address',
-                    fn($join) =>
-                    $join->on('provider_address.source_id', '=', 'providers.id')
-                        ->where('provider_address.rn', 1)
-                )
-                ->select(
-                    'schedules.id',
-                    'schedules.provider_id',
-                    'provider_user.name as provider_name',
-                    'providers.gender',
-                    'provider_address.district as provider_district',
-                )
-                ->orderBy('schedules.date', 'desc')
-                ->limit(5)
-                ->get();
+            ->leftJoin('providers', 'providers.id', '=', 'schedules.provider_id')
+            ->leftJoin('users as provider_user', 'provider_user.id', '=', 'providers.user_id')
+            ->leftJoinSub(
+                Address::preferredForProvider(),
+                'provider_address',
+                fn($join) =>
+                $join->on('provider_address.source_id', '=', 'providers.id')
+                    ->where('provider_address.rn', 1)
+            )
+            ->select(
+                'schedules.id',
+                'schedules.provider_id',
+                'provider_user.name as provider_name',
+                'providers.gender',
+                'provider_address.district as provider_district',
+            )
+            ->orderBy('schedules.date', 'desc')
+            ->limit(5)
+            ->get();
 
         $lastDoneSchedules->each(function ($item) {
             $item->gender_label = GenderEnum::labelFor($item->gender);
@@ -207,7 +207,7 @@ class DashboardService
             data_get($clientCoordinates, 'longitude'),
         );
 
-         $providerAddressLatestSubquery = DB::raw("
+        $providerAddressLatestSubquery = DB::raw("
             (
                 SELECT DISTINCT ON (source_id)
                     *
@@ -260,7 +260,7 @@ class DashboardService
                 'providers.daily_price_4h',
                 'providers.daily_price_2h',
 
-                    DB::raw("
+                DB::raw("
                 (
                     SELECT COUNT(*)
                     FROM reviews
@@ -271,10 +271,10 @@ class DashboardService
                 ) AS total_reviews
             "),
 
-                    $providersCloseDistanceSelect,
-                )
-                ->orderByRaw('distance_km ASC NULLS LAST')
-                ->get();
+                $providersCloseDistanceSelect,
+            )
+            ->orderByRaw('distance_km ASC NULLS LAST')
+            ->get();
 
         $this->zipCodeCoordinatesService->preload(
             $providersClose->whereNull('distance_km')->pluck('provider_zip_code')
@@ -328,25 +328,25 @@ class DashboardService
         $pendingSchedules = Schedule::with([
             'address:district,address,number,source_id,source,id,address_type',
         ])
-                ->where('schedules.client_id', $cliente->id)
-                ->whereIn('schedules.status', ['pending', 'accepted'])
-                ->where('schedules.schedule_type', 'default')
-                ->whereDate('schedules.date', '>=', now()->toDateString())
-                ->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',
-                    'providers.gender',
-                    'schedules.date',
-                    'schedules.address_id',
-                    'schedules.status',
-                    'schedules.total_amount',
-                    'schedules.start_time',
-                    'schedules.end_time',
-
-                    DB::raw("
+            ->where('schedules.client_id', $cliente->id)
+            ->whereIn('schedules.status', ['pending', 'accepted'])
+            ->where('schedules.schedule_type', 'default')
+            ->whereDate('schedules.date', '>=', now()->toDateString())
+            ->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',
+                'providers.gender',
+                'schedules.date',
+                'schedules.address_id',
+                'schedules.status',
+                'schedules.total_amount',
+                'schedules.start_time',
+                'schedules.end_time',
+
+                DB::raw("
                 CASE
                     WHEN (NOW() - schedules.created_at) < INTERVAL '1 hour' THEN
                         CONCAT(
@@ -366,7 +366,7 @@ class DashboardService
                 END AS time_since_request
             "),
 
-                    DB::raw("
+                DB::raw("
                 (
                     SELECT spi.service_package_id
                     FROM service_package_items spi
@@ -375,7 +375,7 @@ class DashboardService
                 ) AS service_package_id
             "),
 
-                    DB::raw("
+                DB::raw("
                 (
                     SELECT COUNT(*)
                     FROM service_package_items spi_count
@@ -390,9 +390,9 @@ class DashboardService
                     )
                 ) AS service_package_items_count
             "),
-                )
-                ->orderBy('schedules.date', 'asc')
-                ->get();
+            )
+            ->orderBy('schedules.date', 'asc')
+            ->get();
 
         $pendingSchedules->each(function ($item) {
             $item->gender_label = GenderEnum::labelFor($item->gender);
@@ -503,28 +503,28 @@ class DashboardService
         $todaySchedules = Schedule::with([
             'address:district,address,number,source_id,source,id,address_type',
         ])
-                ->where('schedules.client_id', $cliente->id)
-                ->whereIn('schedules.status', ['accepted', 'paid', 'started', 'cancelled', 'finished'])
-                ->whereDate('schedules.date', now()->toDateString())
-                ->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',
-                    'providers.gender',
-                    'schedules.date',
-                    'schedules.start_time',
-                    'schedules.end_time',
-                    'schedules.total_amount',
-                    'schedules.period_type',
-                    'schedules.schedule_type',
-                    'schedules.address_id',
-                    'schedules.status',
-                    'schedules.code_verified',
-                    'schedules.code',
-
-                    DB::raw("
+            ->where('schedules.client_id', $cliente->id)
+            ->whereIn('schedules.status', ['accepted', 'paid', 'started', 'cancelled', 'finished'])
+            ->whereDate('schedules.date', now()->toDateString())
+            ->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',
+                'providers.gender',
+                'schedules.date',
+                'schedules.start_time',
+                'schedules.end_time',
+                'schedules.total_amount',
+                'schedules.period_type',
+                'schedules.schedule_type',
+                'schedules.address_id',
+                'schedules.status',
+                'schedules.code_verified',
+                'schedules.code',
+
+                DB::raw("
                 (
                     SELECT spi.service_package_id
                     FROM service_package_items spi
@@ -533,7 +533,7 @@ class DashboardService
                 ) AS service_package_id
             "),
 
-                    DB::raw("
+                DB::raw("
                 (
                     SELECT COUNT(*)
                     FROM service_package_items spi_count
@@ -549,7 +549,7 @@ class DashboardService
                 ) AS service_package_items_count
             "),
 
-                    DB::raw("
+                DB::raw("
                 EXISTS (
                     SELECT 1
                     FROM reviews
@@ -559,14 +559,14 @@ class DashboardService
                     AND reviews.deleted_at IS NULL
                 ) AS client_reviewed
             "),
-                )
-                ->orderBy('schedules.start_time', 'asc')
-                ->get()
-                ->map(function ($item) {
+            )
+            ->orderBy('schedules.start_time', 'asc')
+            ->get()
+            ->map(function ($item) {
                 $item->gender_label = GenderEnum::labelFor($item->gender);
 
-                    return $item;
-                });
+                return $item;
+            });
 
         $providerCollections = collect([
             $nextSchedules,
@@ -678,10 +678,20 @@ class DashboardService
             ];
         }
 
-        $priceSuggestedAvg = Provider::where('user_id', '!=', $user->id)
-            ->whereNotNull('daily_price_8h')
-            ->pluck('daily_price_8h')
-            ->avg();
+        $providerCityId = $address?->city_id;
+
+        $priceSuggestedAvg = Provider::query()
+            ->where('providers.user_id', '!=', $user->id)
+            ->whereNotNull('providers.daily_price_8h')
+            ->whereExists(function ($query) use ($providerCityId) {
+                $query->select(DB::raw(1))
+                    ->from('addresses')
+                    ->whereColumn('addresses.source_id', 'providers.id')
+                    ->where('addresses.source', 'provider')
+                    ->whereNull('addresses.deleted_at')
+                    ->where('addresses.city_id', $providerCityId);
+            })
+            ->avg('providers.daily_price_8h');
 
         $priceActual = $provider->daily_price_8h;
 
@@ -694,32 +704,32 @@ class DashboardService
             'address:district,source_id,source,id,zip_code,latitude,longitude',
             'customSchedule.specialities',
         ])
-                ->where('schedules.provider_id', $provider->id)
-                ->where('schedules.status', 'pending')
-                ->leftJoin('clients', 'clients.id', '=', 'schedules.client_id')
-                ->leftJoin('users as client_user', 'client_user.id', '=', 'clients.user_id')
-                ->leftJoin('custom_schedules', 'custom_schedules.schedule_id', '=', 'schedules.id')
-                ->select(
-                    'schedules.id',
-                    'schedules.client_id',
-                    'client_user.name as client_name',
-                    'clients.average_rating',
-                    'schedules.date',
-
-                    DB::raw("
+            ->where('schedules.provider_id', $provider->id)
+            ->where('schedules.status', 'pending')
+            ->leftJoin('clients', 'clients.id', '=', 'schedules.client_id')
+            ->leftJoin('users as client_user', 'client_user.id', '=', 'clients.user_id')
+            ->leftJoin('custom_schedules', 'custom_schedules.schedule_id', '=', 'schedules.id')
+            ->select(
+                'schedules.id',
+                'schedules.client_id',
+                'client_user.name as client_name',
+                'clients.average_rating',
+                'schedules.date',
+
+                DB::raw("
                 TO_CHAR(schedules.date, 'DD/MM/YYYY') AS formatted_date
             "),
 
-                    'schedules.start_time',
-                    'schedules.end_time',
-                    'schedules.total_amount',
-                    'schedules.period_type',
-                    'schedules.schedule_type',
-                    'schedules.address_id',
-                    'schedules.status',
-                    'custom_schedules.offers_meal',
+                'schedules.start_time',
+                'schedules.end_time',
+                'schedules.total_amount',
+                'schedules.period_type',
+                'schedules.schedule_type',
+                'schedules.address_id',
+                'schedules.status',
+                'custom_schedules.offers_meal',
 
-                    DB::raw("
+                DB::raw("
                 CASE
                     WHEN (NOW() - schedules.created_at) < INTERVAL '1 day' THEN
                         CONCAT(
@@ -742,7 +752,7 @@ class DashboardService
                 END AS time_since_request
             "),
 
-                    DB::raw("
+                DB::raw("
                 (
                     SELECT service_package_items.service_package_id
                     FROM service_package_items
@@ -753,8 +763,8 @@ class DashboardService
             )
             ->orderBy('schedules.date', 'asc')
             ->get()
-        ->append('specialities')
-        ->makeHidden('customSchedule');
+            ->append('specialities')
+            ->makeHidden('customSchedule');
 
         $solicitations->each(function ($solicitation) use ($address) {
             $solicitation->distance_km = $this->zipCodeCoordinatesService->calculateDistance(
@@ -770,29 +780,29 @@ class DashboardService
         $todayServices = Schedule::with([
             'address:district,address,number,source_id,source,id',
         ])
-                ->where('schedules.provider_id', $provider->id)
-                ->whereIn('schedules.status', ['accepted', 'paid', 'started', 'finished'])
-                ->whereDate('schedules.date', now()->toDateString())
-                ->leftJoin('clients', 'clients.id', '=', 'schedules.client_id')
-                ->leftJoin('users as client_user', 'client_user.id', '=', 'clients.user_id')
-                ->leftJoin('custom_schedules', 'custom_schedules.schedule_id', '=', 'schedules.id')
-                ->select(
-                    'schedules.id',
-                    'schedules.client_id',
-                    'client_user.name as client_name',
-                    'schedules.date',
-                    'schedules.start_time',
-                    'schedules.end_time',
-                    'schedules.total_amount',
-                    'schedules.period_type',
-                    'schedules.address_id',
-                    'schedules.schedule_type',
-                    'schedules.status',
-                    'schedules.code_verified',
-                    'schedules.code',
-                    'custom_schedules.offers_meal',
-
-                    DB::raw("
+            ->where('schedules.provider_id', $provider->id)
+            ->whereIn('schedules.status', ['accepted', 'paid', 'started', 'finished'])
+            ->whereDate('schedules.date', now()->toDateString())
+            ->leftJoin('clients', 'clients.id', '=', 'schedules.client_id')
+            ->leftJoin('users as client_user', 'client_user.id', '=', 'clients.user_id')
+            ->leftJoin('custom_schedules', 'custom_schedules.schedule_id', '=', 'schedules.id')
+            ->select(
+                'schedules.id',
+                'schedules.client_id',
+                'client_user.name as client_name',
+                'schedules.date',
+                'schedules.start_time',
+                'schedules.end_time',
+                'schedules.total_amount',
+                'schedules.period_type',
+                'schedules.address_id',
+                'schedules.schedule_type',
+                'schedules.status',
+                'schedules.code_verified',
+                'schedules.code',
+                'custom_schedules.offers_meal',
+
+                DB::raw("
                 EXISTS (
                     SELECT 1
                     FROM reviews
@@ -803,7 +813,7 @@ class DashboardService
                 ) AS provider_reviewed
             "),
 
-                    DB::raw("
+                DB::raw("
                 (
                     SELECT service_package_items.service_package_id
                     FROM service_package_items
@@ -811,9 +821,9 @@ class DashboardService
                     LIMIT 1
                 ) AS service_package_id
             "),
-                )
-                ->orderBy('schedules.start_time', 'asc')
-                ->get();
+            )
+            ->orderBy('schedules.start_time', 'asc')
+            ->get();
 
 
         $pendingConfirmation = Schedule::with(

+ 4 - 0
routes/console.php

@@ -9,6 +9,8 @@ use App\Services\Pagarme\PagarmeTransferService;
 use App\Services\ProviderWithdrawalService;
 use Illuminate\Foundation\Inspiring;
 use Illuminate\Support\Facades\Artisan;
+use App\Jobs\InvalidateExpiredSchedules;
+use Illuminate\Support\Facades\Schedule;
 
 Artisan::command('inspire', function () {
     $this->comment(Inspiring::quote());
@@ -72,3 +74,5 @@ Artisan::command('pagarme:recipient-balance {recipient_id} {--skip-local}', func
 
     $this->line(json_encode($pagarmeTransfer->getRecipientBalance($recipientId), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
 })->purpose('Consult Pagar.me recipient balance and compare it with local withdrawal balance');
+
+Schedule::job(new InvalidateExpiredSchedules)->daily();