New report system and views

This commit is contained in:
Simon Pocrnjič
2026-01-02 12:32:20 +01:00
parent 9fc5b54b8a
commit 703b52ff59
67 changed files with 8255 additions and 2794 deletions
+73 -29
View File
@@ -2,7 +2,8 @@
namespace App\Http\Controllers;
use App\Reports\ReportRegistry;
use App\Models\Report;
use App\Services\ReportQueryBuilder;
use Illuminate\Http\Request;
use Inertia\Inertia;
@@ -10,15 +11,19 @@
class ReportController extends Controller
{
public function __construct(protected ReportRegistry $registry) {}
public function __construct(protected ReportQueryBuilder $queryBuilder) {}
public function index(Request $request)
{
$reports = collect($this->registry->all())
$reports = Report::where('enabled', true)
->orderBy('order')
->orderBy('name')
->get()
->map(fn ($r) => [
'slug' => $r->slug(),
'name' => $r->name(),
'description' => $r->description(),
'slug' => $r->slug,
'name' => $r->name,
'description' => $r->description,
'category' => $r->category,
])
->values();
@@ -29,26 +34,30 @@ public function index(Request $request)
public function show(string $slug, Request $request)
{
$report = $this->registry->findBySlug($slug);
abort_if(! $report, 404);
$report->authorize($request);
$report = Report::with(['filters', 'columns'])
->where('slug', $slug)
->where('enabled', true)
->firstOrFail();
// Accept filters & pagination from query and return initial data for server-driven table
$filters = $this->validateFilters($report->inputs(), $request);
$inputs = $this->buildInputsArray($report);
$filters = $this->validateFilters($inputs, $request);
\Log::info('Report filters', ['filters' => $filters, 'request' => $request->all()]);
$perPage = (int) ($request->integer('per_page') ?: 25);
$paginator = $report->paginate($filters, $perPage);
$query = $this->queryBuilder->build($report, $filters);
$paginator = $query->paginate($perPage);
$rows = collect($paginator->items())
->map(fn ($row) => $this->normalizeRow($row))
->values();
return Inertia::render('Reports/Show', [
'slug' => $report->slug(),
'name' => $report->name(),
'description' => $report->description(),
'inputs' => $report->inputs(),
'columns' => $report->columns(),
'slug' => $report->slug,
'name' => $report->name,
'description' => $report->description,
'inputs' => $inputs,
'columns' => $this->buildColumnsArray($report),
'rows' => $rows,
'meta' => [
'total' => $paginator->total(),
@@ -62,14 +71,17 @@ public function show(string $slug, Request $request)
public function data(string $slug, Request $request)
{
$report = $this->registry->findBySlug($slug);
abort_if(! $report, 404);
$report->authorize($request);
$report = Report::with(['filters', 'columns'])
->where('slug', $slug)
->where('enabled', true)
->firstOrFail();
$filters = $this->validateFilters($report->inputs(), $request);
$inputs = $this->buildInputsArray($report);
$filters = $this->validateFilters($inputs, $request);
$perPage = (int) ($request->integer('per_page') ?: 25);
$paginator = $report->paginate($filters, $perPage);
$query = $this->queryBuilder->build($report, $filters);
$paginator = $query->paginate($perPage);
$rows = collect($paginator->items())
->map(fn ($row) => $this->normalizeRow($row))
@@ -85,20 +97,23 @@ public function data(string $slug, Request $request)
public function export(string $slug, Request $request)
{
$report = $this->registry->findBySlug($slug);
abort_if(! $report, 404);
$report->authorize($request);
$report = Report::with(['filters', 'columns'])
->where('slug', $slug)
->where('enabled', true)
->firstOrFail();
$filters = $this->validateFilters($report->inputs(), $request);
$inputs = $this->buildInputsArray($report);
$filters = $this->validateFilters($inputs, $request);
$format = strtolower((string) $request->get('format', 'csv'));
$rows = $report->query($filters)->get()->map(fn ($row) => $this->normalizeRow($row));
$columns = $report->columns();
$filename = $report->slug().'-'.now()->format('Ymd_His');
$query = $this->queryBuilder->build($report, $filters);
$rows = $query->get()->map(fn ($row) => $this->normalizeRow($row));
$columns = $this->buildColumnsArray($report);
$filename = $report->slug.'-'.now()->format('Ymd_His');
if ($format === 'pdf') {
$pdf = \Barryvdh\DomPDF\Facade\Pdf::loadView('reports.pdf.table', [
'name' => $report->name(),
'name' => $report->name,
'columns' => $columns,
'rows' => $rows,
]);
@@ -299,6 +314,35 @@ protected function validateFilters(array $inputs, Request $request): array
return $request->validate($rules);
}
/**
* Build inputs array from report filters.
*/
protected function buildInputsArray(Report $report): array
{
return $report->filters->map(fn($filter) => [
'key' => $filter->key,
'type' => $filter->type,
'label' => $filter->label,
'nullable' => $filter->nullable,
'default' => $filter->default_value,
'options' => $filter->options,
])->toArray();
}
/**
* Build columns array from report columns.
*/
protected function buildColumnsArray(Report $report): array
{
return $report->columns
->where('visible', true)
->map(fn($col) => [
'key' => $col->key,
'label' => $col->label,
])
->toArray();
}
/**
* Ensure derived export/display fields exist on row objects.
*/