Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
10.81% covered (danger)
10.81%
4 / 37
50.00% covered (danger)
50.00%
4 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
CustomerListReport
10.81% covered (danger)
10.81%
4 / 37
50.00% covered (danger)
50.00%
4 / 8
53.41
0.00% covered (danger)
0.00%
0 / 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
 filters
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 columns
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 rows
0.00% covered (danger)
0.00%
0 / 21
0.00% covered (danger)
0.00%
0 / 1
2
 summary
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace App\Reports\Customers;
4
5use App\Models\admin\Customer;
6use App\Models\Order;
7use App\Reports\Report;
8use Illuminate\Support\Collection;
9
10/** Every customer with their lifetime order count and spend — a snapshot, no date filter. */
11class CustomerListReport extends Report
12{
13    public function key(): string
14    {
15        return 'customer-list';
16    }
17
18    public function label(): string
19    {
20        return 'Customers & Lifetime Value';
21    }
22
23    public function group(): string
24    {
25        return 'Customers';
26    }
27
28    public function description(): ?string
29    {
30        return 'Every customer, how many orders they have placed, and total spend to date.';
31    }
32
33    public function filters(): array
34    {
35        return [];
36    }
37
38    public function columns(): array
39    {
40        return [
41            ['key' => 'name', 'label' => 'Customer'],
42            ['key' => 'phone', 'label' => 'Phone'],
43            ['key' => 'orders', 'label' => 'Orders', 'align' => 'right'],
44            ['key' => 'spend', 'label' => 'Lifetime Spend', 'align' => 'right', 'render' => fn ($r) => money($r->spend)],
45            ['key' => 'due', 'label' => 'Due', 'align' => 'right', 'render' => fn ($r) => money($r->due)],
46        ];
47    }
48
49    public function rows(array $filters): Collection
50    {
51        $totals = Order::query()
52            ->selectRaw('customer_id, COUNT(*) as orders, SUM(total) as spend, SUM(due) as due')
53            ->whereNotNull('customer_id')
54            ->groupBy('customer_id')
55            ->get()
56            ->keyBy('customer_id');
57
58        return Customer::query()
59            ->whereIn('id', $totals->keys())
60            ->get()
61            ->map(function (Customer $c) use ($totals) {
62                $t = $totals->get($c->id);
63
64                return (object) [
65                    'name' => $c->name,
66                    'phone' => $c->phone,
67                    'orders' => (int) $t->orders,
68                    'spend' => (float) $t->spend,
69                    'due' => (float) $t->due,
70                ];
71            })
72            ->sortByDesc('spend')
73            ->values();
74    }
75
76    public function summary(Collection $rows, array $filters): array
77    {
78        return [
79            'Customers' => number_format($rows->count()),
80            'Total Lifetime Spend' => money($rows->sum('spend')),
81        ];
82    }
83}