Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
7 / 7
CRAP
100.00% covered (success)
100.00%
1 / 1
SalesByCategoryReport
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
7 / 7
7
100.00% covered (success)
100.00%
1 / 1
 key
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 label
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 group
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 description
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 columns
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 rows
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
1
 summary
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace App\Reports\Sales;
4
5use App\Models\OrderDetails;
6use App\Reports\Report;
7use Illuminate\Support\Collection;
8use Illuminate\Support\Facades\DB;
9
10class SalesByCategoryReport extends Report
11{
12    public function key(): string
13    {
14        return 'sales-by-category';
15    }
16
17    public function label(): string
18    {
19        return 'Sales by Category';
20    }
21
22    public function group(): string
23    {
24        return 'Sales';
25    }
26
27    public function description(): ?string
28    {
29        return 'Revenue per product category in the selected range.';
30    }
31
32    public function columns(): array
33    {
34        return [
35            ['key' => 'name', 'label' => 'Category'],
36            ['key' => 'qty', 'label' => 'Qty Sold', 'align' => 'right'],
37            ['key' => 'revenue', 'label' => 'Revenue', 'align' => 'right', 'render' => fn ($r) => money($r->revenue)],
38        ];
39    }
40
41    public function rows(array $filters): Collection
42    {
43        return OrderDetails::query()
44            ->join('stocks', 'order_details.stock_id', '=', 'stocks.id')
45            ->join('products', 'stocks.product_id', '=', 'products.id')
46            ->leftJoin('categories', 'products.category_id', '=', 'categories.id')
47            ->join('orders', 'order_details.order_id', '=', 'orders.id')
48            ->whereDate('orders.created_at', '>=', $filters['from'])
49            ->whereDate('orders.created_at', '<=', $filters['to'])
50            ->select(DB::raw("COALESCE(categories.name, 'Uncategorized') as name"), DB::raw('SUM(order_details.qty) as qty'), DB::raw('SUM(order_details.total) as revenue'))
51            ->groupBy('categories.id', 'categories.name')
52            ->orderByDesc('revenue')
53            ->get();
54    }
55
56    public function summary(Collection $rows, array $filters): array
57    {
58        return [
59            'Categories' => number_format($rows->count()),
60            'Revenue' => money($rows->sum('revenue')),
61        ];
62    }
63}