diff --git a/app/Domains/Ticket/Controllers/Scanner/ScanAttemptController.php b/app/Domains/Ticket/Controllers/Scanner/ScanAttemptController.php index d13996b..8ca53df 100644 --- a/app/Domains/Ticket/Controllers/Scanner/ScanAttemptController.php +++ b/app/Domains/Ticket/Controllers/Scanner/ScanAttemptController.php @@ -5,8 +5,10 @@ namespace App\Domains\Ticket\Controllers\Scanner; use App\Domains\Auth\Models\User; use App\Domains\Ticket\Requests\ScanAttemptIndexRequest; use App\Domains\Ticket\Resources\Scanner\ScanAttemptResource; +use App\Domains\Ticket\Resources\Scanner\ScannerScanResultResource; use App\Domains\Ticket\Services\ScannerTicketService; use App\Http\Controllers\Controller; +use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\AnonymousResourceCollection; class ScanAttemptController extends Controller @@ -22,4 +24,14 @@ class ScanAttemptController extends Controller $this->ticketService->attemptsBy($scanner, $request->validated()) ); } + + public function show(Request $request, int $scanAttempt): ScannerScanResultResource + { + /** @var User $scanner */ + $scanner = $request->user(); + + return ScannerScanResultResource::make( + $this->ticketService->scanAttemptDetail($scanner, $scanAttempt) + ); + } } diff --git a/app/Domains/Ticket/Services/ScannerTicketService.php b/app/Domains/Ticket/Services/ScannerTicketService.php index 336ebed..d4579a1 100644 --- a/app/Domains/Ticket/Services/ScannerTicketService.php +++ b/app/Domains/Ticket/Services/ScannerTicketService.php @@ -51,6 +51,19 @@ class ScannerTicketService ->withQueryString(); } + public function scanAttemptDetail(User $scanner, int $scanAttemptId): ScanAttempt + { + $scanAttempt = ScanAttempt::query() + ->with('ticket') + ->where('tenant_code', $scanner->tenant_codigo) + ->where('scanner_user_id', $scanner->getKey()) + ->findOrFail($scanAttemptId); + + $scanAttempt->ticket?->loadMissing($this->relations()); + + return $scanAttempt; + } + private function parseSearchDate(string $search): ?string { if (preg_match('/^(\d{4})-(\d{2})-(\d{2})$/', $search, $matches) === 1) { diff --git a/app/Domains/Ticket/routes/scanner.php b/app/Domains/Ticket/routes/scanner.php index c37336b..a92ccbb 100644 --- a/app/Domains/Ticket/routes/scanner.php +++ b/app/Domains/Ticket/routes/scanner.php @@ -7,6 +7,8 @@ use Illuminate\Support\Facades\Route; Route::middleware(['auth:sanctum', 'scanner.tenant']) ->group(function (): void { Route::get('v1/scanner/attempts', ScanAttemptController::class); + Route::get('v1/scanner/attempts/{scanAttempt}', [ScanAttemptController::class, 'show']) + ->whereNumber('scanAttempt'); Route::prefix('v1/scanner/tickets')->group(function (): void { Route::post('scan', [TicketController::class, 'scan']); diff --git a/tests/Feature/Ticket/ScannerTicketControllerTest.php b/tests/Feature/Ticket/ScannerTicketControllerTest.php index e208b58..62e1ce2 100644 --- a/tests/Feature/Ticket/ScannerTicketControllerTest.php +++ b/tests/Feature/Ticket/ScannerTicketControllerTest.php @@ -143,6 +143,53 @@ class ScannerTicketControllerTest extends TestCase ->assertJsonPath('data.0.id', $matching->id); } + public function test_scanner_can_read_its_scan_attempt_detail(): void + { + $ticket = $this->createTicket('abababab-abab-4bab-8bab-abababababab'); + $scanAttempt = $this->createScanAttempt($ticket->ticket, [ + 'ticket_id' => $ticket->id, + ]); + Sanctum::actingAs($this->scanner); + + $this->getJson("/api/v1/scanner/attempts/{$scanAttempt->id}") + ->assertOk() + ->assertJsonPath('data.scan_attempt.id', $scanAttempt->id) + ->assertJsonPath('data.scan_attempt.ticket_id', $ticket->id) + ->assertJsonPath('data.scan_attempt.result', ScanAttemptResult::Accepted->value) + ->assertJsonPath('data.ticket.id', $ticket->id) + ->assertJsonPath('data.ticket.ticket', $ticket->ticket) + ->assertJsonPath('data.ticket.client', $this->ticketOwner->nombre_apellido) + ->assertJsonPath('data.client.id', $this->ticketOwner->id) + ->assertJsonPath('data.client.nombre_apellido', $this->ticketOwner->nombre_apellido); + } + + public function test_scanner_cannot_read_another_scanners_attempt_detail(): void + { + $otherScanner = User::factory()->create([ + 'rol_codigo' => RoleCode::Scanner->value, + 'tenant_codigo' => $this->tenant->codigo, + ]); + $scanAttempt = $this->createScanAttempt('not-this-scanner', [], $otherScanner); + Sanctum::actingAs($this->scanner); + + $this->getJson("/api/v1/scanner/attempts/{$scanAttempt->id}") + ->assertNotFound(); + } + + public function test_scan_attempt_detail_returns_null_ticket_and_client_when_unassociated(): void + { + $scanAttempt = $this->createScanAttempt('not-a-ticket', [ + 'result' => ScanAttemptResult::TicketNotFound, + ]); + Sanctum::actingAs($this->scanner); + + $this->getJson("/api/v1/scanner/attempts/{$scanAttempt->id}") + ->assertOk() + ->assertJsonPath('data.scan_attempt.id', $scanAttempt->id) + ->assertJsonPath('data.ticket', null) + ->assertJsonPath('data.client', null); + } + public function test_scanner_can_read_an_authorized_ticket_detail_by_uuid(): void { $ticket = $this->createTicket('44444444-4444-4444-8444-444444444444');