Andrew Wallo 11 个月前
父节点
当前提交
add50b01d5

+ 6
- 0
app/Contracts/ExportableReport.php 查看文件

3
 namespace App\Contracts;
3
 namespace App\Contracts;
4
 
4
 
5
 use App\DTO\ReportCategoryDTO;
5
 use App\DTO\ReportCategoryDTO;
6
+use App\Support\Column;
6
 
7
 
7
 interface ExportableReport
8
 interface ExportableReport
8
 {
9
 {
17
 
18
 
18
     public function getOverallTotals(): array;
19
     public function getOverallTotals(): array;
19
 
20
 
21
+    /**
22
+     * @return Column[]
23
+     */
20
     public function getColumns(): array;
24
     public function getColumns(): array;
21
 
25
 
22
     public function getPdfView(): string;
26
     public function getPdfView(): string;
27
+
28
+    public function getAlignmentClass(string $columnName): string;
23
 }
29
 }

+ 23
- 0
app/Contracts/HasSummaryReport.php 查看文件

1
+<?php
2
+
3
+namespace App\Contracts;
4
+
5
+use App\DTO\ReportCategoryDTO;
6
+use App\Support\Column;
7
+
8
+interface HasSummaryReport
9
+{
10
+    /**
11
+     * @return Column[]
12
+     */
13
+    public function getSummaryColumns(): array;
14
+
15
+    public function getSummaryHeaders(): array;
16
+
17
+    /**
18
+     * @return ReportCategoryDTO[]
19
+     */
20
+    public function getSummaryCategories(): array;
21
+
22
+    public function getSummaryOverallTotals(): array;
23
+}

+ 59
- 43
app/Services/ExportService.php 查看文件

4
 
4
 
5
 use App\Contracts\ExportableReport;
5
 use App\Contracts\ExportableReport;
6
 use App\Models\Company;
6
 use App\Models\Company;
7
-use App\Support\Column;
8
 use Barryvdh\Snappy\Facades\SnappyPdf;
7
 use Barryvdh\Snappy\Facades\SnappyPdf;
9
 use Carbon\Exceptions\InvalidFormatException;
8
 use Carbon\Exceptions\InvalidFormatException;
10
 use Illuminate\Support\Carbon;
9
 use Illuminate\Support\Carbon;
10
+use League\Csv\Bom;
11
+use League\Csv\CannotInsertRecord;
12
+use League\Csv\Exception;
13
+use League\Csv\Writer;
11
 use Symfony\Component\HttpFoundation\StreamedResponse;
14
 use Symfony\Component\HttpFoundation\StreamedResponse;
12
 
15
 
13
 class ExportService
16
 class ExportService
33
         ];
36
         ];
34
 
37
 
35
         $callback = function () use ($startDate, $endDate, $report, $company) {
38
         $callback = function () use ($startDate, $endDate, $report, $company) {
36
-            $file = fopen('php://output', 'wb');
39
+            $csv = Writer::createFromStream(fopen('php://output', 'wb'));
40
+            $csv->setOutputBOM(Bom::Utf8);
37
 
41
 
38
             if ($startDate && $endDate) {
42
             if ($startDate && $endDate) {
39
                 $defaultStartDateFormat = Carbon::parse($startDate)->toDefaultDateFormat();
43
                 $defaultStartDateFormat = Carbon::parse($startDate)->toDefaultDateFormat();
43
                 $dateLabel = 'As of ' . Carbon::parse($endDate)->toDefaultDateFormat();
47
                 $dateLabel = 'As of ' . Carbon::parse($endDate)->toDefaultDateFormat();
44
             }
48
             }
45
 
49
 
46
-            fputcsv($file, [$report->getTitle()]);
47
-            fputcsv($file, [$company->name]);
48
-            fputcsv($file, [$dateLabel]);
49
-            fputcsv($file, []);
50
+            $csv->insertOne([$report->getTitle()]);
51
+            $csv->insertOne([$company->name]);
52
+            $csv->insertOne([$dateLabel]);
53
+            $csv->insertOne([]);
50
 
54
 
51
-            fputcsv($file, $report->getHeaders());
55
+            $csv->insertOne($report->getHeaders());
52
 
56
 
53
             foreach ($report->getCategories() as $category) {
57
             foreach ($report->getCategories() as $category) {
54
-                if (isset($category->header[0]) && is_array($category->header[0])) {
55
-                    foreach ($category->header as $headerRow) {
56
-                        fputcsv($file, $headerRow);
57
-                    }
58
-                } else {
59
-                    fputcsv($file, $category->header);
60
-                }
58
+                $this->writeDataRowsToCsv($csv, $category->header, $category->data, $report->getColumns());
61
 
59
 
62
-                foreach ($category->data as $accountRow) {
63
-                    $row = [];
64
-                    $columns = $report->getColumns();
65
-
66
-                    /**
67
-                     * @var Column $column
68
-                     */
69
-                    foreach ($columns as $index => $column) {
70
-                        $cell = $accountRow[$index] ?? '';
71
-
72
-                        if ($column->isDate()) {
73
-                            try {
74
-                                $row[] = Carbon::parse($cell)->toDateString();
75
-                            } catch (InvalidFormatException) {
76
-                                $row[] = $cell;
77
-                            }
78
-                        } elseif (is_array($cell)) {
79
-                            // Handle array cells by extracting 'name' or 'description'
80
-                            $row[] = $cell['name'] ?? $cell['description'] ?? '';
81
-                        } else {
82
-                            $row[] = $cell;
83
-                        }
84
-                    }
60
+                foreach ($category->types ?? [] as $type) {
61
+                    $this->writeDataRowsToCsv($csv, $type->header, $type->data, $report->getColumns());
85
 
62
 
86
-                    fputcsv($file, $row);
63
+                    if (filled($type->summary)) {
64
+                        $csv->insertOne($type->summary);
65
+                    }
87
                 }
66
                 }
88
 
67
 
89
                 if (filled($category->summary)) {
68
                 if (filled($category->summary)) {
90
-                    fputcsv($file, $category->summary);
69
+                    $csv->insertOne($category->summary);
91
                 }
70
                 }
92
 
71
 
93
-                fputcsv($file, []); // Empty row for spacing
72
+                $csv->insertOne([]);
94
             }
73
             }
95
 
74
 
96
             if (filled($report->getOverallTotals())) {
75
             if (filled($report->getOverallTotals())) {
97
-                fputcsv($file, $report->getOverallTotals());
76
+                $csv->insertOne($report->getOverallTotals());
98
             }
77
             }
99
-
100
-            fclose($file);
101
         };
78
         };
102
 
79
 
103
         return response()->streamDownload($callback, $filename, $headers);
80
         return response()->streamDownload($callback, $filename, $headers);
129
             echo $pdf->inline();
106
             echo $pdf->inline();
130
         }, $filename);
107
         }, $filename);
131
     }
108
     }
109
+
110
+    /**
111
+     * @throws CannotInsertRecord
112
+     * @throws Exception
113
+     */
114
+    protected function writeDataRowsToCsv(Writer $csv, array $header, array $data, array $columns): void
115
+    {
116
+        if (isset($header[0]) && is_array($header[0])) {
117
+            foreach ($header as $headerRow) {
118
+                $csv->insertOne($headerRow);
119
+            }
120
+        } else {
121
+            $csv->insertOne($header);
122
+        }
123
+
124
+        // Output data rows
125
+        foreach ($data as $rowData) {
126
+            $row = [];
127
+
128
+            foreach ($columns as $column) {
129
+                $columnName = $column->getName();
130
+                $cell = $rowData[$columnName] ?? '';
131
+
132
+                if ($column->isDate()) {
133
+                    try {
134
+                        $row[] = Carbon::parse($cell)->toDateString();
135
+                    } catch (InvalidFormatException) {
136
+                        $row[] = $cell;
137
+                    }
138
+                } elseif (is_array($cell)) {
139
+                    $row[] = $cell['name'] ?? $cell['description'] ?? '';
140
+                } else {
141
+                    $row[] = $cell;
142
+                }
143
+            }
144
+
145
+            $csv->insertOne($row);
146
+        }
147
+    }
132
 }
148
 }

+ 5
- 16
app/Transformers/AccountBalanceReportTransformer.php 查看文件

4
 
4
 
5
 use App\DTO\AccountDTO;
5
 use App\DTO\AccountDTO;
6
 use App\DTO\ReportCategoryDTO;
6
 use App\DTO\ReportCategoryDTO;
7
-use App\Support\Column;
8
 
7
 
9
 class AccountBalanceReportTransformer extends BaseReportTransformer
8
 class AccountBalanceReportTransformer extends BaseReportTransformer
10
 {
9
 {
13
         return 'Account Balances';
12
         return 'Account Balances';
14
     }
13
     }
15
 
14
 
16
-    public function getHeaders(): array
17
-    {
18
-        return array_map(fn (Column $column) => $column->getLabel(), $this->getColumns());
19
-    }
20
-
21
     /**
15
     /**
22
      * @return ReportCategoryDTO[]
16
      * @return ReportCategoryDTO[]
23
      */
17
      */
26
         $categories = [];
20
         $categories = [];
27
 
21
 
28
         foreach ($this->report->categories as $accountCategoryName => $accountCategory) {
22
         foreach ($this->report->categories as $accountCategoryName => $accountCategory) {
29
-            // Initialize header with empty strings
30
             $header = [];
23
             $header = [];
31
 
24
 
32
-            foreach ($this->getColumns() as $index => $column) {
33
-                if ($column->getName() === 'account_name') {
34
-                    $header[$index] = $accountCategoryName;
35
-                } else {
36
-                    $header[$index] = '';
37
-                }
25
+            foreach ($this->getColumns() as $column) {
26
+                $header[$column->getName()] = $column->getName() === 'account_name' ? $accountCategoryName : '';
38
             }
27
             }
39
 
28
 
40
             $data = array_map(function (AccountDTO $account) {
29
             $data = array_map(function (AccountDTO $account) {
41
                 $row = [];
30
                 $row = [];
42
 
31
 
43
                 foreach ($this->getColumns() as $column) {
32
                 foreach ($this->getColumns() as $column) {
44
-                    $row[] = match ($column->getName()) {
33
+                    $row[$column->getName()] = match ($column->getName()) {
45
                         'account_code' => $account->accountCode,
34
                         'account_code' => $account->accountCode,
46
                         'account_name' => [
35
                         'account_name' => [
47
                             'name' => $account->accountName,
36
                             'name' => $account->accountName,
64
             $summary = [];
53
             $summary = [];
65
 
54
 
66
             foreach ($this->getColumns() as $column) {
55
             foreach ($this->getColumns() as $column) {
67
-                $summary[] = match ($column->getName()) {
56
+                $summary[$column->getName()] = match ($column->getName()) {
68
                     'account_name' => 'Total ' . $accountCategoryName,
57
                     'account_name' => 'Total ' . $accountCategoryName,
69
                     'starting_balance' => $accountCategory->summary->startingBalance ?? '',
58
                     'starting_balance' => $accountCategory->summary->startingBalance ?? '',
70
                     'debit_balance' => $accountCategory->summary->debitBalance,
59
                     'debit_balance' => $accountCategory->summary->debitBalance,
90
         $totals = [];
79
         $totals = [];
91
 
80
 
92
         foreach ($this->getColumns() as $column) {
81
         foreach ($this->getColumns() as $column) {
93
-            $totals[] = match ($column->getName()) {
82
+            $totals[$column->getName()] = match ($column->getName()) {
94
                 'account_name' => 'Total for all accounts',
83
                 'account_name' => 'Total for all accounts',
95
                 'debit_balance' => $this->report->overallTotal->debitBalance,
84
                 'debit_balance' => $this->report->overallTotal->debitBalance,
96
                 'credit_balance' => $this->report->overallTotal->creditBalance,
85
                 'credit_balance' => $this->report->overallTotal->creditBalance,

+ 5
- 16
app/Transformers/AccountTransactionReportTransformer.php 查看文件

4
 
4
 
5
 use App\DTO\AccountTransactionDTO;
5
 use App\DTO\AccountTransactionDTO;
6
 use App\DTO\ReportCategoryDTO;
6
 use App\DTO\ReportCategoryDTO;
7
-use App\Support\Column;
8
 
7
 
9
 class AccountTransactionReportTransformer extends BaseReportTransformer
8
 class AccountTransactionReportTransformer extends BaseReportTransformer
10
 {
9
 {
18
         return 'Account Transactions';
17
         return 'Account Transactions';
19
     }
18
     }
20
 
19
 
21
-    public function getHeaders(): array
22
-    {
23
-        return array_map(fn (Column $column) => $column->getLabel(), $this->getColumns());
24
-    }
25
-
26
     /**
20
     /**
27
      * @return ReportCategoryDTO[]
21
      * @return ReportCategoryDTO[]
28
      */
22
      */
31
         $categories = [];
25
         $categories = [];
32
 
26
 
33
         foreach ($this->report->categories as $categoryData) {
27
         foreach ($this->report->categories as $categoryData) {
34
-            // Initialize header with account and category information
35
-
36
-            $header = [
37
-                array_fill(0, count($this->getColumns()), ''),
38
-                array_fill(0, count($this->getColumns()), ''),
39
-            ];
28
+            $header = [];
40
 
29
 
41
-            foreach ($this->getColumns() as $index => $column) {
30
+            foreach ($this->getColumns() as $column) {
42
                 if ($column->getName() === 'date') {
31
                 if ($column->getName() === 'date') {
43
-                    $header[0][$index] = $categoryData['category'];
44
-                    $header[1][$index] = $categoryData['under'];
32
+                    $header[0][$column->getName()] = $categoryData['category'];
33
+                    $header[1][$column->getName()] = $categoryData['under'];
45
                 }
34
                 }
46
             }
35
             }
47
 
36
 
50
                 $row = [];
39
                 $row = [];
51
 
40
 
52
                 foreach ($this->getColumns() as $column) {
41
                 foreach ($this->getColumns() as $column) {
53
-                    $row[] = match ($column->getName()) {
42
+                    $row[$column->getName()] = match ($column->getName()) {
54
                         'date' => $transaction->date,
43
                         'date' => $transaction->date,
55
                         'description' => [
44
                         'description' => [
56
                             'id' => $transaction->id,
45
                             'id' => $transaction->id,

+ 34
- 33
app/Transformers/BalanceSheetReportTransformer.php 查看文件

4
 
4
 
5
 use App\DTO\AccountDTO;
5
 use App\DTO\AccountDTO;
6
 use App\DTO\ReportCategoryDTO;
6
 use App\DTO\ReportCategoryDTO;
7
+use App\DTO\ReportDTO;
7
 use App\DTO\ReportTypeDTO;
8
 use App\DTO\ReportTypeDTO;
8
-use App\Support\Column;
9
 use App\Utilities\Currency\CurrencyAccessor;
9
 use App\Utilities\Currency\CurrencyAccessor;
10
 
10
 
11
-class BalanceSheetReportTransformer extends BaseReportTransformer
11
+class BalanceSheetReportTransformer extends SummaryReportTransformer
12
 {
12
 {
13
-    protected string $totalAssets = '$0.00';
13
+    protected string $totalAssets;
14
 
14
 
15
-    protected string $totalLiabilities = '$0.00';
15
+    protected string $totalLiabilities;
16
 
16
 
17
-    protected string $totalEquity = '$0.00';
17
+    protected string $totalEquity;
18
 
18
 
19
-    public function getTitle(): string
19
+    public function __construct(ReportDTO $report)
20
     {
20
     {
21
-        return 'Balance Sheet';
21
+        parent::__construct($report);
22
+
23
+        $this->calculateTotals();
22
     }
24
     }
23
 
25
 
24
-    public function getHeaders(): array
26
+    public function getTitle(): string
25
     {
27
     {
26
-        return array_map(fn (Column $column) => $column->getLabel(), $this->getColumns());
28
+        return 'Balance Sheet';
27
     }
29
     }
28
 
30
 
29
     public function calculateTotals(): void
31
     public function calculateTotals(): void
44
         foreach ($this->report->categories as $accountCategoryName => $accountCategory) {
46
         foreach ($this->report->categories as $accountCategoryName => $accountCategory) {
45
             // Header for the main category
47
             // Header for the main category
46
             $header = [];
48
             $header = [];
47
-            foreach ($this->getColumns() as $index => $column) {
48
-                if ($column->getName() === 'account_name') {
49
-                    $header[$index] = $accountCategoryName;
50
-                } else {
51
-                    $header[$index] = '';
52
-                }
49
+
50
+            foreach ($this->getColumns() as $column) {
51
+                $header[$column->getName()] = $column->getName() === 'account_name' ? $accountCategoryName : '';
53
             }
52
             }
54
 
53
 
55
             // Category-level summary
54
             // Category-level summary
56
             $categorySummary = [];
55
             $categorySummary = [];
57
             foreach ($this->getColumns() as $column) {
56
             foreach ($this->getColumns() as $column) {
58
-                $categorySummary[] = match ($column->getName()) {
57
+                $categorySummary[$column->getName()] = match ($column->getName()) {
59
                     'account_name' => 'Total ' . $accountCategoryName,
58
                     'account_name' => 'Total ' . $accountCategoryName,
60
                     'ending_balance' => $accountCategory->summary->endingBalance ?? '',
59
                     'ending_balance' => $accountCategory->summary->endingBalance ?? '',
61
                     default => '',
60
                     default => '',
65
             // Accounts directly under the main category
64
             // Accounts directly under the main category
66
             $data = array_map(function (AccountDTO $account) {
65
             $data = array_map(function (AccountDTO $account) {
67
                 $row = [];
66
                 $row = [];
67
+
68
                 foreach ($this->getColumns() as $column) {
68
                 foreach ($this->getColumns() as $column) {
69
-                    $row[] = match ($column->getName()) {
69
+                    $row[$column->getName()] = match ($column->getName()) {
70
                         'account_code' => $account->accountCode,
70
                         'account_code' => $account->accountCode,
71
                         'account_name' => [
71
                         'account_name' => [
72
                             'name' => $account->accountName,
72
                             'name' => $account->accountName,
87
             foreach ($accountCategory->types as $typeName => $type) {
87
             foreach ($accountCategory->types as $typeName => $type) {
88
                 // Header for subcategory (type)
88
                 // Header for subcategory (type)
89
                 $typeHeader = [];
89
                 $typeHeader = [];
90
-                foreach ($this->getColumns() as $index => $column) {
91
-                    $typeHeader[$index] = $column->getName() === 'account_name' ? $typeName : '';
90
+                foreach ($this->getColumns() as $column) {
91
+                    $typeHeader[$column->getName()] = $column->getName() === 'account_name' ? $typeName : '';
92
                 }
92
                 }
93
 
93
 
94
                 // Account data for the subcategory
94
                 // Account data for the subcategory
95
                 $typeData = array_map(function (AccountDTO $account) {
95
                 $typeData = array_map(function (AccountDTO $account) {
96
                     $row = [];
96
                     $row = [];
97
+
97
                     foreach ($this->getColumns() as $column) {
98
                     foreach ($this->getColumns() as $column) {
98
-                        $row[] = match ($column->getName()) {
99
+                        $row[$column->getName()] = match ($column->getName()) {
99
                             'account_code' => $account->accountCode,
100
                             'account_code' => $account->accountCode,
100
                             'account_name' => [
101
                             'account_name' => [
101
                                 'name' => $account->accountName,
102
                                 'name' => $account->accountName,
114
                 // Subcategory (type) summary
115
                 // Subcategory (type) summary
115
                 $typeSummary = [];
116
                 $typeSummary = [];
116
                 foreach ($this->getColumns() as $column) {
117
                 foreach ($this->getColumns() as $column) {
117
-                    $typeSummary[] = match ($column->getName()) {
118
+                    $typeSummary[$column->getName()] = match ($column->getName()) {
118
                         'account_name' => 'Total ' . $typeName,
119
                         'account_name' => 'Total ' . $typeName,
119
                         'ending_balance' => $type->summary->endingBalance ?? '',
120
                         'ending_balance' => $type->summary->endingBalance ?? '',
120
                         default => '',
121
                         default => '',
145
     {
146
     {
146
         $summaryCategories = [];
147
         $summaryCategories = [];
147
 
148
 
148
-        $columns = [
149
-            'account_name',
150
-            'ending_balance',
151
-        ];
149
+        $columns = $this->getSummaryColumns();
152
 
150
 
153
         foreach ($this->report->categories as $accountCategoryName => $accountCategory) {
151
         foreach ($this->report->categories as $accountCategoryName => $accountCategory) {
154
             $categoryHeader = [];
152
             $categoryHeader = [];
155
 
153
 
156
-            foreach ($columns as $index => $column) {
157
-                $categoryHeader[$index] = $column === 'account_name' ? $accountCategoryName : '';
154
+            foreach ($columns as $column) {
155
+                $categoryHeader[$column->getName()] = $column->getName() === 'account_name' ? $accountCategoryName : '';
158
             }
156
             }
159
 
157
 
160
             $categorySummary = [];
158
             $categorySummary = [];
161
             foreach ($columns as $column) {
159
             foreach ($columns as $column) {
162
-                $categorySummary[] = match ($column) {
160
+                $categorySummary[$column->getName()] = match ($column->getName()) {
163
                     'account_name' => 'Total ' . $accountCategoryName,
161
                     'account_name' => 'Total ' . $accountCategoryName,
164
                     'ending_balance' => $accountCategory->summary->endingBalance ?? '',
162
                     'ending_balance' => $accountCategory->summary->endingBalance ?? '',
165
                     default => '',
163
                     default => '',
175
                 $typeEndingBalance = 0;
173
                 $typeEndingBalance = 0;
176
 
174
 
177
                 foreach ($columns as $column) {
175
                 foreach ($columns as $column) {
178
-                    $typeSummary[] = match ($column) {
176
+                    $typeSummary[$column->getName()] = match ($column->getName()) {
179
                         'account_name' => 'Total ' . $typeName,
177
                         'account_name' => 'Total ' . $typeName,
180
                         'ending_balance' => $type->summary->endingBalance ?? '',
178
                         'ending_balance' => $type->summary->endingBalance ?? '',
181
                         default => '',
179
                         default => '',
182
                     };
180
                     };
183
 
181
 
184
-                    if ($column === 'ending_balance') {
182
+                    if ($column->getName() === 'ending_balance') {
185
                         $typeEndingBalance = $type->summary->endingBalance ?? 0;
183
                         $typeEndingBalance = $type->summary->endingBalance ?? 0;
186
                     }
184
                     }
187
                 }
185
                 }
207
                 // Add "Total Other Equity" as a new "type"
205
                 // Add "Total Other Equity" as a new "type"
208
                 $otherEquitySummary = [];
206
                 $otherEquitySummary = [];
209
                 foreach ($columns as $column) {
207
                 foreach ($columns as $column) {
210
-                    $otherEquitySummary[] = match ($column) {
208
+                    $otherEquitySummary[$column->getName()] = match ($column->getName()) {
211
                         'account_name' => 'Total Other Equity',
209
                         'account_name' => 'Total Other Equity',
212
                         'ending_balance' => $totalOtherEquity,
210
                         'ending_balance' => $totalOtherEquity,
213
                         default => '',
211
                         default => '',
238
         return [];
236
         return [];
239
     }
237
     }
240
 
238
 
241
-    public function getSummary(): array
239
+    public function getSummaryOverallTotals(): array
242
     {
240
     {
243
-        $this->calculateTotals();
241
+        return [];
242
+    }
244
 
243
 
244
+    public function getSummary(): array
245
+    {
245
         return [
246
         return [
246
             [
247
             [
247
                 'label' => 'Total Assets',
248
                 'label' => 'Total Assets',

+ 32
- 10
app/Transformers/BaseReportTransformer.php 查看文件

4
 
4
 
5
 use App\Contracts\ExportableReport;
5
 use App\Contracts\ExportableReport;
6
 use App\DTO\ReportDTO;
6
 use App\DTO\ReportDTO;
7
+use App\Support\Column;
7
 use Filament\Support\Enums\Alignment;
8
 use Filament\Support\Enums\Alignment;
8
 
9
 
9
 abstract class BaseReportTransformer implements ExportableReport
10
 abstract class BaseReportTransformer implements ExportableReport
15
         $this->report = $report;
16
         $this->report = $report;
16
     }
17
     }
17
 
18
 
19
+    /**
20
+     * @return Column[]
21
+     */
18
     public function getColumns(): array
22
     public function getColumns(): array
19
     {
23
     {
20
-        return $this->report->fields;
24
+        return once(function (): array {
25
+            return $this->report->fields;
26
+        });
27
+    }
28
+
29
+    public function getHeaders(): array
30
+    {
31
+        return once(function (): array {
32
+            $headers = [];
33
+
34
+            foreach ($this->getColumns() as $column) {
35
+                $headers[$column->getName()] = $column->getLabel();
36
+            }
37
+
38
+            return $headers;
39
+        });
21
     }
40
     }
22
 
41
 
23
     public function getPdfView(): string
42
     public function getPdfView(): string
40
         return 'left';
59
         return 'left';
41
     }
60
     }
42
 
61
 
43
-    public function getAlignmentClass(int $index): string
62
+    public function getAlignmentClass(string $columnName): string
44
     {
63
     {
45
-        $column = $this->getColumns()[$index];
64
+        return once(function () use ($columnName): string {
65
+            /** @var Column|null $column */
66
+            $column = collect($this->getColumns())->first(fn (Column $column) => $column->getName() === $columnName);
46
 
67
 
47
-        if ($column->getAlignment() === Alignment::Right) {
48
-            return 'text-right';
49
-        }
68
+            if ($column?->getAlignment() === Alignment::Right) {
69
+                return 'text-right';
70
+            }
50
 
71
 
51
-        if ($column->getAlignment() === Alignment::Center) {
52
-            return 'text-center';
53
-        }
72
+            if ($column?->getAlignment() === Alignment::Center) {
73
+                return 'text-center';
74
+            }
54
 
75
 
55
-        return 'text-left';
76
+            return 'text-left';
77
+        });
56
     }
78
     }
57
 }
79
 }

+ 28
- 44
app/Transformers/IncomeStatementReportTransformer.php 查看文件

4
 
4
 
5
 use App\DTO\AccountDTO;
5
 use App\DTO\AccountDTO;
6
 use App\DTO\ReportCategoryDTO;
6
 use App\DTO\ReportCategoryDTO;
7
-use App\Support\Column;
7
+use App\DTO\ReportDTO;
8
 use App\Utilities\Currency\CurrencyAccessor;
8
 use App\Utilities\Currency\CurrencyAccessor;
9
 
9
 
10
-class IncomeStatementReportTransformer extends BaseReportTransformer
10
+class IncomeStatementReportTransformer extends SummaryReportTransformer
11
 {
11
 {
12
-    protected string $totalRevenue = '0';
12
+    protected string $totalRevenue;
13
 
13
 
14
-    protected string $totalCogs = '0';
14
+    protected string $totalCogs;
15
 
15
 
16
-    protected string $totalExpenses = '0';
16
+    protected string $totalExpenses;
17
 
17
 
18
-    public function getTitle(): string
18
+    public function __construct(ReportDTO $report)
19
     {
19
     {
20
-        return 'Income Statement';
20
+        parent::__construct($report);
21
+
22
+        $this->calculateTotals();
21
     }
23
     }
22
 
24
 
23
-    public function getHeaders(): array
25
+    public function getTitle(): string
24
     {
26
     {
25
-        return array_map(fn (Column $column) => $column->getLabel(), $this->getColumns());
27
+        return 'Income Statement';
26
     }
28
     }
27
 
29
 
28
     public function calculateTotals(): void
30
     public function calculateTotals(): void
41
         $categories = [];
43
         $categories = [];
42
 
44
 
43
         foreach ($this->report->categories as $accountCategoryName => $accountCategory) {
45
         foreach ($this->report->categories as $accountCategoryName => $accountCategory) {
44
-            // Initialize header with empty strings
45
             $header = [];
46
             $header = [];
46
 
47
 
47
-            foreach ($this->getColumns() as $index => $column) {
48
-                if ($column->getName() === 'account_name') {
49
-                    $header[$index] = $accountCategoryName;
50
-                } else {
51
-                    $header[$index] = '';
52
-                }
48
+            foreach ($this->getColumns() as $column) {
49
+                $header[$column->getName()] = $column->getName() === 'account_name' ? $accountCategoryName : '';
53
             }
50
             }
54
 
51
 
55
             $data = array_map(function (AccountDTO $account) {
52
             $data = array_map(function (AccountDTO $account) {
56
                 $row = [];
53
                 $row = [];
57
 
54
 
58
                 foreach ($this->getColumns() as $column) {
55
                 foreach ($this->getColumns() as $column) {
59
-                    $row[] = match ($column->getName()) {
56
+                    $row[$column->getName()] = match ($column->getName()) {
60
                         'account_code' => $account->accountCode,
57
                         'account_code' => $account->accountCode,
61
                         'account_name' => [
58
                         'account_name' => [
62
                             'name' => $account->accountName,
59
                             'name' => $account->accountName,
75
             $summary = [];
72
             $summary = [];
76
 
73
 
77
             foreach ($this->getColumns() as $column) {
74
             foreach ($this->getColumns() as $column) {
78
-                $summary[] = match ($column->getName()) {
75
+                $summary[$column->getName()] = match ($column->getName()) {
79
                     'account_name' => 'Total ' . $accountCategoryName,
76
                     'account_name' => 'Total ' . $accountCategoryName,
80
                     'net_movement' => $accountCategory->summary->netMovement ?? '',
77
                     'net_movement' => $accountCategory->summary->netMovement ?? '',
81
                     default => '',
78
                     default => '',
96
     {
93
     {
97
         $summaryCategories = [];
94
         $summaryCategories = [];
98
 
95
 
99
-        $columns = [
100
-            'account_name',
101
-            'net_movement',
102
-        ];
96
+        $columns = $this->getSummaryColumns();
103
 
97
 
104
         foreach ($this->report->categories as $accountCategoryName => $accountCategory) {
98
         foreach ($this->report->categories as $accountCategoryName => $accountCategory) {
105
             // Header for the main category
99
             // Header for the main category
106
             $categoryHeader = [];
100
             $categoryHeader = [];
107
 
101
 
108
-            foreach ($columns as $index => $column) {
109
-                $categoryHeader[$index] = $column === 'account_name' ? $accountCategoryName : '';
102
+            foreach ($columns as $column) {
103
+                $categoryHeader[$column->getName()] = $column->getName() === 'account_name' ? $accountCategoryName : '';
110
             }
104
             }
111
 
105
 
112
             // Category-level summary
106
             // Category-level summary
113
             $categorySummary = [];
107
             $categorySummary = [];
114
             foreach ($columns as $column) {
108
             foreach ($columns as $column) {
115
-                $categorySummary[] = match ($column) {
109
+                $categorySummary[$column->getName()] = match ($column->getName()) {
116
                     'account_name' => $accountCategoryName,
110
                     'account_name' => $accountCategoryName,
117
                     'net_movement' => $accountCategory->summary->netMovement ?? '',
111
                     'net_movement' => $accountCategory->summary->netMovement ?? '',
118
                     default => '',
112
                     default => '',
133
 
127
 
134
     public function getGrossProfit(): array
128
     public function getGrossProfit(): array
135
     {
129
     {
136
-        $this->calculateTotals();
137
-
138
         $grossProfit = [];
130
         $grossProfit = [];
139
 
131
 
140
-        $columns = [
141
-            'account_name',
142
-            'net_movement',
143
-        ];
132
+        $columns = $this->getSummaryColumns();
144
 
133
 
145
         $revenue = money($this->totalRevenue, CurrencyAccessor::getDefaultCurrency())->getAmount();
134
         $revenue = money($this->totalRevenue, CurrencyAccessor::getDefaultCurrency())->getAmount();
146
         $cogs = money($this->totalCogs, CurrencyAccessor::getDefaultCurrency())->getAmount();
135
         $cogs = money($this->totalCogs, CurrencyAccessor::getDefaultCurrency())->getAmount();
149
         $grossProfitFormatted = money($grossProfitAmount, CurrencyAccessor::getDefaultCurrency(), true)->format();
138
         $grossProfitFormatted = money($grossProfitAmount, CurrencyAccessor::getDefaultCurrency(), true)->format();
150
 
139
 
151
         foreach ($columns as $column) {
140
         foreach ($columns as $column) {
152
-            $grossProfit[] = match ($column) {
141
+            $grossProfit[$column->getName()] = match ($column->getName()) {
153
                 'account_name' => 'Gross Profit',
142
                 'account_name' => 'Gross Profit',
154
                 'net_movement' => $grossProfitFormatted,
143
                 'net_movement' => $grossProfitFormatted,
155
                 default => '',
144
                 default => '',
159
         return $grossProfit;
148
         return $grossProfit;
160
     }
149
     }
161
 
150
 
162
-    public function getSummaryTotals(): array
151
+    public function getOverallTotals(): array
163
     {
152
     {
164
         $totals = [];
153
         $totals = [];
165
-        $columns = [
166
-            'account_name',
167
-            'net_movement',
168
-        ];
169
 
154
 
170
-        foreach ($columns as $column) {
171
-            $totals[] = match ($column) {
155
+        foreach ($this->getColumns() as $column) {
156
+            $totals[$column->getName()] = match ($column->getName()) {
172
                 'account_name' => 'Net Earnings',
157
                 'account_name' => 'Net Earnings',
173
                 'net_movement' => $this->report->overallTotal->netMovement ?? '',
158
                 'net_movement' => $this->report->overallTotal->netMovement ?? '',
174
                 default => '',
159
                 default => '',
178
         return $totals;
163
         return $totals;
179
     }
164
     }
180
 
165
 
181
-    public function getOverallTotals(): array
166
+    public function getSummaryOverallTotals(): array
182
     {
167
     {
183
         $totals = [];
168
         $totals = [];
169
+        $columns = $this->getSummaryColumns();
184
 
170
 
185
-        foreach ($this->getColumns() as $column) {
186
-            $totals[] = match ($column->getName()) {
171
+        foreach ($columns as $column) {
172
+            $totals[$column->getName()] = match ($column->getName()) {
187
                 'account_name' => 'Net Earnings',
173
                 'account_name' => 'Net Earnings',
188
                 'net_movement' => $this->report->overallTotal->netMovement ?? '',
174
                 'net_movement' => $this->report->overallTotal->netMovement ?? '',
189
                 default => '',
175
                 default => '',
195
 
181
 
196
     public function getSummary(): array
182
     public function getSummary(): array
197
     {
183
     {
198
-        $this->calculateTotals();
199
-
200
         return [
184
         return [
201
             [
185
             [
202
                 'label' => 'Revenue',
186
                 'label' => 'Revenue',

+ 34
- 0
app/Transformers/SummaryReportTransformer.php 查看文件

1
+<?php
2
+
3
+namespace App\Transformers;
4
+
5
+use App\Contracts\HasSummaryReport;
6
+use App\Support\Column;
7
+
8
+abstract class SummaryReportTransformer extends BaseReportTransformer implements HasSummaryReport
9
+{
10
+    /**
11
+     * @return Column[]
12
+     */
13
+    public function getSummaryColumns(): array
14
+    {
15
+        return once(function (): array {
16
+            return collect($this->getColumns())
17
+                ->reject(fn (Column $column) => $column->getName() === 'account_code')
18
+                ->toArray();
19
+        });
20
+    }
21
+
22
+    public function getSummaryHeaders(): array
23
+    {
24
+        return once(function (): array {
25
+            $headers = [];
26
+
27
+            foreach ($this->getSummaryColumns() as $column) {
28
+                $headers[$column->getName()] = $column->getLabel();
29
+            }
30
+
31
+            return $headers;
32
+        });
33
+    }
34
+}

+ 5
- 15
app/Transformers/TrialBalanceReportTransformer.php 查看文件

4
 
4
 
5
 use App\DTO\AccountDTO;
5
 use App\DTO\AccountDTO;
6
 use App\DTO\ReportCategoryDTO;
6
 use App\DTO\ReportCategoryDTO;
7
-use App\Support\Column;
8
 
7
 
9
 class TrialBalanceReportTransformer extends BaseReportTransformer
8
 class TrialBalanceReportTransformer extends BaseReportTransformer
10
 {
9
 {
16
         };
15
         };
17
     }
16
     }
18
 
17
 
19
-    public function getHeaders(): array
20
-    {
21
-        return array_map(fn (Column $column) => $column->getLabel(), $this->getColumns());
22
-    }
23
-
24
     /**
18
     /**
25
      * @return ReportCategoryDTO[]
19
      * @return ReportCategoryDTO[]
26
      */
20
      */
32
             // Initialize header with empty strings
26
             // Initialize header with empty strings
33
             $header = [];
27
             $header = [];
34
 
28
 
35
-            foreach ($this->getColumns() as $index => $column) {
36
-                if ($column->getName() === 'account_name') {
37
-                    $header[$index] = $accountCategoryName;
38
-                } else {
39
-                    $header[$index] = '';
40
-                }
29
+            foreach ($this->getColumns() as $column) {
30
+                $header[$column->getName()] = $column->getName() === 'account_name' ? $accountCategoryName : '';
41
             }
31
             }
42
 
32
 
43
             $data = array_map(function (AccountDTO $account) {
33
             $data = array_map(function (AccountDTO $account) {
44
                 $row = [];
34
                 $row = [];
45
 
35
 
46
                 foreach ($this->getColumns() as $column) {
36
                 foreach ($this->getColumns() as $column) {
47
-                    $row[] = match ($column->getName()) {
37
+                    $row[$column->getName()] = match ($column->getName()) {
48
                         'account_code' => $account->accountCode,
38
                         'account_code' => $account->accountCode,
49
                         'account_name' => [
39
                         'account_name' => [
50
                             'name' => $account->accountName,
40
                             'name' => $account->accountName,
64
             $summary = [];
54
             $summary = [];
65
 
55
 
66
             foreach ($this->getColumns() as $column) {
56
             foreach ($this->getColumns() as $column) {
67
-                $summary[] = match ($column->getName()) {
57
+                $summary[$column->getName()] = match ($column->getName()) {
68
                     'account_name' => 'Total ' . $accountCategoryName,
58
                     'account_name' => 'Total ' . $accountCategoryName,
69
                     'debit_balance' => $accountCategory->summary->debitBalance,
59
                     'debit_balance' => $accountCategory->summary->debitBalance,
70
                     'credit_balance' => $accountCategory->summary->creditBalance,
60
                     'credit_balance' => $accountCategory->summary->creditBalance,
87
         $totals = [];
77
         $totals = [];
88
 
78
 
89
         foreach ($this->getColumns() as $column) {
79
         foreach ($this->getColumns() as $column) {
90
-            $totals[] = match ($column->getName()) {
80
+            $totals[$column->getName()] = match ($column->getName()) {
91
                 'account_name' => 'Total for all accounts',
81
                 'account_name' => 'Total for all accounts',
92
                 'debit_balance' => $this->report->overallTotal->debitBalance,
82
                 'debit_balance' => $this->report->overallTotal->debitBalance,
93
                 'credit_balance' => $this->report->overallTotal->creditBalance,
83
                 'credit_balance' => $this->report->overallTotal->creditBalance,

+ 17
- 17
composer.lock 查看文件

9925
         },
9925
         },
9926
         {
9926
         {
9927
             "name": "pestphp/pest",
9927
             "name": "pestphp/pest",
9928
-            "version": "v3.4.1",
9928
+            "version": "v3.4.2",
9929
             "source": {
9929
             "source": {
9930
                 "type": "git",
9930
                 "type": "git",
9931
                 "url": "https://github.com/pestphp/pest.git",
9931
                 "url": "https://github.com/pestphp/pest.git",
9932
-                "reference": "67f217852ce153134fbea8857487a3829904c086"
9932
+                "reference": "2903a7e62100171d5faf4e50cda755ffeadedc57"
9933
             },
9933
             },
9934
             "dist": {
9934
             "dist": {
9935
                 "type": "zip",
9935
                 "type": "zip",
9936
-                "url": "https://api.github.com/repos/pestphp/pest/zipball/67f217852ce153134fbea8857487a3829904c086",
9937
-                "reference": "67f217852ce153134fbea8857487a3829904c086",
9936
+                "url": "https://api.github.com/repos/pestphp/pest/zipball/2903a7e62100171d5faf4e50cda755ffeadedc57",
9937
+                "reference": "2903a7e62100171d5faf4e50cda755ffeadedc57",
9938
                 "shasum": ""
9938
                 "shasum": ""
9939
             },
9939
             },
9940
             "require": {
9940
             "require": {
9945
                 "pestphp/pest-plugin-arch": "^3.0.0",
9945
                 "pestphp/pest-plugin-arch": "^3.0.0",
9946
                 "pestphp/pest-plugin-mutate": "^3.0.5",
9946
                 "pestphp/pest-plugin-mutate": "^3.0.5",
9947
                 "php": "^8.2.0",
9947
                 "php": "^8.2.0",
9948
-                "phpunit/phpunit": "^11.4.1"
9948
+                "phpunit/phpunit": "^11.4.2"
9949
             },
9949
             },
9950
             "conflict": {
9950
             "conflict": {
9951
                 "filp/whoops": "<2.16.0",
9951
                 "filp/whoops": "<2.16.0",
9952
-                "phpunit/phpunit": ">11.4.1",
9952
+                "phpunit/phpunit": ">11.4.2",
9953
                 "sebastian/exporter": "<6.0.0",
9953
                 "sebastian/exporter": "<6.0.0",
9954
                 "webmozart/assert": "<1.11.0"
9954
                 "webmozart/assert": "<1.11.0"
9955
             },
9955
             },
10021
             ],
10021
             ],
10022
             "support": {
10022
             "support": {
10023
                 "issues": "https://github.com/pestphp/pest/issues",
10023
                 "issues": "https://github.com/pestphp/pest/issues",
10024
-                "source": "https://github.com/pestphp/pest/tree/v3.4.1"
10024
+                "source": "https://github.com/pestphp/pest/tree/v3.4.2"
10025
             },
10025
             },
10026
             "funding": [
10026
             "funding": [
10027
                 {
10027
                 {
10033
                     "type": "github"
10033
                     "type": "github"
10034
                 }
10034
                 }
10035
             ],
10035
             ],
10036
-            "time": "2024-10-15T16:17:09+00:00"
10036
+            "time": "2024-10-20T11:47:25+00:00"
10037
         },
10037
         },
10038
         {
10038
         {
10039
             "name": "pestphp/pest-plugin",
10039
             "name": "pestphp/pest-plugin",
11164
         },
11164
         },
11165
         {
11165
         {
11166
             "name": "phpunit/phpunit",
11166
             "name": "phpunit/phpunit",
11167
-            "version": "11.4.1",
11167
+            "version": "11.4.2",
11168
             "source": {
11168
             "source": {
11169
                 "type": "git",
11169
                 "type": "git",
11170
                 "url": "https://github.com/sebastianbergmann/phpunit.git",
11170
                 "url": "https://github.com/sebastianbergmann/phpunit.git",
11171
-                "reference": "7875627f15f4da7e7f0823d1f323f7295a77334e"
11171
+                "reference": "1863643c3f04ad03dcb9c6996c294784cdda4805"
11172
             },
11172
             },
11173
             "dist": {
11173
             "dist": {
11174
                 "type": "zip",
11174
                 "type": "zip",
11175
-                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/7875627f15f4da7e7f0823d1f323f7295a77334e",
11176
-                "reference": "7875627f15f4da7e7f0823d1f323f7295a77334e",
11175
+                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1863643c3f04ad03dcb9c6996c294784cdda4805",
11176
+                "reference": "1863643c3f04ad03dcb9c6996c294784cdda4805",
11177
                 "shasum": ""
11177
                 "shasum": ""
11178
             },
11178
             },
11179
             "require": {
11179
             "require": {
11187
                 "phar-io/manifest": "^2.0.4",
11187
                 "phar-io/manifest": "^2.0.4",
11188
                 "phar-io/version": "^3.2.1",
11188
                 "phar-io/version": "^3.2.1",
11189
                 "php": ">=8.2",
11189
                 "php": ">=8.2",
11190
-                "phpunit/php-code-coverage": "^11.0.6",
11190
+                "phpunit/php-code-coverage": "^11.0.7",
11191
                 "phpunit/php-file-iterator": "^5.1.0",
11191
                 "phpunit/php-file-iterator": "^5.1.0",
11192
                 "phpunit/php-invoker": "^5.0.1",
11192
                 "phpunit/php-invoker": "^5.0.1",
11193
                 "phpunit/php-text-template": "^4.0.1",
11193
                 "phpunit/php-text-template": "^4.0.1",
11194
                 "phpunit/php-timer": "^7.0.1",
11194
                 "phpunit/php-timer": "^7.0.1",
11195
                 "sebastian/cli-parser": "^3.0.2",
11195
                 "sebastian/cli-parser": "^3.0.2",
11196
                 "sebastian/code-unit": "^3.0.1",
11196
                 "sebastian/code-unit": "^3.0.1",
11197
-                "sebastian/comparator": "^6.1.0",
11197
+                "sebastian/comparator": "^6.1.1",
11198
                 "sebastian/diff": "^6.0.2",
11198
                 "sebastian/diff": "^6.0.2",
11199
                 "sebastian/environment": "^7.2.0",
11199
                 "sebastian/environment": "^7.2.0",
11200
                 "sebastian/exporter": "^6.1.3",
11200
                 "sebastian/exporter": "^6.1.3",
11201
                 "sebastian/global-state": "^7.0.2",
11201
                 "sebastian/global-state": "^7.0.2",
11202
                 "sebastian/object-enumerator": "^6.0.1",
11202
                 "sebastian/object-enumerator": "^6.0.1",
11203
                 "sebastian/type": "^5.1.0",
11203
                 "sebastian/type": "^5.1.0",
11204
-                "sebastian/version": "^5.0.1"
11204
+                "sebastian/version": "^5.0.2"
11205
             },
11205
             },
11206
             "suggest": {
11206
             "suggest": {
11207
                 "ext-soap": "To be able to generate mocks based on WSDL files"
11207
                 "ext-soap": "To be able to generate mocks based on WSDL files"
11244
             "support": {
11244
             "support": {
11245
                 "issues": "https://github.com/sebastianbergmann/phpunit/issues",
11245
                 "issues": "https://github.com/sebastianbergmann/phpunit/issues",
11246
                 "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
11246
                 "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
11247
-                "source": "https://github.com/sebastianbergmann/phpunit/tree/11.4.1"
11247
+                "source": "https://github.com/sebastianbergmann/phpunit/tree/11.4.2"
11248
             },
11248
             },
11249
             "funding": [
11249
             "funding": [
11250
                 {
11250
                 {
11260
                     "type": "tidelift"
11260
                     "type": "tidelift"
11261
                 }
11261
                 }
11262
             ],
11262
             ],
11263
-            "time": "2024-10-08T15:38:37+00:00"
11263
+            "time": "2024-10-19T13:05:19+00:00"
11264
         },
11264
         },
11265
         {
11265
         {
11266
             "name": "rector/rector",
11266
             "name": "rector/rector",

+ 1
- 5
resources/css/filament/company/theme.css 查看文件

107
 }
107
 }
108
 
108
 
109
 .es-table__header-ctn, .es-table__footer-ctn {
109
 .es-table__header-ctn, .es-table__footer-ctn {
110
-    @apply divide-y divide-gray-200 dark:divide-white/10 h-12;
111
-}
112
-
113
-.es-table__row {
114
-    @apply [@media(hover:hover)]:transition [@media(hover:hover)]:duration-75 hover:bg-gray-50 dark:hover:bg-white/5;
110
+    @apply divide-y divide-gray-200 dark:divide-white/10 min-h-12;
115
 }
111
 }
116
 
112
 
117
 .es-table .es-table__rowgroup td:first-child {
113
 .es-table .es-table__rowgroup td:first-child {

+ 2
- 2
resources/views/components/company/tables/reports/account-transactions.blade.php 查看文件

4
         <tbody class="divide-y divide-gray-200 whitespace-nowrap dark:divide-white/5">
4
         <tbody class="divide-y divide-gray-200 whitespace-nowrap dark:divide-white/5">
5
         <!-- Category Header -->
5
         <!-- Category Header -->
6
         <tr class="bg-gray-50 dark:bg-white/5">
6
         <tr class="bg-gray-50 dark:bg-white/5">
7
-            <x-filament-tables::cell colspan="{{ count($report->getHeaders()) }}" class="text-left">
7
+            <x-filament-tables::cell tag="th" colspan="{{ count($report->getHeaders()) }}" class="text-left">
8
                 <div class="px-3 py-3.5">
8
                 <div class="px-3 py-3.5">
9
                     @foreach ($category->header as $headerRow)
9
                     @foreach ($category->header as $headerRow)
10
                         <div
10
                         <div
11
-                            class="text-sm {{ $loop->first ? 'font-semibold text-gray-950 dark:text-white' : 'text-gray-500 dark:text-white/50' }}">
11
+                            class="text-sm {{ $loop->first ? 'font-semibold text-gray-950 dark:text-white' : 'font-normal text-gray-500 dark:text-white/50' }}">
12
                             @foreach ($headerRow as $headerValue)
12
                             @foreach ($headerRow as $headerValue)
13
                                 @if (!empty($headerValue))
13
                                 @if (!empty($headerValue))
14
                                     {{ $headerValue }}
14
                                     {{ $headerValue }}

+ 11
- 35
resources/views/components/company/tables/reports/balance-sheet-summary.blade.php 查看文件

1
 <table class="w-full table-auto divide-y divide-gray-200 dark:divide-white/5">
1
 <table class="w-full table-auto divide-y divide-gray-200 dark:divide-white/5">
2
-    <thead class="divide-y divide-gray-200 dark:divide-white/5">
3
-    <tr class="bg-gray-50 dark:bg-white/5">
4
-        <th class="px-3 py-3.5 sm:first-of-type:ps-6 sm:last-of-type:pe-6 text-left">
5
-            <span class="text-sm font-semibold leading-6 text-gray-950 dark:text-white">
6
-                Accounts
7
-            </span>
8
-        </th>
9
-        <th class="px-3 py-3.5 sm:first-of-type:ps-6 sm:last-of-type:pe-6 text-right">
10
-            <span class="text-sm font-semibold leading-6 text-gray-950 dark:text-white">
11
-                Amount
12
-            </span>
13
-        </th>
14
-    </tr>
15
-    </thead>
2
+    <x-company.tables.header :headers="$report->getSummaryHeaders()" :alignment-class="[$report, 'getAlignmentClass']"/>
16
     @foreach($report->getSummaryCategories() as $accountCategory)
3
     @foreach($report->getSummaryCategories() as $accountCategory)
17
         <tbody class="divide-y divide-gray-200 whitespace-nowrap dark:divide-white/5">
4
         <tbody class="divide-y divide-gray-200 whitespace-nowrap dark:divide-white/5">
18
-        <tr class="bg-gray-50 dark:bg-white/5">
19
-            @foreach($accountCategory->header as $accountCategoryHeaderIndex => $accountCategoryHeaderCell)
20
-                <th class="px-3 py-3.5 sm:first-of-type:ps-6 sm:last-of-type:pe-6 {{ $accountCategoryHeaderIndex === 0 ? 'text-left' : 'text-right' }}">
21
-                    <span class="text-sm font-semibold leading-6 text-gray-950 dark:text-white">
22
-                        {{ $accountCategoryHeaderCell }}
23
-                    </span>
24
-                </th>
25
-            @endforeach
26
-        </tr>
5
+        <x-company.tables.category-header :category-headers="$accountCategory->header"
6
+                                          :alignment-class="[$report, 'getAlignmentClass']"/>
27
         @foreach($accountCategory->types as $accountType)
7
         @foreach($accountCategory->types as $accountType)
28
             <tr>
8
             <tr>
29
                 @foreach($accountType->summary as $accountTypeSummaryIndex => $accountTypeSummaryCell)
9
                 @foreach($accountType->summary as $accountTypeSummaryIndex => $accountTypeSummaryCell)
30
-                    <x-filament-tables::cell
31
-                        class="{{ $accountTypeSummaryIndex === 0 ? 'text-left' : 'text-right' }} ps-8">
32
-                        <div class="px-3 py-4 text-sm leading-6 text-gray-950 dark:text-white">
33
-                            {{ $accountTypeSummaryCell }}
34
-                        </div>
35
-                    </x-filament-tables::cell>
10
+                    <x-company.tables.cell :alignment-class="$report->getAlignmentClass($accountTypeSummaryIndex)">
11
+                        {{ $accountTypeSummaryCell }}
12
+                    </x-company.tables.cell>
36
                 @endforeach
13
                 @endforeach
37
             </tr>
14
             </tr>
38
         @endforeach
15
         @endforeach
39
         <tr>
16
         <tr>
40
             @foreach($accountCategory->summary as $accountCategorySummaryIndex => $accountCategorySummaryCell)
17
             @foreach($accountCategory->summary as $accountCategorySummaryIndex => $accountCategorySummaryCell)
41
-                <x-filament-tables::cell class="{{ $accountCategorySummaryIndex === 0 ? 'text-left' : 'text-right' }}">
42
-                    <div class="px-3 py-4 text-sm leading-6 font-semibold text-gray-950 dark:text-white">
43
-                        {{ $accountCategorySummaryCell }}
44
-                    </div>
45
-                </x-filament-tables::cell>
18
+                <x-company.tables.cell :alignment-class="$report->getAlignmentClass($accountCategorySummaryIndex)"
19
+                                       bold="true">
20
+                    {{ $accountCategorySummaryCell }}
21
+                </x-company.tables.cell>
46
             @endforeach
22
             @endforeach
47
         </tr>
23
         </tr>
48
         <tr>
24
         <tr>
49
-            <td colspan="2">
25
+            <td colspan="{{ count($report->getSummaryHeaders()) }}">
50
                 <div class="min-h-12"></div>
26
                 <div class="min-h-12"></div>
51
             </td>
27
             </td>
52
         </tr>
28
         </tr>

+ 8
- 34
resources/views/components/company/tables/reports/income-statement-summary.blade.php 查看文件

1
 <table class="w-full table-auto divide-y divide-gray-200 dark:divide-white/5">
1
 <table class="w-full table-auto divide-y divide-gray-200 dark:divide-white/5">
2
-    <thead class="divide-y divide-gray-200 dark:divide-white/5">
3
-    <tr class="bg-gray-50 dark:bg-white/5">
4
-        <th class="px-3 py-3.5 sm:first-of-type:ps-6 sm:last-of-type:pe-6 text-left">
5
-            <span class="text-sm font-semibold leading-6 text-gray-950 dark:text-white">
6
-                Accounts
7
-            </span>
8
-        </th>
9
-        <th class="px-3 py-3.5 sm:first-of-type:ps-6 sm:last-of-type:pe-6 text-right">
10
-            <span class="text-sm font-semibold leading-6 text-gray-950 dark:text-white">
11
-                Amount
12
-            </span>
13
-        </th>
14
-    </tr>
15
-    </thead>
2
+    <x-company.tables.header :headers="$report->getSummaryHeaders()" :alignment-class="[$report, 'getAlignmentClass']"/>
16
     @foreach($report->getSummaryCategories() as $accountCategory)
3
     @foreach($report->getSummaryCategories() as $accountCategory)
17
         <tbody class="divide-y divide-gray-200 whitespace-nowrap dark:divide-white/5">
4
         <tbody class="divide-y divide-gray-200 whitespace-nowrap dark:divide-white/5">
18
         <tr>
5
         <tr>
19
             @foreach($accountCategory->summary as $accountCategorySummaryIndex => $accountCategorySummaryCell)
6
             @foreach($accountCategory->summary as $accountCategorySummaryIndex => $accountCategorySummaryCell)
20
-                <x-filament-tables::cell class="{{ $accountCategorySummaryIndex === 0 ? 'text-left' : 'text-right' }}">
21
-                    <div class="px-3 py-4 text-sm leading-6 font-normal text-gray-950 dark:text-white">
22
-                        {{ $accountCategorySummaryCell }}
23
-                    </div>
24
-                </x-filament-tables::cell>
7
+                <x-company.tables.cell :alignment-class="$report->getAlignmentClass($accountCategorySummaryIndex)">
8
+                    {{ $accountCategorySummaryCell }}
9
+                </x-company.tables.cell>
25
             @endforeach
10
             @endforeach
26
         </tr>
11
         </tr>
27
 
12
 
28
-        @if($accountCategory->header[0] === 'Cost of Goods Sold')
13
+        @if($accountCategory->header['account_name'] === 'Cost of Goods Sold')
29
             <tr class="bg-gray-50 dark:bg-white/5">
14
             <tr class="bg-gray-50 dark:bg-white/5">
30
                 @foreach($report->getGrossProfit() as $grossProfitIndex => $grossProfitCell)
15
                 @foreach($report->getGrossProfit() as $grossProfitIndex => $grossProfitCell)
31
-                    <x-filament-tables::cell class="{{ $grossProfitIndex === 0 ? 'text-left' : 'text-right' }}">
16
+                    <x-filament-tables::cell class="{{ $report->getAlignmentClass($grossProfitIndex) }}">
32
                         <div class="px-3 py-2 text-sm leading-6 font-semibold text-gray-950 dark:text-white">
17
                         <div class="px-3 py-2 text-sm leading-6 font-semibold text-gray-950 dark:text-white">
33
                             {{ $grossProfitCell }}
18
                             {{ $grossProfitCell }}
34
                         </div>
19
                         </div>
38
         @endif
23
         @endif
39
         </tbody>
24
         </tbody>
40
     @endforeach
25
     @endforeach
41
-    @if(! empty($report->getSummaryTotals()))
42
-        <tfoot>
43
-        <tr class="bg-gray-50 dark:bg-white/5">
44
-            @foreach($report->getSummaryTotals() as $index => $total)
45
-                <x-filament-tables::cell class="{{ $index === 0 ? 'text-left' : 'text-right' }}">
46
-                    <div class="px-3 py-2 text-sm leading-6 font-semibold text-gray-950 dark:text-white">
47
-                        {{ $total }}
48
-                    </div>
49
-                </x-filament-tables::cell>
50
-            @endforeach
51
-        </tr>
52
-        </tfoot>
53
-    @endif
26
+    <x-company.tables.footer :totals="$report->getSummaryOverallTotals()"
27
+                             :alignment-class="[$report, 'getAlignmentClass']"/>
54
 </table>
28
 </table>

正在加载...
取消
保存