Passed
Push — master ( fd7c1e...90cfdb )
by Adrien
14:46
created

AccountingReport::processAccounts()   D

Complexity

Conditions 21
Paths 13

Size

Total Lines 30
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 24
CRAP Score 21.0281

Importance

Changes 0
Metric Value
eloc 23
dl 0
loc 30
ccs 24
cts 25
cp 0.96
rs 4.1666
c 0
b 0
f 0
cc 21
nc 13
nop 2
crap 21.0281

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Application\Service\Exporter;
6
7
use Application\DBAL\Types\AccountTypeType;
8
use Application\Model\Account;
9
use Cake\Chronos\ChronosDate;
10
use Ecodev\Felix\Format;
11
use Money\Money;
12
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
13
use PhpOffice\PhpSpreadsheet\Style\Alignment;
14
use PhpOffice\PhpSpreadsheet\Style\Color;
15
use PhpOffice\PhpSpreadsheet\Style\Fill;
16
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
17
18
class AccountingReport extends AbstractExcel
19
{
20
    private ChronosDate $date;
21
22
    private array $assets = [];
23
24
    private array $liabilities = [];
25
26
    private array $expenses = [];
27
28
    private array $revenues = [];
29
30
    private static array $balanceFormat = [
31
        'fill' => [
32
            'fillType' => Fill::FILL_SOLID,
33
            'startColor' => [
34
                'argb' => 'FFDDDDDD',
35
            ],
36
        ],
37
        'numberFormat' => [
38
            'formatCode' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1, // eg. 12'345.67
39
        ],
40
    ];
41
42
    private static array $columnWidth = [
43
        'accountCode' => 11,
44
        'accountName' => 35,
45
        'balance' => 12,
46
    ];
47
48 1
    public function __construct(string $hostname, private readonly array $accountingConfig)
49
    {
50 1
        parent::__construct($hostname);
51
52 1
        $this->date = ChronosDate::today();
53
54 1
        $this->sheet->setTitle('Bilan + PP');
55 1
        $this->zebra = false;
56 1
        $this->autoFilter = false;
57
    }
58
59 1
    protected function getTitleForFilename(): string
60
    {
61 1
        return sprintf('compta_rapport_%s', $this->date->format('Y-m-d'));
62
    }
63
64 1
    public function setDate(ChronosDate $date): void
65
    {
66 1
        $this->date = $date;
67
    }
68
69 1
    protected function writeTitle(): void
70
    {
71 1
        $this->column = 1;
72 1
        $this->sheet->mergeCellsByColumnAndRow($this->column, $this->row, $this->column + 14, $this->row);
0 ignored issues
show
Deprecated Code introduced by
The function PhpOffice\PhpSpreadsheet...geCellsByColumnAndRow() has been deprecated: 1.23.0 Use the mergeCells() method with a cell address range such as 'C5:F8' instead;, or passing in an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 8]), or an AddressRange object. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

72
        /** @scrutinizer ignore-deprecated */ $this->sheet->mergeCellsByColumnAndRow($this->column, $this->row, $this->column + 14, $this->row);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
73 1
        $this->write(
74 1
            sprintf($this->hostname . ': rapport comptable au %s', $this->date->format('d.m.Y')),
75 1
            self::$titleFormat,
76 1
            self::$centerFormat
77 1
        );
78 1
        $this->sheet->getRowDimension($this->row)->setRowHeight(35);
79 1
        ++$this->row;
80
81 1
        $this->column = 1;
82 1
        $this->sheet->mergeCellsByColumnAndRow($this->column, $this->row, $this->column + 6, $this->row);
0 ignored issues
show
Deprecated Code introduced by
The function PhpOffice\PhpSpreadsheet...geCellsByColumnAndRow() has been deprecated: 1.23.0 Use the mergeCells() method with a cell address range such as 'C5:F8' instead;, or passing in an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 8]), or an AddressRange object. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

82
        /** @scrutinizer ignore-deprecated */ $this->sheet->mergeCellsByColumnAndRow($this->column, $this->row, $this->column + 6, $this->row);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
83 1
        $this->write(
84 1
            'Bilan',
85 1
            self::$titleFormat,
86 1
            self::$centerFormat
87 1
        );
88 1
        $this->column = 9;
89 1
        $this->sheet->mergeCellsByColumnAndRow($this->column, $this->row, $this->column + 6, $this->row);
0 ignored issues
show
Deprecated Code introduced by
The function PhpOffice\PhpSpreadsheet...geCellsByColumnAndRow() has been deprecated: 1.23.0 Use the mergeCells() method with a cell address range such as 'C5:F8' instead;, or passing in an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 8]), or an AddressRange object. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

89
        /** @scrutinizer ignore-deprecated */ $this->sheet->mergeCellsByColumnAndRow($this->column, $this->row, $this->column + 6, $this->row);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
90 1
        $this->write(
91 1
            'Résultat',
92 1
            self::$titleFormat,
93 1
            self::$centerFormat
94 1
        );
95
96 1
        $this->sheet->getRowDimension($this->row)->setRowHeight(35);
97 1
        ++$this->row;
98
    }
99
100 1
    private function processAccounts(array $accounts, int $depth): void
101
    {
102 1
        foreach ($accounts as $account) {
103 1
            $balance = $account->getBalanceAtDate($this->date);
104 1
            if ($this->accountingConfig['report']['showAccountsWithZeroBalance'] === false && $depth > 1 && $balance->isZero()) {
105
                continue;
106
            }
107 1
            if ($account->getType() === AccountTypeType::EQUITY) {
108
                // Don't show special accounts since it's an interim statement, their balance will be computed manually
109 1
                continue;
110
            }
111 1
            $data = [
112 1
                'code' => $account->getCode(),
113 1
                'name' => Format::truncate($account->getName(), 55),
114 1
                'depth' => $depth,
115 1
                'balance' => $balance,
116 1
                'account' => $account,
117 1
            ];
118 1
            if ($account->getType() === AccountTypeType::ASSET || ($account->getType() === AccountTypeType::GROUP && mb_substr((string) $account->getCode(), 0, 1) === '1')) {
119 1
                $this->assets[] = $data;
120 1
            } elseif ($account->getType() === AccountTypeType::LIABILITY || ($account->getType() === AccountTypeType::GROUP && mb_substr((string) $account->getCode(), 0, 1) === '2')) {
121 1
                $this->liabilities[] = $data;
122 1
            } elseif ($account->getType() === AccountTypeType::REVENUE || ($account->getType() === AccountTypeType::GROUP && mb_substr((string) $account->getCode(), 0, 1) === '3')) {
123 1
                $this->revenues[] = $data;
124 1
            } elseif ($account->getType() === AccountTypeType::EXPENSE || ($account->getType() === AccountTypeType::GROUP && in_array(mb_substr((string) $account->getCode(), 0, 1), ['4', '5', '6'], true))) {
125 1
                $this->expenses[] = $data;
126
            }
127 1
            if ($account->getType() === AccountTypeType::GROUP && $depth <= $this->accountingConfig['report']['maxAccountDepth'] && $account->getCode() !== $this->accountingConfig['customerDepositsAccountCode']) {
128 1
                $children = $account->getChildren()->toArray();
129 1
                $this->processAccounts($children, $depth + 1);
130
            }
131
        }
132
    }
133
134
    /**
135
     * @param Account[] $items
136
     */
137 1
    protected function writeData(array $items): void
138
    {
139 1
        $this->processAccounts($items, 1);
140
141 1
        $this->sheet->setShowGridlines(false);
142
143 1
        $profitOrLoss = $this->getProfitOrLoss();
144
145 1
        if ($profitOrLoss->isNegative()) {
146
            // A loss is written at the end of the Revenues and Assets columns
147
            $data = [
148
                'code' => '',
149
                'name' => 'Résultat intermédiaire (perte)',
150
                'depth' => 1,
151
                'balance' => $profitOrLoss->absolute(),
152
                'account' => null,
153
                'format' => ['font' => ['color' => ['argb' => Color::COLOR_RED]]],
154
            ];
155
            $this->revenues[] = $data;
156
            $this->assets[] = $data;
157
        } else {
158
            // A profit is written at the end of the Expenses and Liabilities columns
159 1
            $data = [
160 1
                'code' => '',
161 1
                'name' => 'Résultat intermédiaire (bénéfice)',
162 1
                'depth' => 1,
163 1
                'balance' => $profitOrLoss,
164 1
                'account' => null,
165 1
                'format' => ['font' => ['color' => ['argb' => Color::COLOR_DARKGREEN]]],
166 1
            ];
167 1
            $this->expenses[] = $data;
168 1
            $this->liabilities[] = $data;
169
        }
170
171
        // Assets
172 1
        $this->column = $initialColumn = 1;
173 1
        $initialRow = $this->row;
174 1
        $firstLine = true;
175 1
        $this->lastDataRow = $this->row;
176 1
        foreach ($this->assets as $index => $data) {
177 1
            if ($firstLine) {
178 1
                $this->sheet->getColumnDimensionByColumn($this->column)->setWidth(self::$columnWidth['accountCode']);
179
            }
180 1
            $format = ['font' => ['bold' => $data['depth'] <= 2]];
181 1
            $this->write(
182 1
                str_repeat('  ', $data['depth'] - 1) . $data['code'],
183 1
                ['alignment' => ['horizontal' => Alignment::HORIZONTAL_LEFT, 'indent' => 1]],
184 1
                $format
185 1
            );
186 1
            if ($firstLine) {
187 1
                $this->sheet->getColumnDimensionByColumn($this->column)->setWidth(self::$columnWidth['accountName']);
188
            }
189 1
            $this->write($data['name'], ['alignment' => ['wrapText' => true]], $format, $data['format'] ?? []);
190 1
            if ($firstLine) {
191 1
                $this->sheet->getColumnDimensionByColumn($this->column)->setWidth(self::$columnWidth['balance']);
192
            }
193
            // Store the coordinate of the cell to later compute totals
194 1
            $this->assets[$index]['cell'] = $this->sheet->getCellByColumnAndRow($this->column, $this->row)->getCoordinate();
0 ignored issues
show
Deprecated Code introduced by
The function PhpOffice\PhpSpreadsheet...getCellByColumnAndRow() has been deprecated: 1.23.0 Use the getCell() method with a cell address such as 'C5' instead;, or passing in an array of [$columnIndex, $row] (e.g. [3, 5]), or a CellAddress object. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

194
            $this->assets[$index]['cell'] = /** @scrutinizer ignore-deprecated */ $this->sheet->getCellByColumnAndRow($this->column, $this->row)->getCoordinate();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
195 1
            $this->write($data['balance'], self::$balanceFormat);
196
197 1
            $firstLine = false;
198 1
            ++$this->row;
199 1
            $this->column = $initialColumn;
200
201 1
            $this->lastDataRow = max($this->lastDataRow, $this->row);
202
        }
203
204
        // Liabilities
205 1
        $this->row = $initialRow;
206 1
        $this->column = $initialColumn = $initialColumn + 4;
207 1
        $firstLine = true;
208 1
        foreach ($this->liabilities as $index => $data) {
209 1
            if ($firstLine) {
210 1
                $this->sheet->getColumnDimensionByColumn($this->column)->setWidth(self::$columnWidth['balance']);
211
            }
212
            // Store the coordinate of the cell to later compute totals
213 1
            $this->liabilities[$index]['cell'] = $this->sheet->getCellByColumnAndRow($this->column, $this->row)->getCoordinate();
0 ignored issues
show
Deprecated Code introduced by
The function PhpOffice\PhpSpreadsheet...getCellByColumnAndRow() has been deprecated: 1.23.0 Use the getCell() method with a cell address such as 'C5' instead;, or passing in an array of [$columnIndex, $row] (e.g. [3, 5]), or a CellAddress object. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

213
            $this->liabilities[$index]['cell'] = /** @scrutinizer ignore-deprecated */ $this->sheet->getCellByColumnAndRow($this->column, $this->row)->getCoordinate();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
214 1
            $this->write($data['balance'], self::$balanceFormat);
215 1
            $format = ['font' => ['bold' => $data['depth'] <= 2]];
216 1
            if ($firstLine) {
217 1
                $this->sheet->getColumnDimensionByColumn($this->column)->setWidth(self::$columnWidth['accountCode']);
218
            }
219 1
            $this->write(
220 1
                str_repeat('  ', $data['depth'] - 1) . $data['code'],
221 1
                ['alignment' => ['horizontal' => Alignment::HORIZONTAL_LEFT, 'indent' => 1]],
222 1
                $format
223 1
            );
224 1
            if ($firstLine) {
225 1
                $this->sheet->getColumnDimensionByColumn($this->column)->setWidth(self::$columnWidth['accountName']);
226
            }
227 1
            $this->write($data['name'], ['alignment' => ['wrapText' => true]], $format, $data['format'] ?? []);
228 1
            $firstLine = false;
229 1
            ++$this->row;
230 1
            $this->column = $initialColumn;
231
232 1
            $this->lastDataRow = max($this->lastDataRow, $this->row);
233
        }
234
235
        // Expenses
236 1
        $this->row = $initialRow;
237 1
        $this->column = $initialColumn = $initialColumn + 4;
238 1
        $firstLine = true;
239 1
        foreach ($this->expenses as $index => $data) {
240 1
            if ($firstLine) {
241 1
                $this->sheet->getColumnDimensionByColumn($this->column)->setWidth(self::$columnWidth['accountCode']);
242
            }
243 1
            $format = ['font' => ['bold' => $data['depth'] === 1]];
244 1
            $this->write(
245 1
                str_repeat('  ', $data['depth'] - 1) . $data['code'],
246 1
                ['alignment' => ['horizontal' => Alignment::HORIZONTAL_LEFT, 'indent' => 1]],
247 1
                $format
248 1
            );
249 1
            if ($firstLine) {
250 1
                $this->sheet->getColumnDimensionByColumn($this->column)->setWidth(self::$columnWidth['accountName']);
251
            }
252 1
            $this->write($data['name'], ['alignment' => ['wrapText' => true]], $format, $data['format'] ?? []);
253 1
            if ($firstLine) {
254 1
                $this->sheet->getColumnDimensionByColumn($this->column)->setWidth(self::$columnWidth['balance']);
255
            }
256
            // Store the coordinate of the cell to later compute totals
257 1
            $this->expenses[$index]['cell'] = $this->sheet->getCellByColumnAndRow($this->column, $this->row)->getCoordinate();
0 ignored issues
show
Deprecated Code introduced by
The function PhpOffice\PhpSpreadsheet...getCellByColumnAndRow() has been deprecated: 1.23.0 Use the getCell() method with a cell address such as 'C5' instead;, or passing in an array of [$columnIndex, $row] (e.g. [3, 5]), or a CellAddress object. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

257
            $this->expenses[$index]['cell'] = /** @scrutinizer ignore-deprecated */ $this->sheet->getCellByColumnAndRow($this->column, $this->row)->getCoordinate();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
258 1
            $this->write($data['balance'], self::$balanceFormat);
259 1
            $firstLine = false;
260 1
            ++$this->row;
261 1
            $this->column = $initialColumn;
262
263 1
            $this->lastDataRow = max($this->lastDataRow, $this->row);
264
        }
265
266
        // Revenues
267 1
        $this->row = $initialRow;
268 1
        $this->column = $initialColumn = $initialColumn + 4;
269 1
        $firstLine = true;
270 1
        foreach ($this->revenues as $index => $data) {
271 1
            if ($firstLine) {
272 1
                $this->sheet->getColumnDimensionByColumn($this->column)->setWidth(self::$columnWidth['balance']);
273
            }
274
            // Store the coordinate of the cell to later compute totals
275 1
            $this->revenues[$index]['cell'] = $this->sheet->getCellByColumnAndRow($this->column, $this->row)->getCoordinate();
0 ignored issues
show
Deprecated Code introduced by
The function PhpOffice\PhpSpreadsheet...getCellByColumnAndRow() has been deprecated: 1.23.0 Use the getCell() method with a cell address such as 'C5' instead;, or passing in an array of [$columnIndex, $row] (e.g. [3, 5]), or a CellAddress object. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

275
            $this->revenues[$index]['cell'] = /** @scrutinizer ignore-deprecated */ $this->sheet->getCellByColumnAndRow($this->column, $this->row)->getCoordinate();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
276 1
            $this->write($data['balance'], self::$balanceFormat);
277 1
            $format = ['font' => ['bold' => $data['depth'] === 1]];
278 1
            if ($firstLine) {
279 1
                $this->sheet->getColumnDimensionByColumn($this->column)->setWidth(self::$columnWidth['accountCode']);
280
            }
281 1
            $this->write(
282 1
                str_repeat('  ', $data['depth'] - 1) . $data['code'],
283 1
                ['alignment' => ['horizontal' => Alignment::HORIZONTAL_LEFT, 'indent' => 1]],
284 1
                $format
285 1
            );
286 1
            if ($firstLine) {
287 1
                $this->sheet->getColumnDimensionByColumn($this->column)->setWidth(self::$columnWidth['accountName']);
288
            }
289 1
            $this->write($data['name'], ['alignment' => ['wrapText' => true]], $format, $data['format'] ?? []);
290 1
            $firstLine = false;
291 1
            ++$this->row;
292 1
            $this->column = $initialColumn;
293
294 1
            $this->lastDataRow = max($this->lastDataRow, $this->row);
295
        }
296
297 1
        $this->applyExtraFormatting();
298
    }
299
300 1
    private function getProfitOrLoss(): Money
301
    {
302
        // Sum the profit and loss root accounts
303 1
        $totalRevenues = $this->sumBalance($this->revenues);
304
305 1
        $totalExpenses = $this->sumBalance($this->expenses);
306
307 1
        return $totalRevenues->subtract($totalExpenses);
308
    }
309
310 1
    protected function getHeaders(): array
311
    {
312 1
        $headers = [];
313
314 1
        $headers[] = ['label' => 'Actifs', 'formats' => [self::$headerFormat, self::$centerFormat], 'colspan' => 3];
315 1
        $headers[] = ['label' => '', 'width' => 3, 'formats' => []]; // margin
316 1
        $headers[] = ['label' => 'Passifs', 'formats' => [self::$headerFormat, self::$centerFormat], 'colspan' => 3];
317
318 1
        $headers[] = ['label' => '', 'width' => 5, 'formats' => []]; // margin
319
320 1
        $headers[] = ['label' => 'Charges', 'formats' => [self::$headerFormat, self::$centerFormat], 'colspan' => 3];
321 1
        $headers[] = ['label' => '', 'width' => 3, 'formats' => []]; // margin
322 1
        $headers[] = ['label' => 'Profits', 'formats' => [self::$headerFormat, self::$centerFormat], 'colspan' => 3];
323
324 1
        return $headers;
325
    }
326
327 1
    protected function writeFooter(): void
328
    {
329 1
        $initialColumn = $this->column;
330
331
        // BALANCE SHEET
332
333
        // Assets
334
        // Account.code
335 1
        $this->write('');
336
        // Account.name
337 1
        $this->write('');
338
        // Account.balance
339 1
        $this->writeSum($this->assets);
340
341
        // Margin
342 1
        $this->write('');
343
344
        // Liabilities
345
        // Account.balance
346 1
        $this->writeSum($this->liabilities);
347
348
        // Account.code
349 1
        $this->write('');
350
        // Account.name
351 1
        $this->write('');
352
353
        // Margin
354 1
        $this->write('');
355
356
        // INCOME STATEMENT
357
358
        // Expenses
359
        // Account.code
360 1
        $this->write('');
361
        // Account.name
362 1
        $this->write('');
363
        // Account.balance
364 1
        $this->writeSum($this->expenses);
365
366
        // Margin
367 1
        $this->write('');
368
369
        // Revenues
370
        // Account.balance
371 1
        $this->writeSum($this->revenues);
372
        // Account.code
373 1
        $this->write('');
374
        // Account.name
375 1
        $this->write('');
376
377
        // Apply style
378 1
        $range = Coordinate::stringFromColumnIndex($initialColumn) . $this->row . ':' . Coordinate::stringFromColumnIndex($this->column - 1) . $this->row;
379 1
        $this->sheet->getStyle($range)->applyFromArray(self::$totalFormat);
380
    }
381
382 1
    private function applyExtraFormatting(): void
383
    {
384
        // Format balance numbers
385 1
        foreach ([3, 5, 11, 13] as $colIndex) {
386 1
            $range = Coordinate::stringFromColumnIndex($colIndex) . 4 . ':' . Coordinate::stringFromColumnIndex($colIndex) . $this->lastDataRow;
387 1
            $this->sheet->getStyle($range)->applyFromArray(self::$balanceFormat);
388
        }
389
390
        // Increase row height since account names can wrap on multiple lines
391 1
        for ($r = 4; $r <= $this->lastDataRow; ++$r) {
392 1
            $this->sheet->getRowDimension($r)->setRowHeight(30);
393
        }
394
    }
395
396 1
    private function writeSum(array $data): void
397
    {
398 1
        $cellsToSum = $this->cellsToSum($data);
399 1
        $sum = $cellsToSum ? '=SUM(' . implode(',', $cellsToSum) . ')' : '';
400 1
        $this->write($sum, self::$balanceFormat, self::$totalFormat);
401
    }
402
403 1
    private function cellsToSum(array $data): array
404
    {
405 1
        $cells = array_reduce($data, function (array $carry, $data) {
406 1
            if (isset($data['cell']) && ($data['depth'] === 1 || (int) mb_substr((string) $data['code'], 0, 1) > 6)) {
407 1
                $carry[] = $data['cell'];
408
            }
409
410 1
            return $carry;
411 1
        }, []);
412
413 1
        return $cells;
414
    }
415
416 1
    private function sumBalance(array $data): Money
417
    {
418 1
        $sum = array_reduce($data, function (Money $carry, $data) {
419 1
            if ($data['depth'] === 1 || (int) mb_substr((string) $data['code'], 0, 1) > 6) {
420 1
                return $carry->add($data['balance']);
421
            }
422
423 1
            return $carry;
424 1
        }, Money::CHF(0));
425
426 1
        return $sum;
427
    }
428
}
429