Bladeren bron

wip Cash Flow Statement

3.x
Andrew Wallo 11 maanden geleden
bovenliggende
commit
8f1954b017

+ 2
- 1
app/Filament/Company/Pages/Reports.php Bestand weergeven

@@ -5,6 +5,7 @@ namespace App\Filament\Company\Pages;
5 5
 use App\Filament\Company\Pages\Reports\AccountBalances;
6 6
 use App\Filament\Company\Pages\Reports\AccountTransactions;
7 7
 use App\Filament\Company\Pages\Reports\BalanceSheet;
8
+use App\Filament\Company\Pages\Reports\CashFlowStatement;
8 9
 use App\Filament\Company\Pages\Reports\IncomeStatement;
9 10
 use App\Filament\Company\Pages\Reports\TrialBalance;
10 11
 use App\Infolists\Components\ReportEntry;
@@ -49,7 +50,7 @@ class Reports extends Page
49 50
                             ->description('Shows cash inflows and outflows over a specific period of time.')
50 51
                             ->icon('heroicon-o-document-currency-dollar')
51 52
                             ->iconColor(Color::Cyan)
52
-                            ->url('#'),
53
+                            ->url(CashFlowStatement::getUrl()),
53 54
                     ]),
54 55
                 Section::make('Detailed Reports')
55 56
                     ->aside()

+ 87
- 0
app/Filament/Company/Pages/Reports/CashFlowStatement.php Bestand weergeven

@@ -0,0 +1,87 @@
1
+<?php
2
+
3
+namespace App\Filament\Company\Pages\Reports;
4
+
5
+use App\Contracts\ExportableReport;
6
+use App\DTO\ReportDTO;
7
+use App\Services\ExportService;
8
+use App\Services\ReportService;
9
+use App\Support\Column;
10
+use App\Transformers\CashFlowStatementReportTransformer;
11
+use Filament\Forms\Form;
12
+use Filament\Support\Enums\Alignment;
13
+use Guava\FilamentClusters\Forms\Cluster;
14
+use Livewire\Attributes\Url;
15
+use Symfony\Component\HttpFoundation\StreamedResponse;
16
+
17
+class CashFlowStatement extends BaseReportPage
18
+{
19
+    protected static string $view = 'filament.company.pages.reports.cash-flow-statement';
20
+
21
+    protected static ?string $slug = 'reports/cash-flow-statement';
22
+
23
+    protected static bool $shouldRegisterNavigation = false;
24
+
25
+    protected ReportService $reportService;
26
+
27
+    protected ExportService $exportService;
28
+
29
+    #[Url]
30
+    public ?string $activeTab = 'summary';
31
+
32
+    public function boot(ReportService $reportService, ExportService $exportService): void
33
+    {
34
+        $this->reportService = $reportService;
35
+        $this->exportService = $exportService;
36
+    }
37
+
38
+    public function getTable(): array
39
+    {
40
+        return [
41
+            Column::make('account_code')
42
+                ->label('Account Code')
43
+                ->toggleable()
44
+                ->alignment(Alignment::Center),
45
+            Column::make('account_name')
46
+                ->label('Account')
47
+                ->alignment(Alignment::Left),
48
+            Column::make('net_movement')
49
+                ->label('Amount')
50
+                ->alignment(Alignment::Right),
51
+        ];
52
+    }
53
+
54
+    public function filtersForm(Form $form): Form
55
+    {
56
+        return $form
57
+            ->inlineLabel()
58
+            ->columns()
59
+            ->schema([
60
+                $this->getDateRangeFormComponent(),
61
+                Cluster::make([
62
+                    $this->getStartDateFormComponent(),
63
+                    $this->getEndDateFormComponent(),
64
+                ])->hiddenLabel(),
65
+            ]);
66
+    }
67
+
68
+    protected function buildReport(array $columns): ReportDTO
69
+    {
70
+        return $this->reportService->buildCashFlowStatementReport($this->getFormattedStartDate(), $this->getFormattedEndDate(), $columns);
71
+    }
72
+
73
+    protected function getTransformer(ReportDTO $reportDTO): ExportableReport
74
+    {
75
+        return new CashFlowStatementReportTransformer($reportDTO);
76
+    }
77
+
78
+    public function exportCSV(): StreamedResponse
79
+    {
80
+        return $this->exportService->exportToCsv($this->company, $this->report, $this->getFilterState('startDate'), $this->getFilterState('endDate'));
81
+    }
82
+
83
+    public function exportPDF(): StreamedResponse
84
+    {
85
+        return $this->exportService->exportToPdf($this->company, $this->report, $this->getFilterState('startDate'), $this->getFilterState('endDate'));
86
+    }
87
+}

+ 166
- 0
app/Services/ReportService.php Bestand weergeven

@@ -432,6 +432,172 @@ class ReportService
432 432
         return new ReportDTO($accountCategories, $formattedReportTotalBalances, $columns);
433 433
     }
434 434
 
435
+    public function buildCashFlowStatementReport(string $startDate, string $endDate, array $columns = []): ReportDTO
436
+    {
437
+        $sections = [
438
+            'Operating Activities' => $this->buildOperatingActivities($startDate, $endDate),
439
+            'Investing Activities' => $this->buildInvestingActivities($startDate, $endDate),
440
+            'Financing Activities' => $this->buildFinancingActivities($startDate, $endDate),
441
+        ];
442
+
443
+        $totalCashFlows = $this->calculateTotalCashFlows($sections);
444
+
445
+        ray($sections);
446
+
447
+        return new ReportDTO($sections, $totalCashFlows, $columns);
448
+    }
449
+
450
+    private function buildOperatingActivities(string $startDate, string $endDate): AccountCategoryDTO
451
+    {
452
+        $accounts = $this->accountService->getAccountBalances($startDate, $endDate)
453
+            ->whereIn('accounts.type', [
454
+                AccountType::OperatingRevenue,
455
+                AccountType::UncategorizedRevenue,
456
+                AccountType::OperatingExpense,
457
+                AccountType::NonOperatingExpense,
458
+                AccountType::UncategorizedExpense,
459
+                AccountType::CurrentAsset,
460
+            ])
461
+            ->whereRelation('subtype', 'name', '!=', 'Cash and Cash Equivalents')
462
+            ->orderByRaw('LENGTH(code), code')
463
+            ->get();
464
+
465
+        $adjustments = $this->accountService->getAccountBalances($startDate, $endDate)
466
+            ->whereIn('accounts.type', [
467
+                AccountType::ContraAsset,
468
+                AccountType::CurrentLiability,
469
+            ])
470
+            ->whereRelation('subtype', 'name', '!=', 'Short-Term Borrowings')
471
+            ->orderByRaw('LENGTH(code), code')
472
+            ->get();
473
+
474
+        return $this->formatSectionAccounts('Operating Activities', $accounts, $adjustments, $startDate, $endDate);
475
+    }
476
+
477
+    private function buildInvestingActivities(string $startDate, string $endDate): AccountCategoryDTO
478
+    {
479
+        $accounts = $this->accountService->getAccountBalances($startDate, $endDate)
480
+            ->whereIn('accounts.type', [AccountType::NonCurrentAsset])
481
+            ->orderByRaw('LENGTH(code), code')
482
+            ->get();
483
+
484
+        $adjustments = $this->accountService->getAccountBalances($startDate, $endDate)
485
+            ->whereIn('accounts.type', [AccountType::NonOperatingRevenue])
486
+            ->orderByRaw('LENGTH(code), code')
487
+            ->get();
488
+
489
+        return $this->formatSectionAccounts('Investing Activities', $accounts, $adjustments, $startDate, $endDate);
490
+    }
491
+
492
+    private function buildFinancingActivities(string $startDate, string $endDate): AccountCategoryDTO
493
+    {
494
+        $accounts = $this->accountService->getAccountBalances($startDate, $endDate)
495
+            ->where(function (Builder $query) {
496
+                $query->whereIn('accounts.type', [
497
+                    AccountType::Equity,
498
+                    AccountType::NonCurrentLiability,
499
+                ])
500
+                    ->orWhere(function (Builder $subQuery) {
501
+                        $subQuery->where('accounts.type', AccountType::CurrentLiability)
502
+                            ->whereRelation('subtype', 'name', 'Short-Term Borrowings');
503
+                    });
504
+            })
505
+            ->orderByRaw('LENGTH(code), code')
506
+            ->get();
507
+
508
+        return $this->formatSectionAccounts('Financing Activities', $accounts, [], $startDate, $endDate);
509
+    }
510
+
511
+    private function formatSectionAccounts(
512
+        string $sectionName,
513
+        $accounts,
514
+        $adjustments,
515
+        string $startDate,
516
+        string $endDate
517
+    ): AccountCategoryDTO {
518
+        $accountTypes = [];
519
+        $sectionTotal = 0;
520
+
521
+        foreach ($accounts as $account) {
522
+            $accountCategory = $account->type->getCategory();
523
+            $accountBalances = $this->calculateAccountBalances($account, $accountCategory);
524
+            $netCashFlow = $accountBalances['ending_balance'] ?? $accountBalances['net_movement'] ?? 0;
525
+            $sectionTotal += $netCashFlow;
526
+
527
+            $formattedAccountBalances = $this->formatBalances(['net_movement' => $netCashFlow]);
528
+
529
+            $accountDTO = new AccountDTO(
530
+                $account->name,
531
+                $account->code,
532
+                $account->id,
533
+                $formattedAccountBalances,
534
+                $startDate,
535
+                $endDate,
536
+            );
537
+
538
+            $accountTypeName = $account->subtype->name;
539
+            $accountTypes[$accountTypeName]['accounts'][] = $accountDTO;
540
+        }
541
+
542
+        foreach ($adjustments as $adjustment) {
543
+            $accountCategory = $adjustment->type->getCategory();
544
+            $adjustmentBalances = $this->calculateAccountBalances($adjustment, $accountCategory);
545
+            $netCashFlow = $adjustmentBalances['ending_balance'] ?? $adjustmentBalances['net_movement'] ?? 0;
546
+            $sectionTotal += $netCashFlow;
547
+
548
+            $formattedAdjustmentBalances = $this->formatBalances(['net_movement' => $netCashFlow]);
549
+
550
+            $accountDTO = new AccountDTO(
551
+                $adjustment->name,
552
+                $adjustment->code,
553
+                $adjustment->id,
554
+                $formattedAdjustmentBalances,
555
+                $startDate,
556
+                $endDate,
557
+            );
558
+
559
+            $accountTypeName = $adjustment->subtype->name;
560
+            $accountTypes[$accountTypeName]['accounts'][] = $accountDTO;
561
+        }
562
+
563
+        $formattedSectionTotal = $this->formatBalances(['net_movement' => $sectionTotal]);
564
+
565
+        // Convert each type array to AccountTypeDTO with summary balance
566
+        foreach ($accountTypes as $typeName => &$typeData) {
567
+            $typeNetMovement = array_reduce($typeData['accounts'], function ($carry, $account) {
568
+                return $carry + (float) \money($account->balance->netMovement, CurrencyAccessor::getDefaultCurrency(), true)->getAmount();
569
+            }, 0);
570
+
571
+            $formattedTypeBalance = $this->formatBalances(['net_movement' => $typeNetMovement]);
572
+
573
+            $typeData = new AccountTypeDTO(
574
+                accounts: $typeData['accounts'],
575
+                summary: $formattedTypeBalance
576
+            );
577
+        }
578
+
579
+        return new AccountCategoryDTO(
580
+            accounts: [], // No direct accounts, only types in cash flow
581
+            types: $accountTypes, // Structured by AccountTypeDTO
582
+            summary: $formattedSectionTotal,
583
+        );
584
+    }
585
+
586
+    private function calculateTotalCashFlows(array $sections): AccountBalanceDTO
587
+    {
588
+        $totalCashFlow = 0;
589
+
590
+        foreach ($sections as $section) {
591
+            $netMovement = $section->summary->netMovement ?? 0;
592
+
593
+            $numericNetMovement = money($netMovement, CurrencyAccessor::getDefaultCurrency())->getAmount();
594
+
595
+            $totalCashFlow += $numericNetMovement;
596
+        }
597
+
598
+        return $this->formatBalances(['net_movement' => $totalCashFlow]);
599
+    }
600
+
435 601
     public function buildBalanceSheetReport(string $asOfDate, array $columns = []): ReportDTO
436 602
     {
437 603
         $asOfDateCarbon = Carbon::parse($asOfDate);

+ 252
- 0
app/Transformers/CashFlowStatementReportTransformer.php Bestand weergeven

@@ -0,0 +1,252 @@
1
+<?php
2
+
3
+namespace App\Transformers;
4
+
5
+use App\DTO\AccountDTO;
6
+use App\DTO\ReportCategoryDTO;
7
+use App\DTO\ReportDTO;
8
+use App\DTO\ReportTypeDTO;
9
+use App\Utilities\Currency\CurrencyAccessor;
10
+
11
+class CashFlowStatementReportTransformer extends SummaryReportTransformer
12
+{
13
+    protected string $totalOperatingActivities;
14
+
15
+    protected string $totalInvestingActivities;
16
+
17
+    protected string $totalFinancingActivities;
18
+
19
+    protected string $grossCashInflow;
20
+
21
+    protected string $grossCashOutflow;
22
+
23
+    public function __construct(ReportDTO $report)
24
+    {
25
+        parent::__construct($report);
26
+
27
+        $this->calculateTotals();
28
+    }
29
+
30
+    public function getTitle(): string
31
+    {
32
+        return 'Cash Flow Statement';
33
+    }
34
+
35
+    public function calculateTotals(): void
36
+    {
37
+        $cashInflow = 0;
38
+        $cashOutflow = 0;
39
+
40
+        foreach ($this->report->categories as $categoryName => $category) {
41
+            $netMovement = (float) money($category->summary->netMovement, CurrencyAccessor::getDefaultCurrency())->getAmount();
42
+
43
+            match ($categoryName) {
44
+                'Operating Activities' => $this->totalOperatingActivities = $netMovement,
45
+                'Investing Activities' => $this->totalInvestingActivities = $netMovement,
46
+                'Financing Activities' => $this->totalFinancingActivities = $netMovement,
47
+            };
48
+
49
+            // Sum inflows and outflows separately
50
+            if ($netMovement > 0) {
51
+                $cashInflow += $netMovement;
52
+            } else {
53
+                $cashOutflow += $netMovement;
54
+            }
55
+        }
56
+
57
+        // Store gross totals
58
+        $this->grossCashInflow = money($cashInflow, CurrencyAccessor::getDefaultCurrency())->format();
59
+        $this->grossCashOutflow = money($cashOutflow, CurrencyAccessor::getDefaultCurrency())->format();
60
+    }
61
+
62
+    public function getCategories(): array
63
+    {
64
+        $categories = [];
65
+
66
+        foreach ($this->report->categories as $accountCategoryName => $accountCategory) {
67
+            // Header for the main category
68
+            $header = [];
69
+
70
+            foreach ($this->getColumns() as $column) {
71
+                $header[$column->getName()] = $column->getName() === 'account_name' ? $accountCategoryName : '';
72
+            }
73
+
74
+            // Category-level summary
75
+            $categorySummary = [];
76
+            foreach ($this->getColumns() as $column) {
77
+                $categorySummary[$column->getName()] = match ($column->getName()) {
78
+                    'account_name' => 'Total ' . $accountCategoryName,
79
+                    'net_movement' => $accountCategory->summary->netMovement ?? '',
80
+                    default => '',
81
+                };
82
+            }
83
+
84
+            // Accounts directly under the main category
85
+            $data = array_map(function (AccountDTO $account) {
86
+                $row = [];
87
+
88
+                foreach ($this->getColumns() as $column) {
89
+                    $row[$column->getName()] = match ($column->getName()) {
90
+                        'account_code' => $account->accountCode,
91
+                        'account_name' => [
92
+                            'name' => $account->accountName,
93
+                            'id' => $account->accountId ?? null,
94
+                            'start_date' => $account->startDate,
95
+                            'end_date' => $account->endDate,
96
+                        ],
97
+                        'net_movement' => $account->balance->netMovement ?? '',
98
+                        default => '',
99
+                    };
100
+                }
101
+
102
+                return $row;
103
+            }, $accountCategory->accounts ?? []);
104
+
105
+            // Subcategories (types) under the main category
106
+            $types = [];
107
+            ray($accountCategory->types);
108
+            foreach ($accountCategory->types as $typeName => $type) {
109
+                // Header for subcategory (type)
110
+                $typeHeader = [];
111
+                foreach ($this->getColumns() as $column) {
112
+                    $typeHeader[$column->getName()] = $column->getName() === 'account_name' ? $typeName : '';
113
+                }
114
+
115
+                ray($typeHeader);
116
+
117
+                // Account data for the subcategory
118
+                $typeData = array_map(function (AccountDTO $account) {
119
+                    $row = [];
120
+
121
+                    foreach ($this->getColumns() as $column) {
122
+                        $row[$column->getName()] = match ($column->getName()) {
123
+                            'account_code' => $account->accountCode,
124
+                            'account_name' => [
125
+                                'name' => $account->accountName,
126
+                                'id' => $account->accountId ?? null,
127
+                                'start_date' => $account->startDate,
128
+                                'end_date' => $account->endDate,
129
+                            ],
130
+                            'net_movement' => $account->balance->netMovement ?? '',
131
+                            default => '',
132
+                        };
133
+                    }
134
+
135
+                    return $row;
136
+                }, $type->accounts ?? []);
137
+
138
+                ray($typeData);
139
+
140
+                // Subcategory (type) summary
141
+                $typeSummary = [];
142
+                foreach ($this->getColumns() as $column) {
143
+                    $typeSummary[$column->getName()] = match ($column->getName()) {
144
+                        'account_name' => 'Total ' . $typeName,
145
+                        'net_movement' => $type->summary->netMovement ?? '',
146
+                        default => '',
147
+                    };
148
+                }
149
+
150
+                // Add subcategory (type) to the list
151
+                $types[$typeName] = new ReportTypeDTO(
152
+                    header: $typeHeader,
153
+                    data: $typeData,
154
+                    summary: $typeSummary,
155
+                );
156
+            }
157
+
158
+            // Add the category to the final array with its direct accounts and subcategories (types)
159
+            $categories[$accountCategoryName] = new ReportCategoryDTO(
160
+                header: $header,
161
+                data: $data, // Direct accounts under the category
162
+                summary: $categorySummary,
163
+                types: $types, // Subcategories (types) under the category
164
+            );
165
+        }
166
+
167
+        return $categories;
168
+    }
169
+
170
+    public function getSummaryCategories(): array
171
+    {
172
+        $summaryCategories = [];
173
+
174
+        $columns = $this->getSummaryColumns();
175
+
176
+        foreach ($this->report->categories as $accountCategoryName => $accountCategory) {
177
+            $categoryHeader = [];
178
+
179
+            foreach ($columns as $column) {
180
+                $categoryHeader[$column->getName()] = $column->getName() === 'account_name' ? $accountCategoryName : '';
181
+            }
182
+
183
+            $categorySummary = [];
184
+            foreach ($columns as $column) {
185
+                $categorySummary[$column->getName()] = match ($column->getName()) {
186
+                    'account_name' => 'Total ' . $accountCategoryName,
187
+                    'net_movement' => $accountCategory->summary->netMovement ?? '',
188
+                    default => '',
189
+                };
190
+            }
191
+
192
+            $types = [];
193
+
194
+            // Iterate through each account type and calculate type summaries
195
+            foreach ($accountCategory->types as $typeName => $type) {
196
+                $typeSummary = [];
197
+
198
+                foreach ($columns as $column) {
199
+                    $typeSummary[$column->getName()] = match ($column->getName()) {
200
+                        'account_name' => 'Total ' . $typeName,
201
+                        'net_movement' => $type->summary->netMovement ?? '',
202
+                        default => '',
203
+                    };
204
+                }
205
+
206
+                $types[$typeName] = new ReportTypeDTO(
207
+                    header: [],
208
+                    data: [],
209
+                    summary: $typeSummary,
210
+                );
211
+            }
212
+
213
+            // Add the category with its types and summary to the final array
214
+            $summaryCategories[$accountCategoryName] = new ReportCategoryDTO(
215
+                header: $categoryHeader,
216
+                data: [],
217
+                summary: $categorySummary,
218
+                types: $types,
219
+            );
220
+        }
221
+
222
+        return $summaryCategories;
223
+    }
224
+
225
+    public function getOverallTotals(): array
226
+    {
227
+        return [];
228
+    }
229
+
230
+    public function getSummaryOverallTotals(): array
231
+    {
232
+        return [];
233
+    }
234
+
235
+    public function getSummary(): array
236
+    {
237
+        return [
238
+            [
239
+                'label' => 'Gross Cash Inflow',
240
+                'value' => $this->grossCashInflow,
241
+            ],
242
+            [
243
+                'label' => 'Gross Cash Outflow',
244
+                'value' => $this->grossCashOutflow,
245
+            ],
246
+            [
247
+                'label' => 'Net Cash Flow',
248
+                'value' => $this->report->overallTotal->netMovement ?? '',
249
+            ],
250
+        ];
251
+    }
252
+}

+ 184
- 184
composer.lock
Diff onderdrukt omdat het te groot bestand
Bestand weergeven


+ 45
- 0
config/chart-of-accounts.php Bestand weergeven

@@ -410,4 +410,49 @@ return [
410 410
             ],
411 411
         ],
412 412
     ],
413
+
414
+    'cash_flow' => [
415
+        'operating_activities' => [
416
+            'directly_listed' => [
417
+                'operating_revenue',
418
+                'uncategorized_revenue',
419
+                'operating_expense',
420
+                'non_operating_expense', // e.g., interest expense
421
+                'uncategorized_expense',
422
+                'current_asset', // All current assets except for 'Cash and Cash Equivalents'
423
+            ],
424
+            'adjustments' => [
425
+                'types' => [
426
+                    'contra_asset', // Adjustments like accumulated depreciation
427
+                    'current_liability', // Changes in accounts like Accounts Payable, Accrued Expenses
428
+                ],
429
+            ],
430
+        ],
431
+        'investing_activities' => [
432
+            'directly_listed' => [
433
+                'non_current_asset', // Purchases or sales of long-term assets
434
+            ],
435
+            'adjustments' => [
436
+                'types' => [
437
+                    'non_operating_revenue', // Gains or losses on asset sales
438
+                ],
439
+            ],
440
+        ],
441
+        'financing_activities' => [
442
+            'directly_listed' => [
443
+                'equity', // Cash flows from issuing stock, dividends paid
444
+                'non_current_liability', // Cash flows related to long-term debt
445
+                'short_term_borrowings', // Proceeds or repayments of short-term loans
446
+            ],
447
+        ],
448
+        'missing_activities' => [
449
+            'types' => [
450
+                'contra_liability', // Adjustments, not direct cash flows
451
+                'contra_equity', // E.g., treasury stock adjustments
452
+                'contra_revenue', // Sales returns or allowances
453
+                'contra_expense', // Purchase discounts
454
+                'Cash and Cash Equivalents', // Only appears in beginning/ending balances
455
+            ],
456
+        ],
457
+    ],
413 458
 ];

+ 1
- 1
database/seeders/DatabaseSeeder.php Bestand weergeven

@@ -20,7 +20,7 @@ class DatabaseSeeder extends Seeder
20 20
                     ->state([
21 21
                         'name' => 'ERPSAAS',
22 22
                     ])
23
-                    ->withTransactions();
23
+                    ->withTransactions(10000);
24 24
             })
25 25
             ->create([
26 26
                 'name' => 'Admin',

+ 123
- 93
package-lock.json Bestand weergeven

@@ -541,9 +541,9 @@
541 541
             }
542 542
         },
543 543
         "node_modules/@rollup/rollup-android-arm-eabi": {
544
-            "version": "4.24.0",
545
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz",
546
-            "integrity": "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==",
544
+            "version": "4.24.2",
545
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.2.tgz",
546
+            "integrity": "sha512-ufoveNTKDg9t/b7nqI3lwbCG/9IJMhADBNjjz/Jn6LxIZxD7T5L8l2uO/wD99945F1Oo8FvgbbZJRguyk/BdzA==",
547 547
             "cpu": [
548 548
                 "arm"
549 549
             ],
@@ -555,9 +555,9 @@
555 555
             ]
556 556
         },
557 557
         "node_modules/@rollup/rollup-android-arm64": {
558
-            "version": "4.24.0",
559
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz",
560
-            "integrity": "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==",
558
+            "version": "4.24.2",
559
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.2.tgz",
560
+            "integrity": "sha512-iZoYCiJz3Uek4NI0J06/ZxUgwAfNzqltK0MptPDO4OR0a88R4h0DSELMsflS6ibMCJ4PnLvq8f7O1d7WexUvIA==",
561 561
             "cpu": [
562 562
                 "arm64"
563 563
             ],
@@ -569,9 +569,9 @@
569 569
             ]
570 570
         },
571 571
         "node_modules/@rollup/rollup-darwin-arm64": {
572
-            "version": "4.24.0",
573
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz",
574
-            "integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==",
572
+            "version": "4.24.2",
573
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.2.tgz",
574
+            "integrity": "sha512-/UhrIxobHYCBfhi5paTkUDQ0w+jckjRZDZ1kcBL132WeHZQ6+S5v9jQPVGLVrLbNUebdIRpIt00lQ+4Z7ys4Rg==",
575 575
             "cpu": [
576 576
                 "arm64"
577 577
             ],
@@ -583,9 +583,9 @@
583 583
             ]
584 584
         },
585 585
         "node_modules/@rollup/rollup-darwin-x64": {
586
-            "version": "4.24.0",
587
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz",
588
-            "integrity": "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==",
586
+            "version": "4.24.2",
587
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.2.tgz",
588
+            "integrity": "sha512-1F/jrfhxJtWILusgx63WeTvGTwE4vmsT9+e/z7cZLKU8sBMddwqw3UV5ERfOV+H1FuRK3YREZ46J4Gy0aP3qDA==",
589 589
             "cpu": [
590 590
                 "x64"
591 591
             ],
@@ -596,10 +596,38 @@
596 596
                 "darwin"
597 597
             ]
598 598
         },
599
+        "node_modules/@rollup/rollup-freebsd-arm64": {
600
+            "version": "4.24.2",
601
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.24.2.tgz",
602
+            "integrity": "sha512-1YWOpFcGuC6iGAS4EI+o3BV2/6S0H+m9kFOIlyFtp4xIX5rjSnL3AwbTBxROX0c8yWtiWM7ZI6mEPTI7VkSpZw==",
603
+            "cpu": [
604
+                "arm64"
605
+            ],
606
+            "dev": true,
607
+            "license": "MIT",
608
+            "optional": true,
609
+            "os": [
610
+                "freebsd"
611
+            ]
612
+        },
613
+        "node_modules/@rollup/rollup-freebsd-x64": {
614
+            "version": "4.24.2",
615
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.24.2.tgz",
616
+            "integrity": "sha512-3qAqTewYrCdnOD9Gl9yvPoAoFAVmPJsBvleabvx4bnu1Kt6DrB2OALeRVag7BdWGWLhP1yooeMLEi6r2nYSOjg==",
617
+            "cpu": [
618
+                "x64"
619
+            ],
620
+            "dev": true,
621
+            "license": "MIT",
622
+            "optional": true,
623
+            "os": [
624
+                "freebsd"
625
+            ]
626
+        },
599 627
         "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
600
-            "version": "4.24.0",
601
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz",
602
-            "integrity": "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==",
628
+            "version": "4.24.2",
629
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.2.tgz",
630
+            "integrity": "sha512-ArdGtPHjLqWkqQuoVQ6a5UC5ebdX8INPuJuJNWRe0RGa/YNhVvxeWmCTFQ7LdmNCSUzVZzxAvUznKaYx645Rig==",
603 631
             "cpu": [
604 632
                 "arm"
605 633
             ],
@@ -611,9 +639,9 @@
611 639
             ]
612 640
         },
613 641
         "node_modules/@rollup/rollup-linux-arm-musleabihf": {
614
-            "version": "4.24.0",
615
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz",
616
-            "integrity": "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==",
642
+            "version": "4.24.2",
643
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.2.tgz",
644
+            "integrity": "sha512-B6UHHeNnnih8xH6wRKB0mOcJGvjZTww1FV59HqJoTJ5da9LCG6R4SEBt6uPqzlawv1LoEXSS0d4fBlHNWl6iYw==",
617 645
             "cpu": [
618 646
                 "arm"
619 647
             ],
@@ -625,9 +653,9 @@
625 653
             ]
626 654
         },
627 655
         "node_modules/@rollup/rollup-linux-arm64-gnu": {
628
-            "version": "4.24.0",
629
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz",
630
-            "integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==",
656
+            "version": "4.24.2",
657
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.2.tgz",
658
+            "integrity": "sha512-kr3gqzczJjSAncwOS6i7fpb4dlqcvLidqrX5hpGBIM1wtt0QEVtf4wFaAwVv8QygFU8iWUMYEoJZWuWxyua4GQ==",
631 659
             "cpu": [
632 660
                 "arm64"
633 661
             ],
@@ -639,9 +667,9 @@
639 667
             ]
640 668
         },
641 669
         "node_modules/@rollup/rollup-linux-arm64-musl": {
642
-            "version": "4.24.0",
643
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz",
644
-            "integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==",
670
+            "version": "4.24.2",
671
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.2.tgz",
672
+            "integrity": "sha512-TDdHLKCWgPuq9vQcmyLrhg/bgbOvIQ8rtWQK7MRxJ9nvaxKx38NvY7/Lo6cYuEnNHqf6rMqnivOIPIQt6H2AoA==",
645 673
             "cpu": [
646 674
                 "arm64"
647 675
             ],
@@ -653,9 +681,9 @@
653 681
             ]
654 682
         },
655 683
         "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
656
-            "version": "4.24.0",
657
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz",
658
-            "integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==",
684
+            "version": "4.24.2",
685
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.2.tgz",
686
+            "integrity": "sha512-xv9vS648T3X4AxFFZGWeB5Dou8ilsv4VVqJ0+loOIgDO20zIhYfDLkk5xoQiej2RiSQkld9ijF/fhLeonrz2mw==",
659 687
             "cpu": [
660 688
                 "ppc64"
661 689
             ],
@@ -667,9 +695,9 @@
667 695
             ]
668 696
         },
669 697
         "node_modules/@rollup/rollup-linux-riscv64-gnu": {
670
-            "version": "4.24.0",
671
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz",
672
-            "integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==",
698
+            "version": "4.24.2",
699
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.2.tgz",
700
+            "integrity": "sha512-tbtXwnofRoTt223WUZYiUnbxhGAOVul/3StZ947U4A5NNjnQJV5irKMm76G0LGItWs6y+SCjUn/Q0WaMLkEskg==",
673 701
             "cpu": [
674 702
                 "riscv64"
675 703
             ],
@@ -681,9 +709,9 @@
681 709
             ]
682 710
         },
683 711
         "node_modules/@rollup/rollup-linux-s390x-gnu": {
684
-            "version": "4.24.0",
685
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz",
686
-            "integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==",
712
+            "version": "4.24.2",
713
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.2.tgz",
714
+            "integrity": "sha512-gc97UebApwdsSNT3q79glOSPdfwgwj5ELuiyuiMY3pEWMxeVqLGKfpDFoum4ujivzxn6veUPzkGuSYoh5deQ2Q==",
687 715
             "cpu": [
688 716
                 "s390x"
689 717
             ],
@@ -695,9 +723,9 @@
695 723
             ]
696 724
         },
697 725
         "node_modules/@rollup/rollup-linux-x64-gnu": {
698
-            "version": "4.24.0",
699
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz",
700
-            "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==",
726
+            "version": "4.24.2",
727
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.2.tgz",
728
+            "integrity": "sha512-jOG/0nXb3z+EM6SioY8RofqqmZ+9NKYvJ6QQaa9Mvd3RQxlH68/jcB/lpyVt4lCiqr04IyaC34NzhUqcXbB5FQ==",
701 729
             "cpu": [
702 730
                 "x64"
703 731
             ],
@@ -709,9 +737,9 @@
709 737
             ]
710 738
         },
711 739
         "node_modules/@rollup/rollup-linux-x64-musl": {
712
-            "version": "4.24.0",
713
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz",
714
-            "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==",
740
+            "version": "4.24.2",
741
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.2.tgz",
742
+            "integrity": "sha512-XAo7cJec80NWx9LlZFEJQxqKOMz/lX3geWs2iNT5CHIERLFfd90f3RYLLjiCBm1IMaQ4VOX/lTC9lWfzzQm14Q==",
715 743
             "cpu": [
716 744
                 "x64"
717 745
             ],
@@ -723,9 +751,9 @@
723 751
             ]
724 752
         },
725 753
         "node_modules/@rollup/rollup-win32-arm64-msvc": {
726
-            "version": "4.24.0",
727
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz",
728
-            "integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==",
754
+            "version": "4.24.2",
755
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.2.tgz",
756
+            "integrity": "sha512-A+JAs4+EhsTjnPQvo9XY/DC0ztaws3vfqzrMNMKlwQXuniBKOIIvAAI8M0fBYiTCxQnElYu7mLk7JrhlQ+HeOw==",
729 757
             "cpu": [
730 758
                 "arm64"
731 759
             ],
@@ -737,9 +765,9 @@
737 765
             ]
738 766
         },
739 767
         "node_modules/@rollup/rollup-win32-ia32-msvc": {
740
-            "version": "4.24.0",
741
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz",
742
-            "integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==",
768
+            "version": "4.24.2",
769
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.2.tgz",
770
+            "integrity": "sha512-ZhcrakbqA1SCiJRMKSU64AZcYzlZ/9M5LaYil9QWxx9vLnkQ9Vnkve17Qn4SjlipqIIBFKjBES6Zxhnvh0EAEw==",
743 771
             "cpu": [
744 772
                 "ia32"
745 773
             ],
@@ -751,9 +779,9 @@
751 779
             ]
752 780
         },
753 781
         "node_modules/@rollup/rollup-win32-x64-msvc": {
754
-            "version": "4.24.0",
755
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz",
756
-            "integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==",
782
+            "version": "4.24.2",
783
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.2.tgz",
784
+            "integrity": "sha512-2mLH46K1u3r6uwc95hU+OR9q/ggYMpnS7pSp83Ece1HUQgF9Nh/QwTK5rcgbFnV9j+08yBrU5sA/P0RK2MSBNA==",
757 785
             "cpu": [
758 786
                 "x64"
759 787
             ],
@@ -998,9 +1026,9 @@
998 1026
             }
999 1027
         },
1000 1028
         "node_modules/caniuse-lite": {
1001
-            "version": "1.0.30001669",
1002
-            "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001669.tgz",
1003
-            "integrity": "sha512-DlWzFDJqstqtIVx1zeSpIMLjunf5SmwOw0N2Ck/QSQdS8PLS4+9HrLaYei4w8BIAL7IB/UEDu889d8vhCTPA0w==",
1029
+            "version": "1.0.30001672",
1030
+            "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001672.tgz",
1031
+            "integrity": "sha512-XhW1vRo1ob6aeK2w3rTohwTPBLse/rvjq+s3RTSBwnlZqoFFjx9cHsShJjAIbLsLjyoacaTxpLZy9v3gg6zypw==",
1004 1032
             "dev": true,
1005 1033
             "funding": [
1006 1034
                 {
@@ -1159,9 +1187,9 @@
1159 1187
             "license": "MIT"
1160 1188
         },
1161 1189
         "node_modules/electron-to-chromium": {
1162
-            "version": "1.5.41",
1163
-            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.41.tgz",
1164
-            "integrity": "sha512-dfdv/2xNjX0P8Vzme4cfzHqnPm5xsZXwsolTYr0eyW18IUmNyG08vL+fttvinTfhKfIKdRoqkDIC9e9iWQCNYQ==",
1190
+            "version": "1.5.47",
1191
+            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.47.tgz",
1192
+            "integrity": "sha512-zS5Yer0MOYw4rtK2iq43cJagHZ8sXN0jDHDKzB+86gSBSAI4v07S97mcq+Gs2vclAxSh1j7vOAHxSVgduiiuVQ==",
1165 1193
             "dev": true,
1166 1194
             "license": "ISC"
1167 1195
         },
@@ -1982,9 +2010,9 @@
1982 2010
             }
1983 2011
         },
1984 2012
         "node_modules/postcss-nesting": {
1985
-            "version": "13.0.0",
1986
-            "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-13.0.0.tgz",
1987
-            "integrity": "sha512-TCGQOizyqvEkdeTPM+t6NYwJ3EJszYE/8t8ILxw/YoeUvz2rz7aM8XTAmBWh9/DJjfaaabL88fWrsVHSPF2zgA==",
2013
+            "version": "13.0.1",
2014
+            "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-13.0.1.tgz",
2015
+            "integrity": "sha512-VbqqHkOBOt4Uu3G8Dm8n6lU5+9cJFxiuty9+4rcoyRPO9zZS1JIs6td49VIoix3qYqELHlJIn46Oih9SAKo+yQ==",
1988 2016
             "dev": true,
1989 2017
             "funding": [
1990 2018
                 {
@@ -1998,9 +2026,9 @@
1998 2026
             ],
1999 2027
             "license": "MIT-0",
2000 2028
             "dependencies": {
2001
-                "@csstools/selector-resolve-nested": "^2.0.0",
2002
-                "@csstools/selector-specificity": "^4.0.0",
2003
-                "postcss-selector-parser": "^6.1.0"
2029
+                "@csstools/selector-resolve-nested": "^3.0.0",
2030
+                "@csstools/selector-specificity": "^5.0.0",
2031
+                "postcss-selector-parser": "^7.0.0"
2004 2032
             },
2005 2033
             "engines": {
2006 2034
                 "node": ">=18"
@@ -2010,9 +2038,9 @@
2010 2038
             }
2011 2039
         },
2012 2040
         "node_modules/postcss-nesting/node_modules/@csstools/selector-resolve-nested": {
2013
-            "version": "2.0.0",
2014
-            "resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-2.0.0.tgz",
2015
-            "integrity": "sha512-oklSrRvOxNeeOW1yARd4WNCs/D09cQjunGZUgSq6vM8GpzFswN+8rBZyJA29YFZhOTQ6GFzxgLDNtVbt9wPZMA==",
2041
+            "version": "3.0.0",
2042
+            "resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-3.0.0.tgz",
2043
+            "integrity": "sha512-ZoK24Yku6VJU1gS79a5PFmC8yn3wIapiKmPgun0hZgEI5AOqgH2kiPRsPz1qkGv4HL+wuDLH83yQyk6inMYrJQ==",
2016 2044
             "dev": true,
2017 2045
             "funding": [
2018 2046
                 {
@@ -2029,13 +2057,13 @@
2029 2057
                 "node": ">=18"
2030 2058
             },
2031 2059
             "peerDependencies": {
2032
-                "postcss-selector-parser": "^6.1.0"
2060
+                "postcss-selector-parser": "^7.0.0"
2033 2061
             }
2034 2062
         },
2035 2063
         "node_modules/postcss-nesting/node_modules/@csstools/selector-specificity": {
2036
-            "version": "4.0.0",
2037
-            "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-4.0.0.tgz",
2038
-            "integrity": "sha512-189nelqtPd8++phaHNwYovKZI0FOzH1vQEE3QhHHkNIGrg5fSs9CbYP3RvfEH5geztnIA9Jwq91wyOIwAW5JIQ==",
2064
+            "version": "5.0.0",
2065
+            "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz",
2066
+            "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==",
2039 2067
             "dev": true,
2040 2068
             "funding": [
2041 2069
                 {
@@ -2052,13 +2080,13 @@
2052 2080
                 "node": ">=18"
2053 2081
             },
2054 2082
             "peerDependencies": {
2055
-                "postcss-selector-parser": "^6.1.0"
2083
+                "postcss-selector-parser": "^7.0.0"
2056 2084
             }
2057 2085
         },
2058 2086
         "node_modules/postcss-nesting/node_modules/postcss-selector-parser": {
2059
-            "version": "6.1.2",
2060
-            "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
2061
-            "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
2087
+            "version": "7.0.0",
2088
+            "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz",
2089
+            "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==",
2062 2090
             "dev": true,
2063 2091
             "license": "MIT",
2064 2092
             "dependencies": {
@@ -2171,9 +2199,9 @@
2171 2199
             }
2172 2200
         },
2173 2201
         "node_modules/rollup": {
2174
-            "version": "4.24.0",
2175
-            "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz",
2176
-            "integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==",
2202
+            "version": "4.24.2",
2203
+            "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.2.tgz",
2204
+            "integrity": "sha512-do/DFGq5g6rdDhdpPq5qb2ecoczeK6y+2UAjdJ5trjQJj5f1AiVdLRWRc9A9/fFukfvJRgM0UXzxBIYMovm5ww==",
2177 2205
             "dev": true,
2178 2206
             "license": "MIT",
2179 2207
             "dependencies": {
@@ -2187,22 +2215,24 @@
2187 2215
                 "npm": ">=8.0.0"
2188 2216
             },
2189 2217
             "optionalDependencies": {
2190
-                "@rollup/rollup-android-arm-eabi": "4.24.0",
2191
-                "@rollup/rollup-android-arm64": "4.24.0",
2192
-                "@rollup/rollup-darwin-arm64": "4.24.0",
2193
-                "@rollup/rollup-darwin-x64": "4.24.0",
2194
-                "@rollup/rollup-linux-arm-gnueabihf": "4.24.0",
2195
-                "@rollup/rollup-linux-arm-musleabihf": "4.24.0",
2196
-                "@rollup/rollup-linux-arm64-gnu": "4.24.0",
2197
-                "@rollup/rollup-linux-arm64-musl": "4.24.0",
2198
-                "@rollup/rollup-linux-powerpc64le-gnu": "4.24.0",
2199
-                "@rollup/rollup-linux-riscv64-gnu": "4.24.0",
2200
-                "@rollup/rollup-linux-s390x-gnu": "4.24.0",
2201
-                "@rollup/rollup-linux-x64-gnu": "4.24.0",
2202
-                "@rollup/rollup-linux-x64-musl": "4.24.0",
2203
-                "@rollup/rollup-win32-arm64-msvc": "4.24.0",
2204
-                "@rollup/rollup-win32-ia32-msvc": "4.24.0",
2205
-                "@rollup/rollup-win32-x64-msvc": "4.24.0",
2218
+                "@rollup/rollup-android-arm-eabi": "4.24.2",
2219
+                "@rollup/rollup-android-arm64": "4.24.2",
2220
+                "@rollup/rollup-darwin-arm64": "4.24.2",
2221
+                "@rollup/rollup-darwin-x64": "4.24.2",
2222
+                "@rollup/rollup-freebsd-arm64": "4.24.2",
2223
+                "@rollup/rollup-freebsd-x64": "4.24.2",
2224
+                "@rollup/rollup-linux-arm-gnueabihf": "4.24.2",
2225
+                "@rollup/rollup-linux-arm-musleabihf": "4.24.2",
2226
+                "@rollup/rollup-linux-arm64-gnu": "4.24.2",
2227
+                "@rollup/rollup-linux-arm64-musl": "4.24.2",
2228
+                "@rollup/rollup-linux-powerpc64le-gnu": "4.24.2",
2229
+                "@rollup/rollup-linux-riscv64-gnu": "4.24.2",
2230
+                "@rollup/rollup-linux-s390x-gnu": "4.24.2",
2231
+                "@rollup/rollup-linux-x64-gnu": "4.24.2",
2232
+                "@rollup/rollup-linux-x64-musl": "4.24.2",
2233
+                "@rollup/rollup-win32-arm64-msvc": "4.24.2",
2234
+                "@rollup/rollup-win32-ia32-msvc": "4.24.2",
2235
+                "@rollup/rollup-win32-x64-msvc": "4.24.2",
2206 2236
                 "fsevents": "~2.3.2"
2207 2237
             }
2208 2238
         },
@@ -2550,9 +2580,9 @@
2550 2580
             "license": "MIT"
2551 2581
         },
2552 2582
         "node_modules/vite": {
2553
-            "version": "5.4.9",
2554
-            "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.9.tgz",
2555
-            "integrity": "sha512-20OVpJHh0PAM0oSOELa5GaZNWeDjcAvQjGXy2Uyr+Tp+/D2/Hdz6NLgpJLsarPTA2QJ6v8mX2P1ZfbsSKvdMkg==",
2583
+            "version": "5.4.10",
2584
+            "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.10.tgz",
2585
+            "integrity": "sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==",
2556 2586
             "dev": true,
2557 2587
             "license": "MIT",
2558 2588
             "dependencies": {

+ 87
- 0
resources/views/filament/company/pages/reports/cash-flow-statement.blade.php Bestand weergeven

@@ -0,0 +1,87 @@
1
+<x-filament-panels::page>
2
+    <x-filament::section>
3
+        <div class="flex flex-col md:flex-row items-start md:items-center justify-between gap-4">
4
+            <!-- Form Container -->
5
+            @if(method_exists($this, 'filtersForm'))
6
+                {{ $this->filtersForm }}
7
+            @endif
8
+
9
+            <!-- Grouping Button and Column Toggle -->
10
+            @if($this->hasToggleableColumns())
11
+                <x-filament-tables::column-toggle.dropdown
12
+                    :form="$this->getTableColumnToggleForm()"
13
+                    :trigger-action="$this->getToggleColumnsTriggerAction()"
14
+                />
15
+            @endif
16
+
17
+            <div class="inline-flex items-center min-w-0 md:min-w-[9.5rem] justify-end">
18
+                {{ $this->applyFiltersAction }}
19
+            </div>
20
+        </div>
21
+    </x-filament::section>
22
+
23
+
24
+    <x-filament::section>
25
+        <!-- Summary Section -->
26
+        @if($this->reportLoaded)
27
+            <div
28
+                class="flex flex-col md:flex-row items-center md:items-end text-center justify-center gap-4 md:gap-8">
29
+                @foreach($this->report->getSummary() as $summary)
30
+                    <div class="text-sm">
31
+                        <div class="text-gray-600 font-medium mb-2">{{ $summary['label'] }}</div>
32
+
33
+                        @php
34
+                            $isNetEarnings = $summary['label'] === 'Net Earnings';
35
+                            $isPositive = money($summary['value'], \App\Utilities\Currency\CurrencyAccessor::getDefaultCurrency())->isPositive();
36
+                        @endphp
37
+
38
+                        <strong
39
+                            @class([
40
+                                'text-lg',
41
+                                'text-green-700' => $isNetEarnings && $isPositive,
42
+                                'text-danger-700' => $isNetEarnings && ! $isPositive,
43
+                            ])
44
+                        >
45
+                            {{ $summary['value'] }}
46
+                        </strong>
47
+                    </div>
48
+
49
+                    @if(! $loop->last)
50
+                        <div class="flex items-center justify-center px-2">
51
+                            <strong class="text-lg">
52
+                                {{ $loop->remaining === 1 ? '=' : '-' }}
53
+                            </strong>
54
+                        </div>
55
+                    @endif
56
+                @endforeach
57
+            </div>
58
+        @endif
59
+    </x-filament::section>
60
+
61
+    <x-filament::tabs>
62
+        <x-filament::tabs.item
63
+            :active="$activeTab === 'summary'"
64
+            wire:click="$set('activeTab', 'summary')"
65
+        >
66
+            Summary
67
+        </x-filament::tabs.item>
68
+
69
+        <x-filament::tabs.item
70
+            :active="$activeTab === 'details'"
71
+            wire:click="$set('activeTab', 'details')"
72
+        >
73
+            Details
74
+        </x-filament::tabs.item>
75
+    </x-filament::tabs>
76
+
77
+    <x-company.tables.container :report-loaded="$this->reportLoaded">
78
+        @if($this->report)
79
+            @if($activeTab === 'summary')
80
+                <x-company.tables.reports.income-statement-summary :report="$this->report"/>
81
+            @elseif($activeTab === 'details')
82
+                <x-company.tables.reports.balance-sheet :report="$this->report"/>
83
+            @endif
84
+        @endif
85
+    </x-company.tables.container>
86
+</x-filament-panels::page>
87
+

Laden…
Annuleren
Opslaan