Case Study
Internal Ticketing & Asset Control
Laravel 10 internal helpdesk and asset control panel built on Filament v2 (`/admin`): tickets (open/closed/pending flows), assets tied to stores/areas/brands, branches, users, roles/permissions, problem categories, comments, ticket logs, and reporting widgets (Apex charts). Stack includes Spatie Permission and Activity log, Filament Breezy, optional Socialite sign-in, and Excel-oriented export packages—aligned with the in-repo README and `composer.json`.

Impact
Improved accountability and throughput by unifying ticket and asset lifecycles under explicit RBAC — fewer status gaps, cleaner audit trails, and less spreadsheet shadow IT around internal IT work. 821+ tickets closed across 31 stores and 18 areas.
Problem
IT and operations needed a single authenticated workspace for ticket intake, assignment, and history—not separate spreadsheets for assets, branches, and access rules. Staff roles range from super admin to unit staff; the UI had to reflect who may approve, reassign, or close work without ad hoc database edits.
Solution
Delivered and extended a Filament-first Laravel app: `TicketResource` with dedicated list pages (open, closed, pending approval), relation managers for comments and ticket logs, parallel `AssetResource` with store/area/category linkage, and supporting resources (branches, brands, stores, users, roles, permissions). Activity and permission modeling lean on Spatie packages; exports use Filament/Maatwebsite Excel patterns from the stack.
Highlighted implementation
Policy gate — 4-tier RBAC check
phpclass TicketPolicy
{
public function update(User $user, Ticket $ticket): bool
{
if ($user->hasRole('super_admin')) return true;
if ($user->hasRole('unit_admin')) {
return $user->can('manage-department', $ticket->department_id);
}
if ($user->hasRole('staff')) {
return $ticket->assignee_id === $user->id || $user->can('tickets.reassign', $ticket);
}
return $user->hasRole('general_user') && $ticket->reporter_id === $user->id;
}
}Testing & quality
Form request validation and policy rules covered by PHPUnit. Larastan static analysis enforced on the Filament resource layer.
Architecture
API Structure
Primary surface is the Filament v2 panel at `/admin` (see `config/filament.php` path). The Filament v2 resource structure under `app/Filament/Resources/`—CRUD classes, custom list pages (open/closed/pending), relation managers, and widgets—replaces a large bespoke Blade admin. A thin `routes/web.php` layer handles root redirect to `/admin`, optional Socialite OAuth callbacks, and a few web resources (e.g. `BranchController`) where non-panel flows are required.
Data Flow
Authenticated staff open Filament pages; actions run through Filament forms and table bulk actions into Eloquent models (tickets, assets, departments/branches, etc.). Multi-department routing logic assigns and escalates work across org units while preserving ticket ownership. Audit log design pairs comment rows with Spatie Activity log so every meaningful change has a durable trail—who changed what, when—surfaced in relation managers next to the ticket record. Chart widgets (e.g. `TicketStatusesChart`) read aggregated query results for the dashboard. File attachments and CSV-style exports flow through Laravel storage and Excel pipelines configured for Filament.
Backend Decisions
A 4-tier RBAC model (super admin, unit admin, staff, general user—aligned with README role tiers) maps cleanly to Spatie Laravel Permission resources exposed in the panel rather than hard-coded role strings in random controllers. Filament relation managers keep ticket discussion and immutable-style log history beside the record editors. Policies gate navigation, bulk actions, and approvals so the Filament resource layer stays the single enforcement surface. Choosing Filament v2 for this codebase trades maximum UI novelty for a mature admin pattern: fewer one-off Blade screens, more consistent authorization hooks and form validation tied to resources.
Challenges
Permission matrices grow quickly across a four-tier RBAC model. Keeping Filament policies and navigation in sync with Spatie roles—without duplicating rules in table classes and models—requires discipline. Ticket status and approval flows must stay auditable when exports or bulk actions touch many rows at once. Maintaining clean audit trails across 31 stores and 18 areas without query performance degradation means activity and ticket-log queries stay indexed, scoped, and selective so everyday list and report screens stay fast.
Technical Decisions
Stayed within Laravel 10 and the Filament resource conventions already present: extend via resources/widgets rather than bolting on a second admin framework. Dev tooling from `composer.json` (Pint, PHPUnit, Larastan) supports static and style checks as the Filament surface grows; social login and language-switch packages stay optional integration points, not core domain dependencies.