Reports

How do I create a report?

To create a report, make a class that extends \Aero\Admin\Reports\Report.

For example, let's make a basic stock report.

First, let's make the report class, this defines the base query for our report:

class StockReport extends \Aero\Admin\Reports\Report
{
    use \Aero\Admin\Reports\Traits\HasTables;
    use \Aero\Admin\Reports\Traits\HasFilters;
    use \Aero\Admin\Reports\Traits\CanExport;

    protected static $exports = [
        \Aero\Admin\Reports\Exporters\CSVExporter::class,
        \Aero\Admin\Reports\Exporters\JSONExporter::class,
        \Aero\Admin\Reports\Exporters\XMLExporter::class,
    ];

    protected static $tables = [
        // TODO
    ];

    protected static $filters = [
        // TODO
    ];

    protected function newQuery(): \Illuminate\Database\Eloquent\Builder
    {
        return \Aero\Catalog\Models\Variant::query()
            ->select([
                'variants.id',
                'variants.sku',
                'variants.stock_level',
            ])
            ->groupBy('variants.id');
    }
}

Next, let's make a table class, this defines the UI of the report:

class StockReportTable extends \Aero\Admin\Reports\ReportTable
{
    public function columns(): array
    {
        $positionStart = 0;
        $positionIncrement = 10;

        return [
            \Aero\Admin\Reports\ReportTableColumn::create('SKU', function ($row) {
                return $row->sku;
            })
            ->position($positionStart = $positionStart + $positionIncrement)
            ->setSearchAction(function ($query, $search) {
                $query->whereLower('sku', 'like', "%{$search}%");
            }),

            \Aero\Admin\Reports\ReportTableColumn::create('Stock', function ($row) {
                return $row->stock_level;
            })
            ->position($positionStart = $positionStart + $positionIncrement),
        ];
    }

    public function emptyMessage(): string
    {
        return 'No stock data';
    }
}

Next, let's make a stock level filter:

class MinMaxStockFilter extends \Aero\Admin\Filters\MinMaxAdminFilter
{
    public function handleMinMax($min, $max, $query): void
    {
        $query->whereBetween('stock_level', [$min, $max]);
    }

    public function title(): string
    {
        return 'Stock Level';
    }
}

Finally, let's hook it all up on the report:

class StockReport extends \Aero\Admin\Reports\Report
{
    use \Aero\Admin\Reports\Traits\HasTables;
    use \Aero\Admin\Reports\Traits\HasFilters;
    use \Aero\Admin\Reports\Traits\CanExport;

    protected static $exports = [
        \Aero\Admin\Reports\Exporters\CSVExporter::class,
        \Aero\Admin\Reports\Exporters\JSONExporter::class,
        \Aero\Admin\Reports\Exporters\XMLExporter::class,
    ];

    protected static $tables = [
        \Aerocargo\Acme\Tables\StockReportTable::class,
    ];

    protected static $filters = [
        \Aerocargo\Acme\Filters\MinMaxStockFilter::class,
    ];

    protected function newQuery(): \Illuminate\Database\Eloquent\Builder
    {
        return \Aero\Catalog\Models\Variant::query()
            ->select([
                'variants.id',
                'variants.sku',
                'variants.stock_level',
            ])
            ->groupBy('variants.id');
    }
}

And register it so that it shows on the Reports index page:

\Aero\Admin\AdminReport::create(\Aerocargo\Acme\StockReport::class)
    ->title('Stock Report')
    ->summary('Stock report for all products');

How do I add a column to an existing report?

You can use the addColumn() method(s) to add a column to an existing report:

\Aero\Admin\Reports\Implementations\SalesReport::extend(function (\Aero\Admin\Reports\Implementations\SalesReport $report, \Closure $next) {
    // Add it as the first column
    $report->table()->addColumn('Header', function ($row) {
        return 'Content';
    });

    // Add it after a specific column
    $report->table()->addColumnAfter('Header', function ($row) {
        return 'Content';
    }, 'name');

    // Add it before a specific column
    $report->table()->addColumnBefore('Header', function ($row) {
        return 'Content';
    }, 'name');

    return $next($report);
});

If you need to see the keys of the existing columns in order to position your new column appropriately, you can dump them out:

\Aero\Admin\Reports\Implementations\SalesReport::extend(function (\Aero\Admin\Reports\Implementations\SalesReport $report, \Closure $next) {
    dd($report->table()->getColumns()->map->key());

    return $next($report);
});

How do I add a filter to an existing report?

You can use the addFilter() method to add a filter to an existing report:

\Aero\Admin\Reports\Implementations\SalesReport::extend(function (\Aero\Admin\Reports\Implementations\SalesReport $report, \Closure $next) {
    $report->addFilter(\Aerocargo\Acme\Filters\MinMaxStockFilter::class);

    return $next($report);
});

 

How do I add a lens to an existing report?

You can use the addLens() method to add a lens to an existing report:

\Aero\Admin\Reports\Implementations\SalesReport::extend(function (\Aero\Admin\Reports\Implementations\SalesReport $report, \Closure $next) {
    $report->addLens(\Aerocargo\Acme\Lenses\TotalRevenueLens::class);

    return $next($report);
});
class TotalRevenueLens extends \Aero\Admin\Reports\ReportLens
{
    protected function value(): \Aero\Cart\CartPrice
    {
        $totalRevenue = \DB::query()
            ->fromSub($this->query, 'results')
            ->selectRaw('SUM(results.revenue + results.tax) as total')
            ->value('total');

        $currency = request()->store()->currency;

        return new \Aero\Cart\CartPrice($currency, $totalRevenue * 100);
    }
}

Where the lens added extends \Aero\Admin\Reports\ReportLens:

class TotalRevenueLens extends \Aero\Admin\Reports\ReportLens
{
    protected function value(): \Aero\Cart\CartPrice
    {
        $totalRevenue = \DB::query()
            ->fromSub($this->query, 'results')
            ->selectRaw('SUM(results.revenue + results.tax) as total')
            ->value('total');

        $currency = request()->store()->currency;

        return new \Aero\Cart\CartPrice($currency, $totalRevenue * 100);
    }
}

$this->query is a copy of the report query, the value method must return a string (or stringable).