feat(ticket): add cancel ticket functionality and corresponding tests
This commit is contained in:
@@ -5,10 +5,12 @@ namespace App\Domains\Ticket\Controllers\AdminApp;
|
|||||||
use App\Domains\Ticket\Requests\AdminAppTicketExportRequest;
|
use App\Domains\Ticket\Requests\AdminAppTicketExportRequest;
|
||||||
use App\Domains\Ticket\Requests\AdminAppTicketIndexRequest;
|
use App\Domains\Ticket\Requests\AdminAppTicketIndexRequest;
|
||||||
use App\Domains\Ticket\Resources\AdminApp\AdminAppTicketCollection;
|
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\AdminAppTicketExcelService;
|
||||||
use App\Domains\Ticket\Services\AdminAppTicketPdfService;
|
use App\Domains\Ticket\Services\AdminAppTicketPdfService;
|
||||||
use App\Domains\Ticket\Services\AdminAppTicketService;
|
use App\Domains\Ticket\Services\AdminAppTicketService;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Http\Response;
|
use Illuminate\Http\Response;
|
||||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
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
|
public function downloadPdf(AdminAppTicketExportRequest $request): Response
|
||||||
{
|
{
|
||||||
$tenant = $request->user()->tenant()->firstOrFail();
|
$tenant = $request->user()->tenant()->firstOrFail();
|
||||||
|
|||||||
@@ -75,6 +75,18 @@ class AdminAppTicketService
|
|||||||
return $databaseSorted ? $tickets : $this->sortTickets($tickets, $tenant, $filters);
|
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
|
* @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<Ticket>
|
* @return Builder<Ticket>
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ Route::prefix('v1/adminapp/tenant')
|
|||||||
Route::get('tickets', [TicketController::class, 'index'])
|
Route::get('tickets', [TicketController::class, 'index'])
|
||||||
->middleware('tenant.menu:adminapp.tickets')
|
->middleware('tenant.menu:adminapp.tickets')
|
||||||
->name('adminapp.tickets.index');
|
->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'])
|
Route::get('tickets/pdf', [TicketController::class, 'downloadPdf'])
|
||||||
->middleware('tenant.menu:adminapp.tickets')
|
->middleware('tenant.menu:adminapp.tickets')
|
||||||
->name('adminapp.tickets.pdf');
|
->name('adminapp.tickets.pdf');
|
||||||
|
|||||||
@@ -80,6 +80,38 @@ class AdminAppTicketControllerTest extends TestCase
|
|||||||
->assertJsonPath('meta.total', 1);
|
->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
|
public function test_it_searches_by_id_and_does_not_search_by_uuid(): void
|
||||||
{
|
{
|
||||||
$tenant = $this->createTenant('fiesta_futbol_infantil');
|
$tenant = $this->createTenant('fiesta_futbol_infantil');
|
||||||
|
|||||||
Reference in New Issue
Block a user