Andrew Wallo 1 год назад
Родитель
Сommit
fe4633e07a

+ 0
- 2
app/Contracts/AccountHandler.php Просмотреть файл

@@ -21,7 +21,5 @@ interface AccountHandler
21 21
 
22 22
     public function getTotalBalanceForAllBankAccounts(string $startDate, string $endDate): Money;
23 23
 
24
-    public function getAccountCategoryOrder(): array;
25
-
26 24
     public function getEarliestTransactionDate(): string;
27 25
 }

+ 65
- 0
app/Enums/Accounting/AccountCategory.php Просмотреть файл

@@ -38,4 +38,69 @@ enum AccountCategory: string implements HasLabel
38 38
 
39 39
         return null;
40 40
     }
41
+
42
+    /**
43
+     * Determines if the account typically has a normal debit balance.
44
+     *
45
+     * In accounting, assets and expenses typically have a normal debit balance.
46
+     * A debit increases the balance of these accounts, while a credit decreases it.
47
+     */
48
+    public function isNormalDebitBalance(): bool
49
+    {
50
+        return in_array($this, [self::Asset, self::Expense], true);
51
+    }
52
+
53
+    /**
54
+     * Determines if the account typically has a normal credit balance.
55
+     *
56
+     * In accounting, liabilities, equity, and revenue typically have a normal credit balance.
57
+     * A credit increases the balance of these accounts, while a debit decreases it.
58
+     */
59
+    public function isNormalCreditBalance(): bool
60
+    {
61
+        return ! $this->isNormalDebitBalance();
62
+    }
63
+
64
+    /**
65
+     * Determines if the account is a nominal account.
66
+     *
67
+     * In accounting, nominal accounts are temporary accounts that are closed at the end of each accounting period,
68
+     * with their net balances transferred to Retained Earnings (a real account).
69
+     */
70
+    public function isNominal(): bool
71
+    {
72
+        return in_array($this, [self::Revenue, self::Expense], true);
73
+    }
74
+
75
+    /**
76
+     * Determines if the account is a real account.
77
+     *
78
+     * In accounting, real accounts are permanent accounts that retain their balances across accounting periods.
79
+     * They are not closed at the end of each accounting period.
80
+     */
81
+    public function isReal(): bool
82
+    {
83
+        return ! $this->isNominal();
84
+    }
85
+
86
+    public function getRelevantBalanceFields(): array
87
+    {
88
+        $commonFields = ['debit_balance', 'credit_balance', 'net_movement'];
89
+
90
+        return match ($this->isReal()) {
91
+            true => [...$commonFields, 'starting_balance', 'ending_balance'],
92
+            false => $commonFields,
93
+        };
94
+    }
95
+
96
+    public static function getOrderedCategories(): array
97
+    {
98
+        return [
99
+            self::Asset,
100
+            self::Liability,
101
+            self::Equity,
102
+            self::Revenue,
103
+            self::Expense,
104
+        ];
105
+    }
41 106
 }

+ 1
- 1
app/Filament/Company/Pages/Accounting/Transactions.php Просмотреть файл

@@ -224,7 +224,7 @@ class Transactions extends Page implements HasTable
224 224
                 Tables\Columns\TextColumn::make('posted_at')
225 225
                     ->label('Date')
226 226
                     ->sortable()
227
-                    ->localizeDate(),
227
+                    ->defaultDateFormat(),
228 228
                 Tables\Columns\TextColumn::make('description')
229 229
                     ->label('Description')
230 230
                     ->limit(30)

+ 1
- 1
app/Filament/Company/Pages/Reports/AccountTransactions.php Просмотреть файл

@@ -96,7 +96,7 @@ class AccountTransactions extends BaseReportPage
96 96
         $accounts = Account::query()
97 97
             ->get()
98 98
             ->groupBy(fn (Account $account) => $account->category->getPluralLabel())
99
-            ->map(fn (Collection $accounts, string $category) => $accounts->pluck('name', 'id'))
99
+            ->map(fn (Collection $accounts) => $accounts->pluck('name', 'id'))
100 100
             ->toArray();
101 101
 
102 102
         $allAccountsOption = [

+ 2
- 2
app/Filament/Company/Pages/Reports/BaseReportPage.php Просмотреть файл

@@ -238,7 +238,7 @@ abstract class BaseReportPage extends Page
238 238
     {
239 239
         return DatePicker::make('startDate')
240 240
             ->label('Start Date')
241
-            ->displayFormat('Y-m-d')
241
+            ->defaultDateFormat()
242 242
             ->afterStateUpdated(static function (Set $set) {
243 243
                 $set('dateRange', 'Custom');
244 244
             });
@@ -248,7 +248,7 @@ abstract class BaseReportPage extends Page
248 248
     {
249 249
         return DatePicker::make('endDate')
250 250
             ->label('End Date')
251
-            ->displayFormat('Y-m-d')
251
+            ->defaultDateFormat()
252 252
             ->afterStateUpdated(static function (Set $set) {
253 253
                 $set('dateRange', 'Custom');
254 254
             });

+ 23
- 1
app/Providers/MacroServiceProvider.php Просмотреть файл

@@ -11,6 +11,7 @@ use App\Utilities\Accounting\AccountCode;
11 11
 use App\Utilities\Currency\CurrencyAccessor;
12 12
 use BackedEnum;
13 13
 use Closure;
14
+use Filament\Forms\Components\DatePicker;
14 15
 use Filament\Forms\Components\Field;
15 16
 use Filament\Forms\Components\TextInput;
16 17
 use Filament\Tables\Columns\TextColumn;
@@ -54,7 +55,7 @@ class MacroServiceProvider extends ServiceProvider
54 55
             return $this;
55 56
         });
56 57
 
57
-        TextColumn::macro('localizeDate', function (): static {
58
+        TextColumn::macro('defaultDateFormat', function (): static {
58 59
             $localization = Localization::firstOrFail();
59 60
 
60 61
             $dateFormat = $localization->date_format->value ?? DateFormat::DEFAULT;
@@ -65,6 +66,18 @@ class MacroServiceProvider extends ServiceProvider
65 66
             return $this;
66 67
         });
67 68
 
69
+        DatePicker::macro('defaultDateFormat', function (): static {
70
+            $localization = Localization::firstOrFail();
71
+
72
+            $dateFormat = $localization->date_format->value ?? DateFormat::DEFAULT;
73
+            $timezone = $localization->timezone ?? Carbon::now()->timezoneName;
74
+
75
+            $this->displayFormat($dateFormat)
76
+                ->timezone($timezone);
77
+
78
+            return $this;
79
+        });
80
+
68 81
         TextColumn::macro('currency', function (string | Closure | null $currency = null, ?bool $convert = null): static {
69 82
             $this->formatStateUsing(static function (TextColumn $column, $state) use ($currency, $convert): ?string {
70 83
                 if (blank($state)) {
@@ -209,5 +222,14 @@ class MacroServiceProvider extends ServiceProvider
209 222
 
210 223
             return '';
211 224
         });
225
+
226
+        Carbon::macro('toDefaultDateFormat', function () {
227
+            $localization = Localization::firstOrFail();
228
+
229
+            $dateFormat = $localization->date_format->value ?? DateFormat::DEFAULT;
230
+            $timezone = $localization->timezone ?? Carbon::now()->timezoneName;
231
+
232
+            return $this->setTimezone($timezone)->format($dateFormat);
233
+        });
212 234
     }
213 235
 }

+ 84
- 117
app/Services/AccountService.php Просмотреть файл

@@ -11,8 +11,9 @@ use App\Repositories\Accounting\JournalEntryRepository;
11 11
 use App\Utilities\Currency\CurrencyAccessor;
12 12
 use App\ValueObjects\Money;
13 13
 use Closure;
14
-use Illuminate\Database\Query\Builder;
14
+use Illuminate\Database\Eloquent\Builder;
15 15
 use Illuminate\Database\Query\JoinClause;
16
+use Illuminate\Support\Carbon;
16 17
 use Illuminate\Support\Facades\DB;
17 18
 
18 19
 class AccountService implements AccountHandler
@@ -53,53 +54,11 @@ class AccountService implements AccountHandler
53 54
         return new Money($balances['starting_balance'], $account->currency_code);
54 55
     }
55 56
 
56
-    public function getStartingBalanceSubquery($startDate, $accountIds = null): Builder
57
+    public function getTransactionDetailsSubquery(string $startDate, string $endDate): Closure
57 58
     {
58
-        return DB::table('journal_entries')
59
-            ->select('journal_entries.account_id')
60
-            ->selectRaw('
61
-                COALESCE(SUM(
62
-                    CASE
63
-                        WHEN accounts.category IN ("asset", "expense") THEN
64
-                            CASE WHEN journal_entries.type = "debit" THEN journal_entries.amount ELSE -journal_entries.amount END
65
-                        ELSE
66
-                            CASE WHEN journal_entries.type = "credit" THEN journal_entries.amount ELSE -journal_entries.amount END
67
-                    END
68
-                ), 0) AS starting_balance
69
-            ')
70
-            ->join('transactions', 'transactions.id', '=', 'journal_entries.transaction_id')
71
-            ->join('accounts', 'accounts.id', '=', 'journal_entries.account_id')
72
-            ->where('transactions.posted_at', '<', $startDate)
73
-            ->groupBy('journal_entries.account_id');
74
-    }
75
-
76
-    public function getTotalDebitSubquery($startDate, $endDate, $accountIds = null): Builder
77
-    {
78
-        return DB::table('journal_entries')
79
-            ->select('journal_entries.account_id')
80
-            ->selectRaw('
81
-                COALESCE(SUM(CASE WHEN journal_entries.type = "debit" THEN journal_entries.amount ELSE 0 END), 0) as total_debit
82
-            ')
83
-            ->join('transactions', 'transactions.id', '=', 'journal_entries.transaction_id')
84
-            ->whereBetween('transactions.posted_at', [$startDate, $endDate])
85
-            ->groupBy('journal_entries.account_id');
86
-    }
59
+        $endOfDay = Carbon::parse($endDate)->endOfDay()->toDateTimeString();
87 60
 
88
-    public function getTotalCreditSubquery($startDate, $endDate, $accountIds = null): Builder
89
-    {
90
-        return DB::table('journal_entries')
91
-            ->select('journal_entries.account_id')
92
-            ->selectRaw('
93
-                COALESCE(SUM(CASE WHEN journal_entries.type = "credit" THEN journal_entries.amount ELSE 0 END), 0) as total_credit
94
-            ')
95
-            ->join('transactions', 'transactions.id', '=', 'journal_entries.transaction_id')
96
-            ->whereBetween('transactions.posted_at', [$startDate, $endDate])
97
-            ->groupBy('journal_entries.account_id');
98
-    }
99
-
100
-    public function getTransactionDetailsSubquery($startDate, $endDate): Closure
101
-    {
102
-        return function ($query) use ($startDate, $endDate) {
61
+        return static function ($query) use ($startDate, $endOfDay) {
103 62
             $query->select(
104 63
                 'journal_entries.id',
105 64
                 'journal_entries.account_id',
@@ -108,15 +67,17 @@ class AccountService implements AccountHandler
108 67
                 'journal_entries.amount',
109 68
                 DB::raw('journal_entries.amount * IF(journal_entries.type = "debit", 1, -1) AS signed_amount')
110 69
             )
111
-                ->whereBetween('transactions.posted_at', [$startDate, $endDate])
70
+                ->whereBetween('transactions.posted_at', [$startDate, $endOfDay])
112 71
                 ->join('transactions', 'transactions.id', '=', 'journal_entries.transaction_id')
113 72
                 ->orderBy('transactions.posted_at')
114 73
                 ->with('transaction:id,type,description,posted_at');
115 74
         };
116 75
     }
117 76
 
118
-    public function getAccountBalances(string $startDate, string $endDate, array $accountIds = []): \Illuminate\Database\Eloquent\Builder
77
+    public function getAccountBalances(string $startDate, string $endDate, array $accountIds = []): Builder
119 78
     {
79
+        $endOfDay = Carbon::parse($endDate)->endOfDay()->toDateTimeString();
80
+
120 81
         $query = Account::query()
121 82
             ->select([
122 83
                 'accounts.id',
@@ -126,32 +87,89 @@ class AccountService implements AccountHandler
126 87
                 'accounts.currency_code',
127 88
                 'accounts.code',
128 89
             ])
129
-            ->leftJoinSub($this->getStartingBalanceSubquery($startDate), 'starting_balance', function (JoinClause $join) {
130
-                $join->on('accounts.id', '=', 'starting_balance.account_id');
131
-            })
132
-            ->leftJoinSub($this->getTotalDebitSubquery($startDate, $endDate), 'total_debit', function (JoinClause $join) {
133
-                $join->on('accounts.id', '=', 'total_debit.account_id');
134
-            })
135
-            ->leftJoinSub($this->getTotalCreditSubquery($startDate, $endDate), 'total_credit', function (JoinClause $join) {
136
-                $join->on('accounts.id', '=', 'total_credit.account_id');
137
-            })
138 90
             ->addSelect([
139
-                DB::raw('COALESCE(starting_balance.starting_balance, 0) as starting_balance'),
140
-                DB::raw('COALESCE(total_debit.total_debit, 0) as total_debit'),
141
-                DB::raw('COALESCE(total_credit.total_credit, 0) as total_credit'),
91
+                DB::raw("
92
+                    COALESCE(
93
+                        IF(accounts.category IN ('asset', 'expense'),
94
+                            SUM(IF(journal_entries.type = 'debit' AND transactions.posted_at < ?, journal_entries.amount, 0)) -
95
+                            SUM(IF(journal_entries.type = 'credit' AND transactions.posted_at < ?, journal_entries.amount, 0)),
96
+                            SUM(IF(journal_entries.type = 'credit' AND transactions.posted_at < ?, journal_entries.amount, 0)) -
97
+                            SUM(IF(journal_entries.type = 'debit' AND transactions.posted_at < ?, journal_entries.amount, 0))
98
+                        ), 0
99
+                    ) AS starting_balance
100
+                "),
101
+                DB::raw("
102
+                    COALESCE(SUM(
103
+                        IF(journal_entries.type = 'debit' AND transactions.posted_at BETWEEN ? AND ?, journal_entries.amount, 0)
104
+                    ), 0) AS total_debit
105
+                "),
106
+                DB::raw("
107
+                    COALESCE(SUM(
108
+                        IF(journal_entries.type = 'credit' AND transactions.posted_at BETWEEN ? AND ?, journal_entries.amount, 0)
109
+                    ), 0) AS total_credit
110
+                "),
142 111
             ])
143
-            ->with(['subtype:id,name'])
144
-            ->whereHas('journalEntries.transaction', function ($query) use ($startDate, $endDate) {
145
-                $query->whereBetween('posted_at', [$startDate, $endDate]);
146
-            });
112
+            ->join('journal_entries', 'journal_entries.account_id', '=', 'accounts.id')
113
+            ->join('transactions', function (JoinClause $join) use ($endOfDay) {
114
+                $join->on('transactions.id', '=', 'journal_entries.transaction_id')
115
+                    ->where('transactions.posted_at', '<=', $endOfDay);
116
+            })
117
+            ->groupBy('accounts.id')
118
+            ->with(['subtype:id,name']);
147 119
 
148 120
         if (! empty($accountIds)) {
149 121
             $query->whereIn('accounts.id', $accountIds);
150 122
         }
151 123
 
124
+        $query->addBinding([$startDate, $startDate, $startDate, $startDate, $startDate, $endOfDay, $startDate, $endOfDay], 'select');
125
+
152 126
         return $query;
153 127
     }
154 128
 
129
+    public function getTotalBalanceForAllBankAccounts(string $startDate, string $endDate): Money
130
+    {
131
+        $endOfDay = Carbon::parse($endDate)->endOfDay()->toDateTimeString();
132
+
133
+        $accountIds = Account::whereHas('bankAccount')
134
+            ->pluck('id')
135
+            ->toArray();
136
+
137
+        if (empty($accountIds)) {
138
+            return new Money(0, CurrencyAccessor::getDefaultCurrency());
139
+        }
140
+
141
+        $result = DB::table('journal_entries')
142
+            ->join('transactions', function (JoinClause $join) use ($endOfDay) {
143
+                $join->on('transactions.id', '=', 'journal_entries.transaction_id')
144
+                    ->where('transactions.posted_at', '<=', $endOfDay);
145
+            })
146
+            ->whereIn('journal_entries.account_id', $accountIds)
147
+            ->selectRaw('
148
+            SUM(CASE
149
+                WHEN transactions.posted_at < ? AND journal_entries.type = "debit" THEN journal_entries.amount
150
+                WHEN transactions.posted_at < ? AND journal_entries.type = "credit" THEN -journal_entries.amount
151
+                ELSE 0
152
+            END) AS totalStartingBalance,
153
+            SUM(CASE
154
+                WHEN transactions.posted_at BETWEEN ? AND ? AND journal_entries.type = "debit" THEN journal_entries.amount
155
+                WHEN transactions.posted_at BETWEEN ? AND ? AND journal_entries.type = "credit" THEN -journal_entries.amount
156
+                ELSE 0
157
+            END) AS totalNetMovement
158
+        ', [
159
+                $startDate,
160
+                $startDate,
161
+                $startDate,
162
+                $endOfDay,
163
+                $startDate,
164
+                $endOfDay,
165
+            ])
166
+            ->first();
167
+
168
+        $totalBalance = $result->totalStartingBalance + $result->totalNetMovement;
169
+
170
+        return new Money($totalBalance, CurrencyAccessor::getDefaultCurrency());
171
+    }
172
+
155 173
     public function getEndingBalance(Account $account, string $startDate, string $endDate): ?Money
156 174
     {
157 175
         $calculatedBalances = $this->calculateBalances($account, $startDate, $endDate);
@@ -175,7 +193,7 @@ class AccountService implements AccountHandler
175 193
         })
176 194
             ->where('type', 'credit')
177 195
             ->whereHas('transaction', static function ($query) use ($startDate) {
178
-                $query->where('posted_at', '<=', $startDate);
196
+                $query->where('posted_at', '<', $startDate);
179 197
             })
180 198
             ->sum('amount');
181 199
 
@@ -184,7 +202,7 @@ class AccountService implements AccountHandler
184 202
         })
185 203
             ->where('type', 'debit')
186 204
             ->whereHas('transaction', static function ($query) use ($startDate) {
187
-                $query->where('posted_at', '<=', $startDate);
205
+                $query->where('posted_at', '<', $startDate);
188 206
             })
189 207
             ->sum('amount');
190 208
 
@@ -251,57 +269,6 @@ class AccountService implements AccountHandler
251 269
         return array_filter($balances, static fn ($value) => $value !== null);
252 270
     }
253 271
 
254
-    public function getTotalBalanceForAllBankAccounts(string $startDate, string $endDate): Money
255
-    {
256
-        $accountIds = Account::whereHas('bankAccount')
257
-            ->pluck('id')
258
-            ->toArray();
259
-
260
-        if (empty($accountIds)) {
261
-            return new Money(0, CurrencyAccessor::getDefaultCurrency());
262
-        }
263
-
264
-        $result = DB::table('journal_entries')
265
-            ->join('transactions', 'journal_entries.transaction_id', '=', 'transactions.id')
266
-            ->whereIn('journal_entries.account_id', $accountIds)
267
-            ->where('transactions.posted_at', '<=', $endDate)
268
-            ->selectRaw('
269
-            SUM(CASE
270
-                WHEN transactions.posted_at <= ? AND journal_entries.type = "debit" THEN journal_entries.amount
271
-                WHEN transactions.posted_at <= ? AND journal_entries.type = "credit" THEN -journal_entries.amount
272
-                ELSE 0
273
-            END) AS totalStartingBalance,
274
-            SUM(CASE
275
-                WHEN transactions.posted_at BETWEEN ? AND ? AND journal_entries.type = "debit" THEN journal_entries.amount
276
-                WHEN transactions.posted_at BETWEEN ? AND ? AND journal_entries.type = "credit" THEN -journal_entries.amount
277
-                ELSE 0
278
-            END) AS totalNetMovement
279
-        ', [
280
-                $startDate,
281
-                $startDate,
282
-                $startDate,
283
-                $endDate,
284
-                $startDate,
285
-                $endDate,
286
-            ])
287
-            ->first();
288
-
289
-        $totalBalance = $result->totalStartingBalance + $result->totalNetMovement;
290
-
291
-        return new Money($totalBalance, CurrencyAccessor::getDefaultCurrency());
292
-    }
293
-
294
-    public function getAccountCategoryOrder(): array
295
-    {
296
-        return [
297
-            AccountCategory::Asset->getPluralLabel(),
298
-            AccountCategory::Liability->getPluralLabel(),
299
-            AccountCategory::Equity->getPluralLabel(),
300
-            AccountCategory::Revenue->getPluralLabel(),
301
-            AccountCategory::Expense->getPluralLabel(),
302
-        ];
303
-    }
304
-
305 272
     public function getEarliestTransactionDate(): string
306 273
     {
307 274
         $earliestDate = Transaction::oldest('posted_at')

+ 71
- 139
app/Services/ReportService.php Просмотреть файл

@@ -8,11 +8,9 @@ use App\DTO\AccountDTO;
8 8
 use App\DTO\AccountTransactionDTO;
9 9
 use App\DTO\ReportDTO;
10 10
 use App\Enums\Accounting\AccountCategory;
11
-use App\Enums\Accounting\JournalEntryType;
12 11
 use App\Models\Accounting\Account;
13 12
 use App\Support\Column;
14 13
 use App\Utilities\Currency\CurrencyAccessor;
15
-use Illuminate\Support\Collection;
16 14
 
17 15
 class ReportService
18 16
 {
@@ -37,59 +35,36 @@ class ReportService
37 35
         );
38 36
     }
39 37
 
40
-    private function filterBalances(array $balances, array $fields): array
41
-    {
42
-        return array_filter($balances, static fn ($key) => in_array($key, $fields, true), ARRAY_FILTER_USE_KEY);
43
-    }
44
-
45
-    private function getCategoryGroupedAccounts(array $allCategories): Collection
46
-    {
47
-        return Account::whereHas('journalEntries')
48
-            ->select(['id', 'name', 'currency_code', 'category', 'code'])
49
-            ->get()
50
-            ->groupBy(fn (Account $account) => $account->category->getPluralLabel())
51
-            ->sortBy(static fn (Collection $groupedAccounts, string $key) => array_search($key, $allCategories, true));
52
-    }
53
-
54 38
     public function buildAccountBalanceReport(string $startDate, string $endDate, array $columns = []): ReportDTO
55 39
     {
56
-        $allCategories = $this->accountService->getAccountCategoryOrder();
57
-
58
-        $accountIds = Account::whereHas('journalEntries')->pluck('id')->toArray();
59
-
60
-        $accounts = $this->accountService->getAccountBalances($startDate, $endDate, $accountIds)->get();
40
+        $orderedCategories = AccountCategory::getOrderedCategories();
61 41
 
62
-        $balanceFields = ['starting_balance', 'debit_balance', 'credit_balance', 'net_movement', 'ending_balance'];
42
+        $accounts = $this->accountService->getAccountBalances($startDate, $endDate)->get();
63 43
 
64 44
         $columnNameKeys = array_map(fn (Column $column) => $column->getName(), $columns);
65 45
 
66
-        $updatedBalanceFields = array_filter($balanceFields, fn (string $balanceField) => in_array($balanceField, $columnNameKeys, true));
67
-
68 46
         $accountCategories = [];
69
-        $reportTotalBalances = array_fill_keys($updatedBalanceFields, 0);
47
+        $reportTotalBalances = [];
48
+
49
+        foreach ($orderedCategories as $category) {
50
+            $accountsInCategory = $accounts->where('category', $category)
51
+                ->sortBy('code', SORT_NATURAL);
70 52
 
71
-        foreach ($allCategories as $categoryPluralName) {
72
-            $categoryName = AccountCategory::fromPluralLabel($categoryPluralName);
73
-            $accountsInCategory = $accounts->where('category', $categoryName)->keyBy('id');
74
-            $categorySummaryBalances = array_fill_keys($updatedBalanceFields, 0);
53
+            $relevantFields = array_intersect($category->getRelevantBalanceFields(), $columnNameKeys);
54
+
55
+            $categorySummaryBalances = array_fill_keys($relevantFields, 0);
75 56
 
76 57
             $categoryAccounts = [];
77 58
 
59
+            /** @var Account $account */
78 60
             foreach ($accountsInCategory as $account) {
79
-                $accountBalances = $this->calculateAccountBalances($account, $categoryName);
61
+                $accountBalances = $this->calculateAccountBalances($account, $category);
80 62
 
81
-                if ($this->hasZeroBalanceSum($accountBalances)) {
82
-                    continue;
63
+                foreach ($relevantFields as $field) {
64
+                    $categorySummaryBalances[$field] += $accountBalances[$field];
83 65
                 }
84 66
 
85
-                foreach ($accountBalances as $accountBalanceType => $accountBalance) {
86
-                    if (array_key_exists($accountBalanceType, $categorySummaryBalances)) {
87
-                        $categorySummaryBalances[$accountBalanceType] += $accountBalance;
88
-                    }
89
-                }
90
-
91
-                $filteredAccountBalances = $this->filterBalances($accountBalances, $updatedBalanceFields);
92
-                $formattedAccountBalances = $this->formatBalances($filteredAccountBalances);
67
+                $formattedAccountBalances = $this->formatBalances($accountBalances);
93 68
 
94 69
                 $categoryAccounts[] = new AccountDTO(
95 70
                     $account->name,
@@ -99,18 +74,13 @@ class ReportService
99 74
                 );
100 75
             }
101 76
 
102
-            $this->adjustAccountBalanceCategoryFields($categoryName, $categorySummaryBalances);
103
-
104
-            foreach ($updatedBalanceFields as $field) {
105
-                if (array_key_exists($field, $categorySummaryBalances)) {
106
-                    $reportTotalBalances[$field] += $categorySummaryBalances[$field];
107
-                }
77
+            foreach ($relevantFields as $field) {
78
+                $reportTotalBalances[$field] = ($reportTotalBalances[$field] ?? 0) + $categorySummaryBalances[$field];
108 79
             }
109 80
 
110
-            $filteredCategorySummaryBalances = $this->filterBalances($categorySummaryBalances, $updatedBalanceFields);
111
-            $formattedCategorySummaryBalances = $this->formatBalances($filteredCategorySummaryBalances);
81
+            $formattedCategorySummaryBalances = $this->formatBalances($categorySummaryBalances);
112 82
 
113
-            $accountCategories[$categoryPluralName] = new AccountCategoryDTO(
83
+            $accountCategories[$category->getPluralLabel()] = new AccountCategoryDTO(
114 84
                 $categoryAccounts,
115 85
                 $formattedCategorySummaryBalances,
116 86
             );
@@ -128,32 +98,20 @@ class ReportService
128 98
             'credit_balance' => $account->total_credit ?? 0,
129 99
         ];
130 100
 
131
-        if (in_array($category, [AccountCategory::Liability, AccountCategory::Equity, AccountCategory::Revenue])) {
132
-            $balances['net_movement'] = $balances['credit_balance'] - $balances['debit_balance'];
133
-        } else {
101
+        if ($category->isNormalDebitBalance()) {
134 102
             $balances['net_movement'] = $balances['debit_balance'] - $balances['credit_balance'];
103
+        } else {
104
+            $balances['net_movement'] = $balances['credit_balance'] - $balances['debit_balance'];
135 105
         }
136 106
 
137
-        if (! in_array($category, [AccountCategory::Expense, AccountCategory::Revenue], true)) {
107
+        if ($category->isReal()) {
138 108
             $balances['starting_balance'] = $account->starting_balance ?? 0;
139
-            $balances['ending_balance'] = $balances['starting_balance'] + $balances['credit_balance'] - $balances['debit_balance'];
109
+            $balances['ending_balance'] = $balances['starting_balance'] + $balances['net_movement'];
140 110
         }
141 111
 
142 112
         return $balances;
143 113
     }
144 114
 
145
-    private function adjustAccountBalanceCategoryFields(AccountCategory $category, array &$categorySummaryBalances): void
146
-    {
147
-        if (in_array($category, [AccountCategory::Expense, AccountCategory::Revenue], true)) {
148
-            unset($categorySummaryBalances['starting_balance'], $categorySummaryBalances['ending_balance']);
149
-        }
150
-    }
151
-
152
-    private function hasZeroBalanceSum(array $balances): bool
153
-    {
154
-        return array_sum(array_map('abs', $balances)) === 0;
155
-    }
156
-
157 115
     public function buildAccountTransactionsReport(string $startDate, string $endDate, ?array $columns = null, ?string $accountId = 'all'): ReportDTO
158 116
     {
159 117
         $columns ??= [];
@@ -189,19 +147,20 @@ class ReportService
189 147
                 $transaction = $journalEntry->transaction;
190 148
                 $signedAmount = $journalEntry->signed_amount;
191 149
 
192
-                // Adjust balance based on account category
193
-                if (in_array($account->category, [AccountCategory::Asset, AccountCategory::Expense])) {
150
+                if ($account->category->isNormalDebitBalance()) {
194 151
                     $currentBalance += $signedAmount;
195 152
                 } else {
196 153
                     $currentBalance -= $signedAmount;
197 154
                 }
198 155
 
156
+                $formattedAmount = money(abs($signedAmount), $defaultCurrency)->format();
157
+
199 158
                 $accountTransactions[] = new AccountTransactionDTO(
200 159
                     id: $transaction->id,
201
-                    date: $transaction->posted_at->format('Y-m-d'),
202
-                    description: $transaction->description ?? '',
203
-                    debit: $journalEntry->type === JournalEntryType::Debit ? money(abs($signedAmount), $defaultCurrency)->format() : '',
204
-                    credit: $journalEntry->type === JournalEntryType::Credit ? money(abs($signedAmount), $defaultCurrency)->format() : '',
160
+                    date: $transaction->posted_at->toDefaultDateFormat(),
161
+                    description: $transaction->description ?? 'Add a description',
162
+                    debit: $journalEntry->type->isDebit() ? $formattedAmount : '',
163
+                    credit: $journalEntry->type->isCredit() ? $formattedAmount : '',
205 164
                     balance: money($currentBalance, $defaultCurrency)->format(),
206 165
                     type: $transaction->type,
207 166
                     tableAction: $transaction->type->isJournal() ? 'updateJournalTransaction' : 'updateTransaction'
@@ -242,37 +201,38 @@ class ReportService
242 201
         return new ReportDTO(categories: $reportCategories, fields: $columns);
243 202
     }
244 203
 
245
-    private function buildReport(array $allCategories, Collection $categoryGroupedAccounts, callable $balanceCalculator, array $balanceFields, array $allFields, ?callable $initializeCategoryBalances = null, bool $includeRetainedEarnings = false, ?string $startDate = null): ReportDTO
204
+    public function buildTrialBalanceReport(string $startDate, string $endDate, array $columns = []): ReportDTO
246 205
     {
206
+        $orderedCategories = AccountCategory::getOrderedCategories();
207
+
208
+        $accounts = $this->accountService->getAccountBalances($startDate, $endDate)->get();
209
+
210
+        $balanceFields = ['debit_balance', 'credit_balance'];
211
+
247 212
         $accountCategories = [];
248 213
         $reportTotalBalances = array_fill_keys($balanceFields, 0);
249 214
 
250
-        foreach ($allCategories as $categoryName) {
251
-            $accountsInCategory = $categoryGroupedAccounts[$categoryName] ?? collect();
252
-            $categorySummaryBalances = array_fill_keys($balanceFields, 0);
215
+        foreach ($orderedCategories as $category) {
216
+            $accountsInCategory = $accounts->where('category', $category)
217
+                ->sortBy('code', SORT_NATURAL);
253 218
 
254
-            if ($initializeCategoryBalances) {
255
-                $initializeCategoryBalances($categoryName, $categorySummaryBalances);
256
-            }
219
+            $categorySummaryBalances = array_fill_keys($balanceFields, 0);
257 220
 
258 221
             $categoryAccounts = [];
259 222
 
223
+            /** @var Account $account */
260 224
             foreach ($accountsInCategory as $account) {
261
-                /** @var Account $account */
262
-                $accountBalances = $balanceCalculator($account);
225
+                $accountBalances = $this->calculateAccountBalances($account, $category);
263 226
 
264
-                if (array_sum($accountBalances) === 0) {
265
-                    continue;
266
-                }
227
+                $endingBalance = $accountBalances['ending_balance'] ?? $accountBalances['net_movement'];
228
+
229
+                $trialBalance = $this->calculateTrialBalance($account->category, $endingBalance);
267 230
 
268
-                foreach ($accountBalances as $accountBalanceType => $accountBalance) {
269
-                    if (array_key_exists($accountBalanceType, $categorySummaryBalances)) {
270
-                        $categorySummaryBalances[$accountBalanceType] += $accountBalance;
271
-                    }
231
+                foreach ($trialBalance as $balanceType => $balance) {
232
+                    $categorySummaryBalances[$balanceType] += $balance;
272 233
                 }
273 234
 
274
-                $filteredAccountBalances = $this->filterBalances($accountBalances, $balanceFields);
275
-                $formattedAccountBalances = $this->formatBalances($filteredAccountBalances);
235
+                $formattedAccountBalances = $this->formatBalances($trialBalance);
276 236
 
277 237
                 $categoryAccounts[] = new AccountDTO(
278 238
                     $account->name,
@@ -282,39 +242,30 @@ class ReportService
282 242
                 );
283 243
             }
284 244
 
285
-            if ($includeRetainedEarnings && $categoryName === AccountCategory::Equity->getPluralLabel()) {
286
-                $retainedEarnings = $this->accountService->getRetainedEarnings($startDate);
287
-                $retainedEarningsAmount = $retainedEarnings->getAmount();
288
-
289
-                if ($retainedEarningsAmount >= 0) {
290
-                    $categorySummaryBalances['credit_balance'] += $retainedEarningsAmount;
291
-                    $categoryAccounts[] = new AccountDTO(
292
-                        'Retained Earnings',
293
-                        'RE',
294
-                        null,
295
-                        $this->formatBalances(['debit_balance' => 0, 'credit_balance' => $retainedEarningsAmount])
296
-                    );
297
-                } else {
298
-                    $categorySummaryBalances['debit_balance'] += abs($retainedEarningsAmount);
299
-                    $categoryAccounts[] = new AccountDTO(
300
-                        'Retained Earnings',
301
-                        'RE',
302
-                        null,
303
-                        $this->formatBalances(['debit_balance' => abs($retainedEarningsAmount), 'credit_balance' => 0])
304
-                    );
305
-                }
245
+            if ($category === AccountCategory::Equity) {
246
+                $retainedEarningsAmount = $this->accountService->getRetainedEarnings($startDate)->getAmount();
247
+                $isCredit = $retainedEarningsAmount >= 0;
248
+
249
+                $categorySummaryBalances[$isCredit ? 'credit_balance' : 'debit_balance'] += abs($retainedEarningsAmount);
250
+
251
+                $categoryAccounts[] = new AccountDTO(
252
+                    'Retained Earnings',
253
+                    'RE',
254
+                    null,
255
+                    $this->formatBalances([
256
+                        'debit_balance' => $isCredit ? 0 : abs($retainedEarningsAmount),
257
+                        'credit_balance' => $isCredit ? $retainedEarningsAmount : 0,
258
+                    ])
259
+                );
306 260
             }
307 261
 
308
-            foreach ($balanceFields as $field) {
309
-                if (array_key_exists($field, $categorySummaryBalances)) {
310
-                    $reportTotalBalances[$field] += $categorySummaryBalances[$field];
311
-                }
262
+            foreach ($categorySummaryBalances as $balanceType => $balance) {
263
+                $reportTotalBalances[$balanceType] += $balance;
312 264
             }
313 265
 
314
-            $filteredCategorySummaryBalances = $this->filterBalances($categorySummaryBalances, $balanceFields);
315
-            $formattedCategorySummaryBalances = $this->formatBalances($filteredCategorySummaryBalances);
266
+            $formattedCategorySummaryBalances = $this->formatBalances($categorySummaryBalances);
316 267
 
317
-            $accountCategories[$categoryName] = new AccountCategoryDTO(
268
+            $accountCategories[$category->getPluralLabel()] = new AccountCategoryDTO(
318 269
                 $categoryAccounts,
319 270
                 $formattedCategorySummaryBalances,
320 271
             );
@@ -322,31 +273,12 @@ class ReportService
322 273
 
323 274
         $formattedReportTotalBalances = $this->formatBalances($reportTotalBalances);
324 275
 
325
-        return new ReportDTO($accountCategories, $formattedReportTotalBalances, $allFields);
326
-    }
327
-
328
-    public function buildTrialBalanceReport(string $startDate, string $endDate, array $columns = []): ReportDTO
329
-    {
330
-        $allCategories = $this->accountService->getAccountCategoryOrder();
331
-
332
-        $categoryGroupedAccounts = $this->getCategoryGroupedAccounts($allCategories);
333
-
334
-        $balanceFields = ['debit_balance', 'credit_balance'];
335
-
336
-        return $this->buildReport($allCategories, $categoryGroupedAccounts, function (Account $account) use ($startDate, $endDate) {
337
-            $endingBalance = $this->accountService->getEndingBalance($account, $startDate, $endDate)?->getAmount() ?? 0;
338
-
339
-            if ($endingBalance === 0) {
340
-                return [];
341
-            }
342
-
343
-            return $this->calculateTrialBalance($account->category, $endingBalance);
344
-        }, $balanceFields, $columns, null, true, $startDate);
276
+        return new ReportDTO($accountCategories, $formattedReportTotalBalances, $columns);
345 277
     }
346 278
 
347 279
     private function calculateTrialBalance(AccountCategory $category, int $endingBalance): array
348 280
     {
349
-        if (in_array($category, [AccountCategory::Asset, AccountCategory::Expense], true)) {
281
+        if ($category->isNormalDebitBalance()) {
350 282
             if ($endingBalance >= 0) {
351 283
                 return ['debit_balance' => $endingBalance, 'credit_balance' => 0];
352 284
             }

+ 107
- 296
composer.lock Просмотреть файл

@@ -497,16 +497,16 @@
497 497
         },
498 498
         {
499 499
             "name": "aws/aws-sdk-php",
500
-            "version": "3.319.1",
500
+            "version": "3.320.2",
501 501
             "source": {
502 502
                 "type": "git",
503 503
                 "url": "https://github.com/aws/aws-sdk-php.git",
504
-                "reference": "78d9f8823a5796e9188a4ddcd9ef2374e47d8b7f"
504
+                "reference": "dbae075b861316237d63418715f8bf4bfdd9d33d"
505 505
             },
506 506
             "dist": {
507 507
                 "type": "zip",
508
-                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/78d9f8823a5796e9188a4ddcd9ef2374e47d8b7f",
509
-                "reference": "78d9f8823a5796e9188a4ddcd9ef2374e47d8b7f",
508
+                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/dbae075b861316237d63418715f8bf4bfdd9d33d",
509
+                "reference": "dbae075b861316237d63418715f8bf4bfdd9d33d",
510 510
                 "shasum": ""
511 511
             },
512 512
             "require": {
@@ -589,9 +589,9 @@
589 589
             "support": {
590 590
                 "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
591 591
                 "issues": "https://github.com/aws/aws-sdk-php/issues",
592
-                "source": "https://github.com/aws/aws-sdk-php/tree/3.319.1"
592
+                "source": "https://github.com/aws/aws-sdk-php/tree/3.320.2"
593 593
             },
594
-            "time": "2024-08-08T18:05:03+00:00"
594
+            "time": "2024-08-16T18:06:17+00:00"
595 595
         },
596 596
         {
597 597
             "name": "aws/aws-sdk-php-laravel",
@@ -897,16 +897,16 @@
897 897
         },
898 898
         {
899 899
             "name": "blade-ui-kit/blade-icons",
900
-            "version": "1.7.0",
900
+            "version": "1.7.1",
901 901
             "source": {
902 902
                 "type": "git",
903 903
                 "url": "https://github.com/blade-ui-kit/blade-icons.git",
904
-                "reference": "74275f44c71e815b85bf7cea66e3bf98c57fb7e4"
904
+                "reference": "8f787baf09d88cdfd6ec4dbaba11ebfa885f0595"
905 905
             },
906 906
             "dist": {
907 907
                 "type": "zip",
908
-                "url": "https://api.github.com/repos/blade-ui-kit/blade-icons/zipball/74275f44c71e815b85bf7cea66e3bf98c57fb7e4",
909
-                "reference": "74275f44c71e815b85bf7cea66e3bf98c57fb7e4",
908
+                "url": "https://api.github.com/repos/blade-ui-kit/blade-icons/zipball/8f787baf09d88cdfd6ec4dbaba11ebfa885f0595",
909
+                "reference": "8f787baf09d88cdfd6ec4dbaba11ebfa885f0595",
910 910
                 "shasum": ""
911 911
             },
912 912
             "require": {
@@ -974,7 +974,7 @@
974 974
                     "type": "paypal"
975 975
                 }
976 976
             ],
977
-            "time": "2024-07-29T21:49:30+00:00"
977
+            "time": "2024-08-14T14:25:11+00:00"
978 978
         },
979 979
         {
980 980
             "name": "brick/math",
@@ -1038,26 +1038,26 @@
1038 1038
         },
1039 1039
         {
1040 1040
             "name": "carbonphp/carbon-doctrine-types",
1041
-            "version": "2.1.0",
1041
+            "version": "3.2.0",
1042 1042
             "source": {
1043 1043
                 "type": "git",
1044 1044
                 "url": "https://github.com/CarbonPHP/carbon-doctrine-types.git",
1045
-                "reference": "99f76ffa36cce3b70a4a6abce41dba15ca2e84cb"
1045
+                "reference": "18ba5ddfec8976260ead6e866180bd5d2f71aa1d"
1046 1046
             },
1047 1047
             "dist": {
1048 1048
                 "type": "zip",
1049
-                "url": "https://api.github.com/repos/CarbonPHP/carbon-doctrine-types/zipball/99f76ffa36cce3b70a4a6abce41dba15ca2e84cb",
1050
-                "reference": "99f76ffa36cce3b70a4a6abce41dba15ca2e84cb",
1049
+                "url": "https://api.github.com/repos/CarbonPHP/carbon-doctrine-types/zipball/18ba5ddfec8976260ead6e866180bd5d2f71aa1d",
1050
+                "reference": "18ba5ddfec8976260ead6e866180bd5d2f71aa1d",
1051 1051
                 "shasum": ""
1052 1052
             },
1053 1053
             "require": {
1054
-                "php": "^7.4 || ^8.0"
1054
+                "php": "^8.1"
1055 1055
             },
1056 1056
             "conflict": {
1057
-                "doctrine/dbal": "<3.7.0 || >=4.0.0"
1057
+                "doctrine/dbal": "<4.0.0 || >=5.0.0"
1058 1058
             },
1059 1059
             "require-dev": {
1060
-                "doctrine/dbal": "^3.7.0",
1060
+                "doctrine/dbal": "^4.0.0",
1061 1061
                 "nesbot/carbon": "^2.71.0 || ^3.0.0",
1062 1062
                 "phpunit/phpunit": "^10.3"
1063 1063
             },
@@ -1087,7 +1087,7 @@
1087 1087
             ],
1088 1088
             "support": {
1089 1089
                 "issues": "https://github.com/CarbonPHP/carbon-doctrine-types/issues",
1090
-                "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/2.1.0"
1090
+                "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/3.2.0"
1091 1091
             },
1092 1092
             "funding": [
1093 1093
                 {
@@ -1103,7 +1103,7 @@
1103 1103
                     "type": "tidelift"
1104 1104
                 }
1105 1105
             ],
1106
-            "time": "2023-12-11T17:09:12+00:00"
1106
+            "time": "2024-02-09T16:56:22+00:00"
1107 1107
         },
1108 1108
         {
1109 1109
             "name": "danharrin/date-format-converter",
@@ -1285,142 +1285,44 @@
1285 1285
             },
1286 1286
             "time": "2024-07-08T12:26:09+00:00"
1287 1287
         },
1288
-        {
1289
-            "name": "doctrine/cache",
1290
-            "version": "2.2.0",
1291
-            "source": {
1292
-                "type": "git",
1293
-                "url": "https://github.com/doctrine/cache.git",
1294
-                "reference": "1ca8f21980e770095a31456042471a57bc4c68fb"
1295
-            },
1296
-            "dist": {
1297
-                "type": "zip",
1298
-                "url": "https://api.github.com/repos/doctrine/cache/zipball/1ca8f21980e770095a31456042471a57bc4c68fb",
1299
-                "reference": "1ca8f21980e770095a31456042471a57bc4c68fb",
1300
-                "shasum": ""
1301
-            },
1302
-            "require": {
1303
-                "php": "~7.1 || ^8.0"
1304
-            },
1305
-            "conflict": {
1306
-                "doctrine/common": ">2.2,<2.4"
1307
-            },
1308
-            "require-dev": {
1309
-                "cache/integration-tests": "dev-master",
1310
-                "doctrine/coding-standard": "^9",
1311
-                "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
1312
-                "psr/cache": "^1.0 || ^2.0 || ^3.0",
1313
-                "symfony/cache": "^4.4 || ^5.4 || ^6",
1314
-                "symfony/var-exporter": "^4.4 || ^5.4 || ^6"
1315
-            },
1316
-            "type": "library",
1317
-            "autoload": {
1318
-                "psr-4": {
1319
-                    "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache"
1320
-                }
1321
-            },
1322
-            "notification-url": "https://packagist.org/downloads/",
1323
-            "license": [
1324
-                "MIT"
1325
-            ],
1326
-            "authors": [
1327
-                {
1328
-                    "name": "Guilherme Blanco",
1329
-                    "email": "guilhermeblanco@gmail.com"
1330
-                },
1331
-                {
1332
-                    "name": "Roman Borschel",
1333
-                    "email": "roman@code-factory.org"
1334
-                },
1335
-                {
1336
-                    "name": "Benjamin Eberlei",
1337
-                    "email": "kontakt@beberlei.de"
1338
-                },
1339
-                {
1340
-                    "name": "Jonathan Wage",
1341
-                    "email": "jonwage@gmail.com"
1342
-                },
1343
-                {
1344
-                    "name": "Johannes Schmitt",
1345
-                    "email": "schmittjoh@gmail.com"
1346
-                }
1347
-            ],
1348
-            "description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.",
1349
-            "homepage": "https://www.doctrine-project.org/projects/cache.html",
1350
-            "keywords": [
1351
-                "abstraction",
1352
-                "apcu",
1353
-                "cache",
1354
-                "caching",
1355
-                "couchdb",
1356
-                "memcached",
1357
-                "php",
1358
-                "redis",
1359
-                "xcache"
1360
-            ],
1361
-            "support": {
1362
-                "issues": "https://github.com/doctrine/cache/issues",
1363
-                "source": "https://github.com/doctrine/cache/tree/2.2.0"
1364
-            },
1365
-            "funding": [
1366
-                {
1367
-                    "url": "https://www.doctrine-project.org/sponsorship.html",
1368
-                    "type": "custom"
1369
-                },
1370
-                {
1371
-                    "url": "https://www.patreon.com/phpdoctrine",
1372
-                    "type": "patreon"
1373
-                },
1374
-                {
1375
-                    "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcache",
1376
-                    "type": "tidelift"
1377
-                }
1378
-            ],
1379
-            "time": "2022-05-20T20:07:39+00:00"
1380
-        },
1381 1288
         {
1382 1289
             "name": "doctrine/dbal",
1383
-            "version": "3.8.7",
1290
+            "version": "4.1.0",
1384 1291
             "source": {
1385 1292
                 "type": "git",
1386 1293
                 "url": "https://github.com/doctrine/dbal.git",
1387
-                "reference": "2093d670ca17f634f3c095ec10a20687eccebd99"
1294
+                "reference": "2377cd41609aa51bee822c8d207317a3f363a558"
1388 1295
             },
1389 1296
             "dist": {
1390 1297
                 "type": "zip",
1391
-                "url": "https://api.github.com/repos/doctrine/dbal/zipball/2093d670ca17f634f3c095ec10a20687eccebd99",
1392
-                "reference": "2093d670ca17f634f3c095ec10a20687eccebd99",
1298
+                "url": "https://api.github.com/repos/doctrine/dbal/zipball/2377cd41609aa51bee822c8d207317a3f363a558",
1299
+                "reference": "2377cd41609aa51bee822c8d207317a3f363a558",
1393 1300
                 "shasum": ""
1394 1301
             },
1395 1302
             "require": {
1396
-                "composer-runtime-api": "^2",
1397
-                "doctrine/cache": "^1.11|^2.0",
1398 1303
                 "doctrine/deprecations": "^0.5.3|^1",
1399
-                "doctrine/event-manager": "^1|^2",
1400
-                "php": "^7.4 || ^8.0",
1304
+                "php": "^8.1",
1401 1305
                 "psr/cache": "^1|^2|^3",
1402 1306
                 "psr/log": "^1|^2|^3"
1403 1307
             },
1404 1308
             "require-dev": {
1405 1309
                 "doctrine/coding-standard": "12.0.0",
1406 1310
                 "fig/log-test": "^1",
1407
-                "jetbrains/phpstorm-stubs": "2023.1",
1311
+                "jetbrains/phpstorm-stubs": "2023.2",
1408 1312
                 "phpstan/phpstan": "1.11.7",
1313
+                "phpstan/phpstan-phpunit": "1.4.0",
1409 1314
                 "phpstan/phpstan-strict-rules": "^1.6",
1410
-                "phpunit/phpunit": "9.6.20",
1411
-                "psalm/plugin-phpunit": "0.18.4",
1315
+                "phpunit/phpunit": "10.5.28",
1316
+                "psalm/plugin-phpunit": "0.19.0",
1412 1317
                 "slevomat/coding-standard": "8.13.1",
1413 1318
                 "squizlabs/php_codesniffer": "3.10.2",
1414
-                "symfony/cache": "^5.4|^6.0|^7.0",
1415
-                "symfony/console": "^4.4|^5.4|^6.0|^7.0",
1416
-                "vimeo/psalm": "4.30.0"
1319
+                "symfony/cache": "^6.3.8|^7.0",
1320
+                "symfony/console": "^5.4|^6.3|^7.0",
1321
+                "vimeo/psalm": "5.24.0"
1417 1322
             },
1418 1323
             "suggest": {
1419 1324
                 "symfony/console": "For helpful console commands such as SQL execution and import of files."
1420 1325
             },
1421
-            "bin": [
1422
-                "bin/doctrine-dbal"
1423
-            ],
1424 1326
             "type": "library",
1425 1327
             "autoload": {
1426 1328
                 "psr-4": {
@@ -1473,7 +1375,7 @@
1473 1375
             ],
1474 1376
             "support": {
1475 1377
                 "issues": "https://github.com/doctrine/dbal/issues",
1476
-                "source": "https://github.com/doctrine/dbal/tree/3.8.7"
1378
+                "source": "https://github.com/doctrine/dbal/tree/4.1.0"
1477 1379
             },
1478 1380
             "funding": [
1479 1381
                 {
@@ -1489,7 +1391,7 @@
1489 1391
                     "type": "tidelift"
1490 1392
                 }
1491 1393
             ],
1492
-            "time": "2024-08-07T11:57:25+00:00"
1394
+            "time": "2024-08-15T07:37:07+00:00"
1493 1395
         },
1494 1396
         {
1495 1397
             "name": "doctrine/deprecations",
@@ -1538,97 +1440,6 @@
1538 1440
             },
1539 1441
             "time": "2024-01-30T19:34:25+00:00"
1540 1442
         },
1541
-        {
1542
-            "name": "doctrine/event-manager",
1543
-            "version": "2.0.1",
1544
-            "source": {
1545
-                "type": "git",
1546
-                "url": "https://github.com/doctrine/event-manager.git",
1547
-                "reference": "b680156fa328f1dfd874fd48c7026c41570b9c6e"
1548
-            },
1549
-            "dist": {
1550
-                "type": "zip",
1551
-                "url": "https://api.github.com/repos/doctrine/event-manager/zipball/b680156fa328f1dfd874fd48c7026c41570b9c6e",
1552
-                "reference": "b680156fa328f1dfd874fd48c7026c41570b9c6e",
1553
-                "shasum": ""
1554
-            },
1555
-            "require": {
1556
-                "php": "^8.1"
1557
-            },
1558
-            "conflict": {
1559
-                "doctrine/common": "<2.9"
1560
-            },
1561
-            "require-dev": {
1562
-                "doctrine/coding-standard": "^12",
1563
-                "phpstan/phpstan": "^1.8.8",
1564
-                "phpunit/phpunit": "^10.5",
1565
-                "vimeo/psalm": "^5.24"
1566
-            },
1567
-            "type": "library",
1568
-            "autoload": {
1569
-                "psr-4": {
1570
-                    "Doctrine\\Common\\": "src"
1571
-                }
1572
-            },
1573
-            "notification-url": "https://packagist.org/downloads/",
1574
-            "license": [
1575
-                "MIT"
1576
-            ],
1577
-            "authors": [
1578
-                {
1579
-                    "name": "Guilherme Blanco",
1580
-                    "email": "guilhermeblanco@gmail.com"
1581
-                },
1582
-                {
1583
-                    "name": "Roman Borschel",
1584
-                    "email": "roman@code-factory.org"
1585
-                },
1586
-                {
1587
-                    "name": "Benjamin Eberlei",
1588
-                    "email": "kontakt@beberlei.de"
1589
-                },
1590
-                {
1591
-                    "name": "Jonathan Wage",
1592
-                    "email": "jonwage@gmail.com"
1593
-                },
1594
-                {
1595
-                    "name": "Johannes Schmitt",
1596
-                    "email": "schmittjoh@gmail.com"
1597
-                },
1598
-                {
1599
-                    "name": "Marco Pivetta",
1600
-                    "email": "ocramius@gmail.com"
1601
-                }
1602
-            ],
1603
-            "description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.",
1604
-            "homepage": "https://www.doctrine-project.org/projects/event-manager.html",
1605
-            "keywords": [
1606
-                "event",
1607
-                "event dispatcher",
1608
-                "event manager",
1609
-                "event system",
1610
-                "events"
1611
-            ],
1612
-            "support": {
1613
-                "issues": "https://github.com/doctrine/event-manager/issues",
1614
-                "source": "https://github.com/doctrine/event-manager/tree/2.0.1"
1615
-            },
1616
-            "funding": [
1617
-                {
1618
-                    "url": "https://www.doctrine-project.org/sponsorship.html",
1619
-                    "type": "custom"
1620
-                },
1621
-                {
1622
-                    "url": "https://www.patreon.com/phpdoctrine",
1623
-                    "type": "patreon"
1624
-                },
1625
-                {
1626
-                    "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fevent-manager",
1627
-                    "type": "tidelift"
1628
-                }
1629
-            ],
1630
-            "time": "2024-05-22T20:47:39+00:00"
1631
-        },
1632 1443
         {
1633 1444
             "name": "doctrine/inflector",
1634 1445
             "version": "2.0.10",
@@ -1927,16 +1738,16 @@
1927 1738
         },
1928 1739
         {
1929 1740
             "name": "filament/actions",
1930
-            "version": "v3.2.97",
1741
+            "version": "v3.2.102",
1931 1742
             "source": {
1932 1743
                 "type": "git",
1933 1744
                 "url": "https://github.com/filamentphp/actions.git",
1934
-                "reference": "aff18fda397dbf3e9f449f9a9360f3359b154c0e"
1745
+                "reference": "1ce746a4a75975f1844c175201f1f03443c48c95"
1935 1746
             },
1936 1747
             "dist": {
1937 1748
                 "type": "zip",
1938
-                "url": "https://api.github.com/repos/filamentphp/actions/zipball/aff18fda397dbf3e9f449f9a9360f3359b154c0e",
1939
-                "reference": "aff18fda397dbf3e9f449f9a9360f3359b154c0e",
1749
+                "url": "https://api.github.com/repos/filamentphp/actions/zipball/1ce746a4a75975f1844c175201f1f03443c48c95",
1750
+                "reference": "1ce746a4a75975f1844c175201f1f03443c48c95",
1940 1751
                 "shasum": ""
1941 1752
             },
1942 1753
             "require": {
@@ -1976,20 +1787,20 @@
1976 1787
                 "issues": "https://github.com/filamentphp/filament/issues",
1977 1788
                 "source": "https://github.com/filamentphp/filament"
1978 1789
             },
1979
-            "time": "2024-07-31T11:53:04+00:00"
1790
+            "time": "2024-08-14T16:52:38+00:00"
1980 1791
         },
1981 1792
         {
1982 1793
             "name": "filament/filament",
1983
-            "version": "v3.2.97",
1794
+            "version": "v3.2.102",
1984 1795
             "source": {
1985 1796
                 "type": "git",
1986 1797
                 "url": "https://github.com/filamentphp/panels.git",
1987
-                "reference": "9e0b750546a51fdbc67b1232f2399385587dcc9a"
1798
+                "reference": "99c703952af053e1ef22a4dd556eba589a574d87"
1988 1799
             },
1989 1800
             "dist": {
1990 1801
                 "type": "zip",
1991
-                "url": "https://api.github.com/repos/filamentphp/panels/zipball/9e0b750546a51fdbc67b1232f2399385587dcc9a",
1992
-                "reference": "9e0b750546a51fdbc67b1232f2399385587dcc9a",
1802
+                "url": "https://api.github.com/repos/filamentphp/panels/zipball/99c703952af053e1ef22a4dd556eba589a574d87",
1803
+                "reference": "99c703952af053e1ef22a4dd556eba589a574d87",
1993 1804
                 "shasum": ""
1994 1805
             },
1995 1806
             "require": {
@@ -2041,20 +1852,20 @@
2041 1852
                 "issues": "https://github.com/filamentphp/filament/issues",
2042 1853
                 "source": "https://github.com/filamentphp/filament"
2043 1854
             },
2044
-            "time": "2024-07-31T11:53:12+00:00"
1855
+            "time": "2024-08-14T16:52:48+00:00"
2045 1856
         },
2046 1857
         {
2047 1858
             "name": "filament/forms",
2048
-            "version": "v3.2.97",
1859
+            "version": "v3.2.102",
2049 1860
             "source": {
2050 1861
                 "type": "git",
2051 1862
                 "url": "https://github.com/filamentphp/forms.git",
2052
-                "reference": "d679d30ae1c345740920e45b0334b5eacc76f7aa"
1863
+                "reference": "32ef8b049ac3c4577407cdc10e576082863f7e47"
2053 1864
             },
2054 1865
             "dist": {
2055 1866
                 "type": "zip",
2056
-                "url": "https://api.github.com/repos/filamentphp/forms/zipball/d679d30ae1c345740920e45b0334b5eacc76f7aa",
2057
-                "reference": "d679d30ae1c345740920e45b0334b5eacc76f7aa",
1867
+                "url": "https://api.github.com/repos/filamentphp/forms/zipball/32ef8b049ac3c4577407cdc10e576082863f7e47",
1868
+                "reference": "32ef8b049ac3c4577407cdc10e576082863f7e47",
2058 1869
                 "shasum": ""
2059 1870
             },
2060 1871
             "require": {
@@ -2097,20 +1908,20 @@
2097 1908
                 "issues": "https://github.com/filamentphp/filament/issues",
2098 1909
                 "source": "https://github.com/filamentphp/filament"
2099 1910
             },
2100
-            "time": "2024-07-31T11:53:08+00:00"
1911
+            "time": "2024-08-15T19:37:09+00:00"
2101 1912
         },
2102 1913
         {
2103 1914
             "name": "filament/infolists",
2104
-            "version": "v3.2.97",
1915
+            "version": "v3.2.102",
2105 1916
             "source": {
2106 1917
                 "type": "git",
2107 1918
                 "url": "https://github.com/filamentphp/infolists.git",
2108
-                "reference": "af2266e0cf9d26e88ea6153d608f11aa9cebb59e"
1919
+                "reference": "96403f2842e4c485f32110e4456b7a3bbcb1e835"
2109 1920
             },
2110 1921
             "dist": {
2111 1922
                 "type": "zip",
2112
-                "url": "https://api.github.com/repos/filamentphp/infolists/zipball/af2266e0cf9d26e88ea6153d608f11aa9cebb59e",
2113
-                "reference": "af2266e0cf9d26e88ea6153d608f11aa9cebb59e",
1923
+                "url": "https://api.github.com/repos/filamentphp/infolists/zipball/96403f2842e4c485f32110e4456b7a3bbcb1e835",
1924
+                "reference": "96403f2842e4c485f32110e4456b7a3bbcb1e835",
2114 1925
                 "shasum": ""
2115 1926
             },
2116 1927
             "require": {
@@ -2148,11 +1959,11 @@
2148 1959
                 "issues": "https://github.com/filamentphp/filament/issues",
2149 1960
                 "source": "https://github.com/filamentphp/filament"
2150 1961
             },
2151
-            "time": "2024-07-31T11:53:07+00:00"
1962
+            "time": "2024-08-14T16:52:44+00:00"
2152 1963
         },
2153 1964
         {
2154 1965
             "name": "filament/notifications",
2155
-            "version": "v3.2.97",
1966
+            "version": "v3.2.102",
2156 1967
             "source": {
2157 1968
                 "type": "git",
2158 1969
                 "url": "https://github.com/filamentphp/notifications.git",
@@ -2204,25 +2015,26 @@
2204 2015
         },
2205 2016
         {
2206 2017
             "name": "filament/support",
2207
-            "version": "v3.2.97",
2018
+            "version": "v3.2.102",
2208 2019
             "source": {
2209 2020
                 "type": "git",
2210 2021
                 "url": "https://github.com/filamentphp/support.git",
2211
-                "reference": "94c5349b8fed252499314bd2149fadf96ddaf6d6"
2022
+                "reference": "7dc30bc972b5c29572bd285bfb7c3f24e909522a"
2212 2023
             },
2213 2024
             "dist": {
2214 2025
                 "type": "zip",
2215
-                "url": "https://api.github.com/repos/filamentphp/support/zipball/94c5349b8fed252499314bd2149fadf96ddaf6d6",
2216
-                "reference": "94c5349b8fed252499314bd2149fadf96ddaf6d6",
2026
+                "url": "https://api.github.com/repos/filamentphp/support/zipball/7dc30bc972b5c29572bd285bfb7c3f24e909522a",
2027
+                "reference": "7dc30bc972b5c29572bd285bfb7c3f24e909522a",
2217 2028
                 "shasum": ""
2218 2029
             },
2219 2030
             "require": {
2220 2031
                 "blade-ui-kit/blade-heroicons": "^2.2.1",
2221
-                "doctrine/dbal": "^3.2",
2032
+                "doctrine/dbal": "^3.2|^4.0",
2222 2033
                 "ext-intl": "*",
2223 2034
                 "illuminate/contracts": "^10.45|^11.0",
2224 2035
                 "illuminate/support": "^10.45|^11.0",
2225 2036
                 "illuminate/view": "^10.45|^11.0",
2037
+                "kirschbaum-development/eloquent-power-joins": "^3.0",
2226 2038
                 "livewire/livewire": "^3.4.10",
2227 2039
                 "php": "^8.1",
2228 2040
                 "ryangjchandler/blade-capture-directive": "^0.2|^0.3|^1.0",
@@ -2258,20 +2070,20 @@
2258 2070
                 "issues": "https://github.com/filamentphp/filament/issues",
2259 2071
                 "source": "https://github.com/filamentphp/filament"
2260 2072
             },
2261
-            "time": "2024-07-31T11:53:25+00:00"
2073
+            "time": "2024-08-13T12:36:11+00:00"
2262 2074
         },
2263 2075
         {
2264 2076
             "name": "filament/tables",
2265
-            "version": "v3.2.97",
2077
+            "version": "v3.2.102",
2266 2078
             "source": {
2267 2079
                 "type": "git",
2268 2080
                 "url": "https://github.com/filamentphp/tables.git",
2269
-                "reference": "0e6e96bde5337b26944ce3a657ae6755bef82d1e"
2081
+                "reference": "072592eba6d29d5f82e2cacfaf6ec7b4309d66da"
2270 2082
             },
2271 2083
             "dist": {
2272 2084
                 "type": "zip",
2273
-                "url": "https://api.github.com/repos/filamentphp/tables/zipball/0e6e96bde5337b26944ce3a657ae6755bef82d1e",
2274
-                "reference": "0e6e96bde5337b26944ce3a657ae6755bef82d1e",
2085
+                "url": "https://api.github.com/repos/filamentphp/tables/zipball/072592eba6d29d5f82e2cacfaf6ec7b4309d66da",
2086
+                "reference": "072592eba6d29d5f82e2cacfaf6ec7b4309d66da",
2275 2087
                 "shasum": ""
2276 2088
             },
2277 2089
             "require": {
@@ -2284,7 +2096,6 @@
2284 2096
                 "illuminate/filesystem": "^10.45|^11.0",
2285 2097
                 "illuminate/support": "^10.45|^11.0",
2286 2098
                 "illuminate/view": "^10.45|^11.0",
2287
-                "kirschbaum-development/eloquent-power-joins": "^3.0",
2288 2099
                 "php": "^8.1",
2289 2100
                 "spatie/laravel-package-tools": "^1.9"
2290 2101
             },
@@ -2311,11 +2122,11 @@
2311 2122
                 "issues": "https://github.com/filamentphp/filament/issues",
2312 2123
                 "source": "https://github.com/filamentphp/filament"
2313 2124
             },
2314
-            "time": "2024-07-31T11:53:24+00:00"
2125
+            "time": "2024-08-12T16:38:51+00:00"
2315 2126
         },
2316 2127
         {
2317 2128
             "name": "filament/widgets",
2318
-            "version": "v3.2.97",
2129
+            "version": "v3.2.102",
2319 2130
             "source": {
2320 2131
                 "type": "git",
2321 2132
                 "url": "https://github.com/filamentphp/widgets.git",
@@ -3697,16 +3508,16 @@
3697 3508
         },
3698 3509
         {
3699 3510
             "name": "league/commonmark",
3700
-            "version": "2.5.1",
3511
+            "version": "2.5.3",
3701 3512
             "source": {
3702 3513
                 "type": "git",
3703 3514
                 "url": "https://github.com/thephpleague/commonmark.git",
3704
-                "reference": "ac815920de0eff6de947eac0a6a94e5ed0fb147c"
3515
+                "reference": "b650144166dfa7703e62a22e493b853b58d874b0"
3705 3516
             },
3706 3517
             "dist": {
3707 3518
                 "type": "zip",
3708
-                "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/ac815920de0eff6de947eac0a6a94e5ed0fb147c",
3709
-                "reference": "ac815920de0eff6de947eac0a6a94e5ed0fb147c",
3519
+                "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/b650144166dfa7703e62a22e493b853b58d874b0",
3520
+                "reference": "b650144166dfa7703e62a22e493b853b58d874b0",
3710 3521
                 "shasum": ""
3711 3522
             },
3712 3523
             "require": {
@@ -3719,8 +3530,8 @@
3719 3530
             },
3720 3531
             "require-dev": {
3721 3532
                 "cebe/markdown": "^1.0",
3722
-                "commonmark/cmark": "0.31.0",
3723
-                "commonmark/commonmark.js": "0.31.0",
3533
+                "commonmark/cmark": "0.31.1",
3534
+                "commonmark/commonmark.js": "0.31.1",
3724 3535
                 "composer/package-versions-deprecated": "^1.8",
3725 3536
                 "embed/embed": "^4.4",
3726 3537
                 "erusev/parsedown": "^1.0",
@@ -3799,7 +3610,7 @@
3799 3610
                     "type": "tidelift"
3800 3611
                 }
3801 3612
             ],
3802
-            "time": "2024-07-24T12:52:09+00:00"
3613
+            "time": "2024-08-16T11:46:16+00:00"
3803 3614
         },
3804 3615
         {
3805 3616
             "name": "league/config",
@@ -5529,16 +5340,16 @@
5529 5340
         },
5530 5341
         {
5531 5342
             "name": "phpseclib/phpseclib",
5532
-            "version": "3.0.39",
5343
+            "version": "3.0.41",
5533 5344
             "source": {
5534 5345
                 "type": "git",
5535 5346
                 "url": "https://github.com/phpseclib/phpseclib.git",
5536
-                "reference": "211ebc399c6e73c225a018435fe5ae209d1d1485"
5347
+                "reference": "621c73f7dcb310b61de34d1da4c4204e8ace6ceb"
5537 5348
             },
5538 5349
             "dist": {
5539 5350
                 "type": "zip",
5540
-                "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/211ebc399c6e73c225a018435fe5ae209d1d1485",
5541
-                "reference": "211ebc399c6e73c225a018435fe5ae209d1d1485",
5351
+                "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/621c73f7dcb310b61de34d1da4c4204e8ace6ceb",
5352
+                "reference": "621c73f7dcb310b61de34d1da4c4204e8ace6ceb",
5542 5353
                 "shasum": ""
5543 5354
             },
5544 5355
             "require": {
@@ -5619,7 +5430,7 @@
5619 5430
             ],
5620 5431
             "support": {
5621 5432
                 "issues": "https://github.com/phpseclib/phpseclib/issues",
5622
-                "source": "https://github.com/phpseclib/phpseclib/tree/3.0.39"
5433
+                "source": "https://github.com/phpseclib/phpseclib/tree/3.0.41"
5623 5434
             },
5624 5435
             "funding": [
5625 5436
                 {
@@ -5635,7 +5446,7 @@
5635 5446
                     "type": "tidelift"
5636 5447
                 }
5637 5448
             ],
5638
-            "time": "2024-06-24T06:27:33+00:00"
5449
+            "time": "2024-08-12T00:13:54+00:00"
5639 5450
         },
5640 5451
         {
5641 5452
             "name": "psr/cache",
@@ -10671,16 +10482,16 @@
10671 10482
         },
10672 10483
         {
10673 10484
             "name": "phpunit/phpunit",
10674
-            "version": "10.5.29",
10485
+            "version": "10.5.30",
10675 10486
             "source": {
10676 10487
                 "type": "git",
10677 10488
                 "url": "https://github.com/sebastianbergmann/phpunit.git",
10678
-                "reference": "8e9e80872b4e8064401788ee8a32d40b4455318f"
10489
+                "reference": "b15524febac0153876b4ba9aab3326c2ee94c897"
10679 10490
             },
10680 10491
             "dist": {
10681 10492
                 "type": "zip",
10682
-                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/8e9e80872b4e8064401788ee8a32d40b4455318f",
10683
-                "reference": "8e9e80872b4e8064401788ee8a32d40b4455318f",
10493
+                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b15524febac0153876b4ba9aab3326c2ee94c897",
10494
+                "reference": "b15524febac0153876b4ba9aab3326c2ee94c897",
10684 10495
                 "shasum": ""
10685 10496
             },
10686 10497
             "require": {
@@ -10701,7 +10512,7 @@
10701 10512
                 "phpunit/php-timer": "^6.0.0",
10702 10513
                 "sebastian/cli-parser": "^2.0.1",
10703 10514
                 "sebastian/code-unit": "^2.0.0",
10704
-                "sebastian/comparator": "^5.0.1",
10515
+                "sebastian/comparator": "^5.0.2",
10705 10516
                 "sebastian/diff": "^5.1.1",
10706 10517
                 "sebastian/environment": "^6.1.0",
10707 10518
                 "sebastian/exporter": "^5.1.2",
@@ -10752,7 +10563,7 @@
10752 10563
             "support": {
10753 10564
                 "issues": "https://github.com/sebastianbergmann/phpunit/issues",
10754 10565
                 "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
10755
-                "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.29"
10566
+                "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.30"
10756 10567
             },
10757 10568
             "funding": [
10758 10569
                 {
@@ -10768,25 +10579,25 @@
10768 10579
                     "type": "tidelift"
10769 10580
                 }
10770 10581
             ],
10771
-            "time": "2024-07-30T11:08:00+00:00"
10582
+            "time": "2024-08-13T06:09:37+00:00"
10772 10583
         },
10773 10584
         {
10774 10585
             "name": "rector/rector",
10775
-            "version": "1.2.2",
10586
+            "version": "1.2.3",
10776 10587
             "source": {
10777 10588
                 "type": "git",
10778 10589
                 "url": "https://github.com/rectorphp/rector.git",
10779
-                "reference": "044e6364017882d1e346da8690eeabc154da5495"
10590
+                "reference": "2433e95410aef1b34b15d7f1b6a134365a4ddb39"
10780 10591
             },
10781 10592
             "dist": {
10782 10593
                 "type": "zip",
10783
-                "url": "https://api.github.com/repos/rectorphp/rector/zipball/044e6364017882d1e346da8690eeabc154da5495",
10784
-                "reference": "044e6364017882d1e346da8690eeabc154da5495",
10594
+                "url": "https://api.github.com/repos/rectorphp/rector/zipball/2433e95410aef1b34b15d7f1b6a134365a4ddb39",
10595
+                "reference": "2433e95410aef1b34b15d7f1b6a134365a4ddb39",
10785 10596
                 "shasum": ""
10786 10597
             },
10787 10598
             "require": {
10788 10599
                 "php": "^7.2|^8.0",
10789
-                "phpstan/phpstan": "^1.11"
10600
+                "phpstan/phpstan": "^1.11.9"
10790 10601
             },
10791 10602
             "conflict": {
10792 10603
                 "rector/rector-doctrine": "*",
@@ -10819,7 +10630,7 @@
10819 10630
             ],
10820 10631
             "support": {
10821 10632
                 "issues": "https://github.com/rectorphp/rector/issues",
10822
-                "source": "https://github.com/rectorphp/rector/tree/1.2.2"
10633
+                "source": "https://github.com/rectorphp/rector/tree/1.2.3"
10823 10634
             },
10824 10635
             "funding": [
10825 10636
                 {
@@ -10827,7 +10638,7 @@
10827 10638
                     "type": "github"
10828 10639
                 }
10829 10640
             ],
10830
-            "time": "2024-07-25T07:44:34+00:00"
10641
+            "time": "2024-08-12T16:36:46+00:00"
10831 10642
         },
10832 10643
         {
10833 10644
             "name": "sebastian/cli-parser",
@@ -10999,16 +10810,16 @@
10999 10810
         },
11000 10811
         {
11001 10812
             "name": "sebastian/comparator",
11002
-            "version": "5.0.1",
10813
+            "version": "5.0.2",
11003 10814
             "source": {
11004 10815
                 "type": "git",
11005 10816
                 "url": "https://github.com/sebastianbergmann/comparator.git",
11006
-                "reference": "2db5010a484d53ebf536087a70b4a5423c102372"
10817
+                "reference": "2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53"
11007 10818
             },
11008 10819
             "dist": {
11009 10820
                 "type": "zip",
11010
-                "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2db5010a484d53ebf536087a70b4a5423c102372",
11011
-                "reference": "2db5010a484d53ebf536087a70b4a5423c102372",
10821
+                "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53",
10822
+                "reference": "2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53",
11012 10823
                 "shasum": ""
11013 10824
             },
11014 10825
             "require": {
@@ -11019,7 +10830,7 @@
11019 10830
                 "sebastian/exporter": "^5.0"
11020 10831
             },
11021 10832
             "require-dev": {
11022
-                "phpunit/phpunit": "^10.3"
10833
+                "phpunit/phpunit": "^10.4"
11023 10834
             },
11024 10835
             "type": "library",
11025 10836
             "extra": {
@@ -11064,7 +10875,7 @@
11064 10875
             "support": {
11065 10876
                 "issues": "https://github.com/sebastianbergmann/comparator/issues",
11066 10877
                 "security": "https://github.com/sebastianbergmann/comparator/security/policy",
11067
-                "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.1"
10878
+                "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.2"
11068 10879
             },
11069 10880
             "funding": [
11070 10881
                 {
@@ -11072,7 +10883,7 @@
11072 10883
                     "type": "github"
11073 10884
                 }
11074 10885
             ],
11075
-            "time": "2023-08-14T13:18:12+00:00"
10886
+            "time": "2024-08-12T06:03:08+00:00"
11076 10887
         },
11077 10888
         {
11078 10889
             "name": "sebastian/complexity",
@@ -12612,16 +12423,16 @@
12612 12423
         },
12613 12424
         {
12614 12425
             "name": "zbateson/mail-mime-parser",
12615
-            "version": "3.0.2",
12426
+            "version": "3.0.3",
12616 12427
             "source": {
12617 12428
                 "type": "git",
12618 12429
                 "url": "https://github.com/zbateson/mail-mime-parser.git",
12619
-                "reference": "9a240522ae5e4eaeb7bf72c9bc88fe89dfb014a3"
12430
+                "reference": "e0d4423fe27850c9dd301190767dbc421acc2f19"
12620 12431
             },
12621 12432
             "dist": {
12622 12433
                 "type": "zip",
12623
-                "url": "https://api.github.com/repos/zbateson/mail-mime-parser/zipball/9a240522ae5e4eaeb7bf72c9bc88fe89dfb014a3",
12624
-                "reference": "9a240522ae5e4eaeb7bf72c9bc88fe89dfb014a3",
12434
+                "url": "https://api.github.com/repos/zbateson/mail-mime-parser/zipball/e0d4423fe27850c9dd301190767dbc421acc2f19",
12435
+                "reference": "e0d4423fe27850c9dd301190767dbc421acc2f19",
12625 12436
                 "shasum": ""
12626 12437
             },
12627 12438
             "require": {
@@ -12684,7 +12495,7 @@
12684 12495
                     "type": "github"
12685 12496
                 }
12686 12497
             ],
12687
-            "time": "2024-05-01T16:49:29+00:00"
12498
+            "time": "2024-08-10T18:44:09+00:00"
12688 12499
         },
12689 12500
         {
12690 12501
             "name": "zbateson/mb-wrapper",

+ 22
- 22
package-lock.json Просмотреть файл

@@ -900,9 +900,9 @@
900 900
             }
901 901
         },
902 902
         "node_modules/axios": {
903
-            "version": "1.7.3",
904
-            "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.3.tgz",
905
-            "integrity": "sha512-Ar7ND9pU99eJ9GpoGQKhKf58GpUOgnzuaB7ueNQ5BMi0p+LZ5oaEnfF999fAArcTIBwXTCHAmGcHOZJaWPq9Nw==",
903
+            "version": "1.7.4",
904
+            "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz",
905
+            "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==",
906 906
             "dev": true,
907 907
             "license": "MIT",
908 908
             "dependencies": {
@@ -1159,9 +1159,9 @@
1159 1159
             "license": "MIT"
1160 1160
         },
1161 1161
         "node_modules/electron-to-chromium": {
1162
-            "version": "1.5.5",
1163
-            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.5.tgz",
1164
-            "integrity": "sha512-QR7/A7ZkMS8tZuoftC/jfqNkZLQO779SSW3YuZHP4eXpj3EffGLFcB/Xu9AAZQzLccTiCV+EmUo3ha4mQ9wnlA==",
1162
+            "version": "1.5.10",
1163
+            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.10.tgz",
1164
+            "integrity": "sha512-C3RDERDjrNW262GCRvpoer3a0Ksd66CtgDLxMHhzShQ8fhL4kwnpVXsJPAKg9xJjIROXUbLBrvtOzVAjALMIWA==",
1165 1165
             "dev": true,
1166 1166
             "license": "ISC"
1167 1167
         },
@@ -1968,9 +1968,9 @@
1968 1968
             }
1969 1969
         },
1970 1970
         "node_modules/postcss-nested/node_modules/postcss-selector-parser": {
1971
-            "version": "6.1.1",
1972
-            "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz",
1973
-            "integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==",
1971
+            "version": "6.1.2",
1972
+            "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
1973
+            "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
1974 1974
             "dev": true,
1975 1975
             "license": "MIT",
1976 1976
             "dependencies": {
@@ -2056,9 +2056,9 @@
2056 2056
             }
2057 2057
         },
2058 2058
         "node_modules/postcss-nesting/node_modules/postcss-selector-parser": {
2059
-            "version": "6.1.1",
2060
-            "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz",
2061
-            "integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==",
2059
+            "version": "6.1.2",
2060
+            "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
2061
+            "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
2062 2062
             "dev": true,
2063 2063
             "license": "MIT",
2064 2064
             "dependencies": {
@@ -2417,9 +2417,9 @@
2417 2417
             }
2418 2418
         },
2419 2419
         "node_modules/tailwindcss": {
2420
-            "version": "3.4.9",
2421
-            "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.9.tgz",
2422
-            "integrity": "sha512-1SEOvRr6sSdV5IDf9iC+NU4dhwdqzF4zKKq3sAbasUWHEM6lsMhX+eNN5gkPx1BvLFEnZQEUFbXnGj8Qlp83Pg==",
2420
+            "version": "3.4.10",
2421
+            "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.10.tgz",
2422
+            "integrity": "sha512-KWZkVPm7yJRhdu4SRSl9d4AK2wM3a50UsvgHZO7xY77NQr2V+fIrEuoDGQcbvswWvFGbS2f6e+jC/6WJm1Dl0w==",
2423 2423
             "dev": true,
2424 2424
             "license": "MIT",
2425 2425
             "dependencies": {
@@ -2455,9 +2455,9 @@
2455 2455
             }
2456 2456
         },
2457 2457
         "node_modules/tailwindcss/node_modules/postcss-selector-parser": {
2458
-            "version": "6.1.1",
2459
-            "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz",
2460
-            "integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==",
2458
+            "version": "6.1.2",
2459
+            "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
2460
+            "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
2461 2461
             "dev": true,
2462 2462
             "license": "MIT",
2463 2463
             "dependencies": {
@@ -2550,14 +2550,14 @@
2550 2550
             "license": "MIT"
2551 2551
         },
2552 2552
         "node_modules/vite": {
2553
-            "version": "5.4.0",
2554
-            "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.0.tgz",
2555
-            "integrity": "sha512-5xokfMX0PIiwCMCMb9ZJcMyh5wbBun0zUzKib+L65vAZ8GY9ePZMXxFrHbr/Kyll2+LSCY7xtERPpxkBDKngwg==",
2553
+            "version": "5.4.1",
2554
+            "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.1.tgz",
2555
+            "integrity": "sha512-1oE6yuNXssjrZdblI9AfBbHCC41nnyoVoEZxQnID6yvQZAFBzxxkqoFLtHUMkYunL8hwOLEjgTuxpkRxvba3kA==",
2556 2556
             "dev": true,
2557 2557
             "license": "MIT",
2558 2558
             "dependencies": {
2559 2559
                 "esbuild": "^0.21.3",
2560
-                "postcss": "^8.4.40",
2560
+                "postcss": "^8.4.41",
2561 2561
                 "rollup": "^4.13.0"
2562 2562
             },
2563 2563
             "bin": {

Загрузка…
Отмена
Сохранить