From ba0e2dd00c0bf3d7bfe405425926355afcbf2cff Mon Sep 17 00:00:00 2001 From: ncoronel Date: Fri, 28 Aug 2026 15:14:11 -0300 Subject: [PATCH] feat(tickets): enhance ticket search functionality and add ticket counts to response --- .../Controllers/AdminApp/TicketController.php | 11 +++-- .../AdminApp/AdminAppTicketCollection.php | 35 +++++++++++++++ .../Ticket/Services/AdminAppTicketResult.php | 16 +++++++ .../Ticket/Services/AdminAppTicketService.php | 44 ++++++++++--------- .../Ticket/AdminAppTicketControllerTest.php | 5 +++ 5 files changed, 85 insertions(+), 26 deletions(-) create mode 100644 app/Domains/Ticket/Resources/AdminApp/AdminAppTicketCollection.php create mode 100644 app/Domains/Ticket/Services/AdminAppTicketResult.php diff --git a/app/Domains/Ticket/Controllers/AdminApp/TicketController.php b/app/Domains/Ticket/Controllers/AdminApp/TicketController.php index 2fa6b10..beb9fac 100644 --- a/app/Domains/Ticket/Controllers/AdminApp/TicketController.php +++ b/app/Domains/Ticket/Controllers/AdminApp/TicketController.php @@ -3,21 +3,20 @@ namespace App\Domains\Ticket\Controllers\AdminApp; use App\Domains\Ticket\Requests\AdminAppTicketIndexRequest; -use App\Domains\Ticket\Resources\TicketResource; +use App\Domains\Ticket\Resources\AdminApp\AdminAppTicketCollection; use App\Domains\Ticket\Services\AdminAppTicketService; use App\Http\Controllers\Controller; -use Illuminate\Http\Resources\Json\AnonymousResourceCollection; class TicketController extends Controller { public function __construct(private readonly AdminAppTicketService $ticketService) {} - public function index(AdminAppTicketIndexRequest $request): AnonymousResourceCollection + public function index(AdminAppTicketIndexRequest $request): AdminAppTicketCollection { $tenant = $request->user()->tenant()->firstOrFail(); - return TicketResource::collection( - $this->ticketService->list($tenant, $request->validated()) - )->additional($this->ticketService->counts($tenant)); + return new AdminAppTicketCollection( + $this->ticketService->search($tenant, $request->validated()) + ); } } diff --git a/app/Domains/Ticket/Resources/AdminApp/AdminAppTicketCollection.php b/app/Domains/Ticket/Resources/AdminApp/AdminAppTicketCollection.php new file mode 100644 index 0000000..4355ad6 --- /dev/null +++ b/app/Domains/Ticket/Resources/AdminApp/AdminAppTicketCollection.php @@ -0,0 +1,35 @@ + */ + public $collects = TicketResource::class; + + private readonly int $scannedTickets; + + private readonly int $totalTickets; + + public function __construct(AdminAppTicketResult $result) + { + parent::__construct($result->tickets); + + $this->scannedTickets = $result->scannedTickets; + $this->totalTickets = $result->totalTickets; + } + + /** @return array{scanned_tickets: int, total_tickets: int} */ + public function with(Request $request): array + { + return [ + 'scanned_tickets' => $this->scannedTickets, + 'total_tickets' => $this->totalTickets, + ]; + } +} diff --git a/app/Domains/Ticket/Services/AdminAppTicketResult.php b/app/Domains/Ticket/Services/AdminAppTicketResult.php new file mode 100644 index 0000000..e9f65f4 --- /dev/null +++ b/app/Domains/Ticket/Services/AdminAppTicketResult.php @@ -0,0 +1,16 @@ + $tickets */ + public function __construct( + public LengthAwarePaginator $tickets, + public int $scannedTickets, + public int $totalTickets, + ) {} +} diff --git a/app/Domains/Ticket/Services/AdminAppTicketService.php b/app/Domains/Ticket/Services/AdminAppTicketService.php index 6d7c9c2..1180843 100644 --- a/app/Domains/Ticket/Services/AdminAppTicketService.php +++ b/app/Domains/Ticket/Services/AdminAppTicketService.php @@ -5,26 +5,39 @@ namespace App\Domains\Ticket\Services; use App\Domains\Tenant\Models\Tenant; use App\Domains\Ticket\Models\Ticket; use Illuminate\Database\Eloquent\Builder; -use Illuminate\Pagination\LengthAwarePaginator; class AdminAppTicketService { - /** @return array{scanned_tickets: int, total_tickets: int} */ - public function counts(Tenant $tenant): array + /** + * @param array{q?: string|null, page?: int, per_page?: int} $filters + */ + public function search(Tenant $tenant, array $filters = []): AdminAppTicketResult { - $query = Ticket::query()->where('tenant_code', $tenant->codigo); + $query = $this->baseQuery($tenant, $filters); - return [ - 'scanned_tickets' => (clone $query)->whereNotNull('used_at')->count(), - 'total_tickets' => $query->count(), - ]; + $tickets = (clone $query) + ->with([ + ...TicketValidityResolver::RELATIONS, + ...TicketPresentationResolver::RELATIONS, + 'user', + 'sourceCatalogItem.category', + ]) + ->orderByDesc('id') + ->paginateFromRequest() + ->withQueryString(); + + return new AdminAppTicketResult( + tickets: $tickets, + scannedTickets: (clone $query)->whereNotNull('used_at')->count(), + totalTickets: $tickets->total(), + ); } /** * @param array{q?: string|null, page?: int, per_page?: int} $filters - * @return LengthAwarePaginator + * @return Builder */ - public function list(Tenant $tenant, array $filters = []): LengthAwarePaginator + private function baseQuery(Tenant $tenant, array $filters): Builder { $search = trim((string) ($filters['q'] ?? '')); @@ -38,15 +51,6 @@ class AdminAppTicketService fn (Builder $searchQuery): Builder => $searchQuery ->where('ticket', 'like', "%{$search}%"), ); - }) - ->with([ - ...TicketValidityResolver::RELATIONS, - ...TicketPresentationResolver::RELATIONS, - 'user', - 'sourceCatalogItem.category', - ]) - ->orderByDesc('id') - ->paginateFromRequest() - ->withQueryString(); + }); } } diff --git a/tests/Feature/Ticket/AdminAppTicketControllerTest.php b/tests/Feature/Ticket/AdminAppTicketControllerTest.php index 2cbea72..9705e65 100644 --- a/tests/Feature/Ticket/AdminAppTicketControllerTest.php +++ b/tests/Feature/Ticket/AdminAppTicketControllerTest.php @@ -98,6 +98,11 @@ class AdminAppTicketControllerTest extends TestCase $this->getJson('/api/v1/adminapp/tenant/tickets?q=does-not-match') ->assertOk() ->assertJsonCount(0, 'data') + ->assertJsonPath('scanned_tickets', 0) + ->assertJsonPath('total_tickets', 0); + + $this->getJson('/api/v1/adminapp/tenant/tickets') + ->assertOk() ->assertJsonPath('scanned_tickets', 1) ->assertJsonPath('total_tickets', 2); }