瀏覽代碼

feat: :sparkles: feat (landingpage e verificacao automatica cadastro) criado novos campos dinamicos na landingpage e aprovacao automatica do associado

foram criados 4 novos campos na landingpage: visao, missao, valores e historia, preenchiveis no sistema web, e tambem foi finalizado o fluxo de cadastro -> aprovacao -> primeiro acesso e efetivacao do usuario, criando a aprovacao automatica caso o primeiro acesso seja do usuario que foi registrado pela importacao de excel

fase:dev | origin:escopo
Gustavo Zanatta 6 小時之前
父節點
當前提交
860433f3c3

+ 4 - 0
app/Http/Controllers/AuthController.php

@@ -39,6 +39,10 @@ class AuthController extends Controller
             return $this->errorResponse(message: __("auth.first_access_required"), code: 403);
         }
 
+        if (isset($result["error"]) && $result["error"] === "pending_approval") {
+            return $this->errorResponse(message: __("auth.pending_approval"), code: 403);
+        }
+
         if (isset($result["error"]) && $result["error"] === "inactive") {
             return $this->errorResponse(message: __("auth.inactive"), code: 403);
         }

+ 12 - 4
app/Http/Controllers/FirstAccessController.php

@@ -16,8 +16,8 @@ class FirstAccessController extends Controller
     {
         $result = $this->service->check($request->validated()['registration']);
 
-        $message = $result['status'] === FirstAccessService::STATUS_DONE
-            ? __('messages.first_access.already_done')
+        $message = in_array($result['status'], FirstAccessService::BLOCKING_STATUSES, true)
+            ? $this->service->blockedMessage($result['status'])
             : null;
 
         return $this->successResponse(payload: $result, message: $message);
@@ -30,9 +30,17 @@ class FirstAccessController extends Controller
             $request->file('photo'),
         );
 
+        $canLogin = $user->canLogin();
+
         return $this->successResponse(
-            payload: new UserResource($user),
-            message: __('messages.first_access.register_success'),
+            payload: [
+                'user'      => new UserResource($user),
+                'can_login' => $canLogin,
+                'status'    => $user->status,
+            ],
+            message: $canLogin
+                ? __('messages.first_access.register_success')
+                : __('messages.first_access.register_pending_approval'),
             code: 201,
         );
     }

+ 4 - 0
app/Http/Requests/CompanySettingRequest.php

@@ -17,6 +17,10 @@ class CompanySettingRequest extends FormRequest
             'stat2_label'       => 'sometimes|nullable|string|max:100',
             'stat3_value'       => 'sometimes|nullable|string|max:50',
             'stat3_label'       => 'sometimes|nullable|string|max:100',
+            'about_vision'      => 'sometimes|nullable|string|max:2000',
+            'about_mission'     => 'sometimes|nullable|string|max:2000',
+            'about_values'      => 'sometimes|nullable|string|max:2000',
+            'about_history'     => 'sometimes|nullable|string|max:10000',
             'contact_email'     => 'sometimes|nullable|email|max:255',
             'contact_phone'     => 'sometimes|nullable|string|max:50',
             'contact_location'  => 'sometimes|nullable|string|max:255',

+ 2 - 1
app/Http/Requests/FirstAccessRegisterRequest.php

@@ -18,7 +18,8 @@ class FirstAccessRegisterRequest extends FormRequest
         return [
             'token'        => 'required|string',
             'registration' => ['required', 'string', 'max:255', Rule::unique('users', 'registration')->ignore($userId)],
-            'name'         => 'required|string|max:255',
+            'name'         => 'required|string|max:120',
+            'last_name'    => 'required|string|max:120',
             'cpf'          => ['required', 'string', 'max:14', Rule::unique('users', 'cpf')->ignore($userId)],
             'email'        => ['required', 'email', 'max:255', Rule::unique('users', 'email')->ignore($userId)],
             'phone'        => 'required|string|max:20',

+ 18 - 2
app/Http/Requests/LandingPageRegisterRequest.php

@@ -2,6 +2,8 @@
 
 namespace App\Http\Requests;
 
+use App\Enums\UserStatusEnum;
+use App\Models\User;
 use Illuminate\Foundation\Http\FormRequest;
 
 class LandingPageRegisterRequest extends FormRequest
@@ -9,7 +11,8 @@ class LandingPageRegisterRequest extends FormRequest
     public function rules(): array
     {
         return [
-            'name'         => 'required|string|max:255',
+            'name'         => 'required|string|max:120',
+            'last_name'    => 'required|string|max:120',
             'cpf'          => 'required|string|max:14|unique:users,cpf',
             'registration' => 'required|string|max:255|unique:users,registration',
             'email'        => 'required|email|unique:users,email',
@@ -22,7 +25,20 @@ class LandingPageRegisterRequest extends FormRequest
     public function messages(): array
     {
         return [
-            'registration.unique' => __('messages.landing.registration_taken'),
+            'registration.unique' => $this->registrationTakenMessage(),
+            'cpf.unique'          => __('messages.landing.cpf_taken'),
+            'email.unique'        => __('messages.landing.email_taken'),
         ];
     }
+
+    private function registrationTakenMessage(): string
+    {
+        $user = User::where('registration', $this->input('registration'))->first();
+
+        return match (true) {
+            (bool) $user?->first_access_completed_at   => __('messages.landing.registration_first_access_done'),
+            $user?->status === UserStatusEnum::PENDING => __('messages.landing.registration_pending_approval'),
+            default                                    => __('messages.landing.registration_taken'),
+        };
+    }
 }

+ 13 - 5
app/Http/Requests/UserRequest.php

@@ -14,11 +14,13 @@ class UserRequest extends FormRequest
 {
     public function rules(): array
     {
-        $emailUnique = 'unique:users,email';
-        $cpfUnique   = 'unique:users,cpf';
+        $emailUnique        = 'unique:users,email';
+        $cpfUnique          = 'unique:users,cpf';
+        $registrationUnique = 'unique:users,registration';
         if ($this->isMethod('put') && $this->route('id')) {
-            $emailUnique = 'unique:users,email,' . $this->route('id');
-            $cpfUnique   = 'unique:users,cpf,' . $this->route('id');
+            $emailUnique        = 'unique:users,email,' . $this->route('id');
+            $cpfUnique          = 'unique:users,cpf,' . $this->route('id');
+            $registrationUnique = 'unique:users,registration,' . $this->route('id');
         }
 
         $rules = [
@@ -29,7 +31,7 @@ class UserRequest extends FormRequest
             'type'           => ['sometimes', Rule::enum(UserTypeEnum::class)],
             'language'       => ['sometimes', Rule::enum(LanguageEnum::class)],
             'cpf'            => ['sometimes', 'nullable', 'string', 'max:14', $cpfUnique],
-            'registration'   => 'sometimes|nullable|string|max:50',
+            'registration'   => ['sometimes', 'nullable', 'string', 'max:50', $registrationUnique],
             'status'         => ['sometimes', Rule::enum(UserStatusEnum::class)],
             'admission_date' => 'sometimes|nullable|date',
             'expiry_date'    => 'sometimes|nullable|date',
@@ -41,6 +43,12 @@ class UserRequest extends FormRequest
             $rules['name']     = 'required|string|max:255';
             $rules['email']    = ['required', 'email', $emailUnique];
             $rules['password'] = 'required|string|min:6';
+
+            if ($this->input('type') === UserTypeEnum::ASSOCIADO->value) {
+                $rules['password']     = 'nullable|string|min:6';
+                $rules['registration'] = ['required', 'string', 'max:50', $registrationUnique];
+            }
+
             if (!$this->has('language')) {
                 $this->merge(['language' => LanguageEnum::PORTUGUESE->value]);
             }

+ 4 - 0
app/Http/Resources/CompanySettingResource.php

@@ -25,6 +25,10 @@ class CompanySettingResource extends JsonResource
             'stat2_label'            => $this->stat2_label,
             'stat3_value'            => $this->stat3_value,
             'stat3_label'            => $this->stat3_label,
+            'about_vision'           => $this->about_vision,
+            'about_mission'          => $this->about_mission,
+            'about_values'           => $this->about_values,
+            'about_history'          => $this->about_history,
             'contact_email'          => $this->contact_email,
             'contact_phone'          => $this->contact_phone,
             'contact_location'       => $this->contact_location,

+ 26 - 0
app/Models/User.php

@@ -99,6 +99,32 @@ class User extends Authenticatable
         return $this->type === UserTypeEnum::PARCEIRO;
     }
 
+    public function loginBlockReason(): ?string
+    {
+        if ($this->isAssociado()) {
+            return match (true) {
+                $this->status === UserStatusEnum::REFUSED  => 'refused',
+                is_null($this->first_access_completed_at)  => 'first_access_required',
+                $this->status === UserStatusEnum::PENDING  => 'pending_approval',
+                default                                    => null,
+            };
+        }
+
+        if ($this->isParceiro() && $this->status === UserStatusEnum::INACTIVE) {
+            return 'inactive';
+        }
+
+        return null;
+    }
+
+    /**
+     * Indica se o usuário já pode ser autenticado (usado ao concluir o primeiro acesso).
+     */
+    public function canLogin(): bool
+    {
+        return $this->loginBlockReason() === null;
+    }
+
     /**
      * Create a new access token for the user.
      */

+ 2 - 11
app/Services/AuthService.php

@@ -5,7 +5,6 @@ namespace App\Services;
 use App\Models\User;
 use App\Models\PersonalAccessToken;
 use App\Models\UserAccessLog;
-use App\Enums\UserStatusEnum;
 use App\Enums\UserTypeEnum;
 use Carbon\Carbon;
 use Illuminate\Support\Facades\Auth;
@@ -25,16 +24,8 @@ class AuthService
             return null;
         }
 
-        if ($user->type === UserTypeEnum::ASSOCIADO && $user->status === UserStatusEnum::REFUSED) {
-            return ["error" => "refused"];
-        }
-
-        if ($user->type === UserTypeEnum::PARCEIRO && $user->status === UserStatusEnum::INACTIVE) {
-            return ["error" => "inactive"];
-        }
-
-        if ($user->type === UserTypeEnum::ASSOCIADO && is_null($user->first_access_completed_at)) {
-            return ["error" => "first_access_required"];
+        if ($blockReason = $user->loginBlockReason()) {
+            return ["error" => $blockReason];
         }
 
         Auth::login($user);

+ 74 - 33
app/Services/FirstAccessService.php

@@ -2,7 +2,6 @@
 
 namespace App\Services;
 
-use App\Enums\LanguageEnum;
 use App\Enums\UserStatusEnum;
 use App\Enums\UserTypeEnum;
 use App\Models\User;
@@ -15,9 +14,19 @@ use Illuminate\Validation\ValidationException;
 
 class FirstAccessService
 {
-    public const STATUS_NOT_FOUND = 'not_found';
-    public const STATUS_PENDING   = 'pending_first_access';
-    public const STATUS_DONE      = 'already_done';
+    public const STATUS_NOT_FOUND    = 'not_found';
+    public const STATUS_PENDING      = 'pending_first_access';
+    public const STATUS_DONE         = 'already_done';
+    public const STATUS_NOT_APPROVED = 'not_approved';
+    public const STATUS_REFUSED      = 'refused';
+
+    /** Situações em que o crachá não libera o formulário de primeiro acesso. */
+    public const BLOCKING_STATUSES = [
+        self::STATUS_NOT_FOUND,
+        self::STATUS_DONE,
+        self::STATUS_NOT_APPROVED,
+        self::STATUS_REFUSED,
+    ];
 
     private const TOKEN_TTL_MINUTES = 15;
 
@@ -27,27 +36,47 @@ class FirstAccessService
 
     /**
      * Consulta um crachá e diz se o associado pode seguir para o formulário de primeiro acesso.
+     * Só crachá já liberado pela administração passa: cadastro inexistente, pendente de aprovação
+     * ou recusado é bloqueado aqui, antes de o formulário abrir.
      */
     public function check(string $registration): array
     {
         $user = $this->findByRegistration($registration);
 
-        if ($user?->first_access_completed_at) {
-            return ['status' => self::STATUS_DONE];
+        if ($blockedStatus = $this->blockingStatus($user)) {
+            return ['status' => $blockedStatus];
         }
 
         return [
-            'status'         => $user ? self::STATUS_PENDING : self::STATUS_NOT_FOUND,
+            'status'         => self::STATUS_PENDING,
             'token'          => $this->issueToken($registration),
             'registration'   => $registration,
-            'user'           => $user ? $this->prefill($user) : null,
-            'missing_fields' => $user ? $this->missingFields($user) : self::PROFILE_FIELDS,
+            'user'           => $this->prefill($user),
+            'missing_fields' => $this->missingFields($user),
         ];
     }
 
-    /**
-     * Conclui o primeiro acesso: cria o associado (ou completa o existente), define a senha e a foto.
-     */
+    private function blockingStatus(?User $user): ?string
+    {
+        return match (true) {
+            !$user                                          => self::STATUS_NOT_FOUND,
+            (bool) $user->first_access_completed_at         => self::STATUS_DONE,
+            $user->status === UserStatusEnum::REFUSED       => self::STATUS_REFUSED,
+            $user->status === UserStatusEnum::PENDING       => self::STATUS_NOT_APPROVED,
+            default                                         => null,
+        };
+    }
+
+    public function blockedMessage(string $status): string
+    {
+        return match ($status) {
+            self::STATUS_DONE         => __('messages.first_access.already_done'),
+            self::STATUS_NOT_APPROVED => __('messages.first_access.not_approved'),
+            self::STATUS_REFUSED      => __('messages.first_access.refused'),
+            default                   => __('messages.first_access.not_found'),
+        };
+    }
+
     public function register(array $data, ?UploadedFile $photo = null): User
     {
         $registration = $data['registration'];
@@ -56,34 +85,22 @@ class FirstAccessService
 
         $user = $this->findByRegistration($registration);
 
-        if ($user?->first_access_completed_at) {
+        if ($blockedStatus = $this->blockingStatus($user)) {
             throw ValidationException::withMessages([
-                'registration' => __('messages.first_access.already_done'),
+                'registration' => $this->blockedMessage($blockedStatus),
             ]);
         }
 
-        return DB::transaction(function () use ($data, $photo, $registration, $user): User {
-            if ($user) {
-                // Associado já existente (importação ou landing page): completa apenas o que falta,
-                // sem sobrescrever o que a administração já cadastrou, e mantém o status atual.
-                foreach (self::PROFILE_FIELDS as $field) {
-                    if ($this->isEmpty($user->{$field})) {
-                        $user->{$field} = $data[$field];
-                    }
-                }
-            } else {
-                $user = new User([
-                    'registration' => $registration,
-                    'type'         => UserTypeEnum::ASSOCIADO,
-                    'status'       => UserStatusEnum::PENDING,
-                    'language'     => LanguageEnum::PORTUGUESE,
-                ]);
-
-                foreach (self::PROFILE_FIELDS as $field) {
+        $data['name'] = $this->fullName($data['name'], $data['last_name'] ?? null);
+
+        return DB::transaction(function () use ($data, $photo, $user): User {
+            foreach (self::PROFILE_FIELDS as $field) {
+                if ($this->isEmpty($user->{$field})) {
                     $user->{$field} = $data[$field];
                 }
             }
 
+            $user->name                      = $data['name'];
             $user->password                  = $data['password'];
             $user->first_access_completed_at = now();
             $user->save();
@@ -106,8 +123,11 @@ class FirstAccessService
 
     private function prefill(User $user): array
     {
+        [$name, $lastName] = $this->splitName($user->name);
+
         return [
-            'name'        => $user->name,
+            'name'        => $name,
+            'last_name'   => $lastName,
             'cpf'         => $user->cpf,
             'email'       => $user->email,
             'phone'       => $user->phone,
@@ -126,6 +146,10 @@ class FirstAccessService
             fn(string $field): bool => $this->isEmpty($user->{$field}),
         ));
 
+        if ($this->isEmpty($this->splitName($user->name)[1])) {
+            $missing[] = 'last_name';
+        }
+
         if (!$user->photo_path) {
             $missing[] = 'photo';
         }
@@ -133,6 +157,23 @@ class FirstAccessService
         return $missing;
     }
 
+    /**
+     * Quebra o nome gravado em primeiro nome + sobrenome para preencher o formulário.
+     *
+     * @return array{0: string, 1: string}
+     */
+    private function splitName(?string $name): array
+    {
+        $parts = preg_split('/\s+/', trim((string) $name), 2, PREG_SPLIT_NO_EMPTY) ?: [];
+
+        return [$parts[0] ?? '', $parts[1] ?? ''];
+    }
+
+    private function fullName(string $name, ?string $lastName): string
+    {
+        return trim(preg_replace('/\s+/', ' ', $name . ' ' . $lastName));
+    }
+
     private function isEmpty(mixed $value): bool
     {
         return $value === null || $value === '';

+ 6 - 1
app/Services/LandingPageService.php

@@ -13,7 +13,7 @@ class LandingPageService
     public function registerUser(array $data): User
     {
         return User::create([
-            'name'         => $data['name'],
+            'name'         => $this->fullName($data['name'], $data['last_name'] ?? null),
             'email'        => $data['email'],
             'cpf'          => $data['cpf'],
             'registration' => $data['registration'],
@@ -26,4 +26,9 @@ class LandingPageService
             'password'     => bcrypt(Str::random(32)),
         ]);
     }
+
+    private function fullName(string $name, ?string $lastName): string
+    {
+        return trim(preg_replace('/\s+/', ' ', $name . ' ' . $lastName));
+    }
 }

+ 9 - 0
app/Services/UserService.php

@@ -7,6 +7,7 @@ use App\Enums\UserTypeEnum;
 use App\Models\User;
 use Illuminate\Database\Eloquent\Collection;
 use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Str;
 
 class UserService
 {
@@ -88,6 +89,10 @@ class UserService
 
     public function create(array $data): User
     {
+        if (empty($data['password'])) {
+            $data['password'] = Str::random(32);
+        }
+
         return User::create($data);
     }
 
@@ -99,6 +104,10 @@ class UserService
             return null;
         }
 
+        if (array_key_exists('password', $data) && empty($data['password'])) {
+            unset($data['password']);
+        }
+
         if (isset($data['status'])) {
             $newStatus = $data['status'] instanceof UserStatusEnum
                 ? $data['status']

+ 3 - 3
config/app.php

@@ -78,11 +78,11 @@ return [
     |
     */
 
-    'locale' => env('APP_LOCALE', 'en'),
+    'locale' => env('APP_LOCALE', 'pt'),
 
-    'fallback_locale' => env('APP_FALLBACK_LOCALE', 'en'),
+    'fallback_locale' => env('APP_FALLBACK_LOCALE', 'pt'),
 
-    'faker_locale' => env('APP_FAKER_LOCALE', 'en_US'),
+    'faker_locale' => env('APP_FAKER_LOCALE', 'pt_BR'),
 
     /*
     |--------------------------------------------------------------------------

+ 30 - 0
database/migrations/2026_08_10_000004_add_about_fields_to_company_settings_table.php

@@ -0,0 +1,30 @@
+<?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('company_settings', function (Blueprint $table) {
+            $table->text('about_vision')->nullable();
+            $table->text('about_mission')->nullable();
+            $table->text('about_values')->nullable();
+            $table->text('about_history')->nullable();
+        });
+    }
+
+    public function down(): void
+    {
+        Schema::table('company_settings', function (Blueprint $table) {
+            $table->dropColumn([
+                'about_vision',
+                'about_mission',
+                'about_values',
+                'about_history',
+            ]);
+        });
+    }
+};

+ 1 - 0
lang/en/auth.php

@@ -24,6 +24,7 @@ return [
     'wrong_type' => 'User found, but the selected type is incorrect. Please select the correct login type and try again.',
     'refused' => 'Your registration was refused. Please contact the administration for more information.',
     'first_access_required' => 'You have not completed your first access yet. Use the "My First Access" option to finish your registration.',
+    'pending_approval' => 'Your registration is under review by the administration. You will be able to sign in once it is approved.',
     'inactive' => 'This access has been deactivated. Please contact the administration for more information.',
     'password_reset_sent' => 'Verification code sent to your email.',
     'password_reset_invalid' => 'Invalid or expired code.',

+ 10 - 2
lang/en/messages.php

@@ -20,8 +20,12 @@ return [
     'not_found'               => 'Record not found',
     'unauthorized'            => 'Unauthorized action',
     'landing'                 => [
-        'register_success'   => 'Association request sent successfully!',
-        'registration_taken' => 'There is already an account with this badge. Use the "My First Access" option on the login screen.',
+        'register_success'             => 'Association request sent successfully!',
+        'registration_taken'           => 'There is already an account with this badge. Use the "My First Access" option on the login screen.',
+        'registration_first_access_done' => 'There is already an account with this badge and the first access has already been completed. Sign in normally or use "Forgot password?".',
+        'registration_pending_approval' => 'There is already a request with this badge awaiting approval by the administration. You will be able to complete the first access once it is approved.',
+        'cpf_taken'                    => 'There is already an account with this CPF. Use the "My First Access" option on the login screen.',
+        'email_taken'                  => 'There is already an account with this email. Use the "My First Access" option on the login screen.',
     ],
     'evaluation'              => [
         'submitted'            => 'Evaluation submitted successfully!',
@@ -33,7 +37,11 @@ return [
     ],
     'first_access'            => [
         'register_success' => 'Registration completed successfully!',
+        'register_pending_approval' => 'Registration completed! Your membership is under review by the administration — you will be able to sign in once it is approved.',
         'already_done'     => 'The first access for this badge has already been completed. Please sign in or use "Forgot your password?".',
+        'not_found'        => 'Badge not found. Request your membership on the Serprati website and wait for the administration to approve it.',
+        'not_approved'     => 'Your registration is still under review by the administration. You will be able to complete the first access once it is approved.',
+        'refused'          => 'This registration was not approved by the administration. Please contact Serprati.',
         'invalid_token'    => 'Session expired. Please enter your badge again to continue.',
     ],
 ];

+ 13 - 1
lang/en/validation.php

@@ -193,6 +193,18 @@ return [
     |
     */
 
-    'attributes' => [],
+    'attributes' => [
+        'name'         => 'name',
+        'last_name'    => 'last name',
+        'email'        => 'email',
+        'password'     => 'password',
+        'cpf'          => 'CPF',
+        'registration' => 'badge',
+        'phone'        => 'phone',
+        'position_id'  => 'position',
+        'sector_id'    => 'sector',
+        'status'       => 'status',
+        'photo'        => 'photo',
+    ],
 
 ];

+ 1 - 0
lang/es/auth.php

@@ -24,6 +24,7 @@ return [
     'wrong_type' => 'Usuario encontrado, pero el tipo seleccionado es incorrecto. Seleccione el tipo de inicio de sesión correcto e inténtelo de nuevo.',
     'refused' => 'Su registro fue rechazado. Comuníquese con la administración para más información.',
     'first_access_required' => 'Aún no realizó su primer acceso. Use la opción "Mi Primer Acceso" para completar su registro.',
+    'pending_approval' => 'Su registro está en análisis por la administración. Podrá acceder en cuanto sea aprobado.',
     'inactive' => 'Este acceso fue desactivado. Póngase en contacto con la administración para más información.',
     'password_reset_sent' => 'Código de verificación enviado a su correo electrónico.',
     'password_reset_invalid' => 'Código inválido o caducado.',

+ 10 - 2
lang/es/messages.php

@@ -20,8 +20,12 @@ return [
     'not_found'               => 'Registro no encontrado',
     'unauthorized'            => 'Acción no autorizada',
     'landing'                 => [
-        'register_success'   => '¡Solicitud de asociación enviada con éxito!',
-        'registration_taken' => 'Ya existe un registro con esta credencial. Use la opción "Mi Primer Acceso" en el inicio de sesión.',
+        'register_success'             => '¡Solicitud de asociación enviada con éxito!',
+        'registration_taken'           => 'Ya existe un registro con esta credencial. Use la opción "Mi Primer Acceso" en el inicio de sesión.',
+        'registration_first_access_done' => 'Ya existe un registro con esta credencial y el primer acceso ya fue realizado. Inicie sesión normalmente o use "¿Olvidó su contraseña?".',
+        'registration_pending_approval' => 'Ya existe una solicitud con esta credencial esperando la aprobación de la administración. Podrá concluir el primer acceso en cuanto sea aprobada.',
+        'cpf_taken'                    => 'Ya existe un registro con este CPF. Use la opción "Mi Primer Acceso" en el inicio de sesión.',
+        'email_taken'                  => 'Ya existe un registro con este correo electrónico. Use la opción "Mi Primer Acceso" en el inicio de sesión.',
     ],
     'evaluation'              => [
         'submitted'            => '¡Evaluación enviada con éxito!',
@@ -33,7 +37,11 @@ return [
     ],
     'first_access'            => [
         'register_success' => '¡Registro completado con éxito!',
+        'register_pending_approval' => '¡Registro completado! Su asociación está en análisis por la administración — podrá acceder en cuanto sea aprobada.',
         'already_done'     => 'El primer acceso de esta credencial ya fue realizado. Inicie sesión normalmente o use "¿Olvidó su contraseña?".',
+        'not_found'        => 'Credencial no encontrada. Solicite su asociación en el sitio de Serprati y espere la aprobación de la administración.',
+        'not_approved'     => 'Su registro aún está en análisis por la administración. Podrá concluir el primer acceso en cuanto sea aprobado.',
+        'refused'          => 'Este registro no fue aprobado por la administración. Póngase en contacto con Serprati.',
         'invalid_token'    => 'Sesión expirada. Ingrese la credencial nuevamente para continuar.',
     ],
 ];

+ 13 - 1
lang/es/validation.php

@@ -193,6 +193,18 @@ return [
     |
     */
 
-    'attributes' => [],
+    'attributes' => [
+        'name'         => 'nombre',
+        'last_name'    => 'apellido',
+        'email'        => 'correo electrónico',
+        'password'     => 'contraseña',
+        'cpf'          => 'CPF',
+        'registration' => 'credencial',
+        'phone'        => 'teléfono',
+        'position_id'  => 'cargo',
+        'sector_id'    => 'sector',
+        'status'       => 'estado',
+        'photo'        => 'foto',
+    ],
 
 ];

+ 1 - 0
lang/pt/auth.php

@@ -24,6 +24,7 @@ return [
     'wrong_type' => 'Usuário encontrado, mas o tipo selecionado está incorreto. Selecione o login correto e tente novamente.',
     'refused' => 'Seu cadastro foi recusado. Entre em contato com a administração para mais informações.',
     'first_access_required' => 'Você ainda não realizou seu primeiro acesso. Use a opção "Meu Primeiro Acesso" para concluir seu cadastro.',
+    'pending_approval' => 'Seu cadastro está em análise pela administração. Você poderá acessar assim que for aprovado.',
     'inactive' => 'Este acesso foi desativado. Entre em contato com a administração para mais informações.',
     'password_reset_sent' => 'Código de verificação enviado para seu e-mail.',
     'password_reset_invalid' => 'Código inválido ou expirado.',

+ 10 - 2
lang/pt/messages.php

@@ -20,8 +20,12 @@ return [
     'not_found'               => 'Registro não encontrado',
     'unauthorized'            => 'Ação não autorizada',
     'landing'                 => [
-        'register_success'   => 'Solicitação de associação enviada com sucesso!',
-        'registration_taken' => 'Já existe um cadastro com este crachá. Use a opção "Meu Primeiro Acesso" no login.',
+        'register_success'             => 'Solicitação de associação enviada com sucesso!',
+        'registration_taken'           => 'Já existe um cadastro com este crachá. Use a opção "Meu Primeiro Acesso" no login.',
+        'registration_first_access_done' => 'Já existe um cadastro com este crachá e o primeiro acesso já foi realizado. Faça login normalmente ou use "Esqueceu a senha?".',
+        'registration_pending_approval' => 'Já existe uma solicitação com este crachá aguardando a liberação da administração. Você poderá concluir o primeiro acesso assim que for aprovada.',
+        'cpf_taken'                    => 'Já existe um cadastro com este CPF. Use a opção "Meu Primeiro Acesso" no login.',
+        'email_taken'                  => 'Já existe um cadastro com este e-mail. Use a opção "Meu Primeiro Acesso" no login.',
     ],
     'evaluation'              => [
         'submitted'            => 'Avaliação enviada com sucesso!',
@@ -33,7 +37,11 @@ return [
     ],
     'first_access'            => [
         'register_success' => 'Cadastro concluído com sucesso!',
+        'register_pending_approval' => 'Cadastro concluído! Sua associação está em análise pela administração — você poderá acessar assim que for aprovada.',
         'already_done'     => 'O primeiro acesso deste crachá já foi realizado. Faça login normalmente ou use "Esqueceu a senha?".',
+        'not_found'        => 'Crachá não encontrado. Solicite sua associação pelo site da Serprati e aguarde a liberação da administração.',
+        'not_approved'     => 'Seu cadastro ainda está em análise pela administração. Você poderá concluir o primeiro acesso assim que for aprovado.',
+        'refused'          => 'Este cadastro não foi aprovado pela administração. Entre em contato com a Serprati.',
         'invalid_token'    => 'Sessão expirada. Informe o crachá novamente para continuar.',
     ],
 ];

+ 13 - 1
lang/pt/validation.php

@@ -194,6 +194,18 @@ return [
     |
     */
 
-    'attributes' => [],
+    'attributes' => [
+        'name'         => 'nome',
+        'last_name'    => 'sobrenome',
+        'email'        => 'e-mail',
+        'password'     => 'senha',
+        'cpf'          => 'CPF',
+        'registration' => 'crachá',
+        'phone'        => 'telefone',
+        'position_id'  => 'cargo',
+        'sector_id'    => 'setor',
+        'status'       => 'status',
+        'photo'        => 'foto',
+    ],
 
 ];