Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
36 / 36
100.00% covered (success)
100.00%
7 / 7
CRAP
100.00% covered (success)
100.00%
1 / 1
SalesSummaryReport
100.00% covered (success)
100.00%
36 / 36
100.00% covered (success)
100.00%
7 / 7
8
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%
10 / 10
100.00% covered (success)
100.00%
1 / 1
1
 rows
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
1
 summary
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3namespace App\Reports\Sales;
4
5use App\Models\Order;
6use App\Reports\Report;
7use Illuminate\Support\Collection;
8
9/**
10 * Every storefront order in a date range. This is the modern, Order-based
11 * replacement for the legacy Sale-based "Sales Report" (admin.xyz) — that
12 * page still exists (still linked from a couple of POS due-payment screens)
13 * but is no longer what the Reports menu points at.
14 */
15class SalesSummaryReport extends Report
16{
17    public function key(): string
18    {
19        return 'sales-summary';
20    }
21
22    public function label(): string
23    {
24        return 'Sales Summary';
25    }
26
27    public function group(): string
28    {
29        return 'Sales';
30    }
31
32    public function description(): ?string
33    {
34        return 'Every order placed in the selected range, with totals, discount, tax and status.';
35    }
36
37    public function columns(): array
38    {
39        return [
40            ['key' => 'bar_code', 'label' => 'Order'],
41            ['key' => 'customer_name', 'label' => 'Customer'],
42            ['key' => 'created_at', 'label' => 'Date', 'render' => fn ($r) => $r->created_at->format('d M, Y')],
43            ['key' => 'total', 'label' => 'Total', 'align' => 'right', 'render' => fn ($r) => money($r->total)],
44            ['key' => 'discount', 'label' => 'Discount', 'align' => 'right', 'render' => fn ($r) => money($r->discount)],
45            ['key' => 'tax', 'label' => 'Tax', 'align' => 'right', 'render' => fn ($r) => money($r->tax)],
46            ['key' => 'due', 'label' => 'Due', 'align' => 'right', 'render' => fn ($r) => money($r->due)],
47            ['key' => 'status', 'label' => 'Status'],
48        ];
49    }
50
51    public function rows(array $filters): Collection
52    {
53        return Order::query()
54            ->with('customer')
55            ->whereDate('created_at', '>=', $filters['from'])
56            ->whereDate('created_at', '<=', $filters['to'])
57            ->latest()
58            ->get()
59            ->map(fn (Order $o) => (object) [
60                'bar_code' => $o->bar_code,
61                'customer_name' => $o->customer->name ?? 'Guest',
62                'created_at' => $o->created_at,
63                'total' => (float) $o->total,
64                'discount' => (float) $o->discount,
65                'tax' => (float) $o->tax,
66                'due' => (float) $o->due,
67                'status' => $o->status,
68            ]);
69    }
70
71    public function summary(Collection $rows, array $filters): array
72    {
73        return [
74            'Orders' => number_format($rows->count()),
75            'Revenue' => money($rows->sum('total')),
76            'Avg. Order Value' => money($rows->count() ? $rows->avg('total') : 0),
77            'Outstanding Due' => money($rows->sum('due')),
78        ];
79    }
80}