feat(scanner): refactor ticket scanning endpoint to accept UUID in request body and add validation
This commit is contained in:
parent
e9521e65d0
commit
b607c1b673
|
|
@ -6086,11 +6086,16 @@
|
|||
"key": "Accept",
|
||||
"value": "application/json",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/json",
|
||||
"type": "text"
|
||||
}
|
||||
],
|
||||
"description": "Ruta Laravel: `POST /api/v1/scanner/tickets/{ticketUuid}/scan`\n\nControlador: `App\\Domains\\Ticket\\Controllers\\Scanner\\TicketController@scan`\n\nRequiere autenticación Sanctum.",
|
||||
"description": "Ruta Laravel: `POST /api/v1/scanner/tickets/scan`\n\nControlador: `App\\Domains\\Ticket\\Controllers\\Scanner\\TicketController@scan`\n\nRequiere autenticación Sanctum.",
|
||||
"url": {
|
||||
"raw": "{{base_url}}/api/v1/scanner/tickets/{{ticket_uuid}}/scan",
|
||||
"raw": "{{base_url}}/api/v1/scanner/tickets/scan",
|
||||
"host": [
|
||||
"{{base_url}}"
|
||||
],
|
||||
|
|
@ -6099,10 +6104,18 @@
|
|||
"v1",
|
||||
"scanner",
|
||||
"tickets",
|
||||
"{{ticket_uuid}}",
|
||||
"scan"
|
||||
]
|
||||
},
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n \"data\": \"{{ticket_uuid}}\"\n}",
|
||||
"options": {
|
||||
"raw": {
|
||||
"language": "json"
|
||||
}
|
||||
}
|
||||
},
|
||||
"auth": {
|
||||
"type": "bearer",
|
||||
"bearer": [
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace App\Domains\Ticket\Controllers\Scanner;
|
|||
|
||||
use App\Domains\Auth\Models\User;
|
||||
use App\Domains\Ticket\Requests\ScannerTicketIndexRequest;
|
||||
use App\Domains\Ticket\Requests\ScanTicketRequest;
|
||||
use App\Domains\Ticket\Resources\Scanner\ScannedTicketResource;
|
||||
use App\Domains\Ticket\Resources\TicketResource;
|
||||
use App\Domains\Ticket\Services\ScannerTicketService;
|
||||
|
|
@ -35,13 +36,13 @@ class TicketController extends Controller
|
|||
);
|
||||
}
|
||||
|
||||
public function scan(Request $request, string $ticketUuid): TicketResource
|
||||
public function scan(ScanTicketRequest $request): TicketResource
|
||||
{
|
||||
/** @var User $scanner */
|
||||
$scanner = $request->user();
|
||||
|
||||
return TicketResource::make(
|
||||
$this->ticketService->scan($scanner, $ticketUuid)
|
||||
$this->ticketService->scan($scanner, $request->validated('data'))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace App\Domains\Ticket\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class ScanTicketRequest extends FormRequest
|
||||
{
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @return array<string, list<string>> */
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'data' => ['required', 'uuid'],
|
||||
];
|
||||
}
|
||||
|
||||
/** @return array<string, string> */
|
||||
public function messages(): array
|
||||
{
|
||||
return [
|
||||
'data.required' => 'El QR proporcionado es inválido.',
|
||||
'data.uuid' => 'El QR proporcionado es inválido.',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -7,8 +7,7 @@ Route::prefix('v1/scanner/tickets')
|
|||
->middleware(['auth:sanctum', 'scanner.tenant'])
|
||||
->group(function (): void {
|
||||
Route::get('/', [TicketController::class, 'index']);
|
||||
Route::post('scan', [TicketController::class, 'scan']);
|
||||
Route::get('{ticketUuid}', [TicketController::class, 'show'])
|
||||
->whereUuid('ticketUuid');
|
||||
Route::post('{ticketUuid}/scan', [TicketController::class, 'scan'])
|
||||
->whereUuid('ticketUuid');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ function bodyFor(string $method, string $uri): ?array
|
|||
'POST api/v1/scanner/password/reset-attempts' => ['email' => '{{scanner_email}}'],
|
||||
'POST api/v1/scanner/password/reset-attempts/validate' => ['email' => '{{scanner_email}}', 'codigo' => '{{reset_code}}'],
|
||||
'POST api/v1/scanner/password/reset' => ['email' => '{{scanner_email}}', 'codigo' => '{{reset_code}}', 'password' => '{{scanner_password}}', 'password_confirmation' => '{{scanner_password}}'],
|
||||
'POST api/v1/scanner/tickets/scan' => ['data' => '{{ticket_uuid}}'],
|
||||
];
|
||||
|
||||
if (isset($exact[$key])) {
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ class PrepareLoadTestTicketsCommandTest extends TestCase
|
|||
|
||||
$first = $rows[0];
|
||||
$this->withToken($first['scanner_token'])
|
||||
->postJson("/api/v1/scanner/tickets/{$first['ticket_uuid']}/scan")
|
||||
->postJson('/api/v1/scanner/tickets/scan', ['data' => $first['ticket_uuid']])
|
||||
->assertOk()
|
||||
->assertJsonPath('data.ticket', $first['ticket_uuid']);
|
||||
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ class ScannerTicketControllerTest extends TestCase
|
|||
$ticket = $this->createTicket('77777777-7777-4777-8777-777777777777');
|
||||
Sanctum::actingAs($this->scanner);
|
||||
|
||||
$this->postJson("/api/v1/scanner/tickets/{$ticket->ticket}/scan")
|
||||
$this->postJson('/api/v1/scanner/tickets/scan', ['data' => $ticket->ticket])
|
||||
->assertOk()
|
||||
->assertJsonPath('data.ticket', $ticket->ticket)
|
||||
->assertJsonPath('data.scanner_user_id', $this->scanner->id)
|
||||
|
|
@ -217,11 +217,26 @@ class ScannerTicketControllerTest extends TestCase
|
|||
$this->assertNotNull($ticket->fresh()->used_at);
|
||||
}
|
||||
|
||||
public function test_scan_requires_a_uuid_in_the_data_field(): void
|
||||
{
|
||||
Sanctum::actingAs($this->scanner);
|
||||
|
||||
$this->postJson('/api/v1/scanner/tickets/scan')
|
||||
->assertUnprocessable()
|
||||
->assertJsonPath('message', 'El QR proporcionado es inválido.')
|
||||
->assertJsonPath('errors.data.0', 'El QR proporcionado es inválido.');
|
||||
|
||||
$this->postJson('/api/v1/scanner/tickets/scan', ['data' => 'not-a-uuid'])
|
||||
->assertUnprocessable()
|
||||
->assertJsonPath('message', 'El QR proporcionado es inválido.')
|
||||
->assertJsonPath('errors.data.0', 'El QR proporcionado es inválido.');
|
||||
}
|
||||
|
||||
public function test_ticket_cannot_be_scanned_twice(): void
|
||||
{
|
||||
$ticket = $this->createTicket('88888888-8888-4888-8888-888888888888');
|
||||
Sanctum::actingAs($this->scanner);
|
||||
$this->postJson("/api/v1/scanner/tickets/{$ticket->ticket}/scan")->assertOk();
|
||||
$this->postJson('/api/v1/scanner/tickets/scan', ['data' => $ticket->ticket])->assertOk();
|
||||
|
||||
$otherScanner = User::factory()->create([
|
||||
'rol_codigo' => RoleCode::Scanner->value,
|
||||
|
|
@ -230,7 +245,7 @@ class ScannerTicketControllerTest extends TestCase
|
|||
$otherScanner->scanCategories()->attach($this->category);
|
||||
Sanctum::actingAs($otherScanner);
|
||||
|
||||
$this->postJson("/api/v1/scanner/tickets/{$ticket->ticket}/scan")
|
||||
$this->postJson('/api/v1/scanner/tickets/scan', ['data' => $ticket->ticket])
|
||||
->assertUnprocessable()
|
||||
->assertJsonValidationErrors('ticket');
|
||||
$this->assertSame($this->scanner->id, $ticket->fresh()->scanner_user_id);
|
||||
|
|
@ -249,7 +264,7 @@ class ScannerTicketControllerTest extends TestCase
|
|||
);
|
||||
Sanctum::actingAs($this->scanner);
|
||||
|
||||
$this->postJson("/api/v1/scanner/tickets/{$ticket->ticket}/scan")
|
||||
$this->postJson('/api/v1/scanner/tickets/scan', ['data' => $ticket->ticket])
|
||||
->assertUnprocessable()
|
||||
->assertJsonValidationErrors('ticket');
|
||||
$this->assertNull($ticket->fresh()->used_at);
|
||||
|
|
@ -274,7 +289,7 @@ class ScannerTicketControllerTest extends TestCase
|
|||
->assertOk()
|
||||
->assertJsonPath('data.id', $ticket->id);
|
||||
|
||||
$this->postJson("/api/v1/scanner/tickets/{$ticket->ticket}/scan")
|
||||
$this->postJson('/api/v1/scanner/tickets/scan', ['data' => $ticket->ticket])
|
||||
->assertOk()
|
||||
->assertJsonPath('data.scanner_user_id', $this->scanner->id);
|
||||
}
|
||||
|
|
@ -297,7 +312,7 @@ class ScannerTicketControllerTest extends TestCase
|
|||
|
||||
$this->getJson("/api/v1/scanner/tickets/{$foreignTicket->ticket}")
|
||||
->assertNotFound();
|
||||
$this->postJson("/api/v1/scanner/tickets/{$foreignTicket->ticket}/scan")
|
||||
$this->postJson('/api/v1/scanner/tickets/scan', ['data' => $foreignTicket->ticket])
|
||||
->assertNotFound();
|
||||
}
|
||||
|
||||
|
|
@ -313,7 +328,7 @@ class ScannerTicketControllerTest extends TestCase
|
|||
|
||||
$this->getJson('/api/v1/scanner/tickets')->assertForbidden();
|
||||
$this->getJson("/api/v1/scanner/tickets/{$ticket->ticket}")->assertForbidden();
|
||||
$this->postJson("/api/v1/scanner/tickets/{$ticket->ticket}/scan")->assertForbidden();
|
||||
$this->postJson('/api/v1/scanner/tickets/scan', ['data' => $ticket->ticket])->assertForbidden();
|
||||
$this->assertNull($ticket->fresh()->used_at);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue