Переглянути джерело

feat: :sparkles: crud provider specialities

crud provider specialities
Gustavo Zanatta 1 місяць тому
батько
коміт
efd40ea4ae

+ 47 - 0
app/Http/Controllers/ProviderSpecialityController.php

@@ -0,0 +1,47 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Http\Requests\ProviderSpecialityRequest;
+use App\Http\Resources\ProviderSpecialityResource;
+use App\Services\ProviderSpecialityService;
+use Illuminate\Http\JsonResponse;
+
+class ProviderSpecialityController extends Controller
+{
+    protected ProviderSpecialityService $providerSpecialityService;
+
+    public function __construct(ProviderSpecialityService $providerSpecialityService)
+    {
+        $this->providerSpecialityService = $providerSpecialityService;
+    }
+
+    public function index(int $providerId): JsonResponse
+    {
+        $providerSpecialities = $this->providerSpecialityService->getByProvider($providerId);
+
+        return $this->successResponse(
+            payload: ProviderSpecialityResource::collection($providerSpecialities)
+        );
+    }
+
+    public function store(ProviderSpecialityRequest $request, int $providerId): JsonResponse
+    {
+        $data = $request->validated();
+        $data['provider_id'] = $providerId;
+
+        $providerSpeciality = $this->providerSpecialityService->create($data);
+
+        return $this->successResponse(
+            payload: new ProviderSpecialityResource($providerSpeciality->load('speciality')),
+            code: 201
+        );
+    }
+
+    public function destroy(int $providerId, int $id): JsonResponse
+    {
+        $this->providerSpecialityService->delete($id);
+
+        return $this->successResponse();
+    }
+}

+ 29 - 0
app/Http/Requests/ProviderSpecialityRequest.php

@@ -0,0 +1,29 @@
+<?php
+
+namespace App\Http\Requests;
+
+use Illuminate\Contracts\Validation\ValidationRule;
+use Illuminate\Foundation\Http\FormRequest;
+
+class ProviderSpecialityRequest extends FormRequest
+{
+    /**
+     * Determine if the user is authorized to make this request.
+     */
+    public function authorize(): bool
+    {
+        return true;
+    }
+
+    /**
+     * Get the validation rules that apply to the request.
+     *
+     * @return array<string, ValidationRule|array|string>
+     */
+    public function rules(): array
+    {
+        return [
+            'speciality_id' => ['required', 'integer', 'exists:specialities,id'],
+        ];
+    }
+}

+ 26 - 0
app/Http/Resources/ProviderSpecialityResource.php

@@ -0,0 +1,26 @@
+<?php
+
+namespace App\Http\Resources;
+
+use Illuminate\Http\Request;
+use Illuminate\Http\Resources\Json\JsonResource;
+
+class ProviderSpecialityResource extends JsonResource
+{
+    /**
+     * Transform the resource into an array.
+     *
+     * @return array<string, mixed>
+     */
+    public function toArray(Request $request): array
+    {
+        return [
+            'id' => $this->id,
+            'provider_id' => $this->provider_id,
+            'speciality_id' => $this->speciality_id,
+            'speciality' => new SpecialityResource($this->whenLoaded('speciality')),
+            'created_at' => $this->created_at,
+            'updated_at' => $this->updated_at,
+        ];
+    }
+}

+ 33 - 0
app/Models/ProviderSpeciality.php

@@ -0,0 +1,33 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
+use Illuminate\Database\Eloquent\SoftDeletes;
+
+class ProviderSpeciality extends Model
+{
+    use HasFactory, SoftDeletes;
+
+    protected $fillable = [
+        'provider_id',
+        'speciality_id',
+    ];
+
+    protected $casts = [
+        'provider_id' => 'integer',
+        'speciality_id' => 'integer',
+    ];
+
+    public function provider(): BelongsTo
+    {
+        return $this->belongsTo(Provider::class);
+    }
+
+    public function speciality(): BelongsTo
+    {
+        return $this->belongsTo(Speciality::class);
+    }
+}

+ 28 - 0
app/Services/ProviderSpecialityService.php

@@ -0,0 +1,28 @@
+<?php
+
+namespace App\Services;
+
+use App\Models\ProviderSpeciality;
+use Illuminate\Database\Eloquent\Collection;
+
+class ProviderSpecialityService
+{
+    public function getByProvider(int $providerId): Collection
+    {
+        return ProviderSpeciality::with('speciality')
+            ->where('provider_id', $providerId)
+            ->orderBy('created_at', 'desc')
+            ->get();
+    }
+
+    public function create(array $data): ProviderSpeciality
+    {
+        return ProviderSpeciality::create($data);
+    }
+
+    public function delete(int $id): bool
+    {
+        $providerSpeciality = ProviderSpeciality::findOrFail($id);
+        return $providerSpeciality->delete();
+    }
+}

+ 31 - 0
database/migrations/2026_02_09_130152_create_provider_specialities_table.php

@@ -0,0 +1,31 @@
+<?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::create('provider_specialities', function (Blueprint $table) {
+            $table->id();
+            $table->foreignId('provider_id')->constrained('providers')->onDelete('cascade');
+            $table->foreignId('speciality_id')->constrained('specialities')->onDelete('cascade');
+            $table->timestamps();
+            $table->softDeletes();
+
+            $table->index('provider_id');
+            $table->index('speciality_id');
+        });
+
+        // Unique constraint considerando soft deletes
+        DB::statement('CREATE UNIQUE INDEX provider_speciality_unique ON provider_specialities(provider_id, speciality_id) WHERE deleted_at IS NULL');
+    }
+
+    public function down(): void
+    {
+        DB::statement('DROP INDEX IF EXISTS provider_speciality_unique');
+        Schema::dropIfExists('provider_specialities');
+    }
+};

+ 6 - 0
database/seeders/PermissionSeeder.php

@@ -88,6 +88,12 @@ class PermissionSeeder extends Seeder
                         "bits" => 271,
                         "children" => [],
                     ],
+                    [
+                        "scope" => "config.provider_speciality",
+                        "description" => "Configurações de Especialidades do Prestador",
+                        "bits" => 271,
+                        "children" => [],
+                    ],
                     [
                         "scope" => "config.provider_services_types",
                         "description" => "Configurações de Tipos de Serviços do Prestador",

+ 1 - 0
database/seeders/UserTypePermissionSeeder.php

@@ -37,6 +37,7 @@ class UserTypePermissionSeeder extends Seeder
                         ['scope' => 'config.country', 'bits' => 1],
                         ['scope' => 'config.state', 'bits' => 1],
                         ['scope' => 'config.provider', 'bits' => 271],
+                        ['scope' => 'config.provider_speciality', 'bits' => 271],
                         ['scope' => 'config.provider_services_types', 'bits' => 271],
                         ['scope' => 'config.improvement_type', 'bits' => 271],
                         ['scope' => 'config.media', 'bits' => 271],

+ 10 - 0
routes/authRoutes/provider_speciality.php

@@ -0,0 +1,10 @@
+<?php
+
+use Illuminate\Support\Facades\Route;
+use App\Http\Controllers\ProviderSpecialityController;
+
+Route::get('/provider/specialities/{providerId}', [ProviderSpecialityController::class, 'index'])->middleware('permission:config.provider_speciality,view');
+
+Route::post('/provider/specialities/{providerId}', [ProviderSpecialityController::class, 'store'])->middleware('permission:config.provider_speciality,add');
+
+Route::delete('/provider/specialities/{providerId}/{id}', [ProviderSpecialityController::class, 'destroy'])->middleware('permission:config.provider_speciality,delete');