Selaa lähdekoodia

feat(users): adiciona usuarios

ebagabee 2 viikkoa sitten
vanhempi
commit
f6f0cc7384

+ 6 - 0
app/Http/Controllers/UnitController.php

@@ -42,4 +42,10 @@ public function destroy(int $id): JsonResponse
         $this->service->delete($id);
         return $this->successResponse(message: __('messages.deleted'), code: 204);
     }
+
+    public function selectList(): JsonResponse
+    {
+        $items = $this->service->getSelectList();
+        return $this->successResponse(payload: $items);
+    }
 }

+ 14 - 9
app/Http/Requests/UserRequest.php

@@ -14,18 +14,23 @@ class UserRequest extends FormRequest
     public function rules(): array
     {
         $rules = [
-            'avatar' => 'sometimes|string|nullable',
-            'name' => 'sometimes|string|nullable',
-            'email' => 'sometimes|email|unique:users,email',
-            'password' => 'sometimes|string|nullable',
-            'type' => ['sometimes', Rule::enum(UserTypeEnum::class)],
-            'language' => ['sometimes', Rule::enum(LanguageEnum::class)],
+            'avatar'    => 'sometimes|nullable|image|max:2048',
+            'name'      => 'sometimes|string|nullable|max:255',
+            'cpf'       => 'sometimes|nullable|string|max:14',
+            'email'     => 'sometimes|email',
+            'password'  => 'sometimes|string|nullable|min:8',
+            'user_type' => ['sometimes', Rule::enum(UserTypeEnum::class)],
+            'language'  => ['sometimes', Rule::enum(LanguageEnum::class)],
+            'state_id'  => 'sometimes|nullable|integer|exists:states,id',
+            'unit_id'   => 'sometimes|nullable|integer|exists:units,id',
         ];
 
         if ($this->isMethod('post')) {
-            $rules['name'] = 'required|string|max:255';
-            $rules['email'] = 'required|email|unique:users,email';
-            $rules['password'] = 'required|string|min:6';
+            $rules['name']      = 'required|string|max:255';
+            $rules['email']     = 'required|email|unique:users,email';
+            $rules['password']  = 'required|string|min:8';
+            $rules['user_type'] = ['required', Rule::enum(UserTypeEnum::class)];
+
             if (!$this->has('language')) {
                 $this->merge(['language' => LanguageEnum::PORTUGUESE->value]);
             }

+ 15 - 7
app/Http/Resources/UserResource.php

@@ -4,29 +4,37 @@
 
 use Carbon\Carbon;
 use Illuminate\Http\Request;
-use Illuminate\Http\Resources\Json\JsonResource;
 use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
+use Illuminate\Http\Resources\Json\JsonResource;
+use Illuminate\Support\Facades\Storage;
 
 class UserResource extends JsonResource
 {
-    /**
-     * Transform the resource into an array.
-     *
-     * @return array<string, mixed>
-     */
     public function toArray(Request $request): array
     {
         return [
             'id'            => $this->id,
             'name'          => $this->name,
+            'cpf'           => $this->cpf,
             'email'         => $this->email,
             'language'      => $this->language,
-            'type'          => $this->type,
+            'user_type'     => $this->user_type,
+            'status'        => $this->status,
+            'state_id'      => $this->state_id,
+            'avatar_url'    => $this->avatar_url
+                ? Storage::temporaryUrl($this->avatar_url, now()->addHours(24))
+                : null,
             'last_login_at' => $this->last_login_at
                 ? Carbon::parse($this->last_login_at)->format('Y-m-d H:i:s')
                 : null,
             'created_at'    => Carbon::parse($this->created_at)->format('Y-m-d H:i:s'),
             'updated_at'    => Carbon::parse($this->updated_at)->format('Y-m-d H:i:s'),
+
+            'state' => $this->whenLoaded('state', fn() => [
+                'id'   => $this->state->id,
+                'name' => $this->state->name,
+                'code' => $this->state->code,
+            ]),
         ];
     }
 

+ 6 - 1
app/Models/User.php

@@ -74,7 +74,12 @@ protected function casts(): array
 
     public function isAdmin(): bool
     {
-        return $this->type === UserTypeEnum::ADMIN;
+        return $this->user_type === UserTypeEnum::ADMIN;
+    }
+
+    public function state(): \Illuminate\Database\Eloquent\Relations\BelongsTo
+    {
+        return $this->belongsTo(\App\Models\State::class, 'state_id');
     }
 
     /**

+ 6 - 0
app/Services/UnitService.php

@@ -18,6 +18,12 @@ public function getAll(): Collection
             ->get();
     }
 
+    public function getSelectList(): \Illuminate\Support\Collection
+    {
+        return Unit::orderBy('fantasy_name')
+            ->get(['id', 'fantasy_name']);
+    }
+
     public function findById(int $id): ?Unit
     {
         return Unit::with(['city', 'state'])->find($id);

+ 50 - 6
app/Services/UserService.php

@@ -3,31 +3,47 @@
 namespace App\Services;
 
 use App\Enums\UserTypeEnum;
+use App\Models\Unit;
+use App\Models\UnitUser;
 use App\Models\User;
 use Illuminate\Database\Eloquent\Collection;
+use Illuminate\Http\UploadedFile;
 use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Storage;
 
 class UserService
 {
     public function authUser(): ?User
     {
-        $user = Auth::user();
-        return $user;
+        return Auth::user();
     }
 
     public function getAll(): Collection
     {
-        return User::orderBy("created_at", "desc")->get();
+        return User::with('state')->orderBy('name')->get();
     }
 
     public function findById(int $id): ?User
     {
-        return User::find($id);
+        return User::with('state')->find($id);
     }
 
     public function create(array $data): User
     {
-        return User::create($data);
+        $unitId = $data['unit_id'] ?? null;
+        unset($data['unit_id']);
+
+        $data = $this->handleAvatar($data);
+        $user = User::create($data);
+
+        if ($unitId) {
+            UnitUser::create([
+                'unit_id' => $unitId,
+                'user_id' => $user->id,
+            ]);
+        }
+
+        return $user->load('state');
     }
 
     public function update(int $id, array $data): ?User
@@ -38,8 +54,10 @@ public function update(int $id, array $data): ?User
             return null;
         }
 
+        unset($data['unit_id']);
+        $data = $this->handleAvatar($data, $model->avatar_url);
         $model->update($data);
-        return $model->fresh();
+        return $model->fresh(['state']);
     }
 
     public function delete(int $id): bool
@@ -50,6 +68,10 @@ public function delete(int $id): bool
             return false;
         }
 
+        if ($model->avatar_url) {
+            Storage::delete($model->avatar_url);
+        }
+
         return $model->delete();
     }
 
@@ -57,4 +79,26 @@ public function getUserTypes(): array
     {
         return UserTypeEnum::toArray();
     }
+
+    private function handleAvatar(array $data, ?string $oldAvatarPath = null): array
+    {
+        if (!isset($data['avatar'])) {
+            return $data;
+        }
+
+        if ($data['avatar'] instanceof UploadedFile) {
+            if ($oldAvatarPath) {
+                Storage::delete($oldAvatarPath);
+            }
+            $data['avatar_url'] = $data['avatar']->store('users/avatars');
+        } elseif (is_null($data['avatar'])) {
+            if ($oldAvatarPath) {
+                Storage::delete($oldAvatarPath);
+            }
+            $data['avatar_url'] = null;
+        }
+
+        unset($data['avatar']);
+        return $data;
+    }
 }

+ 25 - 0
database/migrations/2026_04_15_000003_add_fields_to_users_table.php

@@ -0,0 +1,25 @@
+<?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('users', function (Blueprint $table) {
+            $table->string('cpf', 14)->nullable()->after('name');
+            $table->string('avatar_url')->nullable()->after('user_type');
+            $table->foreignId('state_id')->nullable()->after('avatar_url')->constrained('states');
+        });
+    }
+
+    public function down(): void
+    {
+        Schema::table('users', function (Blueprint $table) {
+            $table->dropConstrainedForeignId('state_id');
+            $table->dropColumn(['cpf', 'avatar_url']);
+        });
+    }
+};

+ 2 - 0
routes/authRoutes/unit.php

@@ -4,6 +4,8 @@
 use App\Http\Controllers\UnitController;
 
 Route::controller(UnitController::class)->prefix('unit')->group(function () {
+    Route::get('/all/select', 'selectList');
+
     Route::get('/', 'index')->middleware('permission:unit,view');
 
     Route::post('/', 'store')->middleware('permission:unit,add');