Explorar el Código

Merge pull request #102 from andrewdwallo/development-3.x

Development 3.x
3.x
Andrew Wallo hace 8 meses
padre
commit
529177c7ab
No account linked to committer's email address
Se han modificado 38 ficheros con 935 adiciones y 239 borrados
  1. 1
    1
      app/Contracts/BalanceFormattable.php
  2. 2
    2
      app/DTO/AccountBalanceDTO.php
  3. 2
    2
      app/DTO/AgingBucketDTO.php
  4. 0
    12
      app/DTO/ClientReportDTO.php
  5. 25
    0
      app/DTO/EntityBalanceDTO.php
  6. 3
    1
      app/DTO/EntityReportDTO.php
  7. 15
    0
      app/DTO/PaymentMetricsDTO.php
  8. 2
    0
      app/DTO/ReportDTO.php
  9. 0
    12
      app/DTO/VendorReportDTO.php
  10. 4
    3
      app/Enums/Accounting/BillStatus.php
  11. 17
    1
      app/Enums/Accounting/DocumentEntityType.php
  12. 6
    0
      app/Enums/Accounting/DocumentType.php
  13. 31
    13
      app/Filament/Company/Pages/Reports.php
  14. 102
    0
      app/Filament/Company/Pages/Reports/BaseEntityBalanceSummaryReportPage.php
  15. 121
    0
      app/Filament/Company/Pages/Reports/BaseEntityPaymentPerformanceReportPage.php
  16. 13
    0
      app/Filament/Company/Pages/Reports/ClientBalanceSummary.php
  17. 13
    0
      app/Filament/Company/Pages/Reports/ClientPaymentPerformance.php
  18. 13
    0
      app/Filament/Company/Pages/Reports/VendorBalanceSummary.php
  19. 13
    0
      app/Filament/Company/Pages/Reports/VendorPaymentPerformance.php
  20. 1
    1
      app/Filament/Company/Resources/Purchases/BillResource.php
  21. 3
    3
      app/Filament/Company/Resources/Purchases/BillResource/Pages/ListBills.php
  22. 1
    1
      app/Filament/Company/Resources/Purchases/BillResource/Widgets/BillOverview.php
  23. 2
    2
      app/Filament/Company/Resources/Purchases/VendorResource.php
  24. 1
    1
      app/Filament/Company/Resources/Purchases/VendorResource/Widgets/BillOverview.php
  25. 1
    1
      app/Filament/Company/Resources/Sales/InvoiceResource/Widgets/InvoiceOverview.php
  26. 3
    3
      app/Models/Accounting/Bill.php
  27. 5
    0
      app/Providers/MacroServiceProvider.php
  28. 3
    1
      app/Services/AccountService.php
  29. 218
    29
      app/Services/ReportService.php
  30. 1
    1
      app/Transformers/AgingReportTransformer.php
  31. 77
    0
      app/Transformers/EntityBalanceSummaryReportTransformer.php
  32. 83
    0
      app/Transformers/EntityPaymentPerformanceReportTransformer.php
  33. 58
    58
      composer.lock
  34. 1
    1
      database/factories/Accounting/BillFactory.php
  35. 1
    1
      database/migrations/2024_11_27_221657_create_bills_table.php
  36. 85
    85
      package-lock.json
  37. 4
    0
      resources/css/filament/company/theme.css
  38. 4
    4
      resources/views/components/company/tables/container.blade.php

app/Contracts/MoneyFormattableDTO.php → app/Contracts/BalanceFormattable.php Ver fichero

@@ -2,7 +2,7 @@
2 2
 
3 3
 namespace App\Contracts;
4 4
 
5
-interface MoneyFormattableDTO
5
+interface BalanceFormattable
6 6
 {
7 7
     public static function fromArray(array $balances): static;
8 8
 }

+ 2
- 2
app/DTO/AccountBalanceDTO.php Ver fichero

@@ -2,9 +2,9 @@
2 2
 
3 3
 namespace App\DTO;
4 4
 
5
-use App\Contracts\MoneyFormattableDTO;
5
+use App\Contracts\BalanceFormattable;
6 6
 
7
-class AccountBalanceDTO implements MoneyFormattableDTO
7
+class AccountBalanceDTO implements BalanceFormattable
8 8
 {
9 9
     public function __construct(
10 10
         public ?string $startingBalance,

+ 2
- 2
app/DTO/AgingBucketDTO.php Ver fichero

@@ -2,9 +2,9 @@
2 2
 
3 3
 namespace App\DTO;
4 4
 
5
-use App\Contracts\MoneyFormattableDTO;
5
+use App\Contracts\BalanceFormattable;
6 6
 
7
-readonly class AgingBucketDTO implements MoneyFormattableDTO
7
+readonly class AgingBucketDTO implements BalanceFormattable
8 8
 {
9 9
     /**
10 10
      * @param  array<string, string>  $periods

+ 0
- 12
app/DTO/ClientReportDTO.php Ver fichero

@@ -1,12 +0,0 @@
1
-<?php
2
-
3
-namespace App\DTO;
4
-
5
-readonly class ClientReportDTO
6
-{
7
-    public function __construct(
8
-        public string $clientName,
9
-        public string $clientId,
10
-        public AgingBucketDTO $aging,
11
-    ) {}
12
-}

+ 25
- 0
app/DTO/EntityBalanceDTO.php Ver fichero

@@ -0,0 +1,25 @@
1
+<?php
2
+
3
+namespace App\DTO;
4
+
5
+use App\Contracts\BalanceFormattable;
6
+
7
+readonly class EntityBalanceDTO implements BalanceFormattable
8
+{
9
+    public function __construct(
10
+        public ?string $totalBalance,
11
+        public ?string $paidBalance,
12
+        public ?string $unpaidBalance,
13
+        public ?string $overdueBalance = null,
14
+    ) {}
15
+
16
+    public static function fromArray(array $balances): static
17
+    {
18
+        return new static(
19
+            totalBalance: $balances['total_balance'] ?? null,
20
+            paidBalance: $balances['paid_balance'] ?? null,
21
+            unpaidBalance: $balances['unpaid_balance'] ?? null,
22
+            overdueBalance: $balances['overdue_balance'] ?? null,
23
+        );
24
+    }
25
+}

+ 3
- 1
app/DTO/EntityReportDTO.php Ver fichero

@@ -7,6 +7,8 @@ readonly class EntityReportDTO
7 7
     public function __construct(
8 8
         public string $name,
9 9
         public string $id,
10
-        public AgingBucketDTO $aging,
10
+        public ?AgingBucketDTO $aging = null,
11
+        public ?EntityBalanceDTO $balance = null,
12
+        public ?PaymentMetricsDTO $paymentMetrics = null,
11 13
     ) {}
12 14
 }

+ 15
- 0
app/DTO/PaymentMetricsDTO.php Ver fichero

@@ -0,0 +1,15 @@
1
+<?php
2
+
3
+namespace App\DTO;
4
+
5
+readonly class PaymentMetricsDTO
6
+{
7
+    public function __construct(
8
+        public int $totalDocuments,
9
+        public ?int $onTimeCount,
10
+        public ?int $lateCount,
11
+        public ?int $avgDaysToPay,
12
+        public ?int $avgDaysLate,
13
+        public string $onTimePaymentRate,
14
+    ) {}
15
+}

+ 2
- 0
app/DTO/ReportDTO.php Ver fichero

@@ -13,6 +13,8 @@ class ReportDTO
13 13
         public array $categories,
14 14
         public ?AccountBalanceDTO $overallTotal = null,
15 15
         public ?AgingBucketDTO $agingSummary = null,
16
+        public ?EntityBalanceDTO $entityBalanceTotal = null,
17
+        public ?PaymentMetricsDTO $overallPaymentMetrics = null,
16 18
         public array $fields = [],
17 19
         public ?string $reportType = null,
18 20
         public ?CashFlowOverviewDTO $overview = null,

+ 0
- 12
app/DTO/VendorReportDTO.php Ver fichero

@@ -1,12 +0,0 @@
1
-<?php
2
-
3
-namespace App\DTO;
4
-
5
-readonly class VendorReportDTO
6
-{
7
-    public function __construct(
8
-        public string $vendorName,
9
-        public string $vendorId,
10
-        public AgingBucketDTO $aging,
11
-    ) {}
12
-}

+ 4
- 3
app/Enums/Accounting/BillStatus.php Ver fichero

@@ -10,7 +10,7 @@ enum BillStatus: string implements HasColor, HasLabel
10 10
     case Overdue = 'overdue';
11 11
     case Partial = 'partial';
12 12
     case Paid = 'paid';
13
-    case Unpaid = 'unpaid';
13
+    case Open = 'open';
14 14
     case Void = 'void';
15 15
 
16 16
     public function getLabel(): ?string
@@ -21,8 +21,9 @@ enum BillStatus: string implements HasColor, HasLabel
21 21
     public function getColor(): string | array | null
22 22
     {
23 23
         return match ($this) {
24
+            self::Open => 'info',
24 25
             self::Overdue => 'danger',
25
-            self::Partial, self::Unpaid => 'warning',
26
+            self::Partial => 'warning',
26 27
             self::Paid => 'success',
27 28
             self::Void => 'gray',
28 29
         };
@@ -32,7 +33,7 @@ enum BillStatus: string implements HasColor, HasLabel
32 33
     {
33 34
         return [
34 35
             self::Partial,
35
-            self::Unpaid,
36
+            self::Open,
36 37
         ];
37 38
     }
38 39
 }

+ 17
- 1
app/Enums/Accounting/DocumentEntityType.php Ver fichero

@@ -14,11 +14,27 @@ enum DocumentEntityType: string implements HasLabel
14 14
         return $this->name;
15 15
     }
16 16
 
17
-    public function getReportTitle(): string
17
+    public function getAgingReportTitle(): string
18 18
     {
19 19
         return match ($this) {
20 20
             self::Client => 'Accounts Receivable Aging',
21 21
             self::Vendor => 'Accounts Payable Aging',
22 22
         };
23 23
     }
24
+
25
+    public function getBalanceSummaryReportTitle(): string
26
+    {
27
+        return match ($this) {
28
+            self::Client => 'Client Balance Summary',
29
+            self::Vendor => 'Vendor Balance Summary',
30
+        };
31
+    }
32
+
33
+    public function getPaymentPerformanceReportTitle(): string
34
+    {
35
+        return match ($this) {
36
+            self::Client => 'Client Payment Performance',
37
+            self::Vendor => 'Vendor Payment Performance',
38
+        };
39
+    }
24 40
 }

+ 6
- 0
app/Enums/Accounting/DocumentType.php Ver fichero

@@ -5,6 +5,7 @@ namespace App\Enums\Accounting;
5 5
 use App\DTO\DocumentLabelDTO;
6 6
 use Filament\Support\Contracts\HasIcon;
7 7
 use Filament\Support\Contracts\HasLabel;
8
+use Illuminate\Support\Str;
8 9
 
9 10
 enum DocumentType: string implements HasIcon, HasLabel
10 11
 {
@@ -23,6 +24,11 @@ enum DocumentType: string implements HasIcon, HasLabel
23 24
         };
24 25
     }
25 26
 
27
+    public function getPluralLabel(): ?string
28
+    {
29
+        return Str::plural($this->getLabel());
30
+    }
31
+
26 32
     public function getIcon(): ?string
27 33
     {
28 34
         return match ($this->value) {

+ 31
- 13
app/Filament/Company/Pages/Reports.php Ver fichero

@@ -8,8 +8,12 @@ use App\Filament\Company\Pages\Reports\AccountsReceivableAging;
8 8
 use App\Filament\Company\Pages\Reports\AccountTransactions;
9 9
 use App\Filament\Company\Pages\Reports\BalanceSheet;
10 10
 use App\Filament\Company\Pages\Reports\CashFlowStatement;
11
+use App\Filament\Company\Pages\Reports\ClientBalanceSummary;
12
+use App\Filament\Company\Pages\Reports\ClientPaymentPerformance;
11 13
 use App\Filament\Company\Pages\Reports\IncomeStatement;
12 14
 use App\Filament\Company\Pages\Reports\TrialBalance;
15
+use App\Filament\Company\Pages\Reports\VendorBalanceSummary;
16
+use App\Filament\Company\Pages\Reports\VendorPaymentPerformance;
13 17
 use App\Filament\Infolists\Components\ReportEntry;
14 18
 use Filament\Infolists\Components\Section;
15 19
 use Filament\Infolists\Infolist;
@@ -74,25 +78,32 @@ class Reports extends Page
74 78
                             ->iconColor(Color::Cyan)
75 79
                             ->url(CashFlowStatement::getUrl()),
76 80
                     ]),
77
-                Section::make('Customer Reports')
81
+                Section::make('Client Reports')
78 82
                     ->aside()
79
-                    ->description('Reports that provide detailed information on your company’s customer transactions and balances.')
83
+                    ->description('Reports that provide detailed information on your company’s client transactions and balances.')
80 84
                     ->extraAttributes(['class' => 'es-report-card'])
81 85
                     ->schema([
82 86
                         ReportEntry::make('ar_aging')
83 87
                             ->hiddenLabel()
84 88
                             ->heading('Accounts Receivable Aging')
85
-                            ->description('Lists outstanding receivables by customer, showing how long invoices have been unpaid.')
89
+                            ->description('Lists outstanding receivables by client, showing how long invoices have been unpaid.')
86 90
                             ->icon('heroicon-o-calendar-date-range')
87 91
                             ->iconColor(Color::Indigo)
88 92
                             ->url(AccountsReceivableAging::getUrl()),
89
-                        ReportEntry::make('income_by_customer')
93
+                        ReportEntry::make('client_balance_summary')
90 94
                             ->hiddenLabel()
91
-                            ->heading('Income by Customer')
92
-                            ->description('Shows revenue generated by each customer, helping identify top customers and opportunities for growth.')
93
-                            ->icon('heroicon-o-arrow-trending-up')
95
+                            ->heading('Client Balance Summary')
96
+                            ->description('Shows total invoiced amounts, payments received, and outstanding balances for each client, helping identify top clients and opportunities for growth.')
97
+                            ->icon('heroicon-o-receipt-percent')
94 98
                             ->iconColor(Color::Emerald)
95
-                            ->url('#'),
99
+                            ->url(ClientBalanceSummary::getUrl()),
100
+                        ReportEntry::make('client_payment_performance')
101
+                            ->hiddenLabel()
102
+                            ->heading('Client Payment Performance')
103
+                            ->description('Analyzes payment behavior showing average days to pay, on-time payment rates, and late payment patterns for each client.')
104
+                            ->icon('heroicon-o-clock')
105
+                            ->iconColor(Color::Fuchsia)
106
+                            ->url(ClientPaymentPerformance::getUrl()),
96 107
                     ]),
97 108
                 Section::make('Vendor Reports')
98 109
                     ->aside()
@@ -106,13 +117,20 @@ class Reports extends Page
106 117
                             ->icon('heroicon-o-clock')
107 118
                             ->iconColor(Color::Rose)
108 119
                             ->url(AccountsPayableAging::getUrl()),
109
-                        ReportEntry::make('expenses_by_vendor')
120
+                        ReportEntry::make('vendor_balance_summary')
110 121
                             ->hiddenLabel()
111
-                            ->heading('Expenses by Vendor')
112
-                            ->description('Shows expenses incurred with each vendor, helping identify top vendors and opportunities for cost savings.')
113
-                            ->icon('heroicon-o-arrow-trending-down')
122
+                            ->heading('Vendor Balance Summary')
123
+                            ->description('Shows total billed amounts, payments made, and outstanding balances for each vendor, helping track payment obligations and vendor relationships.')
124
+                            ->icon('heroicon-o-banknotes')
114 125
                             ->iconColor(Color::Orange)
115
-                            ->url('#'),
126
+                            ->url(VendorBalanceSummary::getUrl()),
127
+                        ReportEntry::make('vendor_payment_performance')
128
+                            ->hiddenLabel()
129
+                            ->heading('Vendor Payment Performance')
130
+                            ->description('Analyzes payment behavior showing average days to pay, on-time payment rates, and late payment patterns for each vendor.')
131
+                            ->icon('heroicon-o-clock')
132
+                            ->iconColor(Color::Violet)
133
+                            ->url(VendorPaymentPerformance::getUrl()),
116 134
                     ]),
117 135
                 Section::make('Detailed Reports')
118 136
                     ->aside()

+ 102
- 0
app/Filament/Company/Pages/Reports/BaseEntityBalanceSummaryReportPage.php Ver fichero

@@ -0,0 +1,102 @@
1
+<?php
2
+
3
+namespace App\Filament\Company\Pages\Reports;
4
+
5
+use App\Contracts\ExportableReport;
6
+use App\DTO\ReportDTO;
7
+use App\Enums\Accounting\DocumentEntityType;
8
+use App\Services\ExportService;
9
+use App\Services\ReportService;
10
+use App\Support\Column;
11
+use App\Transformers\EntityBalanceSummaryReportTransformer;
12
+use Filament\Forms\Form;
13
+use Filament\Support\Enums\Alignment;
14
+use Guava\FilamentClusters\Forms\Cluster;
15
+use Symfony\Component\HttpFoundation\StreamedResponse;
16
+
17
+abstract class BaseEntityBalanceSummaryReportPage extends BaseReportPage
18
+{
19
+    protected static string $view = 'filament.company.pages.reports.detailed-report';
20
+
21
+    protected ReportService $reportService;
22
+
23
+    protected ExportService $exportService;
24
+
25
+    abstract protected function getEntityType(): DocumentEntityType;
26
+
27
+    public function boot(ReportService $reportService, ExportService $exportService): void
28
+    {
29
+        $this->reportService = $reportService;
30
+        $this->exportService = $exportService;
31
+    }
32
+
33
+    public function getTable(): array
34
+    {
35
+        return [
36
+            Column::make('entity_name')
37
+                ->label($this->getEntityType()->getLabel())
38
+                ->alignment(Alignment::Left),
39
+            Column::make('total_balance')
40
+                ->label('Total')
41
+                ->toggleable()
42
+                ->alignment(Alignment::Right),
43
+            Column::make('paid_balance')
44
+                ->label('Paid')
45
+                ->toggleable()
46
+                ->alignment(Alignment::Right),
47
+            Column::make('unpaid_balance')
48
+                ->label('Unpaid')
49
+                ->toggleable()
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->buildEntityBalanceSummaryReport(
71
+            startDate: $this->getFormattedStartDate(),
72
+            endDate: $this->getFormattedEndDate(),
73
+            entityType: $this->getEntityType(),
74
+            columns: $columns
75
+        );
76
+    }
77
+
78
+    protected function getTransformer(ReportDTO $reportDTO): ExportableReport
79
+    {
80
+        return new EntityBalanceSummaryReportTransformer($reportDTO, $this->getEntityType());
81
+    }
82
+
83
+    public function exportCSV(): StreamedResponse
84
+    {
85
+        return $this->exportService->exportToCsv(
86
+            $this->company,
87
+            $this->report,
88
+            $this->getFilterState('startDate'),
89
+            $this->getFilterState('endDate')
90
+        );
91
+    }
92
+
93
+    public function exportPDF(): StreamedResponse
94
+    {
95
+        return $this->exportService->exportToPdf(
96
+            $this->company,
97
+            $this->report,
98
+            $this->getFilterState('startDate'),
99
+            $this->getFilterState('endDate')
100
+        );
101
+    }
102
+}

+ 121
- 0
app/Filament/Company/Pages/Reports/BaseEntityPaymentPerformanceReportPage.php Ver fichero

@@ -0,0 +1,121 @@
1
+<?php
2
+
3
+namespace App\Filament\Company\Pages\Reports;
4
+
5
+use App\Contracts\ExportableReport;
6
+use App\DTO\ReportDTO;
7
+use App\Enums\Accounting\DocumentEntityType;
8
+use App\Enums\Accounting\DocumentType;
9
+use App\Services\ExportService;
10
+use App\Services\ReportService;
11
+use App\Support\Column;
12
+use App\Transformers\EntityPaymentPerformanceReportTransformer;
13
+use Filament\Forms\Form;
14
+use Filament\Support\Enums\Alignment;
15
+use Guava\FilamentClusters\Forms\Cluster;
16
+use Symfony\Component\HttpFoundation\StreamedResponse;
17
+
18
+abstract class BaseEntityPaymentPerformanceReportPage extends BaseReportPage
19
+{
20
+    protected static string $view = 'filament.company.pages.reports.detailed-report';
21
+
22
+    protected ReportService $reportService;
23
+
24
+    protected ExportService $exportService;
25
+
26
+    abstract protected function getEntityType(): DocumentEntityType;
27
+
28
+    public function boot(ReportService $reportService, ExportService $exportService): void
29
+    {
30
+        $this->reportService = $reportService;
31
+        $this->exportService = $exportService;
32
+    }
33
+
34
+    public function getDocumentType(): DocumentType
35
+    {
36
+        return match ($this->getEntityType()) {
37
+            DocumentEntityType::Client => DocumentType::Invoice,
38
+            DocumentEntityType::Vendor => DocumentType::Bill,
39
+        };
40
+    }
41
+
42
+    public function getTable(): array
43
+    {
44
+        return [
45
+            Column::make('entity_name')
46
+                ->label($this->getEntityType()->getLabel())
47
+                ->alignment(Alignment::Left),
48
+            Column::make('total_documents')
49
+                ->label("Total {$this->getDocumentType()->getPluralLabel()}")
50
+                ->alignment(Alignment::Right),
51
+            Column::make('on_time_count')
52
+                ->label('Paid On Time')
53
+                ->toggleable()
54
+                ->alignment(Alignment::Right),
55
+            Column::make('late_count')
56
+                ->label('Paid Late')
57
+                ->toggleable()
58
+                ->alignment(Alignment::Right),
59
+            Column::make('avg_days_to_pay')
60
+                ->label('Avg. Days to Pay')
61
+                ->toggleable()
62
+                ->alignment(Alignment::Right),
63
+            Column::make('avg_days_late')
64
+                ->label('Avg. Days Late')
65
+                ->toggleable()
66
+                ->alignment(Alignment::Right),
67
+            Column::make('on_time_payment_rate')
68
+                ->label('On Time Rate')
69
+                ->alignment(Alignment::Right),
70
+        ];
71
+    }
72
+
73
+    public function filtersForm(Form $form): Form
74
+    {
75
+        return $form
76
+            ->inlineLabel()
77
+            ->columns()
78
+            ->schema([
79
+                $this->getDateRangeFormComponent(),
80
+                Cluster::make([
81
+                    $this->getStartDateFormComponent(),
82
+                    $this->getEndDateFormComponent(),
83
+                ])->hiddenLabel(),
84
+            ]);
85
+    }
86
+
87
+    protected function buildReport(array $columns): ReportDTO
88
+    {
89
+        return $this->reportService->buildEntityPaymentPerformanceReport(
90
+            startDate: $this->getFormattedStartDate(),
91
+            endDate: $this->getFormattedEndDate(),
92
+            entityType: $this->getEntityType(),
93
+            columns: $columns
94
+        );
95
+    }
96
+
97
+    protected function getTransformer(ReportDTO $reportDTO): ExportableReport
98
+    {
99
+        return new EntityPaymentPerformanceReportTransformer($reportDTO, $this->getEntityType());
100
+    }
101
+
102
+    public function exportCSV(): StreamedResponse
103
+    {
104
+        return $this->exportService->exportToCsv(
105
+            $this->company,
106
+            $this->report,
107
+            $this->getFilterState('startDate'),
108
+            $this->getFilterState('endDate')
109
+        );
110
+    }
111
+
112
+    public function exportPDF(): StreamedResponse
113
+    {
114
+        return $this->exportService->exportToPdf(
115
+            $this->company,
116
+            $this->report,
117
+            $this->getFilterState('startDate'),
118
+            $this->getFilterState('endDate')
119
+        );
120
+    }
121
+}

+ 13
- 0
app/Filament/Company/Pages/Reports/ClientBalanceSummary.php Ver fichero

@@ -0,0 +1,13 @@
1
+<?php
2
+
3
+namespace App\Filament\Company\Pages\Reports;
4
+
5
+use App\Enums\Accounting\DocumentEntityType;
6
+
7
+class ClientBalanceSummary extends BaseEntityBalanceSummaryReportPage
8
+{
9
+    protected function getEntityType(): DocumentEntityType
10
+    {
11
+        return DocumentEntityType::Client;
12
+    }
13
+}

+ 13
- 0
app/Filament/Company/Pages/Reports/ClientPaymentPerformance.php Ver fichero

@@ -0,0 +1,13 @@
1
+<?php
2
+
3
+namespace App\Filament\Company\Pages\Reports;
4
+
5
+use App\Enums\Accounting\DocumentEntityType;
6
+
7
+class ClientPaymentPerformance extends BaseEntityPaymentPerformanceReportPage
8
+{
9
+    protected function getEntityType(): DocumentEntityType
10
+    {
11
+        return DocumentEntityType::Client;
12
+    }
13
+}

+ 13
- 0
app/Filament/Company/Pages/Reports/VendorBalanceSummary.php Ver fichero

@@ -0,0 +1,13 @@
1
+<?php
2
+
3
+namespace App\Filament\Company\Pages\Reports;
4
+
5
+use App\Enums\Accounting\DocumentEntityType;
6
+
7
+class VendorBalanceSummary extends BaseEntityBalanceSummaryReportPage
8
+{
9
+    protected function getEntityType(): DocumentEntityType
10
+    {
11
+        return DocumentEntityType::Vendor;
12
+    }
13
+}

+ 13
- 0
app/Filament/Company/Pages/Reports/VendorPaymentPerformance.php Ver fichero

@@ -0,0 +1,13 @@
1
+<?php
2
+
3
+namespace App\Filament\Company\Pages\Reports;
4
+
5
+use App\Enums\Accounting\DocumentEntityType;
6
+
7
+class VendorPaymentPerformance extends BaseEntityPaymentPerformanceReportPage
8
+{
9
+    protected function getEntityType(): DocumentEntityType
10
+    {
11
+        return DocumentEntityType::Vendor;
12
+    }
13
+}

+ 1
- 1
app/Filament/Company/Resources/Purchases/BillResource.php Ver fichero

@@ -400,7 +400,7 @@ class BillResource extends Resource
400 400
                             'paid_at',
401 401
                         ])
402 402
                         ->beforeReplicaSaved(function (Bill $replica) {
403
-                            $replica->status = BillStatus::Unpaid;
403
+                            $replica->status = BillStatus::Open;
404 404
                             $replica->bill_number = Bill::getNextDocumentNumber();
405 405
                             $replica->date = now();
406 406
                             $replica->due_date = now()->addDays($replica->company->defaultBill->payment_terms->getDays());

+ 3
- 3
app/Filament/Company/Resources/Purchases/BillResource/Pages/ListBills.php Ver fichero

@@ -42,10 +42,10 @@ class ListBills extends ListRecords
42 42
             'all' => Tab::make()
43 43
                 ->label('All'),
44 44
 
45
-            'outstanding' => Tab::make()
46
-                ->label('Outstanding')
45
+            'unpaid' => Tab::make()
46
+                ->label('Unpaid')
47 47
                 ->modifyQueryUsing(function (Builder $query) {
48
-                    $query->outstanding();
48
+                    $query->unpaid();
49 49
                 }),
50 50
 
51 51
             'paid' => Tab::make()

+ 1
- 1
app/Filament/Company/Resources/Purchases/BillResource/Widgets/BillOverview.php Ver fichero

@@ -22,7 +22,7 @@ class BillOverview extends EnhancedStatsOverviewWidget
22 22
     protected function getStats(): array
23 23
     {
24 24
         $unpaidBills = $this->getPageTableQuery()
25
-            ->whereIn('status', [BillStatus::Unpaid, BillStatus::Partial, BillStatus::Overdue]);
25
+            ->whereIn('status', [BillStatus::Open, BillStatus::Partial, BillStatus::Overdue]);
26 26
 
27 27
         $amountToPay = $unpaidBills->get()->sumMoneyInDefaultCurrency('amount_due');
28 28
 

+ 2
- 2
app/Filament/Company/Resources/Purchases/VendorResource.php Ver fichero

@@ -180,7 +180,7 @@ class VendorResource extends Resource
180 180
                     ->label('Payable balance')
181 181
                     ->getStateUsing(function (Vendor $vendor) {
182 182
                         return $vendor->bills()
183
-                            ->outstanding()
183
+                            ->unpaid()
184 184
                             ->get()
185 185
                             ->sumMoneyInDefaultCurrency('amount_due');
186 186
                     })
@@ -200,7 +200,7 @@ class VendorResource extends Resource
200 200
                     })
201 201
                     ->sortable(query: function (Builder $query, string $direction) {
202 202
                         return $query
203
-                            ->withSum(['bills' => fn (Builder $query) => $query->outstanding()], 'amount_due')
203
+                            ->withSum(['bills' => fn (Builder $query) => $query->unpaid()], 'amount_due')
204 204
                             ->orderBy('bills_sum_amount_due', $direction);
205 205
                     })
206 206
                     ->currency(convert: false)

+ 1
- 1
app/Filament/Company/Resources/Purchases/VendorResource/Widgets/BillOverview.php Ver fichero

@@ -16,7 +16,7 @@ class BillOverview extends EnhancedStatsOverviewWidget
16 16
     protected function getStats(): array
17 17
     {
18 18
         $unpaidBills = $this->record->bills()
19
-            ->whereIn('status', [BillStatus::Unpaid, BillStatus::Partial, BillStatus::Overdue]);
19
+            ->whereIn('status', [BillStatus::Open, BillStatus::Partial, BillStatus::Overdue]);
20 20
 
21 21
         $amountToPay = $unpaidBills->get()->sumMoneyInDefaultCurrency('amount_due');
22 22
 

+ 1
- 1
app/Filament/Company/Resources/Sales/InvoiceResource/Widgets/InvoiceOverview.php Ver fichero

@@ -53,7 +53,7 @@ class InvoiceOverview extends EnhancedStatsOverviewWidget
53 53
 
54 54
         $averagePaymentTime = $this->getPageTableQuery()
55 55
             ->whereNotNull('paid_at')
56
-            ->selectRaw('AVG(TIMESTAMPDIFF(DAY, date, paid_at)) as avg_days')
56
+            ->selectRaw('AVG(TIMESTAMPDIFF(DAY, approved_at, paid_at)) as avg_days')
57 57
             ->value('avg_days');
58 58
 
59 59
         $averagePaymentTimeFormatted = Number::format($averagePaymentTime ?? 0, maxPrecision: 1);

+ 3
- 3
app/Models/Accounting/Bill.php Ver fichero

@@ -209,10 +209,10 @@ class Bill extends Document
209 209
         return $this->initialTransaction()->exists();
210 210
     }
211 211
 
212
-    public function scopeOutstanding(Builder $query): Builder
212
+    public function scopeUnpaid(Builder $query): Builder
213 213
     {
214 214
         return $query->whereIn('status', [
215
-            BillStatus::Unpaid,
215
+            BillStatus::Open,
216 216
             BillStatus::Partial,
217 217
             BillStatus::Overdue,
218 218
         ]);
@@ -396,7 +396,7 @@ class Bill extends Document
396 396
             ])
397 397
             ->modal(false)
398 398
             ->beforeReplicaSaved(function (self $original, self $replica) {
399
-                $replica->status = BillStatus::Unpaid;
399
+                $replica->status = BillStatus::Open;
400 400
                 $replica->bill_number = self::getNextDocumentNumber();
401 401
                 $replica->date = now();
402 402
                 $replica->due_date = now()->addDays($original->company->defaultBill->payment_terms->getDays());

+ 5
- 0
app/Providers/MacroServiceProvider.php Ver fichero

@@ -22,6 +22,7 @@ use Filament\Tables\Columns\TextColumn;
22 22
 use Filament\Tables\Contracts\HasTable;
23 23
 use Illuminate\Contracts\Support\Htmlable;
24 24
 use Illuminate\Support\Carbon;
25
+use Illuminate\Support\Collection;
25 26
 use Illuminate\Support\HtmlString;
26 27
 use Illuminate\Support\ServiceProvider;
27 28
 
@@ -40,6 +41,10 @@ class MacroServiceProvider extends ServiceProvider
40 41
      */
41 42
     public function boot(): void
42 43
     {
44
+        Collection::macro('whereNot', function (callable | string $key, mixed $value = null): Collection {
45
+            return $this->where($key, '!=', $value);
46
+        });
47
+
43 48
         TextInput::macro('money', function (string | Closure | null $currency = null, bool $useAffix = true): static {
44 49
             $currency ??= CurrencyAccessor::getDefaultCurrency();
45 50
 

+ 3
- 1
app/Services/AccountService.php Ver fichero

@@ -381,6 +381,7 @@ class AccountService
381 381
                 'invoices.client_id',
382 382
                 'invoices.due_date',
383 383
                 'invoices.amount_due',
384
+                'invoices.currency_code',
384 385
                 DB::raw('DATEDIFF(?, invoices.due_date) as days_overdue'),
385 386
             ])
386 387
             ->addBinding([$asOfDate], 'select')
@@ -398,10 +399,11 @@ class AccountService
398 399
                 'bills.vendor_id',
399 400
                 'bills.due_date',
400 401
                 'bills.amount_due',
402
+                'bills.currency_code',
401 403
                 DB::raw('DATEDIFF(?, bills.due_date) as days_overdue'),
402 404
             ])
403 405
             ->addBinding([$asOfDate], 'select')
404
-            ->outstanding()
406
+            ->unpaid()
405 407
             ->where('amount_due', '>', 0);
406 408
     }
407 409
 }

+ 218
- 29
app/Services/ReportService.php Ver fichero

@@ -2,7 +2,8 @@
2 2
 
3 3
 namespace App\Services;
4 4
 
5
-use App\Contracts\MoneyFormattableDTO;
5
+use App\Collections\Accounting\DocumentCollection;
6
+use App\Contracts\BalanceFormattable;
6 7
 use App\DTO\AccountBalanceDTO;
7 8
 use App\DTO\AccountCategoryDTO;
8 9
 use App\DTO\AccountDTO;
@@ -10,13 +11,19 @@ use App\DTO\AccountTransactionDTO;
10 11
 use App\DTO\AccountTypeDTO;
11 12
 use App\DTO\AgingBucketDTO;
12 13
 use App\DTO\CashFlowOverviewDTO;
14
+use App\DTO\EntityBalanceDTO;
13 15
 use App\DTO\EntityReportDTO;
16
+use App\DTO\PaymentMetricsDTO;
14 17
 use App\DTO\ReportDTO;
15 18
 use App\Enums\Accounting\AccountCategory;
16 19
 use App\Enums\Accounting\AccountType;
20
+use App\Enums\Accounting\BillStatus;
17 21
 use App\Enums\Accounting\DocumentEntityType;
22
+use App\Enums\Accounting\InvoiceStatus;
18 23
 use App\Enums\Accounting\TransactionType;
19 24
 use App\Models\Accounting\Account;
25
+use App\Models\Accounting\Bill;
26
+use App\Models\Accounting\Invoice;
20 27
 use App\Models\Accounting\Transaction;
21 28
 use App\Support\Column;
22 29
 use App\Utilities\Currency\CurrencyAccessor;
@@ -24,6 +31,7 @@ use App\Utilities\Currency\CurrencyConverter;
24 31
 use App\ValueObjects\Money;
25 32
 use Illuminate\Database\Eloquent\Builder;
26 33
 use Illuminate\Support\Carbon;
34
+use Illuminate\Support\Number;
27 35
 
28 36
 class ReportService
29 37
 {
@@ -32,9 +40,9 @@ class ReportService
32 40
     ) {}
33 41
 
34 42
     /**
35
-     * @param  class-string<MoneyFormattableDTO>|null  $dtoClass
43
+     * @param  class-string<BalanceFormattable>|null  $dtoClass
36 44
      */
37
-    public function formatBalances(array $balances, ?string $dtoClass = null, bool $formatZeros = true): MoneyFormattableDTO | array
45
+    public function formatBalances(array $balances, ?string $dtoClass = null, bool $formatZeros = true): BalanceFormattable | array
38 46
     {
39 47
         $dtoClass ??= AccountBalanceDTO::class;
40 48
 
@@ -373,7 +381,7 @@ class ReportService
373 381
         return new ReportDTO(categories: $accountCategories, overallTotal: $formattedReportTotalBalances, fields: $columns, reportType: $trialBalanceType);
374 382
     }
375 383
 
376
-    public function getRetainedEarningsBalances(string $startDate, string $endDate): MoneyFormattableDTO | array
384
+    public function getRetainedEarningsBalances(string $startDate, string $endDate): BalanceFormattable | array
377 385
     {
378 386
         $retainedEarningsAmount = $this->calculateRetainedEarnings($startDate, $endDate)->getAmount();
379 387
 
@@ -516,7 +524,7 @@ class ReportService
516 524
         );
517 525
     }
518 526
 
519
-    private function calculateTotalCashFlows(array $sections, string $startDate): MoneyFormattableDTO | array
527
+    private function calculateTotalCashFlows(array $sections, string $startDate): BalanceFormattable | array
520 528
     {
521 529
         $totalInflow = 0;
522 530
         $totalOutflow = 0;
@@ -843,38 +851,39 @@ class ReportService
843 851
             : $this->accountService->getUnpaidVendorBills($asOfDate)->with(['vendor:id,name'])->get()->groupBy('vendor_id');
844 852
 
845 853
         $categories = [];
846
-
847
-        $agingBuckets = ['current' => 0];
848
-
854
+        $totalAging = [
855
+            'current' => 0,
856
+        ];
849 857
         for ($i = 1; $i <= $numberOfPeriods; $i++) {
850
-            $agingBuckets["period_{$i}"] = 0;
858
+            $totalAging["period_{$i}"] = 0;
851 859
         }
860
+        $totalAging['over_periods'] = 0;
861
+        $totalAging['total'] = 0;
852 862
 
853
-        $agingBuckets['over_periods'] = 0;
854
-        $agingBuckets['total'] = 0;
855
-
856
-        $totalAging = $agingBuckets;
857
-
863
+        /** @var DocumentCollection<int,Invoice|Bill> $entityDocuments */
858 864
         foreach ($documents as $entityId => $entityDocuments) {
859
-            $aging = $agingBuckets;
860
-
861
-            foreach ($entityDocuments as $document) {
862
-                $daysOverdue = $document->days_overdue ?? 0;
863
-                $balance = $document->getRawOriginal('amount_due');
865
+            $aging = [
866
+                'current' => $entityDocuments
867
+                    ->filter(static fn ($doc) => ($doc->days_overdue ?? 0) <= 0)
868
+                    ->sumMoneyInDefaultCurrency('amount_due'),
869
+            ];
864 870
 
865
-                if ($daysOverdue <= 0) {
866
-                    $aging['current'] += $balance;
867
-                } else {
868
-                    $period = ceil($daysOverdue / $daysPerPeriod);
871
+            for ($i = 1; $i <= $numberOfPeriods; $i++) {
872
+                $min = ($i - 1) * $daysPerPeriod;
873
+                $max = $i * $daysPerPeriod;
874
+                $aging["period_{$i}"] = $entityDocuments
875
+                    ->filter(static function ($doc) use ($min, $max) {
876
+                        $days = $doc->days_overdue ?? 0;
869 877
 
870
-                    if ($period <= $numberOfPeriods) {
871
-                        $aging["period_{$period}"] += $balance;
872
-                    } else {
873
-                        $aging['over_periods'] += $balance;
874
-                    }
875
-                }
878
+                        return $days > $min && $days <= $max;
879
+                    })
880
+                    ->sumMoneyInDefaultCurrency('amount_due');
876 881
             }
877 882
 
883
+            $aging['over_periods'] = $entityDocuments
884
+                ->filter(static fn ($doc) => ($doc->days_overdue ?? 0) > ($numberOfPeriods * $daysPerPeriod))
885
+                ->sumMoneyInDefaultCurrency('amount_due');
886
+
878 887
             $aging['total'] = array_sum($aging);
879 888
 
880 889
             foreach ($aging as $bucket => $amount) {
@@ -899,4 +908,184 @@ class ReportService
899 908
             endDate: $asOfDateCarbon,
900 909
         );
901 910
     }
911
+
912
+    public function buildEntityBalanceSummaryReport(string $startDate, string $endDate, DocumentEntityType $entityType, array $columns = []): ReportDTO
913
+    {
914
+        $documents = match ($entityType) {
915
+            DocumentEntityType::Client => Invoice::query()
916
+                ->whereBetween('date', [$startDate, $endDate])
917
+                ->whereNotIn('status', [
918
+                    InvoiceStatus::Draft,
919
+                    InvoiceStatus::Void,
920
+                ])
921
+                ->whereNotNull('approved_at')
922
+                ->with(['client:id,name'])
923
+                ->get()
924
+                ->groupBy('client_id'),
925
+            DocumentEntityType::Vendor => Bill::query()
926
+                ->whereBetween('date', [$startDate, $endDate])
927
+                ->whereNot('status', BillStatus::Void)
928
+                ->with(['vendor:id,name'])
929
+                ->get()
930
+                ->groupBy('vendor_id'),
931
+        };
932
+
933
+        $entities = [];
934
+        $totalBalance = 0;
935
+        $totalPaidBalance = 0;
936
+        $totalUnpaidBalance = 0;
937
+
938
+        /** @var DocumentCollection<int,Invoice|Bill> $entityDocuments */
939
+        foreach ($documents as $entityDocuments) {
940
+            $entityTotalBalance = $entityDocuments->sumMoneyInDefaultCurrency('total');
941
+
942
+            $entityPaidBalance = $entityDocuments->sumMoneyInDefaultCurrency('amount_paid');
943
+
944
+            $entityUnpaidBalance = match ($entityType) {
945
+                DocumentEntityType::Client => $entityDocuments->whereNot('status', InvoiceStatus::Overpaid)
946
+                    ->sumMoneyInDefaultCurrency('amount_due'),
947
+                DocumentEntityType::Vendor => $entityDocuments->whereIn('status', [BillStatus::Open, BillStatus::Partial, BillStatus::Overdue])
948
+                    ->sumMoneyInDefaultCurrency('amount_due'),
949
+            };
950
+
951
+            $totalBalance += $entityTotalBalance;
952
+            $totalPaidBalance += $entityPaidBalance;
953
+            $totalUnpaidBalance += $entityUnpaidBalance;
954
+
955
+            $formattedBalances = $this->formatBalances([
956
+                'total_balance' => $entityTotalBalance,
957
+                'paid_balance' => $entityPaidBalance,
958
+                'unpaid_balance' => $entityUnpaidBalance,
959
+            ], EntityBalanceDTO::class);
960
+
961
+            $entity = $entityDocuments->first()->{$entityType->value};
962
+
963
+            $entities[] = new EntityReportDTO(
964
+                name: $entity->name,
965
+                id: $entity->id,
966
+                balance: $formattedBalances,
967
+            );
968
+        }
969
+
970
+        $entityBalanceTotal = $this->formatBalances([
971
+            'total_balance' => $totalBalance,
972
+            'paid_balance' => $totalPaidBalance,
973
+            'unpaid_balance' => $totalUnpaidBalance,
974
+        ], EntityBalanceDTO::class);
975
+
976
+        return new ReportDTO(
977
+            categories: ['Entities' => $entities],
978
+            entityBalanceTotal: $entityBalanceTotal,
979
+            fields: $columns,
980
+            startDate: Carbon::parse($startDate),
981
+            endDate: Carbon::parse($endDate),
982
+        );
983
+    }
984
+
985
+    public function buildEntityPaymentPerformanceReport(
986
+        string $startDate,
987
+        string $endDate,
988
+        DocumentEntityType $entityType,
989
+        array $columns = []
990
+    ): ReportDTO {
991
+        $documents = match ($entityType) {
992
+            DocumentEntityType::Client => Invoice::query()
993
+                ->whereBetween('date', [$startDate, $endDate])
994
+                ->whereNotIn('status', [InvoiceStatus::Draft, InvoiceStatus::Void])
995
+                ->whereNotNull('approved_at')
996
+                ->whereNotNull('paid_at')
997
+                ->with(['client:id,name'])
998
+                ->get()
999
+                ->groupBy('client_id'),
1000
+            DocumentEntityType::Vendor => Bill::query()
1001
+                ->whereBetween('date', [$startDate, $endDate])
1002
+                ->whereNotIn('status', [BillStatus::Void])
1003
+                ->whereNotNull('paid_at')
1004
+                ->with(['vendor:id,name'])
1005
+                ->get()
1006
+                ->groupBy('vendor_id'),
1007
+        };
1008
+
1009
+        $categories = [];
1010
+        $totalDocs = 0;
1011
+        $totalOnTime = 0;
1012
+        $totalLate = 0;
1013
+        $allPaymentDays = [];
1014
+        $allLateDays = [];
1015
+
1016
+        /** @var DocumentCollection<int,Invoice|Bill> $entityDocuments */
1017
+        foreach ($documents as $entityId => $entityDocuments) {
1018
+            $entity = $entityDocuments->first()->{$entityType->value};
1019
+
1020
+            $onTimeDocs = $entityDocuments->filter(fn (Invoice | Bill $doc) => $doc->paid_at->lte($doc->due_date));
1021
+            $onTimeCount = $onTimeDocs->count();
1022
+
1023
+            $lateDocs = $entityDocuments->filter(fn (Invoice | Bill $doc) => $doc->paid_at->gt($doc->due_date));
1024
+            $lateCount = $lateDocs->count();
1025
+
1026
+            $avgDaysToPay = $entityDocuments->avg(
1027
+                fn (Invoice | Bill $doc) => $doc instanceof Invoice
1028
+                    ? $doc->approved_at->diffInDays($doc->paid_at)
1029
+                    : $doc->date->diffInDays($doc->paid_at)
1030
+            ) ?? 0;
1031
+
1032
+            $avgDaysLate = $lateDocs->avg(fn (Invoice | Bill $doc) => $doc->due_date->diffInDays($doc->paid_at)) ?? 0;
1033
+
1034
+            $onTimeRate = $entityDocuments->isNotEmpty()
1035
+                ? ($onTimeCount / $entityDocuments->count() * 100)
1036
+                : 0;
1037
+
1038
+            $totalDocs += $entityDocuments->count();
1039
+            $totalOnTime += $onTimeCount;
1040
+            $totalLate += $lateCount;
1041
+
1042
+            $entityDocuments->each(function (Invoice | Bill $doc) use (&$allPaymentDays, &$allLateDays) {
1043
+                $allPaymentDays[] = $doc instanceof Invoice
1044
+                    ? $doc->approved_at->diffInDays($doc->paid_at)
1045
+                    : $doc->date->diffInDays($doc->paid_at);
1046
+
1047
+                if ($doc->paid_at->gt($doc->due_date)) {
1048
+                    $allLateDays[] = $doc->due_date->diffInDays($doc->paid_at);
1049
+                }
1050
+            });
1051
+
1052
+            $categories[] = new EntityReportDTO(
1053
+                name: $entity->name,
1054
+                id: $entityId,
1055
+                paymentMetrics: new PaymentMetricsDTO(
1056
+                    totalDocuments: $entityDocuments->count(),
1057
+                    onTimeCount: $onTimeCount ?: null,
1058
+                    lateCount: $lateCount ?: null,
1059
+                    avgDaysToPay: $avgDaysToPay ? round($avgDaysToPay) : null,
1060
+                    avgDaysLate: $avgDaysLate ? round($avgDaysLate) : null,
1061
+                    onTimePaymentRate: Number::percentage($onTimeRate, maxPrecision: 2),
1062
+                ),
1063
+            );
1064
+        }
1065
+
1066
+        $categories = collect($categories)
1067
+            ->sortByDesc(static fn (EntityReportDTO $category) => $category->paymentMetrics->onTimePaymentRate, SORT_NATURAL)
1068
+            ->values()
1069
+            ->all();
1070
+
1071
+        $overallMetrics = new PaymentMetricsDTO(
1072
+            totalDocuments: $totalDocs,
1073
+            onTimeCount: $totalOnTime,
1074
+            lateCount: $totalLate,
1075
+            avgDaysToPay: round(collect($allPaymentDays)->avg() ?? 0),
1076
+            avgDaysLate: round(collect($allLateDays)->avg() ?? 0),
1077
+            onTimePaymentRate: Number::percentage(
1078
+                $totalDocs > 0 ? ($totalOnTime / $totalDocs * 100) : 0,
1079
+                maxPrecision: 2
1080
+            ),
1081
+        );
1082
+
1083
+        return new ReportDTO(
1084
+            categories: ['Entities' => $categories],
1085
+            overallPaymentMetrics: $overallMetrics,
1086
+            fields: $columns,
1087
+            startDate: Carbon::parse($startDate),
1088
+            endDate: Carbon::parse($endDate),
1089
+        );
1090
+    }
902 1091
 }

+ 1
- 1
app/Transformers/AgingReportTransformer.php Ver fichero

@@ -18,7 +18,7 @@ class AgingReportTransformer extends BaseReportTransformer
18 18
 
19 19
     public function getTitle(): string
20 20
     {
21
-        return $this->entityType->getReportTitle();
21
+        return $this->entityType->getAgingReportTitle();
22 22
     }
23 23
 
24 24
     /**

+ 77
- 0
app/Transformers/EntityBalanceSummaryReportTransformer.php Ver fichero

@@ -0,0 +1,77 @@
1
+<?php
2
+
3
+namespace App\Transformers;
4
+
5
+use App\DTO\EntityReportDTO;
6
+use App\DTO\ReportCategoryDTO;
7
+use App\DTO\ReportDTO;
8
+use App\Enums\Accounting\DocumentEntityType;
9
+
10
+class EntityBalanceSummaryReportTransformer extends BaseReportTransformer
11
+{
12
+    public function __construct(
13
+        ReportDTO $report,
14
+        private readonly DocumentEntityType $entityType,
15
+    ) {
16
+        parent::__construct($report);
17
+    }
18
+
19
+    public function getTitle(): string
20
+    {
21
+        return $this->entityType->getBalanceSummaryReportTitle();
22
+    }
23
+
24
+    /**
25
+     * @return ReportCategoryDTO[]
26
+     */
27
+    public function getCategories(): array
28
+    {
29
+        $categories = [];
30
+
31
+        foreach ($this->report->categories as $categoryName => $category) {
32
+            $data = array_map(function (EntityReportDTO $entity) {
33
+                $row = [];
34
+
35
+                foreach ($this->getColumns() as $column) {
36
+                    $row[$column->getName()] = match ($column->getName()) {
37
+                        'entity_name' => [
38
+                            'name' => $entity->name,
39
+                            'id' => $entity->id,
40
+                        ],
41
+                        'total_balance' => $entity->balance->totalBalance,
42
+                        'paid_balance' => $entity->balance->paidBalance,
43
+                        'unpaid_balance' => $entity->balance->unpaidBalance,
44
+                        default => '',
45
+                    };
46
+                }
47
+
48
+                return $row;
49
+            }, $category);
50
+
51
+            $categories[] = new ReportCategoryDTO(
52
+                header: null,
53
+                data: $data,
54
+                summary: null,
55
+            );
56
+        }
57
+
58
+        return $categories;
59
+    }
60
+
61
+    public function getOverallTotals(): array
62
+    {
63
+        $totals = [];
64
+
65
+        foreach ($this->getColumns() as $column) {
66
+            $totals[$column->getName()] = match ($column->getName()) {
67
+                'entity_name' => 'Total',
68
+                'total_balance' => $this->report->entityBalanceTotal->totalBalance,
69
+                'paid_balance' => $this->report->entityBalanceTotal->paidBalance,
70
+                'unpaid_balance' => $this->report->entityBalanceTotal->unpaidBalance,
71
+                default => '',
72
+            };
73
+        }
74
+
75
+        return $totals;
76
+    }
77
+}

+ 83
- 0
app/Transformers/EntityPaymentPerformanceReportTransformer.php Ver fichero

@@ -0,0 +1,83 @@
1
+<?php
2
+
3
+namespace App\Transformers;
4
+
5
+use App\DTO\EntityReportDTO;
6
+use App\DTO\ReportCategoryDTO;
7
+use App\DTO\ReportDTO;
8
+use App\Enums\Accounting\DocumentEntityType;
9
+
10
+class EntityPaymentPerformanceReportTransformer extends BaseReportTransformer
11
+{
12
+    public function __construct(
13
+        ReportDTO $report,
14
+        private readonly DocumentEntityType $entityType,
15
+    ) {
16
+        parent::__construct($report);
17
+    }
18
+
19
+    public function getTitle(): string
20
+    {
21
+        return $this->entityType->getPaymentPerformanceReportTitle();
22
+    }
23
+
24
+    /**
25
+     * @return ReportCategoryDTO[]
26
+     */
27
+    public function getCategories(): array
28
+    {
29
+        $categories = [];
30
+
31
+        foreach ($this->report->categories as $categoryName => $category) {
32
+            $data = array_map(function (EntityReportDTO $entity) {
33
+                $row = [];
34
+
35
+                foreach ($this->getColumns() as $column) {
36
+                    $row[$column->getName()] = match ($column->getName()) {
37
+                        'entity_name' => [
38
+                            'name' => $entity->name,
39
+                            'id' => $entity->id,
40
+                        ],
41
+                        'total_documents' => $entity->paymentMetrics->totalDocuments,
42
+                        'on_time_count' => $entity->paymentMetrics->onTimeCount,
43
+                        'late_count' => $entity->paymentMetrics->lateCount,
44
+                        'avg_days_to_pay' => $entity->paymentMetrics->avgDaysToPay,
45
+                        'avg_days_late' => $entity->paymentMetrics->avgDaysLate,
46
+                        'on_time_payment_rate' => $entity->paymentMetrics->onTimePaymentRate,
47
+                        default => '',
48
+                    };
49
+                }
50
+
51
+                return $row;
52
+            }, $category);
53
+
54
+            $categories[] = new ReportCategoryDTO(
55
+                header: null,
56
+                data: $data,
57
+                summary: null,
58
+            );
59
+        }
60
+
61
+        return $categories;
62
+    }
63
+
64
+    public function getOverallTotals(): array
65
+    {
66
+        $totals = [];
67
+
68
+        foreach ($this->getColumns() as $column) {
69
+            $totals[$column->getName()] = match ($column->getName()) {
70
+                'entity_name' => 'Overall Totals',
71
+                'total_documents' => $this->report->overallPaymentMetrics->totalDocuments,
72
+                'on_time_count' => $this->report->overallPaymentMetrics->onTimeCount,
73
+                'late_count' => $this->report->overallPaymentMetrics->lateCount,
74
+                'avg_days_to_pay' => $this->report->overallPaymentMetrics->avgDaysToPay,
75
+                'avg_days_late' => $this->report->overallPaymentMetrics->avgDaysLate,
76
+                'on_time_payment_rate' => $this->report->overallPaymentMetrics->onTimePaymentRate,
77
+                default => '',
78
+            };
79
+        }
80
+
81
+        return $totals;
82
+    }
83
+}

+ 58
- 58
composer.lock Ver fichero

@@ -497,16 +497,16 @@
497 497
         },
498 498
         {
499 499
             "name": "aws/aws-sdk-php",
500
-            "version": "3.339.2",
500
+            "version": "3.339.4",
501 501
             "source": {
502 502
                 "type": "git",
503 503
                 "url": "https://github.com/aws/aws-sdk-php.git",
504
-                "reference": "2f4e85dd8466ffe5186887f8f1466a0248c6c094"
504
+                "reference": "ea62ad03645ef7a1d3f1cda2de49f0869de3c582"
505 505
             },
506 506
             "dist": {
507 507
                 "type": "zip",
508
-                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/2f4e85dd8466ffe5186887f8f1466a0248c6c094",
509
-                "reference": "2f4e85dd8466ffe5186887f8f1466a0248c6c094",
508
+                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/ea62ad03645ef7a1d3f1cda2de49f0869de3c582",
509
+                "reference": "ea62ad03645ef7a1d3f1cda2de49f0869de3c582",
510 510
                 "shasum": ""
511 511
             },
512 512
             "require": {
@@ -589,9 +589,9 @@
589 589
             "support": {
590 590
                 "forum": "https://github.com/aws/aws-sdk-php/discussions",
591 591
                 "issues": "https://github.com/aws/aws-sdk-php/issues",
592
-                "source": "https://github.com/aws/aws-sdk-php/tree/3.339.2"
592
+                "source": "https://github.com/aws/aws-sdk-php/tree/3.339.4"
593 593
             },
594
-            "time": "2025-01-29T19:53:29+00:00"
594
+            "time": "2025-01-31T19:04:39+00:00"
595 595
         },
596 596
         {
597 597
             "name": "aws/aws-sdk-php-laravel",
@@ -1733,16 +1733,16 @@
1733 1733
         },
1734 1734
         {
1735 1735
             "name": "filament/actions",
1736
-            "version": "v3.2.135",
1736
+            "version": "v3.2.136",
1737 1737
             "source": {
1738 1738
                 "type": "git",
1739 1739
                 "url": "https://github.com/filamentphp/actions.git",
1740
-                "reference": "dee2ca6d11e0ea3efb1190eabf6e483dbe2320ff"
1740
+                "reference": "cdefacc18993050cdd37e8e980ec66ca4109ae9a"
1741 1741
             },
1742 1742
             "dist": {
1743 1743
                 "type": "zip",
1744
-                "url": "https://api.github.com/repos/filamentphp/actions/zipball/dee2ca6d11e0ea3efb1190eabf6e483dbe2320ff",
1745
-                "reference": "dee2ca6d11e0ea3efb1190eabf6e483dbe2320ff",
1744
+                "url": "https://api.github.com/repos/filamentphp/actions/zipball/cdefacc18993050cdd37e8e980ec66ca4109ae9a",
1745
+                "reference": "cdefacc18993050cdd37e8e980ec66ca4109ae9a",
1746 1746
                 "shasum": ""
1747 1747
             },
1748 1748
             "require": {
@@ -1782,20 +1782,20 @@
1782 1782
                 "issues": "https://github.com/filamentphp/filament/issues",
1783 1783
                 "source": "https://github.com/filamentphp/filament"
1784 1784
             },
1785
-            "time": "2025-01-24T09:27:43+00:00"
1785
+            "time": "2025-01-31T11:08:24+00:00"
1786 1786
         },
1787 1787
         {
1788 1788
             "name": "filament/filament",
1789
-            "version": "v3.2.135",
1789
+            "version": "v3.2.136",
1790 1790
             "source": {
1791 1791
                 "type": "git",
1792 1792
                 "url": "https://github.com/filamentphp/panels.git",
1793
-                "reference": "bee6e1fd7b51f7dbffd03bc277b220bcfb8c45bb"
1793
+                "reference": "c92daf4b6e4b478be5d32d5e1b404ba92bb45414"
1794 1794
             },
1795 1795
             "dist": {
1796 1796
                 "type": "zip",
1797
-                "url": "https://api.github.com/repos/filamentphp/panels/zipball/bee6e1fd7b51f7dbffd03bc277b220bcfb8c45bb",
1798
-                "reference": "bee6e1fd7b51f7dbffd03bc277b220bcfb8c45bb",
1797
+                "url": "https://api.github.com/repos/filamentphp/panels/zipball/c92daf4b6e4b478be5d32d5e1b404ba92bb45414",
1798
+                "reference": "c92daf4b6e4b478be5d32d5e1b404ba92bb45414",
1799 1799
                 "shasum": ""
1800 1800
             },
1801 1801
             "require": {
@@ -1847,20 +1847,20 @@
1847 1847
                 "issues": "https://github.com/filamentphp/filament/issues",
1848 1848
                 "source": "https://github.com/filamentphp/filament"
1849 1849
             },
1850
-            "time": "2025-01-24T09:27:52+00:00"
1850
+            "time": "2025-01-31T11:08:29+00:00"
1851 1851
         },
1852 1852
         {
1853 1853
             "name": "filament/forms",
1854
-            "version": "v3.2.135",
1854
+            "version": "v3.2.136",
1855 1855
             "source": {
1856 1856
                 "type": "git",
1857 1857
                 "url": "https://github.com/filamentphp/forms.git",
1858
-                "reference": "e17618c921cd0300341a53d0eb2174c51e649565"
1858
+                "reference": "8856b3b3714a0efae65d9f817fcc1934b6f34fda"
1859 1859
             },
1860 1860
             "dist": {
1861 1861
                 "type": "zip",
1862
-                "url": "https://api.github.com/repos/filamentphp/forms/zipball/e17618c921cd0300341a53d0eb2174c51e649565",
1863
-                "reference": "e17618c921cd0300341a53d0eb2174c51e649565",
1862
+                "url": "https://api.github.com/repos/filamentphp/forms/zipball/8856b3b3714a0efae65d9f817fcc1934b6f34fda",
1863
+                "reference": "8856b3b3714a0efae65d9f817fcc1934b6f34fda",
1864 1864
                 "shasum": ""
1865 1865
             },
1866 1866
             "require": {
@@ -1903,20 +1903,20 @@
1903 1903
                 "issues": "https://github.com/filamentphp/filament/issues",
1904 1904
                 "source": "https://github.com/filamentphp/filament"
1905 1905
             },
1906
-            "time": "2025-01-24T09:27:50+00:00"
1906
+            "time": "2025-01-31T11:08:23+00:00"
1907 1907
         },
1908 1908
         {
1909 1909
             "name": "filament/infolists",
1910
-            "version": "v3.2.135",
1910
+            "version": "v3.2.136",
1911 1911
             "source": {
1912 1912
                 "type": "git",
1913 1913
                 "url": "https://github.com/filamentphp/infolists.git",
1914
-                "reference": "3330966b87da7d2078b62556428c279a6e8ff17c"
1914
+                "reference": "35c6dcbae24ae5fb086aeb1d13e2996442001674"
1915 1915
             },
1916 1916
             "dist": {
1917 1917
                 "type": "zip",
1918
-                "url": "https://api.github.com/repos/filamentphp/infolists/zipball/3330966b87da7d2078b62556428c279a6e8ff17c",
1919
-                "reference": "3330966b87da7d2078b62556428c279a6e8ff17c",
1918
+                "url": "https://api.github.com/repos/filamentphp/infolists/zipball/35c6dcbae24ae5fb086aeb1d13e2996442001674",
1919
+                "reference": "35c6dcbae24ae5fb086aeb1d13e2996442001674",
1920 1920
                 "shasum": ""
1921 1921
             },
1922 1922
             "require": {
@@ -1954,20 +1954,20 @@
1954 1954
                 "issues": "https://github.com/filamentphp/filament/issues",
1955 1955
                 "source": "https://github.com/filamentphp/filament"
1956 1956
             },
1957
-            "time": "2025-01-24T09:27:49+00:00"
1957
+            "time": "2025-01-31T11:08:24+00:00"
1958 1958
         },
1959 1959
         {
1960 1960
             "name": "filament/notifications",
1961
-            "version": "v3.2.135",
1961
+            "version": "v3.2.136",
1962 1962
             "source": {
1963 1963
                 "type": "git",
1964 1964
                 "url": "https://github.com/filamentphp/notifications.git",
1965
-                "reference": "e864c50bc0b6e9eb46b5e3d93a672a66f80a0fbe"
1965
+                "reference": "214845e9f613716304707441c8227d2d70b2aabf"
1966 1966
             },
1967 1967
             "dist": {
1968 1968
                 "type": "zip",
1969
-                "url": "https://api.github.com/repos/filamentphp/notifications/zipball/e864c50bc0b6e9eb46b5e3d93a672a66f80a0fbe",
1970
-                "reference": "e864c50bc0b6e9eb46b5e3d93a672a66f80a0fbe",
1969
+                "url": "https://api.github.com/repos/filamentphp/notifications/zipball/214845e9f613716304707441c8227d2d70b2aabf",
1970
+                "reference": "214845e9f613716304707441c8227d2d70b2aabf",
1971 1971
                 "shasum": ""
1972 1972
             },
1973 1973
             "require": {
@@ -2006,11 +2006,11 @@
2006 2006
                 "issues": "https://github.com/filamentphp/filament/issues",
2007 2007
                 "source": "https://github.com/filamentphp/filament"
2008 2008
             },
2009
-            "time": "2025-01-24T09:27:49+00:00"
2009
+            "time": "2025-01-31T11:08:23+00:00"
2010 2010
         },
2011 2011
         {
2012 2012
             "name": "filament/support",
2013
-            "version": "v3.2.135",
2013
+            "version": "v3.2.136",
2014 2014
             "source": {
2015 2015
                 "type": "git",
2016 2016
                 "url": "https://github.com/filamentphp/support.git",
@@ -2069,16 +2069,16 @@
2069 2069
         },
2070 2070
         {
2071 2071
             "name": "filament/tables",
2072
-            "version": "v3.2.135",
2072
+            "version": "v3.2.136",
2073 2073
             "source": {
2074 2074
                 "type": "git",
2075 2075
                 "url": "https://github.com/filamentphp/tables.git",
2076
-                "reference": "db63ab6fd7c2046dc9b1fc6fbd92df0a1aabb54e"
2076
+                "reference": "1b1d9c3b837c11408ad28240dc9e3e33340d870b"
2077 2077
             },
2078 2078
             "dist": {
2079 2079
                 "type": "zip",
2080
-                "url": "https://api.github.com/repos/filamentphp/tables/zipball/db63ab6fd7c2046dc9b1fc6fbd92df0a1aabb54e",
2081
-                "reference": "db63ab6fd7c2046dc9b1fc6fbd92df0a1aabb54e",
2080
+                "url": "https://api.github.com/repos/filamentphp/tables/zipball/1b1d9c3b837c11408ad28240dc9e3e33340d870b",
2081
+                "reference": "1b1d9c3b837c11408ad28240dc9e3e33340d870b",
2082 2082
                 "shasum": ""
2083 2083
             },
2084 2084
             "require": {
@@ -2117,20 +2117,20 @@
2117 2117
                 "issues": "https://github.com/filamentphp/filament/issues",
2118 2118
                 "source": "https://github.com/filamentphp/filament"
2119 2119
             },
2120
-            "time": "2025-01-24T09:28:02+00:00"
2120
+            "time": "2025-01-31T11:08:58+00:00"
2121 2121
         },
2122 2122
         {
2123 2123
             "name": "filament/widgets",
2124
-            "version": "v3.2.135",
2124
+            "version": "v3.2.136",
2125 2125
             "source": {
2126 2126
                 "type": "git",
2127 2127
                 "url": "https://github.com/filamentphp/widgets.git",
2128
-                "reference": "9f6674daceced7d5045494d0bf7e1d2908ea439d"
2128
+                "reference": "3b95cfc23cf7a2b112ca65b067a33c1af7f79dc7"
2129 2129
             },
2130 2130
             "dist": {
2131 2131
                 "type": "zip",
2132
-                "url": "https://api.github.com/repos/filamentphp/widgets/zipball/9f6674daceced7d5045494d0bf7e1d2908ea439d",
2133
-                "reference": "9f6674daceced7d5045494d0bf7e1d2908ea439d",
2132
+                "url": "https://api.github.com/repos/filamentphp/widgets/zipball/3b95cfc23cf7a2b112ca65b067a33c1af7f79dc7",
2133
+                "reference": "3b95cfc23cf7a2b112ca65b067a33c1af7f79dc7",
2134 2134
                 "shasum": ""
2135 2135
             },
2136 2136
             "require": {
@@ -2161,7 +2161,7 @@
2161 2161
                 "issues": "https://github.com/filamentphp/filament/issues",
2162 2162
                 "source": "https://github.com/filamentphp/filament"
2163 2163
             },
2164
-            "time": "2025-01-10T12:48:52+00:00"
2164
+            "time": "2025-01-31T11:08:59+00:00"
2165 2165
         },
2166 2166
         {
2167 2167
             "name": "firebase/php-jwt",
@@ -3051,16 +3051,16 @@
3051 3051
         },
3052 3052
         {
3053 3053
             "name": "laravel/framework",
3054
-            "version": "v11.41.0",
3054
+            "version": "v11.41.3",
3055 3055
             "source": {
3056 3056
                 "type": "git",
3057 3057
                 "url": "https://github.com/laravel/framework.git",
3058
-                "reference": "42d6ae000c868c2abfa946da46702f2358493482"
3058
+                "reference": "3ef433d5865f30a19b6b1be247586068399b59cc"
3059 3059
             },
3060 3060
             "dist": {
3061 3061
                 "type": "zip",
3062
-                "url": "https://api.github.com/repos/laravel/framework/zipball/42d6ae000c868c2abfa946da46702f2358493482",
3063
-                "reference": "42d6ae000c868c2abfa946da46702f2358493482",
3062
+                "url": "https://api.github.com/repos/laravel/framework/zipball/3ef433d5865f30a19b6b1be247586068399b59cc",
3063
+                "reference": "3ef433d5865f30a19b6b1be247586068399b59cc",
3064 3064
                 "shasum": ""
3065 3065
             },
3066 3066
             "require": {
@@ -3262,7 +3262,7 @@
3262 3262
                 "issues": "https://github.com/laravel/framework/issues",
3263 3263
                 "source": "https://github.com/laravel/framework"
3264 3264
             },
3265
-            "time": "2025-01-28T15:22:55+00:00"
3265
+            "time": "2025-01-30T13:25:22+00:00"
3266 3266
         },
3267 3267
         {
3268 3268
             "name": "laravel/prompts",
@@ -5136,16 +5136,16 @@
5136 5136
         },
5137 5137
         {
5138 5138
             "name": "openspout/openspout",
5139
-            "version": "v4.28.4",
5139
+            "version": "v4.28.5",
5140 5140
             "source": {
5141 5141
                 "type": "git",
5142 5142
                 "url": "https://github.com/openspout/openspout.git",
5143
-                "reference": "68d58235c7c1164b3d231b798975b9b0b2b79b15"
5143
+                "reference": "ab05a09fe6fce57c90338f83280648a9786ce36b"
5144 5144
             },
5145 5145
             "dist": {
5146 5146
                 "type": "zip",
5147
-                "url": "https://api.github.com/repos/openspout/openspout/zipball/68d58235c7c1164b3d231b798975b9b0b2b79b15",
5148
-                "reference": "68d58235c7c1164b3d231b798975b9b0b2b79b15",
5147
+                "url": "https://api.github.com/repos/openspout/openspout/zipball/ab05a09fe6fce57c90338f83280648a9786ce36b",
5148
+                "reference": "ab05a09fe6fce57c90338f83280648a9786ce36b",
5149 5149
                 "shasum": ""
5150 5150
             },
5151 5151
             "require": {
@@ -5159,13 +5159,13 @@
5159 5159
             },
5160 5160
             "require-dev": {
5161 5161
                 "ext-zlib": "*",
5162
-                "friendsofphp/php-cs-fixer": "^3.66.1",
5162
+                "friendsofphp/php-cs-fixer": "^3.68.3",
5163 5163
                 "infection/infection": "^0.29.10",
5164
-                "phpbench/phpbench": "^1.3.1",
5165
-                "phpstan/phpstan": "^2.1.1",
5166
-                "phpstan/phpstan-phpunit": "^2.0.3",
5164
+                "phpbench/phpbench": "^1.4.0",
5165
+                "phpstan/phpstan": "^2.1.2",
5166
+                "phpstan/phpstan-phpunit": "^2.0.4",
5167 5167
                 "phpstan/phpstan-strict-rules": "^2",
5168
-                "phpunit/phpunit": "^11.5.2"
5168
+                "phpunit/phpunit": "^11.5.4"
5169 5169
             },
5170 5170
             "suggest": {
5171 5171
                 "ext-iconv": "To handle non UTF-8 CSV files (if \"php-mbstring\" is not already installed or is too limited)",
@@ -5213,7 +5213,7 @@
5213 5213
             ],
5214 5214
             "support": {
5215 5215
                 "issues": "https://github.com/openspout/openspout/issues",
5216
-                "source": "https://github.com/openspout/openspout/tree/v4.28.4"
5216
+                "source": "https://github.com/openspout/openspout/tree/v4.28.5"
5217 5217
             },
5218 5218
             "funding": [
5219 5219
                 {
@@ -5225,7 +5225,7 @@
5225 5225
                     "type": "github"
5226 5226
                 }
5227 5227
             ],
5228
-            "time": "2025-01-07T11:48:34+00:00"
5228
+            "time": "2025-01-30T13:51:11+00:00"
5229 5229
         },
5230 5230
         {
5231 5231
             "name": "paragonie/constant_time_encoding",

+ 1
- 1
database/factories/Accounting/BillFactory.php Ver fichero

@@ -46,7 +46,7 @@ class BillFactory extends Factory
46 46
             'order_number' => $this->faker->unique()->numerify('PO-#####'),
47 47
             'date' => $billDate,
48 48
             'due_date' => Carbon::parse($billDate)->addDays($dueDays),
49
-            'status' => BillStatus::Unpaid,
49
+            'status' => BillStatus::Open,
50 50
             'currency_code' => 'USD',
51 51
             'notes' => $this->faker->sentence,
52 52
             'created_by' => 1,

+ 1
- 1
database/migrations/2024_11_27_221657_create_bills_table.php Ver fichero

@@ -20,7 +20,7 @@ return new class extends Migration
20 20
             $table->date('date')->nullable();
21 21
             $table->date('due_date')->nullable();
22 22
             $table->timestamp('paid_at')->nullable();
23
-            $table->string('status')->default('unpaid');
23
+            $table->string('status')->default('open');
24 24
             $table->string('currency_code')->nullable();
25 25
             $table->string('discount_method')->default('per_line_item');
26 26
             $table->string('discount_computation')->default('percentage');

+ 85
- 85
package-lock.json Ver fichero

@@ -575,9 +575,9 @@
575 575
             }
576 576
         },
577 577
         "node_modules/@rollup/rollup-android-arm-eabi": {
578
-            "version": "4.32.1",
579
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.32.1.tgz",
580
-            "integrity": "sha512-/pqA4DmqyCm8u5YIDzIdlLcEmuvxb0v8fZdFhVMszSpDTgbQKdw3/mB3eMUHIbubtJ6F9j+LtmyCnHTEqIHyzA==",
578
+            "version": "4.34.0",
579
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.0.tgz",
580
+            "integrity": "sha512-Eeao7ewDq79jVEsrtWIj5RNqB8p2knlm9fhR6uJ2gqP7UfbLrTrxevudVrEPDM7Wkpn/HpRC2QfazH7MXLz3vQ==",
581 581
             "cpu": [
582 582
                 "arm"
583 583
             ],
@@ -589,9 +589,9 @@
589 589
             ]
590 590
         },
591 591
         "node_modules/@rollup/rollup-android-arm64": {
592
-            "version": "4.32.1",
593
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.32.1.tgz",
594
-            "integrity": "sha512-If3PDskT77q7zgqVqYuj7WG3WC08G1kwXGVFi9Jr8nY6eHucREHkfpX79c0ACAjLj3QIWKPJR7w4i+f5EdLH5Q==",
592
+            "version": "4.34.0",
593
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.0.tgz",
594
+            "integrity": "sha512-yVh0Kf1f0Fq4tWNf6mWcbQBCLDpDrDEl88lzPgKhrgTcDrTtlmun92ywEF9dCjmYO3EFiSuJeeo9cYRxl2FswA==",
595 595
             "cpu": [
596 596
                 "arm64"
597 597
             ],
@@ -603,9 +603,9 @@
603 603
             ]
604 604
         },
605 605
         "node_modules/@rollup/rollup-darwin-arm64": {
606
-            "version": "4.32.1",
607
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.32.1.tgz",
608
-            "integrity": "sha512-zCpKHioQ9KgZToFp5Wvz6zaWbMzYQ2LJHQ+QixDKq52KKrF65ueu6Af4hLlLWHjX1Wf/0G5kSJM9PySW9IrvHA==",
606
+            "version": "4.34.0",
607
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.0.tgz",
608
+            "integrity": "sha512-gCs0ErAZ9s0Osejpc3qahTsqIPUDjSKIyxK/0BGKvL+Tn0n3Kwvj8BrCv7Y5sR1Ypz1K2qz9Ny0VvkVyoXBVUQ==",
609 609
             "cpu": [
610 610
                 "arm64"
611 611
             ],
@@ -617,9 +617,9 @@
617 617
             ]
618 618
         },
619 619
         "node_modules/@rollup/rollup-darwin-x64": {
620
-            "version": "4.32.1",
621
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.32.1.tgz",
622
-            "integrity": "sha512-sFvF+t2+TyUo/ZQqUcifrJIgznx58oFZbdHS9TvHq3xhPVL9nOp+yZ6LKrO9GWTP+6DbFtoyLDbjTpR62Mbr3Q==",
620
+            "version": "4.34.0",
621
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.0.tgz",
622
+            "integrity": "sha512-aIB5Anc8hngk15t3GUkiO4pv42ykXHfmpXGS+CzM9CTyiWyT8HIS5ygRAy7KcFb/wiw4Br+vh1byqcHRTfq2tQ==",
623 623
             "cpu": [
624 624
                 "x64"
625 625
             ],
@@ -631,9 +631,9 @@
631 631
             ]
632 632
         },
633 633
         "node_modules/@rollup/rollup-freebsd-arm64": {
634
-            "version": "4.32.1",
635
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.32.1.tgz",
636
-            "integrity": "sha512-NbOa+7InvMWRcY9RG+B6kKIMD/FsnQPH0MWUvDlQB1iXnF/UcKSudCXZtv4lW+C276g3w5AxPbfry5rSYvyeYA==",
634
+            "version": "4.34.0",
635
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.0.tgz",
636
+            "integrity": "sha512-kpdsUdMlVJMRMaOf/tIvxk8TQdzHhY47imwmASOuMajg/GXpw8GKNd8LNwIHE5Yd1onehNpcUB9jHY6wgw9nHQ==",
637 637
             "cpu": [
638 638
                 "arm64"
639 639
             ],
@@ -645,9 +645,9 @@
645 645
             ]
646 646
         },
647 647
         "node_modules/@rollup/rollup-freebsd-x64": {
648
-            "version": "4.32.1",
649
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.32.1.tgz",
650
-            "integrity": "sha512-JRBRmwvHPXR881j2xjry8HZ86wIPK2CcDw0EXchE1UgU0ubWp9nvlT7cZYKc6bkypBt745b4bglf3+xJ7hXWWw==",
648
+            "version": "4.34.0",
649
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.0.tgz",
650
+            "integrity": "sha512-D0RDyHygOBCQiqookcPevrvgEarN0CttBecG4chOeIYCNtlKHmf5oi5kAVpXV7qs0Xh/WO2RnxeicZPtT50V0g==",
651 651
             "cpu": [
652 652
                 "x64"
653 653
             ],
@@ -659,9 +659,9 @@
659 659
             ]
660 660
         },
661 661
         "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
662
-            "version": "4.32.1",
663
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.32.1.tgz",
664
-            "integrity": "sha512-PKvszb+9o/vVdUzCCjL0sKHukEQV39tD3fepXxYrHE3sTKrRdCydI7uldRLbjLmDA3TFDmh418XH19NOsDRH8g==",
662
+            "version": "4.34.0",
663
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.0.tgz",
664
+            "integrity": "sha512-mCIw8j5LPDXmCOW8mfMZwT6F/Kza03EnSr4wGYEswrEfjTfVsFOxvgYfuRMxTuUF/XmRb9WSMD5GhCWDe2iNrg==",
665 665
             "cpu": [
666 666
                 "arm"
667 667
             ],
@@ -673,9 +673,9 @@
673 673
             ]
674 674
         },
675 675
         "node_modules/@rollup/rollup-linux-arm-musleabihf": {
676
-            "version": "4.32.1",
677
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.32.1.tgz",
678
-            "integrity": "sha512-9WHEMV6Y89eL606ReYowXuGF1Yb2vwfKWKdD1A5h+OYnPZSJvxbEjxTRKPgi7tkP2DSnW0YLab1ooy+i/FQp/Q==",
676
+            "version": "4.34.0",
677
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.0.tgz",
678
+            "integrity": "sha512-AwwldAu4aCJPob7zmjuDUMvvuatgs8B/QiVB0KwkUarAcPB3W+ToOT+18TQwY4z09Al7G0BvCcmLRop5zBLTag==",
679 679
             "cpu": [
680 680
                 "arm"
681 681
             ],
@@ -687,9 +687,9 @@
687 687
             ]
688 688
         },
689 689
         "node_modules/@rollup/rollup-linux-arm64-gnu": {
690
-            "version": "4.32.1",
691
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.32.1.tgz",
692
-            "integrity": "sha512-tZWc9iEt5fGJ1CL2LRPw8OttkCBDs+D8D3oEM8mH8S1ICZCtFJhD7DZ3XMGM8kpqHvhGUTvNUYVDnmkj4BDXnw==",
690
+            "version": "4.34.0",
691
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.0.tgz",
692
+            "integrity": "sha512-e7kDUGVP+xw05pV65ZKb0zulRploU3gTu6qH1qL58PrULDGxULIS0OSDQJLH7WiFnpd3ZKUU4VM3u/Z7Zw+e7Q==",
693 693
             "cpu": [
694 694
                 "arm64"
695 695
             ],
@@ -701,9 +701,9 @@
701 701
             ]
702 702
         },
703 703
         "node_modules/@rollup/rollup-linux-arm64-musl": {
704
-            "version": "4.32.1",
705
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.32.1.tgz",
706
-            "integrity": "sha512-FTYc2YoTWUsBz5GTTgGkRYYJ5NGJIi/rCY4oK/I8aKowx1ToXeoVVbIE4LGAjsauvlhjfl0MYacxClLld1VrOw==",
704
+            "version": "4.34.0",
705
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.0.tgz",
706
+            "integrity": "sha512-SXYJw3zpwHgaBqTXeAZ31qfW/v50wq4HhNVvKFhRr5MnptRX2Af4KebLWR1wpxGJtLgfS2hEPuALRIY3LPAAcA==",
707 707
             "cpu": [
708 708
                 "arm64"
709 709
             ],
@@ -715,9 +715,9 @@
715 715
             ]
716 716
         },
717 717
         "node_modules/@rollup/rollup-linux-loongarch64-gnu": {
718
-            "version": "4.32.1",
719
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.32.1.tgz",
720
-            "integrity": "sha512-F51qLdOtpS6P1zJVRzYM0v6MrBNypyPEN1GfMiz0gPu9jN8ScGaEFIZQwteSsGKg799oR5EaP7+B2jHgL+d+Kw==",
718
+            "version": "4.34.0",
719
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.0.tgz",
720
+            "integrity": "sha512-e5XiCinINCI4RdyU3sFyBH4zzz7LiQRvHqDtRe9Dt8o/8hTBaYpdPimayF00eY2qy5j4PaaWK0azRgUench6WQ==",
721 721
             "cpu": [
722 722
                 "loong64"
723 723
             ],
@@ -729,9 +729,9 @@
729 729
             ]
730 730
         },
731 731
         "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
732
-            "version": "4.32.1",
733
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.32.1.tgz",
734
-            "integrity": "sha512-wO0WkfSppfX4YFm5KhdCCpnpGbtgQNj/tgvYzrVYFKDpven8w2N6Gg5nB6w+wAMO3AIfSTWeTjfVe+uZ23zAlg==",
732
+            "version": "4.34.0",
733
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.0.tgz",
734
+            "integrity": "sha512-3SWN3e0bAsm9ToprLFBSro8nJe6YN+5xmB11N4FfNf92wvLye/+Rh5JGQtKOpwLKt6e61R1RBc9g+luLJsc23A==",
735 735
             "cpu": [
736 736
                 "ppc64"
737 737
             ],
@@ -743,9 +743,9 @@
743 743
             ]
744 744
         },
745 745
         "node_modules/@rollup/rollup-linux-riscv64-gnu": {
746
-            "version": "4.32.1",
747
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.32.1.tgz",
748
-            "integrity": "sha512-iWswS9cIXfJO1MFYtI/4jjlrGb/V58oMu4dYJIKnR5UIwbkzR0PJ09O0PDZT0oJ3LYWXBSWahNf/Mjo6i1E5/g==",
746
+            "version": "4.34.0",
747
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.0.tgz",
748
+            "integrity": "sha512-B1Oqt3GLh7qmhvfnc2WQla4NuHlcxAD5LyueUi5WtMc76ZWY+6qDtQYqnxARx9r+7mDGfamD+8kTJO0pKUJeJA==",
749 749
             "cpu": [
750 750
                 "riscv64"
751 751
             ],
@@ -757,9 +757,9 @@
757 757
             ]
758 758
         },
759 759
         "node_modules/@rollup/rollup-linux-s390x-gnu": {
760
-            "version": "4.32.1",
761
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.32.1.tgz",
762
-            "integrity": "sha512-RKt8NI9tebzmEthMnfVgG3i/XeECkMPS+ibVZjZ6mNekpbbUmkNWuIN2yHsb/mBPyZke4nlI4YqIdFPgKuoyQQ==",
760
+            "version": "4.34.0",
761
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.0.tgz",
762
+            "integrity": "sha512-UfUCo0h/uj48Jq2lnhX0AOhZPSTAq3Eostas+XZ+GGk22pI+Op1Y6cxQ1JkUuKYu2iU+mXj1QjPrZm9nNWV9rg==",
763 763
             "cpu": [
764 764
                 "s390x"
765 765
             ],
@@ -771,9 +771,9 @@
771 771
             ]
772 772
         },
773 773
         "node_modules/@rollup/rollup-linux-x64-gnu": {
774
-            "version": "4.32.1",
775
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.32.1.tgz",
776
-            "integrity": "sha512-WQFLZ9c42ECqEjwg/GHHsouij3pzLXkFdz0UxHa/0OM12LzvX7DzedlY0SIEly2v18YZLRhCRoHZDxbBSWoGYg==",
774
+            "version": "4.34.0",
775
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.0.tgz",
776
+            "integrity": "sha512-chZLTUIPbgcpm+Z7ALmomXW8Zh+wE2icrG+K6nt/HenPLmtwCajhQC5flNSk1Xy5EDMt/QAOz2MhzfOfJOLSiA==",
777 777
             "cpu": [
778 778
                 "x64"
779 779
             ],
@@ -785,9 +785,9 @@
785 785
             ]
786 786
         },
787 787
         "node_modules/@rollup/rollup-linux-x64-musl": {
788
-            "version": "4.32.1",
789
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.32.1.tgz",
790
-            "integrity": "sha512-BLoiyHDOWoS3uccNSADMza6V6vCNiphi94tQlVIL5de+r6r/CCQuNnerf+1g2mnk2b6edp5dk0nhdZ7aEjOBsA==",
788
+            "version": "4.34.0",
789
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.0.tgz",
790
+            "integrity": "sha512-jo0UolK70O28BifvEsFD/8r25shFezl0aUk2t0VJzREWHkq19e+pcLu4kX5HiVXNz5qqkD+aAq04Ct8rkxgbyQ==",
791 791
             "cpu": [
792 792
                 "x64"
793 793
             ],
@@ -799,9 +799,9 @@
799 799
             ]
800 800
         },
801 801
         "node_modules/@rollup/rollup-win32-arm64-msvc": {
802
-            "version": "4.32.1",
803
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.32.1.tgz",
804
-            "integrity": "sha512-w2l3UnlgYTNNU+Z6wOR8YdaioqfEnwPjIsJ66KxKAf0p+AuL2FHeTX6qvM+p/Ue3XPBVNyVSfCrfZiQh7vZHLQ==",
802
+            "version": "4.34.0",
803
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.0.tgz",
804
+            "integrity": "sha512-Vmg0NhAap2S54JojJchiu5An54qa6t/oKT7LmDaWggpIcaiL8WcWHEN6OQrfTdL6mQ2GFyH7j2T5/3YPEDOOGA==",
805 805
             "cpu": [
806 806
                 "arm64"
807 807
             ],
@@ -813,9 +813,9 @@
813 813
             ]
814 814
         },
815 815
         "node_modules/@rollup/rollup-win32-ia32-msvc": {
816
-            "version": "4.32.1",
817
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.32.1.tgz",
818
-            "integrity": "sha512-Am9H+TGLomPGkBnaPWie4F3x+yQ2rr4Bk2jpwy+iV+Gel9jLAu/KqT8k3X4jxFPW6Zf8OMnehyutsd+eHoq1WQ==",
816
+            "version": "4.34.0",
817
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.0.tgz",
818
+            "integrity": "sha512-CV2aqhDDOsABKHKhNcs1SZFryffQf8vK2XrxP6lxC99ELZAdvsDgPklIBfd65R8R+qvOm1SmLaZ/Fdq961+m7A==",
819 819
             "cpu": [
820 820
                 "ia32"
821 821
             ],
@@ -827,9 +827,9 @@
827 827
             ]
828 828
         },
829 829
         "node_modules/@rollup/rollup-win32-x64-msvc": {
830
-            "version": "4.32.1",
831
-            "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.32.1.tgz",
832
-            "integrity": "sha512-ar80GhdZb4DgmW3myIS9nRFYcpJRSME8iqWgzH2i44u+IdrzmiXVxeFnExQ5v4JYUSpg94bWjevMG8JHf1Da5Q==",
830
+            "version": "4.34.0",
831
+            "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.0.tgz",
832
+            "integrity": "sha512-g2ASy1QwHP88y5KWvblUolJz9rN+i4ZOsYzkEwcNfaNooxNUXG+ON6F5xFo0NIItpHqxcdAyls05VXpBnludGw==",
833 833
             "cpu": [
834 834
                 "x64"
835 835
             ],
@@ -1235,9 +1235,9 @@
1235 1235
             "license": "MIT"
1236 1236
         },
1237 1237
         "node_modules/electron-to-chromium": {
1238
-            "version": "1.5.89",
1239
-            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.89.tgz",
1240
-            "integrity": "sha512-okLMJSmbI+XHr8aG+wCK+VPH+d38sHMED6/q1CTsCNkqfdOZL3k2ThWnh44HL6bJKj9cabPCSVLDv9ynsIm8qg==",
1238
+            "version": "1.5.90",
1239
+            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.90.tgz",
1240
+            "integrity": "sha512-C3PN4aydfW91Natdyd449Kw+BzhLmof6tzy5W1pFC5SpQxVXT+oyiyOG9AgYYSN9OdA/ik3YkCrpwqI8ug5Tug==",
1241 1241
             "dev": true,
1242 1242
             "license": "ISC"
1243 1243
         },
@@ -1330,9 +1330,9 @@
1330 1330
             }
1331 1331
         },
1332 1332
         "node_modules/fastq": {
1333
-            "version": "1.18.0",
1334
-            "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz",
1335
-            "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==",
1333
+            "version": "1.19.0",
1334
+            "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz",
1335
+            "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==",
1336 1336
             "dev": true,
1337 1337
             "license": "ISC",
1338 1338
             "dependencies": {
@@ -2242,9 +2242,9 @@
2242 2242
             }
2243 2243
         },
2244 2244
         "node_modules/rollup": {
2245
-            "version": "4.32.1",
2246
-            "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.32.1.tgz",
2247
-            "integrity": "sha512-z+aeEsOeEa3mEbS1Tjl6sAZ8NE3+AalQz1RJGj81M+fizusbdDMoEJwdJNHfaB40Scr4qNu+welOfes7maKonA==",
2245
+            "version": "4.34.0",
2246
+            "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.0.tgz",
2247
+            "integrity": "sha512-+4C/cgJ9w6sudisA0nZz0+O7lTP9a3CzNLsoDwaRumM8QHwghUsu6tqHXiTmNUp/rqNiM14++7dkzHDyCRs0Jg==",
2248 2248
             "dev": true,
2249 2249
             "license": "MIT",
2250 2250
             "dependencies": {
@@ -2258,25 +2258,25 @@
2258 2258
                 "npm": ">=8.0.0"
2259 2259
             },
2260 2260
             "optionalDependencies": {
2261
-                "@rollup/rollup-android-arm-eabi": "4.32.1",
2262
-                "@rollup/rollup-android-arm64": "4.32.1",
2263
-                "@rollup/rollup-darwin-arm64": "4.32.1",
2264
-                "@rollup/rollup-darwin-x64": "4.32.1",
2265
-                "@rollup/rollup-freebsd-arm64": "4.32.1",
2266
-                "@rollup/rollup-freebsd-x64": "4.32.1",
2267
-                "@rollup/rollup-linux-arm-gnueabihf": "4.32.1",
2268
-                "@rollup/rollup-linux-arm-musleabihf": "4.32.1",
2269
-                "@rollup/rollup-linux-arm64-gnu": "4.32.1",
2270
-                "@rollup/rollup-linux-arm64-musl": "4.32.1",
2271
-                "@rollup/rollup-linux-loongarch64-gnu": "4.32.1",
2272
-                "@rollup/rollup-linux-powerpc64le-gnu": "4.32.1",
2273
-                "@rollup/rollup-linux-riscv64-gnu": "4.32.1",
2274
-                "@rollup/rollup-linux-s390x-gnu": "4.32.1",
2275
-                "@rollup/rollup-linux-x64-gnu": "4.32.1",
2276
-                "@rollup/rollup-linux-x64-musl": "4.32.1",
2277
-                "@rollup/rollup-win32-arm64-msvc": "4.32.1",
2278
-                "@rollup/rollup-win32-ia32-msvc": "4.32.1",
2279
-                "@rollup/rollup-win32-x64-msvc": "4.32.1",
2261
+                "@rollup/rollup-android-arm-eabi": "4.34.0",
2262
+                "@rollup/rollup-android-arm64": "4.34.0",
2263
+                "@rollup/rollup-darwin-arm64": "4.34.0",
2264
+                "@rollup/rollup-darwin-x64": "4.34.0",
2265
+                "@rollup/rollup-freebsd-arm64": "4.34.0",
2266
+                "@rollup/rollup-freebsd-x64": "4.34.0",
2267
+                "@rollup/rollup-linux-arm-gnueabihf": "4.34.0",
2268
+                "@rollup/rollup-linux-arm-musleabihf": "4.34.0",
2269
+                "@rollup/rollup-linux-arm64-gnu": "4.34.0",
2270
+                "@rollup/rollup-linux-arm64-musl": "4.34.0",
2271
+                "@rollup/rollup-linux-loongarch64-gnu": "4.34.0",
2272
+                "@rollup/rollup-linux-powerpc64le-gnu": "4.34.0",
2273
+                "@rollup/rollup-linux-riscv64-gnu": "4.34.0",
2274
+                "@rollup/rollup-linux-s390x-gnu": "4.34.0",
2275
+                "@rollup/rollup-linux-x64-gnu": "4.34.0",
2276
+                "@rollup/rollup-linux-x64-musl": "4.34.0",
2277
+                "@rollup/rollup-win32-arm64-msvc": "4.34.0",
2278
+                "@rollup/rollup-win32-ia32-msvc": "4.34.0",
2279
+                "@rollup/rollup-win32-x64-msvc": "4.34.0",
2280 2280
                 "fsevents": "~2.3.2"
2281 2281
             }
2282 2282
         },

+ 4
- 0
resources/css/filament/company/theme.css Ver fichero

@@ -10,6 +10,10 @@
10 10
 
11 11
 @config 'tailwind.config.js';
12 12
 
13
+.fi-sidebar-nav {
14
+    scrollbar-width: thin;
15
+}
16
+
13 17
 .fi-ta-empty-state-icon-ctn {
14 18
     @apply bg-platinum;
15 19
 }

+ 4
- 4
resources/views/components/company/tables/container.blade.php Ver fichero

@@ -5,11 +5,11 @@
5 5
 <x-filament-tables::container>
6 6
     <div class="es-table__header-ctn"></div>
7 7
     <div
8
-        class="relative divide-y divide-gray-200 overflow-x-auto dark:divide-white/10 dark:border-t-white/10 min-h-64">
9
-        <div wire:init="applyFilters">
10
-            <div wire:loading.class="flex items-center justify-center w-full h-full absolute inset-0 z-10">
8
+        class="relative divide-y divide-gray-200 overflow-x-auto dark:divide-white/10 dark:border-t-white/10 min-h-40">
9
+        <div wire:init="applyFilters" class="relative min-h-40">
10
+            <div wire:loading.class="flex items-center justify-center w-full min-h-40 absolute inset-0 z-10">
11 11
                 <div wire:loading wire:target="applyFilters">
12
-                    <x-filament::loading-indicator class="p-6 text-primary-700 dark:text-primary-300"/>
12
+                    <x-filament::loading-indicator class="p-5 text-primary-700 dark:text-primary-300"/>
13 13
                 </div>
14 14
             </div>
15 15
 

Loading…
Cancelar
Guardar