Passed
Push — develop ( b4818b...dcecff )
by Septianata
16:14
created

OrderExport::mergeCell()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 34
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 23
c 1
b 0
f 0
dl 0
loc 34
ccs 0
cts 22
cp 0
rs 9.552
cc 4
nc 6
nop 1
crap 20
1
<?php
2
3
namespace App\Exports;
4
5
use App\Models\Item;
6
use Illuminate\Contracts\Support\Responsable;
7
use Illuminate\Database\Eloquent\Builder;
8
use Illuminate\Support\Carbon;
9
use Illuminate\Support\Collection;
10
use Illuminate\Support\Str;
11
use Maatwebsite\Excel\Concerns\Exportable;
12
use Maatwebsite\Excel\Concerns\FromCollection;
13
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
14
use Maatwebsite\Excel\Concerns\WithColumnFormatting;
15
use Maatwebsite\Excel\Concerns\WithCustomValueBinder;
16
use Maatwebsite\Excel\Concerns\WithEvents;
17
use Maatwebsite\Excel\Concerns\WithHeadings;
18
use Maatwebsite\Excel\DefaultValueBinder;
19
use Maatwebsite\Excel\Events\AfterSheet;
20
use Maatwebsite\Excel\Excel;
21
use PhpOffice\PhpSpreadsheet\Cell\Cell;
22
use PhpOffice\PhpSpreadsheet\Cell\DataType;
23
use PhpOffice\PhpSpreadsheet\Style\Alignment;
24
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
25
26
class OrderExport extends DefaultValueBinder implements
27
    FromCollection,
28
    WithColumnFormatting,
29
    WithCustomValueBinder,
30
    WithEvents,
31
    WithHeadings,
32
    ShouldAutoSize,
33
    Responsable
34
{
35
    use Exportable;
0 ignored issues
show
introduced by
The trait Maatwebsite\Excel\Concerns\Exportable requires some properties which are not provided by App\Exports\OrderExport: $disk, $diskOptions, $filePath, $headers
Loading history...
36
37
    /**
38
     * It's required to define the fileName within
39
     * the export class when making use of Responsable.
40
     *
41
     * @var string
42
     */
43
    protected string $fileName;
44
45
    /**
46
     * Optional writer type.
47
     *
48
     * @var string
49
     */
50
    protected string $writerType = Excel::XLSX;
51
52
    /**
53
     * Total row of the collection.
54
     *
55
     * @var int
56
     */
57
    protected int $totalRow = 0;
58
59
    /**
60
     * Create a new instance class.
61
     *
62
     * @param  \Illuminate\Database\Eloquent\Builder  $query
63
     * @return void
64
     */
65
    public function __construct(protected Builder $query)
66
    {
67
        $this->fileName = 'Order Report - ' . Carbon::today()->format('Y-m-d') . '.' . Str::lower(Excel::XLSX);
68
    }
69
70
    /**
71
     * {@inheritDoc}
72
     */
73
    public function columnFormats(): array
74
    {
75
        return [
76
            'A' => NumberFormat::FORMAT_NUMBER,
77
            'B' => NumberFormat::FORMAT_TEXT,
78
            'C' => NumberFormat::FORMAT_TEXT,
79
            'D' => NumberFormat::FORMAT_TEXT,
80
            'E' => NumberFormat::FORMAT_NUMBER,
81
            'F' => NumberFormat::FORMAT_NUMBER,
82
            'G' => NumberFormat::FORMAT_NUMBER,
83
            'H' => NumberFormat::FORMAT_NUMBER,
84
            'I' => NumberFormat::FORMAT_TEXT,
85
        ];
86
    }
87
88
    /**
89
     * {@inheritDoc}
90
     */
91
    public function bindValue(Cell $cell, $value): bool
92
    {
93
        if (($this->columnFormats()[$cell->getColumn()] ?? null) === NumberFormat::FORMAT_TEXT) {
94
            $cell->setValueExplicit($value, DataType::TYPE_STRING);
95
96
            return true;
97
        }
98
99
        return parent::bindValue($cell, $value);
100
    }
101
102
    /**
103
     * @return array
104
     */
105
    public function registerEvents(): array
106
    {
107
        return [
108
            AfterSheet::class => function (AfterSheet $event) {
109
                $this->mergeCell($event);
110
            },
111
        ];
112
    }
113
114
    /**
115
     * Merge grand total and teller cell value of the same order data.
116
     *
117
     * @param  \Maatwebsite\Excel\Events\AfterSheet  $event
118
     * @return void
119
     */
120
    protected function mergeCell(AfterSheet $event)
121
    {
122
        $grandTotalIndex = array_search('Grand Total', $this->headings()) + 1;
123
        $tellerIndex = array_search('Teller', $this->headings()) + 1;
124
125
        $mergeRows = [];
126
        $currentMergeRowStart = 2;
127
128
        for ($row = $currentMergeRowStart; $row <= ($this->totalRow + 1); $row++) {
129
            $cell = $event->getSheet()->getDelegate()->getCellByColumnAndRow($grandTotalIndex, $row);
130
131
            if (!is_null($cell->getValue())) {
132
                $currentMergeRowStart = $row;
133
134
                continue;
135
            }
136
137
            $mergeRows[$currentMergeRowStart] = $row;
138
        }
139
140
        foreach ($mergeRows as $rowStart => $rowUntil) {
141
            $event->getSheet()->getDelegate()->mergeCellsByColumnAndRow(
142
                $grandTotalIndex, $rowStart,
143
                $grandTotalIndex, $rowUntil
144
            )->getStyleByColumnAndRow($grandTotalIndex, $rowStart)
145
            ->getAlignment()
146
            ->setVertical(Alignment::VERTICAL_CENTER);
147
148
            $event->getSheet()->getDelegate()->mergeCellsByColumnAndRow(
149
                $tellerIndex, $rowStart,
150
                $tellerIndex, $rowUntil
151
            )->getStyleByColumnAndRow($tellerIndex, $rowStart)
152
            ->getAlignment()
153
            ->setVertical(Alignment::VERTICAL_CENTER);
154
        }
155
    }
156
157
    /**
158
     * {@inheritDoc}
159
     */
160
    public function headings(): array
161
    {
162
        return [
163
            'No.',
164
            'Nama',
165
            'No Rekening/KTP',
166
            'Kode Referensi',
167
            'Pecahan',
168
            'Jumlah',
169
            'Rumus',
170
            'Grand Total',
171
            'Teller',
172
        ];
173
    }
174
175
    /**
176
     * {@inheritDoc}
177
     */
178
    public function collection(): Collection
179
    {
180
        /** @var \App\Models\Item|null */
181
        $lastItem = null;
182
183
        return $this->query->get()->map(function (Item $item, $index) use (&$lastItem) {
184
            $this->totalRow += 1;
185
186
            $showOrderTotal = is_null($lastItem) || !$item->order->is($lastItem->order);
187
188
            $lastItem = $item;
189
190
            return [
191
                $index + 1,
192
                $item->order->customer->fullname,
193
                ($item->order->customer->account_number ?? $item->order->customer->identitycard_number),
194
                $item->order->code,
195
                $item->denomination->value,
196
                $item->quantity,
197
                $item->total,
198
                $showOrderTotal ? $item->order->item_total : null,
199
                $item->order->user ? $item->order->user->fullname : trans('Unscheduled'),
200
            ];
201
        });
202
    }
203
}
204