Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
17.24% covered (danger)
17.24%
5 / 29
62.50% covered (warning)
62.50%
5 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
MaterialConsumptionReport
17.24% covered (danger)
17.24%
5 / 29
62.50% covered (warning)
62.50%
5 / 8
44.28
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
 feature
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
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 / 14
0.00% covered (danger)
0.00%
0 / 1
2
 summary
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace App\Reports\Manufacturing;
4
5use App\Models\ProductionConsumption;
6use App\Reports\Report;
7use Illuminate\Support\Collection;
8
9/** Planned vs actual material usage — how accurate the BOM's quantities turned out to be. */
10class MaterialConsumptionReport extends Report
11{
12    public function key(): string
13    {
14        return 'material-consumption';
15    }
16
17    public function label(): string
18    {
19        return 'Material Consumption (Plan vs Actual)';
20    }
21
22    public function group(): string
23    {
24        return 'Manufacturing';
25    }
26
27    public function feature(): ?string
28    {
29        return 'manufacturing';
30    }
31
32    public function description(): ?string
33    {
34        return 'Every completed production order\'s material consumption, planned vs actually used.';
35    }
36
37    public function columns(): array
38    {
39        return [
40            ['key' => 'order_number', 'label' => 'Order'],
41            ['key' => 'material', 'label' => 'Material'],
42            ['key' => 'planned_qty', 'label' => 'Planned', 'align' => 'right'],
43            ['key' => 'actual_qty', 'label' => 'Actual', 'align' => 'right'],
44            ['key' => 'variance', 'label' => 'Variance', 'align' => 'right'],
45        ];
46    }
47
48    public function rows(array $filters): Collection
49    {
50        return ProductionConsumption::query()
51            ->whereNotNull('actual_qty')
52            ->with('order', 'material')
53            ->whereHas('order', fn ($q) => $q
54                ->whereDate('completed_at', '>=', $filters['from'])
55                ->whereDate('completed_at', '<=', $filters['to']))
56            ->get()
57            ->map(fn (ProductionConsumption $c) => (object) [
58                'order_number' => $c->order->number ?? '—',
59                'material' => $c->material->name ?? '—',
60                'planned_qty' => rtrim(rtrim((string) $c->planned_qty, '0'), '.'),
61                'actual_qty' => rtrim(rtrim((string) $c->actual_qty, '0'), '.'),
62                'variance' => rtrim(rtrim((string) ((float) $c->actual_qty - (float) $c->planned_qty), '0'), '.'),
63            ]);
64    }
65
66    public function summary(Collection $rows, array $filters): array
67    {
68        return [
69            'Consumption Lines' => number_format($rows->count()),
70        ];
71    }
72}