Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
84.62% covered (warning)
84.62%
11 / 13
66.67% covered (warning)
66.67%
4 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
Report
84.62% covered (warning)
84.62%
11 / 13
66.67% covered (warning)
66.67%
4 / 6
9.29
0.00% covered (danger)
0.00%
0 / 1
 key
n/a
0 / 0
n/a
0 / 0
0
 label
n/a
0 / 0
n/a
0 / 0
0
 group
n/a
0 / 0
n/a
0 / 0
0
 feature
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 description
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 filters
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 dateRangeFilters
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 columns
n/a
0 / 0
n/a
0 / 0
0
 rows
n/a
0 / 0
n/a
0 / 0
0
 summary
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 resolveFilters
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
4
1<?php
2
3namespace App\Reports;
4
5use Illuminate\Support\Collection;
6
7/**
8 * One entry in the Reports menu. A concrete report only has to say what it
9 * is (key/label/group), what it filters on, and how to fetch its rows —
10 * App\Services\Reporting\ReportService and the shared <x-ui.report> shell
11 * handle the on-screen table, the summary strip, and Excel/PDF/Print export
12 * identically for every report.
13 */
14abstract class Report
15{
16    abstract public function key(): string;
17
18    abstract public function label(): string;
19
20    /** Sidebar/menu group: Sales, Purchase, Inventory, Finance, Manufacturing, Customers, Marketplace, Staff. */
21    abstract public function group(): string;
22
23    /** Feature flag this report needs to even appear, or null if it's always available. */
24    public function feature(): ?string
25    {
26        return null;
27    }
28
29    public function description(): ?string
30    {
31        return null;
32    }
33
34    /**
35     * Filter field schema — same shape as config/settings/*.php fields
36     * (type/label/default), rendered as a GET filter bar by <x-ui.report>.
37     * Most reports just want a date range; override to add more.
38     */
39    public function filters(): array
40    {
41        return $this->dateRangeFilters();
42    }
43
44    protected function dateRangeFilters(): array
45    {
46        return [
47            'from' => ['type' => 'date', 'label' => 'From', 'default' => now()->startOfMonth()->toDateString()],
48            'to' => ['type' => 'date', 'label' => 'To', 'default' => now()->toDateString()],
49        ];
50    }
51
52    /** @return array{key:string,label:string,align?:string,render?:callable} */
53    abstract public function columns(): array;
54
55    /** @return Collection<int, mixed> plain arrays or objects — whatever columns()'s keys can data_get() out of */
56    abstract public function rows(array $filters): Collection;
57
58    /** @return array<string,string> label => formatted value, shown as chips above the table */
59    public function summary(Collection $rows, array $filters): array
60    {
61        return [];
62    }
63
64    /** Submitted query params merged with each filter field's default. */
65    public function resolveFilters(array $input): array
66    {
67        $resolved = [];
68
69        foreach ($this->filters() as $key => $field) {
70            $value = $input[$key] ?? null;
71            $resolved[$key] = ($value === null || $value === '') ? ($field['default'] ?? null) : $value;
72        }
73
74        return $resolved;
75    }
76}