diff --git a/app/Domains/Ticket/Controllers/AdminApp/TicketController.php b/app/Domains/Ticket/Controllers/AdminApp/TicketController.php index 00194f4..35e174e 100644 --- a/app/Domains/Ticket/Controllers/AdminApp/TicketController.php +++ b/app/Domains/Ticket/Controllers/AdminApp/TicketController.php @@ -5,10 +5,12 @@ namespace App\Domains\Ticket\Controllers\AdminApp; use App\Domains\Ticket\Requests\AdminAppTicketExportRequest; use App\Domains\Ticket\Requests\AdminAppTicketIndexRequest; use App\Domains\Ticket\Resources\AdminApp\AdminAppTicketCollection; +use App\Domains\Ticket\Resources\AdminApp\AdminAppTicketResource; use App\Domains\Ticket\Services\AdminAppTicketExcelService; use App\Domains\Ticket\Services\AdminAppTicketPdfService; use App\Domains\Ticket\Services\AdminAppTicketService; use App\Http\Controllers\Controller; +use Illuminate\Http\Request; use Illuminate\Http\Response; use Symfony\Component\HttpFoundation\StreamedResponse; @@ -29,6 +31,13 @@ class TicketController extends Controller ); } + public function cancel(Request $request, int $ticket): AdminAppTicketResource + { + $tenant = $request->user()->tenant()->firstOrFail(); + + return new AdminAppTicketResource($this->ticketService->cancel($tenant, $ticket)); + } + public function downloadPdf(AdminAppTicketExportRequest $request): Response { $tenant = $request->user()->tenant()->firstOrFail(); diff --git a/app/Domains/Ticket/Services/AdminAppTicketService.php b/app/Domains/Ticket/Services/AdminAppTicketService.php index fe5c020..ebf8f9f 100644 --- a/app/Domains/Ticket/Services/AdminAppTicketService.php +++ b/app/Domains/Ticket/Services/AdminAppTicketService.php @@ -75,6 +75,18 @@ class AdminAppTicketService return $databaseSorted ? $tickets : $this->sortTickets($tickets, $tenant, $filters); } + public function cancel(Tenant $tenant, int $ticketId): Ticket + { + $ticket = Ticket::query() + ->where('tenant_code', $tenant->codigo) + ->findOrFail($ticketId); + + $ticket->markAsCancelled(); + $ticket->save(); + + return $ticket->refresh()->load(self::RELATIONS); + } + /** * @param array{q?: string|null, category?: string|null, product?: string|null, type?: string|null, date?: string|null, size?: string|null, status?: string|null, page?: int, per_page?: int} $filters * @return Builder diff --git a/app/Domains/Ticket/routes/adminapp.php b/app/Domains/Ticket/routes/adminapp.php index f2602cc..0393ee4 100644 --- a/app/Domains/Ticket/routes/adminapp.php +++ b/app/Domains/Ticket/routes/adminapp.php @@ -9,6 +9,10 @@ Route::prefix('v1/adminapp/tenant') Route::get('tickets', [TicketController::class, 'index']) ->middleware('tenant.menu:adminapp.tickets') ->name('adminapp.tickets.index'); + Route::post('tickets/{ticket}/cancel', [TicketController::class, 'cancel']) + ->whereNumber('ticket') + ->middleware('tenant.menu:adminapp.tickets') + ->name('adminapp.tickets.cancel'); Route::get('tickets/pdf', [TicketController::class, 'downloadPdf']) ->middleware('tenant.menu:adminapp.tickets') ->name('adminapp.tickets.pdf'); diff --git a/tests/Feature/Ticket/AdminAppTicketControllerTest.php b/tests/Feature/Ticket/AdminAppTicketControllerTest.php index f894627..b8bc401 100644 --- a/tests/Feature/Ticket/AdminAppTicketControllerTest.php +++ b/tests/Feature/Ticket/AdminAppTicketControllerTest.php @@ -80,6 +80,38 @@ class AdminAppTicketControllerTest extends TestCase ->assertJsonPath('meta.total', 1); } + public function test_it_cancels_a_ticket_from_the_authenticated_tenant(): void + { + $tenant = $this->createTenant('ticket-cancellation'); + $admin = $this->createAdminAppUser($tenant); + $this->grantTicketsMenu($tenant); + Sanctum::actingAs($admin); + $ticket = $this->createTicket($tenant, $admin); + + $this->postJson("/api/v1/adminapp/tenant/tickets/{$ticket->id}/cancel") + ->assertOk() + ->assertJsonPath('data.id', $ticket->id) + ->assertJsonPath('data.status', Ticket::STATUS_CANCELLED) + ->assertJsonPath('data.status_label', 'Cancelado'); + + $this->assertNotNull($ticket->fresh()->cancelled_at); + } + + public function test_it_does_not_cancel_a_ticket_with_another_terminal_status(): void + { + $tenant = $this->createTenant('ticket-cancellation'); + $admin = $this->createAdminAppUser($tenant); + $this->grantTicketsMenu($tenant); + Sanctum::actingAs($admin); + $ticket = $this->createTicket($tenant, $admin, ['disabled_at' => now()]); + + $this->postJson("/api/v1/adminapp/tenant/tickets/{$ticket->id}/cancel") + ->assertUnprocessable() + ->assertJsonValidationErrors('status'); + + $this->assertNull($ticket->fresh()->cancelled_at); + } + public function test_it_searches_by_id_and_does_not_search_by_uuid(): void { $tenant = $this->createTenant('fiesta_futbol_infantil');