From ffa3f10b1856f7b4f81ba756711c78781261628f Mon Sep 17 00:00:00 2001 From: ncoronel Date: Fri, 4 Sep 2026 10:40:46 -0300 Subject: [PATCH] feat(scanner): implement category validation for AdminApp role and update tests --- .../Ticket/Services/ScannerTicketService.php | 11 ++++- .../Ticket/ScannerTicketControllerTest.php | 41 ++++++++++++++++++- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/app/Domains/Ticket/Services/ScannerTicketService.php b/app/Domains/Ticket/Services/ScannerTicketService.php index ccaf189..ffccae9 100644 --- a/app/Domains/Ticket/Services/ScannerTicketService.php +++ b/app/Domains/Ticket/Services/ScannerTicketService.php @@ -3,6 +3,7 @@ namespace App\Domains\Ticket\Services; use App\Domains\Auth\Models\User; +use App\Domains\Authorization\Enums\RoleCode; use App\Domains\Ticket\Models\Ticket; use Illuminate\Database\Eloquent\Builder; use Illuminate\Pagination\LengthAwarePaginator; @@ -73,7 +74,7 @@ class ScannerTicketService ->where('tenant_code', $scanner->tenant_codigo) ->where('ticket', $ticketUuid); - if ($scanner->tenant()->firstOrFail()->requiresScannerCategoryValidation()) { + if ($this->requiresCategoryValidation($scanner)) { $categoryIds = $this->scannerCategoryIds($scanner); $query->where(function (Builder $query) use ($scanner, $categoryIds): void { @@ -158,7 +159,7 @@ class ScannerTicketService private function scannerCanScan(User $scanner, Ticket $ticket): bool { - if (! $scanner->tenant()->firstOrFail()->requiresScannerCategoryValidation()) { + if (! $this->requiresCategoryValidation($scanner)) { return true; } @@ -169,4 +170,10 @@ class ScannerTicketService ->where('categorias.id', $categoryId) ->exists(); } + + private function requiresCategoryValidation(User $scanner): bool + { + return $scanner->rol_codigo !== RoleCode::AdminApp->value + && $scanner->tenant()->firstOrFail()->requiresScannerCategoryValidation(); + } } diff --git a/tests/Feature/Ticket/ScannerTicketControllerTest.php b/tests/Feature/Ticket/ScannerTicketControllerTest.php index 8d22d5a..2993858 100644 --- a/tests/Feature/Ticket/ScannerTicketControllerTest.php +++ b/tests/Feature/Ticket/ScannerTicketControllerTest.php @@ -52,7 +52,7 @@ class ScannerTicketControllerTest extends TestCase $this->getJson('/api/v1/scanner/tickets')->assertUnauthorized(); Sanctum::actingAs(User::factory()->create([ - 'rol_codigo' => RoleCode::AdminApp->value, + 'rol_codigo' => RoleCode::User->value, 'tenant_codigo' => $this->tenant->codigo, ])); @@ -300,6 +300,45 @@ class ScannerTicketControllerTest extends TestCase ->assertNotFound(); } + public function test_adminapp_can_read_and_scan_all_tenant_categories_without_assignments(): void + { + $this->tenant->update(['scanner_category_validation_enabled' => true]); + $admin = User::factory()->create([ + 'rol_codigo' => RoleCode::AdminApp->value, + 'tenant_codigo' => $this->tenant->codigo, + ]); + $this->assertCount(0, $admin->scanCategories); + $otherCategory = Category::query()->create([ + 'tenant_code' => $this->tenant->codigo, 'nombre' => 'Comidas', + ]); + Sanctum::actingAs($admin); + foreach ([$this->category, $otherCategory] as $category) { + $ticket = $this->createTicket((string) Str::uuid(), [], $category); + $this->getJson("/api/v1/scanner/tickets/{$ticket->ticket}")->assertOk(); + $this->postJson("/api/v1/scanner/tickets/{$ticket->ticket}/scan") + ->assertOk()->assertJsonPath('data.scanner_user_id', $admin->id); + $this->postJson("/api/v1/scanner/tickets/{$ticket->ticket}/scan") + ->assertUnprocessable()->assertJsonValidationErrors('ticket'); + } + } + + public function test_adminapp_cannot_read_or_scan_another_tenants_ticket(): void + { + $admin = User::factory()->create([ + 'rol_codigo' => RoleCode::AdminApp->value, + 'tenant_codigo' => $this->tenant->codigo, + ]); + $foreignTenant = $this->createTenant('foreign'); + $foreignCategory = Category::query()->create([ + 'tenant_code' => $foreignTenant->codigo, 'nombre' => 'Externas', + ]); + $ticket = $this->createTicket((string) Str::uuid(), [], $foreignCategory, $foreignTenant); + Sanctum::actingAs($admin); + $this->getJson("/api/v1/scanner/tickets/{$ticket->ticket}")->assertNotFound(); + $this->postJson("/api/v1/scanner/tickets/{$ticket->ticket}/scan")->assertNotFound(); + $this->assertNull($ticket->fresh()->used_at); + } + /** @param array $attributes */ private function createTicket( string $uuid,