feat(scan): implement scan attempt tracking and validation logic
This commit is contained in:
@@ -10,6 +10,8 @@ use App\Domains\Catalog\Models\CatalogItem;
|
||||
use App\Domains\Catalog\Models\Category;
|
||||
use App\Domains\Tenant\Models\Tenant;
|
||||
use App\Domains\Tenant\Models\WebsiteType;
|
||||
use App\Domains\Ticket\Enums\ScanAttemptResult;
|
||||
use App\Domains\Ticket\Models\ScanAttempt;
|
||||
use App\Domains\Ticket\Models\Ticket;
|
||||
use Database\Seeders\AuthorizationSeeder;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
@@ -215,6 +217,14 @@ class ScannerTicketControllerTest extends TestCase
|
||||
'scanner_user_id' => $this->scanner->id,
|
||||
]);
|
||||
$this->assertNotNull($ticket->fresh()->used_at);
|
||||
|
||||
$scanAttempt = ScanAttempt::query()->sole();
|
||||
$this->assertSame($ticket->ticket, $scanAttempt->data);
|
||||
$this->assertSame(ScanAttemptResult::Accepted, $scanAttempt->result);
|
||||
$this->assertTrue($scanAttempt->scanner->is($this->scanner));
|
||||
$this->assertTrue($scanAttempt->ticket->is($ticket));
|
||||
$this->assertTrue($scanAttempt->tenant->is($this->tenant));
|
||||
$this->assertNotNull($scanAttempt->resolved_at);
|
||||
}
|
||||
|
||||
public function test_scan_requires_a_uuid_in_the_data_field(): void
|
||||
@@ -230,6 +240,16 @@ class ScannerTicketControllerTest extends TestCase
|
||||
->assertUnprocessable()
|
||||
->assertJsonPath('message', 'El QR proporcionado es inválido.')
|
||||
->assertJsonPath('errors.data.0', 'El QR proporcionado es inválido.');
|
||||
|
||||
$scanAttempts = ScanAttempt::query()->orderBy('id')->get();
|
||||
$this->assertCount(2, $scanAttempts);
|
||||
$this->assertNull($scanAttempts[0]->data);
|
||||
$this->assertSame('not-a-uuid', $scanAttempts[1]->data);
|
||||
$this->assertTrue($scanAttempts->every(
|
||||
fn (ScanAttempt $scanAttempt): bool => $scanAttempt->result === ScanAttemptResult::InvalidQr
|
||||
&& $scanAttempt->scanner_user_id === $this->scanner->id
|
||||
&& $scanAttempt->resolved_at !== null
|
||||
));
|
||||
}
|
||||
|
||||
public function test_ticket_cannot_be_scanned_twice(): void
|
||||
@@ -249,6 +269,11 @@ class ScannerTicketControllerTest extends TestCase
|
||||
->assertUnprocessable()
|
||||
->assertJsonValidationErrors('ticket');
|
||||
$this->assertSame($this->scanner->id, $ticket->fresh()->scanner_user_id);
|
||||
$this->assertDatabaseHas('scan_attempts', [
|
||||
'scanner_user_id' => $otherScanner->id,
|
||||
'ticket_id' => $ticket->id,
|
||||
'result' => ScanAttemptResult::AlreadyScanned->value,
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_scanner_cannot_scan_a_ticket_from_an_unassigned_category(): void
|
||||
@@ -268,6 +293,11 @@ class ScannerTicketControllerTest extends TestCase
|
||||
->assertUnprocessable()
|
||||
->assertJsonValidationErrors('ticket');
|
||||
$this->assertNull($ticket->fresh()->used_at);
|
||||
$this->assertDatabaseHas('scan_attempts', [
|
||||
'scanner_user_id' => $this->scanner->id,
|
||||
'ticket_id' => $ticket->id,
|
||||
'result' => ScanAttemptResult::CategoryForbidden->value,
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_scanner_can_read_and_scan_any_category_when_tenant_disables_validation(): void
|
||||
@@ -314,6 +344,13 @@ class ScannerTicketControllerTest extends TestCase
|
||||
->assertNotFound();
|
||||
$this->postJson('/api/v1/scanner/tickets/scan', ['data' => $foreignTicket->ticket])
|
||||
->assertNotFound();
|
||||
$this->assertDatabaseHas('scan_attempts', [
|
||||
'tenant_code' => $this->tenant->codigo,
|
||||
'scanner_user_id' => $this->scanner->id,
|
||||
'ticket_id' => null,
|
||||
'data' => $foreignTicket->ticket,
|
||||
'result' => ScanAttemptResult::TicketNotFound->value,
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_adminapp_cannot_access_scanner_routes_even_with_scan_permission(): void
|
||||
@@ -330,6 +367,7 @@ class ScannerTicketControllerTest extends TestCase
|
||||
$this->getJson("/api/v1/scanner/tickets/{$ticket->ticket}")->assertForbidden();
|
||||
$this->postJson('/api/v1/scanner/tickets/scan', ['data' => $ticket->ticket])->assertForbidden();
|
||||
$this->assertNull($ticket->fresh()->used_at);
|
||||
$this->assertDatabaseCount('scan_attempts', 0);
|
||||
}
|
||||
|
||||
/** @param array<string, mixed> $attributes */
|
||||
|
||||
Reference in New Issue
Block a user