Преглед на файлове

feat: add gender nos providers + adiciona obrigatoriedade de campos em cadastros + adicao de config para determinar se saque pix e se sms estao habilitados

Gustavo Mantovani преди 1 седмица
родител
ревизия
5bc1aa2540
променени са 52 файла, в които са добавени 201 реда и са изтрити 143 реда
  1. 20 0
      app/Enums/GenderEnum.php
  2. 7 0
      app/Http/Controllers/ProviderWithdrawalController.php
  3. 15 0
      app/Http/Controllers/ServiceConfigurationController.php
  4. 2 0
      app/Http/Requests/ProviderRequest.php
  5. 14 7
      app/Http/Requests/RegisterClientRequest.php
  6. 16 17
      app/Http/Requests/RegisterProviderRequest.php
  7. 5 0
      app/Http/Resources/ClientFavoriteProviderResource.php
  8. 5 0
      app/Http/Resources/ClientProviderBlockResource.php
  9. 2 0
      app/Http/Resources/ProviderResource.php
  10. 2 0
      app/Http/Resources/ScheduleResource.php
  11. 3 0
      app/Models/Provider.php
  12. 9 3
      app/Services/ClientCalendarService.php
  13. 1 0
      app/Services/ClientFavoriteProviderService.php
  14. 1 0
      app/Services/ClientProviderBlockService.php
  15. 25 0
      app/Services/DashboardService.php
  16. 3 2
      app/Services/ProviderService.php
  17. 3 0
      app/Services/SearchService.php
  18. 1 0
      app/Services/ServicePackageService.php
  19. 4 0
      config/services.php
  20. 5 0
      config/withdrawals.php
  21. 22 0
      database/migrations/2026_07_21_170000_add_gender_to_providers_table.php
  22. 0 1
      lang/en/chatbot.php
  23. 8 0
      lang/en/genders.php
  24. 0 5
      lang/en/mail.php
  25. 0 1
      lang/en/messages.php
  26. 0 1
      lang/en/notifications.php
  27. 0 1
      lang/en/pagination.php
  28. 0 1
      lang/en/passwords.php
  29. 0 1
      lang/en/schedules.php
  30. 1 25
      lang/en/validation.php
  31. 0 1
      lang/es/chatbot.php
  32. 8 0
      lang/es/genders.php
  33. 0 1
      lang/es/http.php
  34. 0 5
      lang/es/mail.php
  35. 0 1
      lang/es/messages.php
  36. 0 1
      lang/es/notifications.php
  37. 0 1
      lang/es/pagination.php
  38. 0 1
      lang/es/passwords.php
  39. 0 1
      lang/es/schedules.php
  40. 2 27
      lang/es/validation.php
  41. 0 1
      lang/pt/chatbot.php
  42. 8 0
      lang/pt/genders.php
  43. 0 1
      lang/pt/http.php
  44. 0 5
      lang/pt/mail.php
  45. 0 1
      lang/pt/messages.php
  46. 0 1
      lang/pt/notifications.php
  47. 0 1
      lang/pt/pagination.php
  48. 0 1
      lang/pt/passwords.php
  49. 0 1
      lang/pt/schedules.php
  50. 2 27
      lang/pt/validation.php
  51. 1 0
      routes/authRoutes/provider.php
  52. 6 0
      routes/noAuthRoutes/service_configuration.php

+ 20 - 0
app/Enums/GenderEnum.php

@@ -0,0 +1,20 @@
+<?php
+
+namespace App\Enums;
+
+use App\Traits\EnumHelper;
+
+enum GenderEnum: string
+{
+    use EnumHelper;
+
+    case MALE              = 'male';
+    case FEMALE            = 'female';
+    case OTHER             = 'other';
+    case PREFER_NOT_TO_SAY = 'prefer_not_to_say';
+
+    public function label(): string
+    {
+        return __("genders.{$this->value}");
+    }
+}

+ 7 - 0
app/Http/Controllers/ProviderWithdrawalController.php

@@ -65,6 +65,13 @@ class ProviderWithdrawalController extends Controller
         ]);
     }
 
+    public function configuration(): JsonResponse
+    {
+        return $this->successResponse(payload: [
+            'pix_enabled' => config('withdrawals.pix_enabled'),
+        ]);
+    }
+
     public function fees(): JsonResponse
     {
         return $this->successResponse(payload: $this->service->getWithdrawalFees());

+ 15 - 0
app/Http/Controllers/ServiceConfigurationController.php

@@ -0,0 +1,15 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Http\JsonResponse;
+
+class ServiceConfigurationController extends Controller
+{
+    public function index(): JsonResponse
+    {
+        return $this->successResponse(payload: [
+            'sms_enabled' => config('services.sms.enabled'),
+        ]);
+    }
+}

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

@@ -3,6 +3,7 @@
 namespace App\Http\Requests;
 
 use App\Enums\ApprovalStatusEnum;
+use App\Enums\GenderEnum;
 use App\Enums\UserTypeEnum;
 use Illuminate\Foundation\Http\FormRequest;
 use Illuminate\Validation\Rule;
@@ -65,6 +66,7 @@ class ProviderRequest extends FormRequest
             'average_rating'         => 'sometimes|nullable|numeric|min:0|max:5',
             'total_services'         => 'sometimes|integer|min:0',
             'birth_date'             => 'sometimes|nullable|date|before:today',
+            'gender'                 => ['sometimes', 'nullable', Rule::enum(GenderEnum::class)],
             'selfie_verified'        => 'sometimes|boolean',
             'document_verified'      => 'sometimes|boolean',
             'approval_status'        => ['sometimes', Rule::enum(ApprovalStatusEnum::class)],

+ 14 - 7
app/Http/Requests/RegisterClientRequest.php

@@ -6,25 +6,32 @@ use Illuminate\Foundation\Http\FormRequest;
 
 class RegisterClientRequest extends FormRequest
 {
+    protected function prepareForValidation(): void
+    {
+        if (! $this->filled('has_complement')) {
+            $this->merge(['has_complement' => false]);
+        }
+    }
+
     public function rules(): array
     {
         return [
             'email'          => 'sometimes|email|nullable',
-            'phone'          => 'sometimes|string|nullable',
+            'phone'          => 'required|string|max:20',
             'name'           => 'sometimes|string|max:255|nullable',
             'code'           => 'required|string|max:6',
-            'document'       => 'sometimes|string|nullable',
+            'document'       => 'required|string|max:20',
             'zip_code'       => 'sometimes|string|max:20|nullable',
             'address'        => 'sometimes|string|max:255|nullable',
-            'number'         => 'sometimes|string|max:20|nullable',
-            'district'       => 'sometimes|string|max:255|nullable',
+            'number'         => 'required|string|max:20',
+            'district'       => 'required|string|max:255',
             'complement'     => 'sometimes|string|max:255|nullable',
-            'has_complement' => 'sometimes|boolean|nullable',
+            'has_complement' => 'required|boolean',
             'nickname'       => 'sometimes|string|max:255|nullable',
             'instructions'   => 'sometimes|string|max:500|nullable',
             'address_type'   => 'sometimes|string|in:home,commercial,other|nullable',
-            'city'           => 'sometimes|string|max:255|nullable',
-            'state'          => 'sometimes|string|max:10|nullable',
+            'city'           => 'required|string|max:255',
+            'state'          => 'required|string|max:10',
             'latitude'       => 'sometimes|numeric|nullable',
             'longitude'      => 'sometimes|numeric|nullable',
             'avatar'         => 'sometimes|nullable|file|image|mimes:jpg,jpeg,png,webp|max:5120',

+ 16 - 17
app/Http/Requests/RegisterProviderRequest.php

@@ -2,24 +2,33 @@
 
 namespace App\Http\Requests;
 
+use App\Enums\GenderEnum;
 use App\Enums\WorkingPeriodEnum;
 use Illuminate\Foundation\Http\FormRequest;
 use Illuminate\Validation\Rule;
 
 class RegisterProviderRequest extends FormRequest
 {
+  protected function prepareForValidation(): void
+  {
+    if (! $this->filled('has_complement')) {
+      $this->merge(['has_complement' => false]);
+    }
+  }
+
   public function rules(): array
   {
     $dailyPriceMin = config('provider.daily_price_min');
 
     $rules = [
-      'email'      => 'sometimes|email',
-      'phone'      => 'sometimes|string|nullable|max:20',
+      'email'      => 'sometimes|nullable|email',
+      'phone'      => 'required|string|max:20',
       'name'       => 'required|string|max:255',
       'code'       => 'required|string|max:6',
       'document'   => ['required', 'string', 'max:20'],
       'rg'         => 'required|string|max:20',
       'birth_date' => 'required|date|before:today',
+      'gender'     => ['sometimes', 'nullable', Rule::enum(GenderEnum::class)],
 
       'recipient_name'        => 'sometimes|string|max:255',
       'recipient_email'       => 'sometimes|email|max:255',
@@ -46,15 +55,15 @@ class RegisterProviderRequest extends FormRequest
 
       'zip_code'       => 'required|string|max:20',
       'address'        => 'required|string|max:255',
-      'number'         => 'sometimes|string|max:20|nullable',
-      'district'       => 'sometimes|string|max:255|nullable',
-      'has_complement' => 'sometimes|boolean',
+      'number'         => 'required|string|max:20',
+      'district'       => 'required|string|max:255',
+      'has_complement' => 'required|boolean',
       'complement'     => 'nullable|string|max:255',
       'nickname'       => 'nullable|string|max:255',
       'instructions'   => 'nullable|string',
       'address_type'   => ['required', Rule::in(['home', 'commercial', 'other'])],
-      'city'           => 'nullable|string|max:255',
-      'state'          => 'nullable|string|max:2',
+      'city'           => 'required|string|max:255',
+      'state'          => 'required|string|max:2',
       'latitude'       => 'sometimes|numeric|nullable',
       'longitude'      => 'sometimes|numeric|nullable',
 
@@ -90,16 +99,6 @@ class RegisterProviderRequest extends FormRequest
       'document_back'   => 'required|file|image|mimes:jpg,jpeg,png,webp|max:10240',
     ];
 
-    if (!$this->has('email')) {
-      $rules['phone'] = 'required|string|max:20';
-      $rules['email'] = 'nullable';
-    }
-
-    if (!$this->has('phone')) {
-      $rules['email'] = 'required|email';
-      $rules['phone'] = 'nullable';
-    }
-
     return $rules;
   }
 }

+ 5 - 0
app/Http/Resources/ClientFavoriteProviderResource.php

@@ -2,6 +2,7 @@
 
 namespace App\Http\Resources;
 
+use App\Enums\GenderEnum;
 use Illuminate\Http\Request;
 use Illuminate\Http\Resources\Json\JsonResource;
 use Illuminate\Support\Facades\Storage;
@@ -20,11 +21,15 @@ class ClientFavoriteProviderResource extends JsonResource
         $dailyPrice4h = $this->daily_price_4h ?? $provider?->daily_price_4h;
         $dailyPrice2h = $this->daily_price_2h ?? $provider?->daily_price_2h;
 
+        $gender = $this->gender ?? $provider?->gender?->value;
+
         return [
             'id'             => $this->id,
             'client_id'      => $this->client_id,
             'provider_id'    => $this->provider_id,
             'provider_name'  => $this->provider_name  ?? ($provider?->relationLoaded('user') ? $provider->user?->name : null),
+            'gender'         => $gender,
+            'gender_label'   => $gender ? GenderEnum::tryFrom($gender)?->label() : null,
             'city_name'      => $this->city_name      ?? null,
             'average_rating' => $this->average_rating ?? $provider?->average_rating,
 

+ 5 - 0
app/Http/Resources/ClientProviderBlockResource.php

@@ -2,6 +2,7 @@
 
 namespace App\Http\Resources;
 
+use App\Enums\GenderEnum;
 use Illuminate\Http\Request;
 use Illuminate\Http\Resources\Json\JsonResource;
 
@@ -9,11 +10,15 @@ class ClientProviderBlockResource extends JsonResource
 {
     public function toArray(Request $request): array
     {
+        $gender = $this->gender ?? $this->provider?->gender?->value;
+
         return [
             'id'                => $this->id,
             'client_id'         => $this->client_id,
             'provider_id'       => $this->provider_id,
             'provider_name'     => $this->provider_name     ?? $this->provider?->user?->name,
+            'gender'            => $gender,
+            'gender_label'      => $gender ? GenderEnum::tryFrom($gender)?->label() : null,
             'provider_email'    => $this->provider_email    ?? $this->provider?->user?->email,
             'provider_phone'    => $this->provider_phone    ?? $this->provider?->user?->phone,
             'provider_district' => $this->provider_district ?? null,

+ 2 - 0
app/Http/Resources/ProviderResource.php

@@ -21,6 +21,8 @@ class ProviderResource extends JsonResource
             'average_rating'                 => $this->average_rating,
             'total_services'                 => $this->total_services,
             'birth_date'                     => $this->birth_date ? Carbon::parse($this->birth_date)->format('d/m/Y') : null,
+            'gender'                         => $this->gender?->value,
+            'gender_label'                   => $this->gender?->label(),
             'selfie_verified'                => $this->selfie_verified,
             'document_verified'              => $this->document_verified,
             'approval_status'                => $this->approval_status?->value ?? $this->approval_status,

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

@@ -24,6 +24,8 @@ class ScheduleResource extends JsonResource
             'client_name'   => $this->client?->user?->name,
             'provider_id'   => $this->provider_id,
             'provider_name' => $this->provider?->user?->name,
+            'gender'        => $this->provider?->gender?->value,
+            'gender_label'  => $this->provider?->gender?->label(),
             'address_id'    => $this->address_id,
 
             'address_full' => $this->address ? implode(', ', array_filter([

+ 3 - 0
app/Models/Provider.php

@@ -3,6 +3,7 @@
 namespace App\Models;
 
 use App\Enums\ApprovalStatusEnum;
+use App\Enums\GenderEnum;
 use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Model;
 use Illuminate\Database\Eloquent\Relations\BelongsTo;
@@ -18,6 +19,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
  * @property numeric|null $average_rating
  * @property int $total_services
  * @property \Illuminate\Support\Carbon|null $birth_date
+ * @property GenderEnum|null $gender
  * @property bool $selfie_verified
  * @property bool $document_verified
  * @property numeric|null $daily_price_8h
@@ -114,6 +116,7 @@ class Provider extends Model
     {
         return [
             'birth_date'                                => 'date',
+            'gender'                                    => GenderEnum::class,
             'selfie_verified'                           => 'boolean',
             'document_verified'                         => 'boolean',
             'approval_status'                           => ApprovalStatusEnum::class,

+ 9 - 3
app/Services/ClientCalendarService.php

@@ -2,6 +2,7 @@
 
 namespace App\Services;
 
+use App\Enums\GenderEnum;
 use App\Models\Client;
 use App\Models\Schedule;
 use Illuminate\Support\Facades\Auth;
@@ -31,6 +32,7 @@ class ClientCalendarService
             'schedules.status',
             'custom_schedules.offers_meal',
             'provider_user.name as provider_name',
+            'providers.gender',
             'providers.average_rating',
             'providers.total_services',
 
@@ -69,9 +71,13 @@ class ClientCalendarService
             "),
         ];
 
-        $signPhoto = fn ($item) => tap($item, fn ($i) => $i->provider_photo = $i->provider_photo
-            ? Storage::temporaryUrl($i->provider_photo, now()->addMinutes(60))
-            : null);
+        $signPhoto = fn ($item) => tap($item, function ($i) {
+            $i->gender_label = $i->gender ? GenderEnum::tryFrom($i->gender)?->label() : null;
+
+            $i->provider_photo = $i->provider_photo
+                ? Storage::temporaryUrl($i->provider_photo, now()->addMinutes(60))
+                : null;
+        });
 
         $upcomingSchedules = Schedule::with('address:district,address,number,source_id,source,id')
             ->where('schedules.client_id', $client->id)

+ 1 - 0
app/Services/ClientFavoriteProviderService.php

@@ -31,6 +31,7 @@ class ClientFavoriteProviderService
                 'client_favorite_providers.created_at',
                 'client_favorite_providers.updated_at',
                 'provider_user.name as provider_name',
+                'providers.gender',
                 'provider_profile_media.path as profile_media_path',
                 'providers.average_rating',
                 'providers.daily_price_8h',

+ 1 - 0
app/Services/ClientProviderBlockService.php

@@ -26,6 +26,7 @@ class ClientProviderBlockService
                 'provider_user.name as provider_name',
                 'provider_user.email as provider_email',
                 'provider_user.phone as provider_phone',
+                'providers.gender',
                 'providers.average_rating as provider_rating',
                 'provider_address.district as provider_district',
             )

+ 25 - 0
app/Services/DashboardService.php

@@ -2,6 +2,7 @@
 
 namespace App\Services;
 
+use App\Enums\GenderEnum;
 use App\Enums\UserTypeEnum;
 use App\Models\Address;
 use App\Models\Client;
@@ -83,6 +84,7 @@ class DashboardService
                 'schedules.id',
                 'schedules.provider_id',
                 'provider_user.name as provider_name',
+                'providers.gender',
                 'schedules.date',
                 'schedules.start_time',
                 'schedules.end_time',
@@ -120,6 +122,8 @@ class DashboardService
             ->get();
 
         $nextSchedules->each(function ($item) {
+            $item->gender_label = $item->gender ? GenderEnum::tryFrom($item->gender)?->label() : null;
+
             $item->provider_photo = $item->provider_photo_path
                 ? Storage::temporaryUrl($item->provider_photo_path, now()->addMinutes(60))
                 : null;
@@ -149,6 +153,7 @@ class DashboardService
                 'schedules.id',
                 'schedules.provider_id',
                 'provider_user.name as provider_name',
+                'providers.gender',
                 'provider_address.district as provider_district',
                 'provider_media.path as provider_photo_path',
             )
@@ -157,6 +162,8 @@ class DashboardService
             ->get();
 
         $lastDoneSchedules->each(function ($item) {
+            $item->gender_label = $item->gender ? GenderEnum::tryFrom($item->gender)?->label() : null;
+
             $item->provider_photo = $item->provider_photo_path
                 ? Storage::temporaryUrl($item->provider_photo_path, now()->addMinutes(60))
                 : null;
@@ -181,6 +188,7 @@ class DashboardService
             ->select(
                 'providers.id as provider_id',
                 'provider_user.name as provider_name',
+                'providers.gender',
                 'providers.average_rating',
                 'provider_address.district as provider_district',
                 'provider_media.path as provider_photo_path',
@@ -190,6 +198,8 @@ class DashboardService
             ->get();
 
         $favoriteProviders->each(function ($item) {
+            $item->gender_label = $item->gender ? GenderEnum::tryFrom($item->gender)?->label() : null;
+
             $item->provider_photo = $item->provider_photo_path
                 ? Storage::temporaryUrl($item->provider_photo_path, now()->addMinutes(60))
                 : null;
@@ -333,6 +343,7 @@ class DashboardService
             ->select(
                 'providers.id as provider_id',
                 'provider_user.name as provider_name',
+                'providers.gender',
                 'provider_address.id as address_id',
                 'provider_address.zip_code as provider_zip_code',
                 'provider_address.district',
@@ -390,6 +401,8 @@ class DashboardService
         );
 
         $providersClose->each(function ($item) use ($clientDistanceAddress) {
+            $item->gender_label = $item->gender ? GenderEnum::tryFrom($item->gender)?->label() : null;
+
             if ($item->distance_km === null) {
                 $item->distance_km = $this->zipCodeCoordinatesService->calculateDistance(
                     $clientDistanceAddress?->latitude !== null ? (float) $clientDistanceAddress->latitude : null,
@@ -445,6 +458,7 @@ class DashboardService
                 'schedules.id',
                 'schedules.provider_id',
                 'provider_user.name as provider_name',
+                'providers.gender',
                 'schedules.date',
                 'schedules.address_id',
                 'schedules.status',
@@ -500,6 +514,8 @@ class DashboardService
             ->get();
 
         $pendingSchedules->each(function ($item) {
+            $item->gender_label = $item->gender ? GenderEnum::tryFrom($item->gender)?->label() : null;
+
             $item->provider_photo = $item->provider_photo_path
                 ? Storage::temporaryUrl($item->provider_photo_path, now()->addMinutes(60))
                 : null;
@@ -564,6 +580,7 @@ class DashboardService
                 "),
 
                 'providers.id as provider_id',
+                'providers.gender',
                 'schedules.id as schedule_id',
                 'schedules.date',
                 'schedules.start_time',
@@ -598,6 +615,8 @@ class DashboardService
             ->get();
 
         $schedulesProposals->each(function ($item) use ($clientDistanceAddress) {
+            $item->gender_label = $item->gender ? GenderEnum::tryFrom($item->gender)?->label() : null;
+
             if ($item->distance_km === null) {
                 $item->distance_km = $this->zipCodeCoordinatesService->calculateDistance(
                     $clientDistanceAddress?->latitude !== null ? (float) $clientDistanceAddress->latitude : null,
@@ -634,6 +653,7 @@ class DashboardService
                 'schedules.id',
                 'schedules.provider_id',
                 'provider_user.name as provider_name',
+                'providers.gender',
                 'schedules.date',
                 'schedules.start_time',
                 'schedules.end_time',
@@ -682,6 +702,8 @@ class DashboardService
             ->orderBy('schedules.start_time', 'asc')
             ->get()
             ->map(function ($item) {
+                $item->gender_label = $item->gender ? GenderEnum::tryFrom($item->gender)?->label() : null;
+
                 $item->provider_photo = $item->provider_photo
                     ? Storage::temporaryUrl(
                         $item->provider_photo,
@@ -981,6 +1003,7 @@ class DashboardService
                 'schedules.provider_id',
                 'provider_user.name as provider_name',
                 'providers.birth_date as provider_birth_date',
+                'providers.gender',
                 'media.path as provider_photo',
                 'custom_schedules.offers_meal',
             )
@@ -1004,6 +1027,8 @@ class DashboardService
         return [
             'provider_name'       => $schedule->provider_name,
             'provider_birth_date' => $schedule->provider_birth_date,
+            'gender'              => $schedule->gender,
+            'gender_label'        => $schedule->gender ? GenderEnum::tryFrom($schedule->gender)?->label() : null,
             'offers_meal'         => $schedule->offers_meal,
             'specialities'        => $specialities,
 

+ 3 - 2
app/Services/ProviderService.php

@@ -192,6 +192,7 @@ class ProviderService
             $provider->rg              = data_get($data, 'rg');
             $provider->document        = $this->sanitizeDigits(data_get($data, 'document'));
             $provider->birth_date      = data_get($data, 'birth_date');
+            $provider->gender          = data_get($data, 'gender');
             $provider->daily_price_8h  = data_get($data, 'daily_price_8h');
             $provider->daily_price_6h  = data_get($data, 'daily_price_6h');
             $provider->daily_price_4h  = data_get($data, 'daily_price_4h');
@@ -476,9 +477,9 @@ class ProviderService
         if (! empty($provider->user?->email)) {
             try {
                 $this->emailService->sendProviderApproved(
-                    email: $provider->user->email,
+                    email:         $provider->user->email,
                     recipientName: $provider->user->name ?? '',
-                    locale: $provider->user->language?->value,
+                    locale:        $provider->user->language?->value,
                 );
             } catch (\Throwable $exception) {
                 Log::error('Falha ao enviar e-mail de aprovação do prestador', [

+ 3 - 0
app/Services/SearchService.php

@@ -2,6 +2,7 @@
 
 namespace App\Services;
 
+use App\Enums\GenderEnum;
 use App\Models\Address;
 use App\Models\Client;
 use App\Models\Media;
@@ -85,6 +86,7 @@ class SearchService
                 'providers.id as provider_id',
                 'providers.profile_media_id',
                 'provider_user.name as provider_name',
+                'providers.gender',
                 'provider_address.zip_code as provider_zip_code',
                 'provider_address.district',
                 'provider_address.latitude as provider_latitude',
@@ -173,6 +175,7 @@ class SearchService
             $arr = is_array($item) ? $item : $item->toArray();
 
             $arr['profile_media_url']   = data_get($mediaUrls, data_get($arr, 'profile_media_id'));
+            $arr['gender_label']        = data_get($arr, 'gender') ? GenderEnum::tryFrom(data_get($arr, 'gender'))?->label() : null;
             $arr['daily_price_8h_base'] = data_get($arr, 'daily_price_8h');
             $arr['daily_price_6h_base'] = data_get($arr, 'daily_price_6h');
             $arr['daily_price_4h_base'] = data_get($arr, 'daily_price_4h');

+ 1 - 0
app/Services/ServicePackageService.php

@@ -107,6 +107,7 @@ class ServicePackageService
     {
         return DB::transaction(function () use ($data) {
             $items = $this->scheduleItems($data);
+
             $providerId = $this->singleProviderId($data, $items);
 
             $schedules = app(ScheduleService::class)->createSingleOrMultiple(

+ 4 - 0
config/services.php

@@ -53,6 +53,10 @@ return [
         'from'  => env('SUPPORT_FROM_EMAIL', env('MAIL_FROM_ADDRESS')),
     ],
 
+    'sms' => [
+        'enabled' => (bool) env('SMS_ENABLED', false),
+    ],
+
     'pagarme' => [
         'secret_key'            => env('PAGARME_SECRET_KEY'),
         'service_referer_name'  => env('PAGARME_SERVICE_REFERER_NAME', env('APP_NAME', 'Laravel')),

+ 5 - 0
config/withdrawals.php

@@ -0,0 +1,5 @@
+<?php
+
+return [
+    'pix_enabled' => (bool) env('PIX_WITHDRAWALS_ENABLED', false),
+];

+ 22 - 0
database/migrations/2026_07_21_170000_add_gender_to_providers_table.php

@@ -0,0 +1,22 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+return new class extends Migration
+{
+    public function up(): void
+    {
+        Schema::table('providers', function (Blueprint $table) {
+            $table->string('gender')->nullable()->after('birth_date');
+        });
+    }
+
+    public function down(): void
+    {
+        Schema::table('providers', function (Blueprint $table) {
+            $table->dropColumn('gender');
+        });
+    }
+};

+ 0 - 1
lang/en/chatbot.php

@@ -2,5 +2,4 @@
 
 return [
     'error_response' => 'Unable to process your message at the moment. Please try again shortly.',
-
 ];

+ 8 - 0
lang/en/genders.php

@@ -0,0 +1,8 @@
+<?php
+
+return [
+    'male'              => 'Male',
+    'female'            => 'Female',
+    'other'             => 'Other',
+    'prefer_not_to_say' => 'Prefer not to say',
+];

+ 0 - 5
lang/en/mail.php

@@ -13,7 +13,6 @@ return [
         'field_title'    => 'Subject',
         'field_message'  => 'Message',
         'footer_note'    => 'This request is also recorded in the backoffice. This is an automated email, please do not reply.',
-
     ],
     'send_code' => [
         'subject'            => 'Your verification code',
@@ -25,7 +24,6 @@ return [
         'ignore_notice'      => 'If you did not request this code, please ignore this email.',
         'footer_note'        => 'This is an automated email. Please do not reply.',
         'footer_title'       => 'Thank you for using the Diaria App ',
-
     ],
     'provider_approved' => [
         'subject'            => 'Registration approved on Diaria App',
@@ -37,7 +35,6 @@ return [
         'next_step'          => 'Log in to the app with the same email or phone used during registration to access your account.',
         'footer_title'       => 'Welcome to Diaria App',
         'footer_note'        => 'This is an automated email. Please do not reply.',
-
     ],
     'service_completed' => [
         'subject'                    => 'Service completed successfully',
@@ -63,7 +60,5 @@ return [
         'service_fee'                => 'Service fee',
         'final_amount'               => 'Final amount',
         'currency'                   => 'R$',
-
     ],
-
 ];

+ 0 - 1
lang/en/messages.php

@@ -64,5 +64,4 @@ return [
     'provider_refused'                             => 'Provider refused.',
     'opportunity_refused'                          => 'Opportunity refused.',
     'withdrawal_requested'                         => 'Withdrawal requested successfully.',
-
 ];

+ 0 - 1
lang/en/notifications.php

@@ -26,5 +26,4 @@ return [
     'opportunity_refused_description'         => ':provider refused your custom request.',
     'proposal_refused_title'                  => 'Proposal refused!',
     'proposal_refused_description'            => 'The client refused your proposal.',
-
 ];

+ 0 - 1
lang/en/pagination.php

@@ -15,5 +15,4 @@ return [
 
     'previous' => '&laquo; Previous',
     'next'     => 'Next &raquo;',
-
 ];

+ 0 - 1
lang/en/passwords.php

@@ -18,5 +18,4 @@ return [
     'throttled' => 'Please wait before retrying.',
     'token'     => 'This password reset token is invalid.',
     'user'      => "We can't find a user with that email address.",
-
 ];

+ 0 - 1
lang/en/schedules.php

@@ -2,5 +2,4 @@
 
 return [
     'schedules_created' => '{1} :count appointment created successfully|[2,*] :count appointments created successfully',
-
 ];

+ 1 - 25
lang/en/validation.php

@@ -30,7 +30,6 @@ return [
         'file'    => 'The :attribute field must be between :min and :max kilobytes.',
         'numeric' => 'The :attribute field must be between :min and :max.',
         'string'  => 'The :attribute field must be between :min and :max characters.',
-
     ],
     'boolean'               => 'The :attribute field must be true or false.',
     'can'                   => 'The :attribute field contains an unauthorized value.',
@@ -64,14 +63,12 @@ return [
         'file'    => 'The :attribute field must be greater than :value kilobytes.',
         'numeric' => 'The :attribute field must be greater than :value.',
         'string'  => 'The :attribute field must be greater than :value characters.',
-
     ],
     'gte' => [
         'array'   => 'The :attribute field must have :value items or more.',
         'file'    => 'The :attribute field must be greater than or equal to :value kilobytes.',
         'numeric' => 'The :attribute field must be greater than or equal to :value.',
         'string'  => 'The :attribute field must be greater than or equal to :value characters.',
-
     ],
     'hex_color' => 'The :attribute field must be a valid hexadecimal color.',
     'image'     => 'The :attribute field must be an image.',
@@ -89,14 +86,12 @@ return [
         'file'    => 'The :attribute field must be less than :value kilobytes.',
         'numeric' => 'The :attribute field must be less than :value.',
         'string'  => 'The :attribute field must be less than :value characters.',
-
     ],
     'lte' => [
         'array'   => 'The :attribute field must not have more than :value items.',
         'file'    => 'The :attribute field must be less than or equal to :value kilobytes.',
         'numeric' => 'The :attribute field must be less than or equal to :value.',
         'string'  => 'The :attribute field must be less than or equal to :value characters.',
-
     ],
     'mac_address' => 'The :attribute field must be a valid MAC address.',
     'max'         => [
@@ -104,7 +99,6 @@ return [
         'file'    => 'The :attribute field must not be greater than :max kilobytes.',
         'numeric' => 'The :attribute field must not be greater than :max.',
         'string'  => 'The :attribute field must not be greater than :max characters.',
-
     ],
     'max_digits' => 'The :attribute field must not have more than :max digits.',
     'mimes'      => 'The :attribute field must be a file of type: :values.',
@@ -114,7 +108,6 @@ return [
         'file'    => 'The :attribute field must be at least :min kilobytes.',
         'numeric' => 'The :attribute field must be at least :min.',
         'string'  => 'The :attribute field must be at least :min characters.',
-
     ],
     'min_digits'       => 'The :attribute field must have at least :min digits.',
     'missing'          => 'The :attribute field must be missing.',
@@ -132,7 +125,6 @@ return [
         'numbers'       => 'The :attribute field must contain at least one number.',
         'symbols'       => 'The :attribute field must contain at least one symbol.',
         'uncompromised' => 'The given :attribute has appeared in a data leak. Please choose a different :attribute.',
-
     ],
     'payment_cant_be_refunded'                => 'This payment cannot be refunded.',
     'present'                                 => 'The :attribute field must be present.',
@@ -163,7 +155,6 @@ return [
         'file'    => 'The :attribute field must be :size kilobytes.',
         'numeric' => 'The :attribute field must be :size.',
         'string'  => 'The :attribute field must be :size characters.',
-
     ],
     'starts_with' => 'The :attribute field must start with one of the following: :values.',
     'string'      => 'The :attribute field must be a string.',
@@ -188,32 +179,25 @@ return [
     'custom' => [
         'attribute-name' => [
             'rule-name' => 'custom-message',
-
         ],
         'document' => [
             'invalid' => 'The CPF or CNPJ provided is invalid.',
-
         ],
         'user_id' => [
             'already_linked_to_client'   => 'This user is already linked to a client.',
             'already_linked_to_provider' => 'This user is already linked to a provider.',
-
         ],
         'zip_code' => [
             'invalid' => 'The zip code provided is invalid. It must contain 8 digits.',
-
         ],
         'source' => [
             'invalid' => 'The source type is invalid. It must be Provider or Client.',
-
         ],
         'source_id' => [
             'not_found' => 'The source record was not found.',
-
         ],
         'address_type' => [
             'invalid' => 'The address type is invalid.',
-
         ],
         'schedule' => [
             'weekly_limit_exceeded'                   => 'This provider already has 2 schedules with this client in the same week.',
@@ -228,7 +212,6 @@ return [
             'provider_conflicting_proposal_same_date' => 'The provider already has a proposal for a schedule on the same day.',
             'client_blocked_by_provider'              => 'The client is blocked by this provider.',
             'provider_blocked_by_client'              => 'The provider is blocked by this client.',
-
         ],
         'opportunity' => [
             'already_assigned'      => 'This opportunity already has a provider assigned.',
@@ -239,26 +222,20 @@ return [
             'schedule_conflict'     => 'Provider already has a schedule at this time.',
             'code_already_verified' => 'The code has already been verified for this schedule.',
             'invalid_code'          => 'The provided code is invalid.',
-
         ],
         'provider_client_block' => [
             'already_blocked' => 'This client is already blocked by this provider.',
-
         ],
         'client_provider_block' => [
             'already_blocked' => 'This provider is already blocked by this client.',
-
         ],
         'review' => [
             'already_reviewed' => 'This schedule has already been reviewed by this user.',
             'invalid_origin'   => 'The origin field must be "providers" or "clients".',
-
         ],
         'review_improvement' => [
             'already_exists' => 'This improvement type is already linked to this review.',
-
         ],
-
     ],
     /*
     |--------------------------------------------------------------------------
@@ -272,7 +249,6 @@ return [
     */
 
     'attributes' => [
-
+        'gender' => 'gender',
     ],
-
 ];

+ 0 - 1
lang/es/chatbot.php

@@ -2,5 +2,4 @@
 
 return [
     'error_response' => 'No se pudo procesar tu mensaje en este momento. Por favor, inténtalo de nuevo en breve.',
-
 ];

+ 8 - 0
lang/es/genders.php

@@ -0,0 +1,8 @@
+<?php
+
+return [
+    'male'              => 'Masculino',
+    'female'            => 'Femenino',
+    'other'             => 'Otro',
+    'prefer_not_to_say' => 'Prefiero no informar',
+];

+ 0 - 1
lang/es/http.php

@@ -36,5 +36,4 @@ return [
     'webhook_received'      => 'Webhook recibido',
     'unauthorized_ip'       => 'IP no autorizada',
     'unauthorized_token'    => 'Token no autorizado',
-
 ];

+ 0 - 5
lang/es/mail.php

@@ -13,7 +13,6 @@ return [
         'field_title'    => 'Asunto',
         'field_message'  => 'Mensaje',
         'footer_note'    => 'Esta solicitud también está registrada en el backoffice. Este es un correo automático, por favor no respondas.',
-
     ],
     'send_code' => [
         'subject'            => 'Tu código de verificación',
@@ -25,7 +24,6 @@ return [
         'ignore_notice'      => 'Si no solicitaste este código, ignora este correo.',
         'footer_note'        => 'Este es un correo automático. Por favor, no respondas.',
         'footer_title'       => 'Gracias por usar la aplicación Diaria ',
-
     ],
     'provider_approved' => [
         'subject'            => 'Registro aprobado en Diaria App',
@@ -37,7 +35,6 @@ return [
         'next_step'          => 'Ingresa a la app con el mismo correo o teléfono usado en el registro para acceder a tu cuenta.',
         'footer_title'       => 'Bienvenido a Diaria App',
         'footer_note'        => 'Este es un correo automático. Por favor, no respondas.',
-
     ],
     'service_completed' => [
         'subject'                    => 'Servicio finalizado con éxito',
@@ -63,7 +60,5 @@ return [
         'service_fee'                => 'Tarifa del servicio',
         'final_amount'               => 'Valor final',
         'currency'                   => 'R$',
-
     ],
-
 ];

+ 0 - 1
lang/es/messages.php

@@ -64,5 +64,4 @@ return [
     'provider_refused'                             => 'Prestador rechazado.',
     'opportunity_refused'                          => 'Oportunidad rechazada.',
     'withdrawal_requested'                         => 'Retiro solicitado con éxito.',
-
 ];

+ 0 - 1
lang/es/notifications.php

@@ -26,5 +26,4 @@ return [
     'opportunity_refused_description'         => ':provider rechazó tu solicitud personalizada.',
     'proposal_refused_title'                  => '¡Propuesta rechazada!',
     'proposal_refused_description'            => 'El cliente rechazó tu propuesta.',
-
 ];

+ 0 - 1
lang/es/pagination.php

@@ -15,5 +15,4 @@ return [
 
     'previous' => '&laquo; Anterior',
     'next'     => 'Proxima &raquo;',
-
 ];

+ 0 - 1
lang/es/passwords.php

@@ -18,5 +18,4 @@ return [
     'throttled' => 'Por favor espera antes de intentar de nuevo.',
     'token'     => 'Este token de restablecimiento de contraseña es inválido.',
     'user'      => 'No podemos encontrar un usuario con esa dirección de correo.',
-
 ];

+ 0 - 1
lang/es/schedules.php

@@ -2,5 +2,4 @@
 
 return [
     'schedules_created' => '{1} :count servicio programado creado con éxito|[2,*] :count servicios programados creados con éxito',
-
 ];

+ 2 - 27
lang/es/validation.php

@@ -31,7 +31,6 @@ return [
         'file'    => 'El campo :attribute debe tener entre :min y :max kilobytes.',
         'numeric' => 'El campo :attribute debe estar entre :min y :max.',
         'string'  => 'El campo :attribute debe tener entre :min y :max caracteres.',
-
     ],
     'boolean'               => 'El campo :attribute debe ser verdadero o falso.',
     'can'                   => 'El campo :attribute contiene un valor no autorizado.',
@@ -65,14 +64,12 @@ return [
         'file'    => 'El campo :attribute debe ser mayor que :value kilobytes.',
         'numeric' => 'El campo :attribute debe ser mayor que :value.',
         'string'  => 'El campo :attribute debe ser mayor que :value caracteres.',
-
     ],
     'gte' => [
         'array'   => 'El campo :attribute debe tener :value elementos o más.',
         'file'    => 'El campo :attribute debe ser mayor o igual a :value kilobytes.',
         'numeric' => 'El campo :attribute debe ser mayor o igual a :value.',
         'string'  => 'El campo :attribute debe ser mayor o igual a :value caracteres.',
-
     ],
     'hex_color' => 'El campo :attribute debe ser un color hexadecimal válido.',
     'image'     => 'El campo :attribute debe ser una imagen.',
@@ -90,14 +87,12 @@ return [
         'file'    => 'El campo :attribute debe ser menor que :value kilobytes.',
         'numeric' => 'El campo :attribute debe ser menor que :value.',
         'string'  => 'El campo :attribute debe ser menor que :value caracteres.',
-
     ],
     'lte' => [
         'array'   => 'El campo :attribute no debe tener más de :value elementos.',
         'file'    => 'El campo :attribute debe ser menor o igual a :value kilobytes.',
         'numeric' => 'El campo :attribute debe ser menor o igual a :value.',
         'string'  => 'El campo :attribute debe ser menor o igual a :value caracteres.',
-
     ],
     'mac_address' => 'El campo :attribute debe ser una dirección MAC válida.',
     'max'         => [
@@ -105,7 +100,6 @@ return [
         'file'    => 'El campo :attribute no debe ser mayor que :max kilobytes.',
         'numeric' => 'El campo :attribute no debe ser mayor que :max.',
         'string'  => 'El campo :attribute no debe ser mayor que :max caracteres.',
-
     ],
     'max_digits' => 'El campo :attribute no debe tener más de :max dígitos.',
     'mimes'      => 'El campo :attribute debe ser un archivo de tipo: :values.',
@@ -115,7 +109,6 @@ return [
         'file'    => 'El campo :attribute debe ser al menos de :min kilobytes.',
         'numeric' => 'El campo :attribute debe ser al menos :min.',
         'string'  => 'El campo :attribute debe tener al menos :min caracteres.',
-
     ],
     'min_digits'       => 'El campo :attribute debe tener al menos :min dígitos.',
     'missing'          => 'El campo :attribute debe estar ausente.',
@@ -133,7 +126,6 @@ return [
         'numbers'       => 'El campo :attribute debe contener al menos un número.',
         'symbols'       => 'El campo :attribute debe contener al menos un símbolo.',
         'uncompromised' => 'El campo :attribute proporcionado ha aparecido en una filtración de datos. Elija un :attribute diferente.',
-
     ],
     'payment_cant_be_refunded'                => 'El pago no puede ser reembolsado.',
     'present'                                 => 'El campo :attribute debe estar presente.',
@@ -164,7 +156,6 @@ return [
         'file'    => 'El campo :attribute debe ser de :size kilobytes.',
         'numeric' => 'El campo :attribute debe ser :size.',
         'string'  => 'El campo :attribute debe tener :size caracteres.',
-
     ],
     'starts_with' => 'El campo :attribute debe comenzar con uno de los siguientes: :values.',
     'string'      => 'El campo :attribute debe ser una cadena.',
@@ -189,32 +180,25 @@ return [
     'custom' => [
         'attribute-name' => [
             'rule-name' => 'mensaje-personalizado',
-
         ],
         'document' => [
             'invalid' => 'El CPF o CNPJ proporcionado es inválido.',
-
         ],
         'user_id' => [
             'already_linked_to_client'   => 'Este usuario ya está vinculado a un cliente.',
             'already_linked_to_provider' => 'Este usuario ya está vinculado a un proveedor.',
-
         ],
         'zip_code' => [
             'invalid' => 'El código postal proporcionado no es válido. Debe contener 8 dígitos.',
-
         ],
         'source' => [
             'invalid' => 'El tipo de origen no es válido. Debe ser Provider o Client.',
-
         ],
         'source_id' => [
             'not_found' => 'El registro de origen no fue encontrado.',
-
         ],
         'address_type' => [
             'invalid' => 'El tipo de dirección no es válido.',
-
         ],
         'schedule' => [
             'weekly_limit_exceeded'                   => 'Este proveedor ya tiene 2 agendas con este cliente en la misma semana.',
@@ -229,7 +213,6 @@ return [
             'provider_conflicting_proposal_same_date' => 'El proveedor ya tiene una propuesta para un agendamiento en el mismo día.',
             'client_blocked_by_provider'              => 'El cliente está bloqueado por este proveedor.',
             'provider_blocked_by_client'              => 'El proveedor está bloqueado por este cliente.',
-
         ],
         'opportunity' => [
             'already_assigned'      => 'Esta oportunidad ya tiene un proveedor asignado.',
@@ -240,26 +223,20 @@ return [
             'schedule_conflict'     => 'El proveedor ya tiene una agenda en este horario.',
             'code_already_verified' => 'El código ya fue verificado para este agendamiento.',
             'invalid_code'          => 'El código informado es inválido.',
-
         ],
         'provider_client_block' => [
             'already_blocked' => 'Este cliente ya está bloqueado por este proveedor.',
-
         ],
         'client_provider_block' => [
             'already_blocked' => 'Este proveedor ya está bloqueado por este cliente.',
-
         ],
         'review' => [
             'already_reviewed' => 'Esta agenda ya fue evaluada por este usuario.',
             'invalid_origin'   => 'El campo origen debe ser "providers" o "clients".',
-
         ],
         'review_improvement' => [
             'already_exists' => 'Este tipo de mejora ya está vinculado a esta evaluación.',
-
         ],
-
     ],
     /*
     |--------------------------------------------------------------------------
@@ -267,14 +244,12 @@ return [
     |--------------------------------------------------------------------------
     |
     | Las siguientes líneas de idioma se utilizan para intercambiar el marcador de posición de atributo
-    | con algo más amigable para el lector,
-    como "Dirección de correo electrónico" en lugar de "correo electrónico".
+    | con algo más amigable para el lector, como "Dirección de correo electrónico" en lugar de "correo electrónico".
     | Esto simplemente nos ayuda a hacer que nuestro mensaje sea más expresivo.
     |
     */
 
     'attributes' => [
-
+        'gender' => 'género',
     ],
-
 ];

+ 0 - 1
lang/pt/chatbot.php

@@ -2,5 +2,4 @@
 
 return [
     'error_response' => 'Não foi possível processar sua mensagem no momento. Tente novamente em instantes.',
-
 ];

+ 8 - 0
lang/pt/genders.php

@@ -0,0 +1,8 @@
+<?php
+
+return [
+    'male'              => 'Masculino',
+    'female'            => 'Feminino',
+    'other'             => 'Outro',
+    'prefer_not_to_say' => 'Prefiro não informar',
+];

+ 0 - 1
lang/pt/http.php

@@ -36,5 +36,4 @@ return [
     'webhook_received'      => 'Webhook recebido',
     'unauthorized_ip'       => 'Endereço IP não autorizado',
     'unauthorized_token'    => 'Token de webhook inválido',
-
 ];

+ 0 - 5
lang/pt/mail.php

@@ -13,7 +13,6 @@ return [
         'field_title'    => 'Assunto',
         'field_message'  => 'Mensagem',
         'footer_note'    => 'Esta solicitação também está registrada no backoffice. Este é um e-mail automático, não responda esta mensagem.',
-
     ],
     'send_code' => [
         'subject'            => 'Seu código de verificação',
@@ -25,7 +24,6 @@ return [
         'ignore_notice'      => 'Se você não solicitou este código, ignore este e-mail.',
         'footer_note'        => 'Este é um e-mail automático. Por favor, não responda.',
         'footer_title'       => 'Obrigado por utilizar o Diaria App ',
-
     ],
     'provider_approved' => [
         'subject'            => 'Cadastro aprovado no Diaria App',
@@ -37,7 +35,6 @@ return [
         'next_step'          => 'Entre no app com o mesmo e-mail ou telefone usado no cadastro para acessar sua conta.',
         'footer_title'       => 'Bem-vindo ao Diaria App',
         'footer_note'        => 'Este é um e-mail automático. Por favor, não responda.',
-
     ],
     'service_completed' => [
         'subject'                    => 'Serviço finalizado com sucesso',
@@ -63,7 +60,5 @@ return [
         'service_fee'                => 'Taxa de serviço',
         'final_amount'               => 'Valor final',
         'currency'                   => 'R$',
-
     ],
-
 ];

+ 0 - 1
lang/pt/messages.php

@@ -64,5 +64,4 @@ return [
     'provider_refused'                             => 'Prestador recusado.',
     'opportunity_refused'                          => 'Oportunidade recusada.',
     'withdrawal_requested'                         => 'Saque solicitado com sucesso.',
-
 ];

+ 0 - 1
lang/pt/notifications.php

@@ -26,5 +26,4 @@ return [
     'opportunity_refused_description'         => ':provider recusou sua solicitação sob medida.',
     'proposal_refused_title'                  => 'Proposta recusada!',
     'proposal_refused_description'            => 'O cliente recusou sua proposta de diária.',
-
 ];

+ 0 - 1
lang/pt/pagination.php

@@ -15,5 +15,4 @@ return [
 
     'previous' => '&laquo; Anterior',
     'next'     => 'Proxima &raquo;',
-
 ];

+ 0 - 1
lang/pt/passwords.php

@@ -18,5 +18,4 @@ return [
     'throttled' => 'Por favor aguarde antes de tentar novamente.',
     'token'     => 'Esse token de redefinição de senha é inválido.',
     'user'      => 'Não conseguimos encontrar um usuário com esse endereço de email.',
-
 ];

+ 0 - 1
lang/pt/schedules.php

@@ -2,5 +2,4 @@
 
 return [
     'schedules_created' => '{1} :count agendamento criado com sucesso|[2,*] :count agendamentos criados com sucesso',
-
 ];

+ 2 - 27
lang/pt/validation.php

@@ -31,7 +31,6 @@ return [
         'file'    => 'O campo :attribute deve ter entre :min e :max kilobytes.',
         'numeric' => 'O campo :attribute deve estar entre :min e :max.',
         'string'  => 'O campo :attribute deve ter entre :min e :max caracteres.',
-
     ],
     'boolean'               => 'O campo :attribute deve ser verdadeiro ou falso.',
     'can'                   => 'O campo :attribute contém um valor não autorizado.',
@@ -65,14 +64,12 @@ return [
         'file'    => 'O campo :attribute deve ser maior que :value kilobytes.',
         'numeric' => 'O campo :attribute deve ser maior que :value.',
         'string'  => 'O campo :attribute deve ser maior que :value caracteres.',
-
     ],
     'gte' => [
         'array'   => 'O campo :attribute deve ter :value itens ou mais.',
         'file'    => 'O campo :attribute deve ser maior ou igual a :value kilobytes.',
         'numeric' => 'O campo :attribute deve ser maior ou igual a :value.',
         'string'  => 'O campo :attribute deve ser maior ou igual a :value caracteres.',
-
     ],
     'hex_color' => 'O campo :attribute deve ser uma cor hexadecimal válida.',
     'image'     => 'O campo :attribute deve ser uma imagem.',
@@ -90,14 +87,12 @@ return [
         'file'    => 'O campo :attribute deve ser menor que :value kilobytes.',
         'numeric' => 'O campo :attribute deve ser menor que :value.',
         'string'  => 'O campo :attribute deve ser menor que :value caracteres.',
-
     ],
     'lte' => [
         'array'   => 'O campo :attribute não deve ter mais de :value itens.',
         'file'    => 'O campo :attribute deve ser menor ou igual a :value kilobytes.',
         'numeric' => 'O campo :attribute deve ser menor ou igual a :value.',
         'string'  => 'O campo :attribute deve ser menor ou igual a :value caracteres.',
-
     ],
     'mac_address' => 'O campo :attribute deve ser um endereço MAC válido.',
     'max'         => [
@@ -105,7 +100,6 @@ return [
         'file'    => 'O campo :attribute não deve ser maior que :max kilobytes.',
         'numeric' => 'O campo :attribute não deve ser maior que :max.',
         'string'  => 'O campo :attribute não deve ser maior que :max caracteres.',
-
     ],
     'max_digits' => 'O campo :attribute não deve ter mais de :max dígitos.',
     'mimes'      => 'O campo :attribute deve ser um arquivo do tipo: :values.',
@@ -115,7 +109,6 @@ return [
         'file'    => 'O campo :attribute deve ter pelo menos :min kilobytes.',
         'numeric' => 'O campo :attribute deve ser pelo menos :min.',
         'string'  => 'O campo :attribute deve ter pelo menos :min caracteres.',
-
     ],
     'min_digits'       => 'O campo :attribute deve ter pelo menos :min dígitos.',
     'missing'          => 'O campo :attribute deve estar ausente.',
@@ -133,7 +126,6 @@ return [
         'numbers'       => 'O campo :attribute deve conter pelo menos um número.',
         'symbols'       => 'O campo :attribute deve conter pelo menos um símbolo.',
         'uncompromised' => 'O campo :attribute fornecido apareceu em um vazamento de dados. Escolha um :attribute diferente.',
-
     ],
     'payment_cant_be_refunded'                => 'O pagamento não pode ser reembolsado.',
     'present'                                 => 'O campo :attribute deve estar presente.',
@@ -164,7 +156,6 @@ return [
         'file'    => 'O campo :attribute deve ter :size kilobytes.',
         'numeric' => 'O campo :attribute deve ser :size.',
         'string'  => 'O campo :attribute deve ter :size caracteres.',
-
     ],
     'starts_with' => 'O campo :attribute deve começar com um dos seguintes: :values.',
     'string'      => 'O campo :attribute deve ser uma string.',
@@ -189,32 +180,25 @@ return [
     'custom' => [
         'attribute-name' => [
             'rule-name' => 'mensagem-personalizada',
-
         ],
         'document' => [
             'invalid' => 'O CPF ou CNPJ informado é inválido.',
-
         ],
         'user_id' => [
             'already_linked_to_client'   => 'Este usuário já está vinculado a um cliente.',
             'already_linked_to_provider' => 'Este usuário já está vinculado a um prestador.',
-
         ],
         'zip_code' => [
             'invalid' => 'O CEP informado é inválido. Deve conter 8 dígitos.',
-
         ],
         'source' => [
             'invalid' => 'O tipo de origem é inválido. Deve ser Provider ou Client.',
-
         ],
         'source_id' => [
             'not_found' => 'O registro de origem não foi encontrado.',
-
         ],
         'address_type' => [
             'invalid' => 'O tipo de endereço é inválido.',
-
         ],
         'schedule' => [
             'weekly_limit_exceeded'                   => 'Este prestador já possui 2 agendamentos com este cliente na mesma semana.',
@@ -229,7 +213,6 @@ return [
             'provider_conflicting_proposal_same_date' => 'O prestador já possui uma proposta para um agendamento no mesmo dia.',
             'client_blocked_by_provider'              => 'O cliente está bloqueado por este prestador.',
             'provider_blocked_by_client'              => 'O prestador está bloqueado por este cliente.',
-
         ],
         'opportunity' => [
             'already_assigned'      => 'Esta oportunidade já possui um prestador atribuído.',
@@ -240,26 +223,20 @@ return [
             'schedule_conflict'     => 'Prestador já possui agendamento neste horário.',
             'code_already_verified' => 'O código já foi verificado para este agendamento.',
             'invalid_code'          => 'O código informado é inválido.',
-
         ],
         'provider_client_block' => [
             'already_blocked' => 'Este cliente já está bloqueado por este prestador.',
-
         ],
         'client_provider_block' => [
             'already_blocked' => 'Este prestador já está bloqueado por este cliente.',
-
         ],
         'review' => [
             'already_reviewed' => 'Esta agenda já foi avaliada por este usuário.',
             'invalid_origin'   => 'O campo origem deve ser "providers" ou "clients".',
-
         ],
         'review_improvement' => [
             'already_exists' => 'Este tipo de melhoria já está vinculado a esta avaliação.',
-
         ],
-
     ],
     /*
     |--------------------------------------------------------------------------
@@ -267,14 +244,12 @@ return [
     |--------------------------------------------------------------------------
     |
     | As seguintes linhas de linguagem são usadas para trocar o espaço reservado de atributo
-    | com algo mais amigável ao leitor,
-    como "Endereço de E-Mail" em vez de "email".
+    | com algo mais amigável ao leitor, como "Endereço de E-Mail" em vez de "email".
     | Isso simplesmente nos ajuda a tornar nossa mensagem mais expressiva.
     |
     */
 
     'attributes' => [
-
+        'gender' => 'gênero',
     ],
-
 ];

+ 1 - 0
routes/authRoutes/provider.php

@@ -11,6 +11,7 @@ Route::get('/provider/payment-splits',            [ProviderWithdrawalController:
 Route::get('/provider-withdrawals',               [ProviderWithdrawalController::class, 'all'])->middleware('permission:payment,view');
 Route::get('/provider/withdrawals/balance',       [ProviderWithdrawalController::class, 'balance'])->middleware('permission:config.provider,view');
 Route::get('/provider/withdrawals/fees',          [ProviderWithdrawalController::class, 'fees'])->middleware('permission:config.provider,view');
+Route::get('/provider/withdrawals/config',        [ProviderWithdrawalController::class, 'configuration']);
 Route::get('/provider/withdrawals',               [ProviderWithdrawalController::class, 'index'])->middleware('permission:config.provider,view');
 Route::post('/provider/withdrawals',              [ProviderWithdrawalController::class, 'store'])->middleware('permission:config.provider,edit');
 Route::get('/provider/withdrawals/{id}',          [ProviderWithdrawalController::class, 'show'])->middleware('permission:config.provider,view');

+ 6 - 0
routes/noAuthRoutes/service_configuration.php

@@ -0,0 +1,6 @@
+<?php
+
+use App\Http\Controllers\ServiceConfigurationController;
+use Illuminate\Support\Facades\Route;
+
+Route::get('/services/config', [ServiceConfigurationController::class, 'index']);