Andrew Wallo 8 月之前
父節點
當前提交
fe4a8b61f1

+ 25
- 0
app/DTO/ClientBalanceDTO.php 查看文件

1
+<?php
2
+
3
+namespace App\DTO;
4
+
5
+use App\Contracts\MoneyFormattableDTO;
6
+
7
+class ClientBalanceDTO implements MoneyFormattableDTO
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
+}

+ 2
- 1
app/DTO/ClientReportDTO.php 查看文件

7
     public function __construct(
7
     public function __construct(
8
         public string $clientName,
8
         public string $clientName,
9
         public string $clientId,
9
         public string $clientId,
10
-        public AgingBucketDTO $aging,
10
+        public ?AgingBucketDTO $aging = null,
11
+        public ?ClientBalanceDTO $balance = null,
11
     ) {}
12
     ) {}
12
 }
13
 }

+ 1
- 0
app/DTO/ReportDTO.php 查看文件

13
         public array $categories,
13
         public array $categories,
14
         public ?AccountBalanceDTO $overallTotal = null,
14
         public ?AccountBalanceDTO $overallTotal = null,
15
         public ?AgingBucketDTO $agingSummary = null,
15
         public ?AgingBucketDTO $agingSummary = null,
16
+        public ?ClientBalanceDTO $clientBalanceTotal = null,
16
         public array $fields = [],
17
         public array $fields = [],
17
         public ?string $reportType = null,
18
         public ?string $reportType = null,
18
         public ?CashFlowOverviewDTO $overview = null,
19
         public ?CashFlowOverviewDTO $overview = null,

+ 9
- 8
app/Filament/Company/Pages/Reports.php 查看文件

8
 use App\Filament\Company\Pages\Reports\AccountTransactions;
8
 use App\Filament\Company\Pages\Reports\AccountTransactions;
9
 use App\Filament\Company\Pages\Reports\BalanceSheet;
9
 use App\Filament\Company\Pages\Reports\BalanceSheet;
10
 use App\Filament\Company\Pages\Reports\CashFlowStatement;
10
 use App\Filament\Company\Pages\Reports\CashFlowStatement;
11
+use App\Filament\Company\Pages\Reports\ClientBalanceSummary;
11
 use App\Filament\Company\Pages\Reports\IncomeStatement;
12
 use App\Filament\Company\Pages\Reports\IncomeStatement;
12
 use App\Filament\Company\Pages\Reports\TrialBalance;
13
 use App\Filament\Company\Pages\Reports\TrialBalance;
13
 use App\Filament\Infolists\Components\ReportEntry;
14
 use App\Filament\Infolists\Components\ReportEntry;
74
                             ->iconColor(Color::Cyan)
75
                             ->iconColor(Color::Cyan)
75
                             ->url(CashFlowStatement::getUrl()),
76
                             ->url(CashFlowStatement::getUrl()),
76
                     ]),
77
                     ]),
77
-                Section::make('Customer Reports')
78
+                Section::make('Client Reports')
78
                     ->aside()
79
                     ->aside()
79
-                    ->description('Reports that provide detailed information on your company’s customer transactions and balances.')
80
+                    ->description('Reports that provide detailed information on your company’s client transactions and balances.')
80
                     ->extraAttributes(['class' => 'es-report-card'])
81
                     ->extraAttributes(['class' => 'es-report-card'])
81
                     ->schema([
82
                     ->schema([
82
                         ReportEntry::make('ar_aging')
83
                         ReportEntry::make('ar_aging')
83
                             ->hiddenLabel()
84
                             ->hiddenLabel()
84
                             ->heading('Accounts Receivable Aging')
85
                             ->heading('Accounts Receivable Aging')
85
-                            ->description('Lists outstanding receivables by customer, showing how long invoices have been unpaid.')
86
+                            ->description('Lists outstanding receivables by client, showing how long invoices have been unpaid.')
86
                             ->icon('heroicon-o-calendar-date-range')
87
                             ->icon('heroicon-o-calendar-date-range')
87
                             ->iconColor(Color::Indigo)
88
                             ->iconColor(Color::Indigo)
88
                             ->url(AccountsReceivableAging::getUrl()),
89
                             ->url(AccountsReceivableAging::getUrl()),
89
-                        ReportEntry::make('income_by_customer')
90
+                        ReportEntry::make('client_balance_summary')
90
                             ->hiddenLabel()
91
                             ->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')
92
+                            ->heading('Client Balance Summary')
93
+                            ->description('Shows total invoiced amounts, payments received, and outstanding balances for each client, helping identify top clients and opportunities for growth.')
94
+                            ->icon('heroicon-o-receipt-percent')
94
                             ->iconColor(Color::Emerald)
95
                             ->iconColor(Color::Emerald)
95
-                            ->url('#'),
96
+                            ->url(ClientBalanceSummary::getUrl()),
96
                     ]),
97
                     ]),
97
                 Section::make('Vendor Reports')
98
                 Section::make('Vendor Reports')
98
                     ->aside()
99
                     ->aside()

+ 98
- 0
app/Filament/Company/Pages/Reports/ClientBalanceSummary.php 查看文件

1
+<?php
2
+
3
+namespace App\Filament\Company\Pages\Reports;
4
+
5
+use App\Contracts\ExportableReport;
6
+use App\DTO\ReportDTO;
7
+use App\Services\ExportService;
8
+use App\Services\ReportService;
9
+use App\Support\Column;
10
+use App\Transformers\ClientBalanceSummaryReportTransformer;
11
+use Filament\Forms\Form;
12
+use Filament\Support\Enums\Alignment;
13
+use Guava\FilamentClusters\Forms\Cluster;
14
+use Symfony\Component\HttpFoundation\StreamedResponse;
15
+
16
+class ClientBalanceSummary extends BaseReportPage
17
+{
18
+    protected static string $view = 'filament.company.pages.reports.detailed-report';
19
+
20
+    protected ReportService $reportService;
21
+
22
+    protected ExportService $exportService;
23
+
24
+    public function boot(ReportService $reportService, ExportService $exportService): void
25
+    {
26
+        $this->reportService = $reportService;
27
+        $this->exportService = $exportService;
28
+    }
29
+
30
+    public function getTable(): array
31
+    {
32
+        return [
33
+            Column::make('client_name')
34
+                ->label('Client')
35
+                ->alignment(Alignment::Left),
36
+            Column::make('total_balance')
37
+                ->label('Total')
38
+                ->toggleable()
39
+                ->alignment(Alignment::Right),
40
+            Column::make('paid_balance')
41
+                ->label('Paid')
42
+                ->toggleable()
43
+                ->alignment(Alignment::Right),
44
+            Column::make('unpaid_balance')
45
+                ->label('Unpaid')
46
+                ->toggleable()
47
+                ->alignment(Alignment::Right),
48
+        ];
49
+    }
50
+
51
+    public function filtersForm(Form $form): Form
52
+    {
53
+        return $form
54
+            ->inlineLabel()
55
+            ->columns()
56
+            ->schema([
57
+                $this->getDateRangeFormComponent(),
58
+                Cluster::make([
59
+                    $this->getStartDateFormComponent(),
60
+                    $this->getEndDateFormComponent(),
61
+                ])->hiddenLabel(),
62
+            ]);
63
+    }
64
+
65
+    protected function buildReport(array $columns): ReportDTO
66
+    {
67
+        return $this->reportService->buildClientBalanceSummaryReport(
68
+            $this->getFormattedStartDate(),
69
+            $this->getFormattedEndDate(),
70
+            $columns
71
+        );
72
+    }
73
+
74
+    protected function getTransformer(ReportDTO $reportDTO): ExportableReport
75
+    {
76
+        return new ClientBalanceSummaryReportTransformer($reportDTO);
77
+    }
78
+
79
+    public function exportCSV(): StreamedResponse
80
+    {
81
+        return $this->exportService->exportToCsv(
82
+            $this->company,
83
+            $this->report,
84
+            $this->getFilterState('startDate'),
85
+            $this->getFilterState('endDate')
86
+        );
87
+    }
88
+
89
+    public function exportPDF(): StreamedResponse
90
+    {
91
+        return $this->exportService->exportToPdf(
92
+            $this->company,
93
+            $this->report,
94
+            $this->getFilterState('startDate'),
95
+            $this->getFilterState('endDate')
96
+        );
97
+    }
98
+}

+ 5
- 0
app/Providers/MacroServiceProvider.php 查看文件

22
 use Filament\Tables\Contracts\HasTable;
22
 use Filament\Tables\Contracts\HasTable;
23
 use Illuminate\Contracts\Support\Htmlable;
23
 use Illuminate\Contracts\Support\Htmlable;
24
 use Illuminate\Support\Carbon;
24
 use Illuminate\Support\Carbon;
25
+use Illuminate\Support\Collection;
25
 use Illuminate\Support\HtmlString;
26
 use Illuminate\Support\HtmlString;
26
 use Illuminate\Support\ServiceProvider;
27
 use Illuminate\Support\ServiceProvider;
27
 
28
 
40
      */
41
      */
41
     public function boot(): void
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
         TextInput::macro('money', function (string | Closure | null $currency = null, bool $useAffix = true): static {
48
         TextInput::macro('money', function (string | Closure | null $currency = null, bool $useAffix = true): static {
44
             $currency ??= CurrencyAccessor::getDefaultCurrency();
49
             $currency ??= CurrencyAccessor::getDefaultCurrency();
45
 
50
 

+ 2
- 0
app/Services/AccountService.php 查看文件

381
                 'invoices.client_id',
381
                 'invoices.client_id',
382
                 'invoices.due_date',
382
                 'invoices.due_date',
383
                 'invoices.amount_due',
383
                 'invoices.amount_due',
384
+                'invoices.currency_code',
384
                 DB::raw('DATEDIFF(?, invoices.due_date) as days_overdue'),
385
                 DB::raw('DATEDIFF(?, invoices.due_date) as days_overdue'),
385
             ])
386
             ])
386
             ->addBinding([$asOfDate], 'select')
387
             ->addBinding([$asOfDate], 'select')
398
                 'bills.vendor_id',
399
                 'bills.vendor_id',
399
                 'bills.due_date',
400
                 'bills.due_date',
400
                 'bills.amount_due',
401
                 'bills.amount_due',
402
+                'bills.currency_code',
401
                 DB::raw('DATEDIFF(?, bills.due_date) as days_overdue'),
403
                 DB::raw('DATEDIFF(?, bills.due_date) as days_overdue'),
402
             ])
404
             ])
403
             ->addBinding([$asOfDate], 'select')
405
             ->addBinding([$asOfDate], 'select')

+ 92
- 24
app/Services/ReportService.php 查看文件

2
 
2
 
3
 namespace App\Services;
3
 namespace App\Services;
4
 
4
 
5
+use App\Collections\Accounting\DocumentCollection;
5
 use App\Contracts\MoneyFormattableDTO;
6
 use App\Contracts\MoneyFormattableDTO;
6
 use App\DTO\AccountBalanceDTO;
7
 use App\DTO\AccountBalanceDTO;
7
 use App\DTO\AccountCategoryDTO;
8
 use App\DTO\AccountCategoryDTO;
10
 use App\DTO\AccountTypeDTO;
11
 use App\DTO\AccountTypeDTO;
11
 use App\DTO\AgingBucketDTO;
12
 use App\DTO\AgingBucketDTO;
12
 use App\DTO\CashFlowOverviewDTO;
13
 use App\DTO\CashFlowOverviewDTO;
14
+use App\DTO\ClientBalanceDTO;
15
+use App\DTO\ClientReportDTO;
13
 use App\DTO\EntityReportDTO;
16
 use App\DTO\EntityReportDTO;
14
 use App\DTO\ReportDTO;
17
 use App\DTO\ReportDTO;
15
 use App\Enums\Accounting\AccountCategory;
18
 use App\Enums\Accounting\AccountCategory;
16
 use App\Enums\Accounting\AccountType;
19
 use App\Enums\Accounting\AccountType;
17
 use App\Enums\Accounting\DocumentEntityType;
20
 use App\Enums\Accounting\DocumentEntityType;
21
+use App\Enums\Accounting\InvoiceStatus;
18
 use App\Enums\Accounting\TransactionType;
22
 use App\Enums\Accounting\TransactionType;
19
 use App\Models\Accounting\Account;
23
 use App\Models\Accounting\Account;
24
+use App\Models\Accounting\Bill;
25
+use App\Models\Accounting\Invoice;
20
 use App\Models\Accounting\Transaction;
26
 use App\Models\Accounting\Transaction;
21
 use App\Support\Column;
27
 use App\Support\Column;
22
 use App\Utilities\Currency\CurrencyAccessor;
28
 use App\Utilities\Currency\CurrencyAccessor;
838
     ): ReportDTO {
844
     ): ReportDTO {
839
         $asOfDateCarbon = Carbon::parse($asOfDate);
845
         $asOfDateCarbon = Carbon::parse($asOfDate);
840
 
846
 
847
+        /** @var DocumentCollection<int,DocumentCollection<int,Invoice|Bill>> $documents */
841
         $documents = $entityType === DocumentEntityType::Client
848
         $documents = $entityType === DocumentEntityType::Client
842
             ? $this->accountService->getUnpaidClientInvoices($asOfDate)->with(['client:id,name'])->get()->groupBy('client_id')
849
             ? $this->accountService->getUnpaidClientInvoices($asOfDate)->with(['client:id,name'])->get()->groupBy('client_id')
843
             : $this->accountService->getUnpaidVendorBills($asOfDate)->with(['vendor:id,name'])->get()->groupBy('vendor_id');
850
             : $this->accountService->getUnpaidVendorBills($asOfDate)->with(['vendor:id,name'])->get()->groupBy('vendor_id');
844
 
851
 
845
         $categories = [];
852
         $categories = [];
846
-
847
-        $agingBuckets = ['current' => 0];
848
-
853
+        $totalAging = [
854
+            'current' => 0,
855
+        ];
849
         for ($i = 1; $i <= $numberOfPeriods; $i++) {
856
         for ($i = 1; $i <= $numberOfPeriods; $i++) {
850
-            $agingBuckets["period_{$i}"] = 0;
857
+            $totalAging["period_{$i}"] = 0;
851
         }
858
         }
852
-
853
-        $agingBuckets['over_periods'] = 0;
854
-        $agingBuckets['total'] = 0;
855
-
856
-        $totalAging = $agingBuckets;
859
+        $totalAging['over_periods'] = 0;
860
+        $totalAging['total'] = 0;
857
 
861
 
858
         foreach ($documents as $entityId => $entityDocuments) {
862
         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');
863
+            $aging = [
864
+                'current' => $entityDocuments
865
+                    ->filter(static fn ($doc) => ($doc->days_overdue ?? 0) <= 0)
866
+                    ->sumMoneyInDefaultCurrency('amount_due'),
867
+            ];
864
 
868
 
865
-                if ($daysOverdue <= 0) {
866
-                    $aging['current'] += $balance;
867
-                } else {
868
-                    $period = ceil($daysOverdue / $daysPerPeriod);
869
+            for ($i = 1; $i <= $numberOfPeriods; $i++) {
870
+                $min = ($i - 1) * $daysPerPeriod;
871
+                $max = $i * $daysPerPeriod;
872
+                $aging["period_{$i}"] = $entityDocuments
873
+                    ->filter(static function ($doc) use ($min, $max) {
874
+                        $days = $doc->days_overdue ?? 0;
869
 
875
 
870
-                    if ($period <= $numberOfPeriods) {
871
-                        $aging["period_{$period}"] += $balance;
872
-                    } else {
873
-                        $aging['over_periods'] += $balance;
874
-                    }
875
-                }
876
+                        return $days > $min && $days <= $max;
877
+                    })
878
+                    ->sumMoneyInDefaultCurrency('amount_due');
876
             }
879
             }
877
 
880
 
881
+            $aging['over_periods'] = $entityDocuments
882
+                ->filter(static fn ($doc) => ($doc->days_overdue ?? 0) > ($numberOfPeriods * $daysPerPeriod))
883
+                ->sumMoneyInDefaultCurrency('amount_due');
884
+
878
             $aging['total'] = array_sum($aging);
885
             $aging['total'] = array_sum($aging);
879
 
886
 
880
             foreach ($aging as $bucket => $amount) {
887
             foreach ($aging as $bucket => $amount) {
899
             endDate: $asOfDateCarbon,
906
             endDate: $asOfDateCarbon,
900
         );
907
         );
901
     }
908
     }
909
+
910
+    public function buildClientBalanceSummaryReport(string $startDate, string $endDate, array $columns = []): ReportDTO
911
+    {
912
+        /** @var DocumentCollection<int,DocumentCollection<int,Invoice>> $invoices */
913
+        $invoices = Invoice::query()
914
+            ->whereBetween('date', [$startDate, $endDate])
915
+            ->whereNotIn('status', [
916
+                InvoiceStatus::Draft,
917
+                InvoiceStatus::Void,
918
+            ])
919
+            ->whereNotNull('approved_at')
920
+            ->with(['client:id,name'])
921
+            ->get()
922
+            ->groupBy('client_id');
923
+
924
+        $clients = [];
925
+        $totalBalance = 0;
926
+        $totalPaidBalance = 0;
927
+        $totalUnpaidBalance = 0;
928
+
929
+        foreach ($invoices as $clientInvoices) {
930
+            $clientTotalBalance = $clientInvoices->sumMoneyInDefaultCurrency('total');
931
+
932
+            $clientPaidBalance = $clientInvoices->sumMoneyInDefaultCurrency('amount_paid');
933
+
934
+            $clientUnpaidBalance = $clientInvoices->whereNot('status', InvoiceStatus::Overpaid)
935
+                ->sumMoneyInDefaultCurrency('amount_due');
936
+
937
+            $totalBalance += $clientTotalBalance;
938
+            $totalPaidBalance += $clientPaidBalance;
939
+            $totalUnpaidBalance += $clientUnpaidBalance;
940
+
941
+            $formattedBalances = $this->formatBalances([
942
+                'total_balance' => $clientTotalBalance,
943
+                'paid_balance' => $clientPaidBalance,
944
+                'unpaid_balance' => $clientUnpaidBalance,
945
+            ], ClientBalanceDTO::class);
946
+
947
+            $client = $clientInvoices->first()->client;
948
+
949
+            $clients[] = new ClientReportDTO(
950
+                clientName: $client->name,
951
+                clientId: $client->id,
952
+                balance: $formattedBalances,
953
+            );
954
+        }
955
+
956
+        $clientBalanceTotal = $this->formatBalances([
957
+            'total_balance' => $totalBalance,
958
+            'paid_balance' => $totalPaidBalance,
959
+            'unpaid_balance' => $totalUnpaidBalance,
960
+        ], ClientBalanceDTO::class);
961
+
962
+        return new ReportDTO(
963
+            categories: ['Clients' => $clients],
964
+            clientBalanceTotal: $clientBalanceTotal,
965
+            fields: $columns,
966
+            startDate: Carbon::parse($startDate),
967
+            endDate: Carbon::parse($endDate),
968
+        );
969
+    }
902
 }
970
 }

+ 68
- 0
app/Transformers/ClientBalanceSummaryReportTransformer.php 查看文件

1
+<?php
2
+
3
+namespace App\Transformers;
4
+
5
+use App\DTO\ClientReportDTO;
6
+use App\DTO\ReportCategoryDTO;
7
+
8
+class ClientBalanceSummaryReportTransformer extends BaseReportTransformer
9
+{
10
+    public function getTitle(): string
11
+    {
12
+        return 'Client Balance Summary';
13
+    }
14
+
15
+    /**
16
+     * @return ReportCategoryDTO[]
17
+     */
18
+    public function getCategories(): array
19
+    {
20
+        $categories = [];
21
+
22
+        foreach ($this->report->categories as $categoryName => $category) {
23
+            $data = array_map(function (ClientReportDTO $client) {
24
+                $row = [];
25
+
26
+                foreach ($this->getColumns() as $column) {
27
+                    $row[$column->getName()] = match ($column->getName()) {
28
+                        'client_name' => [
29
+                            'name' => $client->clientName,
30
+                            'id' => $client->clientId,
31
+                        ],
32
+                        'total_balance' => $client->balance->totalBalance,
33
+                        'paid_balance' => $client->balance->paidBalance,
34
+                        'unpaid_balance' => $client->balance->unpaidBalance,
35
+                        default => '',
36
+                    };
37
+                }
38
+
39
+                return $row;
40
+            }, $category);
41
+
42
+            $categories[] = new ReportCategoryDTO(
43
+                header: null,
44
+                data: $data,
45
+                summary: null,
46
+            );
47
+        }
48
+
49
+        return $categories;
50
+    }
51
+
52
+    public function getOverallTotals(): array
53
+    {
54
+        $totals = [];
55
+
56
+        foreach ($this->getColumns() as $column) {
57
+            $totals[$column->getName()] = match ($column->getName()) {
58
+                'client_name' => 'Total for all clients',
59
+                'total_balance' => $this->report->clientBalanceTotal->totalBalance,
60
+                'paid_balance' => $this->report->clientBalanceTotal->paidBalance,
61
+                'unpaid_balance' => $this->report->clientBalanceTotal->unpaidBalance,
62
+                default => '',
63
+            };
64
+        }
65
+
66
+        return $totals;
67
+    }
68
+}

+ 58
- 58
composer.lock 查看文件

497
         },
497
         },
498
         {
498
         {
499
             "name": "aws/aws-sdk-php",
499
             "name": "aws/aws-sdk-php",
500
-            "version": "3.339.2",
500
+            "version": "3.339.4",
501
             "source": {
501
             "source": {
502
                 "type": "git",
502
                 "type": "git",
503
                 "url": "https://github.com/aws/aws-sdk-php.git",
503
                 "url": "https://github.com/aws/aws-sdk-php.git",
504
-                "reference": "2f4e85dd8466ffe5186887f8f1466a0248c6c094"
504
+                "reference": "ea62ad03645ef7a1d3f1cda2de49f0869de3c582"
505
             },
505
             },
506
             "dist": {
506
             "dist": {
507
                 "type": "zip",
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
                 "shasum": ""
510
                 "shasum": ""
511
             },
511
             },
512
             "require": {
512
             "require": {
589
             "support": {
589
             "support": {
590
                 "forum": "https://github.com/aws/aws-sdk-php/discussions",
590
                 "forum": "https://github.com/aws/aws-sdk-php/discussions",
591
                 "issues": "https://github.com/aws/aws-sdk-php/issues",
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
             "name": "aws/aws-sdk-php-laravel",
597
             "name": "aws/aws-sdk-php-laravel",
1733
         },
1733
         },
1734
         {
1734
         {
1735
             "name": "filament/actions",
1735
             "name": "filament/actions",
1736
-            "version": "v3.2.135",
1736
+            "version": "v3.2.136",
1737
             "source": {
1737
             "source": {
1738
                 "type": "git",
1738
                 "type": "git",
1739
                 "url": "https://github.com/filamentphp/actions.git",
1739
                 "url": "https://github.com/filamentphp/actions.git",
1740
-                "reference": "dee2ca6d11e0ea3efb1190eabf6e483dbe2320ff"
1740
+                "reference": "cdefacc18993050cdd37e8e980ec66ca4109ae9a"
1741
             },
1741
             },
1742
             "dist": {
1742
             "dist": {
1743
                 "type": "zip",
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
                 "shasum": ""
1746
                 "shasum": ""
1747
             },
1747
             },
1748
             "require": {
1748
             "require": {
1782
                 "issues": "https://github.com/filamentphp/filament/issues",
1782
                 "issues": "https://github.com/filamentphp/filament/issues",
1783
                 "source": "https://github.com/filamentphp/filament"
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
             "name": "filament/filament",
1788
             "name": "filament/filament",
1789
-            "version": "v3.2.135",
1789
+            "version": "v3.2.136",
1790
             "source": {
1790
             "source": {
1791
                 "type": "git",
1791
                 "type": "git",
1792
                 "url": "https://github.com/filamentphp/panels.git",
1792
                 "url": "https://github.com/filamentphp/panels.git",
1793
-                "reference": "bee6e1fd7b51f7dbffd03bc277b220bcfb8c45bb"
1793
+                "reference": "c92daf4b6e4b478be5d32d5e1b404ba92bb45414"
1794
             },
1794
             },
1795
             "dist": {
1795
             "dist": {
1796
                 "type": "zip",
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
                 "shasum": ""
1799
                 "shasum": ""
1800
             },
1800
             },
1801
             "require": {
1801
             "require": {
1847
                 "issues": "https://github.com/filamentphp/filament/issues",
1847
                 "issues": "https://github.com/filamentphp/filament/issues",
1848
                 "source": "https://github.com/filamentphp/filament"
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
             "name": "filament/forms",
1853
             "name": "filament/forms",
1854
-            "version": "v3.2.135",
1854
+            "version": "v3.2.136",
1855
             "source": {
1855
             "source": {
1856
                 "type": "git",
1856
                 "type": "git",
1857
                 "url": "https://github.com/filamentphp/forms.git",
1857
                 "url": "https://github.com/filamentphp/forms.git",
1858
-                "reference": "e17618c921cd0300341a53d0eb2174c51e649565"
1858
+                "reference": "8856b3b3714a0efae65d9f817fcc1934b6f34fda"
1859
             },
1859
             },
1860
             "dist": {
1860
             "dist": {
1861
                 "type": "zip",
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
                 "shasum": ""
1864
                 "shasum": ""
1865
             },
1865
             },
1866
             "require": {
1866
             "require": {
1903
                 "issues": "https://github.com/filamentphp/filament/issues",
1903
                 "issues": "https://github.com/filamentphp/filament/issues",
1904
                 "source": "https://github.com/filamentphp/filament"
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
             "name": "filament/infolists",
1909
             "name": "filament/infolists",
1910
-            "version": "v3.2.135",
1910
+            "version": "v3.2.136",
1911
             "source": {
1911
             "source": {
1912
                 "type": "git",
1912
                 "type": "git",
1913
                 "url": "https://github.com/filamentphp/infolists.git",
1913
                 "url": "https://github.com/filamentphp/infolists.git",
1914
-                "reference": "3330966b87da7d2078b62556428c279a6e8ff17c"
1914
+                "reference": "35c6dcbae24ae5fb086aeb1d13e2996442001674"
1915
             },
1915
             },
1916
             "dist": {
1916
             "dist": {
1917
                 "type": "zip",
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
                 "shasum": ""
1920
                 "shasum": ""
1921
             },
1921
             },
1922
             "require": {
1922
             "require": {
1954
                 "issues": "https://github.com/filamentphp/filament/issues",
1954
                 "issues": "https://github.com/filamentphp/filament/issues",
1955
                 "source": "https://github.com/filamentphp/filament"
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
             "name": "filament/notifications",
1960
             "name": "filament/notifications",
1961
-            "version": "v3.2.135",
1961
+            "version": "v3.2.136",
1962
             "source": {
1962
             "source": {
1963
                 "type": "git",
1963
                 "type": "git",
1964
                 "url": "https://github.com/filamentphp/notifications.git",
1964
                 "url": "https://github.com/filamentphp/notifications.git",
1965
-                "reference": "e864c50bc0b6e9eb46b5e3d93a672a66f80a0fbe"
1965
+                "reference": "214845e9f613716304707441c8227d2d70b2aabf"
1966
             },
1966
             },
1967
             "dist": {
1967
             "dist": {
1968
                 "type": "zip",
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
                 "shasum": ""
1971
                 "shasum": ""
1972
             },
1972
             },
1973
             "require": {
1973
             "require": {
2006
                 "issues": "https://github.com/filamentphp/filament/issues",
2006
                 "issues": "https://github.com/filamentphp/filament/issues",
2007
                 "source": "https://github.com/filamentphp/filament"
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
             "name": "filament/support",
2012
             "name": "filament/support",
2013
-            "version": "v3.2.135",
2013
+            "version": "v3.2.136",
2014
             "source": {
2014
             "source": {
2015
                 "type": "git",
2015
                 "type": "git",
2016
                 "url": "https://github.com/filamentphp/support.git",
2016
                 "url": "https://github.com/filamentphp/support.git",
2069
         },
2069
         },
2070
         {
2070
         {
2071
             "name": "filament/tables",
2071
             "name": "filament/tables",
2072
-            "version": "v3.2.135",
2072
+            "version": "v3.2.136",
2073
             "source": {
2073
             "source": {
2074
                 "type": "git",
2074
                 "type": "git",
2075
                 "url": "https://github.com/filamentphp/tables.git",
2075
                 "url": "https://github.com/filamentphp/tables.git",
2076
-                "reference": "db63ab6fd7c2046dc9b1fc6fbd92df0a1aabb54e"
2076
+                "reference": "1b1d9c3b837c11408ad28240dc9e3e33340d870b"
2077
             },
2077
             },
2078
             "dist": {
2078
             "dist": {
2079
                 "type": "zip",
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
                 "shasum": ""
2082
                 "shasum": ""
2083
             },
2083
             },
2084
             "require": {
2084
             "require": {
2117
                 "issues": "https://github.com/filamentphp/filament/issues",
2117
                 "issues": "https://github.com/filamentphp/filament/issues",
2118
                 "source": "https://github.com/filamentphp/filament"
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
             "name": "filament/widgets",
2123
             "name": "filament/widgets",
2124
-            "version": "v3.2.135",
2124
+            "version": "v3.2.136",
2125
             "source": {
2125
             "source": {
2126
                 "type": "git",
2126
                 "type": "git",
2127
                 "url": "https://github.com/filamentphp/widgets.git",
2127
                 "url": "https://github.com/filamentphp/widgets.git",
2128
-                "reference": "9f6674daceced7d5045494d0bf7e1d2908ea439d"
2128
+                "reference": "3b95cfc23cf7a2b112ca65b067a33c1af7f79dc7"
2129
             },
2129
             },
2130
             "dist": {
2130
             "dist": {
2131
                 "type": "zip",
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
                 "shasum": ""
2134
                 "shasum": ""
2135
             },
2135
             },
2136
             "require": {
2136
             "require": {
2161
                 "issues": "https://github.com/filamentphp/filament/issues",
2161
                 "issues": "https://github.com/filamentphp/filament/issues",
2162
                 "source": "https://github.com/filamentphp/filament"
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
             "name": "firebase/php-jwt",
2167
             "name": "firebase/php-jwt",
3051
         },
3051
         },
3052
         {
3052
         {
3053
             "name": "laravel/framework",
3053
             "name": "laravel/framework",
3054
-            "version": "v11.41.0",
3054
+            "version": "v11.41.3",
3055
             "source": {
3055
             "source": {
3056
                 "type": "git",
3056
                 "type": "git",
3057
                 "url": "https://github.com/laravel/framework.git",
3057
                 "url": "https://github.com/laravel/framework.git",
3058
-                "reference": "42d6ae000c868c2abfa946da46702f2358493482"
3058
+                "reference": "3ef433d5865f30a19b6b1be247586068399b59cc"
3059
             },
3059
             },
3060
             "dist": {
3060
             "dist": {
3061
                 "type": "zip",
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
                 "shasum": ""
3064
                 "shasum": ""
3065
             },
3065
             },
3066
             "require": {
3066
             "require": {
3262
                 "issues": "https://github.com/laravel/framework/issues",
3262
                 "issues": "https://github.com/laravel/framework/issues",
3263
                 "source": "https://github.com/laravel/framework"
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
             "name": "laravel/prompts",
3268
             "name": "laravel/prompts",
5136
         },
5136
         },
5137
         {
5137
         {
5138
             "name": "openspout/openspout",
5138
             "name": "openspout/openspout",
5139
-            "version": "v4.28.4",
5139
+            "version": "v4.28.5",
5140
             "source": {
5140
             "source": {
5141
                 "type": "git",
5141
                 "type": "git",
5142
                 "url": "https://github.com/openspout/openspout.git",
5142
                 "url": "https://github.com/openspout/openspout.git",
5143
-                "reference": "68d58235c7c1164b3d231b798975b9b0b2b79b15"
5143
+                "reference": "ab05a09fe6fce57c90338f83280648a9786ce36b"
5144
             },
5144
             },
5145
             "dist": {
5145
             "dist": {
5146
                 "type": "zip",
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
                 "shasum": ""
5149
                 "shasum": ""
5150
             },
5150
             },
5151
             "require": {
5151
             "require": {
5159
             },
5159
             },
5160
             "require-dev": {
5160
             "require-dev": {
5161
                 "ext-zlib": "*",
5161
                 "ext-zlib": "*",
5162
-                "friendsofphp/php-cs-fixer": "^3.66.1",
5162
+                "friendsofphp/php-cs-fixer": "^3.68.3",
5163
                 "infection/infection": "^0.29.10",
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
                 "phpstan/phpstan-strict-rules": "^2",
5167
                 "phpstan/phpstan-strict-rules": "^2",
5168
-                "phpunit/phpunit": "^11.5.2"
5168
+                "phpunit/phpunit": "^11.5.4"
5169
             },
5169
             },
5170
             "suggest": {
5170
             "suggest": {
5171
                 "ext-iconv": "To handle non UTF-8 CSV files (if \"php-mbstring\" is not already installed or is too limited)",
5171
                 "ext-iconv": "To handle non UTF-8 CSV files (if \"php-mbstring\" is not already installed or is too limited)",
5213
             ],
5213
             ],
5214
             "support": {
5214
             "support": {
5215
                 "issues": "https://github.com/openspout/openspout/issues",
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
             "funding": [
5218
             "funding": [
5219
                 {
5219
                 {
5225
                     "type": "github"
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
             "name": "paragonie/constant_time_encoding",
5231
             "name": "paragonie/constant_time_encoding",

+ 6
- 6
package-lock.json 查看文件

1235
             "license": "MIT"
1235
             "license": "MIT"
1236
         },
1236
         },
1237
         "node_modules/electron-to-chromium": {
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
             "dev": true,
1241
             "dev": true,
1242
             "license": "ISC"
1242
             "license": "ISC"
1243
         },
1243
         },
1330
             }
1330
             }
1331
         },
1331
         },
1332
         "node_modules/fastq": {
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
             "dev": true,
1336
             "dev": true,
1337
             "license": "ISC",
1337
             "license": "ISC",
1338
             "dependencies": {
1338
             "dependencies": {

+ 4
- 0
resources/css/filament/company/theme.css 查看文件

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

+ 3
- 0
resources/views/filament/company/pages/reports/income-by-customer.blade.php 查看文件

1
+<x-filament-panels::page>
2
+
3
+</x-filament-panels::page>

Loading…
取消
儲存