فهرست منبع

feat: add edicao de genero para os endpoints de user assim como retorna esse value ao puxar dados proprios

Gustavo Mantovani 1 هفته پیش
والد
کامیت
6e34471d14

+ 6 - 6
app/Http/Requests/ClientFavoriteProviderRequest.php

@@ -53,12 +53,12 @@ class ClientFavoriteProviderRequest extends FormRequest
     public function messages(): array
     {
         return [
-            'client_id.required'   => 'O cliente é obrigatório.',
-            'client_id.exists'     => 'Cliente não encontrado.',
-            'provider_id.required' => 'O prestador é obrigatório.',
-            'provider_id.exists'   => 'Prestador não encontrado.',
-            'provider_id.unique'   => 'Este prestador já está favoritado.',
-            'notes.max'            => 'As observações não podem exceder 1000 caracteres.',
+            'client_id.required'   => __('requests.client_favorite_provider.client_required'),
+            'client_id.exists'     => __('requests.client_favorite_provider.client_not_found'),
+            'provider_id.required' => __('requests.client_favorite_provider.provider_required'),
+            'provider_id.exists'   => __('requests.client_favorite_provider.provider_not_found'),
+            'provider_id.unique'   => __('requests.client_favorite_provider.already_favorite'),
+            'notes.max'            => __('requests.client_favorite_provider.notes_max'),
         ];
     }
 }

+ 14 - 14
app/Http/Requests/ClientPaymentMethodRequest.php

@@ -45,20 +45,20 @@ class ClientPaymentMethodRequest extends FormRequest
     public function messages(): array
     {
         return [
-            'client_id.required'        => 'O cliente é obrigatório.',
-            'client_id.exists'          => 'Cliente não encontrado.',
-            'token.required'            => 'O token do cartão é obrigatório.',
-            'card_number.required'      => 'O número do cartão é obrigatório.',
-            'card_number.min'           => 'O número do cartão deve ter no mínimo 13 dígitos.',
-            'card_number.max'           => 'O número do cartão deve ter no máximo 19 dígitos.',
-            'holder_name.required'      => 'O nome do titular é obrigatório.',
-            'expiration.required'       => 'A data de validade é obrigatória.',
-            'expiration.regex'          => 'A data de validade deve estar no formato MM/YYYY.',
-            'cvv.required'              => 'O CVV é obrigatório.',
-            'cvv.min'                   => 'O CVV deve ter no mínimo 3 dígitos.',
-            'cvv.max'                   => 'O CVV deve ter no máximo 4 dígitos.',
-            'last_four_digits.required' => 'Os últimos 4 dígitos são obrigatórios.',
-            'last_four_digits.size'     => 'Devem ser exatamente 4 dígitos.',
+            'client_id.required'        => __('requests.client_payment_method.client_required'),
+            'client_id.exists'          => __('requests.client_payment_method.client_not_found'),
+            'token.required'            => __('requests.client_payment_method.token_required'),
+            'card_number.required'      => __('requests.client_payment_method.card_number_required'),
+            'card_number.min'           => __('requests.client_payment_method.card_number_min'),
+            'card_number.max'           => __('requests.client_payment_method.card_number_max'),
+            'holder_name.required'      => __('requests.client_payment_method.holder_name_required'),
+            'expiration.required'       => __('requests.client_payment_method.expiration_required'),
+            'expiration.regex'          => __('requests.client_payment_method.expiration_format'),
+            'cvv.required'              => __('requests.client_payment_method.cvv_required'),
+            'cvv.min'                   => __('requests.client_payment_method.cvv_min'),
+            'cvv.max'                   => __('requests.client_payment_method.cvv_max'),
+            'last_four_digits.required' => __('requests.client_payment_method.last_four_required'),
+            'last_four_digits.size'     => __('requests.client_payment_method.last_four_size'),
         ];
     }
 

+ 1 - 1
app/Http/Requests/ClientProviderBlockRequest.php

@@ -55,7 +55,7 @@ class ClientProviderBlockRequest extends FormRequest
             'client_id.exists'     => __('validation.exists', ['attribute' => __('validation.attributes.client')]),
             'provider_id.required' => __('validation.required', ['attribute' => __('validation.attributes.provider')]),
             'provider_id.exists'   => __('validation.exists', ['attribute' => __('validation.attributes.provider')]),
-            'provider_id.unique'   => __('validation.client_provider_block.already_blocked'),
+            'provider_id.unique'   => __('validation.custom.client_provider_block.already_blocked'),
         ];
     }
 }

+ 2 - 2
app/Http/Requests/CustomScheduleAvailableRequest.php

@@ -34,8 +34,8 @@ class CustomScheduleAvailableRequest extends FormRequest
     public function messages(): array
     {
         return [
-            'provider_id.required' => 'O ID do prestador é obrigatório.',
-            'provider_id.exists'   => 'O prestador informado não existe.',
+            'provider_id.required' => __('requests.custom_schedule_available.provider_id_required'),
+            'provider_id.exists'   => __('requests.custom_schedule_available.provider_not_found'),
         ];
     }
 }

+ 3 - 3
app/Http/Requests/CustomScheduleRequest.php

@@ -56,9 +56,9 @@ class CustomScheduleRequest extends FormRequest
     public function messages(): array
     {
         return [
-            'max_price.gte'       => 'O preço máximo deve ser maior ou igual ao preço mínimo.',
-            'date.after_or_equal' => 'A data deve ser hoje ou uma data futura.',
-            'end_time.after'      => 'O horário de término deve ser posterior ao horário de início.',
+            'max_price.gte'       => __('requests.custom_schedule.max_price_gte'),
+            'date.after_or_equal' => __('requests.custom_schedule.date_after_or_equal'),
+            'end_time.after'      => __('requests.custom_schedule.end_time_after'),
         ];
     }
 }

+ 1 - 1
app/Http/Requests/ProviderClientBlockRequest.php

@@ -55,7 +55,7 @@ class ProviderClientBlockRequest extends FormRequest
             'provider_id.exists'   => __('validation.exists', ['attribute' => __('validation.attributes.provider')]),
             'client_id.required'   => __('validation.required', ['attribute' => __('validation.attributes.client')]),
             'client_id.exists'     => __('validation.exists', ['attribute' => __('validation.attributes.client')]),
-            'client_id.unique'     => __('validation.provider_client_block.already_blocked'),
+            'client_id.unique'     => __('validation.custom.provider_client_block.already_blocked'),
         ];
     }
 }

+ 20 - 19
app/Http/Requests/RegisterClientRequest.php

@@ -6,35 +6,36 @@ 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'          => 'required|string|max:20',
-            'name'           => 'sometimes|string|max:255|nullable',
             'code'           => 'required|string|max:6',
+            'email'          => 'required|string|email|max:255',
+            'name'           => 'required|string|max:255',
+            'phone'          => 'required|string|max:20',
             'document'       => 'required|string|max:20',
-            'zip_code'       => 'sometimes|string|max:20|nullable',
-            'address'        => 'sometimes|string|max:255|nullable',
+            'zip_code'       => 'required|string|max:20',
             'number'         => 'required|string|max:20',
+            'address'        => 'required|string|max:255',
             'district'       => 'required|string|max:255',
-            'complement'     => 'sometimes|string|max:255|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'           => 'required|string|max:255',
             'state'          => 'required|string|max:10',
-            'latitude'       => 'sometimes|numeric|nullable',
-            'longitude'      => 'sometimes|numeric|nullable',
+            'has_complement' => 'required|boolean',
+
+            'complement'     => 'sometimes|nullable|string|max:255',
+            'nickname'       => 'sometimes|nullable|string|max:255',
+            'instructions'   => 'sometimes|nullable|string|max:500',
+            'address_type'   => 'sometimes|nullable|string|in:home,commercial,other',
+            'latitude'       => 'sometimes|nullable|numeric',
+            'longitude'      => 'sometimes|nullable|numeric',
             'avatar'         => 'sometimes|nullable|file|image|mimes:jpg,jpeg,png,webp|max:5120',
         ];
     }
+
+    protected function prepareForValidation(): void
+    {
+        if (! $this->filled('has_complement')) {
+            $this->merge(['has_complement' => false]);
+        }
+    }
 }

+ 52 - 72
app/Http/Requests/RegisterProviderRequest.php

@@ -5,98 +5,78 @@ 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|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)],
+      'code'            => 'required|string|max:6',
+      'email'           => 'required|string|email|max:255',
+      'name'            => 'required|string|max:255',
+      'phone'           => 'required|string|max:20',
+      'document'        => 'required|string|max:20',
+      'rg'              => 'required|string|max:20',
+      'gender'          => 'required|string|in:'.implode(',', GenderEnum::toArray()),
+      'birth_date'      => 'required|date|before:today',
+
+      'zip_code'        => 'required|string|max:20',
+      'number'          => 'required|string|max:20',
+      'address'         => 'required|string|max:255',
+      'district'        => 'required|string|max:255',
+      'city'            => 'required|string|max:255',
+      'state'           => 'required|string|max:2',
+      'address_type'    => 'required|string|in:home,commercial,other',
+      'has_complement'  => 'required|boolean',
+
+      'daily_price_8h'  => "required|numeric|min:{$dailyPriceMin}|max:500",
+      'daily_price_6h'  => 'required|numeric|min:0',
+      'daily_price_4h'  => 'required|numeric|min:0',
+      'daily_price_2h'  => 'required|numeric|min:0',
+
+      'selfie'          => 'required|file|image|mimes:jpg,jpeg,png,webp|max:5120',
+      'document_front'  => 'required|file|image|mimes:jpg,jpeg,png,webp|max:10240',
+      'document_back'   => 'required|file|image|mimes:jpg,jpeg,png,webp|max:10240',
+
+      'working_days'          => 'required|array|min:1',
+      'working_days.*.day'    => 'required|integer|min:0|max:6',
+      'working_days.*.period' => 'required|string|in:'.implode(',', array_column(WorkingPeriodEnum::cases(), 'value')),
+
+      'complement'   => 'sometimes|nullable|string|max:255',
+      'nickname'     => 'sometimes|nullable|string|max:255',
+      'latitude'     => 'sometimes|nullable|numeric',
+      'longitude'    => 'sometimes|nullable|numeric',
+      'instructions' => 'sometimes|nullable|string',
 
-      'recipient_name'        => 'sometimes|string|max:255',
-      'recipient_email'       => 'sometimes|email|max:255',
-      'recipient_description' => 'sometimes|string',
-      'recipient_document'    => 'sometimes|string|max:20',
-      'recipient_type'        => ['sometimes', Rule::in(['individual', 'company'])],
+      //
 
-      'recipient_payment_mode' => ['sometimes', Rule::in(['bank_transfer'])],
+      'recipient_email'        => 'sometimes|string|email|max:255',
+      'recipient_name'         => 'sometimes|string|max:255',
+      'recipient_document'     => 'sometimes|string|max:20',
+      'recipient_description'  => 'sometimes|string',
+      'recipient_type'         => 'sometimes|string|in:individual,company',
+      'recipient_payment_mode' => 'sometimes|string|in:bank_transfer',
 
-      'recipient_default_bank_account'                     => 'sometimes|array',
+      'recipient_default_bank_account' => 'sometimes|array',
+ 
       'recipient_default_bank_account.holder_name'         => 'sometimes|string|max:255',
-      'recipient_default_bank_account.holder_type'         => ['sometimes', Rule::in(['individual', 'company'])],
       'recipient_default_bank_account.holder_document'     => 'sometimes|string|max:20',
+      'recipient_default_bank_account.holder_type'         => 'sometimes|string|in:individual,company',
       'recipient_default_bank_account.bank'                => 'sometimes|string|max:3',
       'recipient_default_bank_account.branch_number'       => 'sometimes|string|max:20',
-      'recipient_default_bank_account.branch_check_digit'  => 'sometimes|nullable|string|max:10',
+      'recipient_default_bank_account.branch_check_digit'  => 'sometimes|string|max:10',
       'recipient_default_bank_account.account_number'      => 'sometimes|string|max:20',
       'recipient_default_bank_account.account_check_digit' => 'sometimes|string|max:10',
-      'recipient_default_bank_account.type'                => ['sometimes', Rule::in(['checking', 'savings'])],
+      'recipient_default_bank_account.type'                => 'sometimes|string|in:checking,savings',
       'recipient_default_bank_account.metadata'            => 'sometimes|array',
-      'recipient_default_bank_account.pix_key'             => 'sometimes|nullable|string|max:255',
+      'recipient_default_bank_account.pix_key'             => 'sometimes|string|nullable|max:255',
 
       'recipient_metadata' => 'sometimes|array',
-
-      'zip_code'       => 'required|string|max:20',
-      'address'        => 'required|string|max:255',
-      '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'           => 'required|string|max:255',
-      'state'          => 'required|string|max:2',
-      'latitude'       => 'sometimes|numeric|nullable',
-      'longitude'      => 'sometimes|numeric|nullable',
-
-      'daily_price_8h' => "required|numeric|min:{$dailyPriceMin}|max:500",
-      'daily_price_6h' => 'required|numeric|min:0',
-      'daily_price_4h' => 'required|numeric|min:0',
-      'daily_price_2h' => 'required|numeric|min:0',
-
-      'services_types_ids' => 'sometimes|array',
-
-      'services_types_ids.*' => [
-        'integer',
-        Rule::exists('service_types', 'id')->where(function ($query) {
-          $query->whereNull('deleted_at')->where('is_active', true);
-        }),
-      ],
-
-      'service_types_ids' => 'sometimes|array',
-
-      'service_types_ids.*' => [
-        'integer',
-        Rule::exists('service_types', 'id')->where(function ($query) {
-          $query->whereNull('deleted_at')->where('is_active', true);
-        }),
-      ],
-
-      'working_days'          => 'required|array|min:1',
-      'working_days.*.day'    => 'required|integer|min:0|max:6',
-      'working_days.*.period' => ['required', Rule::in([WorkingPeriodEnum::MORNING->value, WorkingPeriodEnum::AFTERNOON->value])],
-
-      'selfie'          => 'required|file|image|mimes:jpg,jpeg,png,webp|max:5120',
-      'document_front'  => 'required|file|image|mimes:jpg,jpeg,png,webp|max:10240',
-      'document_back'   => 'required|file|image|mimes:jpg,jpeg,png,webp|max:10240',
+      
+      'services_types_ids'   => 'sometimes|array',
+      'services_types_ids.*' => 'integer|exists:service_types,id,deleted_at,NULL,is_active,1',
     ];
 
     return $rules;

+ 1 - 1
app/Http/Requests/ReviewImprovementRequest.php

@@ -42,7 +42,7 @@ class ReviewImprovementRequest extends FormRequest
     public function messages(): array
     {
         return [
-            'improvement_type_id.unique' => __('validation.review_improvement.already_exists'),
+            'improvement_type_id.unique' => __('validation.custom.review_improvement.already_exists'),
         ];
     }
 }

+ 20 - 20
app/Http/Requests/ScheduleRequest.php

@@ -46,26 +46,26 @@ class ScheduleRequest extends FormRequest
     public function messages(): array
     {
         return [
-            'client_id.required'     => 'O cliente é obrigatório.',
-            'client_id.exists'       => 'Cliente não encontrado.',
-            'provider_id.required'   => 'O prestador é obrigatório.',
-            'provider_id.exists'     => 'Prestador não encontrado.',
-            'address_id.required'    => 'O endereço é obrigatório.',
-            'address_id.exists'      => 'Endereço não encontrado.',
-            'date.required'          => 'A data é obrigatória.',
-            'date.date'              => 'Data inválida.',
-            'date.after_or_equal'    => 'A data deve ser hoje ou futura.',
-            'period_type.required'   => 'O período é obrigatório.',
-            'period_type.in'         => 'Período inválido.',
-            'start_time.required'    => 'O horário de início é obrigatório.',
-            'start_time.date_format' => 'Formato de horário inválido.',
-            'end_time.required'      => 'O horário de término é obrigatório.',
-            'end_time.date_format'   => 'Formato de horário inválido.',
-            'end_time.after'         => 'O horário de término deve ser após o horário de início.',
-            'total_amount.required'  => 'O valor total é obrigatório.',
-            'total_amount.numeric'   => 'O valor total deve ser numérico.',
-            'total_amount.min'       => 'O valor total deve ser maior ou igual a zero.',
-            'status.in'              => 'Status inválido.',
+            'client_id.required'     => __('requests.schedule.client_required'),
+            'client_id.exists'       => __('requests.schedule.client_not_found'),
+            'provider_id.required'   => __('requests.schedule.provider_required'),
+            'provider_id.exists'     => __('requests.schedule.provider_not_found'),
+            'address_id.required'    => __('requests.schedule.address_required'),
+            'address_id.exists'      => __('requests.schedule.address_not_found'),
+            'date.required'          => __('requests.schedule.date_required'),
+            'date.date'              => __('requests.schedule.invalid_date'),
+            'date.after_or_equal'    => __('requests.schedule.date_after_or_equal'),
+            'period_type.required'   => __('requests.schedule.period_required'),
+            'period_type.in'         => __('requests.schedule.invalid_period'),
+            'start_time.required'    => __('requests.schedule.start_time_required'),
+            'start_time.date_format' => __('requests.schedule.invalid_time_format'),
+            'end_time.required'      => __('requests.schedule.end_time_required'),
+            'end_time.date_format'   => __('requests.schedule.invalid_time_format'),
+            'end_time.after'         => __('requests.schedule.end_time_after'),
+            'total_amount.required'  => __('requests.schedule.total_amount_required'),
+            'total_amount.numeric'   => __('requests.schedule.total_amount_numeric'),
+            'total_amount.min'       => __('requests.schedule.total_amount_min'),
+            'status.in'              => __('requests.schedule.invalid_status'),
         ];
     }
 }

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

@@ -2,6 +2,7 @@
 
 namespace App\Http\Requests;
 
+use App\Enums\GenderEnum;
 use App\Enums\LanguageEnum;
 use App\Enums\UserTypeEnum;
 use Illuminate\Foundation\Http\FormRequest;
@@ -25,6 +26,7 @@ class UserRequest extends FormRequest
             'type'     => ['sometimes', Rule::enum(UserTypeEnum::class)],
             'language' => ['sometimes', Rule::enum(LanguageEnum::class)],
             'phone'    => 'sometimes|string|nullable',
+            'gender'   => 'sometimes|string|in:'.implode(',', GenderEnum::toArray()),
         ];
 
         if ($this->isMethod('post')) {

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

@@ -22,6 +22,7 @@ class UserResource extends JsonResource
       'name'        => $this->name,
       'email'       => $this->email,
       'phone'       => $this->phone,
+      'gender'      => $this->provider?->gender?->value,
       'language'    => $this->language,
       'type'        => $this->type,
       'provider_id' => $this->provider?->id,

+ 4 - 4
app/Services/ServicePackageItemService.php

@@ -86,13 +86,13 @@ class ServicePackageItemService
 
         if ($servicePackage->status !== ServicePackageStatusEnum::OPEN) {
             throw ValidationException::withMessages([
-                'service_package_id' => 'Somente pacotes abertos podem ser alterados.',
+                'service_package_id' => __('messages.service_package_must_be_open_for_changes'),
             ]);
         }
 
         if ($schedule->client_id !== $servicePackage->client_id) {
             throw ValidationException::withMessages([
-                'schedule_id' => 'O agendamento precisa pertencer ao mesmo cliente do pacote.',
+                'schedule_id' => __('messages.service_package_schedule_same_client'),
             ]);
         }
 
@@ -109,7 +109,7 @@ class ServicePackageItemService
 
         if ($belongsToAnotherPackage) {
             throw ValidationException::withMessages([
-                'schedule_id' => 'O agendamento já pertence a outro pacote.',
+                'schedule_id' => __('messages.service_package_schedule_already_assigned'),
             ]);
         }
 
@@ -125,7 +125,7 @@ class ServicePackageItemService
 
         if ($hasActivePayment) {
             throw ValidationException::withMessages([
-                'schedule_id' => 'O agendamento já possui um pagamento e não pode ser adicionado ao pacote.',
+                'schedule_id' => __('messages.service_package_schedule_has_active_payment'),
             ]);
         }
 

+ 2 - 2
app/Services/ServicePackageService.php

@@ -46,7 +46,7 @@ class ServicePackageService
 
             if ($hasDifferentProvider) {
                 throw ValidationException::withMessages([
-                    'provider_id' => 'O prestador não corresponde aos agendamentos existentes no pacote.',
+                    'provider_id' => __('messages.service_package_provider_mismatch'),
                 ]);
             }
         }
@@ -58,7 +58,7 @@ class ServicePackageService
 
             if ($hasDifferentClient) {
                 throw ValidationException::withMessages([
-                    'client_id' => 'O cliente não corresponde aos agendamentos existentes no pacote.',
+                    'client_id' => __('messages.service_package_client_mismatch'),
                 ]);
             }
         }

+ 24 - 6
app/Services/UserService.php

@@ -11,6 +11,7 @@ use Illuminate\Http\UploadedFile;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Log;
+use Illuminate\Validation\ValidationException;
 
 class UserService
 {
@@ -33,15 +34,32 @@ class UserService
 
     public function update(int $id, array $data): ?User
     {
-        $model = $this->findById($id);
+        return DB::transaction(function () use ($id, $data): ?User {
+            $model = User::with('provider')->find($id);
 
-        if (! $model) {
-            return null;
-        }
+            if (! $model) {
+                return null;
+            }
+
+            $hasGender = array_key_exists('gender', $data);
+            $gender    = data_get($data, 'gender');
 
-        $model->update($data);
+            unset($data['gender']);
+
+            $model->update($data);
+
+            if ($hasGender) {
+                if (! $model->provider) {
+                    throw ValidationException::withMessages([
+                        'gender' => __('messages.gender_only_for_providers'),
+                    ]);
+                }
+
+                $model->provider->update(['gender' => $gender]);
+            }
 
-        return $model->fresh();
+            return $model->fresh(['provider.profileMedia', 'client.profileMedia']);
+        });
     }
 
     public function delete(int $id): bool

+ 7 - 0
lang/en/messages.php

@@ -64,4 +64,11 @@ return [
     'provider_refused'                             => 'Provider refused.',
     'opportunity_refused'                          => 'Opportunity refused.',
     'withdrawal_requested'                         => 'Withdrawal requested successfully.',
+    'service_package_provider_mismatch'             => 'The provider does not match the existing appointments in the service package.',
+    'service_package_client_mismatch'               => 'The client does not match the existing appointments in the service package.',
+    'service_package_must_be_open_for_changes'      => 'Only open service packages may be changed.',
+    'service_package_schedule_same_client'          => 'The appointment must belong to the same client as the service package.',
+    'service_package_schedule_already_assigned'     => 'The appointment already belongs to another service package.',
+    'service_package_schedule_has_active_payment'   => 'The appointment already has a payment and cannot be added to the service package.',
+    'gender_only_for_providers'                     => 'Gender can only be changed for provider users.',
 ];

+ 62 - 0
lang/en/requests.php

@@ -0,0 +1,62 @@
+<?php
+
+return [
+    'client_payment_method' => [
+        'client_required'      => 'The client is required.',
+        'client_not_found'     => 'Client not found.',
+        'token_required'       => 'The card token is required.',
+        'card_number_required' => 'The card number is required.',
+        'card_number_min'      => 'The card number must have at least 13 digits.',
+        'card_number_max'      => 'The card number must have at most 19 digits.',
+        'holder_name_required' => 'The cardholder name is required.',
+        'expiration_required'  => 'The expiration date is required.',
+        'expiration_format'    => 'The expiration date must use the MM/YYYY format.',
+        'cvv_required'         => 'The CVV is required.',
+        'cvv_min'              => 'The CVV must have at least 3 digits.',
+        'cvv_max'              => 'The CVV must have at most 4 digits.',
+        'last_four_required'   => 'The last 4 digits are required.',
+        'last_four_size'       => 'The value must have exactly 4 digits.',
+    ],
+
+    'client_favorite_provider' => [
+        'client_required'    => 'The client is required.',
+        'client_not_found'   => 'Client not found.',
+        'provider_required'  => 'The provider is required.',
+        'provider_not_found' => 'Provider not found.',
+        'already_favorite'   => 'This provider is already a favorite.',
+        'notes_max'          => 'The notes may not exceed 1000 characters.',
+    ],
+
+    'custom_schedule_available' => [
+        'provider_id_required' => 'The provider ID is required.',
+        'provider_not_found'   => 'The selected provider does not exist.',
+    ],
+
+    'custom_schedule' => [
+        'max_price_gte'       => 'The maximum price must be greater than or equal to the minimum price.',
+        'date_after_or_equal' => 'The date must be today or a future date.',
+        'end_time_after'      => 'The end time must be after the start time.',
+    ],
+
+    'schedule' => [
+        'client_required'       => 'The client is required.',
+        'client_not_found'      => 'Client not found.',
+        'provider_required'     => 'The provider is required.',
+        'provider_not_found'    => 'Provider not found.',
+        'address_required'      => 'The address is required.',
+        'address_not_found'     => 'Address not found.',
+        'date_required'         => 'The date is required.',
+        'invalid_date'          => 'Invalid date.',
+        'date_after_or_equal'   => 'The date must be today or a future date.',
+        'period_required'       => 'The period is required.',
+        'invalid_period'        => 'Invalid period.',
+        'start_time_required'   => 'The start time is required.',
+        'invalid_time_format'   => 'Invalid time format.',
+        'end_time_required'     => 'The end time is required.',
+        'end_time_after'        => 'The end time must be after the start time.',
+        'total_amount_required' => 'The total amount is required.',
+        'total_amount_numeric'  => 'The total amount must be numeric.',
+        'total_amount_min'      => 'The total amount must be greater than or equal to zero.',
+        'invalid_status'        => 'Invalid status.',
+    ],
+];

+ 3 - 1
lang/en/validation.php

@@ -249,6 +249,8 @@ return [
     */
 
     'attributes' => [
-        'gender' => 'gender',
+        'client'   => 'client',
+        'gender'   => 'gender',
+        'provider' => 'provider',
     ],
 ];

+ 7 - 0
lang/es/messages.php

@@ -64,4 +64,11 @@ return [
     'provider_refused'                             => 'Prestador rechazado.',
     'opportunity_refused'                          => 'Oportunidad rechazada.',
     'withdrawal_requested'                         => 'Retiro solicitado con éxito.',
+    'service_package_provider_mismatch'             => 'El prestador no coincide con los servicios programados existentes en el paquete.',
+    'service_package_client_mismatch'               => 'El cliente no coincide con los servicios programados existentes en el paquete.',
+    'service_package_must_be_open_for_changes'      => 'Solo se pueden modificar los paquetes de servicios abiertos.',
+    'service_package_schedule_same_client'          => 'El servicio programado debe pertenecer al mismo cliente que el paquete.',
+    'service_package_schedule_already_assigned'     => 'El servicio programado ya pertenece a otro paquete.',
+    'service_package_schedule_has_active_payment'   => 'El servicio programado ya tiene un pago y no puede añadirse al paquete.',
+    'gender_only_for_providers'                     => 'El género solo puede modificarse para usuarios prestadores.',
 ];

+ 62 - 0
lang/es/requests.php

@@ -0,0 +1,62 @@
+<?php
+
+return [
+    'client_payment_method' => [
+        'client_required'      => 'El cliente es obligatorio.',
+        'client_not_found'     => 'Cliente no encontrado.',
+        'token_required'       => 'El token de la tarjeta es obligatorio.',
+        'card_number_required' => 'El número de la tarjeta es obligatorio.',
+        'card_number_min'      => 'El número de la tarjeta debe tener al menos 13 dígitos.',
+        'card_number_max'      => 'El número de la tarjeta debe tener como máximo 19 dígitos.',
+        'holder_name_required' => 'El nombre del titular es obligatorio.',
+        'expiration_required'  => 'La fecha de vencimiento es obligatoria.',
+        'expiration_format'    => 'La fecha de vencimiento debe tener el formato MM/YYYY.',
+        'cvv_required'         => 'El CVV es obligatorio.',
+        'cvv_min'              => 'El CVV debe tener al menos 3 dígitos.',
+        'cvv_max'              => 'El CVV debe tener como máximo 4 dígitos.',
+        'last_four_required'   => 'Los últimos 4 dígitos son obligatorios.',
+        'last_four_size'       => 'El valor debe tener exactamente 4 dígitos.',
+    ],
+
+    'client_favorite_provider' => [
+        'client_required'    => 'El cliente es obligatorio.',
+        'client_not_found'   => 'Cliente no encontrado.',
+        'provider_required'  => 'El prestador es obligatorio.',
+        'provider_not_found' => 'Prestador no encontrado.',
+        'already_favorite'   => 'Este prestador ya está en favoritos.',
+        'notes_max'          => 'Las observaciones no pueden superar los 1000 caracteres.',
+    ],
+
+    'custom_schedule_available' => [
+        'provider_id_required' => 'El ID del prestador es obligatorio.',
+        'provider_not_found'   => 'El prestador informado no existe.',
+    ],
+
+    'custom_schedule' => [
+        'max_price_gte'       => 'El precio máximo debe ser mayor o igual que el precio mínimo.',
+        'date_after_or_equal' => 'La fecha debe ser hoy o una fecha futura.',
+        'end_time_after'      => 'La hora de finalización debe ser posterior a la hora de inicio.',
+    ],
+
+    'schedule' => [
+        'client_required'       => 'El cliente es obligatorio.',
+        'client_not_found'      => 'Cliente no encontrado.',
+        'provider_required'     => 'El prestador es obligatorio.',
+        'provider_not_found'    => 'Prestador no encontrado.',
+        'address_required'      => 'La dirección es obligatoria.',
+        'address_not_found'     => 'Dirección no encontrada.',
+        'date_required'         => 'La fecha es obligatoria.',
+        'invalid_date'          => 'Fecha inválida.',
+        'date_after_or_equal'   => 'La fecha debe ser hoy o futura.',
+        'period_required'       => 'El período es obligatorio.',
+        'invalid_period'        => 'Período inválido.',
+        'start_time_required'   => 'La hora de inicio es obligatoria.',
+        'invalid_time_format'   => 'Formato de hora inválido.',
+        'end_time_required'     => 'La hora de finalización es obligatoria.',
+        'end_time_after'        => 'La hora de finalización debe ser posterior a la hora de inicio.',
+        'total_amount_required' => 'El valor total es obligatorio.',
+        'total_amount_numeric'  => 'El valor total debe ser numérico.',
+        'total_amount_min'      => 'El valor total debe ser mayor o igual que cero.',
+        'invalid_status'        => 'Estado inválido.',
+    ],
+];

+ 3 - 1
lang/es/validation.php

@@ -250,6 +250,8 @@ return [
     */
 
     'attributes' => [
-        'gender' => 'género',
+        'client'   => 'cliente',
+        'gender'   => 'género',
+        'provider' => 'prestador',
     ],
 ];

+ 7 - 0
lang/pt/messages.php

@@ -64,4 +64,11 @@ return [
     'provider_refused'                             => 'Prestador recusado.',
     'opportunity_refused'                          => 'Oportunidade recusada.',
     'withdrawal_requested'                         => 'Saque solicitado com sucesso.',
+    'service_package_provider_mismatch'             => 'O prestador não corresponde aos agendamentos existentes no pacote.',
+    'service_package_client_mismatch'               => 'O cliente não corresponde aos agendamentos existentes no pacote.',
+    'service_package_must_be_open_for_changes'      => 'Somente pacotes abertos podem ser alterados.',
+    'service_package_schedule_same_client'          => 'O agendamento precisa pertencer ao mesmo cliente do pacote.',
+    'service_package_schedule_already_assigned'     => 'O agendamento já pertence a outro pacote.',
+    'service_package_schedule_has_active_payment'   => 'O agendamento já possui um pagamento e não pode ser adicionado ao pacote.',
+    'gender_only_for_providers'                     => 'O gênero só pode ser alterado para usuários prestadores.',
 ];

+ 62 - 0
lang/pt/requests.php

@@ -0,0 +1,62 @@
+<?php
+
+return [
+    'client_payment_method' => [
+        'client_required'      => 'O cliente é obrigatório.',
+        'client_not_found'     => 'Cliente não encontrado.',
+        'token_required'       => 'O token do cartão é obrigatório.',
+        'card_number_required' => 'O número do cartão é obrigatório.',
+        'card_number_min'      => 'O número do cartão deve ter no mínimo 13 dígitos.',
+        'card_number_max'      => 'O número do cartão deve ter no máximo 19 dígitos.',
+        'holder_name_required' => 'O nome do titular é obrigatório.',
+        'expiration_required'  => 'A data de validade é obrigatória.',
+        'expiration_format'    => 'A data de validade deve estar no formato MM/YYYY.',
+        'cvv_required'         => 'O CVV é obrigatório.',
+        'cvv_min'              => 'O CVV deve ter no mínimo 3 dígitos.',
+        'cvv_max'              => 'O CVV deve ter no máximo 4 dígitos.',
+        'last_four_required'   => 'Os últimos 4 dígitos são obrigatórios.',
+        'last_four_size'       => 'Devem ser exatamente 4 dígitos.',
+    ],
+
+    'client_favorite_provider' => [
+        'client_required'    => 'O cliente é obrigatório.',
+        'client_not_found'   => 'Cliente não encontrado.',
+        'provider_required'  => 'O prestador é obrigatório.',
+        'provider_not_found' => 'Prestador não encontrado.',
+        'already_favorite'   => 'Este prestador já está favoritado.',
+        'notes_max'          => 'As observações não podem exceder 1000 caracteres.',
+    ],
+
+    'custom_schedule_available' => [
+        'provider_id_required' => 'O ID do prestador é obrigatório.',
+        'provider_not_found'   => 'O prestador informado não existe.',
+    ],
+
+    'custom_schedule' => [
+        'max_price_gte'       => 'O preço máximo deve ser maior ou igual ao preço mínimo.',
+        'date_after_or_equal' => 'A data deve ser hoje ou uma data futura.',
+        'end_time_after'      => 'O horário de término deve ser posterior ao horário de início.',
+    ],
+
+    'schedule' => [
+        'client_required'       => 'O cliente é obrigatório.',
+        'client_not_found'      => 'Cliente não encontrado.',
+        'provider_required'     => 'O prestador é obrigatório.',
+        'provider_not_found'    => 'Prestador não encontrado.',
+        'address_required'      => 'O endereço é obrigatório.',
+        'address_not_found'     => 'Endereço não encontrado.',
+        'date_required'         => 'A data é obrigatória.',
+        'invalid_date'          => 'Data inválida.',
+        'date_after_or_equal'   => 'A data deve ser hoje ou futura.',
+        'period_required'       => 'O período é obrigatório.',
+        'invalid_period'        => 'Período inválido.',
+        'start_time_required'   => 'O horário de início é obrigatório.',
+        'invalid_time_format'   => 'Formato de horário inválido.',
+        'end_time_required'     => 'O horário de término é obrigatório.',
+        'end_time_after'        => 'O horário de término deve ser após o horário de início.',
+        'total_amount_required' => 'O valor total é obrigatório.',
+        'total_amount_numeric'  => 'O valor total deve ser numérico.',
+        'total_amount_min'      => 'O valor total deve ser maior ou igual a zero.',
+        'invalid_status'        => 'Status inválido.',
+    ],
+];

+ 3 - 1
lang/pt/validation.php

@@ -250,6 +250,8 @@ return [
     */
 
     'attributes' => [
-        'gender' => 'gênero',
+        'client'   => 'cliente',
+        'gender'   => 'gênero',
+        'provider' => 'prestador',
     ],
 ];