From 13fc7f0d8d8f831dc914dce33b67f8dd13121942 Mon Sep 17 00:00:00 2001 From: James Cole Date: Wed, 19 Feb 2025 06:21:27 +0100 Subject: [PATCH 01/23] Fix #9862 --- app/Repositories/Account/AccountRepository.php | 2 ++ app/Repositories/UserGroups/Account/AccountRepository.php | 2 ++ 2 files changed, 4 insertions(+) diff --git a/app/Repositories/Account/AccountRepository.php b/app/Repositories/Account/AccountRepository.php index 57728ffe9b..02e06bb0f4 100644 --- a/app/Repositories/Account/AccountRepository.php +++ b/app/Repositories/Account/AccountRepository.php @@ -498,6 +498,8 @@ class AccountRepository implements AccountRepositoryInterface } $query->orderBy('accounts.active', 'DESC'); $query->orderBy('accounts.name', 'ASC'); + $query->orderBy('accounts.account_type_id', 'ASC'); + $query->orderBy('accounts.id', 'ASC'); } return $query->get(['accounts.*']); diff --git a/app/Repositories/UserGroups/Account/AccountRepository.php b/app/Repositories/UserGroups/Account/AccountRepository.php index 6e70c4cf94..912a4d0e0e 100644 --- a/app/Repositories/UserGroups/Account/AccountRepository.php +++ b/app/Repositories/UserGroups/Account/AccountRepository.php @@ -361,6 +361,8 @@ class AccountRepository implements AccountRepositoryInterface } $query->orderBy('accounts.order', 'ASC'); $query->orderBy('accounts.name', 'ASC'); + $query->orderBy('accounts.account_type_id', 'ASC'); + $query->orderBy('accounts.id', 'ASC'); } return $query->get(['accounts.*']); From 30007b05cb0d8f70a459122992de262d40a1580a Mon Sep 17 00:00:00 2001 From: James Cole Date: Wed, 19 Feb 2025 06:37:40 +0100 Subject: [PATCH 02/23] Fix #9861 --- app/Repositories/PiggyBank/ModifiesPiggyBanks.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Repositories/PiggyBank/ModifiesPiggyBanks.php b/app/Repositories/PiggyBank/ModifiesPiggyBanks.php index 6e52c4856b..c4cd2725c7 100644 --- a/app/Repositories/PiggyBank/ModifiesPiggyBanks.php +++ b/app/Repositories/PiggyBank/ModifiesPiggyBanks.php @@ -233,8 +233,8 @@ trait ModifiesPiggyBanks $difference = bcsub($piggyBank->target_amount, $currentAmount); // an amount will be removed, create "negative" event: - Log::debug(sprintf('ChangedAmount: is triggered with difference "%s"', $difference)); - event(new ChangedAmount($piggyBank, $difference, null, null)); +// Log::debug(sprintf('ChangedAmount: is triggered with difference "%s"', $difference)); +// event(new ChangedAmount($piggyBank, $difference, null, null)); // question is, from which account(s) to remove the difference? // solution: just start from the top until there is no more money left to remove. From e0709f29757b1da434eb4c7419a2e4787764ee8b Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 19 Feb 2025 09:14:18 +0100 Subject: [PATCH 03/23] Auto commit for release 'develop' on 2025-02-19 --- .ci/php-cs-fixer/composer.lock | 12 ++++++------ app/Repositories/PiggyBank/ModifiesPiggyBanks.php | 4 ++-- config/firefly.php | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.ci/php-cs-fixer/composer.lock b/.ci/php-cs-fixer/composer.lock index e6e7554c13..6ec2d09671 100644 --- a/.ci/php-cs-fixer/composer.lock +++ b/.ci/php-cs-fixer/composer.lock @@ -406,16 +406,16 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.69.0", + "version": "v3.69.1", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "630a59448c00729bc235d5e95cfedefeaca37523" + "reference": "13b0c0eede38c11cd674b080f2b485d0f14ffa9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/630a59448c00729bc235d5e95cfedefeaca37523", - "reference": "630a59448c00729bc235d5e95cfedefeaca37523", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/13b0c0eede38c11cd674b080f2b485d0f14ffa9f", + "reference": "13b0c0eede38c11cd674b080f2b485d0f14ffa9f", "shasum": "" }, "require": { @@ -497,7 +497,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.69.0" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.69.1" }, "funding": [ { @@ -505,7 +505,7 @@ "type": "github" } ], - "time": "2025-02-14T16:19:23+00:00" + "time": "2025-02-18T23:57:43+00:00" }, { "name": "psr/container", diff --git a/app/Repositories/PiggyBank/ModifiesPiggyBanks.php b/app/Repositories/PiggyBank/ModifiesPiggyBanks.php index c4cd2725c7..d00b74c58b 100644 --- a/app/Repositories/PiggyBank/ModifiesPiggyBanks.php +++ b/app/Repositories/PiggyBank/ModifiesPiggyBanks.php @@ -233,8 +233,8 @@ trait ModifiesPiggyBanks $difference = bcsub($piggyBank->target_amount, $currentAmount); // an amount will be removed, create "negative" event: -// Log::debug(sprintf('ChangedAmount: is triggered with difference "%s"', $difference)); -// event(new ChangedAmount($piggyBank, $difference, null, null)); + // Log::debug(sprintf('ChangedAmount: is triggered with difference "%s"', $difference)); + // event(new ChangedAmount($piggyBank, $difference, null, null)); // question is, from which account(s) to remove the difference? // solution: just start from the top until there is no more money left to remove. diff --git a/config/firefly.php b/config/firefly.php index 0d150159a7..a042e69f94 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -81,7 +81,7 @@ return [ 'running_balance_column' => env('USE_RUNNING_BALANCE', false), // see cer.php for exchange rates feature flag. ], - 'version' => '6.2.7', + 'version' => 'develop/2025-02-19', 'api_version' => '2.1.0', // field is no longer used. 'db_version' => 25, From adbf6defe527da6e44ae976098da132f744239c7 Mon Sep 17 00:00:00 2001 From: James Cole Date: Thu, 20 Feb 2025 06:21:29 +0100 Subject: [PATCH 04/23] Catch nullpointer. --- .../JsonApi/Enrichments/AccountEnrichment.php | 26 +------------------ 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/app/Support/JsonApi/Enrichments/AccountEnrichment.php b/app/Support/JsonApi/Enrichments/AccountEnrichment.php index 6180c6f7ca..92a2bb3476 100644 --- a/app/Support/JsonApi/Enrichments/AccountEnrichment.php +++ b/app/Support/JsonApi/Enrichments/AccountEnrichment.php @@ -117,30 +117,6 @@ class AccountEnrichment implements EnrichmentInterface $this->collectNotes(); $this->collectLocations(); $this->collectOpeningBalances(); - // $this->default = app('amount')->getNativeCurrency(); - // $this->currencies = []; - // $this->balances = []; - // $this->objectGroups = []; - // $this->grouped = []; - // - // // do everything here: - // $this->getLastActivity(); - // $this->collectAccountTypes(); - // $this->collectMetaData(); - // $this->getMetaBalances(); - // $this->getObjectGroups(); - - // $this->collection->transform(function (Account $account) { - // $account->user_array = ['id' => 1, 'bla bla' => 'bla']; - // $account->balances = collect([ - // ['balance_id' => 1, 'balance' => 5], - // ['balance_id' => 2, 'balance' => 5], - // ['balance_id' => 3, 'balance' => 5], - // ]); - // - // return $account; - // }); - $this->appendCollectedData(); return $this->collection; @@ -275,7 +251,7 @@ class AccountEnrichment implements EnrichmentInterface $this->currencies[(int) $currency->id] = $currency; } foreach ($this->currencies as $id => $currency) { - if (true === $currency) { + if (true === $currency && 0 !== (int) $id) { throw new FireflyException(sprintf('Currency #%d not found.', $id)); } } From f7f317a3b2c38e0f9b00150a4d20df4ed5e810a4 Mon Sep 17 00:00:00 2001 From: James Cole Date: Thu, 20 Feb 2025 07:28:24 +0100 Subject: [PATCH 05/23] Fix #9863 --- app/Support/Preferences.php | 87 +++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 37 deletions(-) diff --git a/app/Support/Preferences.php b/app/Support/Preferences.php index 99427071e5..6da4d74d00 100644 --- a/app/Support/Preferences.php +++ b/app/Support/Preferences.php @@ -47,16 +47,15 @@ class Preferences } return Preference::where('user_id', $user->id) - ->where('name', '!=', 'currencyPreference') - ->where(function (Builder $q) use ($user): void { - $q->whereNull('user_group_id'); - $q->orWhere('user_group_id', $user->user_group_id); - }) - ->get() - ; + ->where('name', '!=', 'currencyPreference') + ->where(function (Builder $q) use ($user): void { + $q->whereNull('user_group_id'); + $q->orWhere('user_group_id', $user->user_group_id); + }) + ->get(); } - public function get(string $name, null|array|bool|int|string $default = null): ?Preference + public function get(string $name, null | array | bool | int | string $default = null): ?Preference { /** @var null|User $user */ $user = auth()->user(); @@ -70,22 +69,32 @@ class Preferences return $this->getForUser($user, $name, $default); } - public function getForUser(User $user, string $name, null|array|bool|int|string $default = null): ?Preference + public function getForUser(User $user, string $name, null | array | bool | int | string $default = null): ?Preference { + Log::debug(sprintf('getForUser(#%d, "%s")', $user->id, $name)); // don't care about user group ID, except for some specific preferences. $userGroupId = $this->getUserGroupId($user, $name); - $preference = Preference::where('user_group_id', $userGroupId)->where('user_id', $user->id)->where('name', $name)->first(['id', 'user_id', 'name', 'data', 'updated_at', 'created_at']); + $query = Preference::where('user_id', $user->id)->where('name', $name); + if (null !== $userGroupId) { + Log::debug('Include user group ID in query'); + $query->where('user_group_id', $userGroupId); + } + + $preference = $query->first(['id', 'user_id', 'user_group_id', 'name', 'data', 'updated_at', 'created_at']); if (null !== $preference && null === $preference->data) { $preference->delete(); $preference = null; + Log::debug('Removed empty preference.'); } if (null !== $preference) { + Log::debug(sprintf('Found preference #%d for user #%d: %s', $preference->id, $user->id, $name)); return $preference; } // no preference found and default is null: if (null === $default) { + Log::debug('Return NULL, create no preference.'); // return NULL return null; } @@ -122,37 +131,42 @@ class Preferences Cache::put($key, '', 5); } - public function setForUser(User $user, string $name, null|array|bool|int|string $value): Preference + public function setForUser(User $user, string $name, null | array | bool | int | string $value): Preference { - $fullName = sprintf('preference%s%s', $user->id, $name); - $groupId = $this->getUserGroupId($user, $name); - $groupId = 0 === (int) $groupId ? null : (int) $groupId; + $fullName = sprintf('preference%s%s', $user->id, $name); + $userGroupId = $this->getUserGroupId($user, $name); + $userGroupId = 0 === (int) $userGroupId ? null : (int) $userGroupId; Cache::forget($fullName); - /** @var null|Preference $pref */ - $pref = Preference::where('user_group_id', $groupId)->where('user_id', $user->id)->where('name', $name)->first(['id', 'name', 'data', 'updated_at', 'created_at']); + $query = Preference::where('user_id', $user->id)->where('name', $name); + if (null !== $userGroupId) { + Log::debug('Include user group ID in query'); + $query->where('user_group_id', $userGroupId); + } - if (null !== $pref && null === $value) { - $pref->delete(); + $preference = $query->first(['id', 'user_id', 'user_group_id', 'name', 'data', 'updated_at', 'created_at']); + + if (null !== $preference && null === $value) { + $preference->delete(); return new Preference(); } if (null === $value) { return new Preference(); } - if (null === $pref) { - $pref = new Preference(); - $pref->user_id = (int) $user->id; - $pref->user_group_id = $groupId; - $pref->name = $name; + if (null === $preference) { + $preference = new Preference(); + $preference->user_id = (int) $user->id; + $preference->user_group_id = $userGroupId; + $preference->name = $name; } - $pref->data = $value; - $pref->save(); - Cache::forever($fullName, $pref); + $preference->data = $value; + $preference->save(); + Cache::forever($fullName, $preference); - return $pref; + return $preference; } public function beginsWith(User $user, string $search): Collection @@ -174,13 +188,12 @@ class Preferences { $result = []; $preferences = Preference::where('user_id', $user->id) - ->where(function (Builder $q) use ($user): void { - $q->whereNull('user_group_id'); - $q->orWhere('user_group_id', $user->user_group_id); - }) - ->whereIn('name', $list) - ->get(['id', 'name', 'data']) - ; + ->where(function (Builder $q) use ($user): void { + $q->whereNull('user_group_id'); + $q->orWhere('user_group_id', $user->user_group_id); + }) + ->whereIn('name', $list) + ->get(['id', 'name', 'data']); /** @var Preference $preference */ foreach ($preferences as $preference) { @@ -222,7 +235,7 @@ class Preferences return $result; } - public function getEncryptedForUser(User $user, string $name, null|array|bool|int|string $default = null): ?Preference + public function getEncryptedForUser(User $user, string $name, null | array | bool | int | string $default = null): ?Preference { $result = $this->getForUser($user, $name, $default); if ('' === $result->data) { @@ -247,7 +260,7 @@ class Preferences return $result; } - public function getFresh(string $name, null|array|bool|int|string $default = null): ?Preference + public function getFresh(string $name, null | array | bool | int | string $default = null): ?Preference { /** @var null|User $user */ $user = auth()->user(); @@ -285,7 +298,7 @@ class Preferences Session::forget('first'); } - public function set(string $name, null|array|bool|int|string $value): Preference + public function set(string $name, null | array | bool | int | string $value): Preference { /** @var null|User $user */ $user = auth()->user(); From ea337607c4106668caabc9ef8e29a0bf36f88fed Mon Sep 17 00:00:00 2001 From: James Cole Date: Thu, 20 Feb 2025 07:30:30 +0100 Subject: [PATCH 06/23] Fix #9868 --- .../TransactionGroupTransformer.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/app/Transformers/TransactionGroupTransformer.php b/app/Transformers/TransactionGroupTransformer.php index 11f992f00e..d670901ada 100644 --- a/app/Transformers/TransactionGroupTransformer.php +++ b/app/Transformers/TransactionGroupTransformer.php @@ -131,7 +131,7 @@ class TransactionGroupTransformer extends AbstractTransformer return [ 'user' => (string) $transaction['user_id'], - 'transaction_journal_id' => $transaction['transaction_journal_id'], + 'transaction_journal_id' => (string) $transaction['transaction_journal_id'], 'type' => strtolower($type), 'date' => $transaction['date']->toAtomString(), 'order' => $transaction['order'], @@ -320,17 +320,17 @@ class TransactionGroupTransformer extends AbstractTransformer return [ 'user' => $journal->user_id, - 'transaction_journal_id' => $journal->id, + 'transaction_journal_id' => (string) $journal->id, 'type' => strtolower($type), 'date' => $journal->date->toAtomString(), 'order' => $journal->order, - 'currency_id' => $currency->id, + 'currency_id' => (string) $currency->id, 'currency_code' => $currency->code, 'currency_symbol' => $currency->symbol, 'currency_decimal_places' => $currency->decimal_places, - 'foreign_currency_id' => $foreignCurrency['id'], + 'foreign_currency_id' => (string) $foreignCurrency['id'], 'foreign_currency_code' => $foreignCurrency['code'], 'foreign_currency_symbol' => $foreignCurrency['symbol'], 'foreign_currency_decimal_places' => $foreignCurrency['decimal_places'], @@ -340,23 +340,23 @@ class TransactionGroupTransformer extends AbstractTransformer 'description' => $journal->description, - 'source_id' => $source->account_id, + 'source_id' => (string) $source->account_id, 'source_name' => $source->account->name, 'source_iban' => $source->account->iban, 'source_type' => $source->account->accountType->type, - 'destination_id' => $destination->account_id, + 'destination_id' => (string) $destination->account_id, 'destination_name' => $destination->account->name, 'destination_iban' => $destination->account->iban, 'destination_type' => $destination->account->accountType->type, - 'budget_id' => $budget['id'], + 'budget_id' => (string) $budget['id'], 'budget_name' => $budget['name'], - 'category_id' => $category['id'], + 'category_id' => (string) $category['id'], 'category_name' => $category['name'], - 'bill_id' => $bill['id'], + 'bill_id' => (string) $bill['id'], 'bill_name' => $bill['name'], 'reconciled' => $source->reconciled, From 2e3669a32fc1ad48fef1a65833da24a140ecc0cd Mon Sep 17 00:00:00 2001 From: James Cole Date: Thu, 20 Feb 2025 07:43:32 +0100 Subject: [PATCH 07/23] Fix #9871 --- app/Support/JsonApi/Enrichments/AccountEnrichment.php | 2 +- app/Transformers/AccountTransformer.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Support/JsonApi/Enrichments/AccountEnrichment.php b/app/Support/JsonApi/Enrichments/AccountEnrichment.php index 92a2bb3476..4e62c1c0cd 100644 --- a/app/Support/JsonApi/Enrichments/AccountEnrichment.php +++ b/app/Support/JsonApi/Enrichments/AccountEnrichment.php @@ -234,7 +234,7 @@ class AccountEnrichment implements EnrichmentInterface private function collectMetaData(): void { - $set = AccountMeta::whereIn('name', ['is_multi_currency', 'currency_id', 'account_role', 'account_number', 'liability_direction', 'interest', 'interest_period', 'current_debt']) + $set = AccountMeta::whereIn('name', ['is_multi_currency', 'include_net_worth','currency_id', 'account_role', 'account_number', 'liability_direction', 'interest', 'interest_period', 'current_debt']) ->whereIn('account_id', $this->accountIds) ->get(['account_meta.id', 'account_meta.account_id', 'account_meta.name', 'account_meta.data'])->toArray() ; diff --git a/app/Transformers/AccountTransformer.php b/app/Transformers/AccountTransformer.php index e536f078c6..e48f0205b4 100644 --- a/app/Transformers/AccountTransformer.php +++ b/app/Transformers/AccountTransformer.php @@ -92,7 +92,7 @@ class AccountTransformer extends AbstractTransformer $decimalPlaces = (int) $account->meta['currency']?->decimal_places; $decimalPlaces = 0 === $decimalPlaces ? 2 : $decimalPlaces; $openingBalance = Steam::bcround($openingBalance, $decimalPlaces); - $includeNetWorth = '0' !== ($account->meta['include_net_worth'] ?? null); + $includeNetWorth = 1 === (int) ($account->meta['include_net_worth'] ?? 0); $longitude = $account->meta['location']['longitude'] ?? null; $latitude = $account->meta['location']['latitude'] ?? null; $zoomLevel = $account->meta['location']['zoom_level'] ?? null; From 12629a19551ebe41f9b2c0acf767bd973d050700 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 20 Feb 2025 08:00:12 +0100 Subject: [PATCH 08/23] Auto commit for release 'develop' on 2025-02-20 --- .../JsonApi/Enrichments/AccountEnrichment.php | 2 +- app/Support/Preferences.php | 52 ++++++++++--------- composer.lock | 20 +++---- config/firefly.php | 2 +- package-lock.json | 20 +++---- resources/assets/v1/src/locales/it.json | 4 +- 6 files changed, 52 insertions(+), 48 deletions(-) diff --git a/app/Support/JsonApi/Enrichments/AccountEnrichment.php b/app/Support/JsonApi/Enrichments/AccountEnrichment.php index 4e62c1c0cd..8a98985a5c 100644 --- a/app/Support/JsonApi/Enrichments/AccountEnrichment.php +++ b/app/Support/JsonApi/Enrichments/AccountEnrichment.php @@ -234,7 +234,7 @@ class AccountEnrichment implements EnrichmentInterface private function collectMetaData(): void { - $set = AccountMeta::whereIn('name', ['is_multi_currency', 'include_net_worth','currency_id', 'account_role', 'account_number', 'liability_direction', 'interest', 'interest_period', 'current_debt']) + $set = AccountMeta::whereIn('name', ['is_multi_currency', 'include_net_worth', 'currency_id', 'account_role', 'account_number', 'liability_direction', 'interest', 'interest_period', 'current_debt']) ->whereIn('account_id', $this->accountIds) ->get(['account_meta.id', 'account_meta.account_id', 'account_meta.name', 'account_meta.data'])->toArray() ; diff --git a/app/Support/Preferences.php b/app/Support/Preferences.php index 6da4d74d00..baa577ab4f 100644 --- a/app/Support/Preferences.php +++ b/app/Support/Preferences.php @@ -47,15 +47,16 @@ class Preferences } return Preference::where('user_id', $user->id) - ->where('name', '!=', 'currencyPreference') - ->where(function (Builder $q) use ($user): void { - $q->whereNull('user_group_id'); - $q->orWhere('user_group_id', $user->user_group_id); - }) - ->get(); + ->where('name', '!=', 'currencyPreference') + ->where(function (Builder $q) use ($user): void { + $q->whereNull('user_group_id'); + $q->orWhere('user_group_id', $user->user_group_id); + }) + ->get() + ; } - public function get(string $name, null | array | bool | int | string $default = null): ?Preference + public function get(string $name, null|array|bool|int|string $default = null): ?Preference { /** @var null|User $user */ $user = auth()->user(); @@ -69,7 +70,7 @@ class Preferences return $this->getForUser($user, $name, $default); } - public function getForUser(User $user, string $name, null | array | bool | int | string $default = null): ?Preference + public function getForUser(User $user, string $name, null|array|bool|int|string $default = null): ?Preference { Log::debug(sprintf('getForUser(#%d, "%s")', $user->id, $name)); // don't care about user group ID, except for some specific preferences. @@ -80,7 +81,7 @@ class Preferences $query->where('user_group_id', $userGroupId); } - $preference = $query->first(['id', 'user_id', 'user_group_id', 'name', 'data', 'updated_at', 'created_at']); + $preference = $query->first(['id', 'user_id', 'user_group_id', 'name', 'data', 'updated_at', 'created_at']); if (null !== $preference && null === $preference->data) { $preference->delete(); @@ -90,11 +91,13 @@ class Preferences if (null !== $preference) { Log::debug(sprintf('Found preference #%d for user #%d: %s', $preference->id, $user->id, $name)); + return $preference; } // no preference found and default is null: if (null === $default) { Log::debug('Return NULL, create no preference.'); + // return NULL return null; } @@ -131,21 +134,21 @@ class Preferences Cache::put($key, '', 5); } - public function setForUser(User $user, string $name, null | array | bool | int | string $value): Preference + public function setForUser(User $user, string $name, null|array|bool|int|string $value): Preference { - $fullName = sprintf('preference%s%s', $user->id, $name); - $userGroupId = $this->getUserGroupId($user, $name); - $userGroupId = 0 === (int) $userGroupId ? null : (int) $userGroupId; + $fullName = sprintf('preference%s%s', $user->id, $name); + $userGroupId = $this->getUserGroupId($user, $name); + $userGroupId = 0 === (int) $userGroupId ? null : (int) $userGroupId; Cache::forget($fullName); - $query = Preference::where('user_id', $user->id)->where('name', $name); + $query = Preference::where('user_id', $user->id)->where('name', $name); if (null !== $userGroupId) { Log::debug('Include user group ID in query'); $query->where('user_group_id', $userGroupId); } - $preference = $query->first(['id', 'user_id', 'user_group_id', 'name', 'data', 'updated_at', 'created_at']); + $preference = $query->first(['id', 'user_id', 'user_group_id', 'name', 'data', 'updated_at', 'created_at']); if (null !== $preference && null === $value) { $preference->delete(); @@ -188,12 +191,13 @@ class Preferences { $result = []; $preferences = Preference::where('user_id', $user->id) - ->where(function (Builder $q) use ($user): void { - $q->whereNull('user_group_id'); - $q->orWhere('user_group_id', $user->user_group_id); - }) - ->whereIn('name', $list) - ->get(['id', 'name', 'data']); + ->where(function (Builder $q) use ($user): void { + $q->whereNull('user_group_id'); + $q->orWhere('user_group_id', $user->user_group_id); + }) + ->whereIn('name', $list) + ->get(['id', 'name', 'data']) + ; /** @var Preference $preference */ foreach ($preferences as $preference) { @@ -235,7 +239,7 @@ class Preferences return $result; } - public function getEncryptedForUser(User $user, string $name, null | array | bool | int | string $default = null): ?Preference + public function getEncryptedForUser(User $user, string $name, null|array|bool|int|string $default = null): ?Preference { $result = $this->getForUser($user, $name, $default); if ('' === $result->data) { @@ -260,7 +264,7 @@ class Preferences return $result; } - public function getFresh(string $name, null | array | bool | int | string $default = null): ?Preference + public function getFresh(string $name, null|array|bool|int|string $default = null): ?Preference { /** @var null|User $user */ $user = auth()->user(); @@ -298,7 +302,7 @@ class Preferences Session::forget('first'); } - public function set(string $name, null | array | bool | int | string $value): Preference + public function set(string $name, null|array|bool|int|string $value): Preference { /** @var null|User $user */ $user = auth()->user(); diff --git a/composer.lock b/composer.lock index 95086b3e97..f25084387e 100644 --- a/composer.lock +++ b/composer.lock @@ -1874,16 +1874,16 @@ }, { "name": "laravel/framework", - "version": "v11.43.0", + "version": "v11.43.2", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "70760d976486310b11d8e487e873077db069e77a" + "reference": "99d1573698abc42222f04d25fcd5b213d0eedf21" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/70760d976486310b11d8e487e873077db069e77a", - "reference": "70760d976486310b11d8e487e873077db069e77a", + "url": "https://api.github.com/repos/laravel/framework/zipball/99d1573698abc42222f04d25fcd5b213d0eedf21", + "reference": "99d1573698abc42222f04d25fcd5b213d0eedf21", "shasum": "" }, "require": { @@ -2085,7 +2085,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-02-18T15:37:56+00:00" + "time": "2025-02-19T21:53:48+00:00" }, { "name": "laravel/passport", @@ -11267,16 +11267,16 @@ }, { "name": "phpstan/phpstan", - "version": "2.1.5", + "version": "2.1.6", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "451b17f9665481ee502adc39be987cb71067ece2" + "reference": "6eaec7c6c9e90dcfe46ad1e1ffa5171e2dab641c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/451b17f9665481ee502adc39be987cb71067ece2", - "reference": "451b17f9665481ee502adc39be987cb71067ece2", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/6eaec7c6c9e90dcfe46ad1e1ffa5171e2dab641c", + "reference": "6eaec7c6c9e90dcfe46ad1e1ffa5171e2dab641c", "shasum": "" }, "require": { @@ -11321,7 +11321,7 @@ "type": "github" } ], - "time": "2025-02-13T12:49:56+00:00" + "time": "2025-02-19T15:46:42+00:00" }, { "name": "phpstan/phpstan-deprecation-rules", diff --git a/config/firefly.php b/config/firefly.php index a042e69f94..dbbcf59e37 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -81,7 +81,7 @@ return [ 'running_balance_column' => env('USE_RUNNING_BALANCE', false), // see cer.php for exchange rates feature flag. ], - 'version' => 'develop/2025-02-19', + 'version' => 'develop/2025-02-20', 'api_version' => '2.1.0', // field is no longer used. 'db_version' => 25, diff --git a/package-lock.json b/package-lock.json index 29d84889fd..f22be6ba87 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4510,9 +4510,9 @@ } }, "node_modules/chart.js": { - "version": "4.4.7", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.7.tgz", - "integrity": "sha512-pwkcKfdzTMAU/+jNosKhNL2bHtJc/sSmYgVbuGTEDhzkrhmyihmP7vUc/5ZK9WopidMDHNe3Wm7jOd/WhuHWuw==", + "version": "4.4.8", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.8.tgz", + "integrity": "sha512-IkGZlVpXP+83QpMm4uxEiGqSI7jFizwVtF3+n5Pc3k7sMO+tkd0qxh2OzLhenM0K80xtmAONWGBn082EiBQSDA==", "license": "MIT", "dependencies": { "@kurkle/color": "^0.3.0" @@ -8901,9 +8901,9 @@ } }, "node_modules/postcss": { - "version": "8.5.2", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.2.tgz", - "integrity": "sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==", + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", "dev": true, "funding": [ { @@ -11344,14 +11344,14 @@ } }, "node_modules/vite": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.1.0.tgz", - "integrity": "sha512-RjjMipCKVoR4hVfPY6GQTgveinjNuyLw+qruksLDvA5ktI1150VmcMBKmQaEWJhg/j6Uaf6dNCNA0AfdzUb/hQ==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.1.1.tgz", + "integrity": "sha512-4GgM54XrwRfrOp297aIYspIti66k56v16ZnqHvrIM7mG+HjDlAwS7p+Srr7J6fGvEdOJ5JcQ/D9T7HhtdXDTzA==", "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.24.2", - "postcss": "^8.5.1", + "postcss": "^8.5.2", "rollup": "^4.30.1" }, "bin": { diff --git a/resources/assets/v1/src/locales/it.json b/resources/assets/v1/src/locales/it.json index bd1457663d..29bc997a34 100644 --- a/resources/assets/v1/src/locales/it.json +++ b/resources/assets/v1/src/locales/it.json @@ -172,8 +172,8 @@ }, "list": { "title": "Titolo", - "active": "Attivo", - "native_currency": "Native currency", + "active": "\u00c8 attivo?", + "native_currency": "Valuta nativa", "trigger": "Trigger", "response": "Risposta", "delivery": "Consegna", From 334a521ca123a5819dd5a02a8c169b723f376756 Mon Sep 17 00:00:00 2001 From: James Cole Date: Thu, 20 Feb 2025 08:08:07 +0100 Subject: [PATCH 09/23] Better fix for nullpointer. --- app/Support/JsonApi/Enrichments/AccountEnrichment.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/Support/JsonApi/Enrichments/AccountEnrichment.php b/app/Support/JsonApi/Enrichments/AccountEnrichment.php index 4e62c1c0cd..c11fd4562e 100644 --- a/app/Support/JsonApi/Enrichments/AccountEnrichment.php +++ b/app/Support/JsonApi/Enrichments/AccountEnrichment.php @@ -250,8 +250,9 @@ class AccountEnrichment implements EnrichmentInterface foreach ($currencies as $currency) { $this->currencies[(int) $currency->id] = $currency; } + $this->currencies[0] = $this->native; foreach ($this->currencies as $id => $currency) { - if (true === $currency && 0 !== (int) $id) { + if (true === $currency) { throw new FireflyException(sprintf('Currency #%d not found.', $id)); } } From f95758ff4736cfa665d0b442f4bc5b67b96ed1ab Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 20 Feb 2025 08:11:36 +0100 Subject: [PATCH 10/23] Auto commit for release 'develop' on 2025-02-20 --- app/Support/JsonApi/Enrichments/AccountEnrichment.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Support/JsonApi/Enrichments/AccountEnrichment.php b/app/Support/JsonApi/Enrichments/AccountEnrichment.php index 9c1774b268..094fb7014c 100644 --- a/app/Support/JsonApi/Enrichments/AccountEnrichment.php +++ b/app/Support/JsonApi/Enrichments/AccountEnrichment.php @@ -234,7 +234,7 @@ class AccountEnrichment implements EnrichmentInterface private function collectMetaData(): void { - $set = AccountMeta::whereIn('name', ['is_multi_currency', 'include_net_worth', 'currency_id', 'account_role', 'account_number', 'liability_direction', 'interest', 'interest_period', 'current_debt']) + $set = AccountMeta::whereIn('name', ['is_multi_currency', 'include_net_worth', 'currency_id', 'account_role', 'account_number', 'liability_direction', 'interest', 'interest_period', 'current_debt']) ->whereIn('account_id', $this->accountIds) ->get(['account_meta.id', 'account_meta.account_id', 'account_meta.name', 'account_meta.data'])->toArray() ; @@ -246,7 +246,7 @@ class AccountEnrichment implements EnrichmentInterface $this->currencies[(int) $entry['data']] = true; } } - $currencies = TransactionCurrency::whereIn('id', array_keys($this->currencies))->get(); + $currencies = TransactionCurrency::whereIn('id', array_keys($this->currencies))->get(); foreach ($currencies as $currency) { $this->currencies[(int) $currency->id] = $currency; } From 54990308f688e84fa2c5d03aa0def5ba960703c4 Mon Sep 17 00:00:00 2001 From: Sander Dorigo Date: Thu, 20 Feb 2025 12:58:38 +0100 Subject: [PATCH 11/23] fix type error --- app/Http/Controllers/Transaction/ShowController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/Transaction/ShowController.php b/app/Http/Controllers/Transaction/ShowController.php index 2cd234f39a..5336712538 100644 --- a/app/Http/Controllers/Transaction/ShowController.php +++ b/app/Http/Controllers/Transaction/ShowController.php @@ -103,7 +103,7 @@ class ShowController extends Controller foreach (array_keys($groupArray['transactions']) as $index) { $groupArray['transactions'][$index]['tags'] = $this->repository->getTagObjects( - $groupArray['transactions'][$index]['transaction_journal_id'] + (int) $groupArray['transactions'][$index]['transaction_journal_id'] ); } From 58fab756810b27c41862e78b2672f4892be6f6e7 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Thu, 20 Feb 2025 14:51:04 -0500 Subject: [PATCH 12/23] fix: ignore the Procfile when building the docker image The Procfile is heroku-specific, causing issues on platforms which respect it when specifying processes to run for docker image or dockerfile based deploys. Closes #9833 Signed-off-by: Jose Diaz-Gonzalez --- .dockerignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..ab76ba7a2d --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +Procfile From 9921c5a9254905e1d9a6e9c9f52f53db7c54361f Mon Sep 17 00:00:00 2001 From: James Cole Date: Fri, 21 Feb 2025 06:18:11 +0100 Subject: [PATCH 13/23] Fix #9882 --- .../Models/Transaction/StoreController.php | 1 + .../Model/Transaction/StoreController.php | 1 + .../Commands/Upgrade/UpgradesToGroups.php | 3 +- .../Account/ReconcileController.php | 29 ++++++++++--------- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/app/Api/V1/Controllers/Models/Transaction/StoreController.php b/app/Api/V1/Controllers/Models/Transaction/StoreController.php index b9148c2ee1..03cbd54dab 100644 --- a/app/Api/V1/Controllers/Models/Transaction/StoreController.php +++ b/app/Api/V1/Controllers/Models/Transaction/StoreController.php @@ -90,6 +90,7 @@ class StoreController extends Controller $data['user'] = auth()->user(); $data['user_group'] = $this->userGroup; + Log::channel('audit')->info('Store new transaction over API.', $data); try { diff --git a/app/Api/V2/Controllers/Model/Transaction/StoreController.php b/app/Api/V2/Controllers/Model/Transaction/StoreController.php index 70988387b1..570313010c 100644 --- a/app/Api/V2/Controllers/Model/Transaction/StoreController.php +++ b/app/Api/V2/Controllers/Model/Transaction/StoreController.php @@ -73,6 +73,7 @@ class StoreController extends Controller $userGroup = $request->getUserGroup(); $data['user_group'] = $userGroup; + // overrule user group and see where we end up. // what happens when we refer to a budget that is not in this user group? diff --git a/app/Console/Commands/Upgrade/UpgradesToGroups.php b/app/Console/Commands/Upgrade/UpgradesToGroups.php index f847ca57f3..d1c0625efe 100644 --- a/app/Console/Commands/Upgrade/UpgradesToGroups.php +++ b/app/Console/Commands/Upgrade/UpgradesToGroups.php @@ -238,7 +238,8 @@ class UpgradesToGroups extends Command return [ 'type' => strtolower($journal->transactionType->type), 'date' => $journal->date, - 'user' => $journal->user_id, + 'user' => $journal->user, + 'user_group' => $journal->user->userGroup, 'currency_id' => $transaction->transaction_currency_id, 'foreign_currency_id' => $transaction->foreign_currency_id, 'amount' => $transaction->amount, diff --git a/app/Http/Controllers/Account/ReconcileController.php b/app/Http/Controllers/Account/ReconcileController.php index ee018d8bf2..095bfb6c34 100644 --- a/app/Http/Controllers/Account/ReconcileController.php +++ b/app/Http/Controllers/Account/ReconcileController.php @@ -87,10 +87,10 @@ class ReconcileController extends Controller return redirect(route('accounts.index', [config(sprintf('firefly.shortNamesByFullName.%s', $account->accountType->type))])); } - $currency = $this->accountRepos->getAccountCurrency($account) ?? $this->defaultCurrency; + $currency = $this->accountRepos->getAccountCurrency($account) ?? $this->defaultCurrency; // no start or end: - $range = app('navigation')->getViewRange(false); + $range = app('navigation')->getViewRange(false); // get start and end @@ -99,7 +99,7 @@ class ReconcileController extends Controller $start = clone session('start', app('navigation')->startOfPeriod(new Carbon(), $range)); /** @var Carbon $end */ - $end = clone session('end', app('navigation')->endOfPeriod(new Carbon(), $range)); + $end = clone session('end', app('navigation')->endOfPeriod(new Carbon(), $range)); } if (null === $end) { /** @var Carbon $end */ @@ -113,15 +113,15 @@ class ReconcileController extends Controller $start->startOfDay(); $end->endOfDay(); - $startDate = clone $start; + $startDate = clone $start; $startDate->subDay()->endOfDay(); // this is correct, subday endofday ends at 23:59:59 // both are validated and are correct. Log::debug(sprintf('reconcile: Call finalAccountBalance with date/time "%s"', $startDate->toIso8601String())); Log::debug(sprintf('reconcile2: Call finalAccountBalance with date/time "%s"', $end->toIso8601String())); - $startBalance = Steam::bcround(Steam::finalAccountBalance($account, $startDate)['balance'], $currency->decimal_places); - $endBalance = Steam::bcround(Steam::finalAccountBalance($account, $end)['balance'], $currency->decimal_places); - $subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $account->accountType->type)); - $subTitle = (string) trans('firefly.reconcile_account', ['account' => $account->name]); + $startBalance = Steam::bcround(Steam::finalAccountBalance($account, $startDate)['balance'], $currency->decimal_places); + $endBalance = Steam::bcround(Steam::finalAccountBalance($account, $end)['balance'], $currency->decimal_places); + $subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $account->accountType->type)); + $subTitle = (string) trans('firefly.reconcile_account', ['account' => $account->name]); // various links $transactionsUrl = route('accounts.reconcile.transactions', [$account->id, '%start%', '%end%']); @@ -162,7 +162,7 @@ class ReconcileController extends Controller } app('log')->debug('In ReconcileController::submit()'); - $data = $request->getAll(); + $data = $request->getAll(); /** @var string $journalId */ foreach ($data['journals'] as $journalId) { @@ -217,19 +217,20 @@ class ReconcileController extends Controller } // title: - $description = trans( + $description = trans( 'firefly.reconciliation_transaction_title', [ 'from' => $start->isoFormat($this->monthAndDayFormat), 'to' => $end->isoFormat($this->monthAndDayFormat), ] ); - $submission = [ + $submission = [ 'user' => auth()->user()->id, 'group_title' => null, 'transactions' => [ [ - 'user' => auth()->user()->id, + 'user' => auth()->user(), + 'user_group' => auth()->user()->userGroup, 'type' => strtolower(TransactionTypeEnum::RECONCILIATION->value), 'date' => $end, 'order' => 0, @@ -246,10 +247,10 @@ class ReconcileController extends Controller ]; /** @var TransactionGroupFactory $factory */ - $factory = app(TransactionGroupFactory::class); + $factory = app(TransactionGroupFactory::class); /** @var User $user */ - $user = auth()->user(); + $user = auth()->user(); $factory->setUser($user); try { From e452ba938d54776f68d42a43f4ff471ec134f723 Mon Sep 17 00:00:00 2001 From: James Cole Date: Fri, 21 Feb 2025 06:20:17 +0100 Subject: [PATCH 14/23] Update changelog. --- changelog.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/changelog.md b/changelog.md index d9329f5825..ccf470e37d 100644 --- a/changelog.md +++ b/changelog.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## 6.2.8 - 2025-02-22 + +### Fixed + +- #9861 +- #9862 +- #9863 +- #9868 +- #9871 +- #9882 + ## 6.2.7 - 2025-02-19 ### Changed From 56470bfbba3dc6b3411ab9e84e0e619d69e6c9b1 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 21 Feb 2025 08:32:55 +0100 Subject: [PATCH 15/23] Auto commit for release 'develop' on 2025-02-21 --- THANKS.md | 1 + .../Account/ReconcileController.php | 26 +++--- changelog.md | 12 +-- composer.lock | 82 +++++++++---------- config/firefly.php | 2 +- 5 files changed, 62 insertions(+), 61 deletions(-) diff --git a/THANKS.md b/THANKS.md index 08f7d1e678..90d3cf983f 100755 --- a/THANKS.md +++ b/THANKS.md @@ -4,6 +4,7 @@ Over time, many people have contributed to Firefly III. Their efforts are not al Please find below all the people who contributed to the Firefly III code. Their names are mentioned in the year of their first contribution. ## 2025 +- Jose Diaz-Gonzalez - SoftBrix ## 2024 diff --git a/app/Http/Controllers/Account/ReconcileController.php b/app/Http/Controllers/Account/ReconcileController.php index 095bfb6c34..8178076bdc 100644 --- a/app/Http/Controllers/Account/ReconcileController.php +++ b/app/Http/Controllers/Account/ReconcileController.php @@ -87,10 +87,10 @@ class ReconcileController extends Controller return redirect(route('accounts.index', [config(sprintf('firefly.shortNamesByFullName.%s', $account->accountType->type))])); } - $currency = $this->accountRepos->getAccountCurrency($account) ?? $this->defaultCurrency; + $currency = $this->accountRepos->getAccountCurrency($account) ?? $this->defaultCurrency; // no start or end: - $range = app('navigation')->getViewRange(false); + $range = app('navigation')->getViewRange(false); // get start and end @@ -99,7 +99,7 @@ class ReconcileController extends Controller $start = clone session('start', app('navigation')->startOfPeriod(new Carbon(), $range)); /** @var Carbon $end */ - $end = clone session('end', app('navigation')->endOfPeriod(new Carbon(), $range)); + $end = clone session('end', app('navigation')->endOfPeriod(new Carbon(), $range)); } if (null === $end) { /** @var Carbon $end */ @@ -113,15 +113,15 @@ class ReconcileController extends Controller $start->startOfDay(); $end->endOfDay(); - $startDate = clone $start; + $startDate = clone $start; $startDate->subDay()->endOfDay(); // this is correct, subday endofday ends at 23:59:59 // both are validated and are correct. Log::debug(sprintf('reconcile: Call finalAccountBalance with date/time "%s"', $startDate->toIso8601String())); Log::debug(sprintf('reconcile2: Call finalAccountBalance with date/time "%s"', $end->toIso8601String())); - $startBalance = Steam::bcround(Steam::finalAccountBalance($account, $startDate)['balance'], $currency->decimal_places); - $endBalance = Steam::bcround(Steam::finalAccountBalance($account, $end)['balance'], $currency->decimal_places); - $subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $account->accountType->type)); - $subTitle = (string) trans('firefly.reconcile_account', ['account' => $account->name]); + $startBalance = Steam::bcround(Steam::finalAccountBalance($account, $startDate)['balance'], $currency->decimal_places); + $endBalance = Steam::bcround(Steam::finalAccountBalance($account, $end)['balance'], $currency->decimal_places); + $subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $account->accountType->type)); + $subTitle = (string) trans('firefly.reconcile_account', ['account' => $account->name]); // various links $transactionsUrl = route('accounts.reconcile.transactions', [$account->id, '%start%', '%end%']); @@ -162,7 +162,7 @@ class ReconcileController extends Controller } app('log')->debug('In ReconcileController::submit()'); - $data = $request->getAll(); + $data = $request->getAll(); /** @var string $journalId */ foreach ($data['journals'] as $journalId) { @@ -217,14 +217,14 @@ class ReconcileController extends Controller } // title: - $description = trans( + $description = trans( 'firefly.reconciliation_transaction_title', [ 'from' => $start->isoFormat($this->monthAndDayFormat), 'to' => $end->isoFormat($this->monthAndDayFormat), ] ); - $submission = [ + $submission = [ 'user' => auth()->user()->id, 'group_title' => null, 'transactions' => [ @@ -247,10 +247,10 @@ class ReconcileController extends Controller ]; /** @var TransactionGroupFactory $factory */ - $factory = app(TransactionGroupFactory::class); + $factory = app(TransactionGroupFactory::class); /** @var User $user */ - $user = auth()->user(); + $user = auth()->user(); $factory->setUser($user); try { diff --git a/changelog.md b/changelog.md index ccf470e37d..19d525e969 100644 --- a/changelog.md +++ b/changelog.md @@ -7,12 +7,12 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Fixed -- #9861 -- #9862 -- #9863 -- #9868 -- #9871 -- #9882 +- [Issue 9861](https://github.com/firefly-iii/firefly-iii/issues/9861) (lower piggy amount when full creates double audit log entry) reported by @4e868df3 +- [Issue 9862](https://github.com/firefly-iii/firefly-iii/issues/9862) (Can't retrieve all accounts with the same name via API) reported by @Toshik1978 +- [Issue 9863](https://github.com/firefly-iii/firefly-iii/issues/9863) (User preferences reset after restart) reported by @mico28 +- [Issue 9868](https://github.com/firefly-iii/firefly-iii/issues/9868) (API: `TransactionSplit` -> `transaction_journal_id` returns int, not String) reported by @dreautall +- [Issue 9871](https://github.com/firefly-iii/firefly-iii/issues/9871) (include net worth is ignored in the API - from PICO developer) reported by @fate8383 +- [Issue 9882](https://github.com/firefly-iii/firefly-iii/issues/9882) (Reconciliation bug on Docker instance) reported by @benjaminteyssier ## 6.2.7 - 2025-02-19 diff --git a/composer.lock b/composer.lock index f25084387e..e8e492b5ba 100644 --- a/composer.lock +++ b/composer.lock @@ -3703,16 +3703,16 @@ }, { "name": "nesbot/carbon", - "version": "3.8.5", + "version": "3.8.6", "source": { "type": "git", "url": "https://github.com/CarbonPHP/carbon.git", - "reference": "b1a53a27898639579a67de42e8ced5d5386aa9a4" + "reference": "ff2f20cf83bd4d503720632ce8a426dc747bf7fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/b1a53a27898639579a67de42e8ced5d5386aa9a4", - "reference": "b1a53a27898639579a67de42e8ced5d5386aa9a4", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/ff2f20cf83bd4d503720632ce8a426dc747bf7fd", + "reference": "ff2f20cf83bd4d503720632ce8a426dc747bf7fd", "shasum": "" }, "require": { @@ -3805,7 +3805,7 @@ "type": "tidelift" } ], - "time": "2025-02-11T16:28:45+00:00" + "time": "2025-02-20T17:33:38+00:00" }, { "name": "nette/schema", @@ -6274,23 +6274,23 @@ }, { "name": "spatie/laravel-ignition", - "version": "2.9.0", + "version": "2.9.1", "source": { "type": "git", "url": "https://github.com/spatie/laravel-ignition.git", - "reference": "62042df15314b829d0f26e02108f559018e2aad0" + "reference": "1baee07216d6748ebd3a65ba97381b051838707a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/62042df15314b829d0f26e02108f559018e2aad0", - "reference": "62042df15314b829d0f26e02108f559018e2aad0", + "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/1baee07216d6748ebd3a65ba97381b051838707a", + "reference": "1baee07216d6748ebd3a65ba97381b051838707a", "shasum": "" }, "require": { "ext-curl": "*", "ext-json": "*", "ext-mbstring": "*", - "illuminate/support": "^10.0|^11.0", + "illuminate/support": "^10.0|^11.0|^12.0", "php": "^8.1", "spatie/ignition": "^1.15", "symfony/console": "^6.2.3|^7.0", @@ -6299,12 +6299,12 @@ "require-dev": { "livewire/livewire": "^2.11|^3.3.5", "mockery/mockery": "^1.5.1", - "openai-php/client": "^0.8.1", - "orchestra/testbench": "8.22.3|^9.0", - "pestphp/pest": "^2.34", + "openai-php/client": "^0.8.1|^0.10", + "orchestra/testbench": "8.22.3|^9.0|^10.0", + "pestphp/pest": "^2.34|^3.7", "phpstan/extension-installer": "^1.3.1", - "phpstan/phpstan-deprecation-rules": "^1.1.1", - "phpstan/phpstan-phpunit": "^1.3.16", + "phpstan/phpstan-deprecation-rules": "^1.1.1|^2.0", + "phpstan/phpstan-phpunit": "^1.3.16|^2.0", "vlucas/phpdotenv": "^5.5" }, "suggest": { @@ -6361,7 +6361,7 @@ "type": "github" } ], - "time": "2024-12-02T08:43:31+00:00" + "time": "2025-02-20T13:13:55+00:00" }, { "name": "spatie/laravel-package-tools", @@ -10587,40 +10587,40 @@ }, { "name": "larastan/larastan", - "version": "v3.0.4", + "version": "v3.1.0", "source": { "type": "git", "url": "https://github.com/larastan/larastan.git", - "reference": "b394eba5805727423071fac9b53ea50dd7e920f4" + "reference": "dbb2dc20e5c8e1ed3ff289054e1955f269187312" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/larastan/larastan/zipball/b394eba5805727423071fac9b53ea50dd7e920f4", - "reference": "b394eba5805727423071fac9b53ea50dd7e920f4", + "url": "https://api.github.com/repos/larastan/larastan/zipball/dbb2dc20e5c8e1ed3ff289054e1955f269187312", + "reference": "dbb2dc20e5c8e1ed3ff289054e1955f269187312", "shasum": "" }, "require": { "ext-json": "*", - "illuminate/console": "^11.15.0", - "illuminate/container": "^11.15.0", - "illuminate/contracts": "^11.15.0", - "illuminate/database": "^11.15.0", - "illuminate/http": "^11.15.0", - "illuminate/pipeline": "^11.15.0", - "illuminate/support": "^11.15.0", + "illuminate/console": "^11.15.0 || ^12.0", + "illuminate/container": "^11.15.0 || ^12.0", + "illuminate/contracts": "^11.15.0 || ^12.0", + "illuminate/database": "^11.15.0 || ^12.0", + "illuminate/http": "^11.15.0 || ^12.0", + "illuminate/pipeline": "^11.15.0 || ^12.0", + "illuminate/support": "^11.15.0 || ^12.0", "php": "^8.2", "phpmyadmin/sql-parser": "^5.9.0", "phpstan/phpstan": "^2.1.3" }, "require-dev": { "doctrine/coding-standard": "^12.0", - "laravel/framework": "^11.15.0", + "laravel/framework": "^11.15.0 || ^12.0", "mockery/mockery": "^1.6", "nikic/php-parser": "^5.3", - "orchestra/canvas": "^v9.1.3", - "orchestra/testbench-core": "^9.5.2", + "orchestra/canvas": "^v9.1.3 || ^10.0", + "orchestra/testbench-core": "^9.5.2 || ^10.0", "phpstan/phpstan-deprecation-rules": "^2.0.0", - "phpunit/phpunit": "^10.5.16" + "phpunit/phpunit": "^10.5.35 || ^11.3.6" }, "suggest": { "orchestra/testbench": "Using Larastan for analysing a package needs Testbench" @@ -10633,7 +10633,7 @@ ] }, "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -10668,7 +10668,7 @@ ], "support": { "issues": "https://github.com/larastan/larastan/issues", - "source": "https://github.com/larastan/larastan/tree/v3.0.4" + "source": "https://github.com/larastan/larastan/tree/v3.1.0" }, "funding": [ { @@ -10676,7 +10676,7 @@ "type": "github" } ], - "time": "2025-02-06T21:03:36+00:00" + "time": "2025-02-20T15:25:15+00:00" }, { "name": "laravel-json-api/testing", @@ -11743,16 +11743,16 @@ }, { "name": "phpunit/phpunit", - "version": "11.5.8", + "version": "11.5.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "c9bd61aab12f0fc5e82ecfe621ff518a1d1f1049" + "reference": "c91c830e7108a81e5845aeb6ba8fe3c1a4351c0b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c9bd61aab12f0fc5e82ecfe621ff518a1d1f1049", - "reference": "c9bd61aab12f0fc5e82ecfe621ff518a1d1f1049", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c91c830e7108a81e5845aeb6ba8fe3c1a4351c0b", + "reference": "c91c830e7108a81e5845aeb6ba8fe3c1a4351c0b", "shasum": "" }, "require": { @@ -11762,7 +11762,7 @@ "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.12.1", + "myclabs/deep-copy": "^1.13.0", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=8.2", @@ -11824,7 +11824,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.8" + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.9" }, "funding": [ { @@ -11840,7 +11840,7 @@ "type": "tidelift" } ], - "time": "2025-02-18T06:26:59+00:00" + "time": "2025-02-21T06:08:50+00:00" }, { "name": "sebastian/cli-parser", diff --git a/config/firefly.php b/config/firefly.php index dbbcf59e37..606647601c 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -81,7 +81,7 @@ return [ 'running_balance_column' => env('USE_RUNNING_BALANCE', false), // see cer.php for exchange rates feature flag. ], - 'version' => 'develop/2025-02-20', + 'version' => 'develop/2025-02-21', 'api_version' => '2.1.0', // field is no longer used. 'db_version' => 25, From 48c1b525be96a2fdb76b296b532bcc9acaead85a Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 22 Feb 2025 08:03:42 +0100 Subject: [PATCH 16/23] Fix #9874 --- .../Models/PiggyBank/StoreRequest.php | 17 ------- .../Models/PiggyBank/UpdateRequest.php | 48 +++++++++++-------- .../PiggyBank/ModifiesPiggyBanks.php | 3 +- app/Support/Request/ConvertsDataTypes.php | 19 ++++++++ 4 files changed, 50 insertions(+), 37 deletions(-) diff --git a/app/Api/V1/Requests/Models/PiggyBank/StoreRequest.php b/app/Api/V1/Requests/Models/PiggyBank/StoreRequest.php index b4c416f1a3..729b5e9a83 100644 --- a/app/Api/V1/Requests/Models/PiggyBank/StoreRequest.php +++ b/app/Api/V1/Requests/Models/PiggyBank/StoreRequest.php @@ -65,24 +65,7 @@ class StoreRequest extends FormRequest return $data; } - private function parseAccounts(mixed $array): array - { - if (!is_array($array)) { - return []; - } - $return = []; - foreach ($array as $entry) { - if (!is_array($entry)) { - continue; - } - $return[] = [ - 'account_id' => $this->integerFromValue((string) ($entry['account_id'] ?? '0')), - 'current_amount' => $this->clearString((string) ($entry['current_amount'] ?? '0')), - ]; - } - return $return; - } /** * The rules that the incoming request must be matched against. diff --git a/app/Api/V1/Requests/Models/PiggyBank/UpdateRequest.php b/app/Api/V1/Requests/Models/PiggyBank/UpdateRequest.php index ca2062527a..f506b1c870 100644 --- a/app/Api/V1/Requests/Models/PiggyBank/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/PiggyBank/UpdateRequest.php @@ -25,8 +25,8 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\PiggyBank; use FireflyIII\Models\PiggyBank; -use FireflyIII\Rules\IsAssetAccountId; use FireflyIII\Rules\IsValidPositiveAmount; +use FireflyIII\Rules\IsValidZeroOrMoreAmount; use FireflyIII\Rules\LessThanPiggyTarget; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; @@ -46,19 +46,22 @@ class UpdateRequest extends FormRequest public function getAll(): array { $fields = [ - 'name' => ['name', 'convertString'], - 'account_id' => ['account_id', 'convertInteger'], - 'targetamount' => ['target_amount', 'convertString'], - 'current_amount' => ['current_amount', 'convertString'], - 'startdate' => ['start_date', 'convertDateTime'], - 'targetdate' => ['target_date', 'convertDateTime'], - 'notes' => ['notes', 'stringWithNewlines'], - 'order' => ['order', 'convertInteger'], - 'object_group_title' => ['object_group_title', 'convertString'], - 'object_group_id' => ['object_group_id', 'convertInteger'], + 'name' => ['name', 'convertString'], + 'target_amount' => ['target_amount', 'convertString'], + 'start_date' => ['start_date', 'convertDateTime'], + 'target_date' => ['target_date', 'convertDateTime'], + 'notes' => ['notes', 'stringWithNewlines'], + 'order' => ['order', 'convertInteger'], + 'object_group_title' => ['object_group_title', 'convertString'], + 'object_group_id' => ['object_group_id', 'convertInteger'], + 'transaction_currency_code' => ['transaction_currency_code', 'convertString'], + 'transaction_currency_id' => ['transaction_currency_id', 'convertInteger'], ]; - return $this->getAllData($fields); + $result = $this->getAllData($fields); + $result['accounts'] = $this->parseAccounts($this->get('accounts')); + + return $result; } /** @@ -70,13 +73,20 @@ class UpdateRequest extends FormRequest $piggyBank = $this->route()->parameter('piggyBank'); return [ - 'name' => 'min:1|max:255|uniquePiggyBankForUser:'.$piggyBank->id, - 'current_amount' => ['nullable', new LessThanPiggyTarget(), new IsValidPositiveAmount()], - 'target_amount' => ['nullable', new IsValidPositiveAmount()], - 'start_date' => 'date|nullable', - 'target_date' => 'date|nullable|after:start_date', - 'notes' => 'max:65000', - 'account_id' => ['belongsToUser:accounts', new IsAssetAccountId()], + 'name' => 'min:1|max:255|uniquePiggyBankForUser:' . $piggyBank->id, + 'current_amount' => ['nullable', new LessThanPiggyTarget(), new IsValidPositiveAmount()], + 'target_amount' => ['nullable', new IsValidZeroOrMoreAmount()], + 'start_date' => 'date|nullable', + 'target_date' => 'date|nullable|after:start_date', + 'notes' => 'max:65000', + 'accounts' => 'required', + 'accounts.*' => 'array|required', + 'accounts.*.account_id' => ['required', 'numeric', 'belongsToUser:accounts,id'], + 'accounts.*.current_amount' => ['numeric', new IsValidZeroOrMoreAmount()], + 'object_group_id' => 'numeric|belongsToUser:object_groups,id', + 'object_group_title' => ['min:1', 'max:255'], + 'transaction_currency_id' => 'exists:transaction_currencies,id|nullable', + 'transaction_currency_code' => 'exists:transaction_currencies,code|nullable', ]; } } diff --git a/app/Repositories/PiggyBank/ModifiesPiggyBanks.php b/app/Repositories/PiggyBank/ModifiesPiggyBanks.php index d00b74c58b..568e37895d 100644 --- a/app/Repositories/PiggyBank/ModifiesPiggyBanks.php +++ b/app/Repositories/PiggyBank/ModifiesPiggyBanks.php @@ -222,7 +222,8 @@ trait ModifiesPiggyBanks // update the accounts $factory = new PiggyBankFactory(); $factory->user = $this->user; - $factory->linkToAccountIds($piggyBank, $data['accounts']); + + $factory->linkToAccountIds($piggyBank, $data['accounts'] ?? []); // if the piggy bank is now smaller than the sum of the money saved, diff --git a/app/Support/Request/ConvertsDataTypes.php b/app/Support/Request/ConvertsDataTypes.php index 6e4644250b..18e93a8343 100644 --- a/app/Support/Request/ConvertsDataTypes.php +++ b/app/Support/Request/ConvertsDataTypes.php @@ -390,6 +390,25 @@ trait ConvertsDataTypes return (int) $string; } + protected function parseAccounts(mixed $array): array + { + if (!is_array($array)) { + return []; + } + $return = []; + foreach ($array as $entry) { + if (!is_array($entry)) { + continue; + } + $return[] = [ + 'account_id' => $this->integerFromValue((string) ($entry['account_id'] ?? '0')), + 'current_amount' => $this->clearString((string) ($entry['current_amount'] ?? '0')), + ]; + } + + return $return; + } + protected function floatFromValue(?string $string): ?float { if (null === $string) { From a4637debe9ecdff1c2b9ed9daabeec4486c682c3 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 22 Feb 2025 08:07:52 +0100 Subject: [PATCH 17/23] Update changelog, fix log reference. --- .../Authentication/RemoteUserGuard.php | 35 ++++++++++--------- changelog.md | 2 ++ 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/app/Support/Authentication/RemoteUserGuard.php b/app/Support/Authentication/RemoteUserGuard.php index a6c787a8d8..93c418ce69 100644 --- a/app/Support/Authentication/RemoteUserGuard.php +++ b/app/Support/Authentication/RemoteUserGuard.php @@ -31,6 +31,7 @@ use Illuminate\Contracts\Auth\Guard; use Illuminate\Contracts\Auth\UserProvider; use Illuminate\Contracts\Foundation\Application; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Log; /** * Class RemoteUserGuard @@ -48,7 +49,7 @@ class RemoteUserGuard implements Guard { /** @var null|Request $request */ $request = $app->get('request'); - app('log')->debug(sprintf('Created RemoteUserGuard for %s "%s"', $request?->getMethod(), $request?->getRequestUri())); + Log::debug(sprintf('Created RemoteUserGuard for %s "%s"', $request?->getMethod(), $request?->getRequestUri())); $this->application = $app; $this->provider = $provider; $this->user = null; @@ -56,9 +57,9 @@ class RemoteUserGuard implements Guard public function authenticate(): void { - app('log')->debug(sprintf('Now at %s', __METHOD__)); + Log::debug(sprintf('Now at %s', __METHOD__)); if (null !== $this->user) { - app('log')->debug(sprintf('%s is found: #%d, "%s".', get_class($this->user), $this->user->id, $this->user->email)); + Log::debug(sprintf('%s is found: #%d, "%s".', get_class($this->user), $this->user->id, $this->user->email)); return; } @@ -67,17 +68,17 @@ class RemoteUserGuard implements Guard $userID = request()->server($header) ?? null; if (function_exists('apache_request_headers')) { - app('log')->debug('Use apache_request_headers to find user ID.'); + Log::debug('Use apache_request_headers to find user ID.'); $userID = request()->server($header) ?? apache_request_headers()[$header] ?? null; } if (null === $userID || '' === $userID) { - app('log')->error(sprintf('No user in header "%s".', $header)); + Log::error(sprintf('No user in header "%s".', $header)); throw new FireflyException('The guard header was unexpectedly empty. See the logs.'); } - app('log')->debug(sprintf('User ID found in header is "%s"', $userID)); + Log::debug(sprintf('User ID found in header is "%s"', $userID)); /** @var User $retrievedUser */ $retrievedUser = $this->provider->retrieveById($userID); @@ -98,30 +99,30 @@ class RemoteUserGuard implements Guard } } - app('log')->debug(sprintf('Result of getting user from provider: %s', $retrievedUser->email)); + Log::debug(sprintf('Result of getting user from provider: %s', $retrievedUser->email)); $this->user = $retrievedUser; } public function guest(): bool { - app('log')->debug(sprintf('Now at %s', __METHOD__)); + Log::debug(sprintf('Now at %s', __METHOD__)); return !$this->check(); } public function check(): bool { - app('log')->debug(sprintf('Now at %s', __METHOD__)); + Log::debug(sprintf('Now at %s', __METHOD__)); return null !== $this->user(); } public function user(): ?User { - app('log')->debug(sprintf('Now at %s', __METHOD__)); + Log::debug(sprintf('Now at %s', __METHOD__)); $user = $this->user; if (null === $user) { - app('log')->debug('User is NULL'); + Log::debug('User is NULL'); return null; } @@ -131,7 +132,7 @@ class RemoteUserGuard implements Guard public function hasUser(): bool { - app('log')->debug(sprintf('Now at %s', __METHOD__)); + Log::debug(sprintf('Now at %s', __METHOD__)); throw new FireflyException('Did not implement RemoteUserGuard::hasUser()'); } @@ -141,20 +142,20 @@ class RemoteUserGuard implements Guard */ public function id(): null|int|string { - app('log')->debug(sprintf('Now at %s', __METHOD__)); + Log::debug(sprintf('Now at %s', __METHOD__)); return $this->user?->id; } public function setUser(null|Authenticatable|User $user): void // @phpstan-ignore-line { - app('log')->debug(sprintf('Now at %s', __METHOD__)); + Log::debug(sprintf('Now at %s', __METHOD__)); if ($user instanceof User) { $this->user = $user; return; } - app('log')->error(sprintf('Did not set user at %s', __METHOD__)); + Log::error(sprintf('Did not set user at %s', __METHOD__)); } /** @@ -164,14 +165,14 @@ class RemoteUserGuard implements Guard */ public function validate(array $credentials = []): bool { - app('log')->debug(sprintf('Now at %s', __METHOD__)); + Log::debug(sprintf('Now at %s', __METHOD__)); throw new FireflyException('Did not implement RemoteUserGuard::validate()'); } public function viaRemember(): bool { - app('log')->debug(sprintf('Now at %s', __METHOD__)); + Log::debug(sprintf('Now at %s', __METHOD__)); return false; } diff --git a/changelog.md b/changelog.md index 19d525e969..9db3bd1361 100644 --- a/changelog.md +++ b/changelog.md @@ -13,6 +13,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). - [Issue 9868](https://github.com/firefly-iii/firefly-iii/issues/9868) (API: `TransactionSplit` -> `transaction_journal_id` returns int, not String) reported by @dreautall - [Issue 9871](https://github.com/firefly-iii/firefly-iii/issues/9871) (include net worth is ignored in the API - from PICO developer) reported by @fate8383 - [Issue 9882](https://github.com/firefly-iii/firefly-iii/issues/9882) (Reconciliation bug on Docker instance) reported by @benjaminteyssier +- #9884 +- #9887 ## 6.2.7 - 2025-02-19 From bf04ca12c1c7046d72b5faa67149f9369b494de9 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 22 Feb 2025 08:18:27 +0100 Subject: [PATCH 18/23] Auto commit for release 'develop' on 2025-02-22 --- .../Models/PiggyBank/StoreRequest.php | 2 - .../Models/PiggyBank/UpdateRequest.php | 4 +- changelog.md | 4 +- composer.lock | 207 +++++++++--------- config/firefly.php | 2 +- package-lock.json | 18 +- 6 files changed, 119 insertions(+), 118 deletions(-) diff --git a/app/Api/V1/Requests/Models/PiggyBank/StoreRequest.php b/app/Api/V1/Requests/Models/PiggyBank/StoreRequest.php index 729b5e9a83..6ee29d70d9 100644 --- a/app/Api/V1/Requests/Models/PiggyBank/StoreRequest.php +++ b/app/Api/V1/Requests/Models/PiggyBank/StoreRequest.php @@ -65,8 +65,6 @@ class StoreRequest extends FormRequest return $data; } - - /** * The rules that the incoming request must be matched against. */ diff --git a/app/Api/V1/Requests/Models/PiggyBank/UpdateRequest.php b/app/Api/V1/Requests/Models/PiggyBank/UpdateRequest.php index f506b1c870..61312e094c 100644 --- a/app/Api/V1/Requests/Models/PiggyBank/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/PiggyBank/UpdateRequest.php @@ -45,7 +45,7 @@ class UpdateRequest extends FormRequest */ public function getAll(): array { - $fields = [ + $fields = [ 'name' => ['name', 'convertString'], 'target_amount' => ['target_amount', 'convertString'], 'start_date' => ['start_date', 'convertDateTime'], @@ -73,7 +73,7 @@ class UpdateRequest extends FormRequest $piggyBank = $this->route()->parameter('piggyBank'); return [ - 'name' => 'min:1|max:255|uniquePiggyBankForUser:' . $piggyBank->id, + 'name' => 'min:1|max:255|uniquePiggyBankForUser:'.$piggyBank->id, 'current_amount' => ['nullable', new LessThanPiggyTarget(), new IsValidPositiveAmount()], 'target_amount' => ['nullable', new IsValidZeroOrMoreAmount()], 'start_date' => 'date|nullable', diff --git a/changelog.md b/changelog.md index 9db3bd1361..dfe9e770de 100644 --- a/changelog.md +++ b/changelog.md @@ -13,8 +13,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). - [Issue 9868](https://github.com/firefly-iii/firefly-iii/issues/9868) (API: `TransactionSplit` -> `transaction_journal_id` returns int, not String) reported by @dreautall - [Issue 9871](https://github.com/firefly-iii/firefly-iii/issues/9871) (include net worth is ignored in the API - from PICO developer) reported by @fate8383 - [Issue 9882](https://github.com/firefly-iii/firefly-iii/issues/9882) (Reconciliation bug on Docker instance) reported by @benjaminteyssier -- #9884 -- #9887 +- [Issue 9884](https://github.com/firefly-iii/firefly-iii/issues/9884) (Data import, currency #0 not found) reported by @ragnarkarlsson +- [Issue 9887](https://github.com/firefly-iii/firefly-iii/issues/9887) (Creating a Liability Account Throws TypeError in TransactionJournalFactory::setUser()) reported by @mikeashi ## 6.2.7 - 2025-02-19 diff --git a/composer.lock b/composer.lock index e8e492b5ba..fe4310b3f3 100644 --- a/composer.lock +++ b/composer.lock @@ -6113,16 +6113,16 @@ }, { "name": "spatie/ignition", - "version": "1.15.0", + "version": "1.15.1", "source": { "type": "git", "url": "https://github.com/spatie/ignition.git", - "reference": "e3a68e137371e1eb9edc7f78ffa733f3b98991d2" + "reference": "31f314153020aee5af3537e507fef892ffbf8c85" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/ignition/zipball/e3a68e137371e1eb9edc7f78ffa733f3b98991d2", - "reference": "e3a68e137371e1eb9edc7f78ffa733f3b98991d2", + "url": "https://api.github.com/repos/spatie/ignition/zipball/31f314153020aee5af3537e507fef892ffbf8c85", + "reference": "31f314153020aee5af3537e507fef892ffbf8c85", "shasum": "" }, "require": { @@ -6135,7 +6135,7 @@ "symfony/var-dumper": "^5.4|^6.0|^7.0" }, "require-dev": { - "illuminate/cache": "^9.52|^10.0|^11.0", + "illuminate/cache": "^9.52|^10.0|^11.0|^12.0", "mockery/mockery": "^1.4", "pestphp/pest": "^1.20|^2.0", "phpstan/extension-installer": "^1.1", @@ -6192,7 +6192,7 @@ "type": "github" } ], - "time": "2024-06-12T14:55:22+00:00" + "time": "2025-02-21T14:31:39+00:00" }, { "name": "spatie/laravel-html", @@ -10033,30 +10033,30 @@ "packages-dev": [ { "name": "barryvdh/laravel-debugbar", - "version": "v3.14.10", + "version": "v3.15.0", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-debugbar.git", - "reference": "56b9bd235e3fe62e250124804009ce5bab97cc63" + "reference": "77cca4a1162d45e1fe64e7a71b4a3031656b6c86" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/56b9bd235e3fe62e250124804009ce5bab97cc63", - "reference": "56b9bd235e3fe62e250124804009ce5bab97cc63", + "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/77cca4a1162d45e1fe64e7a71b4a3031656b6c86", + "reference": "77cca4a1162d45e1fe64e7a71b4a3031656b6c86", "shasum": "" }, "require": { - "illuminate/routing": "^9|^10|^11", - "illuminate/session": "^9|^10|^11", - "illuminate/support": "^9|^10|^11", - "maximebf/debugbar": "~1.23.0", - "php": "^8.0", + "illuminate/routing": "^9|^10|^11|^12", + "illuminate/session": "^9|^10|^11|^12", + "illuminate/support": "^9|^10|^11|^12", + "php": "^8.1", + "php-debugbar/php-debugbar": "~2.1.1", "symfony/finder": "^6|^7" }, "require-dev": { "mockery/mockery": "^1.3.3", - "orchestra/testbench-dusk": "^5|^6|^7|^8|^9", - "phpunit/phpunit": "^9.6|^10.5", + "orchestra/testbench-dusk": "^7|^8|^9|^10", + "phpunit/phpunit": "^9.5.10|^10|^11", "squizlabs/php_codesniffer": "^3.5" }, "type": "library", @@ -10070,7 +10070,7 @@ ] }, "branch-alias": { - "dev-master": "3.14-dev" + "dev-master": "3.15-dev" } }, "autoload": { @@ -10095,13 +10095,14 @@ "keywords": [ "debug", "debugbar", + "dev", "laravel", "profiler", "webprofiler" ], "support": { "issues": "https://github.com/barryvdh/laravel-debugbar/issues", - "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.14.10" + "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.15.0" }, "funding": [ { @@ -10113,40 +10114,40 @@ "type": "github" } ], - "time": "2024-12-23T10:10:42+00:00" + "time": "2025-02-21T15:00:44+00:00" }, { "name": "barryvdh/laravel-ide-helper", - "version": "v3.5.4", + "version": "v3.5.5", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-ide-helper.git", - "reference": "980a87e250fc2a7558bc46e07f61c7594500ea53" + "reference": "8d441ec99f8612b942b55f5183151d91591b618a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/980a87e250fc2a7558bc46e07f61c7594500ea53", - "reference": "980a87e250fc2a7558bc46e07f61c7594500ea53", + "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/8d441ec99f8612b942b55f5183151d91591b618a", + "reference": "8d441ec99f8612b942b55f5183151d91591b618a", "shasum": "" }, "require": { "barryvdh/reflection-docblock": "^2.3", "composer/class-map-generator": "^1.0", "ext-json": "*", - "illuminate/console": "^11.15", - "illuminate/database": "^11.15", - "illuminate/filesystem": "^11.15", - "illuminate/support": "^11.15", + "illuminate/console": "^11.15 || ^12", + "illuminate/database": "^11.15 || ^12", + "illuminate/filesystem": "^11.15 || ^12", + "illuminate/support": "^11.15 || ^12", "php": "^8.2" }, "require-dev": { "ext-pdo_sqlite": "*", "friendsofphp/php-cs-fixer": "^3", - "illuminate/config": "^11.15", - "illuminate/view": "^11.15", + "illuminate/config": "^11.15 || ^12", + "illuminate/view": "^11.15 || ^12", "mockery/mockery": "^1.4", - "orchestra/testbench": "^9.2", - "phpunit/phpunit": "^10.5", + "orchestra/testbench": "^9.2 || ^10", + "phpunit/phpunit": "^10.5 || ^11.5.3", "spatie/phpunit-snapshot-assertions": "^4 || ^5", "vimeo/psalm": "^5.4", "vlucas/phpdotenv": "^5" @@ -10195,7 +10196,7 @@ ], "support": { "issues": "https://github.com/barryvdh/laravel-ide-helper/issues", - "source": "https://github.com/barryvdh/laravel-ide-helper/tree/v3.5.4" + "source": "https://github.com/barryvdh/laravel-ide-helper/tree/v3.5.5" }, "funding": [ { @@ -10207,7 +10208,7 @@ "type": "github" } ], - "time": "2025-01-14T09:07:00+00:00" + "time": "2025-02-11T13:59:46+00:00" }, { "name": "barryvdh/reflection-docblock", @@ -10743,74 +10744,6 @@ }, "time": "2024-11-30T16:50:45+00:00" }, - { - "name": "maximebf/debugbar", - "version": "v1.23.6", - "source": { - "type": "git", - "url": "https://github.com/php-debugbar/php-debugbar.git", - "reference": "4b3d5f1afe09a7db5a9d3282890f49f6176d6542" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/4b3d5f1afe09a7db5a9d3282890f49f6176d6542", - "reference": "4b3d5f1afe09a7db5a9d3282890f49f6176d6542", - "shasum": "" - }, - "require": { - "php": "^7.2|^8", - "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^4|^5|^6|^7" - }, - "require-dev": { - "dbrekelmans/bdi": "^1", - "phpunit/phpunit": "^8|^9", - "symfony/panther": "^1|^2.1", - "twig/twig": "^1.38|^2.7|^3.0" - }, - "suggest": { - "kriswallsmith/assetic": "The best way to manage assets", - "monolog/monolog": "Log using Monolog", - "predis/predis": "Redis storage" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.23-dev" - } - }, - "autoload": { - "psr-4": { - "DebugBar\\": "src/DebugBar/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Maxime Bouroumeau-Fuseau", - "email": "maxime.bouroumeau@gmail.com", - "homepage": "http://maximebf.com" - }, - { - "name": "Barry vd. Heuvel", - "email": "barryvdh@gmail.com" - } - ], - "description": "Debug bar in the browser for php application", - "homepage": "https://github.com/maximebf/php-debugbar", - "keywords": [ - "debug", - "debugbar" - ], - "support": { - "issues": "https://github.com/php-debugbar/php-debugbar/issues", - "source": "https://github.com/php-debugbar/php-debugbar/tree/v1.23.6" - }, - "time": "2025-02-13T12:22:36+00:00" - }, { "name": "mockery/mockery", "version": "1.6.12", @@ -11130,6 +11063,76 @@ }, "time": "2022-02-21T01:04:05+00:00" }, + { + "name": "php-debugbar/php-debugbar", + "version": "v2.1.5", + "source": { + "type": "git", + "url": "https://github.com/php-debugbar/php-debugbar.git", + "reference": "3f589bbbaed53039d9699702c2908148647c27a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/3f589bbbaed53039d9699702c2908148647c27a1", + "reference": "3f589bbbaed53039d9699702c2908148647c27a1", + "shasum": "" + }, + "require": { + "php": "^8", + "psr/log": "^1|^2|^3", + "symfony/var-dumper": "^4|^5|^6|^7" + }, + "require-dev": { + "dbrekelmans/bdi": "^1", + "phpunit/phpunit": "^8|^9", + "symfony/panther": "^1|^2.1", + "twig/twig": "^1.38|^2.7|^3.0" + }, + "suggest": { + "kriswallsmith/assetic": "The best way to manage assets", + "monolog/monolog": "Log using Monolog", + "predis/predis": "Redis storage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "DebugBar\\": "src/DebugBar/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Maxime Bouroumeau-Fuseau", + "email": "maxime.bouroumeau@gmail.com", + "homepage": "http://maximebf.com" + }, + { + "name": "Barry vd. Heuvel", + "email": "barryvdh@gmail.com" + } + ], + "description": "Debug bar in the browser for php application", + "homepage": "https://github.com/php-debugbar/php-debugbar", + "keywords": [ + "debug", + "debug bar", + "debugbar", + "dev" + ], + "support": { + "issues": "https://github.com/php-debugbar/php-debugbar/issues", + "source": "https://github.com/php-debugbar/php-debugbar/tree/v2.1.5" + }, + "time": "2025-02-21T13:02:05+00:00" + }, { "name": "phpmyadmin/sql-parser", "version": "5.10.3", diff --git a/config/firefly.php b/config/firefly.php index 606647601c..7728e8a78e 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -81,7 +81,7 @@ return [ 'running_balance_column' => env('USE_RUNNING_BALANCE', false), // see cer.php for exchange rates feature flag. ], - 'version' => 'develop/2025-02-21', + 'version' => 'develop/2025-02-22', 'api_version' => '2.1.0', // field is no longer used. 'db_version' => 25, diff --git a/package-lock.json b/package-lock.json index f22be6ba87..33805cec08 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3147,9 +3147,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.13.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.4.tgz", - "integrity": "sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg==", + "version": "22.13.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.5.tgz", + "integrity": "sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg==", "dev": true, "license": "MIT", "dependencies": { @@ -5677,9 +5677,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.102", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.102.tgz", - "integrity": "sha512-eHhqaja8tE/FNpIiBrvBjFV/SSKpyWHLvxuR9dPTdo+3V9ppdLmFB7ZZQ98qNovcngPLYIz0oOBF9P0FfZef5Q==", + "version": "1.5.103", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.103.tgz", + "integrity": "sha512-P6+XzIkfndgsrjROJWfSvVEgNHtPgbhVyTkwLjUM2HU/h7pZRORgaTlHqfAikqxKmdJMLW8fftrdGWbd/Ds0FA==", "dev": true, "license": "ISC" }, @@ -12174,9 +12174,9 @@ "license": "ISC" }, "node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", "dev": true, "license": "MIT", "engines": { From 73776e786900af53c62b430adba7bc903473f3ec Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 22 Feb 2025 10:05:44 +0100 Subject: [PATCH 19/23] Fix #9887 --- app/Services/Internal/Support/AccountServiceTrait.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/Services/Internal/Support/AccountServiceTrait.php b/app/Services/Internal/Support/AccountServiceTrait.php index b87cbaaec7..c43478a64e 100644 --- a/app/Services/Internal/Support/AccountServiceTrait.php +++ b/app/Services/Internal/Support/AccountServiceTrait.php @@ -239,7 +239,8 @@ trait AccountServiceTrait // submit to factory: $submission = [ 'group_title' => null, - 'user' => $account->user_id, + 'user' => $account->user, + 'user_group' => $account->user->userGroup, 'transactions' => [ [ 'type' => 'Opening balance', @@ -460,11 +461,11 @@ trait AccountServiceTrait if (null === $currency) { $currency = app('amount')->getNativeCurrencyByUserGroup($account->user->userGroup); } - // submit to factory: $submission = [ 'group_title' => null, - 'user' => $account->user_id, + 'user' => $account->user, + 'user_group' => $account->user->userGroup, 'transactions' => [ [ 'type' => 'Liability credit', From 19d08137a567447ed8cb4067fe73798722c2a3fb Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 22 Feb 2025 10:06:59 +0100 Subject: [PATCH 20/23] Fix #9887 --- .env.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.example b/.env.example index a6d48554b8..1d9afab05e 100644 --- a/.env.example +++ b/.env.example @@ -19,7 +19,7 @@ SITE_OWNER=mail@example.com APP_KEY=SomeRandomStringOf32CharsExactly # Firefly III will launch using this language (for new users and unauthenticated visitors) -# For a list of available languages: https://github.com/firefly-iii/firefly-iii/tree/main/resources/lang +# For a list of available languages: https://github.com/firefly-iii/firefly-iii/blob/main/config/firefly.php#L123 # # If text is still in English, remember that not everything may have been translated. DEFAULT_LANGUAGE=en_US From 68c3e14b0cb6febee19fbede5963ef86fbbb2ea8 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 22 Feb 2025 10:12:30 +0100 Subject: [PATCH 21/23] Update changelog. --- changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.md b/changelog.md index dfe9e770de..d54e65ca54 100644 --- a/changelog.md +++ b/changelog.md @@ -14,6 +14,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - [Issue 9871](https://github.com/firefly-iii/firefly-iii/issues/9871) (include net worth is ignored in the API - from PICO developer) reported by @fate8383 - [Issue 9882](https://github.com/firefly-iii/firefly-iii/issues/9882) (Reconciliation bug on Docker instance) reported by @benjaminteyssier - [Issue 9884](https://github.com/firefly-iii/firefly-iii/issues/9884) (Data import, currency #0 not found) reported by @ragnarkarlsson +- #9885 - [Issue 9887](https://github.com/firefly-iii/firefly-iii/issues/9887) (Creating a Liability Account Throws TypeError in TransactionJournalFactory::setUser()) reported by @mikeashi ## 6.2.7 - 2025-02-19 From b098952f821376fbb6efa4d3f14f5c3655ee5807 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 22 Feb 2025 10:16:15 +0100 Subject: [PATCH 22/23] Auto commit for release 'develop' on 2025-02-22 --- changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index d54e65ca54..15eb529207 100644 --- a/changelog.md +++ b/changelog.md @@ -14,7 +14,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - [Issue 9871](https://github.com/firefly-iii/firefly-iii/issues/9871) (include net worth is ignored in the API - from PICO developer) reported by @fate8383 - [Issue 9882](https://github.com/firefly-iii/firefly-iii/issues/9882) (Reconciliation bug on Docker instance) reported by @benjaminteyssier - [Issue 9884](https://github.com/firefly-iii/firefly-iii/issues/9884) (Data import, currency #0 not found) reported by @ragnarkarlsson -- #9885 +- [Issue 9885](https://github.com/firefly-iii/firefly-iii/issues/9885) (Invalid server configuration: missing required package) reported by @EricVanCaenenberghe - [Issue 9887](https://github.com/firefly-iii/firefly-iii/issues/9887) (Creating a Liability Account Throws TypeError in TransactionJournalFactory::setUser()) reported by @mikeashi ## 6.2.7 - 2025-02-19 From b2960b1ed983542ce0c529148c13ec7ef6417a8d Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 22 Feb 2025 10:20:55 +0100 Subject: [PATCH 23/23] Remove docker ignore, not useful in this context. --- .dockerignore | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index ab76ba7a2d..0000000000 --- a/.dockerignore +++ /dev/null @@ -1 +0,0 @@ -Procfile