Parcourir la source

feat: :sparkles: crud client favorite providers

crud client favorite providers
Gustavo Zanatta il y a 1 mois
Parent
commit
4c78b24c4a

+ 85 - 0
app/Http/Controllers/ClientFavoriteProviderController.php

@@ -0,0 +1,85 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Http\Requests\ClientFavoriteProviderRequest;
+use App\Http\Resources\ClientFavoriteProviderResource;
+use App\Services\ClientFavoriteProviderService;
+use Illuminate\Http\JsonResponse;
+
+class ClientFavoriteProviderController extends Controller
+{
+
+        //     return $this->successResponse(
+        //     payload: new ProviderBlockedDayResource($blockedDay),
+        //     message: __("messages.created"),
+        //     code: 201,
+        // );
+    public function __construct(
+        private ClientFavoriteProviderService $service
+    ) {}
+
+    public function index(int $clientId): JsonResponse
+    {
+        $favorites = $this->service->getByClientId($clientId);
+
+        return $this->successResponse(
+            payload: ClientFavoriteProviderResource::collection($favorites),
+        );
+    }
+
+    public function show(int $id): JsonResponse
+    {
+        $favorite = $this->service->getById($id);
+
+        return $this->successResponse(
+            payload: new ClientFavoriteProviderResource($favorite),
+        );
+    }
+
+    public function store(ClientFavoriteProviderRequest $request): JsonResponse
+    {
+        $favorite = $this->service->create($request->validated());
+
+        return $this->successResponse(
+            payload: new ClientFavoriteProviderResource($favorite),
+            message: __("messages.created"),
+            code: 201,
+        );
+
+        return $this->successResponse(
+            payload: new ClientFavoriteProviderResource($favorite),
+            message: __("messages.created"),
+            code: 201,
+        );
+    }
+
+    public function update(ClientFavoriteProviderRequest $request, int $id): JsonResponse
+    {
+        $favorite = $this->service->update($id, $request->validated());
+
+        return $this->successResponse(
+            payload: new ClientFavoriteProviderResource($favorite),
+            message: __("messages.updated"),
+        );
+    }
+
+    public function destroy(int $id): JsonResponse
+    {
+        $this->service->delete($id);
+
+        return $this->successResponse(
+            message: __("messages.deleted"),
+            code: 204,
+        );
+    }
+
+    public function getFavoritedProviders(int $clientId): JsonResponse
+    {
+        $providerIds = $this->service->getFavoritedProviderIds($clientId);
+
+        return $this->successResponse(
+            payload: $providerIds,
+        );
+    }
+}

+ 46 - 0
app/Http/Requests/ClientFavoriteProviderRequest.php

@@ -0,0 +1,46 @@
+<?php
+
+namespace App\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+use Illuminate\Validation\Rule;
+
+class ClientFavoriteProviderRequest extends FormRequest
+{
+    public function authorize(): bool
+    {
+        return true;
+    }
+
+    public function rules(): array
+    {
+        $clientId = $this->input('client_id');
+        $favoriteId = $this->route('id');
+
+        return [
+            'client_id' => ['required', 'integer', 'exists:clients,id'],
+            'provider_id' => [
+                'required',
+                'integer',
+                'exists:providers,id',
+                Rule::unique('client_favorite_providers', 'provider_id')
+                    ->where('client_id', $clientId)
+                    ->whereNull('deleted_at')
+                    ->ignore($favoriteId),
+            ],
+            'notes' => ['nullable', 'string', 'max:1000'],
+        ];
+    }
+
+    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.',
+        ];
+    }
+}

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

@@ -0,0 +1,22 @@
+<?php
+
+namespace App\Http\Resources;
+
+use Illuminate\Http\Request;
+use Illuminate\Http\Resources\Json\JsonResource;
+
+class ClientFavoriteProviderResource extends JsonResource
+{
+    public function toArray(Request $request): array
+    {
+        return [
+            'id' => $this->id,
+            'client_id' => $this->client_id,
+            'provider_id' => $this->provider_id,
+            'provider_name' => $this->provider->user->name ?? null,
+            'notes' => $this->notes,
+            'created_at' => $this->created_at?->format('Y-m-d H:i:s'),
+            'updated_at' => $this->updated_at?->format('Y-m-d H:i:s'),
+        ];
+    }
+}

+ 35 - 0
app/Models/ClientFavoriteProvider.php

@@ -0,0 +1,35 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\SoftDeletes;
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
+
+class ClientFavoriteProvider extends Model
+{
+    use HasFactory, SoftDeletes;
+
+    protected $fillable = [
+        'client_id',
+        'provider_id',
+        'notes',
+    ];
+
+    protected $casts = [
+        'created_at' => 'datetime',
+        'updated_at' => 'datetime',
+        'deleted_at' => 'datetime',
+    ];
+
+    public function client(): BelongsTo
+    {
+        return $this->belongsTo(Client::class);
+    }
+
+    public function provider(): BelongsTo
+    {
+        return $this->belongsTo(Provider::class);
+    }
+}

+ 54 - 0
app/Services/ClientFavoriteProviderService.php

@@ -0,0 +1,54 @@
+<?php
+
+namespace App\Services;
+
+use App\Models\ClientFavoriteProvider;
+use App\Http\Resources\ClientFavoriteProviderResource;
+use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
+
+class ClientFavoriteProviderService
+{
+    public function getByClientId(int $clientId): AnonymousResourceCollection
+    {
+        $favorites = ClientFavoriteProvider::with('provider')
+            ->where('client_id', $clientId)
+            ->orderBy('created_at', 'desc')
+            ->get();
+
+        return ClientFavoriteProviderResource::collection($favorites);
+    }
+
+    public function getById(int $id): ClientFavoriteProviderResource
+    {
+        $favorite = ClientFavoriteProvider::with('provider')->findOrFail($id);
+        return new ClientFavoriteProviderResource($favorite);
+    }
+
+    public function create(array $data): ClientFavoriteProviderResource
+    {
+        $favorite = ClientFavoriteProvider::create($data);
+        $favorite->load('provider');
+        return new ClientFavoriteProviderResource($favorite);
+    }
+
+    public function update(int $id, array $data): ClientFavoriteProviderResource
+    {
+        $favorite = ClientFavoriteProvider::findOrFail($id);
+        $favorite->update($data);
+        $favorite->load('provider');
+        return new ClientFavoriteProviderResource($favorite);
+    }
+
+    public function delete(int $id): bool
+    {
+        $favorite = ClientFavoriteProvider::findOrFail($id);
+        return $favorite->delete();
+    }
+
+    public function getFavoritedProviderIds(int $clientId): array
+    {
+        return ClientFavoriteProvider::where('client_id', $clientId)
+            ->pluck('provider_id')
+            ->toArray();
+    }
+}

+ 4 - 2
app/Services/ClientService.php

@@ -4,6 +4,7 @@ namespace App\Services;
 
 use App\Models\Client;
 use Illuminate\Database\Eloquent\Collection;
+use Illuminate\Support\Facades\Log;
 
 class ClientService
 {
@@ -22,10 +23,11 @@ class ClientService
         return Client::create($data);
     }
 
-    public function update(array $data, int $id): bool
+    public function update(array $data, int $id): Client
     {
         $client = Client::findOrFail($id);
-        return $client->update($data);
+        $client->update($data);
+        return $client;
     }
 
     public function delete(int $id): bool

+ 37 - 0
database/migrations/2026_02_10_175305_create_client_favorite_providers_table.php

@@ -0,0 +1,37 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+return new class extends Migration
+{
+    /**
+     * Run the migrations.
+     */
+    public function up(): void
+    {
+        Schema::create('client_favorite_providers', function (Blueprint $table) {
+            $table->id();
+            $table->foreignId('client_id')->constrained('clients')->onDelete('cascade');
+            $table->foreignId('provider_id')->constrained('providers')->onDelete('cascade');
+            $table->text('notes')->nullable();
+            $table->timestamps();
+            $table->softDeletes();
+
+            $table->index('client_id');
+            $table->index('provider_id');
+            
+            // Unique constraint: client can only favorite a provider once
+            $table->unique(['client_id', 'provider_id', 'deleted_at'], 'client_provider_unique');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::dropIfExists('client_favorite_providers');
+    }
+};

+ 6 - 0
database/seeders/PermissionSeeder.php

@@ -70,6 +70,12 @@ class PermissionSeeder extends Seeder
                         "bits" => 271,
                         "children" => [],
                     ],
+                    [
+                        "scope" => "config.client_favorite_provider",
+                        "description" => "Configurações de Prestadores Favoritos do Cliente",
+                        "bits" => 271,
+                        "children" => [],
+                    ],
                     [
                         "scope" => "config.country",
                         "description" => "Configurações de Países",

+ 1 - 0
database/seeders/UserTypePermissionSeeder.php

@@ -34,6 +34,7 @@ class UserTypePermissionSeeder extends Seeder
                         ['scope' => 'config.address', 'bits' => 271],
                         ['scope' => 'config.city', 'bits' => 1],
                         ['scope' => 'config.client', 'bits' => 271],
+                        ['scope' => 'config.client_favorite_provider', 'bits' => 271],
                         ['scope' => 'config.country', 'bits' => 1],
                         ['scope' => 'config.state', 'bits' => 1],
                         ['scope' => 'config.provider', 'bits' => 271],

+ 16 - 0
routes/authRoutes/client_favorite_provider.php

@@ -0,0 +1,16 @@
+<?php
+
+use App\Http\Controllers\ClientFavoriteProviderController;
+use Illuminate\Support\Facades\Route;
+
+// Get list by client
+Route::get('/client/favorite-providers/{clientId}', [ClientFavoriteProviderController::class, 'index']);
+
+// Get favorited provider IDs (for filtering)
+Route::get('/client/favorited-providers/{clientId}', [ClientFavoriteProviderController::class, 'getFavoritedProviders']);
+
+// CRUD individual
+Route::get('/client/favorite-provider/{id}', [ClientFavoriteProviderController::class, 'show']);
+Route::post('/client/favorite-provider', [ClientFavoriteProviderController::class, 'store']);
+Route::put('/client/favorite-provider/{id}', [ClientFavoriteProviderController::class, 'update']);
+Route::delete('/client/favorite-provider/{id}', [ClientFavoriteProviderController::class, 'destroy']);