Compare commits

...

19 Commits

Author SHA1 Message Date
github-actions[bot]
d134fb42ab Merge pull request #12079 from firefly-iii/release-1775194287
🤖 Automatically merge the PR into the develop branch.
2026-04-03 07:31:35 +02:00
JC5
ecab686ac9 🤖 Auto commit for release 'develop' on 2026-04-03 2026-04-03 07:31:27 +02:00
James Cole
4435231ffb Merge pull request #12049 from firefly-iii/dependabot/npm_and_yarn/develop/i18next-26.0.1
Bump i18next from 25.10.10 to 26.0.1
2026-04-03 07:25:54 +02:00
James Cole
40246caaa8 Fix https://github.com/firefly-iii/firefly-iii/issues/12070 2026-04-02 05:47:42 +02:00
github-actions[bot]
1ac6949f95 Merge pull request #12068 from firefly-iii/release-1775021292
🤖 Automatically merge the PR into the develop branch.
2026-04-01 07:28:18 +02:00
JC5
43acafb7a7 🤖 Auto commit for release 'develop' on 2026-04-01 2026-04-01 07:28:12 +02:00
James Cole
ca85a4c034 Catch group order 2026-04-01 07:23:14 +02:00
dependabot[bot]
8e393066b8 Bump i18next from 25.10.10 to 26.0.1
Bumps [i18next](https://github.com/i18next/i18next) from 25.10.10 to 26.0.1.
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v25.10.10...v26.0.1)

---
updated-dependencies:
- dependency-name: i18next
  dependency-version: 26.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-01 04:00:19 +00:00
github-actions[bot]
22752559e1 Merge pull request #12067 from firefly-iii/release-1775015934
🤖 Automatically merge the PR into the develop branch.
2026-04-01 05:59:03 +02:00
JC5
a341cae6bb 🤖 Auto commit for release 'develop' on 2026-04-01 2026-04-01 05:58:54 +02:00
James Cole
64035a71ea Fix validation for piggy banks. 2026-04-01 05:52:29 +02:00
James Cole
074ca1756d Fix https://github.com/firefly-iii/firefly-iii/issues/12066 2026-04-01 05:47:24 +02:00
James Cole
0aa73ccf96 Fix https://github.com/firefly-iii/firefly-iii/issues/12063 2026-03-31 20:13:49 +02:00
James Cole
85c37d8812 Fix https://github.com/firefly-iii/firefly-iii/issues/12056 2026-03-30 18:21:48 +02:00
github-actions[bot]
16eb2ca4ca Merge pull request #12051 from firefly-iii/release-1774843626
🤖 Automatically merge the PR into the develop branch.
2026-03-30 06:07:15 +02:00
JC5
f491155f9b 🤖 Auto commit for release 'develop' on 2026-03-30 2026-03-30 06:07:06 +02:00
github-actions[bot]
c5706e95b7 Merge pull request #12048 from firefly-iii/release-1774809887
🤖 Automatically merge the PR into the develop branch.
2026-03-29 20:44:53 +02:00
JC5
fdabb2c994 🤖 Auto commit for release 'develop' on 2026-03-29 2026-03-29 20:44:47 +02:00
James Cole
615fa733e6 Add extra debug. 2026-03-29 20:39:23 +02:00
72 changed files with 474 additions and 995 deletions

View File

@@ -1264,16 +1264,16 @@
},
{
"name": "symfony/console",
"version": "v8.0.7",
"version": "v8.0.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "15ed9008a4ebe2d6a78e4937f74e0c13ef2e618a"
"reference": "5b66d385dc58f69652e56f78a4184615e3f2b7f7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/15ed9008a4ebe2d6a78e4937f74e0c13ef2e618a",
"reference": "15ed9008a4ebe2d6a78e4937f74e0c13ef2e618a",
"url": "https://api.github.com/repos/symfony/console/zipball/5b66d385dc58f69652e56f78a4184615e3f2b7f7",
"reference": "5b66d385dc58f69652e56f78a4184615e3f2b7f7",
"shasum": ""
},
"require": {
@@ -1330,7 +1330,7 @@
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v8.0.7"
"source": "https://github.com/symfony/console/tree/v8.0.8"
},
"funding": [
{
@@ -1350,7 +1350,7 @@
"type": "tidelift"
}
],
"time": "2026-03-06T14:06:22+00:00"
"time": "2026-03-30T15:14:47+00:00"
},
{
"name": "symfony/deprecation-contracts",
@@ -1421,16 +1421,16 @@
},
{
"name": "symfony/event-dispatcher",
"version": "v8.0.4",
"version": "v8.0.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
"reference": "99301401da182b6cfaa4700dbe9987bb75474b47"
"reference": "f662acc6ab22a3d6d716dcb44c381c6002940df6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/99301401da182b6cfaa4700dbe9987bb75474b47",
"reference": "99301401da182b6cfaa4700dbe9987bb75474b47",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/f662acc6ab22a3d6d716dcb44c381c6002940df6",
"reference": "f662acc6ab22a3d6d716dcb44c381c6002940df6",
"shasum": ""
},
"require": {
@@ -1482,7 +1482,7 @@
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/event-dispatcher/tree/v8.0.4"
"source": "https://github.com/symfony/event-dispatcher/tree/v8.0.8"
},
"funding": [
{
@@ -1502,7 +1502,7 @@
"type": "tidelift"
}
],
"time": "2026-01-05T11:45:55+00:00"
"time": "2026-03-30T15:14:47+00:00"
},
{
"name": "symfony/event-dispatcher-contracts",
@@ -1582,16 +1582,16 @@
},
{
"name": "symfony/filesystem",
"version": "v8.0.6",
"version": "v8.0.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "7bf9162d7a0dff98d079b72948508fa48018a770"
"reference": "66b769ae743ce2d13e435528fbef4af03d623e5a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/7bf9162d7a0dff98d079b72948508fa48018a770",
"reference": "7bf9162d7a0dff98d079b72948508fa48018a770",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/66b769ae743ce2d13e435528fbef4af03d623e5a",
"reference": "66b769ae743ce2d13e435528fbef4af03d623e5a",
"shasum": ""
},
"require": {
@@ -1628,7 +1628,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/filesystem/tree/v8.0.6"
"source": "https://github.com/symfony/filesystem/tree/v8.0.8"
},
"funding": [
{
@@ -1648,20 +1648,20 @@
"type": "tidelift"
}
],
"time": "2026-02-25T16:59:43+00:00"
"time": "2026-03-30T15:14:47+00:00"
},
{
"name": "symfony/finder",
"version": "v8.0.6",
"version": "v8.0.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "441404f09a54de6d1bd6ad219e088cdf4c91f97c"
"reference": "8da41214757b87d97f181e3d14a4179286151007"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/441404f09a54de6d1bd6ad219e088cdf4c91f97c",
"reference": "441404f09a54de6d1bd6ad219e088cdf4c91f97c",
"url": "https://api.github.com/repos/symfony/finder/zipball/8da41214757b87d97f181e3d14a4179286151007",
"reference": "8da41214757b87d97f181e3d14a4179286151007",
"shasum": ""
},
"require": {
@@ -1696,7 +1696,7 @@
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/finder/tree/v8.0.6"
"source": "https://github.com/symfony/finder/tree/v8.0.8"
},
"funding": [
{
@@ -1716,20 +1716,20 @@
"type": "tidelift"
}
],
"time": "2026-01-29T09:41:02+00:00"
"time": "2026-03-30T15:14:47+00:00"
},
{
"name": "symfony/options-resolver",
"version": "v8.0.0",
"version": "v8.0.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/options-resolver.git",
"reference": "d2b592535ffa6600c265a3893a7f7fd2bad82dd7"
"reference": "b48bce0a70b914f6953dafbd10474df232ed4de8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/d2b592535ffa6600c265a3893a7f7fd2bad82dd7",
"reference": "d2b592535ffa6600c265a3893a7f7fd2bad82dd7",
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/b48bce0a70b914f6953dafbd10474df232ed4de8",
"reference": "b48bce0a70b914f6953dafbd10474df232ed4de8",
"shasum": ""
},
"require": {
@@ -1767,7 +1767,7 @@
"options"
],
"support": {
"source": "https://github.com/symfony/options-resolver/tree/v8.0.0"
"source": "https://github.com/symfony/options-resolver/tree/v8.0.8"
},
"funding": [
{
@@ -1787,7 +1787,7 @@
"type": "tidelift"
}
],
"time": "2025-11-12T15:55:31+00:00"
"time": "2026-03-30T15:14:47+00:00"
},
{
"name": "symfony/polyfill-ctype",
@@ -2370,16 +2370,16 @@
},
{
"name": "symfony/process",
"version": "v8.0.5",
"version": "v8.0.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "b5f3aa6762e33fd95efbaa2ec4f4bc9fdd16d674"
"reference": "cb8939aff03470d1a9d1d1b66d08c6fa71b3bbdc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/b5f3aa6762e33fd95efbaa2ec4f4bc9fdd16d674",
"reference": "b5f3aa6762e33fd95efbaa2ec4f4bc9fdd16d674",
"url": "https://api.github.com/repos/symfony/process/zipball/cb8939aff03470d1a9d1d1b66d08c6fa71b3bbdc",
"reference": "cb8939aff03470d1a9d1d1b66d08c6fa71b3bbdc",
"shasum": ""
},
"require": {
@@ -2411,7 +2411,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/process/tree/v8.0.5"
"source": "https://github.com/symfony/process/tree/v8.0.8"
},
"funding": [
{
@@ -2431,7 +2431,7 @@
"type": "tidelift"
}
],
"time": "2026-01-26T15:08:38+00:00"
"time": "2026-03-30T15:14:47+00:00"
},
{
"name": "symfony/service-contracts",
@@ -2522,16 +2522,16 @@
},
{
"name": "symfony/stopwatch",
"version": "v8.0.0",
"version": "v8.0.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/stopwatch.git",
"reference": "67df1914c6ccd2d7b52f70d40cf2aea02159d942"
"reference": "85954ed72d5440ea4dc9a10b7e49e01df766ffa3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/67df1914c6ccd2d7b52f70d40cf2aea02159d942",
"reference": "67df1914c6ccd2d7b52f70d40cf2aea02159d942",
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/85954ed72d5440ea4dc9a10b7e49e01df766ffa3",
"reference": "85954ed72d5440ea4dc9a10b7e49e01df766ffa3",
"shasum": ""
},
"require": {
@@ -2564,7 +2564,7 @@
"description": "Provides a way to profile code",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/stopwatch/tree/v8.0.0"
"source": "https://github.com/symfony/stopwatch/tree/v8.0.8"
},
"funding": [
{
@@ -2584,20 +2584,20 @@
"type": "tidelift"
}
],
"time": "2025-08-04T07:36:47+00:00"
"time": "2026-03-30T15:14:47+00:00"
},
{
"name": "symfony/string",
"version": "v8.0.6",
"version": "v8.0.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "6c9e1108041b5dce21a9a4984b531c4923aa9ec4"
"reference": "ae9488f874d7603f9d2dfbf120203882b645d963"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/6c9e1108041b5dce21a9a4984b531c4923aa9ec4",
"reference": "6c9e1108041b5dce21a9a4984b531c4923aa9ec4",
"url": "https://api.github.com/repos/symfony/string/zipball/ae9488f874d7603f9d2dfbf120203882b645d963",
"reference": "ae9488f874d7603f9d2dfbf120203882b645d963",
"shasum": ""
},
"require": {
@@ -2654,7 +2654,7 @@
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v8.0.6"
"source": "https://github.com/symfony/string/tree/v8.0.8"
},
"funding": [
{
@@ -2674,7 +2674,7 @@
"type": "tidelift"
}
],
"time": "2026-02-09T10:14:57+00:00"
"time": "2026-03-30T15:14:47+00:00"
}
],
"packages-dev": [],

View File

@@ -30,6 +30,7 @@ use FireflyIII\Models\Account;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Budget;
use FireflyIII\Models\Category;
use FireflyIII\Models\Note;
use FireflyIII\Models\Recurrence;
use FireflyIII\Models\Rule;
use FireflyIII\Models\RuleGroup;
@@ -85,6 +86,9 @@ final class PurgeController extends Controller
// rules
Rule::whereUserId($user->id)->onlyTrashed()->forceDelete();
// notes (this will actually purge EVERYBODY's deleted notes)
Note::onlyTrashed()->forceDelete();
// recurring transactions
Recurrence::whereUserId($user->id)->onlyTrashed()->forceDelete();

View File

@@ -60,11 +60,7 @@ class CreatesGroupMemberships extends Command
if (null === $userRole) {
throw new FireflyException('Firefly III could not find a user role. Please make sure all migrations have run.');
}
$membership = GroupMembership::where('user_id', $user->id)
->where('user_group_id', $userGroup->id)
->where('user_role_id', $userRole->id)
->first()
;
$membership = GroupMembership::where('user_id', $user->id)->where('user_group_id', $userGroup->id)->where('user_role_id', $userRole->id)->first();
if (null === $membership) {
GroupMembership::create(['user_id' => $user->id, 'user_role_id' => $userRole->id, 'user_group_id' => $userGroup->id]);
}

View File

@@ -57,30 +57,10 @@ class RemovesLinksToDeletedObjects extends Command
*/
public function handle(): void
{
$deletedTags = Tag::withTrashed()
->whereNotNull('deleted_at')
->get('tags.id')
->pluck('id')
->toArray()
;
$deletedJournals = TransactionJournal::withTrashed()
->whereNotNull('deleted_at')
->get('transaction_journals.id')
->pluck('id')
->toArray()
;
$deletedBudgets = Budget::withTrashed()
->whereNotNull('deleted_at')
->get('budgets.id')
->pluck('id')
->toArray()
;
$deletedCategories = Category::withTrashed()
->whereNotNull('deleted_at')
->get('categories.id')
->pluck('id')
->toArray()
;
$deletedTags = Tag::withTrashed()->whereNotNull('deleted_at')->get('tags.id')->pluck('id')->toArray();
$deletedJournals = TransactionJournal::withTrashed()->whereNotNull('deleted_at')->get('transaction_journals.id')->pluck('id')->toArray();
$deletedBudgets = Budget::withTrashed()->whereNotNull('deleted_at')->get('budgets.id')->pluck('id')->toArray();
$deletedCategories = Category::withTrashed()->whereNotNull('deleted_at')->get('categories.id')->pluck('id')->toArray();
if (count($deletedTags) > 0) {
$this->cleanupTags($deletedTags);

View File

@@ -42,11 +42,7 @@ class RemovesZeroAmount extends Command
*/
public function handle(): int
{
$set = Transaction::where('amount', 0)
->get(['transaction_journal_id'])
->pluck('transaction_journal_id')
->toArray()
;
$set = Transaction::where('amount', 0)->get(['transaction_journal_id'])->pluck('transaction_journal_id')->toArray();
$set = array_unique($set);
$journals = TransactionJournal::whereIn('id', $set)->get();

View File

@@ -70,20 +70,12 @@ class UpgradesJournalMetaData extends Command
private function getIdsForBudgets(): array
{
$transactions = DB::table('budget_transaction')
->distinct()
->pluck('transaction_id')
->toArray()
;
$transactions = DB::table('budget_transaction')->distinct()->pluck('transaction_id')->toArray();
$array = [];
$chunks = array_chunk($transactions, 500);
foreach ($chunks as $chunk) {
$set = DB::table('transactions')
->whereIn('transactions.id', $chunk)
->pluck('transaction_journal_id')
->toArray()
;
$set = DB::table('transactions')->whereIn('transactions.id', $chunk)->pluck('transaction_journal_id')->toArray();
$array = array_merge($array, $set);
}
@@ -92,20 +84,12 @@ class UpgradesJournalMetaData extends Command
private function getIdsForCategories(): array
{
$transactions = DB::table('category_transaction')
->distinct()
->pluck('transaction_id')
->toArray()
;
$transactions = DB::table('category_transaction')->distinct()->pluck('transaction_id')->toArray();
$array = [];
$chunks = array_chunk($transactions, 500);
foreach ($chunks as $chunk) {
$set = DB::table('transactions')
->whereIn('transactions.id', $chunk)
->pluck('transaction_journal_id')
->toArray()
;
$set = DB::table('transactions')->whereIn('transactions.id', $chunk)->pluck('transaction_journal_id')->toArray();
$array = array_merge($array, $set);
}

View File

@@ -104,11 +104,7 @@ class UpgradesWebhooks extends Command
private function upgradeWebhooks(): void
{
$set = Webhook::where('delivery', '>', 1)
->orWhere('trigger', '>', 1)
->orWhere('response', '>', 1)
->get()
;
$set = Webhook::where('delivery', '>', 1)->orWhere('trigger', '>', 1)->orWhere('response', '>', 1)->get();
/** @var Webhook $webhook */
foreach ($set as $webhook) {

View File

@@ -96,12 +96,7 @@ class AccountFactory
$type = AccountType::whereType($accountType)->first();
/** @var null|Account */
return $this->user
->accounts()
->where('account_type_id', $type->id)
->where('name', $accountName)
->first()
;
return $this->user->accounts()->where('account_type_id', $type->id)->where('name', $accountName)->first();
}
/**
@@ -117,12 +112,7 @@ class AccountFactory
}
/** @var null|Account $return */
$return = $this->user
->accounts
->where('account_type_id', $type->id)
->where('name', $accountName)
->first()
;
$return = $this->user->accounts->where('account_type_id', $type->id)->where('name', $accountName)->first();
if (null === $return) {
Log::debug('Found nothing. Will create a new one.');

View File

@@ -136,11 +136,7 @@ class BillFactory
public function findByName(string $name): ?Bill
{
/** @var null|Bill */
return $this->user
->bills()
->whereLike('name', sprintf('%%%s%%', $name))
->first()
;
return $this->user->bills()->whereLike('name', sprintf('%%%s%%', $name))->first();
}
public function setUser(User $user): void

View File

@@ -64,11 +64,7 @@ class BudgetFactory
public function findByName(string $name): ?Budget
{
/** @var null|Budget */
return $this->user
->budgets()
->where('name', $name)
->first()
;
return $this->user->budgets()->where('name', $name)->first();
}
public function setUser(User $user): void

View File

@@ -39,11 +39,7 @@ class CategoryFactory
public function findByName(string $name): ?Category
{
/** @var null|Category */
return $this->user
->categories()
->where('name', $name)
->first()
;
return $this->user->categories()->where('name', $name)->first();
}
/**

View File

@@ -76,11 +76,7 @@ class TagFactory
Log::debug(sprintf('Now in TagFactory::findOrCreate("%s")', $tag));
/** @var null|Tag $dbTag */
$dbTag = $this->user
->tags()
->where('tag', $tag)
->first()
;
$dbTag = $this->user->tags()->where('tag', $tag)->first();
if (null !== $dbTag) {
Log::debug(sprintf('Tag exists (#%d), return it.', $dbTag->id));

View File

@@ -49,11 +49,7 @@ class DeletedAccountObserver
$repository->destroy($attachment);
}
$journalIds = Transaction::where('account_id', $account->id)
->get(['transactions.transaction_journal_id'])
->pluck('transaction_journal_id')
->toArray()
;
$journalIds = Transaction::where('account_id', $account->id)->get(['transactions.transaction_journal_id'])->pluck('transaction_journal_id')->toArray();
$groupIds = array_map(function (array $item) {
return $item['transaction_group_id'];

View File

@@ -750,11 +750,7 @@ class GroupCollector implements GroupCollectorInterface
private function getCollectedGroupIds(): array
{
return $this->query
->get(['transaction_journals.transaction_group_id'])
->pluck('transaction_group_id')
->toArray()
;
return $this->query->get(['transaction_journals.transaction_group_id'])->pluck('transaction_group_id')->toArray();
}
private function mergeAttachments(array $existingJournal, TransactionJournal $newJournal): array
@@ -1126,6 +1122,7 @@ class GroupCollector implements GroupCollectorInterface
->orderBy('transaction_journals.order', 'ASC')
->orderBy('transaction_journals.id', 'DESC')
->orderBy('transaction_journals.description', 'DESC')
->orderBy('source.amount', 'DESC');
->orderBy('source.amount', 'DESC')
;
}
}

View File

@@ -172,8 +172,8 @@ final class BudgetLimitController extends Controller
// return empty array:
return response()->json([]);
}
if ((int) $amount > 268_435_456) { // intentional cast to integer
$amount = '268435456';
if ((int) $amount > 2_147_483_647) { // intentional cast to integer
$amount = '2147483647';
}
if (-1 === bccomp($amount, '0')) {
$amount = bcmul($amount, '-1');
@@ -232,8 +232,8 @@ final class BudgetLimitController extends Controller
if ('' === $amount) {
$amount = '0';
}
if ((int) $amount > 268_435_456) { // 268 million, intentional integer
$amount = '268435456';
if ((int) $amount > 2_147_483_647) { // 268 million, intentional integer
$amount = '2147483647';
}
// sanity check on amount:
if (0 === bccomp($amount, '0')) {

View File

@@ -109,11 +109,7 @@ final class NewUserController extends Controller
$currencyRepository->makePrimary($currency);
// store frontpage preferences:
$accounts = $this->repository
->getAccountsByType([AccountTypeEnum::ASSET->value])
->pluck('id')
->toArray()
;
$accounts = $this->repository->getAccountsByType([AccountTypeEnum::ASSET->value])->pluck('id')->toArray();
Preferences::set('frontpageAccounts', $accounts);
// mark.

View File

@@ -187,11 +187,7 @@ final class ProfileController extends Controller
/** @var User $user */
$user = auth()->user();
$isInternalAuth = $this->internalAuth;
$count = DB::table('oauth_clients')
->where('personal_access_client', true)
->whereNull('user_id')
->count()
;
$count = DB::table('oauth_clients')->where('personal_access_client', true)->whereNull('user_id')->count();
$subTitle = $user->email;
$userId = $user->id;
$enabled2FA = null !== $user->mfa_secret;

View File

@@ -82,11 +82,7 @@ final class EditController extends Controller
$currency->symbol = htmlentities($currency->symbol);
// is currently enabled (for this user?)
$userCurrencies = $this->repository
->get()
->pluck('id')
->toArray()
;
$userCurrencies = $this->repository->get()->pluck('id')->toArray();
$enabled = in_array($currency->id, $userCurrencies, true);
// code to handle active-checkboxes

View File

@@ -41,7 +41,7 @@ class ProcessesUpdatedTransactionGroup
{
Log::debug(sprintf('Now handling event %s', get_class($event)));
$effect = $this->unifyAccounts($event);
Log::debug(sprintf('Effect of unifyAccounts = %d', $effect));
Log::debug(sprintf('Transaction journal count is %d', $event->objects->transactionJournals->count()));
if (!$event->flags->applyRules) {
Log::debug(sprintf('Will NOT process rules for %d journal(s)', $event->objects->transactionJournals->count()));

View File

@@ -26,6 +26,7 @@ namespace FireflyIII\Notifications;
use Exception;
use FireflyIII\Notifications\Notifiables\OwnerNotifiable;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User;
use GuzzleHttp\Exception\ClientException;
use Illuminate\Notifications\Notification;
@@ -36,8 +37,16 @@ class NotificationSender
{
public static function send(OwnerNotifiable|User $user, Notification $notification): void
{
// ::locale($user->locale))
$lang = config('firefly.default_language');
Log::debug(sprintf('Notification send language defaults to "%s"', $lang));
if ($user instanceof User) {
$lang = Preferences::getForUser($user, 'language', $lang)->data;
Log::debug(sprintf('Notification send language set to "%s"', $lang));
}
try {
NotificationFacade::send($user, $notification);
NotificationFacade::locale($lang)->send($user, $notification);
} catch (ClientException $e) {
Log::error(sprintf('[a] Error sending notification: %s', $e->getMessage()));
} catch (Exception $e) {

View File

@@ -48,9 +48,10 @@ class UserTestNotificationEmail extends Notification
public function toMail(User $notifiable): MailMessage
{
$address = (string) $notifiable->email;
$link = route('index');
return new MailMessage()
->markdown('emails.admin-test', ['email' => $address])
->markdown('emails.admin-test', ['email' => $address, 'link' => $link])
->subject((string) trans('email.admin_test_subject'))
;
}

View File

@@ -60,11 +60,7 @@ class AccountRepository implements AccountRepositoryInterface, UserGroupInterfac
public function count(array $types): int
{
return $this->user
->accounts()
->accountTypeIn($types)
->count()
;
return $this->user->accounts()->accountTypeIn($types)->count();
}
/**
@@ -88,12 +84,7 @@ class AccountRepository implements AccountRepositoryInterface, UserGroupInterfac
/** @var Account $account */
foreach ($accounts as $account) {
$byName = $this->user
->accounts()
->where('name', $account->name)
->where('id', '!=', $account->id)
->first()
;
$byName = $this->user->accounts()->where('name', $account->name)->where('id', '!=', $account->id)->first();
if (null !== $byName) {
$result->push($account);
$result->push($byName);
@@ -101,12 +92,7 @@ class AccountRepository implements AccountRepositoryInterface, UserGroupInterfac
continue;
}
if (null !== $account->iban) {
$byIban = $this->user
->accounts()
->where('iban', $account->iban)
->where('id', '!=', $account->id)
->first()
;
$byIban = $this->user->accounts()->where('iban', $account->iban)->where('id', '!=', $account->id)->first();
if (null !== $byIban) {
$result->push($account);
$result->push($byIban);
@@ -151,11 +137,7 @@ class AccountRepository implements AccountRepositoryInterface, UserGroupInterfac
public function findByIbanNull(string $iban, array $types): ?Account
{
$iban = Steam::filterSpaces($iban);
$query = $this->user
->accounts()
->where('iban', '!=', '')
->whereNotNull('iban')
;
$query = $this->user->accounts()->where('iban', '!=', '')->whereNotNull('iban');
if (0 !== count($types)) {
$query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id');
@@ -453,12 +435,7 @@ class AccountRepository implements AccountRepositoryInterface, UserGroupInterfac
$type = AccountType::where('type', AccountTypeEnum::RECONCILIATION->value)->first();
/** @var null|Account $current */
$current = $this->user
->accounts()
->where('account_type_id', $type->id)
->where('name', $name)
->first()
;
$current = $this->user->accounts()->where('account_type_id', $type->id)->where('name', $name)->first();
if (null !== $current) {
return $current;

View File

@@ -87,11 +87,7 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
*/
public function correctOrder(): void
{
$set = $this->user
->bills()
->orderBy('order', 'ASC')
->get()
;
$set = $this->user->bills()->orderBy('order', 'ASC')->get();
$current = 1;
foreach ($set as $bill) {
if ($bill->order !== $current) {
@@ -110,12 +106,7 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
if (null === $withdrawal) {
return;
}
$this->user
->transactionJournals()
->whereNotNull('bill_id')
->where('transaction_type_id', '!=', $withdrawal->id)
->update(['bill_id' => null])
;
$this->user->transactionJournals()->whereNotNull('bill_id')->where('transaction_type_id', '!=', $withdrawal->id)->update(['bill_id' => null]);
}
public function destroy(Bill $bill): bool
@@ -174,11 +165,7 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
public function findByName(string $name): ?Bill
{
/** @var null|Bill */
return $this->user
->bills()
->where('name', $name)
->first(['bills.*'])
;
return $this->user->bills()->where('name', $name)->first(['bills.*']);
}
public function getActiveBills(): Collection
@@ -261,11 +248,7 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
*/
public function getByIds(array $billIds): Collection
{
return $this->user
->bills()
->whereIn('id', $billIds)
->get()
;
return $this->user->bills()->whereIn('id', $billIds)->get();
}
/**
@@ -329,12 +312,7 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
public function getPaginator(int $size): LengthAwarePaginator
{
return $this->user
->bills()
->orderBy('active', 'DESC')
->orderBy('name', 'ASC')
->paginate($size)
;
return $this->user->bills()->orderBy('active', 'DESC')->orderBy('name', 'ASC')->paginate($size);
}
/**
@@ -726,11 +704,7 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
public function unlinkAll(Bill $bill): void
{
$this->user
->transactionJournals()
->where('bill_id', $bill->id)
->update(['bill_id' => null])
;
$this->user->transactionJournals()->where('bill_id', $bill->id)->update(['bill_id' => null]);
}
/**

View File

@@ -79,11 +79,7 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface, U
->toArray()
;
// delete available budgets without these currencies.
$this->user
->availableBudgets()
->whereNotIn('transaction_currency_id', $currencies)
->delete()
;
$this->user->availableBudgets()->whereNotIn('transaction_currency_id', $currencies)->delete();
}
/**
@@ -180,11 +176,7 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface, U
*/
public function getAvailableBudgetsByCurrency(TransactionCurrency $currency): Collection
{
return $this->user
->availableBudgets()
->where('transaction_currency_id', $currency->id)
->get()
;
return $this->user->availableBudgets()->where('transaction_currency_id', $currency->id)->get();
}
/**
@@ -209,24 +201,14 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface, U
*/
public function getAvailableBudgetsByExactDate(Carbon $start, Carbon $end): Collection
{
return $this->user
->availableBudgets()
->where('start_date', '=', $start->format('Y-m-d'))
->where('end_date', '=', $end->format('Y-m-d'))
->get()
;
return $this->user->availableBudgets()->where('start_date', '=', $start->format('Y-m-d'))->where('end_date', '=', $end->format('Y-m-d'))->get();
}
public function getAvailableBudgetWithCurrency(Carbon $start, Carbon $end): array
{
Log::debug(sprintf('Now in %s(%s, %s)', __METHOD__, $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
$return = [];
$availableBudgets = $this->user
->availableBudgets()
->where('start_date', $start->format('Y-m-d'))
->where('end_date', $end->format('Y-m-d'))
->get()
;
$availableBudgets = $this->user->availableBudgets()->where('start_date', $start->format('Y-m-d'))->where('end_date', $end->format('Y-m-d'))->get();
Log::debug(sprintf('Found %d available budgets (already converted)', $availableBudgets->count()));

View File

@@ -227,11 +227,7 @@ class BudgetRepository implements BudgetRepositoryInterface, UserGroupInterface
$budget->saveQuietly();
}
// other budgets, set to 0.
$this->user
->budgets()
->where('active', 0)
->update(['order' => 0])
;
$this->user->budgets()->where('active', 0)->update(['order' => 0]);
return true;
}
@@ -316,11 +312,7 @@ class BudgetRepository implements BudgetRepositoryInterface, UserGroupInterface
$query = sprintf('%%%s%%', $name);
/** @var null|Budget */
return $this->user
->budgets()
->whereLike('name', $query)
->first()
;
return $this->user->budgets()->whereLike('name', $query)->first();
}
/**
@@ -369,20 +361,10 @@ class BudgetRepository implements BudgetRepositoryInterface, UserGroupInterface
public function getBudgets(): Collection
{
if (null === $this->user) {
return $this->userGroup
->budgets()
->orderBy('order', 'ASC')
->orderBy('name', 'ASC')
->get()
;
return $this->userGroup->budgets()->orderBy('order', 'ASC')->orderBy('name', 'ASC')->get();
}
return $this->user
->budgets()
->orderBy('order', 'ASC')
->orderBy('name', 'ASC')
->get()
;
return $this->user->budgets()->orderBy('order', 'ASC')->orderBy('name', 'ASC')->get();
}
/**
@@ -390,11 +372,7 @@ class BudgetRepository implements BudgetRepositoryInterface, UserGroupInterface
*/
public function getByIds(array $budgetIds): Collection
{
return $this->user
->budgets()
->whereIn('id', $budgetIds)
->get()
;
return $this->user->budgets()->whereIn('id', $budgetIds)->get();
}
public function getInactiveBudgets(): Collection

View File

@@ -111,11 +111,7 @@ class CategoryRepository implements CategoryRepositoryInterface, UserGroupInterf
public function findByName(string $name): ?Category
{
/** @var null|Category */
return $this->user
->categories()
->where('name', $name)
->first(['categories.*'])
;
return $this->user->categories()->where('name', $name)->first(['categories.*']);
}
/**
@@ -184,11 +180,7 @@ class CategoryRepository implements CategoryRepositoryInterface, UserGroupInterf
*/
public function getByIds(array $categoryIds): Collection
{
return $this->user
->categories()
->whereIn('id', $categoryIds)
->get()
;
return $this->user->categories()->whereIn('id', $categoryIds)->get();
}
/**
@@ -196,12 +188,7 @@ class CategoryRepository implements CategoryRepositoryInterface, UserGroupInterf
*/
public function getCategories(): Collection
{
return $this->user
->categories()
->with(['attachments'])
->orderBy('name', 'ASC')
->get()
;
return $this->user->categories()->with(['attachments'])->orderBy('name', 'ASC')->get();
}
public function getNoteText(Category $category): ?string

View File

@@ -155,12 +155,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface, UserGroupInterf
}
// is the default currency for the user or the system
$count = $this->userGroup
->currencies()
->where('transaction_currencies.id', $currency->id)
->wherePivot('group_default', 1)
->count()
;
$count = $this->userGroup->currencies()->where('transaction_currencies.id', $currency->id)->wherePivot('group_default', 1)->count();
if ($count > 0) {
Log::info('Is the default currency of the user, return true.');
@@ -168,12 +163,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface, UserGroupInterf
}
// is the default currency for the user or the system
$count = $this->userGroup
->currencies()
->where('transaction_currencies.id', $currency->id)
->wherePivot('group_default', 1)
->count()
;
$count = $this->userGroup->currencies()->where('transaction_currencies.id', $currency->id)->wherePivot('group_default', 1)->count();
if ($count > 0) {
Log::info('Is the default currency of the user group, return true.');
@@ -298,12 +288,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface, UserGroupInterf
public function get(): Collection
{
$all = $this->userGroup
->currencies()
->orderBy('code', 'ASC')
->withPivot(['group_default'])
->get()
;
$all = $this->userGroup->currencies()->orderBy('code', 'ASC')->withPivot(['group_default'])->get();
$all->map(static function (TransactionCurrency $current): TransactionCurrency {
$current->userGroupEnabled = true;
$current->userGroupNative = 1 === (int) $current->pivot->group_default;

View File

@@ -40,31 +40,18 @@ class ExchangeRateRepository implements ExchangeRateRepositoryInterface, UserGro
#[Override]
public function deleteRate(CurrencyExchangeRate $rate): void
{
$this->userGroup
->currencyExchangeRates()
->where('id', $rate->id)
->delete()
;
$this->userGroup->currencyExchangeRates()->where('id', $rate->id)->delete();
}
public function deleteRates(TransactionCurrency $from, TransactionCurrency $to): void
{
$this->userGroup
->currencyExchangeRates()
->where('from_currency_id', $from->id)
->where('to_currency_id', $to->id)
->delete()
;
$this->userGroup->currencyExchangeRates()->where('from_currency_id', $from->id)->where('to_currency_id', $to->id)->delete();
}
#[Override]
public function getAll(): Collection
{
return $this->userGroup
->currencyExchangeRates()
->orderBy('date', 'ASC')
->get()
;
return $this->userGroup->currencyExchangeRates()->orderBy('date', 'ASC')->get();
}
#[Override]

View File

@@ -130,11 +130,7 @@ class JournalRepository implements JournalRepositoryInterface, UserGroupInterfac
public function firstNull(): ?TransactionJournal
{
/** @var null|TransactionJournal */
return $this->user
->transactionJournals()
->orderBy('date', 'ASC')
->first(['transaction_journals.*'])
;
return $this->user->transactionJournals()->orderBy('date', 'ASC')->first(['transaction_journals.*']);
}
#[Override]
@@ -183,11 +179,7 @@ class JournalRepository implements JournalRepositoryInterface, UserGroupInterfac
public function getLast(): ?TransactionJournal
{
/** @var null|TransactionJournal */
return $this->user
->transactionJournals()
->orderBy('date', 'DESC')
->first(['transaction_journals.*'])
;
return $this->user->transactionJournals()->orderBy('date', 'DESC')->first(['transaction_journals.*']);
}
public function getLinkNoteText(TransactionJournalLink $link): string
@@ -241,11 +233,7 @@ class JournalRepository implements JournalRepositoryInterface, UserGroupInterfac
#[Override]
public function getUncompletedJournals(): Collection
{
return $this->userGroup
->transactionJournals()
->where('completed', false)
->get(['transaction_journals.*'])
;
return $this->userGroup->transactionJournals()->where('completed', false)->get(['transaction_journals.*']);
}
#[Override]
@@ -266,11 +254,7 @@ class JournalRepository implements JournalRepositoryInterface, UserGroupInterfac
*/
public function searchJournalDescriptions(string $search, int $limit): Collection
{
$query = $this->user
->transactionJournals()
->orderBy('date', 'DESC')
->orderBy('description', 'ASC')
;
$query = $this->user->transactionJournals()->orderBy('date', 'DESC')->orderBy('description', 'ASC');
if ('' !== $search) {
$query->whereLike('description', sprintf('%%%s%%', $search));
}

View File

@@ -96,11 +96,7 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface, UserGroupInterf
*/
public function findSpecificLink(LinkType $linkType, TransactionJournal $inward, TransactionJournal $outward): ?TransactionJournalLink
{
return TransactionJournalLink::where('link_type_id', $linkType->id)
->where('source_id', $inward->id)
->where('destination_id', $outward->id)
->first()
;
return TransactionJournalLink::where('link_type_id', $linkType->id)->where('source_id', $inward->id)->where('destination_id', $outward->id)->first();
}
public function get(): Collection

View File

@@ -34,21 +34,13 @@ trait CreatesObjectGroups
protected function findObjectGroup(string $title): ?ObjectGroup
{
/** @var null|ObjectGroup */
return $this->user
->objectGroups()
->where('title', $title)
->first()
;
return $this->user->objectGroups()->where('title', $title)->first();
}
protected function findObjectGroupById(int $groupId): ?ObjectGroup
{
/** @var null|ObjectGroup */
return $this->user
->objectGroups()
->where('id', $groupId)
->first()
;
return $this->user->objectGroups()->where('id', $groupId)->first();
}
protected function findOrCreateObjectGroup(string $title): ?ObjectGroup
@@ -74,10 +66,6 @@ trait CreatesObjectGroups
protected function hasObjectGroup(string $title): bool
{
return 1 === $this->user
->objectGroups()
->where('title', $title)
->count()
;
return 1 === $this->user->objectGroups()->where('title', $title)->count();
}
}

View File

@@ -122,11 +122,7 @@ class ObjectGroupRepository implements ObjectGroupRepositoryInterface, UserGroup
public function search(string $query, int $limit): Collection
{
$dbQuery = $this->user
->objectGroups()
->orderBy('order', 'ASC')
->orderBy('title', 'ASC')
;
$dbQuery = $this->user->objectGroups()->orderBy('order', 'ASC')->orderBy('title', 'ASC');
if ('' !== $query) {
// split query on spaces just in case:
$parts = explode(' ', $query);

View File

@@ -100,11 +100,7 @@ class RuleRepository implements RuleRepositoryInterface, UserGroupInterface
*/
public function getAll(): Collection
{
return $this->user
->rules()
->with(['ruleGroup', 'ruleTriggers', 'ruleActions'])
->get()
;
return $this->user->rules()->with(['ruleGroup', 'ruleTriggers', 'ruleActions'])->get();
}
/**
@@ -309,11 +305,7 @@ class RuleRepository implements RuleRepositoryInterface, UserGroupInterface
$ruleGroup = $this->user->ruleGroups()->find($data['rule_group_id']);
}
if (array_key_exists('rule_group_title', $data)) {
$ruleGroup = $this->user
->ruleGroups()
->where('title', $data['rule_group_title'])
->first()
;
$ruleGroup = $this->user->ruleGroups()->where('title', $data['rule_group_title'])->first();
}
if (null === $ruleGroup) {
throw new FireflyException('No such rule group.');

View File

@@ -115,20 +115,12 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface, UserGroupInte
public function findByTitle(string $title): ?RuleGroup
{
/** @var null|RuleGroup */
return $this->user
->ruleGroups()
->where('title', $title)
->first()
;
return $this->user->ruleGroups()->where('title', $title)->first();
}
public function get(): Collection
{
return $this->user
->ruleGroups()
->orderBy('order', 'ASC')
->get()
;
return $this->user->ruleGroups()->orderBy('order', 'ASC')->get();
}
public function getActiveGroups(): Collection
@@ -278,11 +270,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface, UserGroupInte
public function maxOrder(): int
{
return (int) $this->user
->ruleGroups()
->where('active', true)
->max('order')
;
return (int) $this->user->ruleGroups()->where('active', true)->max('order');
}
public function resetOrder(): bool

View File

@@ -100,11 +100,7 @@ class TagRepository implements TagRepositoryInterface, UserGroupInterface
public function findByTag(string $tag): ?Tag
{
/** @var null|Tag */
return $this->user
->tags()
->where('tag', $tag)
->first()
;
return $this->user->tags()->where('tag', $tag)->first();
}
public function firstUseDate(Tag $tag): ?Carbon
@@ -114,11 +110,7 @@ class TagRepository implements TagRepositoryInterface, UserGroupInterface
public function get(): Collection
{
return $this->user
->tags()
->orderBy('tag', 'ASC')
->get(['tags.*'])
;
return $this->user->tags()->orderBy('tag', 'ASC')->get(['tags.*']);
}
public function getAttachments(Tag $tag): Collection
@@ -150,11 +142,7 @@ class TagRepository implements TagRepositoryInterface, UserGroupInterface
public function getTagsInYear(?int $year): array
{
// get all tags in the year (if present):
$tagQuery = $this->user
->tags()
->with(['locations', 'attachments'])
->orderBy('tags.tag')
;
$tagQuery = $this->user->tags()->with(['locations', 'attachments'])->orderBy('tags.tag');
// add date range (or not):
if (null === $year) {
@@ -207,23 +195,13 @@ class TagRepository implements TagRepositoryInterface, UserGroupInterface
public function newestTag(): ?Tag
{
/** @var null|Tag */
return $this->user
->tags()
->whereNotNull('date')
->orderBy('date', 'DESC')
->first()
;
return $this->user->tags()->whereNotNull('date')->orderBy('date', 'DESC')->first();
}
public function oldestTag(): ?Tag
{
/** @var null|Tag */
return $this->user
->tags()
->whereNotNull('date')
->orderBy('date', 'ASC')
->first()
;
return $this->user->tags()->whereNotNull('date')->orderBy('date', 'ASC')->first();
}
#[Override]
@@ -274,11 +252,7 @@ class TagRepository implements TagRepositoryInterface, UserGroupInterface
{
$search = sprintf('%%%s%%', $query);
return $this->user
->tags()
->whereLike('tag', $search)
->get(['tags.*'])
;
return $this->user->tags()->whereLike('tag', $search)->get(['tags.*']);
}
/**
@@ -381,22 +355,14 @@ class TagRepository implements TagRepositoryInterface, UserGroupInterface
{
$search = sprintf('%%%s', $query);
return $this->user
->tags()
->whereLike('tag', $search)
->get(['tags.*'])
;
return $this->user->tags()->whereLike('tag', $search)->get(['tags.*']);
}
public function tagStartsWith(string $query): Collection
{
$search = sprintf('%s%%', $query);
return $this->user
->tags()
->whereLike('tag', $search)
->get(['tags.*'])
;
return $this->user->tags()->whereLike('tag', $search)->get(['tags.*']);
}
public function transferredInPeriod(Tag $tag, Carbon $start, Carbon $end): array

View File

@@ -412,11 +412,7 @@ class UserRepository implements UserRepositoryInterface
public function validateInviteCode(string $code): bool
{
$now = today(config('app.timezone'));
$invitee = InvitedUser::where('invite_code', $code)
->where('expires', '>', $now->format('Y-m-d H:i:s'))
->where('redeemed', 0)
->first()
;
$invitee = InvitedUser::where('invite_code', $code)->where('expires', '>', $now->format('Y-m-d H:i:s'))->where('redeemed', 0)->first();
return null !== $invitee;
}

View File

@@ -157,11 +157,7 @@ class UserGroupRepository implements UserGroupRepositoryInterface, UserGroupInte
#[Override]
public function getMembershipsFromGroupId(int $groupId): Collection
{
return $this->user
->groupMemberships()
->where('user_group_id', $groupId)
->get()
;
return $this->user->groupMemberships()->where('user_group_id', $groupId)->get();
}
/**

View File

@@ -62,9 +62,7 @@ class IsEnoughInAccounts implements ValidationRule
return;
}
if ('' === $amount || 0 === bccomp($amount, '0')) {
$fail('validation.more_than_zero_correct')->translate();
return;
continue;
}
$diff = bcsub($amount, $piggyRepos->getCurrentAmount($this->piggyBank, $account));
if (1 === bccomp($diff, '0') && !$piggyRepos->canAddAmount($this->piggyBank, $account, $amount)) {

View File

@@ -43,10 +43,6 @@ class CategoryDestroyService
DB::table('category_transaction')->where('category_id', $category->id)->delete();
// delete references to category from recurring transactions.
DB::table('rt_meta')
->where('name', 'category_id')
->where('value', $category->id)
->delete()
;
DB::table('rt_meta')->where('name', 'category_id')->where('value', $category->id)->delete();
}
}

View File

@@ -40,11 +40,7 @@ trait BillServiceTrait
return;
}
$ruleIds = $bill->user->rules()->get(['id'])->pluck('id')->toArray();
$set = RuleAction::whereIn('rule_id', $ruleIds)
->where('action_type', 'link_to_bill')
->where('action_value', $oldName)
->get()
;
$set = RuleAction::whereIn('rule_id', $ruleIds)->where('action_type', 'link_to_bill')->where('action_value', $oldName)->get();
/** @var RuleAction $ruleAction */
foreach ($set as $ruleAction) {

View File

@@ -208,11 +208,7 @@ class JournalUpdateService
{
if (!$this->destinationTransaction instanceof Transaction) {
/** @var null|Transaction $result */
$result = $this->transactionJournal
->transactions()
->where('amount', '>', 0)
->first()
;
$result = $this->transactionJournal->transactions()->where('amount', '>', 0)->first();
$this->destinationTransaction = $result;
}
@@ -260,12 +256,7 @@ class JournalUpdateService
{
if (!$this->sourceTransaction instanceof Transaction) {
/** @var null|Transaction $result */
$result = $this->transactionJournal
->transactions()
->with(['account'])
->where('amount', '<', 0)
->first()
;
$result = $this->transactionJournal->transactions()->with(['account'])->where('amount', '<', 0)->first();
$this->sourceTransaction = $result;
}
Log::debug(sprintf('getSourceTransaction: %s', $this->sourceTransaction->amount));
@@ -418,18 +409,10 @@ class JournalUpdateService
private function isBetweenAssetAndLiability(): bool
{
/** @var null|Transaction $sourceTransaction */
$sourceTransaction = $this->transactionJournal
->transactions()
->where('amount', '<', 0)
->first()
;
$sourceTransaction = $this->transactionJournal->transactions()->where('amount', '<', 0)->first();
/** @var null|Transaction $destinationTransaction */
$destinationTransaction = $this->transactionJournal
->transactions()
->where('amount', '>', 0)
->first()
;
$destinationTransaction = $this->transactionJournal->transactions()->where('amount', '>', 0)->first();
if (null === $sourceTransaction || null === $destinationTransaction) {
Log::warning('Either transaction is false, stop.');

View File

@@ -53,11 +53,7 @@ trait CollectsAccountsFromFilter
}
// if no preselected, but no accounts:
if ('empty' === $queryParameters['preselected'] && 0 === $collection->count()) {
$defaultSet = $this->repository
->getAccountsByType([AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value])
->pluck('id')
->toArray()
;
$defaultSet = $this->repository->getAccountsByType([AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value])->pluck('id')->toArray();
$frontpage = Preferences::get('frontpageAccounts', $defaultSet);
if (!(is_array($frontpage->data) && count($frontpage->data) > 0)) {

View File

@@ -109,11 +109,7 @@ class BudgetLimitEnrichment implements EnrichmentInterface
private function collectBudgets(): void
{
$budgetIds = $this->collection
->pluck('budget_id')
->unique()
->toArray()
;
$budgetIds = $this->collection->pluck('budget_id')->unique()->toArray();
$budgets = Budget::whereIn('id', $budgetIds)->get();
$repository = app(OperationsRepository::class);

View File

@@ -188,16 +188,16 @@ class PiggyBankEnrichment implements EnrichmentInterface
$this->ids[] = $id;
$this->currencyIds[$id] = (int) $piggy->transaction_currency_id;
}
$this->ids = array_unique($this->ids);
$this->ids = array_unique($this->ids);
// collect currencies.
$currencies = TransactionCurrency::whereIn('id', $this->currencyIds)->get();
$currencies = TransactionCurrency::whereIn('id', $this->currencyIds)->get();
foreach ($currencies as $currency) {
$this->currencies[(int) $currency->id] = $currency;
}
// collect accounts
$set = DB::table('account_piggy_bank')->whereIn('piggy_bank_id', $this->ids)->get([
$set = DB::table('account_piggy_bank')->whereIn('piggy_bank_id', $this->ids)->get([
'piggy_bank_id',
'account_id',
'current_amount',
@@ -208,8 +208,9 @@ class PiggyBankEnrichment implements EnrichmentInterface
$accountId = (int) $item->account_id;
$this->amounts[$id] ??= [];
if (!array_key_exists($id, $this->accountIds)) {
$this->accountIds[$id] = (int) $item->account_id;
$this->accountIds[$id] = [];
}
$this->accountIds[$id][] = (int) $item->account_id;
if (!array_key_exists($accountId, $this->amounts[$id])) {
$this->amounts[$id][$accountId] = ['current_amount' => '0', 'pc_current_amount' => '0'];
}
@@ -225,12 +226,17 @@ class PiggyBankEnrichment implements EnrichmentInterface
}
}
$allAccountIds = [];
foreach ($this->accountIds as $accountIds) {
$allAccountIds = array_merge($allAccountIds, $accountIds);
}
// get account currency preference for ALL.
$set = AccountMeta::whereIn('account_id', array_values($this->accountIds))->where('name', 'currency_id')->get();
$set = AccountMeta::whereIn('account_id', $allAccountIds)->where('name', 'currency_id')->get();
/** @var AccountMeta $item */
foreach ($set as $item) {
$accountId = (int) $item->account_id;
// $accountId = (int) $item->account_id;
$currencyId = (int) $item->data;
if (!array_key_exists($currencyId, $this->currencies)) {
$this->currencies[$currencyId] = Amount::getTransactionCurrencyById($currencyId);
@@ -239,8 +245,7 @@ class PiggyBankEnrichment implements EnrichmentInterface
// $this->accountCurrencies[$accountId] = $this->currencies[$currencyId];
}
// get account info.
$set = Account::whereIn('id', array_values($this->accountIds))->get();
$set = Account::whereIn('id', $allAccountIds)->get();
/** @var Account $item */
foreach ($set as $item) {

View File

@@ -250,11 +250,7 @@ class OperatorQuerySearch implements SearchInterface
$this->tagRepository->setUser($user);
$this->collector = app(GroupCollectorInterface::class);
$this->collector->setUser($user);
$this->collector
->withAccountInformation()
->withCategoryInformation()
->withBudgetInformation()
;
$this->collector->withAccountInformation()->withCategoryInformation()->withBudgetInformation();
$this->setLimit((int) Preferences::getForUser($user, 'listPageSize', 50)->data);
}

View File

@@ -76,12 +76,7 @@ class TransactionGroupTwig extends AbstractExtension
{
return new TwigFunction('journalGetMetaDate', static function (int $journalId, string $metaField): Carbon|CarbonInterface {
/** @var null|TransactionJournalMeta $entry */
$entry = DB::table('journal_meta')
->where('name', $metaField)
->where('transaction_journal_id', $journalId)
->whereNull('deleted_at')
->first()
;
$entry = DB::table('journal_meta')->where('name', $metaField)->where('transaction_journal_id', $journalId)->whereNull('deleted_at')->first();
if (null === $entry) {
return today(config('app.timezone'));
}
@@ -94,12 +89,7 @@ class TransactionGroupTwig extends AbstractExtension
{
return new TwigFunction('journalGetMetaField', static function (int $journalId, string $metaField) {
/** @var null|TransactionJournalMeta $entry */
$entry = DB::table('journal_meta')
->where('name', $metaField)
->where('transaction_journal_id', $journalId)
->whereNull('deleted_at')
->first()
;
$entry = DB::table('journal_meta')->where('name', $metaField)->where('transaction_journal_id', $journalId)->whereNull('deleted_at')->first();
if (null === $entry) {
return '';
}
@@ -111,12 +101,7 @@ class TransactionGroupTwig extends AbstractExtension
public function journalHasMeta(): TwigFunction
{
return new TwigFunction('journalHasMeta', static function (int $journalId, string $metaField): bool {
$count = DB::table('journal_meta')
->where('name', $metaField)
->where('transaction_journal_id', $journalId)
->whereNull('deleted_at')
->count()
;
$count = DB::table('journal_meta')->where('name', $metaField)->where('transaction_journal_id', $journalId)->whereNull('deleted_at')->count();
return 1 === $count;
});

View File

@@ -75,11 +75,7 @@ class AddTag implements ActionInterface
return false;
}
$count = DB::table('tag_transaction_journal')
->where('tag_id', $tag->id)
->where('transaction_journal_id', $journal['transaction_journal_id'])
->count()
;
$count = DB::table('tag_transaction_journal')->where('tag_id', $tag->id)->where('transaction_journal_id', $journal['transaction_journal_id'])->count();
if (0 === $count) {
// add to journal:
DB::table('tag_transaction_journal')->insert([

View File

@@ -49,11 +49,7 @@ class AppendDescription implements ActionInterface
$this->refreshNotes($journal);
$append = $this->action->getValue($journal);
$description = sprintf('%s %s', $journal['description'], $append);
DB::table('transaction_journals')
->where('id', $journal['transaction_journal_id'])
->limit(1)
->update(['description' => $description])
;
DB::table('transaction_journals')->where('id', $journal['transaction_journal_id'])->limit(1)->update(['description' => $description]);
// event for audit log entry
/** @var TransactionJournal $object */

View File

@@ -58,11 +58,7 @@ class ClearNotes implements ActionInterface
}
$before = $notes->text;
DB::table('notes')
->where('noteable_id', $journal['transaction_journal_id'])
->where('noteable_type', TransactionJournal::class)
->delete()
;
DB::table('notes')->where('noteable_id', $journal['transaction_journal_id'])->where('noteable_type', TransactionJournal::class)->delete();
Log::debug(sprintf('RuleAction ClearNotes removed all notes from journal #%d.', $journal['transaction_journal_id']));
event(new TransactionGroupRequestsAuditLogEntry($this->action->rule, $object, 'clear_notes', $before, null));

View File

@@ -169,11 +169,7 @@ class ConvertToDeposit implements ActionInterface
Log::debug(sprintf('ConvertToDeposit. Action value is "%s", revenue name is "%s"', $actionValue, $opposingAccount->name));
// update source transaction(s) to be revenue account
DB::table('transactions')
->where('transaction_journal_id', '=', $journal->id)
->where('amount', '<', 0)
->update(['account_id' => $opposingAccount->id])
;
DB::table('transactions')->where('transaction_journal_id', '=', $journal->id)->where('amount', '<', 0)->update(['account_id' => $opposingAccount->id]);
// change transaction type of journal:
$newType = TransactionType::whereType(TransactionTypeEnum::DEPOSIT->value)->first();
@@ -219,18 +215,10 @@ class ConvertToDeposit implements ActionInterface
Log::debug(sprintf('ConvertToDeposit. Action value is "%s", new opposing name is "%s"', $actionValue, $opposingAccount->name));
// update the source transaction and put in the new revenue ID.
DB::table('transactions')
->where('transaction_journal_id', '=', $journal->id)
->where('amount', '<', 0)
->update(['account_id' => $opposingAccount->id])
;
DB::table('transactions')->where('transaction_journal_id', '=', $journal->id)->where('amount', '<', 0)->update(['account_id' => $opposingAccount->id]);
// update the destination transaction and put in the original source account ID.
DB::table('transactions')
->where('transaction_journal_id', '=', $journal->id)
->where('amount', '>', 0)
->update(['account_id' => $sourceAccount->id])
;
DB::table('transactions')->where('transaction_journal_id', '=', $journal->id)->where('amount', '>', 0)->update(['account_id' => $sourceAccount->id]);
// change transaction type of journal:
$newType = TransactionType::whereType(TransactionTypeEnum::DEPOSIT->value)->first();

View File

@@ -196,11 +196,7 @@ class ConvertToTransfer implements ActionInterface
}
// update source transaction:
DB::table('transactions')
->where('transaction_journal_id', '=', $journal->id)
->where('amount', '<', 0)
->update(['account_id' => $opposing->id])
;
DB::table('transactions')->where('transaction_journal_id', '=', $journal->id)->where('amount', '<', 0)->update(['account_id' => $opposing->id]);
// change transaction type of journal:
$newType = TransactionType::whereType(TransactionTypeEnum::TRANSFER->value)->first();

View File

@@ -163,18 +163,10 @@ class ConvertToWithdrawal implements ActionInterface
Log::debug(sprintf('ConvertToWithdrawal. Action value is "%s", expense name is "%s"', $actionValue, $opposingName));
// update source transaction(s) to be the original destination account
DB::table('transactions')
->where('transaction_journal_id', '=', $journal->id)
->where('amount', '<', 0)
->update(['account_id' => $destAccount->id])
;
DB::table('transactions')->where('transaction_journal_id', '=', $journal->id)->where('amount', '<', 0)->update(['account_id' => $destAccount->id]);
// update destination transaction(s) to be new expense account.
DB::table('transactions')
->where('transaction_journal_id', '=', $journal->id)
->where('amount', '>', 0)
->update(['account_id' => $opposingAccount->id])
;
DB::table('transactions')->where('transaction_journal_id', '=', $journal->id)->where('amount', '>', 0)->update(['account_id' => $opposingAccount->id]);
// change transaction type of journal:
$newType = TransactionType::whereType(TransactionTypeEnum::WITHDRAWAL->value)->first();
@@ -218,11 +210,7 @@ class ConvertToWithdrawal implements ActionInterface
Log::debug(sprintf('ConvertToWithdrawal. Action value is "%s", destination name is "%s"', $actionValue, $opposingName));
// update destination transaction(s) to be new expense account.
DB::table('transactions')
->where('transaction_journal_id', '=', $journal->id)
->where('amount', '>', 0)
->update(['account_id' => $opposingAccount->id])
;
DB::table('transactions')->where('transaction_journal_id', '=', $journal->id)->where('amount', '>', 0)->update(['account_id' => $opposingAccount->id]);
// change transaction type of journal:
$newType = TransactionType::whereType(TransactionTypeEnum::WITHDRAWAL->value)->first();

View File

@@ -61,11 +61,7 @@ class LinkToBill implements ActionInterface
$type = $object->transactionType->type;
if (null !== $bill && TransactionTypeEnum::WITHDRAWAL->value === $type) {
$count = DB::table('transaction_journals')
->where('id', '=', $journal['transaction_journal_id'])
->where('bill_id', $bill->id)
->count()
;
$count = DB::table('transaction_journals')->where('id', '=', $journal['transaction_journal_id'])->where('bill_id', $bill->id)->count();
if (0 !== $count) {
Log::error(sprintf(
'RuleAction LinkToBill could not set the bill of journal #%d to bill "%s": already set.',

View File

@@ -45,11 +45,7 @@ class PrependDescription implements ActionInterface
{
$before = $journal['description'];
$after = sprintf('%s%s', $this->action->getValue($journal), $journal['description']);
DB::table('transaction_journals')
->where('id', $journal['transaction_journal_id'])
->limit(1)
->update(['description' => $after])
;
DB::table('transaction_journals')->where('id', $journal['transaction_journal_id'])->limit(1)->update(['description' => $after]);
// journal
/** @var TransactionJournal $object */

View File

@@ -62,11 +62,7 @@ class RemoveTag implements ActionInterface
return false;
}
$count = DB::table('tag_transaction_journal')
->where('transaction_journal_id', $journal['transaction_journal_id'])
->where('tag_id', $tag->id)
->count()
;
$count = DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal['transaction_journal_id'])->where('tag_id', $tag->id)->count();
if (0 === $count) {
Log::debug(sprintf(
'RuleAction RemoveTag tried to remove tag "%s" from journal #%d but no such tag is linked.',
@@ -79,11 +75,7 @@ class RemoveTag implements ActionInterface
}
Log::debug(sprintf('RuleAction RemoveTag removed tag #%d ("%s") from journal #%d.', $tag->id, $tag->tag, $journal['transaction_journal_id']));
DB::table('tag_transaction_journal')
->where('transaction_journal_id', $journal['transaction_journal_id'])
->where('tag_id', $tag->id)
->delete()
;
DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal['transaction_journal_id'])->where('tag_id', $tag->id)->delete();
/** @var TransactionJournal $object */
$object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);

View File

@@ -124,11 +124,7 @@ class SetDestinationAccount implements ActionInterface
event(new TransactionGroupRequestsAuditLogEntry($this->action->rule, $object, 'set_destination', null, $newAccount->name));
// update destination transaction with new destination account:
DB::table('transactions')
->where('transaction_journal_id', '=', $object->id)
->where('amount', '>', 0)
->update(['account_id' => $newAccount->id])
;
DB::table('transactions')->where('transaction_journal_id', '=', $object->id)->where('amount', '>', 0)->update(['account_id' => $newAccount->id]);
Log::debug(sprintf('Updated journal #%d (group #%d) and gave it new destination account ID.', $object->id, $object->transaction_group_id));

View File

@@ -105,11 +105,7 @@ class SetDestinationToCashAccount implements ActionInterface
event(new TransactionGroupRequestsAuditLogEntry($this->action->rule, $object, 'set_destination', null, $cashAccount->name));
// update destination transaction with new destination account:
DB::table('transactions')
->where('transaction_journal_id', '=', $object->id)
->where('amount', '>', 0)
->update(['account_id' => $cashAccount->id])
;
DB::table('transactions')->where('transaction_journal_id', '=', $object->id)->where('amount', '>', 0)->update(['account_id' => $cashAccount->id]);
Log::debug(sprintf('Updated journal #%d (group #%d) and gave it new destination account ID.', $object->id, $object->transaction_group_id));

View File

@@ -113,11 +113,7 @@ class SetSourceAccount implements ActionInterface
Log::debug(sprintf('New source account is #%d ("%s").', $newAccount->id, $newAccount->name));
// update source transaction with new source account:
DB::table('transactions')
->where('transaction_journal_id', '=', $object->id)
->where('amount', '<', 0)
->update(['account_id' => $newAccount->id])
;
DB::table('transactions')->where('transaction_journal_id', '=', $object->id)->where('amount', '<', 0)->update(['account_id' => $newAccount->id]);
event(new TransactionGroupRequestsAuditLogEntry($this->action->rule, $object, 'set_source', null, $newAccount->name));

View File

@@ -105,11 +105,7 @@ class SetSourceToCashAccount implements ActionInterface
event(new TransactionGroupRequestsAuditLogEntry($this->action->rule, $object, 'set_source', null, $cashAccount->name));
// update destination transaction with new destination account:
DB::table('transactions')
->where('transaction_journal_id', '=', $object->id)
->where('amount', '<', 0)
->update(['account_id' => $cashAccount->id])
;
DB::table('transactions')->where('transaction_journal_id', '=', $object->id)->where('amount', '<', 0)->update(['account_id' => $cashAccount->id]);
Log::debug(sprintf('Updated journal #%d (group #%d) and gave it new source account ID.', $object->id, $object->transaction_group_id));

View File

@@ -497,12 +497,7 @@ class User extends Authenticatable
$dbRolesIds = $dbRoles->pluck('id')->toArray();
$dbRolesTitles = $dbRoles->pluck('title')->toArray();
$groupMemberships = $this
->groupMemberships()
->whereIn('user_role_id', $dbRolesIds)
->where('user_group_id', $userGroup->id)
->get()
;
$groupMemberships = $this->groupMemberships()->whereIn('user_role_id', $dbRolesIds)->where('user_group_id', $userGroup->id)->get();
if (0 === $groupMemberships->count()) {
Log::error(sprintf(
'User #%d "%s" does not have roles %s in user group #%d "%s"',

View File

@@ -72,7 +72,7 @@ trait ValidatesAutoBudgetRequest
$validator->errors()->add('auto_budget_amount', (string) trans('validation.require_currency_info'));
}
// too big amount
if ((int) $amount > 268_435_456) {
if ((int) $amount > 2_147_483_647) {
$validator->errors()->add('auto_budget_amount', (string) trans('validation.amount_required_for_auto_budget'));
}
}

View File

@@ -109,11 +109,7 @@ class FireflyValidator extends Validator
if (0 === (int) $value) {
return true;
}
$count = DB::table($parameters[0])
->where('user_id', auth()->user()->id)
->where($field, $value)
->count()
;
$count = DB::table($parameters[0])->where('user_id', auth()->user()->id)->where($field, $value)->count();
return 1 === $count;
}
@@ -634,11 +630,7 @@ class FireflyValidator extends Validator
*/
public function validateUniqueCurrency(string $field, string $attribute, string $value): bool
{
return 0 === DB::table('transaction_currencies')
->where($field, $value)
->whereNull('deleted_at')
->count()
;
return 0 === DB::table('transaction_currencies')->where($field, $value)->whereNull('deleted_at')->count();
}
/**

View File

@@ -495,22 +495,14 @@ trait TransactionValidation
}
/** @var null|Transaction $source */
$source = Transaction::where('transaction_journal_id', $journalId)
->where('amount', '<', 0)
->with(['account'])
->first()
;
$source = Transaction::where('transaction_journal_id', $journalId)->where('amount', '<', 0)->with(['account'])->first();
if (null !== $source) {
$return['source_id'] = $source->account_id;
$return['source_name'] = $source->account->name;
}
/** @var null|Transaction $destination */
$destination = Transaction::where('transaction_journal_id', $journalId)
->where('amount', '>', 0)
->with(['account'])
->first()
;
$destination = Transaction::where('transaction_journal_id', $journalId)->where('amount', '>', 0)->with(['account'])->first();
if (null !== $destination) {
$return['destination_id'] = $destination->account_id;
$return['destination_name'] = $destination->account->name;

414
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -78,8 +78,8 @@ return [
'running_balance_column' => (bool)envDefaultWhenEmpty(env('USE_RUNNING_BALANCE'), true), // this is only the default value, is not used.
// see cer.php for exchange rates feature flag.
],
'version' => 'develop/2026-03-29',
'build_time' => 1774808978,
'version' => 'develop/2026-04-03',
'build_time' => 1775194095,
'api_version' => '2.1.0', // field is no longer used.
'db_version' => 28, // field is no longer used.

108
package-lock.json generated
View File

@@ -1703,22 +1703,22 @@
}
},
"node_modules/@emnapi/core": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.1.tgz",
"integrity": "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA==",
"version": "1.9.2",
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz",
"integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==",
"dev": true,
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"@emnapi/wasi-threads": "1.2.0",
"@emnapi/wasi-threads": "1.2.1",
"tslib": "^2.4.0"
}
},
"node_modules/@emnapi/runtime": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.1.tgz",
"integrity": "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==",
"version": "1.9.2",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz",
"integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==",
"dev": true,
"license": "MIT",
"optional": true,
@@ -1728,9 +1728,9 @@
}
},
"node_modules/@emnapi/wasi-threads": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.0.tgz",
"integrity": "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==",
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz",
"integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==",
"dev": true,
"license": "MIT",
"optional": true,
@@ -3385,9 +3385,9 @@
}
},
"node_modules/alpinejs": {
"version": "3.15.9",
"resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.15.9.tgz",
"integrity": "sha512-O30m8Tw/aARbLXmeTnISAFgrNm0K71PT7bZy/1NgRqFD36QGb34VJ4a6WBL1iIO/bofN+LkIkKLikUTkfPL2wQ==",
"version": "3.15.11",
"resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.15.11.tgz",
"integrity": "sha512-m26gkTg/MId8O+F4jHKK3vB3SjbFxxk/JHP+qzmw1H6aQrZuPAg4CUoAefnASzzp/eNroBjrRQe7950bNeaBJw==",
"license": "MIT",
"dependencies": {
"@vue/reactivity": "~3.1.1"
@@ -3682,9 +3682,9 @@
"license": "MIT"
},
"node_modules/baseline-browser-mapping": {
"version": "2.10.12",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.12.tgz",
"integrity": "sha512-qyq26DxfY4awP2gIRXhhLWfwzwI+N5Nxk6iQi8EFizIaWIjqicQTE4sLnZZVdeKPRcVNoJOkkpfzoIYuvCKaIQ==",
"version": "2.10.13",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.13.tgz",
"integrity": "sha512-BL2sTuHOdy0YT1lYieUxTw/QMtPBC3pmlJC6xk8BBYVv6vcw3SGdKemQ+Xsx9ik2F/lYDO9tqsFQH1r9PFuHKw==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@@ -3969,9 +3969,9 @@
}
},
"node_modules/browserslist": {
"version": "4.28.1",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
"integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==",
"version": "4.28.2",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz",
"integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==",
"dev": true,
"funding": [
{
@@ -3989,11 +3989,11 @@
],
"license": "MIT",
"dependencies": {
"baseline-browser-mapping": "^2.9.0",
"caniuse-lite": "^1.0.30001759",
"electron-to-chromium": "^1.5.263",
"node-releases": "^2.0.27",
"update-browserslist-db": "^1.2.0"
"baseline-browser-mapping": "^2.10.12",
"caniuse-lite": "^1.0.30001782",
"electron-to-chromium": "^1.5.328",
"node-releases": "^2.0.36",
"update-browserslist-db": "^1.2.3"
},
"bin": {
"browserslist": "cli.js"
@@ -4134,9 +4134,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001781",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001781.tgz",
"integrity": "sha512-RdwNCyMsNBftLjW6w01z8bKEvT6e/5tpPVEgtn22TiLGlstHOVecsX2KHFkD5e/vRnIE4EGzpuIODb3mtswtkw==",
"version": "1.0.30001784",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001784.tgz",
"integrity": "sha512-WU346nBTklUV9YfUl60fqRbU5ZqyXlqvo1SgigE1OAXK5bFL8LL9q1K7aap3N739l4BvNqnkm3YrGHiY9sfUQw==",
"dev": true,
"funding": [
{
@@ -4688,12 +4688,12 @@
}
},
"node_modules/cross-fetch": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz",
"integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==",
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.1.0.tgz",
"integrity": "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==",
"license": "MIT",
"dependencies": {
"node-fetch": "^2.6.12"
"node-fetch": "^2.7.0"
}
},
"node_modules/cross-spawn": {
@@ -5338,9 +5338,9 @@
"license": "MIT"
},
"node_modules/electron-to-chromium": {
"version": "1.5.328",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.328.tgz",
"integrity": "sha512-QNQ5l45DzYytThO21403XN3FvK0hOkWDG8viNf6jqS42msJ8I4tGDSpBCgvDRRPnkffafiwAym2X2eHeGD2V0w==",
"version": "1.5.331",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.331.tgz",
"integrity": "sha512-IbxXrsTlD3hRodkLnbxAPP4OuJYdWCeM3IOdT+CpcMoIwIoDfCmRpEtSPfwBXxVkg9xmBeY7Lz2Eo2TDn/HC3Q==",
"dev": true,
"license": "ISC"
},
@@ -6647,9 +6647,9 @@
}
},
"node_modules/i18next": {
"version": "25.10.10",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-25.10.10.tgz",
"integrity": "sha512-cqUW2Z3EkRx7NqSyywjkgCLK7KLCL6IFVFcONG7nVYIJ3ekZ1/N5jUsihHV6Bq37NfhgtczxJcxduELtjTwkuQ==",
"version": "26.0.3",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-26.0.3.tgz",
"integrity": "sha512-1571kXINxHKY7LksWp8wP+zP0YqHSSpl/OW0Y0owFEf2H3s8gCAffWaZivcz14rMkOvn3R/psiQxVsR9t2Nafg==",
"funding": [
{
"type": "individual",
@@ -6687,12 +6687,12 @@
}
},
"node_modules/i18next-http-backend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-3.0.2.tgz",
"integrity": "sha512-PdlvPnvIp4E1sYi46Ik4tBYh/v/NbYfFFgTjkwFl0is8A18s7/bx9aXqsrOax9WUbeNS6mD2oix7Z0yGGf6m5g==",
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-3.0.4.tgz",
"integrity": "sha512-udwrBIE6cNpqn1gRAqRULq3+7MzIIuaiKRWrz++dVz5SqWW2VwXmPJtAgkI0JtMLFaADC9qNmnZAxWAhsxXx2g==",
"license": "MIT",
"dependencies": {
"cross-fetch": "4.0.0"
"cross-fetch": "4.1.0"
}
},
"node_modules/i18next-localstorage-backend": {
@@ -7397,9 +7397,9 @@
}
},
"node_modules/laravel-vite-plugin": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-3.0.0.tgz",
"integrity": "sha512-eO6B/IPH448XNjyA5OmJsFAeJH3MeQGWodNMzejx44+rhV44cs0op05t4yku9ifaRnikDkSHLOLXszJL0tiW3w==",
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-3.0.1.tgz",
"integrity": "sha512-Bx8sVcLIaZT1d0eisABcmjQ1GZdJpaXcV66A8RhXGp9JgR3iL8jDnvakVDXuH87Tn5S9KNx3VOhmJZW1CSexOg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -7755,9 +7755,9 @@
}
},
"node_modules/lodash": {
"version": "4.17.23",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
"integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
"integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
"dev": true,
"license": "MIT"
},
@@ -8270,9 +8270,9 @@
}
},
"node_modules/node-releases": {
"version": "2.0.36",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz",
"integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==",
"version": "2.0.37",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.37.tgz",
"integrity": "sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==",
"dev": true,
"license": "MIT"
},
@@ -9982,9 +9982,9 @@
"license": "MIT"
},
"node_modules/sass": {
"version": "1.98.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.98.0.tgz",
"integrity": "sha512-+4N/u9dZ4PrgzGgPlKnaaRQx64RO0JBKs9sDhQ2pLgN6JQZ25uPQZKQYaBJU48Kd5BxgXoJ4e09Dq7nMcOUW3A==",
"version": "1.99.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.99.0.tgz",
"integrity": "sha512-kgW13M54DUB7IsIRM5LvJkNlpH+WhMpooUcaWGFARkF1Tc82v9mIWkCbCYf+MBvpIUBSeSOTilpZjEPr2VYE6Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -12244,7 +12244,7 @@
"chartjs-adapter-date-fns": "^3.0.0",
"chartjs-chart-sankey": "^0.14.0",
"date-fns": "^4.0.0",
"i18next": "^25.0.1",
"i18next": "^26.0.3",
"i18next-chained-backend": "^5.0.0",
"i18next-http-backend": "^3.0.1",
"i18next-localstorage-backend": "^4.2.0",

View File

@@ -81,6 +81,9 @@ export default {
let currentPiggy = res.data[key];
if (null !== currentPiggy.object_group_id) {
let groupOrder = currentPiggy.object_group_order;
if(0 === groupOrder) {
groupOrder = 1;
}
if (!tempList[groupOrder]) {
tempList[groupOrder] = {
group: {

View File

@@ -189,6 +189,6 @@
},
"config": {
"html_language": "ru",
"date_time_fns": "d MMMM yyyy @ HH:mm:ss"
"date_time_fns": "d MMMM yyyy, HH:mm:ss"
}
}

View File

@@ -27,7 +27,7 @@
"chartjs-adapter-date-fns": "^3.0.0",
"chartjs-chart-sankey": "^0.14.0",
"date-fns": "^4.0.0",
"i18next": "^25.0.1",
"i18next": "^26.0.3",
"i18next-chained-backend": "^5.0.0",
"i18next-http-backend": "^3.0.1",
"i18next-localstorage-backend": "^4.2.0",

View File

@@ -68,11 +68,7 @@ final class ListControllerTest extends TestCase
$this->user = $this->createAuthenticatedUser();
$this->actingAs($this->user);
$this->account = Account::factory()
->for($this->user)
->withType(AccountTypeEnum::ASSET)
->create()
;
$this->account = Account::factory()->for($this->user)->withType(AccountTypeEnum::ASSET)->create();
app(AttachmentFactory::class)
->setUser($this->user)
->create([

View File

@@ -77,29 +77,10 @@ final class ShowControllerTest extends TestCase
$this->user = $this->createAuthenticatedUser();
$this->actingAs($this->user);
Account::factory()
->for($this->user)
->withType(AccountTypeEnum::ASSET)
->create()
;
Account::factory()
->for($this->user)
->withType(AccountTypeEnum::REVENUE)
->create()
;
Account::factory()
->for($this->user)
->withType(AccountTypeEnum::EXPENSE)
->create()
;
Account::factory()
->for($this->user)
->withType(AccountTypeEnum::DEBT)
->create()
;
Account::factory()
->for($this->user)
->withType(AccountTypeEnum::ASSET)
->create();
Account::factory()->for($this->user)->withType(AccountTypeEnum::ASSET)->create();
Account::factory()->for($this->user)->withType(AccountTypeEnum::REVENUE)->create();
Account::factory()->for($this->user)->withType(AccountTypeEnum::EXPENSE)->create();
Account::factory()->for($this->user)->withType(AccountTypeEnum::DEBT)->create();
Account::factory()->for($this->user)->withType(AccountTypeEnum::ASSET)->create();
}
}

View File

@@ -59,109 +59,73 @@ final class NavigationEndOfPeriodTest extends TestCase
yield '1W' => [
'1W',
Carbon::now(),
Carbon::now()
->addWeek()
->subDay()
->endOfDay(),
Carbon::now()->addWeek()->subDay()->endOfDay(),
];
yield 'week' => [
'week',
Carbon::now(),
Carbon::now()
->addWeek()
->subDay()
->endOfDay(),
Carbon::now()->addWeek()->subDay()->endOfDay(),
];
yield 'weekly' => [
'weekly',
Carbon::now(),
Carbon::now()
->addWeek()
->subDay()
->endOfDay(),
Carbon::now()->addWeek()->subDay()->endOfDay(),
];
yield 'month' => [
'month',
Carbon::now(),
Carbon::now()
->addMonth()
->subDay()
->endOfDay(),
Carbon::now()->addMonth()->subDay()->endOfDay(),
];
yield '1M' => [
'1M',
Carbon::now(),
Carbon::now()
->addMonth()
->subDay()
->endOfDay(),
Carbon::now()->addMonth()->subDay()->endOfDay(),
];
yield 'monthly' => [
'monthly',
Carbon::now(),
Carbon::now()
->addMonth()
->subDay()
->endOfDay(),
Carbon::now()->addMonth()->subDay()->endOfDay(),
];
yield '3M' => [
'3M',
Carbon::now(),
Carbon::now()
->addQuarter()
->subDay()
->endOfDay(),
Carbon::now()->addQuarter()->subDay()->endOfDay(),
];
yield 'quarter' => [
'quarter',
Carbon::now(),
Carbon::now()
->addQuarter()
->subDay()
->endOfDay(),
Carbon::now()->addQuarter()->subDay()->endOfDay(),
];
yield 'quarterly' => [
'quarterly',
Carbon::now(),
Carbon::now()
->addQuarter()
->subDay()
->endOfDay(),
Carbon::now()->addQuarter()->subDay()->endOfDay(),
];
yield 'year' => [
'year',
Carbon::now(),
Carbon::now()
->addYearNoOverflow()
->subDay()
->endOfDay(),
Carbon::now()->addYearNoOverflow()->subDay()->endOfDay(),
];
yield 'yearly' => [
'yearly',
Carbon::now(),
Carbon::now()
->addYearNoOverflow()
->subDay()
->endOfDay(),
Carbon::now()->addYearNoOverflow()->subDay()->endOfDay(),
];
yield '1Y' => [
'1Y',
Carbon::now(),
Carbon::now()
->addYearNoOverflow()
->subDay()
->endOfDay(),
Carbon::now()->addYearNoOverflow()->subDay()->endOfDay(),
];
yield 'half-year' => ['half-year', Carbon::parse('2023-05-20'), Carbon::parse('2023-11-19')->endOfDay()];