Просмотр исходного кода

feat: :sparkles: crud clientes

crud clientes
Gustavo Zanatta 1 месяц назад
Родитель
Сommit
eb88be8d96

+ 94 - 0
app/Http/Controllers/ClientController.php

@@ -0,0 +1,94 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Http\Requests\ClientRequest;
+use App\Http\Resources\ClientResource;
+use App\Services\ClientService;
+use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
+use Illuminate\Http\JsonResponse;
+
+class ClientController extends Controller
+{
+    // protected ClientService $clientService;
+
+    // public function __construct(ClientService $clientService)
+    // {
+    //     $this->clientService = $clientService;
+    // }
+
+    // public function index(): AnonymousResourceCollection
+    // {
+    //     $clients = $this->clientService->getAll();
+    //     return ClientResource::collection($clients);
+    // }
+
+    // public function store(ClientRequest $request): ClientResource
+    // {
+    //     $client = $this->clientService->create($request->validated());
+    //     return new ClientResource($client->load('user'));
+    // }
+
+    // public function show(string $id): ClientResource
+    // {
+    //     $client = $this->clientService->findById($id);
+    //     return new ClientResource($client);
+    // }
+
+    // public function update(ClientRequest $request, string $id): JsonResponse
+    // {
+    //     $this->clientService->update($request->validated(), $id);
+    //     return response()->json(['message' => 'Client updated successfully']);
+    // }
+
+    // public function destroy(string $id): JsonResponse
+    // {
+    //     $this->clientService->delete($id);
+    //     return response()->json(['message' => 'Client deleted successfully']);
+    // }
+
+
+    public function __construct(protected ClientService $service) {}
+
+    public function index(): JsonResponse
+    {
+        $items = $this->service->getAll();
+        return $this->successResponse(
+            payload: ClientResource::collection($items),
+        );
+    }
+
+    public function store(ClientRequest $request): JsonResponse
+    {
+        $item = $this->service->create($request->validated());
+        return $this->successResponse(
+            payload: new ClientResource($item),
+            message: __("messages.created"),
+            code: 201,
+        );
+    }
+
+    public function show(int $id): JsonResponse
+    {
+        $item = $this->service->findById($id);
+        return $this->successResponse(payload: new ClientResource($item));
+    }
+
+    public function update(ClientRequest $request, int $id): JsonResponse
+    {
+        $item = $this->service->update($request->validated(), $id);
+        return $this->successResponse(
+            payload: new ClientResource($item),
+            message: __("messages.updated"),
+        );
+    }
+
+    public function destroy(int $id): JsonResponse
+    {
+        $this->service->delete($id);
+        return $this->successResponse(
+            message: __("messages.deleted"),
+            code: 204,
+        );
+    }
+}

+ 169 - 0
app/Http/Requests/ClientRequest.php

@@ -0,0 +1,169 @@
+<?php
+
+namespace App\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+use Illuminate\Validation\Rule;
+
+class ClientRequest extends FormRequest
+{
+    public function rules(): array
+    {
+        $clientId = $this->route('id');
+
+        $rules = [
+            'document' => [
+                'sometimes',
+                'string',
+                'regex:/^[0-9]{11}$|^[0-9]{14}$/',
+                function ($attribute, $value, $fail) {
+                    if (!$this->isValidCpfCnpj($value)) {
+                        $fail(__('validation.custom.document.invalid'));
+                    }
+                },
+            ],
+            'user_id' => [
+                'sometimes',
+                'exists:users,id',
+                function ($attribute, $value, $fail) use ($clientId) {
+                    $clientExists = \DB::table('clients')
+                        ->where('user_id', $value)
+                        ->whereNull('deleted_at')
+                        ->when($clientId, function ($query) use ($clientId) {
+                            $query->where('id', '!=', $clientId);
+                        })
+                        ->exists();
+
+                    if ($clientExists) {
+                        $fail(__('validation.custom.user_id.already_linked_to_client'));
+                    }
+
+                    $providerExists = \DB::table('providers')
+                        ->where('user_id', $value)
+                        ->whereNull('deleted_at')
+                        ->exists();
+                    
+                    if ($providerExists) {
+                        $fail(__('validation.custom.user_id.already_linked_to_provider'));
+                    }
+                },
+            ],
+        ];
+
+        if ($this->isMethod('post')) {
+            $rules['document'] = [
+                'required',
+                'string',
+                'regex:/^[0-9]{11}$|^[0-9]{14}$/',
+                function ($attribute, $value, $fail) {
+                    if (!$this->isValidCpfCnpj($value)) {
+                        $fail(__('validation.custom.document.invalid'));
+                    }
+                },
+            ];
+            $rules['user_id'] = [
+                'required',
+                'exists:users,id',
+                function ($attribute, $value, $fail) {
+                    $clientExists = \DB::table('clients')
+                        ->where('user_id', $value)
+                        ->whereNull('deleted_at')
+                        ->exists();
+
+                    if ($clientExists) {
+                        $fail(__('validation.custom.user_id.already_linked_to_client'));
+                    }
+
+                    $providerExists = \DB::table('providers')
+                        ->where('user_id', $value)
+                        ->whereNull('deleted_at')
+                        ->exists();
+                    
+                    if ($providerExists) {
+                        $fail(__('validation.custom.user_id.already_linked_to_provider'));
+                    }
+                },
+            ];
+        }
+
+        return $rules;
+    }
+
+    private function isValidCpfCnpj(string $value): bool
+    {
+        $value = preg_replace('/[^0-9]/', '', $value);
+
+        if (strlen($value) === 11) {
+            return $this->isValidCpf($value);
+        } elseif (strlen($value) === 14) {
+            return $this->isValidCnpj($value);
+        }
+
+        return false;
+    }
+
+    private function isValidCpf(string $cpf): bool
+    {
+        if (preg_match('/(\d)\1{10}/', $cpf)) {
+            return false;
+        }
+
+        for ($t = 9; $t < 11; $t++) {
+            for ($d = 0, $c = 0; $c < $t; $c++) {
+                $d += $cpf[$c] * (($t + 1) - $c);
+            }
+            $d = ((10 * $d) % 11) % 10;
+            if ($cpf[$c] != $d) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    private function isValidCnpj(string $cnpj): bool
+    {
+        if (preg_match('/(\d)\1{13}/', $cnpj)) {
+            return false;
+        }
+
+        $length = strlen($cnpj) - 2;
+        $numbers = substr($cnpj, 0, $length);
+        $digits = substr($cnpj, $length);
+        $sum = 0;
+        $pos = $length - 7;
+
+        for ($i = $length; $i >= 1; $i--) {
+            $sum += $numbers[$length - $i] * $pos--;
+            if ($pos < 2) {
+                $pos = 9;
+            }
+        }
+
+        $result = $sum % 11 < 2 ? 0 : 11 - $sum % 11;
+
+        if ($result != $digits[0]) {
+            return false;
+        }
+
+        $length = $length + 1;
+        $numbers = substr($cnpj, 0, $length);
+        $sum = 0;
+        $pos = $length - 7;
+
+        for ($i = $length; $i >= 1; $i--) {
+            $sum += $numbers[$length - $i] * $pos--;
+            if ($pos < 2) {
+                $pos = 9;
+            }
+        }
+
+        $result = $sum % 11 < 2 ? 0 : 11 - $sum % 11;
+
+        if ($result != $digits[1]) {
+            return false;
+        }
+
+        return true;
+    }
+}

+ 39 - 10
app/Http/Requests/ProviderRequest.php

@@ -33,11 +33,27 @@ class ProviderRequest extends FormRequest
                 Rule::unique('providers', 'user_id')
                     ->ignore($providerId)
                     ->whereNull('deleted_at'),
-                // function ($attribute, $value, $fail) {
-                //     if (\DB::table('clients')->where('user_id', $value)->whereNull('deleted_at')->exists()) {
-                //         $fail(__('validation.custom.user_id.already_linked_to_client'));
-                //     }
-                // },
+                function ($attribute, $value, $fail) use ($providerId) {
+                    $clientExists = \DB::table('clients')
+                        ->where('user_id', $value)
+                        ->whereNull('deleted_at')
+                        ->exists();
+                    
+                    if ($clientExists) {
+                        $fail(__('validation.custom.user_id.already_linked_to_client'));
+                    }
+
+                    $providerExists = \DB::table('providers')
+                        ->where('user_id', $value)
+                        ->whereNull('deleted_at')
+                        ->when($providerId, function ($query) use ($providerId) {
+                            $query->where('id', '!=', $providerId);
+                        })
+                        ->exists();
+                    if ($providerExists) {
+                        $fail(__('validation.custom.user_id.already_linked_to_provider'));
+                    }
+                },
             ],
             'average_rating' => 'sometimes|nullable|numeric|min:0|max:5',
             'total_services' => 'sometimes|integer|min:0',
@@ -68,11 +84,24 @@ class ProviderRequest extends FormRequest
                 'required',
                 'exists:users,id',
                 Rule::unique('providers', 'user_id')->whereNull('deleted_at'),
-                // function ($attribute, $value, $fail) {
-                //     if (\DB::table('clients')->where('user_id', $value)->whereNull('deleted_at')->exists()) {
-                //         $fail(__('validation.custom.user_id.already_linked_to_client'));
-                //     }
-                // },
+                function ($attribute, $value, $fail) {
+                    $clientExists = \DB::table('clients')
+                        ->where('user_id', $value)
+                        ->whereNull('deleted_at')
+                        ->exists();
+                    
+                    if ($clientExists) {
+                        $fail(__('validation.custom.user_id.already_linked_to_client'));
+                    }
+
+                    $providerExists = \DB::table('providers')
+                        ->where('user_id', $value)
+                        ->whereNull('deleted_at')
+                        ->exists();
+                    if ($providerExists) {
+                        $fail(__('validation.custom.user_id.already_linked_to_provider'));
+                    }
+                },
             ];
         }
 

+ 27 - 0
app/Http/Resources/ClientResource.php

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

+ 29 - 0
app/Models/Client.php

@@ -0,0 +1,29 @@
+<?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 Client extends Model
+{
+    use HasFactory, SoftDeletes;
+
+    protected $fillable = [
+        'document',
+        'user_id',
+    ];
+
+    protected $casts = [
+        'created_at' => 'datetime',
+        'updated_at' => 'datetime',
+        'deleted_at' => 'datetime',
+    ];
+
+    public function user(): BelongsTo
+    {
+        return $this->belongsTo(User::class);
+    }
+}

+ 36 - 0
app/Services/ClientService.php

@@ -0,0 +1,36 @@
+<?php
+
+namespace App\Services;
+
+use App\Models\Client;
+use Illuminate\Database\Eloquent\Collection;
+
+class ClientService
+{
+    public function getAll(): Collection
+    {
+        return Client::with(['user'])->get();
+    }
+
+    public function findById(int $id): ?Client
+    {
+        return Client::with(['user'])->find($id);
+    }
+
+    public function create(array $data): Client
+    {
+        return Client::create($data);
+    }
+
+    public function update(array $data, int $id): bool
+    {
+        $client = Client::findOrFail($id);
+        return $client->update($data);
+    }
+
+    public function delete(int $id): bool
+    {
+        $client = Client::findOrFail($id);
+        return $client->delete();
+    }
+}

+ 34 - 0
database/migrations/2026_02_05_000002_create_clients_table.php

@@ -0,0 +1,34 @@
+<?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('clients', function (Blueprint $table) {
+            $table->id();
+            $table->string('document');
+            $table->foreignId('user_id')->constrained('users')->onDelete('cascade');
+            $table->timestamps();
+            $table->softDeletes();
+
+            // Indexes
+            $table->index('document');
+            $table->index('user_id');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::dropIfExists('clients');
+    }
+};

+ 6 - 0
database/seeders/PermissionSeeder.php

@@ -58,6 +58,12 @@ class PermissionSeeder extends Seeder
                         "bits" => 271,
                         "children" => [],
                     ],
+                    [
+                        "scope" => "config.client",
+                        "description" => "Configurações de Clientes",
+                        "bits" => 271,
+                        "children" => [],
+                    ],
                     [
                         "scope" => "config.country",
                         "description" => "Configurações de Países",

+ 1 - 0
database/seeders/UserTypePermissionSeeder.php

@@ -32,6 +32,7 @@ class UserTypePermissionSeeder extends Seeder
                         ['scope' => 'dashboard', 'bits' => 1],
                         ['scope' => 'config.user', 'bits' => 5],
                         ['scope' => 'config.city', 'bits' => 1],
+                        ['scope' => 'config.client', 'bits' => 271],
                         ['scope' => 'config.country', 'bits' => 1],
                         ['scope' => 'config.state', 'bits' => 1],
                         ['scope' => 'config.provider', 'bits' => 271],

+ 1 - 0
lang/en/validation.php

@@ -185,6 +185,7 @@ return [
         ],
         'user_id' => [
             'already_linked_to_client' => 'This user is already linked to a client.',
+            'already_linked_to_provider' => 'This user is already linked to a provider.',
         ],
     ],
 

+ 1 - 0
lang/es/validation.php

@@ -185,6 +185,7 @@ return [
         ],
         'user_id' => [
             'already_linked_to_client' => 'Este usuario ya está vinculado a un cliente.',
+            'already_linked_to_provider' => 'Este usuario ya está vinculado a un proveedor.',
         ],
     ],
 

+ 1 - 0
lang/pt/validation.php

@@ -186,6 +186,7 @@ return [
         ],
         'user_id' => [
             'already_linked_to_client' => 'Este usuário já está vinculado a um cliente.',
+            'already_linked_to_provider' => 'Este usuário já está vinculado a um prestador.',
         ],
     ],
 

+ 10 - 0
routes/authRoutes/client.php

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