| 
									
										
										
										
											2023-03-25 11:32:33 +01:00
										 |  |  | <?php | 
					
						
							| 
									
										
										
										
											2023-04-01 07:50:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-25 11:32:33 +01:00
										 |  |  | /* | 
					
						
							|  |  |  |  * AccountRepository.php | 
					
						
							|  |  |  |  * Copyright (c) 2023 james@firefly-iii.org | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This file is part of Firefly III (https://github.com/firefly-iii). | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  |  * it under the terms of the GNU Affero General Public License as | 
					
						
							|  |  |  |  * published by the Free Software Foundation, either version 3 of the | 
					
						
							|  |  |  |  * License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU Affero General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU Affero General Public License | 
					
						
							|  |  |  |  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-15 16:02:42 +02:00
										 |  |  | declare(strict_types=1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-21 15:50:49 +02:00
										 |  |  | namespace FireflyIII\Repositories\UserGroups\Account; | 
					
						
							| 
									
										
										
										
											2023-03-25 11:32:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-03 09:15:52 +01:00
										 |  |  | use FireflyIII\Enums\AccountTypeEnum; | 
					
						
							| 
									
										
										
										
											2023-07-25 09:01:44 +02:00
										 |  |  | use FireflyIII\Models\Account; | 
					
						
							|  |  |  | use FireflyIII\Models\AccountMeta; | 
					
						
							|  |  |  | use FireflyIII\Models\AccountType; | 
					
						
							| 
									
										
										
										
											2024-04-28 14:40:22 +02:00
										 |  |  | use FireflyIII\Models\ObjectGroup; | 
					
						
							| 
									
										
										
										
											2024-04-20 16:18:41 +02:00
										 |  |  | use FireflyIII\Models\Transaction; | 
					
						
							| 
									
										
										
										
											2023-07-25 09:01:44 +02:00
										 |  |  | use FireflyIII\Models\TransactionCurrency; | 
					
						
							| 
									
										
										
										
											2024-03-16 22:00:25 +01:00
										 |  |  | use FireflyIII\Services\Internal\Update\AccountUpdateService; | 
					
						
							| 
									
										
										
										
											2024-05-18 06:42:09 +02:00
										 |  |  | use FireflyIII\Support\Facades\Steam; | 
					
						
							| 
									
										
										
										
											2023-09-21 15:50:49 +02:00
										 |  |  | use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait; | 
					
						
							| 
									
										
										
										
											2023-11-28 17:18:31 +01:00
										 |  |  | use Illuminate\Database\Eloquent\Builder as EloquentBuilder; | 
					
						
							| 
									
										
										
										
											2023-03-25 11:32:33 +01:00
										 |  |  | use Illuminate\Support\Collection; | 
					
						
							| 
									
										
										
										
											2024-04-20 16:18:41 +02:00
										 |  |  | use Illuminate\Support\Facades\DB; | 
					
						
							| 
									
										
										
										
											2025-05-27 16:57:36 +02:00
										 |  |  | use Override; | 
					
						
							|  |  |  | use stdClass; | 
					
						
							| 
									
										
										
										
											2023-03-25 11:32:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-27 17:06:15 +02:00
										 |  |  | use function Safe\json_encode; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-25 11:32:33 +01:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Class AccountRepository | 
					
						
							| 
									
										
										
										
											2025-02-23 12:27:34 +01:00
										 |  |  |  * | 
					
						
							|  |  |  |  * @deprecated | 
					
						
							| 
									
										
										
										
											2023-03-25 11:32:33 +01:00
										 |  |  |  */ | 
					
						
							|  |  |  | class AccountRepository implements AccountRepositoryInterface | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-09-21 15:50:49 +02:00
										 |  |  |     use UserGroupTrait; | 
					
						
							| 
									
										
										
										
											2023-03-25 11:32:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-27 16:57:36 +02:00
										 |  |  |     #[Override]
 | 
					
						
							| 
									
										
										
										
											2024-03-06 07:16:01 +01:00
										 |  |  |     public function countAccounts(array $types): int | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $query = $this->userGroup->accounts(); | 
					
						
							|  |  |  |         if (0 !== count($types)) { | 
					
						
							|  |  |  |             $query->accountTypeIn($types); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $query->count(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-10 06:51:59 +01:00
										 |  |  |     public function findByAccountNumber(string $number, array $types): ?Account | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $dbQuery = $this->userGroup | 
					
						
							|  |  |  |             ->accounts() | 
					
						
							|  |  |  |             ->leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id') | 
					
						
							|  |  |  |             ->where('accounts.active', true) | 
					
						
							|  |  |  |             ->where( | 
					
						
							| 
									
										
										
										
											2025-01-04 19:43:58 +01:00
										 |  |  |                 static function (EloquentBuilder $q1) use ($number): void { | 
					
						
							| 
									
										
										
										
											2025-05-27 17:06:15 +02:00
										 |  |  |                     $json = json_encode($number); | 
					
						
							| 
									
										
										
										
											2023-12-10 06:51:59 +01:00
										 |  |  |                     $q1->where('account_meta.name', '=', 'account_number'); | 
					
						
							|  |  |  |                     $q1->where('account_meta.data', '=', $json); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2025-03-14 17:45:16 +01:00
										 |  |  |             ) | 
					
						
							|  |  |  |         ; | 
					
						
							| 
									
										
										
										
											2023-12-10 06:51:59 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (0 !== count($types)) { | 
					
						
							|  |  |  |             $dbQuery->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id'); | 
					
						
							|  |  |  |             $dbQuery->whereIn('account_types.type', $types); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-04 07:39:16 +01:00
										 |  |  |         /** @var null|Account */ | 
					
						
							| 
									
										
										
										
											2023-12-10 06:51:59 +01:00
										 |  |  |         return $dbQuery->first(['accounts.*']); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function findByIbanNull(string $iban, array $types): ?Account | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-05-18 06:49:29 +02:00
										 |  |  |         $iban  = Steam::filterSpaces($iban); | 
					
						
							| 
									
										
										
										
											2023-12-10 06:51:59 +01:00
										 |  |  |         $query = $this->userGroup->accounts()->where('iban', '!=', '')->whereNotNull('iban'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (0 !== count($types)) { | 
					
						
							|  |  |  |             $query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id'); | 
					
						
							|  |  |  |             $query->whereIn('account_types.type', $types); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-04 07:39:16 +01:00
										 |  |  |         /** @var null|Account */ | 
					
						
							| 
									
										
										
										
											2023-12-10 06:51:59 +01:00
										 |  |  |         return $query->where('iban', $iban)->first(['accounts.*']); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-23 07:15:41 +02:00
										 |  |  |     public function findByName(string $name, array $types): ?Account | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2025-03-14 17:45:16 +01:00
										 |  |  |         $query   = $this->userGroup->accounts(); | 
					
						
							| 
									
										
										
										
											2023-09-23 07:15:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (0 !== count($types)) { | 
					
						
							|  |  |  |             $query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id'); | 
					
						
							|  |  |  |             $query->whereIn('account_types.type', $types); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |         app('log')->debug(sprintf('Searching for account named "%s" (of user #%d) of the following type(s)', $name, $this->user->id), ['types' => $types]); | 
					
						
							| 
									
										
										
										
											2023-09-23 07:15:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         $query->where('accounts.name', $name); | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         /** @var null|Account $account */ | 
					
						
							| 
									
										
										
										
											2023-09-23 07:15:41 +02:00
										 |  |  |         $account = $query->first(['accounts.*']); | 
					
						
							|  |  |  |         if (null === $account) { | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |             app('log')->debug(sprintf('There is no account with name "%s" of types', $name), $types); | 
					
						
							| 
									
										
										
										
											2023-09-23 07:15:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             return null; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |         app('log')->debug(sprintf('Found #%d (%s) with type id %d', $account->id, $account->name, $account->account_type_id)); | 
					
						
							| 
									
										
										
										
											2023-09-23 07:15:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return $account; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-27 16:57:36 +02:00
										 |  |  |     #[Override]
 | 
					
						
							| 
									
										
										
										
											2024-12-22 08:43:12 +01:00
										 |  |  |     public function getAccountBalances(Account $account): Collection | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return $account->accountBalances; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-01 09:27:39 +02:00
										 |  |  |     public function getAccountCurrency(Account $account): ?TransactionCurrency | 
					
						
							| 
									
										
										
										
											2023-07-17 20:33:26 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2025-03-14 17:45:16 +01:00
										 |  |  |         $type       = $account->accountType->type; | 
					
						
							|  |  |  |         $list       = config('firefly.valid_currency_account_types'); | 
					
						
							| 
									
										
										
										
											2023-08-01 09:27:39 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // return null if not in this list.
 | 
					
						
							|  |  |  |         if (!in_array($type, $list, true)) { | 
					
						
							|  |  |  |             return null; | 
					
						
							| 
									
										
										
										
											2023-03-25 11:32:33 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2024-04-20 16:18:41 +02:00
										 |  |  |         $currencyId = (int) $this->getMetaValue($account, 'currency_id'); | 
					
						
							| 
									
										
										
										
											2023-08-01 09:27:39 +02:00
										 |  |  |         if ($currencyId > 0) { | 
					
						
							|  |  |  |             return TransactionCurrency::find($currencyId); | 
					
						
							| 
									
										
										
										
											2023-03-25 11:32:33 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-01 09:27:39 +02:00
										 |  |  |         return null; | 
					
						
							| 
									
										
										
										
											2023-03-25 11:32:33 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-07-25 09:01:44 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2023-08-01 09:27:39 +02:00
										 |  |  |      * Return meta value for account. Null if not found. | 
					
						
							| 
									
										
										
										
											2023-07-25 09:01:44 +02:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2023-08-01 09:27:39 +02:00
										 |  |  |     public function getMetaValue(Account $account, string $field): ?string | 
					
						
							| 
									
										
										
										
											2023-07-25 09:01:44 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-08-01 09:27:39 +02:00
										 |  |  |         $result = $account->accountMeta->filter( | 
					
						
							| 
									
										
										
										
											2025-05-04 13:55:42 +02:00
										 |  |  |             static fn (AccountMeta $meta) => strtolower($meta->name) === strtolower($field) | 
					
						
							| 
									
										
										
										
											2023-08-01 09:27:39 +02:00
										 |  |  |         ); | 
					
						
							|  |  |  |         if (0 === $result->count()) { | 
					
						
							|  |  |  |             return null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (1 === $result->count()) { | 
					
						
							| 
									
										
										
										
											2024-04-20 16:18:41 +02:00
										 |  |  |             return (string) $result->first()->data; | 
					
						
							| 
									
										
										
										
											2023-07-25 09:01:44 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-01 09:27:39 +02:00
										 |  |  |         return null; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function find(int $accountId): ?Account | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $account = $this->user->accounts()->find($accountId); | 
					
						
							|  |  |  |         if (null === $account) { | 
					
						
							| 
									
										
										
										
											2025-05-27 17:06:15 +02:00
										 |  |  |             return $this->userGroup->accounts()->find($accountId); | 
					
						
							| 
									
										
										
										
											2023-07-25 09:01:44 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2025-01-04 07:39:16 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         /** @var null|Account */ | 
					
						
							| 
									
										
										
										
											2023-08-01 09:27:39 +02:00
										 |  |  |         return $account; | 
					
						
							| 
									
										
										
										
											2023-07-25 09:01:44 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-27 16:57:36 +02:00
										 |  |  |     #[Override]
 | 
					
						
							| 
									
										
										
										
											2024-12-22 08:43:12 +01:00
										 |  |  |     public function getAccountTypes(Collection $accounts): Collection | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return AccountType::leftJoin('accounts', 'accounts.account_type_id', '=', 'account_types.id') | 
					
						
							| 
									
										
										
										
											2025-03-14 17:45:16 +01:00
										 |  |  |             ->whereIn('accounts.id', $accounts->pluck('id')->toArray()) | 
					
						
							|  |  |  |             ->get(['accounts.id', 'account_types.type']) | 
					
						
							|  |  |  |         ; | 
					
						
							| 
									
										
										
										
											2024-12-22 08:43:12 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-25 09:01:44 +02:00
										 |  |  |     public function getAccountsById(array $accountIds): Collection | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $query = $this->userGroup->accounts(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (0 !== count($accountIds)) { | 
					
						
							|  |  |  |             $query->whereIn('accounts.id', $accountIds); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         $query->orderBy('accounts.order', 'ASC'); | 
					
						
							|  |  |  |         $query->orderBy('accounts.active', 'DESC'); | 
					
						
							|  |  |  |         $query->orderBy('accounts.name', 'ASC'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $query->get(['accounts.*']); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-27 16:57:36 +02:00
										 |  |  |     #[Override]
 | 
					
						
							| 
									
										
										
										
											2024-03-06 07:16:01 +01:00
										 |  |  |     public function getAccountsInOrder(array $types, array $sort, int $startRow, int $endRow): Collection | 
					
						
							| 
									
										
										
										
											2023-07-25 09:01:44 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-08-01 09:27:39 +02:00
										 |  |  |         $query = $this->userGroup->accounts(); | 
					
						
							|  |  |  |         if (0 !== count($types)) { | 
					
						
							|  |  |  |             $query->accountTypeIn($types); | 
					
						
							| 
									
										
										
										
											2023-07-25 09:01:44 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2024-03-06 07:16:01 +01:00
										 |  |  |         $query->skip($startRow); | 
					
						
							|  |  |  |         $query->take($endRow - $startRow); | 
					
						
							| 
									
										
										
										
											2023-08-01 09:27:39 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // add sort parameters. At this point they're filtered to allowed fields to sort by:
 | 
					
						
							|  |  |  |         if (0 !== count($sort)) { | 
					
						
							| 
									
										
										
										
											2024-03-06 07:16:01 +01:00
										 |  |  |             foreach ($sort as $label => $direction) { | 
					
						
							|  |  |  |                 $query->orderBy(sprintf('accounts.%s', $label), $direction); | 
					
						
							| 
									
										
										
										
											2023-08-01 09:27:39 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2023-07-25 09:01:44 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-01 09:27:39 +02:00
										 |  |  |         if (0 === count($sort)) { | 
					
						
							| 
									
										
										
										
											2024-03-06 07:16:01 +01:00
										 |  |  |             $query->orderBy('accounts.order', 'ASC'); | 
					
						
							| 
									
										
										
										
											2023-08-01 09:27:39 +02:00
										 |  |  |             $query->orderBy('accounts.active', 'DESC'); | 
					
						
							|  |  |  |             $query->orderBy('accounts.name', 'ASC'); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-01 09:27:39 +02:00
										 |  |  |         return $query->get(['accounts.*']); | 
					
						
							| 
									
										
										
										
											2023-07-25 09:01:44 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-06 11:22:36 +02:00
										 |  |  |     public function getActiveAccountsByType(array $types): Collection | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $query = $this->userGroup->accounts(); | 
					
						
							|  |  |  |         if (0 !== count($types)) { | 
					
						
							|  |  |  |             $query->accountTypeIn($types); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         $query->where('active', true); | 
					
						
							|  |  |  |         $query->orderBy('accounts.account_type_id', 'ASC'); | 
					
						
							|  |  |  |         $query->orderBy('accounts.order', 'ASC'); | 
					
						
							|  |  |  |         $query->orderBy('accounts.name', 'ASC'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $query->get(['accounts.*']); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-27 16:57:36 +02:00
										 |  |  |     #[Override]
 | 
					
						
							| 
									
										
										
										
											2024-12-22 08:43:12 +01:00
										 |  |  |     public function getLastActivity(Collection $accounts): array | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return Transaction::whereIn('account_id', $accounts->pluck('id')->toArray()) | 
					
						
							| 
									
										
										
										
											2025-03-14 17:45:16 +01:00
										 |  |  |             ->leftJoin('transaction_journals', 'transaction_journals.id', 'transactions.transaction_journal_id') | 
					
						
							|  |  |  |             ->groupBy('transactions.account_id') | 
					
						
							|  |  |  |             ->get(['transactions.account_id', DB::raw('MAX(transaction_journals.date) as date_max')])->toArray() // @phpstan-ignore-line
 | 
					
						
							|  |  |  |         ; | 
					
						
							| 
									
										
										
										
											2024-12-22 08:43:12 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-27 16:57:36 +02:00
										 |  |  |     #[Override]
 | 
					
						
							| 
									
										
										
										
											2024-12-22 08:43:12 +01:00
										 |  |  |     public function getMetaValues(Collection $accounts, array $fields): Collection | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $query = AccountMeta::whereIn('account_id', $accounts->pluck('id')->toArray()); | 
					
						
							|  |  |  |         if (count($fields) > 0) { | 
					
						
							|  |  |  |             $query->whereIn('name', $fields); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $query->get(['account_meta.id', 'account_meta.account_id', 'account_meta.name', 'account_meta.data']); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-27 16:57:36 +02:00
										 |  |  |     #[Override]
 | 
					
						
							| 
									
										
										
										
											2024-12-22 08:43:12 +01:00
										 |  |  |     public function getObjectGroups(Collection $accounts): array | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $groupIds = []; | 
					
						
							|  |  |  |         $return   = []; | 
					
						
							|  |  |  |         $set      = DB::table('object_groupables')->where('object_groupable_type', Account::class) | 
					
						
							| 
									
										
										
										
											2025-03-14 17:45:16 +01:00
										 |  |  |             ->whereIn('object_groupable_id', $accounts->pluck('id')->toArray())->get() | 
					
						
							|  |  |  |         ; | 
					
						
							| 
									
										
										
										
											2024-12-22 08:43:12 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-27 16:57:36 +02:00
										 |  |  |         /** @var stdClass $row */ | 
					
						
							| 
									
										
										
										
											2024-12-22 08:43:12 +01:00
										 |  |  |         foreach ($set as $row) { | 
					
						
							|  |  |  |             $groupIds[] = $row->object_group_id; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         $groupIds = array_unique($groupIds); | 
					
						
							|  |  |  |         $groups   = ObjectGroup::whereIn('id', $groupIds)->get(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-27 16:57:36 +02:00
										 |  |  |         /** @var stdClass $row */ | 
					
						
							| 
									
										
										
										
											2024-12-22 08:43:12 +01:00
										 |  |  |         foreach ($set as $row) { | 
					
						
							|  |  |  |             if (!array_key_exists($row->object_groupable_id, $return)) { | 
					
						
							|  |  |  |                 /** @var null|ObjectGroup $group */ | 
					
						
							|  |  |  |                 $group = $groups->firstWhere('id', '=', $row->object_group_id); | 
					
						
							|  |  |  |                 if (null !== $group) { | 
					
						
							|  |  |  |                     $return[$row->object_groupable_id] = ['title' => $group->title, 'order' => $group->order, 'id' => $group->id]; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-04 20:41:34 +01:00
										 |  |  |     public function resetAccountOrder(): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $sets = [ | 
					
						
							| 
									
										
										
										
											2025-01-03 09:15:52 +01:00
										 |  |  |             [AccountTypeEnum::DEFAULT->value, AccountTypeEnum::ASSET->value], | 
					
						
							|  |  |  |             [AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::CREDITCARD->value, AccountTypeEnum::MORTGAGE->value], | 
					
						
							| 
									
										
										
										
											2024-03-04 20:41:34 +01:00
										 |  |  |         ]; | 
					
						
							|  |  |  |         foreach ($sets as $set) { | 
					
						
							|  |  |  |             $list  = $this->getAccountsByType($set); | 
					
						
							|  |  |  |             $index = 1; | 
					
						
							|  |  |  |             foreach ($list as $account) { | 
					
						
							|  |  |  |                 if (false === $account->active) { | 
					
						
							|  |  |  |                     $account->order = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     continue; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2024-04-20 16:18:41 +02:00
										 |  |  |                 if ($index !== (int) $account->order) { | 
					
						
							| 
									
										
										
										
											2024-03-04 20:41:34 +01:00
										 |  |  |                     app('log')->debug(sprintf('Account #%d ("%s"): order should %d be but is %d.', $account->id, $account->name, $index, $account->order)); | 
					
						
							|  |  |  |                     $account->order = $index; | 
					
						
							|  |  |  |                     $account->save(); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 ++$index; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2024-07-26 03:57:35 +02:00
										 |  |  |         // reset the rest to zero.
 | 
					
						
							| 
									
										
										
										
											2025-03-14 17:45:16 +01:00
										 |  |  |         $all  = [AccountTypeEnum::DEFAULT->value, AccountTypeEnum::ASSET->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::CREDITCARD->value, AccountTypeEnum::MORTGAGE->value]; | 
					
						
							| 
									
										
										
										
											2024-07-29 05:06:54 +02:00
										 |  |  |         $this->user->accounts()->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id') | 
					
						
							| 
									
										
										
										
											2025-03-14 17:45:16 +01:00
										 |  |  |             ->whereNotIn('account_types.type', $all) | 
					
						
							|  |  |  |             ->update(['order' => 0]) | 
					
						
							|  |  |  |         ; | 
					
						
							| 
									
										
										
										
											2024-03-04 20:41:34 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-28 09:54:28 +02:00
										 |  |  |     public function getAccountsByType(array $types, ?array $sort = [], ?array $filters = []): Collection | 
					
						
							| 
									
										
										
										
											2024-03-04 20:41:34 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2025-03-14 17:45:16 +01:00
										 |  |  |         $sortable        = ['name', 'active']; // TODO yes this is a duplicate array.
 | 
					
						
							|  |  |  |         $res             = array_intersect([AccountTypeEnum::ASSET->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value], $types); | 
					
						
							|  |  |  |         $query           = $this->userGroup->accounts(); | 
					
						
							| 
									
										
										
										
											2024-03-04 20:41:34 +01:00
										 |  |  |         if (0 !== count($types)) { | 
					
						
							|  |  |  |             $query->accountTypeIn($types); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-28 09:54:28 +02:00
										 |  |  |         // process filters
 | 
					
						
							|  |  |  |         // TODO this should be repeatable, it feels like a hack when you do it here.
 | 
					
						
							| 
									
										
										
										
											2024-04-28 13:30:42 +02:00
										 |  |  |         // TODO some fields cannot be filtered using the query, and a second filter must be applied on the collection.
 | 
					
						
							| 
									
										
										
										
											2024-04-28 14:40:22 +02:00
										 |  |  |         foreach ($filters as $column => $value) { | 
					
						
							| 
									
										
										
										
											2024-04-28 09:54:28 +02:00
										 |  |  |             // filter on NULL values
 | 
					
						
							| 
									
										
										
										
											2024-04-28 14:40:22 +02:00
										 |  |  |             if (null === $value) { | 
					
						
							| 
									
										
										
										
											2024-04-28 09:54:28 +02:00
										 |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if ('active' === $column) { | 
					
						
							|  |  |  |                 $query->where('accounts.active', $value); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2024-04-28 14:40:22 +02:00
										 |  |  |             if ('name' === $column) { | 
					
						
							| 
									
										
										
										
											2024-10-10 06:30:05 +02:00
										 |  |  |                 $query->whereLike('accounts.name', sprintf('%%%s%%', $value)); | 
					
						
							| 
									
										
										
										
											2024-04-28 13:30:42 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2024-04-28 09:54:28 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-04 20:41:34 +01:00
										 |  |  |         // add sort parameters. At this point they're filtered to allowed fields to sort by:
 | 
					
						
							| 
									
										
										
										
											2024-03-24 11:08:24 +01:00
										 |  |  |         $hasActiveColumn = array_key_exists('active', $sort); | 
					
						
							| 
									
										
										
										
											2024-03-09 19:31:27 +01:00
										 |  |  |         if (count($sort) > 0) { | 
					
						
							| 
									
										
										
										
											2024-03-24 11:08:24 +01:00
										 |  |  |             if (false === $hasActiveColumn) { | 
					
						
							|  |  |  |                 $query->orderBy('accounts.active', 'DESC'); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2024-03-09 19:31:27 +01:00
										 |  |  |             foreach ($sort as $column => $direction) { | 
					
						
							|  |  |  |                 if (in_array($column, $sortable, true)) { | 
					
						
							|  |  |  |                     $query->orderBy(sprintf('accounts.%s', $column), $direction); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2024-03-04 20:41:34 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (0 === count($sort)) { | 
					
						
							| 
									
										
										
										
											2024-03-06 07:16:01 +01:00
										 |  |  |             if (0 !== count($res)) { | 
					
						
							| 
									
										
										
										
											2024-03-24 11:08:24 +01:00
										 |  |  |                 $query->orderBy('accounts.active', 'DESC'); | 
					
						
							| 
									
										
										
										
											2024-03-06 07:16:01 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2024-03-24 11:08:24 +01:00
										 |  |  |             $query->orderBy('accounts.order', 'ASC'); | 
					
						
							| 
									
										
										
										
											2024-03-04 20:41:34 +01:00
										 |  |  |             $query->orderBy('accounts.name', 'ASC'); | 
					
						
							| 
									
										
										
										
											2025-02-19 06:21:27 +01:00
										 |  |  |             $query->orderBy('accounts.account_type_id', 'ASC'); | 
					
						
							|  |  |  |             $query->orderBy('accounts.id', 'ASC'); | 
					
						
							| 
									
										
										
										
											2024-03-04 20:41:34 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $query->get(['accounts.*']); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-27 16:57:36 +02:00
										 |  |  |     #[Override]
 | 
					
						
							| 
									
										
										
										
											2024-12-22 08:43:12 +01:00
										 |  |  |     public function update(Account $account, array $data): Account | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         /** @var AccountUpdateService $service */ | 
					
						
							|  |  |  |         $service = app(AccountUpdateService::class); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $service->update($account, $data); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-20 10:16:54 +02:00
										 |  |  |     public function searchAccount(string $query, array $types, int $page, int $limit): Collection | 
					
						
							| 
									
										
										
										
											2024-03-04 20:41:34 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-03-06 07:16:01 +01:00
										 |  |  |         // search by group, not by user
 | 
					
						
							|  |  |  |         $dbQuery = $this->userGroup->accounts() | 
					
						
							| 
									
										
										
										
											2025-03-14 17:45:16 +01:00
										 |  |  |             ->where('active', true) | 
					
						
							|  |  |  |             ->orderBy('accounts.updated_at', 'ASC') | 
					
						
							|  |  |  |             ->orderBy('accounts.order', 'ASC') | 
					
						
							|  |  |  |             ->orderBy('accounts.account_type_id', 'ASC') | 
					
						
							|  |  |  |             ->orderBy('accounts.name', 'ASC') | 
					
						
							|  |  |  |             ->with(['accountType']) | 
					
						
							|  |  |  |         ; | 
					
						
							| 
									
										
										
										
											2024-10-20 10:16:54 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // split query on spaces just in case:
 | 
					
						
							| 
									
										
										
										
											2024-10-21 05:15:16 +02:00
										 |  |  |         if ('' !== trim($query)) { | 
					
						
							| 
									
										
										
										
											2024-05-19 10:26:25 +02:00
										 |  |  |             $dbQuery->where(function (EloquentBuilder $q) use ($query): void { | 
					
						
							| 
									
										
										
										
											2024-10-20 10:16:54 +02:00
										 |  |  |                 $parts = explode(' ', $query); | 
					
						
							|  |  |  |                 foreach ($parts as $part) { | 
					
						
							|  |  |  |                     $search = sprintf('%%%s%%', $part); | 
					
						
							|  |  |  |                     $q->orWhereLike('name', $search); | 
					
						
							| 
									
										
										
										
											2024-05-19 06:36:31 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |             }); | 
					
						
							| 
									
										
										
										
											2024-03-06 07:16:01 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2024-10-20 10:16:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-04 20:41:34 +01:00
										 |  |  |         if (0 !== count($types)) { | 
					
						
							| 
									
										
										
										
											2024-03-06 07:16:01 +01:00
										 |  |  |             $dbQuery->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id'); | 
					
						
							|  |  |  |             $dbQuery->whereIn('account_types.type', $types); | 
					
						
							| 
									
										
										
										
											2024-03-04 20:41:34 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2024-03-05 19:38:45 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-21 05:15:16 +02:00
										 |  |  |         $dbQuery->skip(($page - 1) * $limit)->take($limit); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-20 10:16:54 +02:00
										 |  |  |         return $dbQuery->get(['accounts.*']); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-04 20:41:34 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-03-25 11:32:33 +01:00
										 |  |  | } |