From d756977ee06683dd53a120d51c4e4c65c319842f Mon Sep 17 00:00:00 2001 From: JC5 Date: Thu, 13 Nov 2025 05:55:24 +0100 Subject: [PATCH 01/26] =?UTF-8?q?=F0=9F=A4=96=20Auto=20commit=20for=20rele?= =?UTF-8?q?ase=20'develop'=20on=202025-11-13?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/firefly.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/firefly.php b/config/firefly.php index e8d24229ea..974e45af6e 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -78,8 +78,8 @@ return [ 'running_balance_column' => env('USE_RUNNING_BALANCE', false), // see cer.php for exchange rates feature flag. ], - 'version' => '6.4.8', - 'build_time' => 1763008810, + 'version' => 'develop/2025-11-13', + 'build_time' => 1763009625, 'api_version' => '2.1.0', // field is no longer used. 'db_version' => 28, // field is no longer used. From 34bfeba63a199d010ced99203e22c6224a4d2d5e Mon Sep 17 00:00:00 2001 From: James Cole Date: Thu, 13 Nov 2025 20:32:02 +0100 Subject: [PATCH 02/26] Fix #11211 --- changelog.md | 6 ++++++ resources/views/transactions/show.twig | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/changelog.md b/changelog.md index 08452898e0..c944d14f1d 100644 --- a/changelog.md +++ b/changelog.md @@ -3,6 +3,12 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## 6.4.9 - 2025-11-xx + +### Fixed + +- #11211 + ## 6.4.8 - 2025-11-14 ### Fixed diff --git a/resources/views/transactions/show.twig b/resources/views/transactions/show.twig index 0f49eab7f9..a0c6eab04a 100644 --- a/resources/views/transactions/show.twig +++ b/resources/views/transactions/show.twig @@ -62,6 +62,10 @@
+ + + + From 55d23af802ea6af33fab13137a832c5d4be2e0b4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Nov 2025 03:00:53 +0000 Subject: [PATCH 03/26] Bump bacon/bacon-qr-code from 3.0.1 to 3.0.2 Bumps [bacon/bacon-qr-code](https://github.com/Bacon/BaconQrCode) from 3.0.1 to 3.0.2. - [Release notes](https://github.com/Bacon/BaconQrCode/releases) - [Changelog](https://github.com/Bacon/BaconQrCode/blob/main/CHANGELOG.md) - [Commits](https://github.com/Bacon/BaconQrCode/compare/v3.0.1...v3.0.2) --- updated-dependencies: - dependency-name: bacon/bacon-qr-code dependency-version: 3.0.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- composer.lock | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/composer.lock b/composer.lock index fc5e553989..6491d10bb4 100644 --- a/composer.lock +++ b/composer.lock @@ -8,16 +8,16 @@ "packages": [ { "name": "bacon/bacon-qr-code", - "version": "v3.0.1", + "version": "v3.0.2", "source": { "type": "git", "url": "https://github.com/Bacon/BaconQrCode.git", - "reference": "f9cc1f52b5a463062251d666761178dbdb6b544f" + "reference": "fe259c55425b8178f77fb6d1f84ba2473e21ed55" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/f9cc1f52b5a463062251d666761178dbdb6b544f", - "reference": "f9cc1f52b5a463062251d666761178dbdb6b544f", + "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/fe259c55425b8178f77fb6d1f84ba2473e21ed55", + "reference": "fe259c55425b8178f77fb6d1f84ba2473e21ed55", "shasum": "" }, "require": { @@ -27,8 +27,9 @@ }, "require-dev": { "phly/keep-a-changelog": "^2.12", - "phpunit/phpunit": "^10.5.11 || 11.0.4", + "phpunit/phpunit": "^10.5.11 || ^11.0.4", "spatie/phpunit-snapshot-assertions": "^5.1.5", + "spatie/pixelmatch-php": "^1.2.0", "squizlabs/php_codesniffer": "^3.9" }, "suggest": { @@ -56,9 +57,9 @@ "homepage": "https://github.com/Bacon/BaconQrCode", "support": { "issues": "https://github.com/Bacon/BaconQrCode/issues", - "source": "https://github.com/Bacon/BaconQrCode/tree/v3.0.1" + "source": "https://github.com/Bacon/BaconQrCode/tree/v3.0.2" }, - "time": "2024-10-01T13:55:55+00:00" + "time": "2025-11-16T22:59:48+00:00" }, { "name": "beberlei/assert", From 30b48a479c89a6dda7da91eb0fa4a3af575579f4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Nov 2025 03:01:12 +0000 Subject: [PATCH 04/26] Bump alpinejs from 3.15.1 to 3.15.2 Bumps [alpinejs](https://github.com/alpinejs/alpine/tree/HEAD/packages/alpinejs) from 3.15.1 to 3.15.2. - [Release notes](https://github.com/alpinejs/alpine/releases) - [Commits](https://github.com/alpinejs/alpine/commits/v3.15.2/packages/alpinejs) --- updated-dependencies: - dependency-name: alpinejs dependency-version: 3.15.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package-lock.json | 8 ++++---- resources/assets/v2/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index ba6958e770..102ae62dbc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3776,9 +3776,9 @@ } }, "node_modules/alpinejs": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.15.1.tgz", - "integrity": "sha512-HLO1TtiE92VajFHtLLPK8BWaK1YepV/uj31UrfoGnQ00lyFOJZ+oVY3F0DghPAwvg8sLU79pmjGQSytERa2gEg==", + "version": "3.15.2", + "resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.15.2.tgz", + "integrity": "sha512-2kYF2aG+DTFkE6p0rHG5XmN4VEb6sO9b02aOdU4+i8QN6rL0DbRZQiypDE1gBcGO65yDcqMz5KKYUYgMUxgNkw==", "license": "MIT", "dependencies": { "@vue/reactivity": "~3.1.1" @@ -12507,7 +12507,7 @@ "@fortawesome/fontawesome-free": "^7", "@popperjs/core": "^2.11.8", "admin-lte": "^4.0.0-rc4", - "alpinejs": "^3.13.7", + "alpinejs": "^3.15.2", "bootstrap": "^5", "bootstrap5-autocomplete": "^1", "bootstrap5-tags": "^1", diff --git a/resources/assets/v2/package.json b/resources/assets/v2/package.json index d37480fa7a..541e608039 100644 --- a/resources/assets/v2/package.json +++ b/resources/assets/v2/package.json @@ -19,7 +19,7 @@ "@fortawesome/fontawesome-free": "^7", "@popperjs/core": "^2.11.8", "admin-lte": "^4.0.0-rc4", - "alpinejs": "^3.13.7", + "alpinejs": "^3.15.2", "bootstrap": "^5", "bootstrap5-autocomplete": "^1", "bootstrap5-tags": "^1", From 5f6b345c799da2695edacde79c6316e0d9755084 Mon Sep 17 00:00:00 2001 From: JC5 Date: Mon, 17 Nov 2025 04:29:39 +0100 Subject: [PATCH 05/26] =?UTF-8?q?=F0=9F=A4=96=20Auto=20commit=20for=20rele?= =?UTF-8?q?ase=20'develop'=20on=202025-11-17?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .ci/php-cs-fixer/composer.lock | 2 +- changelog.md | 2 +- composer.lock | 41 +++++++++++++++++----------------- config/firefly.php | 4 ++-- package-lock.json | 30 ++++++++++++------------- 5 files changed, 40 insertions(+), 39 deletions(-) diff --git a/.ci/php-cs-fixer/composer.lock b/.ci/php-cs-fixer/composer.lock index ae089b21e6..fb6175e67d 100644 --- a/.ci/php-cs-fixer/composer.lock +++ b/.ci/php-cs-fixer/composer.lock @@ -2675,5 +2675,5 @@ "prefer-lowest": false, "platform": {}, "platform-dev": {}, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/changelog.md b/changelog.md index c944d14f1d..5f26330636 100644 --- a/changelog.md +++ b/changelog.md @@ -7,7 +7,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Fixed -- #11211 +- [Discussion 11211](https://github.com/orgs/firefly-iii/discussions/11211) (question about Transaction journal ID) started by @zhiiwg ## 6.4.8 - 2025-11-14 diff --git a/composer.lock b/composer.lock index fc5e553989..bcb4727e5b 100644 --- a/composer.lock +++ b/composer.lock @@ -8,16 +8,16 @@ "packages": [ { "name": "bacon/bacon-qr-code", - "version": "v3.0.1", + "version": "v3.0.2", "source": { "type": "git", "url": "https://github.com/Bacon/BaconQrCode.git", - "reference": "f9cc1f52b5a463062251d666761178dbdb6b544f" + "reference": "fe259c55425b8178f77fb6d1f84ba2473e21ed55" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/f9cc1f52b5a463062251d666761178dbdb6b544f", - "reference": "f9cc1f52b5a463062251d666761178dbdb6b544f", + "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/fe259c55425b8178f77fb6d1f84ba2473e21ed55", + "reference": "fe259c55425b8178f77fb6d1f84ba2473e21ed55", "shasum": "" }, "require": { @@ -27,8 +27,9 @@ }, "require-dev": { "phly/keep-a-changelog": "^2.12", - "phpunit/phpunit": "^10.5.11 || 11.0.4", + "phpunit/phpunit": "^10.5.11 || ^11.0.4", "spatie/phpunit-snapshot-assertions": "^5.1.5", + "spatie/pixelmatch-php": "^1.2.0", "squizlabs/php_codesniffer": "^3.9" }, "suggest": { @@ -56,9 +57,9 @@ "homepage": "https://github.com/Bacon/BaconQrCode", "support": { "issues": "https://github.com/Bacon/BaconQrCode/issues", - "source": "https://github.com/Bacon/BaconQrCode/tree/v3.0.1" + "source": "https://github.com/Bacon/BaconQrCode/tree/v3.0.2" }, - "time": "2024-10-01T13:55:55+00:00" + "time": "2025-11-16T22:59:48+00:00" }, { "name": "beberlei/assert", @@ -12011,16 +12012,16 @@ }, { "name": "phpunit/phpunit", - "version": "12.4.2", + "version": "12.4.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "a94ea4d26d865875803b23aaf78c3c2c670ea2ea" + "reference": "d8f644d8d9bb904867f7a0aeb1bd306e0d966949" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a94ea4d26d865875803b23aaf78c3c2c670ea2ea", - "reference": "a94ea4d26d865875803b23aaf78c3c2c670ea2ea", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d8f644d8d9bb904867f7a0aeb1bd306e0d966949", + "reference": "d8f644d8d9bb904867f7a0aeb1bd306e0d966949", "shasum": "" }, "require": { @@ -12088,7 +12089,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/12.4.2" + "source": "https://github.com/sebastianbergmann/phpunit/tree/12.4.3" }, "funding": [ { @@ -12112,7 +12113,7 @@ "type": "tidelift" } ], - "time": "2025-10-30T08:41:39+00:00" + "time": "2025-11-13T07:20:26+00:00" }, { "name": "rector/rector", @@ -13183,16 +13184,16 @@ }, { "name": "theseer/tokenizer", - "version": "1.2.3", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + "reference": "d74205c497bfbca49f34d4bc4c19c17e22db4ebb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/d74205c497bfbca49f34d4bc4c19c17e22db4ebb", + "reference": "d74205c497bfbca49f34d4bc4c19c17e22db4ebb", "shasum": "" }, "require": { @@ -13221,7 +13222,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + "source": "https://github.com/theseer/tokenizer/tree/1.3.0" }, "funding": [ { @@ -13229,7 +13230,7 @@ "type": "github" } ], - "time": "2024-03-03T12:36:25+00:00" + "time": "2025-11-13T13:44:09+00:00" }, { "name": "webmozart/assert", @@ -13314,5 +13315,5 @@ "ext-xmlwriter": "*" }, "platform-dev": {}, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/config/firefly.php b/config/firefly.php index 974e45af6e..621ebb59cf 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -78,8 +78,8 @@ return [ 'running_balance_column' => env('USE_RUNNING_BALANCE', false), // see cer.php for exchange rates feature flag. ], - 'version' => 'develop/2025-11-13', - 'build_time' => 1763009625, + 'version' => 'develop/2025-11-17', + 'build_time' => 1763350067, 'api_version' => '2.1.0', // field is no longer used. 'db_version' => 28, // field is no longer used. diff --git a/package-lock.json b/package-lock.json index ba6958e770..eb42b58bd1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3776,9 +3776,9 @@ } }, "node_modules/alpinejs": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.15.1.tgz", - "integrity": "sha512-HLO1TtiE92VajFHtLLPK8BWaK1YepV/uj31UrfoGnQ00lyFOJZ+oVY3F0DghPAwvg8sLU79pmjGQSytERa2gEg==", + "version": "3.15.2", + "resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.15.2.tgz", + "integrity": "sha512-2kYF2aG+DTFkE6p0rHG5XmN4VEb6sO9b02aOdU4+i8QN6rL0DbRZQiypDE1gBcGO65yDcqMz5KKYUYgMUxgNkw==", "license": "MIT", "dependencies": { "@vue/reactivity": "~3.1.1" @@ -4075,9 +4075,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.8.27", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.27.tgz", - "integrity": "sha512-2CXFpkjVnY2FT+B6GrSYxzYf65BJWEqz5tIRHCvNsZZ2F3CmsCB37h8SpYgKG7y9C4YAeTipIPWG7EmFmhAeXA==", + "version": "2.8.28", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.28.tgz", + "integrity": "sha512-gYjt7OIqdM0PcttNYP2aVrr2G0bMALkBaoehD4BuRGjAOtipg0b6wHg1yNL+s5zSnLZZrGHOw4IrND8CD+3oIQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -4521,9 +4521,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001754", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001754.tgz", - "integrity": "sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg==", + "version": "1.0.30001755", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001755.tgz", + "integrity": "sha512-44V+Jm6ctPj7R52Na4TLi3Zri4dWUljJd+RDm+j8LtNCc/ihLCT+X1TzoOAkRETEWqjuLnh9581Tl80FvK7jVA==", "dev": true, "funding": [ { @@ -5365,9 +5365,9 @@ } }, "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.2.tgz", + "integrity": "sha512-D80T+tiqkd/8B0xNlbstWDG4x6aqVfO52+OlSUNIdkTvmNw0uQpJLeos2J/2XvpyidAFuTPmpad+tUxLndwj6g==", "dev": true, "license": "MIT" }, @@ -5736,9 +5736,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.250", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.250.tgz", - "integrity": "sha512-/5UMj9IiGDMOFBnN4i7/Ry5onJrAGSbOGo3s9FEKmwobGq6xw832ccET0CE3CkkMBZ8GJSlUIesZofpyurqDXw==", + "version": "1.5.254", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.254.tgz", + "integrity": "sha512-DcUsWpVhv9svsKRxnSCZ86SjD+sp32SGidNB37KpqXJncp1mfUgKbHvBomE89WJDbfVKw1mdv5+ikrvd43r+Bg==", "dev": true, "license": "ISC" }, From 4a901a1b420d594fad86d9e6ab4b61c504652ded Mon Sep 17 00:00:00 2001 From: James Cole Date: Mon, 17 Nov 2025 19:01:38 +0100 Subject: [PATCH 06/26] Add a bunch of debug #11247 --- .../Controllers/Recurring/EditController.php | 2 +- .../Enrichments/RecurringEnrichment.php | 162 +++++++++--------- 2 files changed, 83 insertions(+), 81 deletions(-) diff --git a/app/Http/Controllers/Recurring/EditController.php b/app/Http/Controllers/Recurring/EditController.php index f0cdb8b4da..dbbd7c2947 100644 --- a/app/Http/Controllers/Recurring/EditController.php +++ b/app/Http/Controllers/Recurring/EditController.php @@ -174,7 +174,7 @@ class EditController extends Controller public function update(RecurrenceFormRequest $request, Recurrence $recurrence) { $data = $request->getAll(); - $this->repository->update($recurrence, $data); + $recurrence = $this->repository->update($recurrence, $data); $request->session()->flash('success', (string) trans('firefly.updated_recurrence', ['title' => $recurrence->title])); Log::channel('audit')->info(sprintf('Updated recurrence #%d.', $recurrence->id), $data); diff --git a/app/Support/JsonApi/Enrichments/RecurringEnrichment.php b/app/Support/JsonApi/Enrichments/RecurringEnrichment.php index 1f881ddbc5..0143aa2602 100644 --- a/app/Support/JsonApi/Enrichments/RecurringEnrichment.php +++ b/app/Support/JsonApi/Enrichments/RecurringEnrichment.php @@ -51,28 +51,28 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Log; - use function Safe\json_decode; class RecurringEnrichment implements EnrichmentInterface { - private array $accounts = []; + private array $accounts = []; private Collection $collection; // private array $transactionTypeIds = []; // private array $transactionTypes = []; - private readonly bool $convertToPrimary; - private array $currencies = []; - private array $currencyIds = []; - private array $destinationAccountIds = []; - private array $foreignCurrencyIds = []; - private array $ids = []; - private string $language = 'en_US'; - private array $notes = []; + private readonly bool $convertToPrimary; + private array $currencies = []; + private array $currencyIds = []; + private array $destinationAccountIds = []; + private array $foreignCurrencyIds = []; + private array $ids = []; + private string $language = 'en_US'; + private array $notes = []; private readonly TransactionCurrency $primaryCurrency; - private array $recurrenceIds = []; - private array $repetitions = []; - private array $sourceAccountIds = []; - private array $transactions = []; + private array $recurrenceIds = []; + private array $recurrenceByTransaction = []; + private array $repetitions = []; + private array $sourceAccountIds = []; + private array $transactions = []; private User $user; private UserGroup $userGroup; @@ -84,6 +84,7 @@ class RecurringEnrichment implements EnrichmentInterface public function enrich(Collection $collection): Collection { + Log::debug(__METHOD__); $this->collection = $collection; $this->collectIds(); $this->collectRepetitions(); @@ -98,7 +99,7 @@ class RecurringEnrichment implements EnrichmentInterface return $this->collection; } - public function enrichSingle(array|Model $model): array|Model + public function enrichSingle(array | Model $model): array | Model { Log::debug(__METHOD__); $collection = new Collection()->push($model); @@ -132,7 +133,7 @@ class RecurringEnrichment implements EnrichmentInterface return (string)trans('firefly.recurring_monthly', ['dayOfMonth' => $repetition->repetition_moment, 'skip' => $repetition->repetition_skip - 1], $this->language); } if ('ndom' === $repetition->repetition_type) { - $parts = explode(',', $repetition->repetition_moment); + $parts = explode(',', $repetition->repetition_moment); // first part is number of week, second is weekday. $dayOfWeek = trans(sprintf('config.dow_%s', $parts[1]), [], $this->language); if ($repetition->repetition_skip > 0) { @@ -149,7 +150,7 @@ class RecurringEnrichment implements EnrichmentInterface } // $diffInYears = (int)$today->diffInYears($repDate, true); // $repDate->addYears($diffInYears); // technically not necessary. - $string = $repDate->isoFormat((string)trans('config.month_and_day_no_year_js')); + $string = $repDate->isoFormat((string)trans('config.month_and_day_no_year_js')); return (string)trans('firefly.recurring_yearly', ['date' => $string], $this->language); } @@ -172,8 +173,8 @@ class RecurringEnrichment implements EnrichmentInterface private function appendCollectedData(): void { $this->collection = $this->collection->map(function (Recurrence $item): Recurrence { - $id = (int)$item->id; - $meta = [ + $id = (int)$item->id; + $meta = [ 'notes' => $this->notes[$id] ?? null, 'repetitions' => array_values($this->repetitions[$id] ?? []), 'transactions' => $this->processTransactions(array_values($this->transactions[$id] ?? [])), @@ -194,6 +195,7 @@ class RecurringEnrichment implements EnrichmentInterface foreach ($accounts as $account) { $id = (int)$account->id; $this->accounts[$id] = $account; + Log::debug(sprintf('Collected account #%d', $id)); } } @@ -279,6 +281,7 @@ class RecurringEnrichment implements EnrichmentInterface foreach ($currencies as $currency) { $id = (int)$currency->id; $this->currencies[$id] = $currency; + Log::debug(sprintf('Collected currency #%d', $id)); } } @@ -287,29 +290,23 @@ class RecurringEnrichment implements EnrichmentInterface /** @var Recurrence $recurrence */ foreach ($this->collection as $recurrence) { $id = (int)$recurrence->id; - // $typeId = (int)$recurrence->transaction_type_id; $this->ids[] = $id; - // $this->transactionTypeIds[$id] = $typeId; + Log::debug(sprintf('Collected recurrence id #%d', $id)); } $this->ids = array_unique($this->ids); - - // collect transaction types. - // $transactionTypes = TransactionType::whereIn('id', array_unique($this->transactionTypeIds))->get(); - // foreach ($transactionTypes as $transactionType) { - // $id = (int)$transactionType->id; - // $this->transactionTypes[$id] = TransactionTypeEnum::from($transactionType->type); - // } + Log::debug('Final array:', $this->ids); } private function collectNotes(): void { $notes = Note::query()->whereIn('noteable_id', $this->ids) - ->whereNotNull('notes.text') - ->where('notes.text', '!=', '') - ->where('noteable_type', Recurrence::class)->get(['notes.noteable_id', 'notes.text'])->toArray() - ; + ->whereNotNull('notes.text') + ->where('notes.text', '!=', '') + ->where('noteable_type', Recurrence::class)->get(['notes.id', 'notes.noteable_id', 'notes.text'])->toArray(); foreach ($notes as $note) { - $this->notes[(int)$note['noteable_id']] = (string)$note['text']; + $notableId = (int)$note['noteable_id']; + $this->notes[$notableId] = (string)$note['text']; + Log::debug(sprintf('Collected note #%d for recurrence #%d', $note['id'], $notableId)); } Log::debug(sprintf('Enrich with %d note(s)', count($this->notes))); } @@ -337,26 +334,27 @@ class RecurringEnrichment implements EnrichmentInterface Log::debug('Start of enrichment: collectRepetitions()'); $repository = app(RecurringRepositoryInterface::class); $repository->setUserGroup($this->userGroup); - $set = RecurrenceRepetition::whereIn('recurrence_id', $this->ids)->get(); + $set = RecurrenceRepetition::whereIn('recurrence_id', $this->ids)->get(); /** @var RecurrenceRepetition $repetition */ foreach ($set as $repetition) { - $recurrence = $this->collection->filter(fn (Recurrence $item): bool => (int)$item->id === (int)$repetition->recurrence_id)->first(); - $fromDate = clone ($recurrence->latest_date ?? $recurrence->first_date); - $id = (int)$repetition->recurrence_id; - $repId = (int)$repetition->id; - $this->repetitions[$id] ??= []; + $recurrence = $this->collection->filter(fn(Recurrence $item): bool => (int)$item->id === (int)$repetition->recurrence_id)->first(); + $fromDate = clone($recurrence->latest_date ?? $recurrence->first_date); + $recurrenceId = (int)$repetition->recurrence_id; + $repId = (int)$repetition->id; + $this->repetitions[$recurrenceId] ??= []; + Log::debug(sprintf('Collected repetition #%d of recurrence #%d.', $repId, $recurrenceId)); // get the (future) occurrences for this specific type of repetition: - $amount = 'daily' === $repetition->repetition_type ? 9 : 5; - $set = $repository->getXOccurrencesSince($repetition, $fromDate, now(config('app.timezone')), $amount); - $occurrences = []; + $amount = 'daily' === $repetition->repetition_type ? 9 : 5; + $set = $repository->getXOccurrencesSince($repetition, $fromDate, now(config('app.timezone')), $amount); + $occurrences = []; /** @var Carbon $carbon */ foreach ($set as $carbon) { $occurrences[] = $carbon->toAtomString(); } - $this->repetitions[$id][$repId] = [ + $this->repetitions[$recurrenceId][$repId] = [ 'id' => (string)$repId, 'created_at' => $repetition->created_at->toAtomString(), 'updated_at' => $repetition->updated_at->toAtomString(), @@ -373,8 +371,11 @@ class RecurringEnrichment implements EnrichmentInterface private function collectTransactionMetaData(): void { - $ids = array_keys($this->transactions); - $meta = RecurrenceTransactionMeta::whereNull('deleted_at')->whereIn('rt_id', $ids)->get(); + $rtIds = []; + foreach ($this->ids as $recurrenceId) { + $rtIds = array_merge($rtIds, array_keys($this->transactions[$recurrenceId])); + } + $meta = RecurrenceTransactionMeta::whereNull('deleted_at')->whereIn('rt_id', $rtIds)->get(); // other meta-data to be collected: $billIds = []; $piggyBankIds = []; @@ -386,10 +387,11 @@ class RecurringEnrichment implements EnrichmentInterface $transactionId = (int)$entry->rt_id; // this should refer to another array, were rtIds can be used to find the recurrence. - $recurrenceId = $this->recurrenceIds[$transactionId] ?? 0; - $name = (string)($entry->name ?? ''); + $recurrenceId = $this->recurrenceByTransaction[$transactionId] ?? 0; + Log::debug(sprintf('Collecting meta data entry #%d for recurrence transaction #%d, for recurrence #%d ', $id, $transactionId, $recurrenceId)); + $name = (string)($entry->name ?? ''); if (0 === $recurrenceId) { - Log::error(sprintf('Could not find recurrence ID for recurrence transaction ID %d', $transactionId)); + Log::error(sprintf('Could not find recurrence ID for recurrence transaction ID #%d', $transactionId)); continue; } @@ -487,16 +489,16 @@ class RecurringEnrichment implements EnrichmentInterface /** @var RecurrenceTransaction $transaction */ foreach ($set as $transaction) { - $id = (int)$transaction->recurrence_id; - $transactionId = (int)$transaction->id; - $this->recurrenceIds[$transactionId] = $id; - $this->transactions[$id] ??= []; - $amount = $transaction->amount; - $foreignAmount = $transaction->foreign_amount; + $recurrenceId = (int)$transaction->recurrence_id; + $transactionId = (int)$transaction->id; + $this->recurrenceByTransaction[$transactionId] = $recurrenceId; + $this->transactions[$recurrenceId] ??= []; + $amount = $transaction->amount; + $foreignAmount = $transaction->foreign_amount; + Log::debug(sprintf('Collected transaction #%d of recurrence #%d', $transactionId, $recurrenceId)); - $this->transactions[$id][$transactionId] = [ + $this->transactions[$recurrenceId][$transactionId] = [ 'id' => (string)$transactionId, - // 'recurrence_id' => $id, 'transaction_currency_id' => (int)$transaction->transaction_currency_id, 'foreign_currency_id' => null === $transaction->foreign_currency_id ? null : (int)$transaction->foreign_currency_id, 'source_id' => (int)$transaction->source_id, @@ -518,7 +520,7 @@ class RecurringEnrichment implements EnrichmentInterface 'subscription_name' => null, ]; - // collect all kinds of meta data to be collected later. + // collect all kinds of meta-data to be collected later. $this->currencyIds[$transactionId] = (int)$transaction->transaction_currency_id; $this->sourceAccountIds[$transactionId] = (int)$transaction->source_id; $this->destinationAccountIds[$transactionId] = (int)$transaction->destination_id; @@ -531,8 +533,8 @@ class RecurringEnrichment implements EnrichmentInterface private function getLanguage(): void { /** @var Preference $preference */ - $preference = Preferences::getForUser($this->user, 'language', config('firefly.default_language', 'en_US')); - $language = $preference->data; + $preference = Preferences::getForUser($this->user, 'language', config('firefly.default_language', 'en_US')); + $language = $preference->data; if (is_array($language)) { $language = 'en_US'; } @@ -545,9 +547,9 @@ class RecurringEnrichment implements EnrichmentInterface $return = []; $converter = new ExchangeRateConverter(); foreach ($transactions as $transaction) { - $currencyId = $transaction['transaction_currency_id']; - $pcAmount = null; - $pcForeignAmount = null; + $currencyId = $transaction['transaction_currency_id']; + $pcAmount = null; + $pcForeignAmount = null; // set the same amount in the primary currency, if both are the same anyway. if ($this->convertToPrimary && $currencyId === (int)$this->primaryCurrency->id) { $pcAmount = $transaction['amount']; @@ -563,26 +565,26 @@ class RecurringEnrichment implements EnrichmentInterface } } - $transaction['pc_amount'] = $pcAmount; - $transaction['pc_foreign_amount'] = $pcForeignAmount; + $transaction['pc_amount'] = $pcAmount; + $transaction['pc_foreign_amount'] = $pcForeignAmount; - $sourceId = $transaction['source_id']; - $transaction['source_name'] = $this->accounts[$sourceId]->name; - $transaction['source_iban'] = $this->accounts[$sourceId]->iban; - $transaction['source_type'] = $this->accounts[$sourceId]->accountType->type; - $transaction['source_id'] = (string)$transaction['source_id']; + $sourceId = $transaction['source_id']; + $transaction['source_name'] = $this->accounts[$sourceId]->name; + $transaction['source_iban'] = $this->accounts[$sourceId]->iban; + $transaction['source_type'] = $this->accounts[$sourceId]->accountType->type; + $transaction['source_id'] = (string)$transaction['source_id']; - $destId = $transaction['destination_id']; - $transaction['destination_name'] = $this->accounts[$destId]->name; - $transaction['destination_iban'] = $this->accounts[$destId]->iban; - $transaction['destination_type'] = $this->accounts[$destId]->accountType->type; - $transaction['destination_id'] = (string)$transaction['destination_id']; + $destId = $transaction['destination_id']; + $transaction['destination_name'] = $this->accounts[$destId]->name; + $transaction['destination_iban'] = $this->accounts[$destId]->iban; + $transaction['destination_type'] = $this->accounts[$destId]->accountType->type; + $transaction['destination_id'] = (string)$transaction['destination_id']; - $transaction['currency_id'] = (string)$currencyId; - $transaction['currency_name'] = $this->currencies[$currencyId]->name; - $transaction['currency_code'] = $this->currencies[$currencyId]->code; - $transaction['currency_symbol'] = $this->currencies[$currencyId]->symbol; - $transaction['currency_decimal_places'] = $this->currencies[$currencyId]->decimal_places; + $transaction['currency_id'] = (string)$currencyId; + $transaction['currency_name'] = $this->currencies[$currencyId]->name; + $transaction['currency_code'] = $this->currencies[$currencyId]->code; + $transaction['currency_symbol'] = $this->currencies[$currencyId]->symbol; + $transaction['currency_decimal_places'] = $this->currencies[$currencyId]->decimal_places; $transaction['primary_currency_id'] = (string)$this->primaryCurrency->id; $transaction['primary_currency_name'] = $this->primaryCurrency->name; @@ -604,7 +606,7 @@ class RecurringEnrichment implements EnrichmentInterface $transaction['foreign_currency_decimal_places'] = $this->currencies[$currencyId]->decimal_places; } unset($transaction['transaction_currency_id']); - $return[] = $transaction; + $return[] = $transaction; } return $return; From 69b46af245036cf69f7da9d2966b27b9e4759138 Mon Sep 17 00:00:00 2001 From: JC5 Date: Mon, 17 Nov 2025 19:08:12 +0100 Subject: [PATCH 07/26] =?UTF-8?q?=F0=9F=A4=96=20Auto=20commit=20for=20rele?= =?UTF-8?q?ase=20'develop'=20on=202025-11-17?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/Recurring/EditController.php | 6 +- .../Enrichments/RecurringEnrichment.php | 108 +++++++++--------- config/firefly.php | 2 +- package-lock.json | 18 +-- 4 files changed, 68 insertions(+), 66 deletions(-) diff --git a/app/Http/Controllers/Recurring/EditController.php b/app/Http/Controllers/Recurring/EditController.php index dbbd7c2947..0141ce94f2 100644 --- a/app/Http/Controllers/Recurring/EditController.php +++ b/app/Http/Controllers/Recurring/EditController.php @@ -173,7 +173,7 @@ class EditController extends Controller */ public function update(RecurrenceFormRequest $request, Recurrence $recurrence) { - $data = $request->getAll(); + $data = $request->getAll(); $recurrence = $this->repository->update($recurrence, $data); $request->session()->flash('success', (string) trans('firefly.updated_recurrence', ['title' => $recurrence->title])); @@ -181,7 +181,7 @@ class EditController extends Controller // store new attachment(s): /** @var null|array $files */ - $files = $request->hasFile('attachments') ? $request->file('attachments') : null; + $files = $request->hasFile('attachments') ? $request->file('attachments') : null; if (null !== $files && !auth()->user()->hasRole('demo')) { $this->attachments->saveAttachmentsForModel($recurrence, $files); } @@ -194,7 +194,7 @@ class EditController extends Controller $request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); } app('preferences')->mark(); - $redirect = redirect($this->getPreviousUrl('recurrences.edit.url')); + $redirect = redirect($this->getPreviousUrl('recurrences.edit.url')); if (1 === (int) $request->get('return_to_edit')) { // set value so edit routine will not overwrite URL: $request->session()->put('recurrences.edit.fromUpdate', true); diff --git a/app/Support/JsonApi/Enrichments/RecurringEnrichment.php b/app/Support/JsonApi/Enrichments/RecurringEnrichment.php index 0143aa2602..6257cf8426 100644 --- a/app/Support/JsonApi/Enrichments/RecurringEnrichment.php +++ b/app/Support/JsonApi/Enrichments/RecurringEnrichment.php @@ -51,11 +51,12 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Log; + use function Safe\json_decode; class RecurringEnrichment implements EnrichmentInterface { - private array $accounts = []; + private array $accounts = []; private Collection $collection; // private array $transactionTypeIds = []; // private array $transactionTypes = []; @@ -99,7 +100,7 @@ class RecurringEnrichment implements EnrichmentInterface return $this->collection; } - public function enrichSingle(array | Model $model): array | Model + public function enrichSingle(array|Model $model): array|Model { Log::debug(__METHOD__); $collection = new Collection()->push($model); @@ -133,7 +134,7 @@ class RecurringEnrichment implements EnrichmentInterface return (string)trans('firefly.recurring_monthly', ['dayOfMonth' => $repetition->repetition_moment, 'skip' => $repetition->repetition_skip - 1], $this->language); } if ('ndom' === $repetition->repetition_type) { - $parts = explode(',', $repetition->repetition_moment); + $parts = explode(',', $repetition->repetition_moment); // first part is number of week, second is weekday. $dayOfWeek = trans(sprintf('config.dow_%s', $parts[1]), [], $this->language); if ($repetition->repetition_skip > 0) { @@ -150,7 +151,7 @@ class RecurringEnrichment implements EnrichmentInterface } // $diffInYears = (int)$today->diffInYears($repDate, true); // $repDate->addYears($diffInYears); // technically not necessary. - $string = $repDate->isoFormat((string)trans('config.month_and_day_no_year_js')); + $string = $repDate->isoFormat((string)trans('config.month_and_day_no_year_js')); return (string)trans('firefly.recurring_yearly', ['date' => $string], $this->language); } @@ -173,8 +174,8 @@ class RecurringEnrichment implements EnrichmentInterface private function appendCollectedData(): void { $this->collection = $this->collection->map(function (Recurrence $item): Recurrence { - $id = (int)$item->id; - $meta = [ + $id = (int)$item->id; + $meta = [ 'notes' => $this->notes[$id] ?? null, 'repetitions' => array_values($this->repetitions[$id] ?? []), 'transactions' => $this->processTransactions(array_values($this->transactions[$id] ?? [])), @@ -300,9 +301,10 @@ class RecurringEnrichment implements EnrichmentInterface private function collectNotes(): void { $notes = Note::query()->whereIn('noteable_id', $this->ids) - ->whereNotNull('notes.text') - ->where('notes.text', '!=', '') - ->where('noteable_type', Recurrence::class)->get(['notes.id', 'notes.noteable_id', 'notes.text'])->toArray(); + ->whereNotNull('notes.text') + ->where('notes.text', '!=', '') + ->where('noteable_type', Recurrence::class)->get(['notes.id', 'notes.noteable_id', 'notes.text'])->toArray() + ; foreach ($notes as $note) { $notableId = (int)$note['noteable_id']; $this->notes[$notableId] = (string)$note['text']; @@ -334,21 +336,21 @@ class RecurringEnrichment implements EnrichmentInterface Log::debug('Start of enrichment: collectRepetitions()'); $repository = app(RecurringRepositoryInterface::class); $repository->setUserGroup($this->userGroup); - $set = RecurrenceRepetition::whereIn('recurrence_id', $this->ids)->get(); + $set = RecurrenceRepetition::whereIn('recurrence_id', $this->ids)->get(); /** @var RecurrenceRepetition $repetition */ foreach ($set as $repetition) { - $recurrence = $this->collection->filter(fn(Recurrence $item): bool => (int)$item->id === (int)$repetition->recurrence_id)->first(); - $fromDate = clone($recurrence->latest_date ?? $recurrence->first_date); - $recurrenceId = (int)$repetition->recurrence_id; - $repId = (int)$repetition->id; + $recurrence = $this->collection->filter(fn (Recurrence $item): bool => (int)$item->id === (int)$repetition->recurrence_id)->first(); + $fromDate = clone ($recurrence->latest_date ?? $recurrence->first_date); + $recurrenceId = (int)$repetition->recurrence_id; + $repId = (int)$repetition->id; $this->repetitions[$recurrenceId] ??= []; Log::debug(sprintf('Collected repetition #%d of recurrence #%d.', $repId, $recurrenceId)); // get the (future) occurrences for this specific type of repetition: - $amount = 'daily' === $repetition->repetition_type ? 9 : 5; - $set = $repository->getXOccurrencesSince($repetition, $fromDate, now(config('app.timezone')), $amount); - $occurrences = []; + $amount = 'daily' === $repetition->repetition_type ? 9 : 5; + $set = $repository->getXOccurrencesSince($repetition, $fromDate, now(config('app.timezone')), $amount); + $occurrences = []; /** @var Carbon $carbon */ foreach ($set as $carbon) { @@ -371,11 +373,11 @@ class RecurringEnrichment implements EnrichmentInterface private function collectTransactionMetaData(): void { - $rtIds = []; + $rtIds = []; foreach ($this->ids as $recurrenceId) { $rtIds = array_merge($rtIds, array_keys($this->transactions[$recurrenceId])); } - $meta = RecurrenceTransactionMeta::whereNull('deleted_at')->whereIn('rt_id', $rtIds)->get(); + $meta = RecurrenceTransactionMeta::whereNull('deleted_at')->whereIn('rt_id', $rtIds)->get(); // other meta-data to be collected: $billIds = []; $piggyBankIds = []; @@ -387,9 +389,9 @@ class RecurringEnrichment implements EnrichmentInterface $transactionId = (int)$entry->rt_id; // this should refer to another array, were rtIds can be used to find the recurrence. - $recurrenceId = $this->recurrenceByTransaction[$transactionId] ?? 0; + $recurrenceId = $this->recurrenceByTransaction[$transactionId] ?? 0; Log::debug(sprintf('Collecting meta data entry #%d for recurrence transaction #%d, for recurrence #%d ', $id, $transactionId, $recurrenceId)); - $name = (string)($entry->name ?? ''); + $name = (string)($entry->name ?? ''); if (0 === $recurrenceId) { Log::error(sprintf('Could not find recurrence ID for recurrence transaction ID #%d', $transactionId)); @@ -489,12 +491,12 @@ class RecurringEnrichment implements EnrichmentInterface /** @var RecurrenceTransaction $transaction */ foreach ($set as $transaction) { - $recurrenceId = (int)$transaction->recurrence_id; - $transactionId = (int)$transaction->id; - $this->recurrenceByTransaction[$transactionId] = $recurrenceId; - $this->transactions[$recurrenceId] ??= []; - $amount = $transaction->amount; - $foreignAmount = $transaction->foreign_amount; + $recurrenceId = (int)$transaction->recurrence_id; + $transactionId = (int)$transaction->id; + $this->recurrenceByTransaction[$transactionId] = $recurrenceId; + $this->transactions[$recurrenceId] ??= []; + $amount = $transaction->amount; + $foreignAmount = $transaction->foreign_amount; Log::debug(sprintf('Collected transaction #%d of recurrence #%d', $transactionId, $recurrenceId)); $this->transactions[$recurrenceId][$transactionId] = [ @@ -521,9 +523,9 @@ class RecurringEnrichment implements EnrichmentInterface ]; // collect all kinds of meta-data to be collected later. - $this->currencyIds[$transactionId] = (int)$transaction->transaction_currency_id; - $this->sourceAccountIds[$transactionId] = (int)$transaction->source_id; - $this->destinationAccountIds[$transactionId] = (int)$transaction->destination_id; + $this->currencyIds[$transactionId] = (int)$transaction->transaction_currency_id; + $this->sourceAccountIds[$transactionId] = (int)$transaction->source_id; + $this->destinationAccountIds[$transactionId] = (int)$transaction->destination_id; if (null !== $transaction->foreign_currency_id) { $this->foreignCurrencyIds[$transactionId] = (int)$transaction->foreign_currency_id; } @@ -533,8 +535,8 @@ class RecurringEnrichment implements EnrichmentInterface private function getLanguage(): void { /** @var Preference $preference */ - $preference = Preferences::getForUser($this->user, 'language', config('firefly.default_language', 'en_US')); - $language = $preference->data; + $preference = Preferences::getForUser($this->user, 'language', config('firefly.default_language', 'en_US')); + $language = $preference->data; if (is_array($language)) { $language = 'en_US'; } @@ -547,9 +549,9 @@ class RecurringEnrichment implements EnrichmentInterface $return = []; $converter = new ExchangeRateConverter(); foreach ($transactions as $transaction) { - $currencyId = $transaction['transaction_currency_id']; - $pcAmount = null; - $pcForeignAmount = null; + $currencyId = $transaction['transaction_currency_id']; + $pcAmount = null; + $pcForeignAmount = null; // set the same amount in the primary currency, if both are the same anyway. if ($this->convertToPrimary && $currencyId === (int)$this->primaryCurrency->id) { $pcAmount = $transaction['amount']; @@ -565,26 +567,26 @@ class RecurringEnrichment implements EnrichmentInterface } } - $transaction['pc_amount'] = $pcAmount; - $transaction['pc_foreign_amount'] = $pcForeignAmount; + $transaction['pc_amount'] = $pcAmount; + $transaction['pc_foreign_amount'] = $pcForeignAmount; - $sourceId = $transaction['source_id']; - $transaction['source_name'] = $this->accounts[$sourceId]->name; - $transaction['source_iban'] = $this->accounts[$sourceId]->iban; - $transaction['source_type'] = $this->accounts[$sourceId]->accountType->type; - $transaction['source_id'] = (string)$transaction['source_id']; + $sourceId = $transaction['source_id']; + $transaction['source_name'] = $this->accounts[$sourceId]->name; + $transaction['source_iban'] = $this->accounts[$sourceId]->iban; + $transaction['source_type'] = $this->accounts[$sourceId]->accountType->type; + $transaction['source_id'] = (string)$transaction['source_id']; - $destId = $transaction['destination_id']; - $transaction['destination_name'] = $this->accounts[$destId]->name; - $transaction['destination_iban'] = $this->accounts[$destId]->iban; - $transaction['destination_type'] = $this->accounts[$destId]->accountType->type; - $transaction['destination_id'] = (string)$transaction['destination_id']; + $destId = $transaction['destination_id']; + $transaction['destination_name'] = $this->accounts[$destId]->name; + $transaction['destination_iban'] = $this->accounts[$destId]->iban; + $transaction['destination_type'] = $this->accounts[$destId]->accountType->type; + $transaction['destination_id'] = (string)$transaction['destination_id']; - $transaction['currency_id'] = (string)$currencyId; - $transaction['currency_name'] = $this->currencies[$currencyId]->name; - $transaction['currency_code'] = $this->currencies[$currencyId]->code; - $transaction['currency_symbol'] = $this->currencies[$currencyId]->symbol; - $transaction['currency_decimal_places'] = $this->currencies[$currencyId]->decimal_places; + $transaction['currency_id'] = (string)$currencyId; + $transaction['currency_name'] = $this->currencies[$currencyId]->name; + $transaction['currency_code'] = $this->currencies[$currencyId]->code; + $transaction['currency_symbol'] = $this->currencies[$currencyId]->symbol; + $transaction['currency_decimal_places'] = $this->currencies[$currencyId]->decimal_places; $transaction['primary_currency_id'] = (string)$this->primaryCurrency->id; $transaction['primary_currency_name'] = $this->primaryCurrency->name; @@ -606,7 +608,7 @@ class RecurringEnrichment implements EnrichmentInterface $transaction['foreign_currency_decimal_places'] = $this->currencies[$currencyId]->decimal_places; } unset($transaction['transaction_currency_id']); - $return[] = $transaction; + $return[] = $transaction; } return $return; diff --git a/config/firefly.php b/config/firefly.php index 621ebb59cf..cc11a74b7f 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -79,7 +79,7 @@ return [ // see cer.php for exchange rates feature flag. ], 'version' => 'develop/2025-11-17', - 'build_time' => 1763350067, + 'build_time' => 1763402780, 'api_version' => '2.1.0', // field is no longer used. 'db_version' => 28, // field is no longer used. diff --git a/package-lock.json b/package-lock.json index ffaec8bd69..cdadcc353f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4075,9 +4075,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.8.28", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.28.tgz", - "integrity": "sha512-gYjt7OIqdM0PcttNYP2aVrr2G0bMALkBaoehD4BuRGjAOtipg0b6wHg1yNL+s5zSnLZZrGHOw4IrND8CD+3oIQ==", + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.29.tgz", + "integrity": "sha512-sXdt2elaVnhpDNRDz+1BDx1JQoJRuNk7oVlAlbGiFkLikHCAQiccexF/9e91zVi6RCgqspl04aP+6Cnl9zRLrA==", "dev": true, "license": "Apache-2.0", "bin": { @@ -5365,9 +5365,9 @@ } }, "node_modules/csstype": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.2.tgz", - "integrity": "sha512-D80T+tiqkd/8B0xNlbstWDG4x6aqVfO52+OlSUNIdkTvmNw0uQpJLeos2J/2XvpyidAFuTPmpad+tUxLndwj6g==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "dev": true, "license": "MIT" }, @@ -6443,9 +6443,9 @@ } }, "node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "dev": true, "license": "MIT", "dependencies": { From 3f386b9003b8dea72ce11e36e201865556a5f7fa Mon Sep 17 00:00:00 2001 From: James Cole Date: Wed, 19 Nov 2025 06:26:40 +0100 Subject: [PATCH 08/26] Fix #11191 --- .../Controllers/Account/IndexController.php | 7 ++++++- .../Controllers/Account/ShowController.php | 19 +++++++++---------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/app/Http/Controllers/Account/IndexController.php b/app/Http/Controllers/Account/IndexController.php index 564dc3401e..174328d275 100644 --- a/app/Http/Controllers/Account/IndexController.php +++ b/app/Http/Controllers/Account/IndexController.php @@ -167,12 +167,17 @@ class IndexController extends Controller /** @var Carbon $end */ $end = clone session('end', today(config('app.timezone'))->endOfMonth()); + $now = now(); + if ($now->gt($end) || $now->lt($start)) { + $now = $end; + } + $ids = $accounts->pluck('id')->toArray(); Log::debug(sprintf('index: accountsBalancesInRange("%s", "%s")', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s'))); [ $startBalances, $endBalances, - ] = Steam::accountsBalancesInRange($accounts, $start, $end, $this->primaryCurrency, $this->convertToPrimary); + ] = Steam::accountsBalancesInRange($accounts, $start, $now, $this->primaryCurrency, $this->convertToPrimary); $activities = Steam::getLastActivities($ids); diff --git a/app/Http/Controllers/Account/ShowController.php b/app/Http/Controllers/Account/ShowController.php index 1d5edb91fc..d9f2d77f77 100644 --- a/app/Http/Controllers/Account/ShowController.php +++ b/app/Http/Controllers/Account/ShowController.php @@ -164,7 +164,7 @@ class ShowController extends Controller $timer->stop('collection'); $groups->setPath(route('accounts.show', [$account->id, $start->format('Y-m-d'), $end->format('Y-m-d')])); $showAll = false; - $now = today()->endOfDay(); + $now = now(); if ($now->gt($end) || $now->lt($start)) { $now = $end; } @@ -173,10 +173,7 @@ class ShowController extends Controller $balances = Steam::accountsBalancesOptimized(new Collection()->push($account), $now)[$account->id]; // $balances = Steam::filterAccountBalance(Steam::finalAccountBalance($account, $now), $account, $this->convertToPrimary, $accountCurrency); - return view( - 'accounts.show', - ['account' => $account, 'showAll' => $showAll, 'objectType' => $objectType, 'currency' => $currency, 'today' => $today, 'periods' => $periods, 'subTitleIcon' => $subTitleIcon, 'groups' => $groups, 'attachments' => $attachments, 'subTitle' => $subTitle, 'start' => $start, 'end' => $end, 'chartUrl' => $chartUrl, 'location' => $location, 'balances' => $balances] - ); + return view('accounts.show', ['account' => $account, 'showAll' => $showAll, 'objectType' => $objectType, 'currency' => $currency, 'today' => $today, 'periods' => $periods, 'subTitleIcon' => $subTitleIcon, 'groups' => $groups, 'attachments' => $attachments, 'subTitle' => $subTitle, 'start' => $start, 'end' => $end, 'chartUrl' => $chartUrl, 'location' => $location, 'balances' => $balances]); } /** @@ -224,14 +221,16 @@ class ShowController extends Controller // correct Log::debug(sprintf('showAll: Call accountsBalancesOptimized with date/time "%s"', $end->toIso8601String())); + $now = now(); + if ($now->gt($end) || $now->lt($start)) { + $now = $end; + } + // 2025-10-08 replace finalAccountBalance with accountsBalancesOptimized. // $balances = Steam::finalAccountBalance($account, $end); // $balances = Steam::filterAccountBalance($balances, $account, $this->convertToPrimary, $accountCurrency); - $balances = Steam::accountsBalancesOptimized(new Collection()->push($account), $end)[$account->id]; + $balances = Steam::accountsBalancesOptimized(new Collection()->push($account), $now)[$account->id]; - return view( - 'accounts.show', - ['account' => $account, 'showAll' => $showAll, 'location' => $location, 'objectType' => $objectType, 'isLiability' => $isLiability, 'attachments' => $attachments, 'currency' => $currency, 'today' => $today, 'chartUrl' => $chartUrl, 'periods' => $periods, 'subTitleIcon' => $subTitleIcon, 'groups' => $groups, 'subTitle' => $subTitle, 'start' => $start, 'end' => $end, 'balances' => $balances] - ); + return view('accounts.show', ['account' => $account, 'showAll' => $showAll, 'location' => $location, 'objectType' => $objectType, 'isLiability' => $isLiability, 'attachments' => $attachments, 'currency' => $currency, 'today' => $today, 'chartUrl' => $chartUrl, 'periods' => $periods, 'subTitleIcon' => $subTitleIcon, 'groups' => $groups, 'subTitle' => $subTitle, 'start' => $start, 'end' => $end, 'balances' => $balances]); } } From 21a689260187d02d8fd0e0366003881af2b6a050 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sun, 23 Nov 2025 06:55:54 +0100 Subject: [PATCH 09/26] Fix #11265 --- .../Models/CurrencyExchangeRate/IndexController.php | 2 +- changelog.md | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/Api/V1/Controllers/Models/CurrencyExchangeRate/IndexController.php b/app/Api/V1/Controllers/Models/CurrencyExchangeRate/IndexController.php index f5bdd92d87..226a091487 100644 --- a/app/Api/V1/Controllers/Models/CurrencyExchangeRate/IndexController.php +++ b/app/Api/V1/Controllers/Models/CurrencyExchangeRate/IndexController.php @@ -40,7 +40,7 @@ class IndexController extends Controller { use ValidatesUserGroupTrait; - public const string RESOURCE_KEY = 'currency_exchange_rates'; + public const string RESOURCE_KEY = 'exchange-rates'; protected array $acceptedRoles = [UserRoleEnum::OWNER]; private ExchangeRateRepositoryInterface $repository; diff --git a/changelog.md b/changelog.md index 5f26330636..821ec7980c 100644 --- a/changelog.md +++ b/changelog.md @@ -9,6 +9,10 @@ This project adheres to [Semantic Versioning](http://semver.org/). - [Discussion 11211](https://github.com/orgs/firefly-iii/discussions/11211) (question about Transaction journal ID) started by @zhiiwg +### API + +- #11265 + ## 6.4.8 - 2025-11-14 ### Fixed From 5fea35d5b19bd4166b606e32392cbd0a65730104 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sun, 23 Nov 2025 08:44:01 +0100 Subject: [PATCH 10/26] Allow command to be forced. --- .../Commands/System/ForcesDecimalSize.php | 180 +++++++++--------- 1 file changed, 90 insertions(+), 90 deletions(-) diff --git a/app/Console/Commands/System/ForcesDecimalSize.php b/app/Console/Commands/System/ForcesDecimalSize.php index e3a644e2bc..0a39fedf78 100644 --- a/app/Console/Commands/System/ForcesDecimalSize.php +++ b/app/Console/Commands/System/ForcesDecimalSize.php @@ -42,7 +42,6 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Log; - use function Safe\json_encode; use function Safe\mb_regex_encoding; @@ -55,11 +54,11 @@ class ForcesDecimalSize extends Command { use ShowsFriendlyMessages; - protected $description = 'This command resizes DECIMAL columns in MySQL or PostgreSQL and correct amounts (only MySQL).'; - protected $signature = 'firefly-iii:force-decimal-size'; + protected $description = 'This command resizes DECIMAL columns in MySQL or PostgreSQL and correct amounts (only MySQL).'; + protected $signature = 'firefly-iii:force-decimal-size {--force}'; private string $cast; private array $classes - = [ + = [ 'accounts' => Account::class, 'auto_budgets' => AutoBudget::class, 'available_budgets' => AvailableBudget::class, @@ -75,7 +74,7 @@ class ForcesDecimalSize extends Command private string $operator; private string $regularExpression; private array $tables - = [ + = [ 'accounts' => ['virtual_balance'], 'auto_budgets' => ['amount'], 'available_budgets' => ['amount'], @@ -98,9 +97,14 @@ class ForcesDecimalSize extends Command Log::debug('Now in ForceDecimalSize::handle()'); $this->determineDatabaseType(); - $this->friendlyError('Running this command is dangerous and can cause data loss.'); - $this->friendlyError('Please do not continue.'); - $question = $this->confirm('Do you want to continue?'); + $force = $this->option('force'); + $question = true; + if (false === $force) { + $this->friendlyError('Running this command is dangerous and can cause data loss.'); + $this->friendlyError('Please make sure you have a backup.'); + $question = $this->confirm('Do you want to continue?'); + } + if (true === $question) { $this->correctAmounts(); $this->updateDecimals(); @@ -131,17 +135,17 @@ class ForcesDecimalSize extends Command private function correctAmounts(): void { // if sqlite, add function? - if ('sqlite' === (string) config('database.default')) { + if ('sqlite' === (string)config('database.default')) { DB::connection()->getPdo()->sqliteCreateFunction('REGEXP', static function ($pattern, $value): int { mb_regex_encoding('UTF-8'); $pattern = trim($pattern, '"'); - return (mb_ereg($pattern, (string) $value)) ? 1 : 0; + return (mb_ereg($pattern, (string)$value)) ? 1 : 0; }); } - if (!in_array((string) config('database.default'), ['mysql', 'pgsql', 'sqlite'], true)) { - $this->friendlyWarning(sprintf('Skip correcting amounts, does not support "%s"...', (string) config('database.default'))); + if (!in_array((string)config('database.default'), ['mysql', 'pgsql', 'sqlite'], true)) { + $this->friendlyWarning(sprintf('Skip correcting amounts, does not support "%s"...', (string)config('database.default'))); return; } @@ -234,10 +238,9 @@ class ForcesDecimalSize extends Command $regularExpression = $this->regularExpression; /** @var Builder $query */ - $query = Account::leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id') - ->where('account_meta.name', 'currency_id') - ->where('account_meta.data', json_encode((string) $currency->id)) - ; + $query = Account::leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id') + ->where('account_meta.name', 'currency_id') + ->where('account_meta.data', json_encode((string)$currency->id)); $query->where(static function (Builder $q) use ($fields, $currency, $operator, $cast, $regularExpression): void { foreach ($fields as $field) { $q->orWhere( @@ -247,7 +250,7 @@ class ForcesDecimalSize extends Command ); } }); - $result = $query->get(['accounts.*']); + $result = $query->get(['accounts.*']); if (0 === $result->count()) { $this->friendlyPositive(sprintf('All accounts in %s are OK', $currency->code)); @@ -258,13 +261,13 @@ class ForcesDecimalSize extends Command foreach ($result as $account) { /** @var string $field */ foreach ($fields as $field) { - $value = $account->{$field}; + $value = $account->{$field}; if (null === $value) { continue; } // fix $field by rounding it down correctly. - $pow = 10 ** $currency->decimal_places; - $correct = bcdiv((string) round($value * $pow), (string) $pow, 12); + $pow = 10 ** $currency->decimal_places; + $correct = bcdiv((string)round($value * $pow), (string)$pow, 12); $this->friendlyInfo(sprintf('Account #%d has %s with value "%s", this has been corrected to "%s".', $account->id, $field, $value, $correct)); /** @var null|Account $updateAccount */ @@ -286,7 +289,7 @@ class ForcesDecimalSize extends Command $regularExpression = $this->regularExpression; /** @var Builder $query */ - $query = $class::where('transaction_currency_id', $currency->id)->where( + $query = $class::where('transaction_currency_id', $currency->id)->where( static function (Builder $q) use ($fields, $currency, $operator, $cast, $regularExpression): void { /** @var string $field */ foreach ($fields as $field) { @@ -299,7 +302,7 @@ class ForcesDecimalSize extends Command } ); - $result = $query->get(); + $result = $query->get(); if (0 === $result->count()) { $this->friendlyPositive(sprintf('All %s in %s are OK', $table, $currency->code)); @@ -310,17 +313,17 @@ class ForcesDecimalSize extends Command foreach ($result as $item) { /** @var string $field */ foreach ($fields as $field) { - $value = $item->{$field}; + $value = $item->{$field}; if (null === $value || '' === $value) { continue; } // fix $field by rounding it down correctly. $pow = 10 ** $currency->decimal_places; - $correct = bcdiv((string) round($value * $pow), (string) $pow, 12); + $correct = bcdiv((string)round($value * $pow), (string)$pow, 12); $this->friendlyWarning(sprintf('%s #%d has %s with value "%s", this has been corrected to "%s".', $table, $item->id, $field, $value, $correct)); /** @var null|Model $model */ - $model = $class::find($item->id); + $model = $class::find($item->id); $model?->update([$field => $correct]); } } @@ -336,23 +339,22 @@ class ForcesDecimalSize extends Command $regularExpression = $this->regularExpression; /** @var Builder $query */ - $query = PiggyBankEvent::leftJoin('piggy_banks', 'piggy_bank_events.piggy_bank_id', '=', 'piggy_banks.id') - ->leftJoin('accounts', 'piggy_banks.account_id', '=', 'accounts.id') - ->leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id') - ->where('account_meta.name', 'currency_id') - ->where('account_meta.data', json_encode((string) $currency->id)) - ->where(static function (Builder $q) use ($fields, $currency, $cast, $operator, $regularExpression): void { - foreach ($fields as $field) { - $q->orWhere( - DB::raw(sprintf('CAST(piggy_bank_events.%s AS %s)', $field, $cast)), - $operator, - DB::raw(sprintf($regularExpression, $currency->decimal_places)) - ); - } - }) - ; + $query = PiggyBankEvent::leftJoin('piggy_banks', 'piggy_bank_events.piggy_bank_id', '=', 'piggy_banks.id') + ->leftJoin('accounts', 'piggy_banks.account_id', '=', 'accounts.id') + ->leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id') + ->where('account_meta.name', 'currency_id') + ->where('account_meta.data', json_encode((string)$currency->id)) + ->where(static function (Builder $q) use ($fields, $currency, $cast, $operator, $regularExpression): void { + foreach ($fields as $field) { + $q->orWhere( + DB::raw(sprintf('CAST(piggy_bank_events.%s AS %s)', $field, $cast)), + $operator, + DB::raw(sprintf($regularExpression, $currency->decimal_places)) + ); + } + }); - $result = $query->get(['piggy_bank_events.*']); + $result = $query->get(['piggy_bank_events.*']); if (0 === $result->count()) { $this->friendlyPositive(sprintf('All piggy bank events in %s are OK', $currency->code)); @@ -363,19 +365,19 @@ class ForcesDecimalSize extends Command foreach ($result as $item) { /** @var string $field */ foreach ($fields as $field) { - $value = $item->{$field}; + $value = $item->{$field}; if (null === $value) { continue; } // fix $field by rounding it down correctly. $pow = 10 ** $currency->decimal_places; - $correct = bcdiv((string) round($value * $pow), (string) $pow, 12); + $correct = bcdiv((string)round($value * $pow), (string)$pow, 12); $this->friendlyWarning( sprintf('Piggy bank event #%d has %s with value "%s", this has been corrected to "%s".', $item->id, $field, $value, $correct) ); /** @var null|PiggyBankEvent $event */ - $event = PiggyBankEvent::find($item->id); + $event = PiggyBankEvent::find($item->id); $event?->update([$field => $correct]); } } @@ -392,23 +394,22 @@ class ForcesDecimalSize extends Command // select all piggy bank repetitions with this currency and issue. /** @var Builder $query */ - $query = PiggyBankRepetition::leftJoin('piggy_banks', 'piggy_bank_repetitions.piggy_bank_id', '=', 'piggy_banks.id') - ->leftJoin('accounts', 'piggy_banks.account_id', '=', 'accounts.id') - ->leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id') - ->where('account_meta.name', 'currency_id') - ->where('account_meta.data', json_encode((string) $currency->id)) - ->where(static function (Builder $q) use ($fields, $currency, $operator, $cast, $regularExpression): void { - foreach ($fields as $field) { - $q->orWhere( - DB::raw(sprintf('CAST(piggy_bank_repetitions.%s AS %s)', $field, $cast)), - $operator, - DB::raw(sprintf($regularExpression, $currency->decimal_places)) - ); - } - }) - ; + $query = PiggyBankRepetition::leftJoin('piggy_banks', 'piggy_bank_repetitions.piggy_bank_id', '=', 'piggy_banks.id') + ->leftJoin('accounts', 'piggy_banks.account_id', '=', 'accounts.id') + ->leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id') + ->where('account_meta.name', 'currency_id') + ->where('account_meta.data', json_encode((string)$currency->id)) + ->where(static function (Builder $q) use ($fields, $currency, $operator, $cast, $regularExpression): void { + foreach ($fields as $field) { + $q->orWhere( + DB::raw(sprintf('CAST(piggy_bank_repetitions.%s AS %s)', $field, $cast)), + $operator, + DB::raw(sprintf($regularExpression, $currency->decimal_places)) + ); + } + }); - $result = $query->get(['piggy_bank_repetitions.*']); + $result = $query->get(['piggy_bank_repetitions.*']); if (0 === $result->count()) { $this->friendlyPositive(sprintf('All piggy bank repetitions in %s', $currency->code)); @@ -419,13 +420,13 @@ class ForcesDecimalSize extends Command foreach ($result as $item) { /** @var string $field */ foreach ($fields as $field) { - $value = $item->{$field}; + $value = $item->{$field}; if (null === $value) { continue; } // fix $field by rounding it down correctly. - $pow = 10 ** $currency->decimal_places; - $correct = bcdiv((string) round($value * $pow), (string) $pow, 12); + $pow = 10 ** $currency->decimal_places; + $correct = bcdiv((string)round($value * $pow), (string)$pow, 12); $this->friendlyWarning( sprintf('Piggy bank repetition #%d has %s with value "%s", this has been corrected to "%s".', $item->id, $field, $value, $correct) ); @@ -447,22 +448,21 @@ class ForcesDecimalSize extends Command $regularExpression = $this->regularExpression; /** @var Builder $query */ - $query = PiggyBank::leftJoin('accounts', 'piggy_banks.account_id', '=', 'accounts.id') - ->leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id') - ->where('account_meta.name', 'currency_id') - ->where('account_meta.data', json_encode((string) $currency->id)) - ->where(static function (Builder $q) use ($fields, $currency, $operator, $cast, $regularExpression): void { - foreach ($fields as $field) { - $q->orWhere( - DB::raw(sprintf('CAST(piggy_banks.%s AS %s)', $field, $cast)), - $operator, - DB::raw(sprintf($regularExpression, $currency->decimal_places)) - ); - } - }) - ; + $query = PiggyBank::leftJoin('accounts', 'piggy_banks.account_id', '=', 'accounts.id') + ->leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id') + ->where('account_meta.name', 'currency_id') + ->where('account_meta.data', json_encode((string)$currency->id)) + ->where(static function (Builder $q) use ($fields, $currency, $operator, $cast, $regularExpression): void { + foreach ($fields as $field) { + $q->orWhere( + DB::raw(sprintf('CAST(piggy_banks.%s AS %s)', $field, $cast)), + $operator, + DB::raw(sprintf($regularExpression, $currency->decimal_places)) + ); + } + }); - $result = $query->get(['piggy_banks.*']); + $result = $query->get(['piggy_banks.*']); if (0 === $result->count()) { $this->friendlyPositive(sprintf('All piggy banks in %s are OK', $currency->code)); @@ -473,13 +473,13 @@ class ForcesDecimalSize extends Command foreach ($result as $item) { /** @var string $field */ foreach ($fields as $field) { - $value = $item->{$field}; + $value = $item->{$field}; if (null === $value) { continue; } // fix $field by rounding it down correctly. - $pow = 10 ** $currency->decimal_places; - $correct = bcdiv((string) round($value * $pow), (string) $pow, 12); + $pow = 10 ** $currency->decimal_places; + $correct = bcdiv((string)round($value * $pow), (string)$pow, 12); $this->friendlyWarning(sprintf('Piggy bank #%d has %s with value "%s", this has been corrected to "%s".', $item->id, $field, $value, $correct)); /** @var null|PiggyBank $piggyBank */ @@ -496,7 +496,7 @@ class ForcesDecimalSize extends Command { // select all transactions with this currency and issue. /** @var Builder $query */ - $query = Transaction::where('transaction_currency_id', $currency->id)->where( + $query = Transaction::where('transaction_currency_id', $currency->id)->where( DB::raw(sprintf('CAST(amount as %s)', $this->cast)), $this->operator, DB::raw(sprintf($this->regularExpression, $currency->decimal_places)) @@ -509,13 +509,13 @@ class ForcesDecimalSize extends Command /** @var Transaction $item */ foreach ($result as $item) { - $value = $item->amount; + $value = $item->amount; if ('' === $value) { continue; } // fix $field by rounding it down correctly. - $pow = 10.0 ** $currency->decimal_places; - $correct = bcdiv((string) round((float) $value * $pow), (string) $pow, 12); + $pow = 10.0 ** $currency->decimal_places; + $correct = bcdiv((string)round((float)$value * $pow), (string)$pow, 12); $this->friendlyWarning(sprintf('Transaction #%d has amount with value "%s", this has been corrected to "%s".', $item->id, $value, $correct)); /** @var null|Transaction $transaction */ @@ -525,7 +525,7 @@ class ForcesDecimalSize extends Command // select all transactions with this FOREIGN currency and issue. /** @var Builder $query */ - $query = Transaction::where('foreign_currency_id', $currency->id)->where( + $query = Transaction::where('foreign_currency_id', $currency->id)->where( DB::raw(sprintf('CAST(foreign_amount as %s)', $this->cast)), $this->operator, DB::raw(sprintf($this->regularExpression, $currency->decimal_places)) @@ -540,13 +540,13 @@ class ForcesDecimalSize extends Command /** @var Transaction $item */ foreach ($result as $item) { - $value = $item->foreign_amount; + $value = $item->foreign_amount; if (null === $value) { continue; } // fix $field by rounding it down correctly. - $pow = 10.0 ** $currency->decimal_places; - $correct = bcdiv((string) round((float) $value * $pow), (string) $pow, 12); + $pow = 10.0 ** $currency->decimal_places; + $correct = bcdiv((string)round((float)$value * $pow), (string)$pow, 12); $this->friendlyWarning( sprintf('Transaction #%d has foreign amount with value "%s", this has been corrected to "%s".', $item->id, $value, $correct) ); @@ -560,7 +560,7 @@ class ForcesDecimalSize extends Command private function updateDecimals(): void { $this->friendlyInfo('Going to force the size of DECIMAL columns. Please hold.'); - $type = (string) config('database.default'); + $type = (string)config('database.default'); /** * @var string $name From 521a496c179c15bf9835fd86b75eb546a47b8843 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sun, 23 Nov 2025 21:03:53 +0100 Subject: [PATCH 11/26] Fix #11267 --- app/TransactionRules/Actions/AddTag.php | 14 +++++++++----- changelog.md | 1 + 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/app/TransactionRules/Actions/AddTag.php b/app/TransactionRules/Actions/AddTag.php index d5e25c8be9..c7bcea80ee 100644 --- a/app/TransactionRules/Actions/AddTag.php +++ b/app/TransactionRules/Actions/AddTag.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Actions; +use FireflyIII\Enums\TransactionTypeEnum; use Illuminate\Support\Facades\Log; use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; use FireflyIII\Events\TriggeredAuditLog; @@ -54,6 +55,13 @@ class AddTag implements ActionInterface $tagName = $this->action->getValue($journal); $tag = $factory->findOrCreate($tagName); + $type = $journal['transaction_type_type']; + if(TransactionTypeEnum::OPENING_BALANCE->value === $type || TransactionTypeEnum::LIABILITY_CREDIT->value === $type || TransactionTypeEnum::INVALID->value === $type) { + // fail silently on invalid transaction types. + + return false; + } + if (null === $tag) { // could not find, could not create tag. event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.find_or_create_tag_failed', ['tag' => $tagName]))); @@ -61,11 +69,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(['tag_id' => $tag->id, 'transaction_journal_id' => $journal['transaction_journal_id']]); diff --git a/changelog.md b/changelog.md index 821ec7980c..bd45a2ec20 100644 --- a/changelog.md +++ b/changelog.md @@ -8,6 +8,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - [Discussion 11211](https://github.com/orgs/firefly-iii/discussions/11211) (question about Transaction journal ID) started by @zhiiwg +- #11267 ### API From 373e5c37334982a6cc81ecf17f1b7195d48546d8 Mon Sep 17 00:00:00 2001 From: JC5 Date: Mon, 24 Nov 2025 04:34:17 +0100 Subject: [PATCH 12/26] =?UTF-8?q?=F0=9F=A4=96=20Auto=20commit=20for=20rele?= =?UTF-8?q?ase=20'develop'=20on=202025-11-24?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .ci/php-cs-fixer/composer.lock | 66 ++++----- changelog.md | 4 +- composer.lock | 205 ++++++++++++++-------------- config/firefly.php | 4 +- package-lock.json | 236 ++++++++++++++++----------------- 5 files changed, 262 insertions(+), 253 deletions(-) diff --git a/.ci/php-cs-fixer/composer.lock b/.ci/php-cs-fixer/composer.lock index fb6175e67d..83bfb70f78 100644 --- a/.ci/php-cs-fixer/composer.lock +++ b/.ci/php-cs-fixer/composer.lock @@ -402,16 +402,16 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.89.2", + "version": "v3.90.0", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "7569658f91e475ec93b99bd5964b059ad1336dcf" + "reference": "ad732c2e9299c9743f9c55ae53cc0e7642ab1155" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/7569658f91e475ec93b99bd5964b059ad1336dcf", - "reference": "7569658f91e475ec93b99bd5964b059ad1336dcf", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/ad732c2e9299c9743f9c55ae53cc0e7642ab1155", + "reference": "ad732c2e9299c9743f9c55ae53cc0e7642ab1155", "shasum": "" }, "require": { @@ -429,17 +429,17 @@ "react/socket": "^1.16", "react/stream": "^1.4", "sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0", - "symfony/console": "^5.4.47 || ^6.4.24 || ^7.0", - "symfony/event-dispatcher": "^5.4.45 || ^6.4.24 || ^7.0", - "symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.0", - "symfony/finder": "^5.4.45 || ^6.4.24 || ^7.0", - "symfony/options-resolver": "^5.4.45 || ^6.4.24 || ^7.0", + "symfony/console": "^5.4.47 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/event-dispatcher": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/finder": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/options-resolver": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", "symfony/polyfill-mbstring": "^1.33", "symfony/polyfill-php80": "^1.33", "symfony/polyfill-php81": "^1.33", "symfony/polyfill-php84": "^1.33", - "symfony/process": "^5.4.47 || ^6.4.24 || ^7.2", - "symfony/stopwatch": "^5.4.45 || ^6.4.24 || ^7.0" + "symfony/process": "^5.4.47 || ^6.4.24 || ^7.2 || ^8.0", + "symfony/stopwatch": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0" }, "require-dev": { "facile-it/paraunit": "^1.3.1 || ^2.7", @@ -451,8 +451,8 @@ "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6", "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6", "phpunit/phpunit": "^9.6.25 || ^10.5.53 || ^11.5.34", - "symfony/var-dumper": "^5.4.48 || ^6.4.24 || ^7.3.2", - "symfony/yaml": "^5.4.45 || ^6.4.24 || ^7.3.2" + "symfony/var-dumper": "^5.4.48 || ^6.4.24 || ^7.3.2 || ^8.0", + "symfony/yaml": "^5.4.45 || ^6.4.24 || ^7.3.2 || ^8.0" }, "suggest": { "ext-dom": "For handling output formats in XML", @@ -493,7 +493,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.89.2" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.90.0" }, "funding": [ { @@ -501,7 +501,7 @@ "type": "github" } ], - "time": "2025-11-06T21:12:50+00:00" + "time": "2025-11-20T15:15:16+00:00" }, { "name": "psr/container", @@ -805,16 +805,16 @@ }, { "name": "react/dns", - "version": "v1.13.0", + "version": "v1.14.0", "source": { "type": "git", "url": "https://github.com/reactphp/dns.git", - "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5" + "reference": "7562c05391f42701c1fccf189c8225fece1cd7c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/dns/zipball/eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", - "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", + "url": "https://api.github.com/repos/reactphp/dns/zipball/7562c05391f42701c1fccf189c8225fece1cd7c3", + "reference": "7562c05391f42701c1fccf189c8225fece1cd7c3", "shasum": "" }, "require": { @@ -869,7 +869,7 @@ ], "support": { "issues": "https://github.com/reactphp/dns/issues", - "source": "https://github.com/reactphp/dns/tree/v1.13.0" + "source": "https://github.com/reactphp/dns/tree/v1.14.0" }, "funding": [ { @@ -877,20 +877,20 @@ "type": "open_collective" } ], - "time": "2024-06-13T14:18:03+00:00" + "time": "2025-11-18T19:34:28+00:00" }, { "name": "react/event-loop", - "version": "v1.5.0", + "version": "v1.6.0", "source": { "type": "git", "url": "https://github.com/reactphp/event-loop.git", - "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354" + "reference": "ba276bda6083df7e0050fd9b33f66ad7a4ac747a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/event-loop/zipball/bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", - "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", + "url": "https://api.github.com/repos/reactphp/event-loop/zipball/ba276bda6083df7e0050fd9b33f66ad7a4ac747a", + "reference": "ba276bda6083df7e0050fd9b33f66ad7a4ac747a", "shasum": "" }, "require": { @@ -941,7 +941,7 @@ ], "support": { "issues": "https://github.com/reactphp/event-loop/issues", - "source": "https://github.com/reactphp/event-loop/tree/v1.5.0" + "source": "https://github.com/reactphp/event-loop/tree/v1.6.0" }, "funding": [ { @@ -949,7 +949,7 @@ "type": "open_collective" } ], - "time": "2023-11-13T13:48:05+00:00" + "time": "2025-11-17T20:46:25+00:00" }, { "name": "react/promise", @@ -1026,16 +1026,16 @@ }, { "name": "react/socket", - "version": "v1.16.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/reactphp/socket.git", - "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1" + "reference": "ef5b17b81f6f60504c539313f94f2d826c5faa08" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/socket/zipball/23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", - "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", + "url": "https://api.github.com/repos/reactphp/socket/zipball/ef5b17b81f6f60504c539313f94f2d826c5faa08", + "reference": "ef5b17b81f6f60504c539313f94f2d826c5faa08", "shasum": "" }, "require": { @@ -1094,7 +1094,7 @@ ], "support": { "issues": "https://github.com/reactphp/socket/issues", - "source": "https://github.com/reactphp/socket/tree/v1.16.0" + "source": "https://github.com/reactphp/socket/tree/v1.17.0" }, "funding": [ { @@ -1102,7 +1102,7 @@ "type": "open_collective" } ], - "time": "2024-07-26T10:38:09+00:00" + "time": "2025-11-19T20:47:34+00:00" }, { "name": "react/stream", diff --git a/changelog.md b/changelog.md index bd45a2ec20..cd8ade13b5 100644 --- a/changelog.md +++ b/changelog.md @@ -8,11 +8,11 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - [Discussion 11211](https://github.com/orgs/firefly-iii/discussions/11211) (question about Transaction journal ID) started by @zhiiwg -- #11267 +- [Issue 11267](https://github.com/firefly-iii/firefly-iii/issues/11267) (Tags can be added to elements that can't be removed) reported by @Fmstrat ### API -- #11265 +- [Issue 11265](https://github.com/firefly-iii/firefly-iii/issues/11265) (Inconsistent object type in exchange rates API) reported by @jfpedroza ## 6.4.8 - 2025-11-14 diff --git a/composer.lock b/composer.lock index bcb4727e5b..9ef7ac18d8 100644 --- a/composer.lock +++ b/composer.lock @@ -8,16 +8,16 @@ "packages": [ { "name": "bacon/bacon-qr-code", - "version": "v3.0.2", + "version": "v3.0.3", "source": { "type": "git", "url": "https://github.com/Bacon/BaconQrCode.git", - "reference": "fe259c55425b8178f77fb6d1f84ba2473e21ed55" + "reference": "36a1cb2b81493fa5b82e50bf8068bf84d1542563" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/fe259c55425b8178f77fb6d1f84ba2473e21ed55", - "reference": "fe259c55425b8178f77fb6d1f84ba2473e21ed55", + "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/36a1cb2b81493fa5b82e50bf8068bf84d1542563", + "reference": "36a1cb2b81493fa5b82e50bf8068bf84d1542563", "shasum": "" }, "require": { @@ -57,9 +57,9 @@ "homepage": "https://github.com/Bacon/BaconQrCode", "support": { "issues": "https://github.com/Bacon/BaconQrCode/issues", - "source": "https://github.com/Bacon/BaconQrCode/tree/v3.0.2" + "source": "https://github.com/Bacon/BaconQrCode/tree/v3.0.3" }, - "time": "2025-11-16T22:59:48+00:00" + "time": "2025-11-19T17:15:36+00:00" }, { "name": "beberlei/assert", @@ -1938,16 +1938,16 @@ }, { "name": "laravel/framework", - "version": "v12.38.1", + "version": "v12.39.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "7f3012af6059f5f64a12930701cd8caed6cf7c17" + "reference": "1a6176129ef28eaf42b6b4a6250025120c3d8dac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/7f3012af6059f5f64a12930701cd8caed6cf7c17", - "reference": "7f3012af6059f5f64a12930701cd8caed6cf7c17", + "url": "https://api.github.com/repos/laravel/framework/zipball/1a6176129ef28eaf42b6b4a6250025120c3d8dac", + "reference": "1a6176129ef28eaf42b6b4a6250025120c3d8dac", "shasum": "" }, "require": { @@ -2153,7 +2153,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-11-13T02:12:47+00:00" + "time": "2025-11-18T15:16:10+00:00" }, { "name": "laravel/passport", @@ -3362,33 +3362,38 @@ }, { "name": "league/uri", - "version": "7.5.1", + "version": "7.6.0", "source": { "type": "git", "url": "https://github.com/thephpleague/uri.git", - "reference": "81fb5145d2644324614cc532b28efd0215bda430" + "reference": "f625804987a0a9112d954f9209d91fec52182344" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri/zipball/81fb5145d2644324614cc532b28efd0215bda430", - "reference": "81fb5145d2644324614cc532b28efd0215bda430", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/f625804987a0a9112d954f9209d91fec52182344", + "reference": "f625804987a0a9112d954f9209d91fec52182344", "shasum": "" }, "require": { - "league/uri-interfaces": "^7.5", - "php": "^8.1" + "league/uri-interfaces": "^7.6", + "php": "^8.1", + "psr/http-factory": "^1" }, "conflict": { "league/uri-schemes": "^1.0" }, "suggest": { "ext-bcmath": "to improve IPV4 host parsing", + "ext-dom": "to convert the URI into an HTML anchor tag", "ext-fileinfo": "to create Data URI from file contennts", "ext-gmp": "to improve IPV4 host parsing", "ext-intl": "to handle IDN host with the best performance", + "ext-uri": "to use the PHP native URI class", "jeremykendall/php-domain-parser": "to resolve Public Suffix and Top Level Domain", "league/uri-components": "Needed to easily manipulate URI objects components", + "league/uri-polyfill": "Needed to backport the PHP URI extension for older versions of PHP", "php-64bit": "to improve IPV4 host parsing", + "rowbot/url": "to handle WHATWG URL", "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" }, "type": "library", @@ -3416,6 +3421,7 @@ "description": "URI manipulation library", "homepage": "https://uri.thephpleague.com", "keywords": [ + "URN", "data-uri", "file-uri", "ftp", @@ -3428,9 +3434,11 @@ "psr-7", "query-string", "querystring", + "rfc2141", "rfc3986", "rfc3987", "rfc6570", + "rfc8141", "uri", "uri-template", "url", @@ -3440,7 +3448,7 @@ "docs": "https://uri.thephpleague.com", "forum": "https://thephpleague.slack.com", "issues": "https://github.com/thephpleague/uri-src/issues", - "source": "https://github.com/thephpleague/uri/tree/7.5.1" + "source": "https://github.com/thephpleague/uri/tree/7.6.0" }, "funding": [ { @@ -3448,26 +3456,25 @@ "type": "github" } ], - "time": "2024-12-08T08:40:02+00:00" + "time": "2025-11-18T12:17:23+00:00" }, { "name": "league/uri-interfaces", - "version": "7.5.0", + "version": "7.6.0", "source": { "type": "git", "url": "https://github.com/thephpleague/uri-interfaces.git", - "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742" + "reference": "ccbfb51c0445298e7e0b7f4481b942f589665368" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", - "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", + "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/ccbfb51c0445298e7e0b7f4481b942f589665368", + "reference": "ccbfb51c0445298e7e0b7f4481b942f589665368", "shasum": "" }, "require": { "ext-filter": "*", "php": "^8.1", - "psr/http-factory": "^1", "psr/http-message": "^1.1 || ^2.0" }, "suggest": { @@ -3475,6 +3482,7 @@ "ext-gmp": "to improve IPV4 host parsing", "ext-intl": "to handle IDN host with the best performance", "php-64bit": "to improve IPV4 host parsing", + "rowbot/url": "to handle WHATWG URL", "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" }, "type": "library", @@ -3499,7 +3507,7 @@ "homepage": "https://nyamsprod.com" } ], - "description": "Common interfaces and classes for URI representation and interaction", + "description": "Common tools for parsing and resolving RFC3987/RFC3986 URI", "homepage": "https://uri.thephpleague.com", "keywords": [ "data-uri", @@ -3524,7 +3532,7 @@ "docs": "https://uri.thephpleague.com", "forum": "https://thephpleague.slack.com", "issues": "https://github.com/thephpleague/uri-src/issues", - "source": "https://github.com/thephpleague/uri-interfaces/tree/7.5.0" + "source": "https://github.com/thephpleague/uri-interfaces/tree/7.6.0" }, "funding": [ { @@ -3532,26 +3540,26 @@ "type": "github" } ], - "time": "2024-12-08T08:18:47+00:00" + "time": "2025-11-18T12:17:23+00:00" }, { "name": "mailersend/laravel-driver", - "version": "v2.12.0", + "version": "v2.9.1", "source": { "type": "git", "url": "https://github.com/mailersend/mailersend-laravel-driver.git", - "reference": "15e1ec41e29e65d3ca226929c65804190aaa93eb" + "reference": "87fd5ab76808bbaac9221be0d306baef13e98725" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mailersend/mailersend-laravel-driver/zipball/15e1ec41e29e65d3ca226929c65804190aaa93eb", - "reference": "15e1ec41e29e65d3ca226929c65804190aaa93eb", + "url": "https://api.github.com/repos/mailersend/mailersend-laravel-driver/zipball/87fd5ab76808bbaac9221be0d306baef13e98725", + "reference": "87fd5ab76808bbaac9221be0d306baef13e98725", "shasum": "" }, "require": { "ext-json": "*", "illuminate/support": "^9.0 || ^10.0 || ^11.0 || ^12.0", - "mailersend/mailersend": "^0.35.0", + "mailersend/mailersend": "^0.31.0", "nyholm/psr7": "^1.5", "php": ">=8.0", "php-http/guzzle7-adapter": "^1.0", @@ -3599,28 +3607,29 @@ ], "support": { "issues": "https://github.com/mailersend/mailersend-laravel-driver/issues", - "source": "https://github.com/mailersend/mailersend-laravel-driver/tree/v2.12.0" + "source": "https://github.com/mailersend/mailersend-laravel-driver/tree/v2.9.1" }, - "time": "2025-10-28T14:59:16+00:00" + "time": "2025-04-09T09:33:07+00:00" }, { "name": "mailersend/mailersend", - "version": "v0.35.0", + "version": "v0.31.0", "source": { "type": "git", "url": "https://github.com/mailersend/mailersend-php.git", - "reference": "f1696cf9e727e9503fbc5882d2a111bd966ad276" + "reference": "513ff83ee768526055ad52987cde401ea7218c67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mailersend/mailersend-php/zipball/f1696cf9e727e9503fbc5882d2a111bd966ad276", - "reference": "f1696cf9e727e9503fbc5882d2a111bd966ad276", + "url": "https://api.github.com/repos/mailersend/mailersend-php/zipball/513ff83ee768526055ad52987cde401ea7218c67", + "reference": "513ff83ee768526055ad52987cde401ea7218c67", "shasum": "" }, "require": { "beberlei/assert": "^3.2", "ext-json": "*", - "php": "^7.4 || ^8.0 <8.5", + "illuminate/collections": "^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0", + "php": "^7.4|^8.0", "php-http/client-common": "^2.2", "php-http/discovery": "^1.9", "php-http/httplug": "^2.1", @@ -3665,9 +3674,9 @@ ], "support": { "issues": "https://github.com/mailersend/mailersend-php/issues", - "source": "https://github.com/mailersend/mailersend-php/tree/v0.35.0" + "source": "https://github.com/mailersend/mailersend-php/tree/v0.31.0" }, - "time": "2025-10-28T13:11:43+00:00" + "time": "2025-04-03T12:16:11+00:00" }, { "name": "monolog/monolog", @@ -3944,16 +3953,16 @@ }, { "name": "nette/utils", - "version": "v4.0.8", + "version": "v4.0.9", "source": { "type": "git", "url": "https://github.com/nette/utils.git", - "reference": "c930ca4e3cf4f17dcfb03037703679d2396d2ede" + "reference": "505a30ad386daa5211f08a318e47015b501cad30" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/c930ca4e3cf4f17dcfb03037703679d2396d2ede", - "reference": "c930ca4e3cf4f17dcfb03037703679d2396d2ede", + "url": "https://api.github.com/repos/nette/utils/zipball/505a30ad386daa5211f08a318e47015b501cad30", + "reference": "505a30ad386daa5211f08a318e47015b501cad30", "shasum": "" }, "require": { @@ -4027,22 +4036,22 @@ ], "support": { "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v4.0.8" + "source": "https://github.com/nette/utils/tree/v4.0.9" }, - "time": "2025-08-06T21:43:34+00:00" + "time": "2025-10-31T00:45:47+00:00" }, { "name": "nunomaduro/collision", - "version": "v8.8.2", + "version": "v8.8.3", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "60207965f9b7b7a4ce15a0f75d57f9dadb105bdb" + "reference": "1dc9e88d105699d0fee8bb18890f41b274f6b4c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/60207965f9b7b7a4ce15a0f75d57f9dadb105bdb", - "reference": "60207965f9b7b7a4ce15a0f75d57f9dadb105bdb", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/1dc9e88d105699d0fee8bb18890f41b274f6b4c4", + "reference": "1dc9e88d105699d0fee8bb18890f41b274f6b4c4", "shasum": "" }, "require": { @@ -4064,7 +4073,7 @@ "laravel/sanctum": "^4.1.1", "laravel/tinker": "^2.10.1", "orchestra/testbench-core": "^9.12.0 || ^10.4", - "pestphp/pest": "^3.8.2", + "pestphp/pest": "^3.8.2 || ^4.0.0", "sebastian/environment": "^7.2.1 || ^8.0" }, "type": "library", @@ -4128,35 +4137,35 @@ "type": "patreon" } ], - "time": "2025-06-25T02:12:12+00:00" + "time": "2025-11-20T02:55:25+00:00" }, { "name": "nunomaduro/termwind", - "version": "v2.3.2", + "version": "v2.3.3", "source": { "type": "git", "url": "https://github.com/nunomaduro/termwind.git", - "reference": "eb61920a53057a7debd718a5b89c2178032b52c0" + "reference": "6fb2a640ff502caace8e05fd7be3b503a7e1c017" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/eb61920a53057a7debd718a5b89c2178032b52c0", - "reference": "eb61920a53057a7debd718a5b89c2178032b52c0", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/6fb2a640ff502caace8e05fd7be3b503a7e1c017", + "reference": "6fb2a640ff502caace8e05fd7be3b503a7e1c017", "shasum": "" }, "require": { "ext-mbstring": "*", "php": "^8.2", - "symfony/console": "^7.3.4" + "symfony/console": "^7.3.6" }, "require-dev": { "illuminate/console": "^11.46.1", "laravel/pint": "^1.25.1", "mockery/mockery": "^1.6.12", - "pestphp/pest": "^2.36.0 || ^3.8.4", + "pestphp/pest": "^2.36.0 || ^3.8.4 || ^4.1.3", "phpstan/phpstan": "^1.12.32", "phpstan/phpstan-strict-rules": "^1.6.2", - "symfony/var-dumper": "^7.3.4", + "symfony/var-dumper": "^7.3.5", "thecodingmachine/phpstan-strict-rules": "^1.0.0" }, "type": "library", @@ -4199,7 +4208,7 @@ ], "support": { "issues": "https://github.com/nunomaduro/termwind/issues", - "source": "https://github.com/nunomaduro/termwind/tree/v2.3.2" + "source": "https://github.com/nunomaduro/termwind/tree/v2.3.3" }, "funding": [ { @@ -4215,7 +4224,7 @@ "type": "github" } ], - "time": "2025-10-18T11:10:27+00:00" + "time": "2025-11-20T02:34:59+00:00" }, { "name": "nyholm/psr7", @@ -10307,24 +10316,24 @@ "packages-dev": [ { "name": "barryvdh/laravel-debugbar", - "version": "v3.16.0", + "version": "v3.16.1", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-debugbar.git", - "reference": "f265cf5e38577d42311f1a90d619bcd3740bea23" + "reference": "21b2c6fce05453efd4bceb34f9fddaa1cdb44090" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/f265cf5e38577d42311f1a90d619bcd3740bea23", - "reference": "f265cf5e38577d42311f1a90d619bcd3740bea23", + "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/21b2c6fce05453efd4bceb34f9fddaa1cdb44090", + "reference": "21b2c6fce05453efd4bceb34f9fddaa1cdb44090", "shasum": "" }, "require": { - "illuminate/routing": "^9|^10|^11|^12", - "illuminate/session": "^9|^10|^11|^12", - "illuminate/support": "^9|^10|^11|^12", + "illuminate/routing": "^10|^11|^12", + "illuminate/session": "^10|^11|^12", + "illuminate/support": "^10|^11|^12", "php": "^8.1", - "php-debugbar/php-debugbar": "~2.2.0", + "php-debugbar/php-debugbar": "^2.2.4", "symfony/finder": "^6|^7" }, "require-dev": { @@ -10376,7 +10385,7 @@ ], "support": { "issues": "https://github.com/barryvdh/laravel-debugbar/issues", - "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.16.0" + "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.16.1" }, "funding": [ { @@ -10388,7 +10397,7 @@ "type": "github" } ], - "time": "2025-07-14T11:56:43+00:00" + "time": "2025-11-19T08:31:25+00:00" }, { "name": "barryvdh/laravel-ide-helper", @@ -10596,22 +10605,22 @@ }, { "name": "composer/class-map-generator", - "version": "1.6.2", + "version": "1.7.0", "source": { "type": "git", "url": "https://github.com/composer/class-map-generator.git", - "reference": "ba9f089655d4cdd64e762a6044f411ccdaec0076" + "reference": "2373419b7709815ed323ebf18c3c72d03ff4a8a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/class-map-generator/zipball/ba9f089655d4cdd64e762a6044f411ccdaec0076", - "reference": "ba9f089655d4cdd64e762a6044f411ccdaec0076", + "url": "https://api.github.com/repos/composer/class-map-generator/zipball/2373419b7709815ed323ebf18c3c72d03ff4a8a6", + "reference": "2373419b7709815ed323ebf18c3c72d03ff4a8a6", "shasum": "" }, "require": { "composer/pcre": "^2.1 || ^3.1", "php": "^7.2 || ^8.0", - "symfony/finder": "^4.4 || ^5.3 || ^6 || ^7" + "symfony/finder": "^4.4 || ^5.3 || ^6 || ^7 || ^8" }, "require-dev": { "phpstan/phpstan": "^1.12 || ^2", @@ -10619,7 +10628,7 @@ "phpstan/phpstan-phpunit": "^1 || ^2", "phpstan/phpstan-strict-rules": "^1.1 || ^2", "phpunit/phpunit": "^8", - "symfony/filesystem": "^5.4 || ^6" + "symfony/filesystem": "^5.4 || ^6 || ^7 || ^8" }, "type": "library", "extra": { @@ -10649,7 +10658,7 @@ ], "support": { "issues": "https://github.com/composer/class-map-generator/issues", - "source": "https://github.com/composer/class-map-generator/tree/1.6.2" + "source": "https://github.com/composer/class-map-generator/tree/1.7.0" }, "funding": [ { @@ -10661,7 +10670,7 @@ "type": "github" } ], - "time": "2025-08-20T18:52:43+00:00" + "time": "2025-11-19T10:41:15+00:00" }, { "name": "composer/pcre", @@ -12012,16 +12021,16 @@ }, { "name": "phpunit/phpunit", - "version": "12.4.3", + "version": "12.4.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "d8f644d8d9bb904867f7a0aeb1bd306e0d966949" + "reference": "9253ec75a672e39fcc9d85bdb61448215b8162c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d8f644d8d9bb904867f7a0aeb1bd306e0d966949", - "reference": "d8f644d8d9bb904867f7a0aeb1bd306e0d966949", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9253ec75a672e39fcc9d85bdb61448215b8162c7", + "reference": "9253ec75a672e39fcc9d85bdb61448215b8162c7", "shasum": "" }, "require": { @@ -12089,7 +12098,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/12.4.3" + "source": "https://github.com/sebastianbergmann/phpunit/tree/12.4.4" }, "funding": [ { @@ -12113,7 +12122,7 @@ "type": "tidelift" } ], - "time": "2025-11-13T07:20:26+00:00" + "time": "2025-11-21T07:39:11+00:00" }, { "name": "rector/rector", @@ -13126,16 +13135,16 @@ }, { "name": "thecodingmachine/phpstan-safe-rule", - "version": "v1.4.1", + "version": "v1.4.3", "source": { "type": "git", "url": "https://github.com/thecodingmachine/phpstan-safe-rule.git", - "reference": "5f9795eae8891dffa475965463a4281633651768" + "reference": "5c804889253ce9498ef185e108e9f94b6023208e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thecodingmachine/phpstan-safe-rule/zipball/5f9795eae8891dffa475965463a4281633651768", - "reference": "5f9795eae8891dffa475965463a4281633651768", + "url": "https://api.github.com/repos/thecodingmachine/phpstan-safe-rule/zipball/5c804889253ce9498ef185e108e9f94b6023208e", + "reference": "5c804889253ce9498ef185e108e9f94b6023208e", "shasum": "" }, "require": { @@ -13178,22 +13187,22 @@ "description": "A PHPStan rule to detect safety issues. Must be used in conjunction with thecodingmachine/safe", "support": { "issues": "https://github.com/thecodingmachine/phpstan-safe-rule/issues", - "source": "https://github.com/thecodingmachine/phpstan-safe-rule/tree/v1.4.1" + "source": "https://github.com/thecodingmachine/phpstan-safe-rule/tree/v1.4.3" }, - "time": "2025-04-09T20:30:35+00:00" + "time": "2025-11-21T09:41:49+00:00" }, { "name": "theseer/tokenizer", - "version": "1.3.0", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "d74205c497bfbca49f34d4bc4c19c17e22db4ebb" + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/d74205c497bfbca49f34d4bc4c19c17e22db4ebb", - "reference": "d74205c497bfbca49f34d4bc4c19c17e22db4ebb", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c", + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c", "shasum": "" }, "require": { @@ -13222,7 +13231,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.3.0" + "source": "https://github.com/theseer/tokenizer/tree/1.3.1" }, "funding": [ { @@ -13230,7 +13239,7 @@ "type": "github" } ], - "time": "2025-11-13T13:44:09+00:00" + "time": "2025-11-17T20:03:58+00:00" }, { "name": "webmozart/assert", diff --git a/config/firefly.php b/config/firefly.php index cc11a74b7f..a8151ad390 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -78,8 +78,8 @@ return [ 'running_balance_column' => env('USE_RUNNING_BALANCE', false), // see cer.php for exchange rates feature flag. ], - 'version' => 'develop/2025-11-17', - 'build_time' => 1763402780, +'version' => 'develop/2025-11-24', +'build_time' => 1763955176, 'api_version' => '2.1.0', // field is no longer used. 'db_version' => 28, // field is no longer used. diff --git a/package-lock.json b/package-lock.json index cdadcc353f..42c12bdcad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2589,9 +2589,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.2.tgz", - "integrity": "sha512-yDPzwsgiFO26RJA4nZo8I+xqzh7sJTZIWQOxn+/XOdPE31lAvLIYCKqjV+lNH/vxE2L2iH3plKxDCRK6i+CwhA==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", + "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==", "cpu": [ "arm" ], @@ -2603,9 +2603,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.2.tgz", - "integrity": "sha512-k8FontTxIE7b0/OGKeSN5B6j25EuppBcWM33Z19JoVT7UTXFSo3D9CdU39wGTeb29NO3XxpMNauh09B+Ibw+9g==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz", + "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==", "cpu": [ "arm64" ], @@ -2617,9 +2617,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.2.tgz", - "integrity": "sha512-A6s4gJpomNBtJ2yioj8bflM2oogDwzUiMl2yNJ2v9E7++sHrSrsQ29fOfn5DM/iCzpWcebNYEdXpaK4tr2RhfQ==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz", + "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==", "cpu": [ "arm64" ], @@ -2631,9 +2631,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.2.tgz", - "integrity": "sha512-e6XqVmXlHrBlG56obu9gDRPW3O3hLxpwHpLsBJvuI8qqnsrtSZ9ERoWUXtPOkY8c78WghyPHZdmPhHLWNdAGEw==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz", + "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==", "cpu": [ "x64" ], @@ -2645,9 +2645,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.2.tgz", - "integrity": "sha512-v0E9lJW8VsrwPux5Qe5CwmH/CF/2mQs6xU1MF3nmUxmZUCHazCjLgYvToOk+YuuUqLQBio1qkkREhxhc656ViA==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz", + "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==", "cpu": [ "arm64" ], @@ -2659,9 +2659,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.2.tgz", - "integrity": "sha512-ClAmAPx3ZCHtp6ysl4XEhWU69GUB1D+s7G9YjHGhIGCSrsg00nEGRRZHmINYxkdoJehde8VIsDC5t9C0gb6yqA==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz", + "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==", "cpu": [ "x64" ], @@ -2673,9 +2673,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.2.tgz", - "integrity": "sha512-EPlb95nUsz6Dd9Qy13fI5kUPXNSljaG9FiJ4YUGU1O/Q77i5DYFW5KR8g1OzTcdZUqQQ1KdDqsTohdFVwCwjqg==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz", + "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==", "cpu": [ "arm" ], @@ -2687,9 +2687,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.2.tgz", - "integrity": "sha512-BOmnVW+khAUX+YZvNfa0tGTEMVVEerOxN0pDk2E6N6DsEIa2Ctj48FOMfNDdrwinocKaC7YXUZ1pHlKpnkja/Q==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz", + "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==", "cpu": [ "arm" ], @@ -2701,9 +2701,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.2.tgz", - "integrity": "sha512-Xt2byDZ+6OVNuREgBXr4+CZDJtrVso5woFtpKdGPhpTPHcNG7D8YXeQzpNbFRxzTVqJf7kvPMCub/pcGUWgBjA==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz", + "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==", "cpu": [ "arm64" ], @@ -2715,9 +2715,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.2.tgz", - "integrity": "sha512-+LdZSldy/I9N8+klim/Y1HsKbJ3BbInHav5qE9Iy77dtHC/pibw1SR/fXlWyAk0ThnpRKoODwnAuSjqxFRDHUQ==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz", + "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==", "cpu": [ "arm64" ], @@ -2729,9 +2729,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.2.tgz", - "integrity": "sha512-8ms8sjmyc1jWJS6WdNSA23rEfdjWB30LH8Wqj0Cqvv7qSHnvw6kgMMXRdop6hkmGPlyYBdRPkjJnj3KCUHV/uQ==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz", + "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==", "cpu": [ "loong64" ], @@ -2743,9 +2743,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.2.tgz", - "integrity": "sha512-3HRQLUQbpBDMmzoxPJYd3W6vrVHOo2cVW8RUo87Xz0JPJcBLBr5kZ1pGcQAhdZgX9VV7NbGNipah1omKKe23/g==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz", + "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==", "cpu": [ "ppc64" ], @@ -2757,9 +2757,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.2.tgz", - "integrity": "sha512-fMjKi+ojnmIvhk34gZP94vjogXNNUKMEYs+EDaB/5TG/wUkoeua7p7VCHnE6T2Tx+iaghAqQX8teQzcvrYpaQA==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz", + "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==", "cpu": [ "riscv64" ], @@ -2771,9 +2771,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.2.tgz", - "integrity": "sha512-XuGFGU+VwUUV5kLvoAdi0Wz5Xbh2SrjIxCtZj6Wq8MDp4bflb/+ThZsVxokM7n0pcbkEr2h5/pzqzDYI7cCgLQ==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz", + "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==", "cpu": [ "riscv64" ], @@ -2785,9 +2785,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.2.tgz", - "integrity": "sha512-w6yjZF0P+NGzWR3AXWX9zc0DNEGdtvykB03uhonSHMRa+oWA6novflo2WaJr6JZakG2ucsyb+rvhrKac6NIy+w==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz", + "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==", "cpu": [ "s390x" ], @@ -2799,9 +2799,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.2.tgz", - "integrity": "sha512-yo8d6tdfdeBArzC7T/PnHd7OypfI9cbuZzPnzLJIyKYFhAQ8SvlkKtKBMbXDxe1h03Rcr7u++nFS7tqXz87Gtw==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz", + "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", "cpu": [ "x64" ], @@ -2813,9 +2813,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.2.tgz", - "integrity": "sha512-ah59c1YkCxKExPP8O9PwOvs+XRLKwh/mV+3YdKqQ5AMQ0r4M4ZDuOrpWkUaqO7fzAHdINzV9tEVu8vNw48z0lA==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz", + "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==", "cpu": [ "x64" ], @@ -2827,9 +2827,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.2.tgz", - "integrity": "sha512-4VEd19Wmhr+Zy7hbUsFZ6YXEiP48hE//KPLCSVNY5RMGX2/7HZ+QkN55a3atM1C/BZCGIgqN+xrVgtdak2S9+A==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz", + "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==", "cpu": [ "arm64" ], @@ -2841,9 +2841,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.2.tgz", - "integrity": "sha512-IlbHFYc/pQCgew/d5fslcy1KEaYVCJ44G8pajugd8VoOEI8ODhtb/j8XMhLpwHCMB3yk2J07ctup10gpw2nyMA==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz", + "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==", "cpu": [ "arm64" ], @@ -2855,9 +2855,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.2.tgz", - "integrity": "sha512-lNlPEGgdUfSzdCWU176ku/dQRnA7W+Gp8d+cWv73jYrb8uT7HTVVxq62DUYxjbaByuf1Yk0RIIAbDzp+CnOTFg==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz", + "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==", "cpu": [ "ia32" ], @@ -2869,9 +2869,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.2.tgz", - "integrity": "sha512-S6YojNVrHybQis2lYov1sd+uj7K0Q05NxHcGktuMMdIQ2VixGwAfbJ23NnlvvVV1bdpR2m5MsNBViHJKcA4ADw==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz", + "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==", "cpu": [ "x64" ], @@ -2883,9 +2883,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.2.tgz", - "integrity": "sha512-k+/Rkcyx//P6fetPoLMb8pBeqJBNGx81uuf7iljX9++yNBVRDQgD04L+SVXmXmh5ZP4/WOp4mWF0kmi06PW2tA==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz", + "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==", "cpu": [ "x64" ], @@ -4075,9 +4075,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.29.tgz", - "integrity": "sha512-sXdt2elaVnhpDNRDz+1BDx1JQoJRuNk7oVlAlbGiFkLikHCAQiccexF/9e91zVi6RCgqspl04aP+6Cnl9zRLrA==", + "version": "2.8.31", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.31.tgz", + "integrity": "sha512-a28v2eWrrRWPpJSzxc+mKwm0ZtVx/G8SepdQZDArnXYU/XS+IF6mp8aB/4E+hH1tyGCoDo3KlUCdlSxGDsRkAw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -4521,9 +4521,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001755", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001755.tgz", - "integrity": "sha512-44V+Jm6ctPj7R52Na4TLi3Zri4dWUljJd+RDm+j8LtNCc/ihLCT+X1TzoOAkRETEWqjuLnh9581Tl80FvK7jVA==", + "version": "1.0.30001756", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001756.tgz", + "integrity": "sha512-4HnCNKbMLkLdhJz3TToeVWHSnfJvPaq6vu/eRP0Ahub/07n484XHhBF5AJoSGHdVrS8tKFauUQz8Bp9P7LVx7A==", "dev": true, "funding": [ { @@ -4966,13 +4966,13 @@ "license": "MIT" }, "node_modules/core-js-compat": { - "version": "3.46.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.46.0.tgz", - "integrity": "sha512-p9hObIIEENxSV8xIu+V68JjSeARg6UVMG5mR+JEUguG3sI6MsiS1njz2jHmyJDvA+8jX/sytkBHup6kxhM9law==", + "version": "3.47.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.47.0.tgz", + "integrity": "sha512-IGfuznZ/n7Kp9+nypamBhvwdwLsW6KC8IOaURw2doAK5e98AG3acVLdh0woOnEqCfUtS+Vu882JE4k/DAm3ItQ==", "dev": true, "license": "MIT", "dependencies": { - "browserslist": "^4.26.3" + "browserslist": "^4.28.0" }, "funding": { "type": "opencollective", @@ -5736,9 +5736,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.254", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.254.tgz", - "integrity": "sha512-DcUsWpVhv9svsKRxnSCZ86SjD+sp32SGidNB37KpqXJncp1mfUgKbHvBomE89WJDbfVKw1mdv5+ikrvd43r+Bg==", + "version": "1.5.259", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.259.tgz", + "integrity": "sha512-I+oLXgpEJzD6Cwuwt1gYjxsDmu/S/Kd41mmLA3O+/uH2pFRO/DvOjUyGozL8j3KeLV6WyZ7ssPwELMsXCcsJAQ==", "dev": true, "license": "ISC" }, @@ -7088,9 +7088,9 @@ } }, "node_modules/i18next": { - "version": "25.6.2", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.6.2.tgz", - "integrity": "sha512-0GawNyVUw0yvJoOEBq1VHMAsqdM23XrHkMtl2gKEjviJQSLVXsrPqsoYAxBEugW5AB96I2pZkwRxyl8WZVoWdw==", + "version": "25.6.3", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.6.3.tgz", + "integrity": "sha512-AEQvoPDljhp67a1+NsnG/Wb1Nh6YoSvtrmeEd24sfGn3uujCtXCF3cXpr7ulhMywKNFF7p3TX1u2j7y+caLOJg==", "funding": [ { "type": "individual", @@ -7107,7 +7107,7 @@ ], "license": "MIT", "dependencies": { - "@babel/runtime": "^7.27.6" + "@babel/runtime": "^7.28.4" }, "peerDependencies": { "typescript": "^5" @@ -10110,9 +10110,9 @@ } }, "node_modules/rollup": { - "version": "4.53.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.2.tgz", - "integrity": "sha512-MHngMYwGJVi6Fmnk6ISmnk7JAHRNF0UkuucA0CUW3N3a4KnONPEZz+vUanQP/ZC/iY1Qkf3bwPWzyY84wEks1g==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", + "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", "dev": true, "license": "MIT", "dependencies": { @@ -10126,28 +10126,28 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.53.2", - "@rollup/rollup-android-arm64": "4.53.2", - "@rollup/rollup-darwin-arm64": "4.53.2", - "@rollup/rollup-darwin-x64": "4.53.2", - "@rollup/rollup-freebsd-arm64": "4.53.2", - "@rollup/rollup-freebsd-x64": "4.53.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.53.2", - "@rollup/rollup-linux-arm-musleabihf": "4.53.2", - "@rollup/rollup-linux-arm64-gnu": "4.53.2", - "@rollup/rollup-linux-arm64-musl": "4.53.2", - "@rollup/rollup-linux-loong64-gnu": "4.53.2", - "@rollup/rollup-linux-ppc64-gnu": "4.53.2", - "@rollup/rollup-linux-riscv64-gnu": "4.53.2", - "@rollup/rollup-linux-riscv64-musl": "4.53.2", - "@rollup/rollup-linux-s390x-gnu": "4.53.2", - "@rollup/rollup-linux-x64-gnu": "4.53.2", - "@rollup/rollup-linux-x64-musl": "4.53.2", - "@rollup/rollup-openharmony-arm64": "4.53.2", - "@rollup/rollup-win32-arm64-msvc": "4.53.2", - "@rollup/rollup-win32-ia32-msvc": "4.53.2", - "@rollup/rollup-win32-x64-gnu": "4.53.2", - "@rollup/rollup-win32-x64-msvc": "4.53.2", + "@rollup/rollup-android-arm-eabi": "4.53.3", + "@rollup/rollup-android-arm64": "4.53.3", + "@rollup/rollup-darwin-arm64": "4.53.3", + "@rollup/rollup-darwin-x64": "4.53.3", + "@rollup/rollup-freebsd-arm64": "4.53.3", + "@rollup/rollup-freebsd-x64": "4.53.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", + "@rollup/rollup-linux-arm-musleabihf": "4.53.3", + "@rollup/rollup-linux-arm64-gnu": "4.53.3", + "@rollup/rollup-linux-arm64-musl": "4.53.3", + "@rollup/rollup-linux-loong64-gnu": "4.53.3", + "@rollup/rollup-linux-ppc64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-musl": "4.53.3", + "@rollup/rollup-linux-s390x-gnu": "4.53.3", + "@rollup/rollup-linux-x64-gnu": "4.53.3", + "@rollup/rollup-linux-x64-musl": "4.53.3", + "@rollup/rollup-openharmony-arm64": "4.53.3", + "@rollup/rollup-win32-arm64-msvc": "4.53.3", + "@rollup/rollup-win32-ia32-msvc": "4.53.3", + "@rollup/rollup-win32-x64-gnu": "4.53.3", + "@rollup/rollup-win32-x64-msvc": "4.53.3", "fsevents": "~2.3.2" } }, @@ -10203,9 +10203,9 @@ "license": "MIT" }, "node_modules/sass": { - "version": "1.94.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.94.0.tgz", - "integrity": "sha512-Dqh7SiYcaFtdv5Wvku6QgS5IGPm281L+ZtVD1U2FJa7Q0EFRlq8Z3sjYtz6gYObsYThUOz9ArwFqPZx+1azILQ==", + "version": "1.94.2", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.94.2.tgz", + "integrity": "sha512-N+7WK20/wOr7CzA2snJcUSSNTCzeCGUTFY3OgeQP3mZ1aj9NMQ0mSTXwlrnd89j33zzQJGqIN52GIOmYrfq46A==", "dev": true, "license": "MIT", "dependencies": { @@ -11517,9 +11517,9 @@ } }, "node_modules/vite": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.2.tgz", - "integrity": "sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ==", + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.4.tgz", + "integrity": "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==", "dev": true, "license": "MIT", "dependencies": { @@ -11840,9 +11840,9 @@ "license": "BSD-2-Clause" }, "node_modules/webpack": { - "version": "5.102.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.102.1.tgz", - "integrity": "sha512-7h/weGm9d/ywQ6qzJ+Xy+r9n/3qgp/thalBbpOi5i223dPXKi04IBtqPN9nTd+jBc7QKfvDbaBnFipYp4sJAUQ==", + "version": "5.103.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.103.0.tgz", + "integrity": "sha512-HU1JOuV1OavsZ+mfigY0j8d1TgQgbZ6M+J75zDkpEAwYeXjWSqrGJtgnPblJjd/mAyTNQ7ygw0MiKOn6etz8yw==", "dev": true, "license": "MIT", "dependencies": { @@ -11863,7 +11863,7 @@ "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", + "loader-runner": "^4.3.1", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^4.3.3", From fa018e80c0ec2063456b0e2556686f7f1650cea7 Mon Sep 17 00:00:00 2001 From: James Cole Date: Tue, 25 Nov 2025 20:12:23 +0100 Subject: [PATCH 13/26] Replace classes --- app/Helpers/Report/ReportHelper.php | 3 +- .../Account/ReconcileController.php | 9 +++--- app/Http/Controllers/Bill/IndexController.php | 3 +- app/Http/Controllers/Bill/ShowController.php | 5 ++-- .../Controllers/Budget/IndexController.php | 7 +++-- .../Controllers/Chart/AccountController.php | 7 +++-- .../Controllers/Chart/CategoryController.php | 13 +++++---- .../Chart/CategoryReportController.php | 9 +++--- .../Chart/DoubleReportController.php | 9 +++--- .../Chart/ExpenseReportController.php | 5 ++-- .../Controllers/Chart/PiggyBankController.php | 3 +- .../Controllers/Chart/ReportController.php | 11 +++---- .../Controllers/Chart/TagReportController.php | 9 +++--- .../Controllers/PreferencesController.php | 3 +- .../Controllers/Report/CategoryController.php | 9 +++--- app/Http/Middleware/Range.php | 5 ++-- app/Jobs/CreateAutoBudgetLimits.php | 21 +++++++------- app/Repositories/Bill/BillRepository.php | 9 +++--- app/Repositories/Budget/BudgetRepository.php | 5 ++-- .../Budget/NoBudgetRepository.php | 3 +- .../Budget/OperationsRepository.php | 3 +- .../Journal/JournalRepository.php | 2 -- .../Category/WholePeriodChartGenerator.php | 9 +++--- app/Support/Http/Api/AccountFilter.php | 2 +- .../Http/Controllers/DateCalculation.php | 19 ++++++------ .../Http/Controllers/GetConfigurationData.php | 29 ++++++++++--------- .../Enrichments/RecurringEnrichment.php | 1 - app/Support/Models/BillDateCalculator.php | 9 +++--- app/Support/Navigation.php | 4 +-- 29 files changed, 124 insertions(+), 102 deletions(-) diff --git a/app/Helpers/Report/ReportHelper.php b/app/Helpers/Report/ReportHelper.php index 140667989c..9bac6588ba 100644 --- a/app/Helpers/Report/ReportHelper.php +++ b/app/Helpers/Report/ReportHelper.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Helpers\Report; +use FireflyIII\Support\Facades\Navigation; use Carbon\Carbon; use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Helpers\Fiscal\FiscalHelperInterface; @@ -81,7 +82,7 @@ class ReportHelper implements ReportHelperInterface /** @var Carbon $expectedStart */ foreach ($expectedDates as $expectedStart) { - $expectedEnd = app('navigation')->endOfX($expectedStart, $bill->repeat_freq, null); + $expectedEnd = Navigation::endOfX($expectedStart, $bill->repeat_freq, null); // is paid in this period maybe? /** @var GroupCollectorInterface $collector */ diff --git a/app/Http/Controllers/Account/ReconcileController.php b/app/Http/Controllers/Account/ReconcileController.php index a6cbc328cb..248e5efe38 100644 --- a/app/Http/Controllers/Account/ReconcileController.php +++ b/app/Http/Controllers/Account/ReconcileController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Account; +use FireflyIII\Support\Facades\Navigation; use Illuminate\Support\Facades\Log; use Carbon\Carbon; use FireflyIII\Enums\AccountTypeEnum; @@ -91,20 +92,20 @@ class ReconcileController extends Controller $currency = $this->accountRepos->getAccountCurrency($account) ?? $this->primaryCurrency; // no start or end: - $range = app('navigation')->getViewRange(false); + $range = Navigation::getViewRange(false); // get start and end if (!$start instanceof Carbon && !$end instanceof Carbon) { /** @var Carbon $start */ - $start = clone session('start', app('navigation')->startOfPeriod(new Carbon(), $range)); + $start = clone session('start', Navigation::startOfPeriod(new Carbon(), $range)); /** @var Carbon $end */ - $end = clone session('end', app('navigation')->endOfPeriod(new Carbon(), $range)); + $end = clone session('end', Navigation::endOfPeriod(new Carbon(), $range)); } if (null === $end) { /** @var Carbon $end */ - $end = app('navigation')->endOfPeriod($start, $range); + $end = Navigation::endOfPeriod($start, $range); } if ($end->lt($start)) { diff --git a/app/Http/Controllers/Bill/IndexController.php b/app/Http/Controllers/Bill/IndexController.php index 9a1b345b18..46950450e0 100644 --- a/app/Http/Controllers/Bill/IndexController.php +++ b/app/Http/Controllers/Bill/IndexController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Bill; +use FireflyIII\Support\Facades\Navigation; use Illuminate\Support\Facades\Log; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\Bill; @@ -151,7 +152,7 @@ class IndexController extends Controller private function getSums(array $bills): array { $sums = []; - $range = app('navigation')->getViewRange(true); + $range = Navigation::getViewRange(true); /** @var array $group */ foreach ($bills as $groupOrder => $group) { diff --git a/app/Http/Controllers/Bill/ShowController.php b/app/Http/Controllers/Bill/ShowController.php index 33d9fa56b7..fa5ef7d699 100644 --- a/app/Http/Controllers/Bill/ShowController.php +++ b/app/Http/Controllers/Bill/ShowController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Bill; +use FireflyIII\Support\Facades\Navigation; use Carbon\Carbon; use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Http\Controllers\Controller; @@ -139,8 +140,8 @@ class ShowController extends Controller $manager->parseIncludes(['attachments', 'notes']); // add another period to end, could fix 8163 - $range = app('navigation')->getViewRange(true); - $end = app('navigation')->addPeriod($end, $range); + $range = Navigation::getViewRange(true); + $end = Navigation::addPeriod($end, $range); // Make a resource out of the data and $parameters = new ParameterBag(); diff --git a/app/Http/Controllers/Budget/IndexController.php b/app/Http/Controllers/Budget/IndexController.php index 9f675b93a9..776a4e2239 100644 --- a/app/Http/Controllers/Budget/IndexController.php +++ b/app/Http/Controllers/Budget/IndexController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Budget; +use FireflyIII\Support\Facades\Navigation; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Http\Controllers\Controller; @@ -94,11 +95,11 @@ class IndexController extends Controller Log::debug(sprintf('Start of IndexController::index("%s", "%s")', $start?->format('Y-m-d'), $end?->format('Y-m-d'))); // collect some basic vars: - $range = app('navigation')->getViewRange(true); + $range = Navigation::getViewRange(true); $isCustomRange = session('is_custom_range', false); if (false === $isCustomRange) { $start ??= session('start', today(config('app.timezone'))->startOfMonth()); - $end ??= app('navigation')->endOfPeriod($start, $range); + $end ??= Navigation::endOfPeriod($start, $range); } // overrule start and end if necessary: @@ -112,7 +113,7 @@ class IndexController extends Controller $spent = '0'; // new period stuff: - $periodTitle = app('navigation')->periodShow($start, $range); + $periodTitle = Navigation::periodShow($start, $range); $prevLoop = $this->getPreviousPeriods($start, $range); $nextLoop = $this->getNextPeriods($start, $range); diff --git a/app/Http/Controllers/Chart/AccountController.php b/app/Http/Controllers/Chart/AccountController.php index 8cf2c2be9e..70aac51d3a 100644 --- a/app/Http/Controllers/Chart/AccountController.php +++ b/app/Http/Controllers/Chart/AccountController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Chart; +use FireflyIII\Support\Facades\Navigation; use Carbon\Carbon; use FireflyIII\Enums\AccountTypeEnum; use FireflyIII\Enums\TransactionTypeEnum; @@ -514,7 +515,7 @@ class AccountController extends Controller // have to make sure this chart is always based on the balance at the END of the period. // This period depends on the size of the chart $current = clone $start; - $current = app('navigation')->endOfX($current, $step, null); + $current = Navigation::endOfX($current, $step, null); $format = (string)trans('config.month_and_day_js', [], $locale); $accountCurrency = $this->accountRepository->getAccountCurrency($account); Log::debug('Get and filter balance for entire range start'); @@ -574,9 +575,9 @@ class AccountController extends Controller $label = $current->isoFormat($format); $return[$key]['entries'][$label] = $amount; } - $current = app('navigation')->addPeriod($current, $step); + $current = Navigation::addPeriod($current, $step); // here too, to fix #8041, the data is corrected to the end of the period. - $current = app('navigation')->endOfX($current, $step, null); + $current = Navigation::endOfX($current, $step, null); } Log::debug('End of chart loop.'); // second loop (yes) to create nice array with info! Yay! diff --git a/app/Http/Controllers/Chart/CategoryController.php b/app/Http/Controllers/Chart/CategoryController.php index 6e195311b3..8dbd4db7d4 100644 --- a/app/Http/Controllers/Chart/CategoryController.php +++ b/app/Http/Controllers/Chart/CategoryController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Chart; +use FireflyIII\Support\Facades\Navigation; use Carbon\Carbon; use FireflyIII\Generator\Chart\Basic\GeneratorInterface; use FireflyIII\Http\Controllers\Controller; @@ -81,8 +82,8 @@ class CategoryController extends Controller /** @var CategoryRepositoryInterface $repository */ $repository = app(CategoryRepositoryInterface::class); $start = $repository->firstUseDate($category) ?? $this->getDate(); - $range = app('navigation')->getViewRange(false); - $start = app('navigation')->startOfPeriod($start, $range); + $range = Navigation::getViewRange(false); + $start = Navigation::startOfPeriod($start, $range); $end = $this->getDate(); /** @var WholePeriodChartGenerator $chartGenerator */ @@ -178,8 +179,8 @@ class CategoryController extends Controller $income = $opsRepository->listIncome($start, $end, $accounts, $collection); } $currencies = array_unique(array_merge(array_keys($income), array_keys($expenses))); - $periods = app('navigation')->listOfPeriods($start, $end); - $format = app('navigation')->preferredCarbonLocalizedFormat($start, $end); + $periods = Navigation::listOfPeriods($start, $end); + $format = Navigation::preferredCarbonLocalizedFormat($start, $end); $chartData = []; // make empty data array: // double foreach (bad) to make empty array: @@ -260,8 +261,8 @@ class CategoryController extends Controller */ public function specificPeriod(Category $category, Carbon $date): JsonResponse { - $range = app('navigation')->getViewRange(false); - $start = app('navigation')->startOfPeriod($date, $range); + $range = Navigation::getViewRange(false); + $start = Navigation::startOfPeriod($date, $range); $end = session()->get('end'); if ($end < $start) { [$end, $start] = [$start, $end]; diff --git a/app/Http/Controllers/Chart/CategoryReportController.php b/app/Http/Controllers/Chart/CategoryReportController.php index 107509cece..9cce66c5d4 100644 --- a/app/Http/Controllers/Chart/CategoryReportController.php +++ b/app/Http/Controllers/Chart/CategoryReportController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Chart; +use FireflyIII\Support\Facades\Navigation; use Carbon\Carbon; use FireflyIII\Generator\Chart\Basic\GeneratorInterface; use FireflyIII\Http\Controllers\Controller; @@ -210,7 +211,7 @@ class CategoryReportController extends Controller $chartData = []; $spent = $this->opsRepository->listExpenses($start, $end, $accounts, new Collection()->push($category)); $earned = $this->opsRepository->listIncome($start, $end, $accounts, new Collection()->push($category)); - $format = app('navigation')->preferredCarbonLocalizedFormat($start, $end); + $format = Navigation::preferredCarbonLocalizedFormat($start, $end); // loop expenses. foreach ($spent as $currency) { // add things to chart Data for each currency: @@ -276,11 +277,11 @@ class CategoryReportController extends Controller private function makeEntries(Carbon $start, Carbon $end): array { $return = []; - $format = app('navigation')->preferredCarbonLocalizedFormat($start, $end); - $preferredRange = app('navigation')->preferredRangeFormat($start, $end); + $format = Navigation::preferredCarbonLocalizedFormat($start, $end); + $preferredRange = Navigation::preferredRangeFormat($start, $end); $currentStart = clone $start; while ($currentStart <= $end) { - $currentEnd = app('navigation')->endOfPeriod($currentStart, $preferredRange); + $currentEnd = Navigation::endOfPeriod($currentStart, $preferredRange); $key = $currentStart->isoFormat($format); $return[$key] = '0'; $currentStart = clone $currentEnd; diff --git a/app/Http/Controllers/Chart/DoubleReportController.php b/app/Http/Controllers/Chart/DoubleReportController.php index 12b75f9e23..aa096abae2 100644 --- a/app/Http/Controllers/Chart/DoubleReportController.php +++ b/app/Http/Controllers/Chart/DoubleReportController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Chart; +use FireflyIII\Support\Facades\Navigation; use Carbon\Carbon; use FireflyIII\Generator\Chart\Basic\GeneratorInterface; use FireflyIII\Http\Controllers\Controller; @@ -154,7 +155,7 @@ class DoubleReportController extends Controller $accounts = $accounts->merge($opposing); $spent = $this->opsRepository->listExpenses($start, $end, $accounts); $earned = $this->opsRepository->listIncome($start, $end, $accounts); - $format = app('navigation')->preferredCarbonLocalizedFormat($start, $end); + $format = Navigation::preferredCarbonLocalizedFormat($start, $end); // loop expenses. foreach ($spent as $currency) { @@ -238,11 +239,11 @@ class DoubleReportController extends Controller private function makeEntries(Carbon $start, Carbon $end): array { $return = []; - $format = app('navigation')->preferredCarbonLocalizedFormat($start, $end); - $preferredRange = app('navigation')->preferredRangeFormat($start, $end); + $format = Navigation::preferredCarbonLocalizedFormat($start, $end); + $preferredRange = Navigation::preferredRangeFormat($start, $end); $currentStart = clone $start; while ($currentStart <= $end) { - $currentEnd = app('navigation')->endOfPeriod($currentStart, $preferredRange); + $currentEnd = Navigation::endOfPeriod($currentStart, $preferredRange); $key = $currentStart->isoFormat($format); $return[$key] = '0'; $currentStart = clone $currentEnd; diff --git a/app/Http/Controllers/Chart/ExpenseReportController.php b/app/Http/Controllers/Chart/ExpenseReportController.php index d3806d846e..cfce4a2315 100644 --- a/app/Http/Controllers/Chart/ExpenseReportController.php +++ b/app/Http/Controllers/Chart/ExpenseReportController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Chart; +use FireflyIII\Support\Facades\Navigation; use Carbon\Carbon; use FireflyIII\Generator\Chart\Basic\GeneratorInterface; use FireflyIII\Http\Controllers\Controller; @@ -83,8 +84,8 @@ class ExpenseReportController extends Controller return response()->json($cache->get()); } - $format = app('navigation')->preferredCarbonLocalizedFormat($start, $end); - $function = app('navigation')->preferredEndOfPeriod($start, $end); + $format = Navigation::preferredCarbonLocalizedFormat($start, $end); + $function = Navigation::preferredEndOfPeriod($start, $end); $chartData = []; $currentStart = clone $start; $combined = $this->combineAccounts($expense); diff --git a/app/Http/Controllers/Chart/PiggyBankController.php b/app/Http/Controllers/Chart/PiggyBankController.php index c0db48f026..ed8a549951 100644 --- a/app/Http/Controllers/Chart/PiggyBankController.php +++ b/app/Http/Controllers/Chart/PiggyBankController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Chart; +use FireflyIII\Support\Facades\Navigation; use Carbon\Carbon; use FireflyIII\Generator\Chart\Basic\GeneratorInterface; use FireflyIII\Http\Controllers\Controller; @@ -92,7 +93,7 @@ class PiggyBankController extends Controller $currentSum = $filtered->sum('amount'); $label = $oldest->isoFormat((string) trans('config.month_and_day_js', [], $locale)); $chartData[$label] = $currentSum; - $oldest = app('navigation')->addPeriod($oldest, $step); + $oldest = Navigation::addPeriod($oldest, $step); } $finalFiltered = $set->filter( static fn (PiggyBankEvent $event) => $event->date->lte($today) diff --git a/app/Http/Controllers/Chart/ReportController.php b/app/Http/Controllers/Chart/ReportController.php index 5ccd3a0d10..f11c6a3df0 100644 --- a/app/Http/Controllers/Chart/ReportController.php +++ b/app/Http/Controllers/Chart/ReportController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Chart; +use FireflyIII\Support\Facades\Navigation; use Carbon\Carbon; use FireflyIII\Enums\TransactionTypeEnum; use FireflyIII\Generator\Chart\Basic\GeneratorInterface; @@ -154,9 +155,9 @@ class ReportController extends Controller Log::debug('Going to do operations for accounts ', $accounts->pluck('id')->toArray()); Log::debug(sprintf('Period: %s to %s', $start->toW3cString(), $end->toW3cString())); - $format = app('navigation')->preferredCarbonFormat($start, $end); - $titleFormat = app('navigation')->preferredCarbonLocalizedFormat($start, $end); - $preferredRange = app('navigation')->preferredRangeFormat($start, $end); + $format = Navigation::preferredCarbonFormat($start, $end); + $titleFormat = Navigation::preferredCarbonLocalizedFormat($start, $end); + $preferredRange = Navigation::preferredRangeFormat($start, $end); $ids = $accounts->pluck('id')->toArray(); $data = []; $chartData = []; @@ -242,7 +243,7 @@ class ReportController extends Controller // #8374. Sloppy fix for yearly charts. Not really interested in a better fix with v2 layout and all. if ('1Y' === $preferredRange) { - $currentEnd = app('navigation')->endOfPeriod($currentEnd, $preferredRange); + $currentEnd = Navigation::endOfPeriod($currentEnd, $preferredRange); } Log::debug('Start of sub-loop'); while ($currentStart <= $currentEnd) { @@ -260,7 +261,7 @@ class ReportController extends Controller $expense['entries'][$title] = '0'; } - $currentStart = app('navigation')->addPeriod($currentStart, $preferredRange); + $currentStart = Navigation::addPeriod($currentStart, $preferredRange); } Log::debug('End of sub-loop'); diff --git a/app/Http/Controllers/Chart/TagReportController.php b/app/Http/Controllers/Chart/TagReportController.php index 6705377806..8bee1ec38d 100644 --- a/app/Http/Controllers/Chart/TagReportController.php +++ b/app/Http/Controllers/Chart/TagReportController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Chart; +use FireflyIII\Support\Facades\Navigation; use Carbon\Carbon; use FireflyIII\Generator\Chart\Basic\GeneratorInterface; use FireflyIII\Http\Controllers\Controller; @@ -214,7 +215,7 @@ class TagReportController extends Controller $chartData = []; $spent = $this->opsRepository->listExpenses($start, $end, $accounts, new Collection()->push($tag)); $earned = $this->opsRepository->listIncome($start, $end, $accounts, new Collection()->push($tag)); - $format = app('navigation')->preferredCarbonLocalizedFormat($start, $end); + $format = Navigation::preferredCarbonLocalizedFormat($start, $end); // loop expenses. foreach ($spent as $currency) { @@ -281,11 +282,11 @@ class TagReportController extends Controller private function makeEntries(Carbon $start, Carbon $end): array { $return = []; - $format = app('navigation')->preferredCarbonLocalizedFormat($start, $end); - $preferredRange = app('navigation')->preferredRangeFormat($start, $end); + $format = Navigation::preferredCarbonLocalizedFormat($start, $end); + $preferredRange = Navigation::preferredRangeFormat($start, $end); $currentStart = clone $start; while ($currentStart <= $end) { - $currentEnd = app('navigation')->endOfPeriod($currentStart, $preferredRange); + $currentEnd = Navigation::endOfPeriod($currentStart, $preferredRange); $key = $currentStart->isoFormat($format); $return[$key] = '0'; $currentStart = clone $currentEnd; diff --git a/app/Http/Controllers/PreferencesController.php b/app/Http/Controllers/PreferencesController.php index 229f853f3c..3d3badcd3f 100644 --- a/app/Http/Controllers/PreferencesController.php +++ b/app/Http/Controllers/PreferencesController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers; +use FireflyIII\Support\Facades\Navigation; use Carbon\Carbon; use FireflyIII\Enums\AccountTypeEnum; use FireflyIII\Events\Preferences\UserGroupChangedPrimaryCurrency; @@ -101,7 +102,7 @@ class PreferencesController extends Controller /** @var array $accountIds */ $accountIds = $accounts->pluck('id')->toArray(); - $viewRange = app('navigation')->getViewRange(false); + $viewRange = Navigation::getViewRange(false); $frontpageAccountsPref = Preferences::get('frontpageAccounts', $accountIds); $frontpageAccounts = $frontpageAccountsPref->data; if (!is_array($frontpageAccounts)) { diff --git a/app/Http/Controllers/Report/CategoryController.php b/app/Http/Controllers/Report/CategoryController.php index ae4adb23de..1d3a9058a3 100644 --- a/app/Http/Controllers/Report/CategoryController.php +++ b/app/Http/Controllers/Report/CategoryController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Report; +use FireflyIII\Support\Facades\Navigation; use Illuminate\Support\Facades\Log; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; @@ -485,7 +486,7 @@ class CategoryController extends Controller // depending on the carbon format (a reliable way to determine the general date difference) // change the "listOfPeriods" call so the entire period gets included correctly. - $format = app('navigation')->preferredCarbonFormat($start, $end); + $format = Navigation::preferredCarbonFormat($start, $end); if ('Y' === $format) { $start->startOfYear(); @@ -494,7 +495,7 @@ class CategoryController extends Controller $start->startOfMonth(); } - $periods = app('navigation')->listOfPeriods($start, $end); + $periods = Navigation::listOfPeriods($start, $end); $data = []; $with = $this->opsRepository->listExpenses($start, $end, $accounts); $without = $this->noCatRepository->listExpenses($start, $end, $accounts); @@ -559,7 +560,7 @@ class CategoryController extends Controller // depending on the carbon format (a reliable way to determine the general date difference) // change the "listOfPeriods" call so the entire period gets included correctly. - $format = app('navigation')->preferredCarbonFormat($start, $end); + $format = Navigation::preferredCarbonFormat($start, $end); if ('Y' === $format) { $start->startOfYear(); @@ -568,7 +569,7 @@ class CategoryController extends Controller $start->startOfMonth(); } - $periods = app('navigation')->listOfPeriods($start, $end); + $periods = Navigation::listOfPeriods($start, $end); $data = []; $with = $this->opsRepository->listIncome($start, $end, $accounts); $without = $this->noCatRepository->listIncome($start, $end, $accounts); diff --git a/app/Http/Middleware/Range.php b/app/Http/Middleware/Range.php index b9a3ff0292..3d604b4afe 100644 --- a/app/Http/Middleware/Range.php +++ b/app/Http/Middleware/Range.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Middleware; +use FireflyIII\Support\Facades\Navigation; use Carbon\Carbon; use Closure; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; @@ -75,8 +76,8 @@ class Range } $today = today(config('app.timezone')); - $start = app('navigation')->updateStartDate((string) $viewRange, $today); - $end = app('navigation')->updateEndDate((string) $viewRange, $start); + $start = Navigation::updateStartDate((string) $viewRange, $today); + $end = Navigation::updateEndDate((string) $viewRange, $start); app('session')->put('start', $start); app('session')->put('end', $end); diff --git a/app/Jobs/CreateAutoBudgetLimits.php b/app/Jobs/CreateAutoBudgetLimits.php index e9779d0bc0..e645306a99 100644 --- a/app/Jobs/CreateAutoBudgetLimits.php +++ b/app/Jobs/CreateAutoBudgetLimits.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Jobs; +use FireflyIII\Support\Facades\Navigation; use Carbon\Carbon; use FireflyIII\Enums\AutoBudgetType; use FireflyIII\Exceptions\FireflyException; @@ -122,8 +123,8 @@ class CreateAutoBudgetLimits implements ShouldQueue ); // get date range for budget limit, based on range in auto-budget - $start = app('navigation')->startOfPeriod($this->date, $autoBudget->period); - $end = app('navigation')->endOfPeriod($start, $autoBudget->period); + $start = Navigation::startOfPeriod($this->date, $autoBudget->period); + $end = Navigation::endOfPeriod($start, $autoBudget->period); // find budget limit: $budgetLimit = $this->findBudgetLimit($autoBudget->budget, $start, $end); @@ -237,12 +238,12 @@ class CreateAutoBudgetLimits implements ShouldQueue { Log::debug(sprintf('Will now manage rollover for auto budget #%d', $autoBudget->id)); // current period: - $start = app('navigation')->startOfPeriod($this->date, $autoBudget->period); - $end = app('navigation')->endOfPeriod($start, $autoBudget->period); + $start = Navigation::startOfPeriod($this->date, $autoBudget->period); + $end = Navigation::endOfPeriod($start, $autoBudget->period); // which means previous period: - $previousStart = app('navigation')->subtractPeriod($start, $autoBudget->period); - $previousEnd = app('navigation')->endOfPeriod($previousStart, $autoBudget->period); + $previousStart = Navigation::subtractPeriod($start, $autoBudget->period); + $previousEnd = Navigation::endOfPeriod($previousStart, $autoBudget->period); Log::debug( sprintf( @@ -297,12 +298,12 @@ class CreateAutoBudgetLimits implements ShouldQueue { Log::debug(sprintf('Will now manage rollover for auto budget #%d', $autoBudget->id)); // current period: - $start = app('navigation')->startOfPeriod($this->date, $autoBudget->period); - $end = app('navigation')->endOfPeriod($start, $autoBudget->period); + $start = Navigation::startOfPeriod($this->date, $autoBudget->period); + $end = Navigation::endOfPeriod($start, $autoBudget->period); // which means previous period: - $previousStart = app('navigation')->subtractPeriod($start, $autoBudget->period); - $previousEnd = app('navigation')->endOfPeriod($previousStart, $autoBudget->period); + $previousStart = Navigation::subtractPeriod($start, $autoBudget->period); + $previousEnd = Navigation::endOfPeriod($previousStart, $autoBudget->period); Log::debug( sprintf( diff --git a/app/Repositories/Bill/BillRepository.php b/app/Repositories/Bill/BillRepository.php index f33d339cc6..0f8fe684b8 100644 --- a/app/Repositories/Bill/BillRepository.php +++ b/app/Repositories/Bill/BillRepository.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Repositories\Bill; +use FireflyIII\Support\Facades\Navigation; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Factory\BillFactory; @@ -463,11 +464,11 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface while ($start < $date) { Log::debug(sprintf('$start (%s) < $date (%s)', $start->format('Y-m-d H:i:s'), $date->format('Y-m-d H:i:s'))); - $start = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip); + $start = Navigation::addPeriod($start, $bill->repeat_freq, $bill->skip); Log::debug('Start is now '.$start->format('Y-m-d H:i:s')); } - $end = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip); + $end = Navigation::addPeriod($start, $bill->repeat_freq, $bill->skip); $end->endOfDay(); // see if the bill was paid in this period. @@ -477,7 +478,7 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface // this period had in fact a bill. The new start is the current end, and we create a new end. Log::debug(sprintf('Journal count is %d, so start becomes %s', $journalCount, $end->format('Y-m-d'))); $start = clone $end; - $end = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip); + $end = Navigation::addPeriod($start, $bill->repeat_freq, $bill->skip); } Log::debug('nextExpectedMatch: Final start is '.$start->format('Y-m-d')); Log::debug('nextExpectedMatch: Matching end is '.$end->format('Y-m-d')); @@ -681,7 +682,7 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface $start = clone $bill->date; while ($start < $date) { - $start = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip); + $start = Navigation::addPeriod($start, $bill->repeat_freq, $bill->skip); } $cache->store($start); diff --git a/app/Repositories/Budget/BudgetRepository.php b/app/Repositories/Budget/BudgetRepository.php index 3714176818..36d7cd9f00 100644 --- a/app/Repositories/Budget/BudgetRepository.php +++ b/app/Repositories/Budget/BudgetRepository.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Repositories\Budget; +use FireflyIII\Support\Facades\Navigation; use Carbon\Carbon; use FireflyIII\Enums\AutoBudgetType; use FireflyIII\Enums\TransactionTypeEnum; @@ -790,8 +791,8 @@ class BudgetRepository implements BudgetRepositoryInterface, UserGroupInterface // create initial budget limit. $today = today(config('app.timezone')); - $start = app('navigation')->startOfPeriod($today, $autoBudget->period); - $end = app('navigation')->endOfPeriod($start, $autoBudget->period); + $start = Navigation::startOfPeriod($today, $autoBudget->period); + $end = Navigation::endOfPeriod($start, $autoBudget->period); $limitRepos = app(BudgetLimitRepositoryInterface::class); $limitRepos->setUser($this->user); diff --git a/app/Repositories/Budget/NoBudgetRepository.php b/app/Repositories/Budget/NoBudgetRepository.php index 3b5709b18b..6d53f9c243 100644 --- a/app/Repositories/Budget/NoBudgetRepository.php +++ b/app/Repositories/Budget/NoBudgetRepository.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Repositories\Budget; +use FireflyIII\Support\Facades\Navigation; use Carbon\Carbon; use FireflyIII\Enums\TransactionTypeEnum; use FireflyIII\Helpers\Collector\GroupCollectorInterface; @@ -45,7 +46,7 @@ class NoBudgetRepository implements NoBudgetRepositoryInterface, UserGroupInterf #[Deprecated] public function getNoBudgetPeriodReport(Collection $accounts, Carbon $start, Carbon $end): array { - $carbonFormat = app('navigation')->preferredCarbonFormat($start, $end); + $carbonFormat = Navigation::preferredCarbonFormat($start, $end); /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollectorInterface::class); diff --git a/app/Repositories/Budget/OperationsRepository.php b/app/Repositories/Budget/OperationsRepository.php index 157e9ca4af..15d3ea38f9 100644 --- a/app/Repositories/Budget/OperationsRepository.php +++ b/app/Repositories/Budget/OperationsRepository.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Repositories\Budget; +use FireflyIII\Support\Facades\Navigation; use Carbon\Carbon; use Deprecated; use FireflyIII\Enums\TransactionTypeEnum; @@ -82,7 +83,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn #[Deprecated] public function getBudgetPeriodReport(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end): array { - $carbonFormat = app('navigation')->preferredCarbonFormat($start, $end); + $carbonFormat = Navigation::preferredCarbonFormat($start, $end); $data = []; // get all transactions: diff --git a/app/Repositories/Journal/JournalRepository.php b/app/Repositories/Journal/JournalRepository.php index c249f834a4..481418b225 100644 --- a/app/Repositories/Journal/JournalRepository.php +++ b/app/Repositories/Journal/JournalRepository.php @@ -76,7 +76,6 @@ class JournalRepository implements JournalRepositoryInterface, UserGroupInterfac */ public function firstNull(): ?TransactionJournal { - /** @var null|TransactionJournal $entry */ return $this->user->transactionJournals()->orderBy('date', 'ASC')->first(['transaction_journals.*']); } @@ -113,7 +112,6 @@ class JournalRepository implements JournalRepositoryInterface, UserGroupInterfac public function getLast(): ?TransactionJournal { - /** @var null|TransactionJournal $entry */ return $this->user->transactionJournals()->orderBy('date', 'DESC')->first(['transaction_journals.*']); } diff --git a/app/Support/Chart/Category/WholePeriodChartGenerator.php b/app/Support/Chart/Category/WholePeriodChartGenerator.php index 27d6026c2f..e0ea91ac9a 100644 --- a/app/Support/Chart/Category/WholePeriodChartGenerator.php +++ b/app/Support/Chart/Category/WholePeriodChartGenerator.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Support\Chart\Category; +use FireflyIII\Support\Facades\Navigation; use Carbon\Carbon; use FireflyIII\Enums\AccountTypeEnum; use FireflyIII\Models\Category; @@ -59,10 +60,10 @@ class WholePeriodChartGenerator while ($current <= $end) { $key = $current->format('Y-m-d'); - $currentEnd = app('navigation')->endOfPeriod($current, $step); + $currentEnd = Navigation::endOfPeriod($current, $step); $spent[$key] = $opsRepository->sumExpenses($current, $currentEnd, $accounts, $collection); $earned[$key] = $opsRepository->sumIncome($current, $currentEnd, $accounts, $collection); - $current = app('navigation')->addPeriod($current, $step); + $current = Navigation::addPeriod($current, $step); } $currencies = $this->extractCurrencies($spent) + $this->extractCurrencies($earned); @@ -91,7 +92,7 @@ class WholePeriodChartGenerator while ($current <= $end) { $key = $current->format('Y-m-d'); - $label = app('navigation')->periodShow($current, $step); + $label = Navigation::periodShow($current, $step); /** @var array $currency */ foreach ($currencies as $currency) { @@ -104,7 +105,7 @@ class WholePeriodChartGenerator $chartData[$spentInfoKey]['entries'][$label] = app('steam')->bcround($spentAmount, $currency['currency_decimal_places']); $chartData[$earnedInfoKey]['entries'][$label] = app('steam')->bcround($earnedAmount, $currency['currency_decimal_places']); } - $current = app('navigation')->addPeriod($current, $step); + $current = Navigation::addPeriod($current, $step); } return $chartData; diff --git a/app/Support/Http/Api/AccountFilter.php b/app/Support/Http/Api/AccountFilter.php index 1cce125919..dcc74dcd21 100644 --- a/app/Support/Http/Api/AccountFilter.php +++ b/app/Support/Http/Api/AccountFilter.php @@ -107,7 +107,7 @@ trait AccountFilter } if (0 === count($return)) { - $return = $this->types['normal']; + return $this->types['normal']; } return $return; diff --git a/app/Support/Http/Controllers/DateCalculation.php b/app/Support/Http/Controllers/DateCalculation.php index 69c30c77d3..f8d2204e21 100644 --- a/app/Support/Http/Controllers/DateCalculation.php +++ b/app/Support/Http/Controllers/DateCalculation.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Support\Http\Controllers; +use FireflyIII\Support\Facades\Navigation; use Carbon\Carbon; /** @@ -93,18 +94,18 @@ trait DateCalculation $loop = []; /** @var Carbon $current */ - $current = app('navigation')->startOfPeriod($date, $range); - $current = app('navigation')->endOfPeriod($current, $range); + $current = Navigation::startOfPeriod($date, $range); + $current = Navigation::endOfPeriod($current, $range); $current->addDay(); $count = 0; while ($count < 12) { - $current = app('navigation')->endOfPeriod($current, $range); - $currentStart = app('navigation')->startOfPeriod($current, $range); + $current = Navigation::endOfPeriod($current, $range); + $currentStart = Navigation::startOfPeriod($current, $range); $loop[] = [ 'label' => $current->format('Y-m-d'), - 'title' => app('navigation')->periodShow($current, $range), + 'title' => Navigation::periodShow($current, $range), 'start' => clone $currentStart, 'end' => clone $current, ]; @@ -125,15 +126,15 @@ trait DateCalculation $loop = []; /** @var Carbon $current */ - $current = app('navigation')->startOfPeriod($date, $range); + $current = Navigation::startOfPeriod($date, $range); $count = 0; while ($count < 12) { $current->subDay(); - $current = app('navigation')->startOfPeriod($current, $range); - $currentEnd = app('navigation')->endOfPeriod($current, $range); + $current = Navigation::startOfPeriod($current, $range); + $currentEnd = Navigation::endOfPeriod($current, $range); $loop[] = [ 'label' => $current->format('Y-m-d'), - 'title' => app('navigation')->periodShow($current, $range), + 'title' => Navigation::periodShow($current, $range), 'start' => clone $current, 'end' => clone $currentEnd, ]; diff --git a/app/Support/Http/Controllers/GetConfigurationData.php b/app/Support/Http/Controllers/GetConfigurationData.php index d1f28200e0..2ea8527419 100644 --- a/app/Support/Http/Controllers/GetConfigurationData.php +++ b/app/Support/Http/Controllers/GetConfigurationData.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Support\Http\Controllers; +use FireflyIII\Support\Facades\Navigation; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Support\Facades\FireflyConfig; @@ -82,7 +83,7 @@ trait GetConfigurationData */ protected function getDateRangeConfig(): array // get configuration + get preferences. { - $viewRange = app('navigation')->getViewRange(false); + $viewRange = Navigation::getViewRange(false); Log::debug(sprintf('dateRange: the view range is "%s"', $viewRange)); @@ -105,32 +106,32 @@ trait GetConfigurationData // when current range is a custom range, add the current period as the next range. if ($isCustom) { - $index = app('navigation')->periodShow($start, $viewRange); - $customPeriodStart = app('navigation')->startOfPeriod($start, $viewRange); - $customPeriodEnd = app('navigation')->endOfPeriod($customPeriodStart, $viewRange); + $index = Navigation::periodShow($start, $viewRange); + $customPeriodStart = Navigation::startOfPeriod($start, $viewRange); + $customPeriodEnd = Navigation::endOfPeriod($customPeriodStart, $viewRange); $ranges[$index] = [$customPeriodStart, $customPeriodEnd]; } // then add previous range and next range, but skip this for the lastX and YTD stuff. if (!in_array($viewRange, config('firefly.dynamic_date_ranges', []), true)) { - $previousDate = app('navigation')->subtractPeriod($start, $viewRange); - $index = app('navigation')->periodShow($previousDate, $viewRange); - $previousStart = app('navigation')->startOfPeriod($previousDate, $viewRange); - $previousEnd = app('navigation')->endOfPeriod($previousStart, $viewRange); + $previousDate = Navigation::subtractPeriod($start, $viewRange); + $index = Navigation::periodShow($previousDate, $viewRange); + $previousStart = Navigation::startOfPeriod($previousDate, $viewRange); + $previousEnd = Navigation::endOfPeriod($previousStart, $viewRange); $ranges[$index] = [$previousStart, $previousEnd]; - $nextDate = app('navigation')->addPeriod($start, $viewRange); - $index = app('navigation')->periodShow($nextDate, $viewRange); - $nextStart = app('navigation')->startOfPeriod($nextDate, $viewRange); - $nextEnd = app('navigation')->endOfPeriod($nextStart, $viewRange); + $nextDate = Navigation::addPeriod($start, $viewRange); + $index = Navigation::periodShow($nextDate, $viewRange); + $nextStart = Navigation::startOfPeriod($nextDate, $viewRange); + $nextEnd = Navigation::endOfPeriod($nextStart, $viewRange); $ranges[$index] = [$nextStart, $nextEnd]; } // today: /** @var Carbon $todayStart */ - $todayStart = app('navigation')->startOfPeriod($today, $viewRange); + $todayStart = Navigation::startOfPeriod($today, $viewRange); /** @var Carbon $todayEnd */ - $todayEnd = app('navigation')->endOfPeriod($todayStart, $viewRange); + $todayEnd = Navigation::endOfPeriod($todayStart, $viewRange); if ($todayStart->ne($start) || $todayEnd->ne($end)) { $ranges[ucfirst((string)trans('firefly.today'))] = [$todayStart, $todayEnd]; diff --git a/app/Support/JsonApi/Enrichments/RecurringEnrichment.php b/app/Support/JsonApi/Enrichments/RecurringEnrichment.php index 6257cf8426..7010a1de18 100644 --- a/app/Support/JsonApi/Enrichments/RecurringEnrichment.php +++ b/app/Support/JsonApi/Enrichments/RecurringEnrichment.php @@ -69,7 +69,6 @@ class RecurringEnrichment implements EnrichmentInterface private string $language = 'en_US'; private array $notes = []; private readonly TransactionCurrency $primaryCurrency; - private array $recurrenceIds = []; private array $recurrenceByTransaction = []; private array $repetitions = []; private array $sourceAccountIds = []; diff --git a/app/Support/Models/BillDateCalculator.php b/app/Support/Models/BillDateCalculator.php index 6b7cbd2243..d29244e726 100644 --- a/app/Support/Models/BillDateCalculator.php +++ b/app/Support/Models/BillDateCalculator.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Support\Models; +use FireflyIII\Support\Facades\Navigation; use Carbon\Carbon; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Log; @@ -49,7 +50,7 @@ class BillDateCalculator Log::debug(sprintf('Dates must be between %s and %s.', $earliest->format('Y-m-d'), $latest->format('Y-m-d'))); Log::debug(sprintf('Bill started on %s, period is "%s", skip is %d, last paid = "%s".', $billStart->format('Y-m-d'), $period, $skip, $lastPaid?->format('Y-m-d'))); - $daysUntilEOM = app('navigation')->daysUntilEndOfMonth($billStart); + $daysUntilEOM = Navigation::daysUntilEndOfMonth($billStart); Log::debug(sprintf('For bill start, days until end of month is %d', $daysUntilEOM)); $set = new Collection(); @@ -94,7 +95,7 @@ class BillDateCalculator // the next expected month because that month has only 28 days (i.e. february). // this applies to leap years as well. if ($daysUntilEOM < 4) { - $nextUntilEOM = app('navigation')->daysUntilEndOfMonth($nextExpectedMatch); + $nextUntilEOM = Navigation::daysUntilEndOfMonth($nextExpectedMatch); $diffEOM = $daysUntilEOM - $nextUntilEOM; if ($diffEOM > 0) { Log::debug(sprintf('Bill start is %d days from the end of the month. nextExceptedMatch is %d days from the end of the month.', $daysUntilEOM, $nextUntilEOM)); @@ -140,7 +141,7 @@ class BillDateCalculator return $billStartDate; } - $steps = app('navigation')->diffInPeriods($period, $skip, $earliest, $billStartDate); + $steps = Navigation::diffInPeriods($period, $skip, $earliest, $billStartDate); if ($steps === $this->diffInMonths) { Log::debug(sprintf('Steps is %d, which is the same as diffInMonths (%d), so we add another 1.', $steps, $this->diffInMonths)); ++$steps; @@ -150,7 +151,7 @@ class BillDateCalculator if ($steps > 0) { --$steps; Log::debug(sprintf('Steps is %d, because addPeriod already adds 1.', $steps)); - $result = app('navigation')->addPeriod($billStartDate, $period, $steps); + $result = Navigation::addPeriod($billStartDate, $period, $steps); } Log::debug(sprintf('Number of steps is %d, added to %s, result is %s', $steps, $billStartDate->format('Y-m-d'), $result->format('Y-m-d'))); diff --git a/app/Support/Navigation.php b/app/Support/Navigation.php index b80548d990..eeaa7714e2 100644 --- a/app/Support/Navigation.php +++ b/app/Support/Navigation.php @@ -121,8 +121,8 @@ class Navigation if ($workEnd->gt($start)) { while ($workEnd->gt($start) && $loopCount < 20) { // make range: - $workStart = app('navigation')->startOfPeriod($workStart, '1Y'); - $workEnd = app('navigation')->endOfPeriod($workStart, '1Y'); + $workStart = \FireflyIII\Support\Facades\Navigation::startOfPeriod($workStart, '1Y'); + $workEnd = \FireflyIII\Support\Facades\Navigation::endOfPeriod($workStart, '1Y'); // make sure we don't go overboard if ($workEnd->gt($start)) { From d7967a81e35e18338567c0c5aa6587c2b5a5db66 Mon Sep 17 00:00:00 2001 From: James Cole Date: Tue, 25 Nov 2025 20:12:35 +0100 Subject: [PATCH 14/26] Fix https://github.com/firefly-iii/firefly-iii/issues/11284 --- .../RecalculatesAvailableBudgetsTrait.php | 57 ++++++++++++------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/app/Support/Observers/RecalculatesAvailableBudgetsTrait.php b/app/Support/Observers/RecalculatesAvailableBudgetsTrait.php index b4a774ea95..8a238e723b 100644 --- a/app/Support/Observers/RecalculatesAvailableBudgetsTrait.php +++ b/app/Support/Observers/RecalculatesAvailableBudgetsTrait.php @@ -29,11 +29,13 @@ use FireflyIII\Models\AvailableBudget; use FireflyIII\Models\Budget; use FireflyIII\Models\BudgetLimit; use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface; +use FireflyIII\Support\Facades\Navigation; use FireflyIII\User; use Illuminate\Support\Facades\Log; use Psr\Container\ContainerExceptionInterface; use Psr\Container\NotFoundExceptionInterface; use Spatie\Period\Boundaries; +use Spatie\Period\Exceptions\InvalidPeriod; use Spatie\Period\Period; use Spatie\Period\Precision; @@ -41,10 +43,10 @@ trait RecalculatesAvailableBudgetsTrait { private function calculateAmount(AvailableBudget $availableBudget): void { - $repository = app(BudgetLimitRepositoryInterface::class); + $repository = app(BudgetLimitRepositoryInterface::class); $repository->setUser($availableBudget->user); - $newAmount = '0'; - $abPeriod = Period::make($availableBudget->start_date, $availableBudget->end_date, Precision::DAY()); + $newAmount = '0'; + $abPeriod = Period::make($availableBudget->start_date, $availableBudget->end_date, Precision::DAY()); Log::debug( sprintf( 'Now at AB #%d, ("%s" to "%s")', @@ -54,7 +56,7 @@ trait RecalculatesAvailableBudgetsTrait ) ); // have to recalculate everything just in case. - $set = $repository->getAllBudgetLimitsByCurrency($availableBudget->transactionCurrency, $availableBudget->start_date, $availableBudget->end_date); + $set = $repository->getAllBudgetLimitsByCurrency($availableBudget->transactionCurrency, $availableBudget->start_date, $availableBudget->end_date); Log::debug(sprintf('Found %d interesting budget limit(s).', $set->count())); /** @var BudgetLimit $budgetLimit */ @@ -69,8 +71,8 @@ trait RecalculatesAvailableBudgetsTrait ); // overlap in days: $limitPeriod = Period::make( - $budgetLimit->start_date, - $budgetLimit->end_date, + $budgetLimit->start_date, + $budgetLimit->end_date, precision : Precision::DAY(), boundaries: Boundaries::EXCLUDE_NONE() ); @@ -111,8 +113,8 @@ trait RecalculatesAvailableBudgetsTrait return '0'; } $limitPeriod = Period::make( - $budgetLimit->start_date, - $budgetLimit->end_date, + $budgetLimit->start_date, + $budgetLimit->end_date, precision : Precision::DAY(), boundaries: Boundaries::EXCLUDE_NONE() ); @@ -130,7 +132,7 @@ trait RecalculatesAvailableBudgetsTrait Log::debug(sprintf('Now in updateAvailableBudget(limit #%d)', $budgetLimit->id)); /** @var null|Budget $budget */ - $budget = Budget::find($budgetLimit->budget_id); + $budget = Budget::find($budgetLimit->budget_id); if (null === $budget) { Log::warning('Budget is null, probably deleted, find deleted version.'); @@ -145,7 +147,7 @@ trait RecalculatesAvailableBudgetsTrait } /** @var null|User $user */ - $user = $budget->user; + $user = $budget->user; // sanity check. It happens when the budget has been deleted so the original user is unknown. if (null === $user) { @@ -161,7 +163,7 @@ trait RecalculatesAvailableBudgetsTrait // all have to be created or updated. try { $viewRange = app('preferences')->getForUser($user, 'viewRange', '1M')->data; - } catch (ContainerExceptionInterface|NotFoundExceptionInterface $e) { + } catch (ContainerExceptionInterface | NotFoundExceptionInterface $e) { Log::error($e->getMessage()); $viewRange = '1M'; } @@ -169,20 +171,27 @@ trait RecalculatesAvailableBudgetsTrait if (null === $viewRange || is_array($viewRange)) { $viewRange = '1M'; } - $viewRange = (string)$viewRange; + $viewRange = (string)$viewRange; + + $start = Navigation::startOfPeriod($budgetLimit->start_date, $viewRange); + $end = Navigation::startOfPeriod($budgetLimit->end_date, $viewRange); + $end = Navigation::endOfPeriod($end, $viewRange); + if ($end < $start) { + [$start, $end] = [$end, $start]; + $budgetLimit->start_date = $start; + $budgetLimit->end_date = $end; + $budgetLimit->saveQuietly(); + } - $start = app('navigation')->startOfPeriod($budgetLimit->start_date, $viewRange); - $end = app('navigation')->startOfPeriod($budgetLimit->end_date, $viewRange); - $end = app('navigation')->endOfPeriod($end, $viewRange); // limit period in total is: $limitPeriod = Period::make($start, $end, precision: Precision::DAY(), boundaries: Boundaries::EXCLUDE_NONE()); Log::debug(sprintf('Limit period is from %s to %s', $start->format('Y-m-d'), $end->format('Y-m-d'))); // from the start until the end of the budget limit, need to loop! - $current = clone $start; + $current = clone $start; while ($current <= $end) { - $currentEnd = app('navigation')->endOfPeriod($current, $viewRange); + $currentEnd = Navigation::endOfPeriod($current, $viewRange); // create or find AB for this particular period, and set the amount accordingly. /** @var null|AvailableBudget $availableBudget */ @@ -195,9 +204,15 @@ trait RecalculatesAvailableBudgetsTrait if (null === $availableBudget) { Log::debug('No AB found, will create.'); // if not exists: - $currentPeriod = Period::make($current, $currentEnd, precision: Precision::DAY(), boundaries: Boundaries::EXCLUDE_NONE()); - $daily = $this->getDailyAmount($budgetLimit); - $amount = bcmul((string) $daily, (string)$currentPeriod->length(), 12); + try { + $currentPeriod = Period::make($current, $currentEnd, precision: Precision::DAY(), boundaries: Boundaries::EXCLUDE_NONE()); + } catch (InvalidPeriod $e) { + Log::error('Tried to make invalid period.'); + Log::error($e->getMessage()); + continue; + } + $daily = $this->getDailyAmount($budgetLimit); + $amount = bcmul((string)$daily, (string)$currentPeriod->length(), 12); // no need to calculate if period is equal. if ($currentPeriod->equals($limitPeriod)) { @@ -227,7 +242,7 @@ trait RecalculatesAvailableBudgetsTrait } // prep for next loop - $current = app('navigation')->addPeriod($current, $viewRange); + $current = Navigation::addPeriod($current, $viewRange); } } } From d08966d141d38a634ed87322ce30ed12d02c8797 Mon Sep 17 00:00:00 2001 From: James Cole Date: Wed, 26 Nov 2025 06:50:29 +0100 Subject: [PATCH 15/26] Add new correction command. --- .../Commands/Correction/CorrectsDatabase.php | 1 + .../CorrectsInvertedBudgetLimits.php | 74 +++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 app/Console/Commands/Correction/CorrectsInvertedBudgetLimits.php diff --git a/app/Console/Commands/Correction/CorrectsDatabase.php b/app/Console/Commands/Correction/CorrectsDatabase.php index 4288a4af40..8a0c416d41 100644 --- a/app/Console/Commands/Correction/CorrectsDatabase.php +++ b/app/Console/Commands/Correction/CorrectsDatabase.php @@ -74,6 +74,7 @@ class CorrectsDatabase extends Command 'correction:group-accounts', 'correction:recalculates-liabilities', 'correction:preferences', + 'correction:corrects-inverted-budget-limits', // 'correction:transaction-types', // resource heavy, disabled. 'correction:recalculate-pc-amounts', 'correction:remove-links-to-deleted-objects', diff --git a/app/Console/Commands/Correction/CorrectsInvertedBudgetLimits.php b/app/Console/Commands/Correction/CorrectsInvertedBudgetLimits.php new file mode 100644 index 0000000000..bf214ba4ab --- /dev/null +++ b/app/Console/Commands/Correction/CorrectsInvertedBudgetLimits.php @@ -0,0 +1,74 @@ +. + */ + +namespace FireflyIII\Console\Commands\Correction; + +use FireflyIII\Console\Commands\ShowsFriendlyMessages; +use FireflyIII\Models\BudgetLimit; +use Illuminate\Console\Command; +use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Log; + +class CorrectsInvertedBudgetLimits extends Command +{ + use ShowsFriendlyMessages; + + /** + * The name and signature of the console command. + * + * @var string + */ + protected $signature = 'correction:corrects-inverted-budget-limits'; + + /** + * The console command description. + * + * @var string + */ + protected $description = 'Reverse budget limits where the dates are inverted.'; + + /** + * Execute the console command. + */ + public function handle(): int + { + + $set = BudgetLimit::where('start_date', '>', DB::raw('end_date'))->get(); + if (0 === $set->count()) { + Log::debug('No inverted budget limits found.'); + return Command::SUCCESS; + } + /** @var BudgetLimit $budgetLimit */ + foreach ($set as $budgetLimit) { + $start = $budgetLimit->start_date->copy(); + $end = $budgetLimit->end_date->copy(); + $budgetLimit->start_date = $end; + $budgetLimit->end_date = $start; + $budgetLimit->saveQuietly(); + } + if (1 === $set->count()) { + $this->friendlyInfo('Corrected one budget limit to have the right start/end dates.'); + return Command::SUCCESS; + } + $this->friendlyInfo(sprintf('Corrected %d budget limits to have the right start/end dates.', count($set))); + return Command::SUCCESS; + } +} From d8bdbf28423fff8222a8220d4f3ca9a06cb36614 Mon Sep 17 00:00:00 2001 From: JC5 Date: Wed, 26 Nov 2025 06:54:11 +0100 Subject: [PATCH 16/26] =?UTF-8?q?=F0=9F=A4=96=20Auto=20commit=20for=20rele?= =?UTF-8?q?ase=20'develop'=20on=202025-11-26?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CorrectsInvertedBudgetLimits.php | 8 +- .../Commands/System/ForcesDecimalSize.php | 155 +++++++++--------- .../Controllers/Account/IndexController.php | 2 +- .../Controllers/Account/ShowController.php | 2 +- app/Support/Navigation.php | 4 +- .../RecalculatesAvailableBudgetsTrait.php | 40 ++--- app/TransactionRules/Actions/AddTag.php | 4 +- composer.lock | 118 +++++++------ config/firefly.php | 4 +- package-lock.json | 66 ++++---- 10 files changed, 207 insertions(+), 196 deletions(-) diff --git a/app/Console/Commands/Correction/CorrectsInvertedBudgetLimits.php b/app/Console/Commands/Correction/CorrectsInvertedBudgetLimits.php index bf214ba4ab..17a57b7c0b 100644 --- a/app/Console/Commands/Correction/CorrectsInvertedBudgetLimits.php +++ b/app/Console/Commands/Correction/CorrectsInvertedBudgetLimits.php @@ -1,4 +1,6 @@ ', DB::raw('end_date'))->get(); if (0 === $set->count()) { Log::debug('No inverted budget limits found.'); + return Command::SUCCESS; } + /** @var BudgetLimit $budgetLimit */ foreach ($set as $budgetLimit) { $start = $budgetLimit->start_date->copy(); @@ -66,9 +70,11 @@ class CorrectsInvertedBudgetLimits extends Command } if (1 === $set->count()) { $this->friendlyInfo('Corrected one budget limit to have the right start/end dates.'); + return Command::SUCCESS; } $this->friendlyInfo(sprintf('Corrected %d budget limits to have the right start/end dates.', count($set))); + return Command::SUCCESS; } } diff --git a/app/Console/Commands/System/ForcesDecimalSize.php b/app/Console/Commands/System/ForcesDecimalSize.php index 0a39fedf78..ec6ca7fc79 100644 --- a/app/Console/Commands/System/ForcesDecimalSize.php +++ b/app/Console/Commands/System/ForcesDecimalSize.php @@ -42,6 +42,7 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Log; + use function Safe\json_encode; use function Safe\mb_regex_encoding; @@ -54,11 +55,11 @@ class ForcesDecimalSize extends Command { use ShowsFriendlyMessages; - protected $description = 'This command resizes DECIMAL columns in MySQL or PostgreSQL and correct amounts (only MySQL).'; - protected $signature = 'firefly-iii:force-decimal-size {--force}'; + protected $description = 'This command resizes DECIMAL columns in MySQL or PostgreSQL and correct amounts (only MySQL).'; + protected $signature = 'firefly-iii:force-decimal-size {--force}'; private string $cast; private array $classes - = [ + = [ 'accounts' => Account::class, 'auto_budgets' => AutoBudget::class, 'available_budgets' => AvailableBudget::class, @@ -74,7 +75,7 @@ class ForcesDecimalSize extends Command private string $operator; private string $regularExpression; private array $tables - = [ + = [ 'accounts' => ['virtual_balance'], 'auto_budgets' => ['amount'], 'available_budgets' => ['amount'], @@ -238,9 +239,10 @@ class ForcesDecimalSize extends Command $regularExpression = $this->regularExpression; /** @var Builder $query */ - $query = Account::leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id') - ->where('account_meta.name', 'currency_id') - ->where('account_meta.data', json_encode((string)$currency->id)); + $query = Account::leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id') + ->where('account_meta.name', 'currency_id') + ->where('account_meta.data', json_encode((string)$currency->id)) + ; $query->where(static function (Builder $q) use ($fields, $currency, $operator, $cast, $regularExpression): void { foreach ($fields as $field) { $q->orWhere( @@ -250,7 +252,7 @@ class ForcesDecimalSize extends Command ); } }); - $result = $query->get(['accounts.*']); + $result = $query->get(['accounts.*']); if (0 === $result->count()) { $this->friendlyPositive(sprintf('All accounts in %s are OK', $currency->code)); @@ -261,13 +263,13 @@ class ForcesDecimalSize extends Command foreach ($result as $account) { /** @var string $field */ foreach ($fields as $field) { - $value = $account->{$field}; + $value = $account->{$field}; if (null === $value) { continue; } // fix $field by rounding it down correctly. - $pow = 10 ** $currency->decimal_places; - $correct = bcdiv((string)round($value * $pow), (string)$pow, 12); + $pow = 10 ** $currency->decimal_places; + $correct = bcdiv((string)round($value * $pow), (string)$pow, 12); $this->friendlyInfo(sprintf('Account #%d has %s with value "%s", this has been corrected to "%s".', $account->id, $field, $value, $correct)); /** @var null|Account $updateAccount */ @@ -289,7 +291,7 @@ class ForcesDecimalSize extends Command $regularExpression = $this->regularExpression; /** @var Builder $query */ - $query = $class::where('transaction_currency_id', $currency->id)->where( + $query = $class::where('transaction_currency_id', $currency->id)->where( static function (Builder $q) use ($fields, $currency, $operator, $cast, $regularExpression): void { /** @var string $field */ foreach ($fields as $field) { @@ -302,7 +304,7 @@ class ForcesDecimalSize extends Command } ); - $result = $query->get(); + $result = $query->get(); if (0 === $result->count()) { $this->friendlyPositive(sprintf('All %s in %s are OK', $table, $currency->code)); @@ -313,7 +315,7 @@ class ForcesDecimalSize extends Command foreach ($result as $item) { /** @var string $field */ foreach ($fields as $field) { - $value = $item->{$field}; + $value = $item->{$field}; if (null === $value || '' === $value) { continue; } @@ -323,7 +325,7 @@ class ForcesDecimalSize extends Command $this->friendlyWarning(sprintf('%s #%d has %s with value "%s", this has been corrected to "%s".', $table, $item->id, $field, $value, $correct)); /** @var null|Model $model */ - $model = $class::find($item->id); + $model = $class::find($item->id); $model?->update([$field => $correct]); } } @@ -339,22 +341,23 @@ class ForcesDecimalSize extends Command $regularExpression = $this->regularExpression; /** @var Builder $query */ - $query = PiggyBankEvent::leftJoin('piggy_banks', 'piggy_bank_events.piggy_bank_id', '=', 'piggy_banks.id') - ->leftJoin('accounts', 'piggy_banks.account_id', '=', 'accounts.id') - ->leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id') - ->where('account_meta.name', 'currency_id') - ->where('account_meta.data', json_encode((string)$currency->id)) - ->where(static function (Builder $q) use ($fields, $currency, $cast, $operator, $regularExpression): void { - foreach ($fields as $field) { - $q->orWhere( - DB::raw(sprintf('CAST(piggy_bank_events.%s AS %s)', $field, $cast)), - $operator, - DB::raw(sprintf($regularExpression, $currency->decimal_places)) - ); - } - }); + $query = PiggyBankEvent::leftJoin('piggy_banks', 'piggy_bank_events.piggy_bank_id', '=', 'piggy_banks.id') + ->leftJoin('accounts', 'piggy_banks.account_id', '=', 'accounts.id') + ->leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id') + ->where('account_meta.name', 'currency_id') + ->where('account_meta.data', json_encode((string)$currency->id)) + ->where(static function (Builder $q) use ($fields, $currency, $cast, $operator, $regularExpression): void { + foreach ($fields as $field) { + $q->orWhere( + DB::raw(sprintf('CAST(piggy_bank_events.%s AS %s)', $field, $cast)), + $operator, + DB::raw(sprintf($regularExpression, $currency->decimal_places)) + ); + } + }) + ; - $result = $query->get(['piggy_bank_events.*']); + $result = $query->get(['piggy_bank_events.*']); if (0 === $result->count()) { $this->friendlyPositive(sprintf('All piggy bank events in %s are OK', $currency->code)); @@ -365,7 +368,7 @@ class ForcesDecimalSize extends Command foreach ($result as $item) { /** @var string $field */ foreach ($fields as $field) { - $value = $item->{$field}; + $value = $item->{$field}; if (null === $value) { continue; } @@ -377,7 +380,7 @@ class ForcesDecimalSize extends Command ); /** @var null|PiggyBankEvent $event */ - $event = PiggyBankEvent::find($item->id); + $event = PiggyBankEvent::find($item->id); $event?->update([$field => $correct]); } } @@ -394,22 +397,23 @@ class ForcesDecimalSize extends Command // select all piggy bank repetitions with this currency and issue. /** @var Builder $query */ - $query = PiggyBankRepetition::leftJoin('piggy_banks', 'piggy_bank_repetitions.piggy_bank_id', '=', 'piggy_banks.id') - ->leftJoin('accounts', 'piggy_banks.account_id', '=', 'accounts.id') - ->leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id') - ->where('account_meta.name', 'currency_id') - ->where('account_meta.data', json_encode((string)$currency->id)) - ->where(static function (Builder $q) use ($fields, $currency, $operator, $cast, $regularExpression): void { - foreach ($fields as $field) { - $q->orWhere( - DB::raw(sprintf('CAST(piggy_bank_repetitions.%s AS %s)', $field, $cast)), - $operator, - DB::raw(sprintf($regularExpression, $currency->decimal_places)) - ); - } - }); + $query = PiggyBankRepetition::leftJoin('piggy_banks', 'piggy_bank_repetitions.piggy_bank_id', '=', 'piggy_banks.id') + ->leftJoin('accounts', 'piggy_banks.account_id', '=', 'accounts.id') + ->leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id') + ->where('account_meta.name', 'currency_id') + ->where('account_meta.data', json_encode((string)$currency->id)) + ->where(static function (Builder $q) use ($fields, $currency, $operator, $cast, $regularExpression): void { + foreach ($fields as $field) { + $q->orWhere( + DB::raw(sprintf('CAST(piggy_bank_repetitions.%s AS %s)', $field, $cast)), + $operator, + DB::raw(sprintf($regularExpression, $currency->decimal_places)) + ); + } + }) + ; - $result = $query->get(['piggy_bank_repetitions.*']); + $result = $query->get(['piggy_bank_repetitions.*']); if (0 === $result->count()) { $this->friendlyPositive(sprintf('All piggy bank repetitions in %s', $currency->code)); @@ -420,13 +424,13 @@ class ForcesDecimalSize extends Command foreach ($result as $item) { /** @var string $field */ foreach ($fields as $field) { - $value = $item->{$field}; + $value = $item->{$field}; if (null === $value) { continue; } // fix $field by rounding it down correctly. - $pow = 10 ** $currency->decimal_places; - $correct = bcdiv((string)round($value * $pow), (string)$pow, 12); + $pow = 10 ** $currency->decimal_places; + $correct = bcdiv((string)round($value * $pow), (string)$pow, 12); $this->friendlyWarning( sprintf('Piggy bank repetition #%d has %s with value "%s", this has been corrected to "%s".', $item->id, $field, $value, $correct) ); @@ -448,21 +452,22 @@ class ForcesDecimalSize extends Command $regularExpression = $this->regularExpression; /** @var Builder $query */ - $query = PiggyBank::leftJoin('accounts', 'piggy_banks.account_id', '=', 'accounts.id') - ->leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id') - ->where('account_meta.name', 'currency_id') - ->where('account_meta.data', json_encode((string)$currency->id)) - ->where(static function (Builder $q) use ($fields, $currency, $operator, $cast, $regularExpression): void { - foreach ($fields as $field) { - $q->orWhere( - DB::raw(sprintf('CAST(piggy_banks.%s AS %s)', $field, $cast)), - $operator, - DB::raw(sprintf($regularExpression, $currency->decimal_places)) - ); - } - }); + $query = PiggyBank::leftJoin('accounts', 'piggy_banks.account_id', '=', 'accounts.id') + ->leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id') + ->where('account_meta.name', 'currency_id') + ->where('account_meta.data', json_encode((string)$currency->id)) + ->where(static function (Builder $q) use ($fields, $currency, $operator, $cast, $regularExpression): void { + foreach ($fields as $field) { + $q->orWhere( + DB::raw(sprintf('CAST(piggy_banks.%s AS %s)', $field, $cast)), + $operator, + DB::raw(sprintf($regularExpression, $currency->decimal_places)) + ); + } + }) + ; - $result = $query->get(['piggy_banks.*']); + $result = $query->get(['piggy_banks.*']); if (0 === $result->count()) { $this->friendlyPositive(sprintf('All piggy banks in %s are OK', $currency->code)); @@ -473,13 +478,13 @@ class ForcesDecimalSize extends Command foreach ($result as $item) { /** @var string $field */ foreach ($fields as $field) { - $value = $item->{$field}; + $value = $item->{$field}; if (null === $value) { continue; } // fix $field by rounding it down correctly. - $pow = 10 ** $currency->decimal_places; - $correct = bcdiv((string)round($value * $pow), (string)$pow, 12); + $pow = 10 ** $currency->decimal_places; + $correct = bcdiv((string)round($value * $pow), (string)$pow, 12); $this->friendlyWarning(sprintf('Piggy bank #%d has %s with value "%s", this has been corrected to "%s".', $item->id, $field, $value, $correct)); /** @var null|PiggyBank $piggyBank */ @@ -496,7 +501,7 @@ class ForcesDecimalSize extends Command { // select all transactions with this currency and issue. /** @var Builder $query */ - $query = Transaction::where('transaction_currency_id', $currency->id)->where( + $query = Transaction::where('transaction_currency_id', $currency->id)->where( DB::raw(sprintf('CAST(amount as %s)', $this->cast)), $this->operator, DB::raw(sprintf($this->regularExpression, $currency->decimal_places)) @@ -509,13 +514,13 @@ class ForcesDecimalSize extends Command /** @var Transaction $item */ foreach ($result as $item) { - $value = $item->amount; + $value = $item->amount; if ('' === $value) { continue; } // fix $field by rounding it down correctly. - $pow = 10.0 ** $currency->decimal_places; - $correct = bcdiv((string)round((float)$value * $pow), (string)$pow, 12); + $pow = 10.0 ** $currency->decimal_places; + $correct = bcdiv((string)round((float)$value * $pow), (string)$pow, 12); $this->friendlyWarning(sprintf('Transaction #%d has amount with value "%s", this has been corrected to "%s".', $item->id, $value, $correct)); /** @var null|Transaction $transaction */ @@ -525,7 +530,7 @@ class ForcesDecimalSize extends Command // select all transactions with this FOREIGN currency and issue. /** @var Builder $query */ - $query = Transaction::where('foreign_currency_id', $currency->id)->where( + $query = Transaction::where('foreign_currency_id', $currency->id)->where( DB::raw(sprintf('CAST(foreign_amount as %s)', $this->cast)), $this->operator, DB::raw(sprintf($this->regularExpression, $currency->decimal_places)) @@ -540,13 +545,13 @@ class ForcesDecimalSize extends Command /** @var Transaction $item */ foreach ($result as $item) { - $value = $item->foreign_amount; + $value = $item->foreign_amount; if (null === $value) { continue; } // fix $field by rounding it down correctly. - $pow = 10.0 ** $currency->decimal_places; - $correct = bcdiv((string)round((float)$value * $pow), (string)$pow, 12); + $pow = 10.0 ** $currency->decimal_places; + $correct = bcdiv((string)round((float)$value * $pow), (string)$pow, 12); $this->friendlyWarning( sprintf('Transaction #%d has foreign amount with value "%s", this has been corrected to "%s".', $item->id, $value, $correct) ); diff --git a/app/Http/Controllers/Account/IndexController.php b/app/Http/Controllers/Account/IndexController.php index 174328d275..289413e8fb 100644 --- a/app/Http/Controllers/Account/IndexController.php +++ b/app/Http/Controllers/Account/IndexController.php @@ -167,7 +167,7 @@ class IndexController extends Controller /** @var Carbon $end */ $end = clone session('end', today(config('app.timezone'))->endOfMonth()); - $now = now(); + $now = now(); if ($now->gt($end) || $now->lt($start)) { $now = $end; } diff --git a/app/Http/Controllers/Account/ShowController.php b/app/Http/Controllers/Account/ShowController.php index d9f2d77f77..f495e586c8 100644 --- a/app/Http/Controllers/Account/ShowController.php +++ b/app/Http/Controllers/Account/ShowController.php @@ -221,7 +221,7 @@ class ShowController extends Controller // correct Log::debug(sprintf('showAll: Call accountsBalancesOptimized with date/time "%s"', $end->toIso8601String())); - $now = now(); + $now = now(); if ($now->gt($end) || $now->lt($start)) { $now = $end; } diff --git a/app/Support/Navigation.php b/app/Support/Navigation.php index eeaa7714e2..b2d2c76f5d 100644 --- a/app/Support/Navigation.php +++ b/app/Support/Navigation.php @@ -121,8 +121,8 @@ class Navigation if ($workEnd->gt($start)) { while ($workEnd->gt($start) && $loopCount < 20) { // make range: - $workStart = \FireflyIII\Support\Facades\Navigation::startOfPeriod($workStart, '1Y'); - $workEnd = \FireflyIII\Support\Facades\Navigation::endOfPeriod($workStart, '1Y'); + $workStart = Facades\Navigation::startOfPeriod($workStart, '1Y'); + $workEnd = Facades\Navigation::endOfPeriod($workStart, '1Y'); // make sure we don't go overboard if ($workEnd->gt($start)) { diff --git a/app/Support/Observers/RecalculatesAvailableBudgetsTrait.php b/app/Support/Observers/RecalculatesAvailableBudgetsTrait.php index 8a238e723b..2d4ee01702 100644 --- a/app/Support/Observers/RecalculatesAvailableBudgetsTrait.php +++ b/app/Support/Observers/RecalculatesAvailableBudgetsTrait.php @@ -43,10 +43,10 @@ trait RecalculatesAvailableBudgetsTrait { private function calculateAmount(AvailableBudget $availableBudget): void { - $repository = app(BudgetLimitRepositoryInterface::class); + $repository = app(BudgetLimitRepositoryInterface::class); $repository->setUser($availableBudget->user); - $newAmount = '0'; - $abPeriod = Period::make($availableBudget->start_date, $availableBudget->end_date, Precision::DAY()); + $newAmount = '0'; + $abPeriod = Period::make($availableBudget->start_date, $availableBudget->end_date, Precision::DAY()); Log::debug( sprintf( 'Now at AB #%d, ("%s" to "%s")', @@ -56,7 +56,7 @@ trait RecalculatesAvailableBudgetsTrait ) ); // have to recalculate everything just in case. - $set = $repository->getAllBudgetLimitsByCurrency($availableBudget->transactionCurrency, $availableBudget->start_date, $availableBudget->end_date); + $set = $repository->getAllBudgetLimitsByCurrency($availableBudget->transactionCurrency, $availableBudget->start_date, $availableBudget->end_date); Log::debug(sprintf('Found %d interesting budget limit(s).', $set->count())); /** @var BudgetLimit $budgetLimit */ @@ -71,8 +71,8 @@ trait RecalculatesAvailableBudgetsTrait ); // overlap in days: $limitPeriod = Period::make( - $budgetLimit->start_date, - $budgetLimit->end_date, + $budgetLimit->start_date, + $budgetLimit->end_date, precision : Precision::DAY(), boundaries: Boundaries::EXCLUDE_NONE() ); @@ -113,8 +113,8 @@ trait RecalculatesAvailableBudgetsTrait return '0'; } $limitPeriod = Period::make( - $budgetLimit->start_date, - $budgetLimit->end_date, + $budgetLimit->start_date, + $budgetLimit->end_date, precision : Precision::DAY(), boundaries: Boundaries::EXCLUDE_NONE() ); @@ -132,7 +132,7 @@ trait RecalculatesAvailableBudgetsTrait Log::debug(sprintf('Now in updateAvailableBudget(limit #%d)', $budgetLimit->id)); /** @var null|Budget $budget */ - $budget = Budget::find($budgetLimit->budget_id); + $budget = Budget::find($budgetLimit->budget_id); if (null === $budget) { Log::warning('Budget is null, probably deleted, find deleted version.'); @@ -147,7 +147,7 @@ trait RecalculatesAvailableBudgetsTrait } /** @var null|User $user */ - $user = $budget->user; + $user = $budget->user; // sanity check. It happens when the budget has been deleted so the original user is unknown. if (null === $user) { @@ -163,7 +163,7 @@ trait RecalculatesAvailableBudgetsTrait // all have to be created or updated. try { $viewRange = app('preferences')->getForUser($user, 'viewRange', '1M')->data; - } catch (ContainerExceptionInterface | NotFoundExceptionInterface $e) { + } catch (ContainerExceptionInterface|NotFoundExceptionInterface $e) { Log::error($e->getMessage()); $viewRange = '1M'; } @@ -171,13 +171,13 @@ trait RecalculatesAvailableBudgetsTrait if (null === $viewRange || is_array($viewRange)) { $viewRange = '1M'; } - $viewRange = (string)$viewRange; + $viewRange = (string)$viewRange; - $start = Navigation::startOfPeriod($budgetLimit->start_date, $viewRange); - $end = Navigation::startOfPeriod($budgetLimit->end_date, $viewRange); - $end = Navigation::endOfPeriod($end, $viewRange); + $start = Navigation::startOfPeriod($budgetLimit->start_date, $viewRange); + $end = Navigation::startOfPeriod($budgetLimit->end_date, $viewRange); + $end = Navigation::endOfPeriod($end, $viewRange); if ($end < $start) { - [$start, $end] = [$end, $start]; + [$start, $end] = [$end, $start]; $budgetLimit->start_date = $start; $budgetLimit->end_date = $end; $budgetLimit->saveQuietly(); @@ -189,9 +189,9 @@ trait RecalculatesAvailableBudgetsTrait Log::debug(sprintf('Limit period is from %s to %s', $start->format('Y-m-d'), $end->format('Y-m-d'))); // from the start until the end of the budget limit, need to loop! - $current = clone $start; + $current = clone $start; while ($current <= $end) { - $currentEnd = Navigation::endOfPeriod($current, $viewRange); + $currentEnd = Navigation::endOfPeriod($current, $viewRange); // create or find AB for this particular period, and set the amount accordingly. /** @var null|AvailableBudget $availableBudget */ @@ -203,12 +203,14 @@ trait RecalculatesAvailableBudgetsTrait } if (null === $availableBudget) { Log::debug('No AB found, will create.'); + // if not exists: try { $currentPeriod = Period::make($current, $currentEnd, precision: Precision::DAY(), boundaries: Boundaries::EXCLUDE_NONE()); } catch (InvalidPeriod $e) { Log::error('Tried to make invalid period.'); Log::error($e->getMessage()); + continue; } $daily = $this->getDailyAmount($budgetLimit); @@ -242,7 +244,7 @@ trait RecalculatesAvailableBudgetsTrait } // prep for next loop - $current = Navigation::addPeriod($current, $viewRange); + $current = Navigation::addPeriod($current, $viewRange); } } } diff --git a/app/TransactionRules/Actions/AddTag.php b/app/TransactionRules/Actions/AddTag.php index c7bcea80ee..ba07470d45 100644 --- a/app/TransactionRules/Actions/AddTag.php +++ b/app/TransactionRules/Actions/AddTag.php @@ -55,8 +55,8 @@ class AddTag implements ActionInterface $tagName = $this->action->getValue($journal); $tag = $factory->findOrCreate($tagName); - $type = $journal['transaction_type_type']; - if(TransactionTypeEnum::OPENING_BALANCE->value === $type || TransactionTypeEnum::LIABILITY_CREDIT->value === $type || TransactionTypeEnum::INVALID->value === $type) { + $type = $journal['transaction_type_type']; + if (TransactionTypeEnum::OPENING_BALANCE->value === $type || TransactionTypeEnum::LIABILITY_CREDIT->value === $type || TransactionTypeEnum::INVALID->value === $type) { // fail silently on invalid transaction types. return false; diff --git a/composer.lock b/composer.lock index 9ef7ac18d8..78730a5800 100644 --- a/composer.lock +++ b/composer.lock @@ -130,16 +130,16 @@ }, { "name": "brick/math", - "version": "0.14.0", + "version": "0.14.1", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2" + "reference": "f05858549e5f9d7bb45875a75583240a38a281d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2", - "reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2", + "url": "https://api.github.com/repos/brick/math/zipball/f05858549e5f9d7bb45875a75583240a38a281d0", + "reference": "f05858549e5f9d7bb45875a75583240a38a281d0", "shasum": "" }, "require": { @@ -178,7 +178,7 @@ ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.14.0" + "source": "https://github.com/brick/math/tree/0.14.1" }, "funding": [ { @@ -186,7 +186,7 @@ "type": "github" } ], - "time": "2025-08-29T12:40:03+00:00" + "time": "2025-11-24T14:40:29+00:00" }, { "name": "carbonphp/carbon-doctrine-types", @@ -1938,16 +1938,16 @@ }, { "name": "laravel/framework", - "version": "v12.39.0", + "version": "v12.40.1", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "1a6176129ef28eaf42b6b4a6250025120c3d8dac" + "reference": "2e986acbf9acf62cba13400bc23c4d639bf188b9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/1a6176129ef28eaf42b6b4a6250025120c3d8dac", - "reference": "1a6176129ef28eaf42b6b4a6250025120c3d8dac", + "url": "https://api.github.com/repos/laravel/framework/zipball/2e986acbf9acf62cba13400bc23c4d639bf188b9", + "reference": "2e986acbf9acf62cba13400bc23c4d639bf188b9", "shasum": "" }, "require": { @@ -2059,7 +2059,7 @@ "league/flysystem-sftp-v3": "^3.25.1", "mockery/mockery": "^1.6.10", "opis/json-schema": "^2.4.1", - "orchestra/testbench-core": "^10.7.0", + "orchestra/testbench-core": "^10.8.0", "pda/pheanstalk": "^5.0.6|^7.0.0", "php-http/discovery": "^1.15", "phpstan/phpstan": "^2.0", @@ -2153,7 +2153,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-11-18T15:16:10+00:00" + "time": "2025-11-25T16:16:33+00:00" }, { "name": "laravel/passport", @@ -2233,16 +2233,16 @@ }, { "name": "laravel/prompts", - "version": "v0.3.7", + "version": "v0.3.8", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "a1891d362714bc40c8d23b0b1d7090f022ea27cc" + "reference": "096748cdfb81988f60090bbb839ce3205ace0d35" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/a1891d362714bc40c8d23b0b1d7090f022ea27cc", - "reference": "a1891d362714bc40c8d23b0b1d7090f022ea27cc", + "url": "https://api.github.com/repos/laravel/prompts/zipball/096748cdfb81988f60090bbb839ce3205ace0d35", + "reference": "096748cdfb81988f60090bbb839ce3205ace0d35", "shasum": "" }, "require": { @@ -2258,7 +2258,7 @@ "require-dev": { "illuminate/collections": "^10.0|^11.0|^12.0", "mockery/mockery": "^1.5", - "pestphp/pest": "^2.3|^3.4", + "pestphp/pest": "^2.3|^3.4|^4.0", "phpstan/phpstan": "^1.12.28", "phpstan/phpstan-mockery": "^1.1.3" }, @@ -2286,22 +2286,22 @@ "description": "Add beautiful and user-friendly forms to your command-line applications.", "support": { "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.3.7" + "source": "https://github.com/laravel/prompts/tree/v0.3.8" }, - "time": "2025-09-19T13:47:56+00:00" + "time": "2025-11-21T20:52:52+00:00" }, { "name": "laravel/sanctum", - "version": "v4.2.0", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/laravel/sanctum.git", - "reference": "fd6df4f79f48a72992e8d29a9c0ee25422a0d677" + "reference": "f5fb373be39a246c74a060f2cf2ae2c2145b3664" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sanctum/zipball/fd6df4f79f48a72992e8d29a9c0ee25422a0d677", - "reference": "fd6df4f79f48a72992e8d29a9c0ee25422a0d677", + "url": "https://api.github.com/repos/laravel/sanctum/zipball/f5fb373be39a246c74a060f2cf2ae2c2145b3664", + "reference": "f5fb373be39a246c74a060f2cf2ae2c2145b3664", "shasum": "" }, "require": { @@ -2315,9 +2315,8 @@ }, "require-dev": { "mockery/mockery": "^1.6", - "orchestra/testbench": "^9.0|^10.0", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^11.3" + "orchestra/testbench": "^9.15|^10.8", + "phpstan/phpstan": "^1.10" }, "type": "library", "extra": { @@ -2352,20 +2351,20 @@ "issues": "https://github.com/laravel/sanctum/issues", "source": "https://github.com/laravel/sanctum" }, - "time": "2025-07-09T19:45:24+00:00" + "time": "2025-11-21T13:59:03+00:00" }, { "name": "laravel/serializable-closure", - "version": "v2.0.6", + "version": "v2.0.7", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", - "reference": "038ce42edee619599a1debb7e81d7b3759492819" + "reference": "cb291e4c998ac50637c7eeb58189c14f5de5b9dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/038ce42edee619599a1debb7e81d7b3759492819", - "reference": "038ce42edee619599a1debb7e81d7b3759492819", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/cb291e4c998ac50637c7eeb58189c14f5de5b9dd", + "reference": "cb291e4c998ac50637c7eeb58189c14f5de5b9dd", "shasum": "" }, "require": { @@ -2374,7 +2373,7 @@ "require-dev": { "illuminate/support": "^10.0|^11.0|^12.0", "nesbot/carbon": "^2.67|^3.0", - "pestphp/pest": "^2.36|^3.0", + "pestphp/pest": "^2.36|^3.0|^4.0", "phpstan/phpstan": "^2.0", "symfony/var-dumper": "^6.2.0|^7.0.0" }, @@ -2413,20 +2412,20 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2025-10-09T13:42:30+00:00" + "time": "2025-11-21T20:52:36+00:00" }, { "name": "laravel/slack-notification-channel", - "version": "v3.6.0", + "version": "v3.7.0", "source": { "type": "git", "url": "https://github.com/laravel/slack-notification-channel.git", - "reference": "642677a57490eebccb7e9fb666f5a5379c6e3459" + "reference": "414aec57b487bfbac7f90fc30f50a2f0a2df4caa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/slack-notification-channel/zipball/642677a57490eebccb7e9fb666f5a5379c6e3459", - "reference": "642677a57490eebccb7e9fb666f5a5379c6e3459", + "url": "https://api.github.com/repos/laravel/slack-notification-channel/zipball/414aec57b487bfbac7f90fc30f50a2f0a2df4caa", + "reference": "414aec57b487bfbac7f90fc30f50a2f0a2df4caa", "shasum": "" }, "require": { @@ -2476,9 +2475,9 @@ ], "support": { "issues": "https://github.com/laravel/slack-notification-channel/issues", - "source": "https://github.com/laravel/slack-notification-channel/tree/v3.6.0" + "source": "https://github.com/laravel/slack-notification-channel/tree/v3.7.0" }, - "time": "2025-06-26T16:51:38+00:00" + "time": "2025-11-20T17:26:07+00:00" }, { "name": "laravel/ui", @@ -3544,22 +3543,22 @@ }, { "name": "mailersend/laravel-driver", - "version": "v2.9.1", + "version": "v2.12.0", "source": { "type": "git", "url": "https://github.com/mailersend/mailersend-laravel-driver.git", - "reference": "87fd5ab76808bbaac9221be0d306baef13e98725" + "reference": "15e1ec41e29e65d3ca226929c65804190aaa93eb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mailersend/mailersend-laravel-driver/zipball/87fd5ab76808bbaac9221be0d306baef13e98725", - "reference": "87fd5ab76808bbaac9221be0d306baef13e98725", + "url": "https://api.github.com/repos/mailersend/mailersend-laravel-driver/zipball/15e1ec41e29e65d3ca226929c65804190aaa93eb", + "reference": "15e1ec41e29e65d3ca226929c65804190aaa93eb", "shasum": "" }, "require": { "ext-json": "*", "illuminate/support": "^9.0 || ^10.0 || ^11.0 || ^12.0", - "mailersend/mailersend": "^0.31.0", + "mailersend/mailersend": "^0.35.0", "nyholm/psr7": "^1.5", "php": ">=8.0", "php-http/guzzle7-adapter": "^1.0", @@ -3607,29 +3606,28 @@ ], "support": { "issues": "https://github.com/mailersend/mailersend-laravel-driver/issues", - "source": "https://github.com/mailersend/mailersend-laravel-driver/tree/v2.9.1" + "source": "https://github.com/mailersend/mailersend-laravel-driver/tree/v2.12.0" }, - "time": "2025-04-09T09:33:07+00:00" + "time": "2025-10-28T14:59:16+00:00" }, { "name": "mailersend/mailersend", - "version": "v0.31.0", + "version": "v0.35.0", "source": { "type": "git", "url": "https://github.com/mailersend/mailersend-php.git", - "reference": "513ff83ee768526055ad52987cde401ea7218c67" + "reference": "f1696cf9e727e9503fbc5882d2a111bd966ad276" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mailersend/mailersend-php/zipball/513ff83ee768526055ad52987cde401ea7218c67", - "reference": "513ff83ee768526055ad52987cde401ea7218c67", + "url": "https://api.github.com/repos/mailersend/mailersend-php/zipball/f1696cf9e727e9503fbc5882d2a111bd966ad276", + "reference": "f1696cf9e727e9503fbc5882d2a111bd966ad276", "shasum": "" }, "require": { "beberlei/assert": "^3.2", "ext-json": "*", - "illuminate/collections": "^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0", - "php": "^7.4|^8.0", + "php": "^7.4 || ^8.0 <8.5", "php-http/client-common": "^2.2", "php-http/discovery": "^1.9", "php-http/httplug": "^2.1", @@ -3674,9 +3672,9 @@ ], "support": { "issues": "https://github.com/mailersend/mailersend-php/issues", - "source": "https://github.com/mailersend/mailersend-php/tree/v0.31.0" + "source": "https://github.com/mailersend/mailersend-php/tree/v0.35.0" }, - "time": "2025-04-03T12:16:11+00:00" + "time": "2025-10-28T13:11:43+00:00" }, { "name": "monolog/monolog", @@ -5181,16 +5179,16 @@ }, { "name": "predis/predis", - "version": "v3.2.0", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/predis/predis.git", - "reference": "9e9deec4dfd3ebf65d32eb368f498c646ba2ecd8" + "reference": "153097374b39a2f737fe700ebcd725642526cdec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/predis/predis/zipball/9e9deec4dfd3ebf65d32eb368f498c646ba2ecd8", - "reference": "9e9deec4dfd3ebf65d32eb368f498c646ba2ecd8", + "url": "https://api.github.com/repos/predis/predis/zipball/153097374b39a2f737fe700ebcd725642526cdec", + "reference": "153097374b39a2f737fe700ebcd725642526cdec", "shasum": "" }, "require": { @@ -5232,7 +5230,7 @@ ], "support": { "issues": "https://github.com/predis/predis/issues", - "source": "https://github.com/predis/predis/tree/v3.2.0" + "source": "https://github.com/predis/predis/tree/v3.3.0" }, "funding": [ { @@ -5240,7 +5238,7 @@ "type": "github" } ], - "time": "2025-08-06T06:41:24+00:00" + "time": "2025-11-24T17:48:50+00:00" }, { "name": "psr/cache", diff --git a/config/firefly.php b/config/firefly.php index a8151ad390..b372972378 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -78,8 +78,8 @@ return [ 'running_balance_column' => env('USE_RUNNING_BALANCE', false), // see cer.php for exchange rates feature flag. ], -'version' => 'develop/2025-11-24', -'build_time' => 1763955176, + 'version' => 'develop/2025-11-26', + 'build_time' => 1764136346, 'api_version' => '2.1.0', // field is no longer used. 'db_version' => 28, // field is no longer used. diff --git a/package-lock.json b/package-lock.json index 42c12bdcad..c34128d7a8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3291,42 +3291,42 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.5.24", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.24.tgz", - "integrity": "sha512-eDl5H57AOpNakGNAkFDH+y7kTqrQpJkZFXhWZQGyx/5Wh7B1uQYvcWkvZi11BDhscPgj8N7XV3oRwiPnx1Vrig==", + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.25.tgz", + "integrity": "sha512-vay5/oQJdsNHmliWoZfHPoVZZRmnSWhug0BYT34njkYTPqClh3DNWLkZNJBVSjsNMrg0CCrBfoKkjZQPM/QVUw==", "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.28.5", - "@vue/shared": "3.5.24", + "@vue/shared": "3.5.25", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "node_modules/@vue/compiler-dom": { - "version": "3.5.24", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.24.tgz", - "integrity": "sha512-1QHGAvs53gXkWdd3ZMGYuvQFXHW4ksKWPG8HP8/2BscrbZ0brw183q2oNWjMrSWImYLHxHrx1ItBQr50I/q2zw==", + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.25.tgz", + "integrity": "sha512-4We0OAcMZsKgYoGlMjzYvaoErltdFI2/25wqanuTu+S4gismOTRTBPi4IASOjxWdzIwrYSjnqONfKvuqkXzE2Q==", "dev": true, "license": "MIT", "dependencies": { - "@vue/compiler-core": "3.5.24", - "@vue/shared": "3.5.24" + "@vue/compiler-core": "3.5.25", + "@vue/shared": "3.5.25" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.5.24", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.24.tgz", - "integrity": "sha512-8EG5YPRgmTB+YxYBM3VXy8zHD9SWHUJLIGPhDovo3Z8VOgvP+O7UP5vl0J4BBPWYD9vxtBabzW1EuEZ+Cqs14g==", + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.25.tgz", + "integrity": "sha512-PUgKp2rn8fFsI++lF2sO7gwO2d9Yj57Utr5yEsDf3GNaQcowCLKL7sf+LvVFvtJDXUp/03+dC6f2+LCv5aK1ag==", "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.28.5", - "@vue/compiler-core": "3.5.24", - "@vue/compiler-dom": "3.5.24", - "@vue/compiler-ssr": "3.5.24", - "@vue/shared": "3.5.24", + "@vue/compiler-core": "3.5.25", + "@vue/compiler-dom": "3.5.25", + "@vue/compiler-ssr": "3.5.25", + "@vue/shared": "3.5.25", "estree-walker": "^2.0.2", "magic-string": "^0.30.21", "postcss": "^8.5.6", @@ -3334,14 +3334,14 @@ } }, "node_modules/@vue/compiler-ssr": { - "version": "3.5.24", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.24.tgz", - "integrity": "sha512-trOvMWNBMQ/odMRHW7Ae1CdfYx+7MuiQu62Jtu36gMLXcaoqKvAyh+P73sYG9ll+6jLB6QPovqoKGGZROzkFFg==", + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.25.tgz", + "integrity": "sha512-ritPSKLBcParnsKYi+GNtbdbrIE1mtuFEJ4U1sWeuOMlIziK5GtOL85t5RhsNy4uWIXPgk+OUdpnXiTdzn8o3A==", "dev": true, "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.24", - "@vue/shared": "3.5.24" + "@vue/compiler-dom": "3.5.25", + "@vue/shared": "3.5.25" } }, "node_modules/@vue/component-compiler-utils": { @@ -3423,9 +3423,9 @@ "license": "MIT" }, "node_modules/@vue/shared": { - "version": "3.5.24", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.24.tgz", - "integrity": "sha512-9cwHL2EsJBdi8NY22pngYYWzkTDhld6fAD6jlaeloNGciNSJL6bLpbxVgXl96X00Jtc6YWQv96YA/0sxex/k1A==", + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.25.tgz", + "integrity": "sha512-AbOPdQQnAnzs58H2FrrDxYj/TJfmeS2jdfEEhgiKINy+bnOANmVizIEgq1r+C5zsbs6l1CCQxtcj71rwNQ4jWg==", "dev": true, "license": "MIT" }, @@ -4521,9 +4521,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001756", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001756.tgz", - "integrity": "sha512-4HnCNKbMLkLdhJz3TToeVWHSnfJvPaq6vu/eRP0Ahub/07n484XHhBF5AJoSGHdVrS8tKFauUQz8Bp9P7LVx7A==", + "version": "1.0.30001757", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001757.tgz", + "integrity": "sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ==", "dev": true, "funding": [ { @@ -5736,9 +5736,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.259", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.259.tgz", - "integrity": "sha512-I+oLXgpEJzD6Cwuwt1gYjxsDmu/S/Kd41mmLA3O+/uH2pFRO/DvOjUyGozL8j3KeLV6WyZ7ssPwELMsXCcsJAQ==", + "version": "1.5.260", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.260.tgz", + "integrity": "sha512-ov8rBoOBhVawpzdre+Cmz4FB+y66Eqrk6Gwqd8NGxuhv99GQ8XqMAr351KEkOt7gukXWDg6gJWEMKgL2RLMPtA==", "dev": true, "license": "ISC" }, @@ -8400,9 +8400,9 @@ } }, "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.2.tgz", + "integrity": "sha512-6xKiQ+cph9KImrRh0VsjH2d8/GXA4FIMlgU4B757iI1ApvcyA9VlouP0yZJha01V+huImO+kKMU7ih+2+E14fw==", "dev": true, "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { From 7abd30f4dd5daa5dfcec8f478dc8af3f88153b2b Mon Sep 17 00:00:00 2001 From: James Cole Date: Wed, 26 Nov 2025 18:35:56 +0100 Subject: [PATCH 17/26] Attempted fix with sanity check for #11284 --- app/Support/Navigation.php | 142 +++++++++++------- .../RecalculatesAvailableBudgetsTrait.php | 14 +- 2 files changed, 90 insertions(+), 66 deletions(-) diff --git a/app/Support/Navigation.php b/app/Support/Navigation.php index b2d2c76f5d..52eaf56fb0 100644 --- a/app/Support/Navigation.php +++ b/app/Support/Navigation.php @@ -77,10 +77,10 @@ class Navigation if (!array_key_exists($repeatFreq, $functionMap)) { Log::error(sprintf( - 'The periodicity %s is unknown. Choose one of available periodicity: %s', - $repeatFreq, - implode(', ', array_keys($functionMap)) - )); + 'The periodicity %s is unknown. Choose one of available periodicity: %s', + $repeatFreq, + implode(', ', array_keys($functionMap)) + )); return $theDate; } @@ -93,7 +93,7 @@ class Navigation if ($end < $start) { [$start, $end] = [$end, $start]; } - $periods = []; + $periods = []; // first, 13 periods of [range] $loopCount = 0; $loopDate = clone $end; @@ -151,13 +151,13 @@ class Navigation public function diffInPeriods(string $period, int $skip, Carbon $beginning, Carbon $end): int { Log::debug(sprintf( - 'diffInPeriods: %s (skip: %d), between %s and %s.', - $period, - $skip, - $beginning->format('Y-m-d'), - $end->format('Y-m-d') - )); - $map = [ + 'diffInPeriods: %s (skip: %d), between %s and %s.', + $period, + $skip, + $beginning->format('Y-m-d'), + $end->format('Y-m-d') + )); + $map = [ 'daily' => 'diffInDays', 'weekly' => 'diffInWeeks', 'monthly' => 'diffInMonths', @@ -170,7 +170,7 @@ class Navigation return 1; } - $func = $map[$period]; + $func = $map[$period]; // first do the diff $floatDiff = $beginning->{$func}($end, true); // @phpstan-ignore-line @@ -185,7 +185,7 @@ class Navigation } // then do ceil() - $diff = ceil($floatDiff); + $diff = ceil($floatDiff); Log::debug(sprintf('Diff is %f periods (%d rounded up)', $floatDiff, $diff)); @@ -193,11 +193,11 @@ class Navigation $parameter = $skip + 1; $diff = ceil($diff / $parameter) * $parameter; Log::debug(sprintf( - 'diffInPeriods: skip is %d, so param is %d, and diff becomes %d', - $skip, - $parameter, - $diff - )); + 'diffInPeriods: skip is %d, so param is %d, and diff becomes %d', + $skip, + $parameter, + $diff + )); } return (int)$diff; @@ -205,7 +205,7 @@ class Navigation public function endOfPeriod(Carbon $end, string $repeatFreq): Carbon { - $currentEnd = clone $end; + $currentEnd = clone $end; // Log::debug(sprintf('Now in endOfPeriod("%s", "%s").', $currentEnd->toIso8601String(), $repeatFreq)); $functionMap = [ @@ -239,7 +239,7 @@ class Navigation Log::debug('Session data available.'); /** @var Carbon $tStart */ - $tStart = session('start', today(config('app.timezone'))->startOfMonth()); + $tStart = session('start', today(config('app.timezone'))->startOfMonth()); /** @var Carbon $tEnd */ $tEnd = session('end', today(config('app.timezone'))->endOfMonth()); @@ -248,18 +248,32 @@ class Navigation Log::debug(sprintf('Diff in days is %d', $diffInDays)); $currentEnd->addDays($diffInDays); + // add sanity check. + if ($currentEnd->lt($end)) { + throw new FireflyException(sprintf('[a] endOfPeriod(%s, %s) failed, because it resulted in %s.', $end->toW3cString(), $repeatFreq, $currentEnd->toW3cString())); + } + return $currentEnd; } if ('MTD' === $repeatFreq) { $today = today(); if ($today->isSameMonth($end)) { - return $today->endOfDay()->milli(0); + $res = $today->endOfDay()->milli(0); + // add sanity check. + if($res->lt($end)) { + throw new FireflyException(sprintf('[b] endOfPeriod(%s, %s) failed, because it resulted in %s.', $end->toW3cString(), $repeatFreq, $res->toW3cString())); + } + return $res; } + // add sanity check. + if ($currentEnd->lt($end)) { + throw new FireflyException(sprintf('[c] endOfPeriod(%s, %s) failed, because it resulted in %s.', $end->toW3cString(), $repeatFreq, $currentEnd->toW3cString())); + } return $end->endOfMonth(); } - $result = match ($repeatFreq) { + $result = match ($repeatFreq) { 'last7' => $currentEnd->addDays(7)->startOfDay(), 'last30' => $currentEnd->addDays(30)->startOfDay(), 'last90' => $currentEnd->addDays(90)->startOfDay(), @@ -270,6 +284,11 @@ class Navigation default => null, }; if (null !== $result) { + // add sanity check. + if ($currentEnd->lt($end)) { + throw new FireflyException(sprintf('[d] endOfPeriod(%s, %s) failed, because it resulted in %s.', $end->toW3cString(), $repeatFreq, $currentEnd->toW3cString())); + } + return $result; } unset($result); @@ -277,9 +296,14 @@ class Navigation if (!array_key_exists($repeatFreq, $functionMap)) { Log::error(sprintf('Cannot do endOfPeriod for $repeat_freq "%s"', $repeatFreq)); + // add sanity check. + if ($currentEnd->lt($end)) { + throw new FireflyException(sprintf('[e] endOfPeriod(%s, %s) failed, because it resulted in %s.', $end->toW3cString(), $repeatFreq, $currentEnd->toW3cString())); + } + return $end; } - $function = $functionMap[$repeatFreq]; + $function = $functionMap[$repeatFreq]; if (array_key_exists($repeatFreq, $modifierMap)) { $currentEnd->{$function}($modifierMap[$repeatFreq])->milli(0); // @phpstan-ignore-line @@ -288,6 +312,11 @@ class Navigation } $currentEnd->endOfDay()->milli(0); + // add sanity check. + if ($currentEnd->lt($end)) { + throw new FireflyException(sprintf('[f] endOfPeriod(%s, %s) failed, because it resulted in %s.', $end->toW3cString(), $repeatFreq, $currentEnd->toW3cString())); + } + return $currentEnd; } $currentEnd->{$function}(); // @phpstan-ignore-line @@ -297,6 +326,11 @@ class Navigation } // Log::debug(sprintf('Final result: %s', $currentEnd->toIso8601String())); + // add sanity check. + if ($currentEnd->lt($end)) { + throw new FireflyException(sprintf('[g] endOfPeriod(%s, %s) failed, because it resulted in %s.', $end->toW3cString(), $repeatFreq, $currentEnd->toW3cString())); + } + return $currentEnd; } @@ -319,7 +353,7 @@ class Navigation 'yearly' => 'endOfYear', ]; - $currentEnd = clone $theCurrentEnd; + $currentEnd = clone $theCurrentEnd; if (array_key_exists($repeatFreq, $functionMap)) { $function = $functionMap[$repeatFreq]; @@ -362,7 +396,7 @@ class Navigation */ public function listOfPeriods(Carbon $start, Carbon $end): array { - $locale = app('steam')->getLocale(); + $locale = app('steam')->getLocale(); // define period to increment $increment = 'addDay'; $format = $this->preferredCarbonFormat($start, $end); @@ -379,8 +413,8 @@ class Navigation $increment = 'addYear'; $displayFormat = (string)trans('config.year_js'); } - $begin = clone $start; - $entries = []; + $begin = clone $start; + $entries = []; while ($begin < $end) { $formatted = $begin->format($format); $displayed = $begin->isoFormat($displayFormat); @@ -413,26 +447,26 @@ class Navigation { $date = clone $theDate; $formatMap = [ - '1D' => (string)trans('config.specific_day_js'), - 'daily' => (string)trans('config.specific_day_js'), - 'custom' => (string)trans('config.specific_day_js'), - '1W' => (string)trans('config.week_in_year_js'), - 'week' => (string)trans('config.week_in_year_js'), - 'weekly' => (string)trans('config.week_in_year_js'), - '1M' => (string)trans('config.month_js'), - 'MTD' => (string)trans('config.month_js'), - 'month' => (string)trans('config.month_js'), - 'monthly' => (string)trans('config.month_js'), - '1Y' => (string)trans('config.year_js'), - 'YTD' => (string)trans('config.year_js'), - 'year' => (string)trans('config.year_js'), - 'yearly' => (string)trans('config.year_js'), - '6M' => (string)trans('config.half_year_js'), - 'last7' => (string)trans('config.specific_day_js'), - 'last30' => (string)trans('config.month_js'), - 'last90' => (string)trans('config.month_js'), - 'last365' => (string)trans('config.year_js'), - 'QTD' => (string)trans('config.month_js'), + '1D' => (string)trans('config.specific_day_js'), + 'daily' => (string)trans('config.specific_day_js'), + 'custom' => (string)trans('config.specific_day_js'), + '1W' => (string)trans('config.week_in_year_js'), + 'week' => (string)trans('config.week_in_year_js'), + 'weekly' => (string)trans('config.week_in_year_js'), + '1M' => (string)trans('config.month_js'), + 'MTD' => (string)trans('config.month_js'), + 'month' => (string)trans('config.month_js'), + 'monthly' => (string)trans('config.month_js'), + '1Y' => (string)trans('config.year_js'), + 'YTD' => (string)trans('config.year_js'), + 'year' => (string)trans('config.year_js'), + 'yearly' => (string)trans('config.year_js'), + '6M' => (string)trans('config.half_year_js'), + 'last7' => (string)trans('config.specific_day_js'), + 'last30' => (string)trans('config.month_js'), + 'last90' => (string)trans('config.month_js'), + 'last365' => (string)trans('config.year_js'), + 'QTD' => (string)trans('config.month_js'), ]; if (array_key_exists($repeatFrequency, $formatMap)) { @@ -563,9 +597,9 @@ class Navigation public function startOfPeriod(Carbon $theDate, string $repeatFreq): Carbon { - $date = clone $theDate; + $date = clone $theDate; // Log::debug(sprintf('Now in startOfPeriod("%s", "%s")', $date->toIso8601String(), $repeatFreq)); - $functionMap = [ + $functionMap = [ '1D' => 'startOfDay', 'daily' => 'startOfDay', '1W' => 'startOfWeek', @@ -612,7 +646,7 @@ class Navigation return $date; } - $result = match ($repeatFreq) { + $result = match ($repeatFreq) { 'last7' => $date->subDays(7)->startOfDay(), 'last30' => $date->subDays(30)->startOfDay(), 'last90' => $date->subDays(90)->startOfDay(), @@ -644,7 +678,7 @@ class Navigation public function subtractPeriod(Carbon $theDate, string $repeatFreq, ?int $subtract = null): Carbon { $subtract ??= 1; - $date = clone $theDate; + $date = clone $theDate; // 1D 1W 1M 3M 6M 1Y $functionMap = [ '1D' => 'subDays', @@ -683,7 +717,7 @@ class Navigation // this is then subtracted from $theDate (* $subtract). if ('custom' === $repeatFreq) { /** @var Carbon $tStart */ - $tStart = session('start', today(config('app.timezone'))->startOfMonth()); + $tStart = session('start', today(config('app.timezone'))->startOfMonth()); /** @var Carbon $tEnd */ $tEnd = session('end', today(config('app.timezone'))->endOfMonth()); @@ -777,7 +811,7 @@ class Navigation return $fiscalHelper->endOfFiscalYear($end); } - $list = [ + $list = [ 'last7', 'last30', 'last90', diff --git a/app/Support/Observers/RecalculatesAvailableBudgetsTrait.php b/app/Support/Observers/RecalculatesAvailableBudgetsTrait.php index 2d4ee01702..58f40b85a4 100644 --- a/app/Support/Observers/RecalculatesAvailableBudgetsTrait.php +++ b/app/Support/Observers/RecalculatesAvailableBudgetsTrait.php @@ -201,18 +201,8 @@ trait RecalculatesAvailableBudgetsTrait Log::debug('Found 1 AB, will update.'); $this->calculateAmount($availableBudget); } - if (null === $availableBudget) { - Log::debug('No AB found, will create.'); - - // if not exists: - try { - $currentPeriod = Period::make($current, $currentEnd, precision: Precision::DAY(), boundaries: Boundaries::EXCLUDE_NONE()); - } catch (InvalidPeriod $e) { - Log::error('Tried to make invalid period.'); - Log::error($e->getMessage()); - - continue; - } + if (null === $availableBudget && $currentEnd->gte($current)) { + $currentPeriod = Period::make($current, $currentEnd, precision: Precision::DAY(), boundaries: Boundaries::EXCLUDE_NONE()); $daily = $this->getDailyAmount($budgetLimit); $amount = bcmul((string)$daily, (string)$currentPeriod->length(), 12); From 3603ef1cc767aff4cf44a41b8b2a6242e3a78336 Mon Sep 17 00:00:00 2001 From: James Cole Date: Wed, 26 Nov 2025 18:39:05 +0100 Subject: [PATCH 18/26] Fix #11288 --- app/Http/Controllers/PiggyBank/CreateController.php | 3 +++ resources/views/piggy-banks/create.twig | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/PiggyBank/CreateController.php b/app/Http/Controllers/PiggyBank/CreateController.php index d58962bf84..9f0e3ea21b 100644 --- a/app/Http/Controllers/PiggyBank/CreateController.php +++ b/app/Http/Controllers/PiggyBank/CreateController.php @@ -75,6 +75,9 @@ class CreateController extends Controller $subTitleIcon = 'fa-plus'; $request->old('_token'); $preFilled = $request->old(); + if(!array_key_exists('transaction_currency_id', $preFilled)) { + $preFilled['transaction_currency_id'] = $this->primaryCurrency->id; + } // put previous url in session if not redirect from store (not "create another"). if (true !== session('piggy-banks.create.fromStore')) { diff --git a/resources/views/piggy-banks/create.twig b/resources/views/piggy-banks/create.twig index 9171a49fc7..6e1a81ae0a 100644 --- a/resources/views/piggy-banks/create.twig +++ b/resources/views/piggy-banks/create.twig @@ -17,7 +17,7 @@
{{ ExpandedForm.text('name') }} {{ ExpandedForm.amountNoCurrency('target_amount') }} - {{ CurrencyForm.currencyList('transaction_currency_id', null, {helpText:'piggy_default_currency'|_}) }} + {{ CurrencyForm.currencyList('transaction_currency_id', preFilled.transaction_currency_id, {helpText:'piggy_default_currency'|_}) }} {{ AccountForm.assetLiabilityMultiAccountList('accounts', preFilled.accounts, {label: 'saveOnAccounts'|_, helpText: 'piggy_account_currency_match'|_ }) }}
From 8722d264dc51f4e3b868b82ba40ecd098b3fbf5c Mon Sep 17 00:00:00 2001 From: JC5 Date: Wed, 26 Nov 2025 18:43:50 +0100 Subject: [PATCH 19/26] =?UTF-8?q?=F0=9F=A4=96=20Auto=20commit=20for=20rele?= =?UTF-8?q?ase=20'develop'=20on=202025-11-26?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PiggyBank/CreateController.php | 2 +- app/Support/Navigation.php | 70 ++++++++++--------- .../RecalculatesAvailableBudgetsTrait.php | 5 +- config/firefly.php | 2 +- 4 files changed, 40 insertions(+), 39 deletions(-) diff --git a/app/Http/Controllers/PiggyBank/CreateController.php b/app/Http/Controllers/PiggyBank/CreateController.php index 9f0e3ea21b..6cf391dd4a 100644 --- a/app/Http/Controllers/PiggyBank/CreateController.php +++ b/app/Http/Controllers/PiggyBank/CreateController.php @@ -75,7 +75,7 @@ class CreateController extends Controller $subTitleIcon = 'fa-plus'; $request->old('_token'); $preFilled = $request->old(); - if(!array_key_exists('transaction_currency_id', $preFilled)) { + if (!array_key_exists('transaction_currency_id', $preFilled)) { $preFilled['transaction_currency_id'] = $this->primaryCurrency->id; } diff --git a/app/Support/Navigation.php b/app/Support/Navigation.php index 52eaf56fb0..585ba925b8 100644 --- a/app/Support/Navigation.php +++ b/app/Support/Navigation.php @@ -77,10 +77,10 @@ class Navigation if (!array_key_exists($repeatFreq, $functionMap)) { Log::error(sprintf( - 'The periodicity %s is unknown. Choose one of available periodicity: %s', - $repeatFreq, - implode(', ', array_keys($functionMap)) - )); + 'The periodicity %s is unknown. Choose one of available periodicity: %s', + $repeatFreq, + implode(', ', array_keys($functionMap)) + )); return $theDate; } @@ -93,7 +93,7 @@ class Navigation if ($end < $start) { [$start, $end] = [$end, $start]; } - $periods = []; + $periods = []; // first, 13 periods of [range] $loopCount = 0; $loopDate = clone $end; @@ -151,13 +151,13 @@ class Navigation public function diffInPeriods(string $period, int $skip, Carbon $beginning, Carbon $end): int { Log::debug(sprintf( - 'diffInPeriods: %s (skip: %d), between %s and %s.', - $period, - $skip, - $beginning->format('Y-m-d'), - $end->format('Y-m-d') - )); - $map = [ + 'diffInPeriods: %s (skip: %d), between %s and %s.', + $period, + $skip, + $beginning->format('Y-m-d'), + $end->format('Y-m-d') + )); + $map = [ 'daily' => 'diffInDays', 'weekly' => 'diffInWeeks', 'monthly' => 'diffInMonths', @@ -170,7 +170,7 @@ class Navigation return 1; } - $func = $map[$period]; + $func = $map[$period]; // first do the diff $floatDiff = $beginning->{$func}($end, true); // @phpstan-ignore-line @@ -185,7 +185,7 @@ class Navigation } // then do ceil() - $diff = ceil($floatDiff); + $diff = ceil($floatDiff); Log::debug(sprintf('Diff is %f periods (%d rounded up)', $floatDiff, $diff)); @@ -193,11 +193,11 @@ class Navigation $parameter = $skip + 1; $diff = ceil($diff / $parameter) * $parameter; Log::debug(sprintf( - 'diffInPeriods: skip is %d, so param is %d, and diff becomes %d', - $skip, - $parameter, - $diff - )); + 'diffInPeriods: skip is %d, so param is %d, and diff becomes %d', + $skip, + $parameter, + $diff + )); } return (int)$diff; @@ -205,7 +205,7 @@ class Navigation public function endOfPeriod(Carbon $end, string $repeatFreq): Carbon { - $currentEnd = clone $end; + $currentEnd = clone $end; // Log::debug(sprintf('Now in endOfPeriod("%s", "%s").', $currentEnd->toIso8601String(), $repeatFreq)); $functionMap = [ @@ -239,7 +239,7 @@ class Navigation Log::debug('Session data available.'); /** @var Carbon $tStart */ - $tStart = session('start', today(config('app.timezone'))->startOfMonth()); + $tStart = session('start', today(config('app.timezone'))->startOfMonth()); /** @var Carbon $tEnd */ $tEnd = session('end', today(config('app.timezone'))->endOfMonth()); @@ -260,9 +260,10 @@ class Navigation if ($today->isSameMonth($end)) { $res = $today->endOfDay()->milli(0); // add sanity check. - if($res->lt($end)) { + if ($res->lt($end)) { throw new FireflyException(sprintf('[b] endOfPeriod(%s, %s) failed, because it resulted in %s.', $end->toW3cString(), $repeatFreq, $res->toW3cString())); } + return $res; } @@ -270,10 +271,11 @@ class Navigation if ($currentEnd->lt($end)) { throw new FireflyException(sprintf('[c] endOfPeriod(%s, %s) failed, because it resulted in %s.', $end->toW3cString(), $repeatFreq, $currentEnd->toW3cString())); } + return $end->endOfMonth(); } - $result = match ($repeatFreq) { + $result = match ($repeatFreq) { 'last7' => $currentEnd->addDays(7)->startOfDay(), 'last30' => $currentEnd->addDays(30)->startOfDay(), 'last90' => $currentEnd->addDays(90)->startOfDay(), @@ -303,7 +305,7 @@ class Navigation return $end; } - $function = $functionMap[$repeatFreq]; + $function = $functionMap[$repeatFreq]; if (array_key_exists($repeatFreq, $modifierMap)) { $currentEnd->{$function}($modifierMap[$repeatFreq])->milli(0); // @phpstan-ignore-line @@ -353,7 +355,7 @@ class Navigation 'yearly' => 'endOfYear', ]; - $currentEnd = clone $theCurrentEnd; + $currentEnd = clone $theCurrentEnd; if (array_key_exists($repeatFreq, $functionMap)) { $function = $functionMap[$repeatFreq]; @@ -396,7 +398,7 @@ class Navigation */ public function listOfPeriods(Carbon $start, Carbon $end): array { - $locale = app('steam')->getLocale(); + $locale = app('steam')->getLocale(); // define period to increment $increment = 'addDay'; $format = $this->preferredCarbonFormat($start, $end); @@ -413,8 +415,8 @@ class Navigation $increment = 'addYear'; $displayFormat = (string)trans('config.year_js'); } - $begin = clone $start; - $entries = []; + $begin = clone $start; + $entries = []; while ($begin < $end) { $formatted = $begin->format($format); $displayed = $begin->isoFormat($displayFormat); @@ -597,9 +599,9 @@ class Navigation public function startOfPeriod(Carbon $theDate, string $repeatFreq): Carbon { - $date = clone $theDate; + $date = clone $theDate; // Log::debug(sprintf('Now in startOfPeriod("%s", "%s")', $date->toIso8601String(), $repeatFreq)); - $functionMap = [ + $functionMap = [ '1D' => 'startOfDay', 'daily' => 'startOfDay', '1W' => 'startOfWeek', @@ -646,7 +648,7 @@ class Navigation return $date; } - $result = match ($repeatFreq) { + $result = match ($repeatFreq) { 'last7' => $date->subDays(7)->startOfDay(), 'last30' => $date->subDays(30)->startOfDay(), 'last90' => $date->subDays(90)->startOfDay(), @@ -678,7 +680,7 @@ class Navigation public function subtractPeriod(Carbon $theDate, string $repeatFreq, ?int $subtract = null): Carbon { $subtract ??= 1; - $date = clone $theDate; + $date = clone $theDate; // 1D 1W 1M 3M 6M 1Y $functionMap = [ '1D' => 'subDays', @@ -717,7 +719,7 @@ class Navigation // this is then subtracted from $theDate (* $subtract). if ('custom' === $repeatFreq) { /** @var Carbon $tStart */ - $tStart = session('start', today(config('app.timezone'))->startOfMonth()); + $tStart = session('start', today(config('app.timezone'))->startOfMonth()); /** @var Carbon $tEnd */ $tEnd = session('end', today(config('app.timezone'))->endOfMonth()); @@ -811,7 +813,7 @@ class Navigation return $fiscalHelper->endOfFiscalYear($end); } - $list = [ + $list = [ 'last7', 'last30', 'last90', diff --git a/app/Support/Observers/RecalculatesAvailableBudgetsTrait.php b/app/Support/Observers/RecalculatesAvailableBudgetsTrait.php index 58f40b85a4..e55405de9e 100644 --- a/app/Support/Observers/RecalculatesAvailableBudgetsTrait.php +++ b/app/Support/Observers/RecalculatesAvailableBudgetsTrait.php @@ -35,7 +35,6 @@ use Illuminate\Support\Facades\Log; use Psr\Container\ContainerExceptionInterface; use Psr\Container\NotFoundExceptionInterface; use Spatie\Period\Boundaries; -use Spatie\Period\Exceptions\InvalidPeriod; use Spatie\Period\Period; use Spatie\Period\Precision; @@ -203,8 +202,8 @@ trait RecalculatesAvailableBudgetsTrait } if (null === $availableBudget && $currentEnd->gte($current)) { $currentPeriod = Period::make($current, $currentEnd, precision: Precision::DAY(), boundaries: Boundaries::EXCLUDE_NONE()); - $daily = $this->getDailyAmount($budgetLimit); - $amount = bcmul((string)$daily, (string)$currentPeriod->length(), 12); + $daily = $this->getDailyAmount($budgetLimit); + $amount = bcmul((string)$daily, (string)$currentPeriod->length(), 12); // no need to calculate if period is equal. if ($currentPeriod->equals($limitPeriod)) { diff --git a/config/firefly.php b/config/firefly.php index b372972378..2ecdb8e4ad 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -79,7 +79,7 @@ return [ // see cer.php for exchange rates feature flag. ], 'version' => 'develop/2025-11-26', - 'build_time' => 1764136346, + 'build_time' => 1764178914, 'api_version' => '2.1.0', // field is no longer used. 'db_version' => 28, // field is no longer used. From 52164689d4eb7655fdeed87caf257678ab4e90c9 Mon Sep 17 00:00:00 2001 From: James Cole Date: Wed, 26 Nov 2025 19:05:46 +0100 Subject: [PATCH 20/26] Switch to 1M when it's MTD. --- app/Support/Navigation.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/Support/Navigation.php b/app/Support/Navigation.php index 585ba925b8..ed71714888 100644 --- a/app/Support/Navigation.php +++ b/app/Support/Navigation.php @@ -206,7 +206,13 @@ class Navigation public function endOfPeriod(Carbon $end, string $repeatFreq): Carbon { $currentEnd = clone $end; + // Log::debug(sprintf('Now in endOfPeriod("%s", "%s").', $currentEnd->toIso8601String(), $repeatFreq)); + if('MTD' === $repeatFreq) { + // fall back to a monthly schedule if the requested period is MTD. + Log::debug('endOfPeriod() requests "MTD", set it to "1M" instead.'); + $repeatFreq = '1M'; + } $functionMap = [ '1D' => 'endOfDay', From 1dd098a283dc1fcc65370263dfcb24293718ec31 Mon Sep 17 00:00:00 2001 From: James Cole Date: Wed, 26 Nov 2025 19:06:58 +0100 Subject: [PATCH 21/26] Fix #11284 --- app/Support/Navigation.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Support/Navigation.php b/app/Support/Navigation.php index ed71714888..ce78a979f1 100644 --- a/app/Support/Navigation.php +++ b/app/Support/Navigation.php @@ -208,7 +208,7 @@ class Navigation $currentEnd = clone $end; // Log::debug(sprintf('Now in endOfPeriod("%s", "%s").', $currentEnd->toIso8601String(), $repeatFreq)); - if('MTD' === $repeatFreq) { + if('MTD' === $repeatFreq && $end->isFuture()) { // fall back to a monthly schedule if the requested period is MTD. Log::debug('endOfPeriod() requests "MTD", set it to "1M" instead.'); $repeatFreq = '1M'; From e83fe023d2cf27e867f10caad2384fd78cd4cdeb Mon Sep 17 00:00:00 2001 From: JC5 Date: Wed, 26 Nov 2025 19:12:34 +0100 Subject: [PATCH 22/26] =?UTF-8?q?=F0=9F=A4=96=20Auto=20commit=20for=20rele?= =?UTF-8?q?ase=20'develop'=20on=202025-11-26?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Support/Navigation.php | 2 +- config/firefly.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Support/Navigation.php b/app/Support/Navigation.php index ce78a979f1..9443923bcc 100644 --- a/app/Support/Navigation.php +++ b/app/Support/Navigation.php @@ -208,7 +208,7 @@ class Navigation $currentEnd = clone $end; // Log::debug(sprintf('Now in endOfPeriod("%s", "%s").', $currentEnd->toIso8601String(), $repeatFreq)); - if('MTD' === $repeatFreq && $end->isFuture()) { + if ('MTD' === $repeatFreq && $end->isFuture()) { // fall back to a monthly schedule if the requested period is MTD. Log::debug('endOfPeriod() requests "MTD", set it to "1M" instead.'); $repeatFreq = '1M'; diff --git a/config/firefly.php b/config/firefly.php index 2ecdb8e4ad..09170a77b3 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -79,7 +79,7 @@ return [ // see cer.php for exchange rates feature flag. ], 'version' => 'develop/2025-11-26', - 'build_time' => 1764178914, + 'build_time' => 1764180641, 'api_version' => '2.1.0', // field is no longer used. 'db_version' => 28, // field is no longer used. From 3711222f9e9ab2633dd56a6a288c36124cace8fa Mon Sep 17 00:00:00 2001 From: James Cole Date: Fri, 28 Nov 2025 19:01:15 +0100 Subject: [PATCH 23/26] Fix #11281 and some other stuff. --- app/Handlers/Events/WebhookEventHandler.php | 4 +++ .../Controllers/Account/CreateController.php | 7 ++--- .../Controllers/Account/DeleteController.php | 3 ++- .../Controllers/Account/EditController.php | 3 ++- .../Controllers/Account/IndexController.php | 5 ++-- .../Account/ReconcileController.php | 3 ++- .../Controllers/Account/ShowController.php | 5 ++-- .../Admin/ConfigurationController.php | 3 ++- app/Http/Controllers/Admin/HomeController.php | 3 ++- app/Http/Controllers/Admin/LinkController.php | 5 ++-- app/Http/Controllers/Admin/UserController.php | 3 ++- app/Http/Controllers/AttachmentController.php | 5 ++-- .../Controllers/Auth/TwoFactorController.php | 25 ++++++++--------- .../Controllers/Bill/CreateController.php | 3 ++- .../Controllers/Bill/DeleteController.php | 3 ++- app/Http/Controllers/Bill/EditController.php | 3 ++- app/Http/Controllers/Bill/ShowController.php | 5 ++-- .../Budget/BudgetLimitController.php | 3 ++- .../Controllers/Budget/CreateController.php | 3 ++- .../Controllers/Budget/DeleteController.php | 3 ++- .../Controllers/Budget/EditController.php | 3 ++- .../Controllers/Budget/IndexController.php | 3 ++- .../Controllers/Budget/ShowController.php | 9 ++++--- .../Controllers/Category/CreateController.php | 3 ++- .../Controllers/Category/DeleteController.php | 3 ++- .../Controllers/Category/EditController.php | 3 ++- .../Controllers/Category/IndexController.php | 3 ++- .../Category/NoCategoryController.php | 5 ++-- .../Controllers/Category/ShowController.php | 5 ++-- app/Http/Controllers/HomeController.php | 3 ++- app/Http/Controllers/JavascriptController.php | 3 ++- app/Http/Controllers/Json/IntroController.php | 7 ++--- app/Http/Controllers/NewUserController.php | 11 ++++---- .../ObjectGroup/DeleteController.php | 3 ++- .../ObjectGroup/EditController.php | 3 ++- .../PiggyBank/AmountController.php | 5 ++-- .../PiggyBank/CreateController.php | 3 ++- .../PiggyBank/DeleteController.php | 3 ++- .../Controllers/PiggyBank/EditController.php | 3 ++- .../Controllers/Profile/MfaController.php | 27 ++++++++++--------- app/Http/Controllers/ProfileController.php | 15 ++++++----- .../Recurring/CreateController.php | 3 ++- .../Recurring/DeleteController.php | 3 ++- .../Controllers/Recurring/EditController.php | 3 ++- .../Controllers/Recurring/IndexController.php | 3 ++- app/Http/Controllers/ReportController.php | 3 ++- .../Controllers/Rule/CreateController.php | 3 ++- .../Controllers/Rule/DeleteController.php | 3 ++- app/Http/Controllers/Rule/EditController.php | 3 ++- .../RuleGroup/CreateController.php | 3 ++- .../RuleGroup/DeleteController.php | 3 ++- .../Controllers/RuleGroup/EditController.php | 3 ++- .../Controllers/System/InstallController.php | 3 ++- app/Http/Controllers/TagController.php | 11 ++++---- .../Transaction/BulkController.php | 3 ++- .../Transaction/DeleteController.php | 3 ++- .../Transaction/EditController.php | 5 ++-- .../Transaction/IndexController.php | 5 ++-- .../Transaction/LinkController.php | 3 ++- .../Transaction/MassController.php | 5 ++-- .../TransactionCurrency/EditController.php | 3 ++- .../TransactionCurrency/IndexController.php | 3 ++- app/Http/Middleware/InterestingMessage.php | 13 ++++----- app/Http/Middleware/Range.php | 5 ++-- app/Jobs/CreateRecurringTransactions.php | 8 ++++-- .../ReturnsAvailableChannels.php | 11 ++++---- .../Recurring/RecurringRepository.php | 3 ++- app/Repositories/User/UserRepository.php | 13 ++++----- .../Internal/Support/AccountServiceTrait.php | 7 ++--- .../Internal/Update/AccountUpdateService.php | 5 ++-- .../Internal/Update/GroupUpdateService.php | 7 ++--- .../Internal/Update/JournalUpdateService.php | 3 ++- app/Support/Binder/CLIToken.php | 3 ++- app/Support/CacheProperties.php | 3 ++- app/Support/Cronjobs/AutoBudgetCronjob.php | 3 ++- app/Support/Cronjobs/BillWarningCronjob.php | 3 ++- app/Support/Cronjobs/ExchangeRatesCronjob.php | 3 ++- app/Support/Cronjobs/RecurringCronjob.php | 3 ++- app/Support/Cronjobs/WebhookCronjob.php | 3 ++- .../Http/Api/CollectsAccountsFromFilter.php | 3 ++- .../Http/Controllers/RequestInformation.php | 3 ++- app/Support/Navigation.php | 3 ++- .../RecalculatesAvailableBudgetsTrait.php | 3 ++- app/Support/Search/OperatorQuerySearch.php | 3 ++- app/Support/Steam.php | 7 ++--- app/User.php | 9 ++++--- app/Validation/FireflyValidator.php | 3 ++- 87 files changed, 260 insertions(+), 167 deletions(-) diff --git a/app/Handlers/Events/WebhookEventHandler.php b/app/Handlers/Events/WebhookEventHandler.php index 04e575039e..b83079e402 100644 --- a/app/Handlers/Events/WebhookEventHandler.php +++ b/app/Handlers/Events/WebhookEventHandler.php @@ -53,8 +53,12 @@ class WebhookEventHandler )->splice(0, 5) ; Log::debug(sprintf('Found %d webhook message(s) ready to be send.', $messages->count())); + /** @var WebhookMessage $message */ foreach ($messages as $message) { if (false === $message->sent) { + // set it to "sent" right away! + $message->sent = true; + $message->save(); Log::debug(sprintf('Send message #%d', $message->id)); SendWebhookMessage::dispatch($message)->afterResponse(); } diff --git a/app/Http/Controllers/Account/CreateController.php b/app/Http/Controllers/Account/CreateController.php index 65994d0f82..7411952ae9 100644 --- a/app/Http/Controllers/Account/CreateController.php +++ b/app/Http/Controllers/Account/CreateController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Account; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Enums\AccountTypeEnum; use FireflyIII\Helpers\Attachments\AttachmentHelperInterface; use FireflyIII\Http\Controllers\Controller; @@ -141,18 +142,18 @@ class CreateController extends Controller $data = $request->getAccountData(); $account = $this->repository->store($data); $request->session()->flash('success', (string) trans('firefly.stored_new_account', ['name' => $account->name])); - app('preferences')->mark(); + Preferences::mark(); Log::channel('audit')->info('Stored new account.', $data); // update preferences if necessary: - $frontpage = app('preferences')->get('frontpageAccounts', [])->data; + $frontpage = Preferences::get('frontpageAccounts', [])->data; if (!is_array($frontpage)) { $frontpage = []; } if (AccountTypeEnum::ASSET->value === $account->accountType->type) { $frontpage[] = $account->id; - app('preferences')->set('frontpageAccounts', $frontpage); + Preferences::set('frontpageAccounts', $frontpage); } // store attachment(s): diff --git a/app/Http/Controllers/Account/DeleteController.php b/app/Http/Controllers/Account/DeleteController.php index 49686ffe61..8f577d3d6d 100644 --- a/app/Http/Controllers/Account/DeleteController.php +++ b/app/Http/Controllers/Account/DeleteController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Account; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\Account; use FireflyIII\Repositories\Account\AccountRepositoryInterface; @@ -101,7 +102,7 @@ class DeleteController extends Controller $this->repository->destroy($account, $moveTo); $request->session()->flash('success', (string) trans(sprintf('firefly.%s_deleted', $typeName), ['name' => $name])); - app('preferences')->mark(); + Preferences::mark(); return redirect($this->getPreviousUrl('accounts.delete.url')); } diff --git a/app/Http/Controllers/Account/EditController.php b/app/Http/Controllers/Account/EditController.php index 9fa0eea7c0..2b0c39e870 100644 --- a/app/Http/Controllers/Account/EditController.php +++ b/app/Http/Controllers/Account/EditController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Account; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Helpers\Attachments\AttachmentHelperInterface; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Requests\AccountFormRequest; @@ -205,7 +206,7 @@ class EditController extends Controller $redirect = redirect(route('accounts.edit', [$account->id]))->withInput(['return_to_edit' => 1]); } - app('preferences')->mark(); + Preferences::mark(); return $redirect; } diff --git a/app/Http/Controllers/Account/IndexController.php b/app/Http/Controllers/Account/IndexController.php index 289413e8fb..94951b398a 100644 --- a/app/Http/Controllers/Account/IndexController.php +++ b/app/Http/Controllers/Account/IndexController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Account; +use FireflyIII\Support\Facades\Preferences; use Carbon\Carbon; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\Account; @@ -81,7 +82,7 @@ class IndexController extends Controller $collection = $this->repository->getInactiveAccountsByType($types); $total = $collection->count(); $page = 0 === (int) $request->get('page') ? 1 : (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $pageSize = (int) Preferences::get('listPageSize', 50)->data; $accounts = $collection->slice(($page - 1) * $pageSize, $pageSize); unset($collection); @@ -153,7 +154,7 @@ class IndexController extends Controller $collection = $this->repository->getActiveAccountsByType($types); $total = $collection->count(); $page = 0 === (int) $request->get('page') ? 1 : (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $pageSize = (int) Preferences::get('listPageSize', 50)->data; $accounts = $collection->slice(($page - 1) * $pageSize, $pageSize); $inactiveCount = $this->repository->getInactiveAccountsByType($types)->count(); diff --git a/app/Http/Controllers/Account/ReconcileController.php b/app/Http/Controllers/Account/ReconcileController.php index 248e5efe38..c96cd970a6 100644 --- a/app/Http/Controllers/Account/ReconcileController.php +++ b/app/Http/Controllers/Account/ReconcileController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Account; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Support\Facades\Navigation; use Illuminate\Support\Facades\Log; use Carbon\Carbon; @@ -175,7 +176,7 @@ class ReconcileController extends Controller $result = $this->createReconciliation($account, $start, $end, $data['difference']); } Log::debug('End of routine.'); - app('preferences')->mark(); + Preferences::mark(); if ('' === $result) { session()->flash('success', (string) trans('firefly.reconciliation_stored')); } diff --git a/app/Http/Controllers/Account/ShowController.php b/app/Http/Controllers/Account/ShowController.php index f495e586c8..39e5debb64 100644 --- a/app/Http/Controllers/Account/ShowController.php +++ b/app/Http/Controllers/Account/ShowController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Account; +use FireflyIII\Support\Facades\Preferences; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Helpers\Collector\GroupCollectorInterface; @@ -113,7 +114,7 @@ class ShowController extends Controller $today = today(config('app.timezone')); $subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $account->accountType->type)); $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $pageSize = (int) Preferences::get('listPageSize', 50)->data; $accountCurrency = $this->repository->getAccountCurrency($account); $currency = $accountCurrency ?? $this->primaryCurrency; $fStart = $start->isoFormat($this->monthAndDayFormat); @@ -199,7 +200,7 @@ class ShowController extends Controller $start = $this->repository->oldestJournalDate($account) ?? today(config('app.timezone'))->startOfMonth(); $subTitleIcon = config('firefly.subIconsByIdentifier.'.$account->accountType->type); $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $pageSize = (int) Preferences::get('listPageSize', 50)->data; $currency = $this->repository->getAccountCurrency($account) ?? $this->primaryCurrency; $subTitle = (string) trans('firefly.all_journals_for_account', ['name' => $account->name]); $periods = new Collection(); diff --git a/app/Http/Controllers/Admin/ConfigurationController.php b/app/Http/Controllers/Admin/ConfigurationController.php index 541549fade..fe4f9dc3ca 100644 --- a/app/Http/Controllers/Admin/ConfigurationController.php +++ b/app/Http/Controllers/Admin/ConfigurationController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Admin; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Middleware\IsDemoUser; use FireflyIII\Http\Requests\ConfigurationRequest; @@ -95,7 +96,7 @@ class ConfigurationController extends Controller // flash message session()->flash('success', (string) trans('firefly.configuration_updated')); - app('preferences')->mark(); + Preferences::mark(); return redirect()->route('settings.configuration.index'); } diff --git a/app/Http/Controllers/Admin/HomeController.php b/app/Http/Controllers/Admin/HomeController.php index 8915a44f06..0c4fc3911c 100644 --- a/app/Http/Controllers/Admin/HomeController.php +++ b/app/Http/Controllers/Admin/HomeController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Admin; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Middleware\IsDemoUser; use Illuminate\Contracts\View\Factory; @@ -59,7 +60,7 @@ class HomeController extends Controller $title = (string) trans('firefly.system_settings'); $mainTitleIcon = 'fa-hand-spock-o'; $email = auth()->user()->email; - $pref = app('preferences')->get('remote_guard_alt_email'); + $pref = Preferences::get('remote_guard_alt_email'); if (null !== $pref && is_string($pref->data)) { $email = $pref->data; } diff --git a/app/Http/Controllers/Admin/LinkController.php b/app/Http/Controllers/Admin/LinkController.php index 234c980471..d48124d231 100644 --- a/app/Http/Controllers/Admin/LinkController.php +++ b/app/Http/Controllers/Admin/LinkController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Admin; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Middleware\IsDemoUser; use FireflyIII\Http\Requests\LinkTypeFormRequest; @@ -125,7 +126,7 @@ class LinkController extends Controller $this->repository->destroy($linkType, $moveTo); $request->session()->flash('success', (string) trans('firefly.deleted_link_type', ['name' => $name])); - app('preferences')->mark(); + Preferences::mark(); return redirect($this->getPreviousUrl('link-types.delete.url')); } @@ -245,7 +246,7 @@ class LinkController extends Controller Log::channel('audit')->info(sprintf('User update link type #%d.', $linkType->id), $data); $request->session()->flash('success', (string) trans('firefly.updated_link_type', ['name' => $linkType->name])); - app('preferences')->mark(); + Preferences::mark(); $redirect = redirect($this->getPreviousUrl('link-types.edit.url')); if (1 === (int) $request->get('return_to_edit')) { // set value so edit routine will not overwrite URL: diff --git a/app/Http/Controllers/Admin/UserController.php b/app/Http/Controllers/Admin/UserController.php index b2a50a5da5..380ac6dc3e 100644 --- a/app/Http/Controllers/Admin/UserController.php +++ b/app/Http/Controllers/Admin/UserController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Admin; +use FireflyIII\Support\Facades\Preferences; use Illuminate\Support\Facades\Log; use FireflyIII\Events\Admin\InvitationCreated; use FireflyIII\Exceptions\FireflyException; @@ -242,7 +243,7 @@ class UserController extends Controller $this->repository->updateEmail($user, $data['email']); session()->flash('success', (string) trans('firefly.updated_user', ['email' => $user->email])); - app('preferences')->mark(); + Preferences::mark(); $redirect = redirect($this->getPreviousUrl('users.edit.url')); if (1 === (int) $request->get('return_to_edit')) { session()->put('users.edit.fromUpdate', true); diff --git a/app/Http/Controllers/AttachmentController.php b/app/Http/Controllers/AttachmentController.php index 534dd47cee..4c4ff2293a 100644 --- a/app/Http/Controllers/AttachmentController.php +++ b/app/Http/Controllers/AttachmentController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Http\Requests\AttachmentFormRequest; use FireflyIII\Models\Attachment; @@ -85,7 +86,7 @@ class AttachmentController extends Controller $this->repository->destroy($attachment); $request->session()->flash('success', (string) trans('firefly.attachment_deleted', ['name' => $name])); - app('preferences')->mark(); + Preferences::mark(); return redirect($this->getPreviousUrl('attachments.delete.url')); } @@ -175,7 +176,7 @@ class AttachmentController extends Controller $this->repository->update($attachment, $data); $request->session()->flash('success', (string) trans('firefly.attachment_updated', ['name' => $attachment->filename])); - app('preferences')->mark(); + Preferences::mark(); $redirect = redirect($this->getPreviousUrl('attachments.edit.url')); if (1 === (int) $request->get('return_to_edit')) { diff --git a/app/Http/Controllers/Auth/TwoFactorController.php b/app/Http/Controllers/Auth/TwoFactorController.php index 2116f1b827..983f0f8b26 100644 --- a/app/Http/Controllers/Auth/TwoFactorController.php +++ b/app/Http/Controllers/Auth/TwoFactorController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Auth; +use FireflyIII\Support\Facades\Preferences; use Carbon\Carbon; use FireflyIII\Events\Security\MFABackupFewLeft; use FireflyIII\Events\Security\MFABackupNoLeft; @@ -65,7 +66,7 @@ class TwoFactorController extends Controller public function submitMFA(Request $request): Redirector|RedirectResponse { /** @var array $mfaHistory */ - $mfaHistory = app('preferences')->get('mfa_history', [])->data; + $mfaHistory = Preferences::get('mfa_history', [])->data; $mfaCode = (string) $request->get('one_time_password'); // is in history? then refuse to use it. @@ -149,7 +150,7 @@ class TwoFactorController extends Controller private function filterMFAHistory(): void { /** @var array $mfaHistory */ - $mfaHistory = app('preferences')->get('mfa_history', [])->data; + $mfaHistory = Preferences::get('mfa_history', [])->data; $newHistory = []; $now = Carbon::now()->getTimestamp(); foreach ($mfaHistory as $entry) { @@ -162,20 +163,20 @@ class TwoFactorController extends Controller ]; } } - app('preferences')->set('mfa_history', $newHistory); + Preferences::set('mfa_history', $newHistory); } private function addToMFAFailureCounter(): void { - $preference = (int) app('preferences')->get('mfa_failure_count', 0)->data; + $preference = (int) Preferences::get('mfa_failure_count', 0)->data; ++$preference; Log::channel('audit')->info(sprintf('MFA failure count is set to %d.', $preference)); - app('preferences')->set('mfa_failure_count', $preference); + Preferences::set('mfa_failure_count', $preference); } private function getMFAFailureCounter(): int { - $value = (int) app('preferences')->get('mfa_failure_count', 0)->data; + $value = (int) Preferences::get('mfa_failure_count', 0)->data; Log::channel('audit')->info(sprintf('MFA failure count is %d.', $value)); return $value; @@ -184,20 +185,20 @@ class TwoFactorController extends Controller private function addToMFAHistory(string $mfaCode): void { /** @var array $mfaHistory */ - $mfaHistory = app('preferences')->get('mfa_history', [])->data; + $mfaHistory = Preferences::get('mfa_history', [])->data; $entry = [ 'time' => Carbon::now()->getTimestamp(), 'code' => $mfaCode, ]; $mfaHistory[] = $entry; - app('preferences')->set('mfa_history', $mfaHistory); + Preferences::set('mfa_history', $mfaHistory); $this->filterMFAHistory(); } private function resetMFAFailureCounter(): void { - app('preferences')->set('mfa_failure_count', 0); + Preferences::set('mfa_failure_count', 0); Log::channel('audit')->info('MFA failure count is set to zero.'); } @@ -206,7 +207,7 @@ class TwoFactorController extends Controller */ private function isBackupCode(string $mfaCode): bool { - $list = app('preferences')->get('mfa_recovery', [])->data; + $list = Preferences::get('mfa_recovery', [])->data; if (!is_array($list)) { $list = []; } @@ -219,7 +220,7 @@ class TwoFactorController extends Controller */ private function removeFromBackupCodes(string $mfaCode): void { - $list = app('preferences')->get('mfa_recovery', [])->data; + $list = Preferences::get('mfa_recovery', [])->data; if (!is_array($list)) { $list = []; } @@ -238,6 +239,6 @@ class TwoFactorController extends Controller event(new MFABackupNoLeft($user)); } - app('preferences')->set('mfa_recovery', $newList); + Preferences::set('mfa_recovery', $newList); } } diff --git a/app/Http/Controllers/Bill/CreateController.php b/app/Http/Controllers/Bill/CreateController.php index f87059d095..3d8d95fd37 100644 --- a/app/Http/Controllers/Bill/CreateController.php +++ b/app/Http/Controllers/Bill/CreateController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Bill; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Helpers\Attachments\AttachmentHelperInterface; use FireflyIII\Http\Controllers\Controller; @@ -105,7 +106,7 @@ class CreateController extends Controller Log::channel('audit')->info('Stored new bill.', $billData); $request->session()->flash('success', (string) trans('firefly.stored_new_bill', ['name' => $bill->name])); - app('preferences')->mark(); + Preferences::mark(); /** @var null|array $files */ $files = $request->hasFile('attachments') ? $request->file('attachments') : null; diff --git a/app/Http/Controllers/Bill/DeleteController.php b/app/Http/Controllers/Bill/DeleteController.php index a3516bcf4a..70f8d06338 100644 --- a/app/Http/Controllers/Bill/DeleteController.php +++ b/app/Http/Controllers/Bill/DeleteController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Bill; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\Bill; use FireflyIII\Repositories\Bill\BillRepositoryInterface; @@ -83,7 +84,7 @@ class DeleteController extends Controller $this->repository->destroy($bill); $request->session()->flash('success', (string) trans('firefly.deleted_bill', ['name' => $name])); - app('preferences')->mark(); + Preferences::mark(); return redirect($this->getPreviousUrl('bills.delete.url')); } diff --git a/app/Http/Controllers/Bill/EditController.php b/app/Http/Controllers/Bill/EditController.php index 820841215b..536eabb827 100644 --- a/app/Http/Controllers/Bill/EditController.php +++ b/app/Http/Controllers/Bill/EditController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Bill; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Helpers\Attachments\AttachmentHelperInterface; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Requests\BillUpdateRequest; @@ -116,7 +117,7 @@ class EditController extends Controller Log::channel('audit')->info(sprintf('Updated bill #%d.', $bill->id), $billData); $request->session()->flash('success', (string) trans('firefly.updated_bill', ['name' => $bill->name])); - app('preferences')->mark(); + Preferences::mark(); /** @var null|array $files */ $files = $request->hasFile('attachments') ? $request->file('attachments') : null; diff --git a/app/Http/Controllers/Bill/ShowController.php b/app/Http/Controllers/Bill/ShowController.php index fa5ef7d699..a4125f0410 100644 --- a/app/Http/Controllers/Bill/ShowController.php +++ b/app/Http/Controllers/Bill/ShowController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Bill; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Support\Facades\Navigation; use Carbon\Carbon; use FireflyIII\Helpers\Collector\GroupCollectorInterface; @@ -106,7 +107,7 @@ class ShowController extends Controller $ruleEngine->fire(); $request->session()->flash('success', trans_choice('firefly.rescanned_bill', $total)); - app('preferences')->mark(); + Preferences::mark(); return redirect(route('bills.show', [$bill->id])); } @@ -132,7 +133,7 @@ class ShowController extends Controller $end = session('end'); $year = $start->year; $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $pageSize = (int) Preferences::get('listPageSize', 50)->data; $yearAverage = $this->repository->getYearAverage($bill, $start); $overallAverage = $this->repository->getOverallAverage($bill); $manager = new Manager(); diff --git a/app/Http/Controllers/Budget/BudgetLimitController.php b/app/Http/Controllers/Budget/BudgetLimitController.php index 241345f2f5..c074746c2a 100644 --- a/app/Http/Controllers/Budget/BudgetLimitController.php +++ b/app/Http/Controllers/Budget/BudgetLimitController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Budget; +use FireflyIII\Support\Facades\Preferences; use Illuminate\Support\Facades\Log; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; @@ -255,7 +256,7 @@ class BudgetLimitController extends Controller $limit = $this->blRepository->update($budgetLimit, ['amount' => $amount, 'notes' => $notes]); - app('preferences')->mark(); + Preferences::mark(); $array = $limit->toArray(); $spentArr = $this->opsRepository->sumExpenses( diff --git a/app/Http/Controllers/Budget/CreateController.php b/app/Http/Controllers/Budget/CreateController.php index 2146daa4e9..de3a38ebb4 100644 --- a/app/Http/Controllers/Budget/CreateController.php +++ b/app/Http/Controllers/Budget/CreateController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Budget; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Enums\AutoBudgetType; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Helpers\Attachments\AttachmentHelperInterface; @@ -116,7 +117,7 @@ class CreateController extends Controller $budget = $this->repository->store($data); $this->repository->cleanupBudgets(); $request->session()->flash('success', (string) trans('firefly.stored_new_budget', ['name' => $budget->name])); - app('preferences')->mark(); + Preferences::mark(); Log::channel('audit')->info('Stored new budget.', $data); diff --git a/app/Http/Controllers/Budget/DeleteController.php b/app/Http/Controllers/Budget/DeleteController.php index 7338cfa1b1..b9989c45ef 100644 --- a/app/Http/Controllers/Budget/DeleteController.php +++ b/app/Http/Controllers/Budget/DeleteController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Budget; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\Budget; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; @@ -82,7 +83,7 @@ class DeleteController extends Controller $name = $budget->name; $this->repository->destroy($budget); $request->session()->flash('success', (string) trans('firefly.deleted_budget', ['name' => $name])); - app('preferences')->mark(); + Preferences::mark(); return redirect($this->getPreviousUrl('budgets.delete.url')); } diff --git a/app/Http/Controllers/Budget/EditController.php b/app/Http/Controllers/Budget/EditController.php index 15ca61d449..a164365fcd 100644 --- a/app/Http/Controllers/Budget/EditController.php +++ b/app/Http/Controllers/Budget/EditController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Budget; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Enums\AutoBudgetType; use FireflyIII\Helpers\Attachments\AttachmentHelperInterface; use FireflyIII\Http\Controllers\Controller; @@ -126,7 +127,7 @@ class EditController extends Controller $request->session()->flash('success', (string) trans('firefly.updated_budget', ['name' => $budget->name])); $this->repository->cleanupBudgets(); - app('preferences')->mark(); + Preferences::mark(); Log::channel('audit')->info(sprintf('Updated budget #%d.', $budget->id), $data); diff --git a/app/Http/Controllers/Budget/IndexController.php b/app/Http/Controllers/Budget/IndexController.php index 776a4e2239..efe15e03bb 100644 --- a/app/Http/Controllers/Budget/IndexController.php +++ b/app/Http/Controllers/Budget/IndexController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Budget; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Support\Facades\Navigation; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; @@ -308,7 +309,7 @@ class IndexController extends Controller $repository->setBudgetOrder($budget, $index + 1); } } - app('preferences')->mark(); + Preferences::mark(); return response()->json(['OK']); } diff --git a/app/Http/Controllers/Budget/ShowController.php b/app/Http/Controllers/Budget/ShowController.php index 9215523324..9325032225 100644 --- a/app/Http/Controllers/Budget/ShowController.php +++ b/app/Http/Controllers/Budget/ShowController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Budget; +use FireflyIII\Support\Facades\Preferences; use Carbon\Carbon; use FireflyIII\Enums\TransactionTypeEnum; use FireflyIII\Exceptions\FireflyException; @@ -98,7 +99,7 @@ class ShowController extends Controller $firstDate = $first instanceof TransactionJournal ? $first->date : $start; $periods = $this->getNoModelPeriodOverview('budget', $firstDate, $end); $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $pageSize = (int) Preferences::get('listPageSize', 50)->data; /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollectorInterface::class); @@ -126,7 +127,7 @@ class ShowController extends Controller $start = $first instanceof TransactionJournal ? $first->date : new Carbon(); $end = today(config('app.timezone')); $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $pageSize = (int) Preferences::get('listPageSize', 50)->data; /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollectorInterface::class); @@ -153,7 +154,7 @@ class ShowController extends Controller $allStart = session('first', today(config('app.timezone'))->startOfYear()); $allEnd = today(); $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $pageSize = (int) Preferences::get('listPageSize', 50)->data; $limits = $this->getLimits($budget, $allStart, $allEnd); $repetition = null; $attachments = $this->repository->getAttachments($budget); @@ -190,7 +191,7 @@ class ShowController extends Controller $currencySymbol = $budgetLimit->transactionCurrency->symbol; $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $pageSize = (int) Preferences::get('listPageSize', 50)->data; $subTitle = trans( 'firefly.budget_in_period', [ diff --git a/app/Http/Controllers/Category/CreateController.php b/app/Http/Controllers/Category/CreateController.php index da68a62fe9..043cc17ea6 100644 --- a/app/Http/Controllers/Category/CreateController.php +++ b/app/Http/Controllers/Category/CreateController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Category; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Helpers\Attachments\AttachmentHelperInterface; use FireflyIII\Http\Controllers\Controller; @@ -92,7 +93,7 @@ class CreateController extends Controller $category = $this->repository->store($data); $request->session()->flash('success', (string) trans('firefly.stored_category', ['name' => $category->name])); - app('preferences')->mark(); + Preferences::mark(); // store attachment(s): /** @var null|array $files */ diff --git a/app/Http/Controllers/Category/DeleteController.php b/app/Http/Controllers/Category/DeleteController.php index e90b33b56c..d2e106a192 100644 --- a/app/Http/Controllers/Category/DeleteController.php +++ b/app/Http/Controllers/Category/DeleteController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Category; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\Category; use FireflyIII\Repositories\Category\CategoryRepositoryInterface; @@ -83,7 +84,7 @@ class DeleteController extends Controller $this->repository->destroy($category); $request->session()->flash('success', (string) trans('firefly.deleted_category', ['name' => $name])); - app('preferences')->mark(); + Preferences::mark(); return redirect($this->getPreviousUrl('categories.delete.url')); } diff --git a/app/Http/Controllers/Category/EditController.php b/app/Http/Controllers/Category/EditController.php index 9a5ddd55dc..2e02d8fcaa 100644 --- a/app/Http/Controllers/Category/EditController.php +++ b/app/Http/Controllers/Category/EditController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Category; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Helpers\Attachments\AttachmentHelperInterface; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Requests\CategoryFormRequest; @@ -94,7 +95,7 @@ class EditController extends Controller $this->repository->update($category, $data); $request->session()->flash('success', (string) trans('firefly.updated_category', ['name' => $category->name])); - app('preferences')->mark(); + Preferences::mark(); // store new attachment(s): /** @var null|array $files */ diff --git a/app/Http/Controllers/Category/IndexController.php b/app/Http/Controllers/Category/IndexController.php index 15d7f70865..e7cfd7816e 100644 --- a/app/Http/Controllers/Category/IndexController.php +++ b/app/Http/Controllers/Category/IndexController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Category; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\Category; use FireflyIII\Repositories\Category\CategoryRepositoryInterface; @@ -72,7 +73,7 @@ class IndexController extends Controller public function index(Request $request): Factory|\Illuminate\Contracts\View\View { $page = 0 === (int) $request->get('page') ? 1 : (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $pageSize = (int) Preferences::get('listPageSize', 50)->data; $collection = $this->repository->getCategories(); $total = $collection->count(); $collection = $collection->slice(($page - 1) * $pageSize, $pageSize); diff --git a/app/Http/Controllers/Category/NoCategoryController.php b/app/Http/Controllers/Category/NoCategoryController.php index 2e4db37b00..fa03c70f08 100644 --- a/app/Http/Controllers/Category/NoCategoryController.php +++ b/app/Http/Controllers/Category/NoCategoryController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Category; +use FireflyIII\Support\Facades\Preferences; use Carbon\Carbon; use FireflyIII\Enums\TransactionTypeEnum; use FireflyIII\Exceptions\FireflyException; @@ -86,7 +87,7 @@ class NoCategoryController extends Controller /** @var Carbon $start */ /** @var Carbon $end */ $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $pageSize = (int) Preferences::get('listPageSize', 50)->data; $subTitle = trans('firefly.without_category_between', ['start' => $start->isoFormat($this->monthAndDayFormat), 'end' => $end->isoFormat($this->monthAndDayFormat)]); $first = $this->journalRepos->firstNull()->date ?? clone $start; $periods = $this->getNoModelPeriodOverview('category', $first, $end); @@ -122,7 +123,7 @@ class NoCategoryController extends Controller $end = null; $periods = new Collection(); $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $pageSize = (int) Preferences::get('listPageSize', 50)->data; Log::debug('Start of noCategory()'); $subTitle = (string) trans('firefly.all_journals_without_category'); $first = $this->journalRepos->firstNull(); diff --git a/app/Http/Controllers/Category/ShowController.php b/app/Http/Controllers/Category/ShowController.php index 101bf3f75a..1df3544c91 100644 --- a/app/Http/Controllers/Category/ShowController.php +++ b/app/Http/Controllers/Category/ShowController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Category; +use FireflyIII\Support\Facades\Preferences; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Helpers\Collector\GroupCollectorInterface; @@ -86,7 +87,7 @@ class ShowController extends Controller $subTitleIcon = 'fa-bookmark'; $page = (int) $request->get('page'); $attachments = $this->repository->getAttachments($category); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $pageSize = (int) Preferences::get('listPageSize', 50)->data; $oldest = $this->repository->firstUseDate($category) ?? today(config('app.timezone'))->startOfYear(); $periods = $this->getCategoryPeriodOverview($category, $oldest, $end); $path = route('categories.show', [$category->id, $start->format('Y-m-d'), $end->format('Y-m-d')]); @@ -125,7 +126,7 @@ class ShowController extends Controller // default values: $subTitleIcon = 'fa-bookmark'; $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $pageSize = (int) Preferences::get('listPageSize', 50)->data; $start = null; $end = null; $periods = new Collection(); diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index b3cff18071..67118821c6 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers; +use FireflyIII\Support\Facades\Preferences; use Carbon\Carbon; use Carbon\Exceptions\InvalidFormatException; use Exception; @@ -146,7 +147,7 @@ class HomeController extends Controller $count = $repository->count($types); $subTitle = (string) trans('firefly.welcome_back'); $transactions = []; - $frontpage = app('preferences')->getFresh('frontpageAccounts', $repository->getAccountsByType([AccountTypeEnum::ASSET->value])->pluck('id')->toArray()); + $frontpage = Preferences::getFresh('frontpageAccounts', $repository->getAccountsByType([AccountTypeEnum::ASSET->value])->pluck('id')->toArray()); $frontpageArray = $frontpage->data; if (!is_array($frontpageArray)) { $frontpageArray = []; diff --git a/app/Http/Controllers/JavascriptController.php b/app/Http/Controllers/JavascriptController.php index 059e005eb9..65eeab1fa4 100644 --- a/app/Http/Controllers/JavascriptController.php +++ b/app/Http/Controllers/JavascriptController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers; +use FireflyIII\Support\Facades\Preferences; use Carbon\Carbon; use FireflyIII\Enums\AccountTypeEnum; use FireflyIII\Exceptions\FireflyException; @@ -107,7 +108,7 @@ class JavascriptController extends Controller $locale = app('steam')->getLocale(); $accounting = app('amount')->getJsConfig(); $accounting['frac_digits'] = $currency->decimal_places; - $pref = app('preferences')->get('language', config('firefly.default_language', 'en_US')); + $pref = Preferences::get('language', config('firefly.default_language', 'en_US')); $lang = $pref->data; $dateRange = $this->getDateRangeConfig(); $uid = substr(hash('sha256', sprintf('%s-%s-%s', (string) config('app.key'), auth()->user()->id, auth()->user()->email)), 0, 12); diff --git a/app/Http/Controllers/Json/IntroController.php b/app/Http/Controllers/Json/IntroController.php index 9025051314..30badd5350 100644 --- a/app/Http/Controllers/Json/IntroController.php +++ b/app/Http/Controllers/Json/IntroController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Json; +use FireflyIII\Support\Facades\Preferences; use Illuminate\Support\Facades\Log; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Support\Http\Controllers\GetConfigurationData; @@ -98,8 +99,8 @@ class IntroController extends Controller $key = sprintf('%s_%s', $key, $specialPage); } Log::debug(sprintf('Going to mark the following route as NOT done: %s with special "%s" (%s)', $route, $specialPage, $key)); - app('preferences')->set($key, false); - app('preferences')->mark(); + Preferences::set($key, false); + Preferences::mark(); return response()->json(['message' => (string) trans('firefly.intro_boxes_after_refresh')]); } @@ -115,7 +116,7 @@ class IntroController extends Controller $key = sprintf('%s_%s', $key, $specialPage); } Log::debug(sprintf('Going to mark the following route as done: %s with special "%s" (%s)', $route, $specialPage, $key)); - app('preferences')->set($key, true); + Preferences::set($key, true); return response()->json(['result' => sprintf('Reported demo watched for route "%s" (%s): %s.', $route, $specialPage, $key)]); } diff --git a/app/Http/Controllers/NewUserController.php b/app/Http/Controllers/NewUserController.php index db8360ba6f..9b92f08074 100644 --- a/app/Http/Controllers/NewUserController.php +++ b/app/Http/Controllers/NewUserController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Enums\AccountTypeEnum; use FireflyIII\Http\Requests\NewUserFormRequest; use FireflyIII\Models\TransactionCurrency; @@ -92,7 +93,7 @@ class NewUserController extends Controller } // set language preference: - app('preferences')->set('language', $language); + Preferences::set('language', $language); // Store currency preference from input: $currency = $currencyRepository->find((int) $request->input('amount_currency_id_bank_balance')); @@ -111,10 +112,10 @@ class NewUserController extends Controller // store frontpage preferences: $accounts = $this->repository->getAccountsByType([AccountTypeEnum::ASSET->value])->pluck('id')->toArray(); - app('preferences')->set('frontpageAccounts', $accounts); + Preferences::set('frontpageAccounts', $accounts); // mark. - app('preferences')->mark(); + Preferences::mark(); // set default optional fields: $visibleFields = [ @@ -128,10 +129,10 @@ class NewUserController extends Controller 'notes' => true, 'attachments' => true, ]; - app('preferences')->set('transaction_journal_optional_fields', $visibleFields); + Preferences::set('transaction_journal_optional_fields', $visibleFields); session()->flash('success', (string) trans('firefly.stored_new_accounts_new_user')); - app('preferences')->mark(); + Preferences::mark(); return redirect(route('index')); } diff --git a/app/Http/Controllers/ObjectGroup/DeleteController.php b/app/Http/Controllers/ObjectGroup/DeleteController.php index 52c4b61466..6024db89a4 100644 --- a/app/Http/Controllers/ObjectGroup/DeleteController.php +++ b/app/Http/Controllers/ObjectGroup/DeleteController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\ObjectGroup; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\ObjectGroup; use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface; @@ -77,7 +78,7 @@ class DeleteController extends Controller public function destroy(ObjectGroup $objectGroup): RedirectResponse { session()->flash('success', (string) trans('firefly.deleted_object_group', ['title' => $objectGroup->title])); - app('preferences')->mark(); + Preferences::mark(); $this->repository->destroy($objectGroup); return redirect($this->getPreviousUrl('object-groups.delete.url')); diff --git a/app/Http/Controllers/ObjectGroup/EditController.php b/app/Http/Controllers/ObjectGroup/EditController.php index c3a3355eb6..f446765aa2 100644 --- a/app/Http/Controllers/ObjectGroup/EditController.php +++ b/app/Http/Controllers/ObjectGroup/EditController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\ObjectGroup; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Requests\ObjectGroupFormRequest; use FireflyIII\Models\ObjectGroup; @@ -87,7 +88,7 @@ class EditController extends Controller $piggyBank = $this->repository->update($objectGroup, $data); session()->flash('success', (string) trans('firefly.updated_object_group', ['title' => $objectGroup->title])); - app('preferences')->mark(); + Preferences::mark(); $redirect = redirect($this->getPreviousUrl('object-groups.edit.url')); diff --git a/app/Http/Controllers/PiggyBank/AmountController.php b/app/Http/Controllers/PiggyBank/AmountController.php index 011ba2a445..659da06f57 100644 --- a/app/Http/Controllers/PiggyBank/AmountController.php +++ b/app/Http/Controllers/PiggyBank/AmountController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\PiggyBank; +use FireflyIII\Support\Facades\Preferences; use Carbon\Carbon; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\Account; @@ -167,7 +168,7 @@ class AmountController extends Controller } if (0 !== bccomp($total, '0')) { session()->flash('success', (string) trans('firefly.added_amount_to_piggy', ['amount' => app('amount')->formatAnything($piggyBank->transactionCurrency, $total, false), 'name' => $piggyBank->name])); - app('preferences')->mark(); + Preferences::mark(); return redirect(route('piggy-banks.index')); } @@ -216,7 +217,7 @@ class AmountController extends Controller ['amount' => app('amount')->formatAnything($piggyBank->transactionCurrency, $total, false), 'name' => $piggyBank->name] ) ); - app('preferences')->mark(); + Preferences::mark(); return redirect(route('piggy-banks.index')); } diff --git a/app/Http/Controllers/PiggyBank/CreateController.php b/app/Http/Controllers/PiggyBank/CreateController.php index 6cf391dd4a..6c734618ad 100644 --- a/app/Http/Controllers/PiggyBank/CreateController.php +++ b/app/Http/Controllers/PiggyBank/CreateController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\PiggyBank; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Helpers\Attachments\AttachmentHelperInterface; use FireflyIII\Http\Controllers\Controller; @@ -106,7 +107,7 @@ class CreateController extends Controller session()->flash('success', (string) trans('firefly.stored_piggy_bank', ['name' => $piggyBank->name])); session()->flash('success_url', route('piggy-banks.show', [$piggyBank->id])); - app('preferences')->mark(); + Preferences::mark(); // store attachment(s): /** @var null|array $files */ diff --git a/app/Http/Controllers/PiggyBank/DeleteController.php b/app/Http/Controllers/PiggyBank/DeleteController.php index f267db4a5e..e2cb6caf58 100644 --- a/app/Http/Controllers/PiggyBank/DeleteController.php +++ b/app/Http/Controllers/PiggyBank/DeleteController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\PiggyBank; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\PiggyBank; use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; @@ -78,7 +79,7 @@ class DeleteController extends Controller public function destroy(PiggyBank $piggyBank): RedirectResponse { session()->flash('success', (string) trans('firefly.deleted_piggy_bank', ['name' => $piggyBank->name])); - app('preferences')->mark(); + Preferences::mark(); $this->piggyRepos->destroy($piggyBank); return redirect($this->getPreviousUrl('piggy-banks.delete.url')); diff --git a/app/Http/Controllers/PiggyBank/EditController.php b/app/Http/Controllers/PiggyBank/EditController.php index 4140e68da7..67fee2f363 100644 --- a/app/Http/Controllers/PiggyBank/EditController.php +++ b/app/Http/Controllers/PiggyBank/EditController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\PiggyBank; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Helpers\Attachments\AttachmentHelperInterface; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Requests\PiggyBankUpdateRequest; @@ -121,7 +122,7 @@ class EditController extends Controller $piggyBank = $this->piggyRepos->update($piggyBank, $data); session()->flash('success', (string) trans('firefly.updated_piggy_bank', ['name' => $piggyBank->name])); - app('preferences')->mark(); + Preferences::mark(); // store new attachment(s): /** @var null|array $files */ diff --git a/app/Http/Controllers/Profile/MfaController.php b/app/Http/Controllers/Profile/MfaController.php index e434a2e525..23ff40d41b 100644 --- a/app/Http/Controllers/Profile/MfaController.php +++ b/app/Http/Controllers/Profile/MfaController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Profile; +use FireflyIII\Support\Facades\Preferences; use Carbon\Carbon; use FireflyIII\Events\Security\DisabledMFA; use FireflyIII\Events\Security\EnabledMFA; @@ -124,8 +125,8 @@ class MfaController extends Controller ; $codes = implode("\r\n", $recoveryCodes); - app('preferences')->set('mfa_recovery', $recoveryCodes); - app('preferences')->mark(); + Preferences::set('mfa_recovery', $recoveryCodes); + Preferences::mark(); // send user notification. $user = auth()->user(); @@ -172,10 +173,10 @@ class MfaController extends Controller /** @var User $user */ $user = auth()->user(); - app('preferences')->delete('temp-mfa-secret'); - app('preferences')->delete('temp-mfa-codes'); + Preferences::delete('temp-mfa-secret'); + Preferences::delete('temp-mfa-codes'); $repository->setMFACode($user, null); - app('preferences')->mark(); + Preferences::mark(); session()->flash('success', (string) trans('firefly.pref_two_factor_auth_disabled')); session()->flash('info', (string) trans('firefly.pref_two_factor_auth_remove_it')); @@ -218,7 +219,7 @@ class MfaController extends Controller $secret = Google2FA::generateSecretKey(); $image = Google2FA::getQRCodeInline($domain, auth()->user()->email, $secret); - app('preferences')->set('temp-mfa-secret', $secret); + Preferences::set('temp-mfa-secret', $secret); return view('profile.mfa.enable-mfa', ['image' => $image, 'secret' => $secret]); @@ -252,7 +253,7 @@ class MfaController extends Controller /** @var UserRepositoryInterface $repository */ $repository = app(UserRepositoryInterface::class); - $secret = app('preferences')->get('temp-mfa-secret')?->data; + $secret = Preferences::get('temp-mfa-secret')?->data; if (is_array($secret)) { $secret = null; } @@ -260,10 +261,10 @@ class MfaController extends Controller $repository->setMFACode($user, $secret); - app('preferences')->delete('temp-mfa-secret'); + Preferences::delete('temp-mfa-secret'); session()->flash('success', (string) trans('firefly.saved_preferences')); - app('preferences')->mark(); + Preferences::mark(); // also save the code so replay attack is prevented. $mfaCode = $request->get('code'); @@ -293,14 +294,14 @@ class MfaController extends Controller private function addToMFAHistory(string $mfaCode): void { /** @var array $mfaHistory */ - $mfaHistory = app('preferences')->get('mfa_history', [])->data; + $mfaHistory = Preferences::get('mfa_history', [])->data; $entry = [ 'time' => Carbon::now()->getTimestamp(), 'code' => $mfaCode, ]; $mfaHistory[] = $entry; - app('preferences')->set('mfa_history', $mfaHistory); + Preferences::set('mfa_history', $mfaHistory); $this->filterMFAHistory(); } @@ -310,7 +311,7 @@ class MfaController extends Controller private function filterMFAHistory(): void { /** @var array $mfaHistory */ - $mfaHistory = app('preferences')->get('mfa_history', [])->data; + $mfaHistory = Preferences::get('mfa_history', [])->data; $newHistory = []; $now = Carbon::now()->getTimestamp(); foreach ($mfaHistory as $entry) { @@ -323,7 +324,7 @@ class MfaController extends Controller ]; } } - app('preferences')->set('mfa_history', $newHistory); + Preferences::set('mfa_history', $newHistory); } public function index(): Factory|RedirectResponse|View diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php index 67e28666fd..dabe7f6b2d 100644 --- a/app/Http/Controllers/ProfileController.php +++ b/app/Http/Controllers/ProfileController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers; +use FireflyIII\Support\Facades\Preferences; use Illuminate\Support\Facades\Log; use Exception; use FireflyIII\Events\UserChangedEmail; @@ -98,7 +99,7 @@ class ProfileController extends Controller // find preference with this token value. /** @var Collection $set */ - $set = app('preferences')->findByName('email_change_confirm_token'); + $set = Preferences::findByName('email_change_confirm_token'); $user = null; /** @var Preference $preference */ @@ -151,7 +152,7 @@ class ProfileController extends Controller $subTitle = $user->email; $userId = $user->id; $enabled2FA = null !== $user->mfa_secret; - $recoveryData = app('preferences')->get('mfa_recovery', [])->data; + $recoveryData = Preferences::get('mfa_recovery', [])->data; if (!is_array($recoveryData)) { $recoveryData = []; } @@ -165,10 +166,10 @@ class ProfileController extends Controller $repository->createPersonalAccessClient(null, $name, 'http://localhost'); } - $accessToken = app('preferences')->get('access_token'); + $accessToken = Preferences::get('access_token'); if (null === $accessToken) { $token = $user->generateAccessToken(); - $accessToken = app('preferences')->set('access_token', $token); + $accessToken = Preferences::set('access_token', $token); } return view( @@ -374,7 +375,7 @@ class ProfileController extends Controller /** @var User $user */ $user = auth()->user(); $token = $user->generateAccessToken(); - app('preferences')->set('access_token', $token); + Preferences::set('access_token', $token); session()->flash('success', (string) trans('firefly.token_regenerated')); return redirect(route('profile.index')); @@ -392,7 +393,7 @@ class ProfileController extends Controller } // find preference with this token value. - $set = app('preferences')->findByName('email_change_undo_token'); + $set = Preferences::findByName('email_change_undo_token'); $user = null; /** @var Preference $preference */ @@ -406,7 +407,7 @@ class ProfileController extends Controller } // found user.which email address to return to? - $set = app('preferences')->beginsWith($user, 'previous_email_'); + $set = Preferences::beginsWith($user, 'previous_email_'); /** @var null|string $match */ $match = null; diff --git a/app/Http/Controllers/Recurring/CreateController.php b/app/Http/Controllers/Recurring/CreateController.php index 16bf091f03..abca6a0971 100644 --- a/app/Http/Controllers/Recurring/CreateController.php +++ b/app/Http/Controllers/Recurring/CreateController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Recurring; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Enums\RecurrenceRepetitionWeekend; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Helpers\Attachments\AttachmentHelperInterface; @@ -228,7 +229,7 @@ class CreateController extends Controller Log::channel('audit')->info('Stored new recurrence.', $data); $request->session()->flash('success', (string) trans('firefly.stored_new_recurrence', ['title' => $recurrence->title])); - app('preferences')->mark(); + Preferences::mark(); // store attachment(s): /** @var null|array $files */ diff --git a/app/Http/Controllers/Recurring/DeleteController.php b/app/Http/Controllers/Recurring/DeleteController.php index 35d1017f00..b542f2998e 100644 --- a/app/Http/Controllers/Recurring/DeleteController.php +++ b/app/Http/Controllers/Recurring/DeleteController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Recurring; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\Recurrence; use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; @@ -83,7 +84,7 @@ class DeleteController extends Controller { $repository->destroy($recurrence); $request->session()->flash('success', (string) trans('firefly.recurrence_deleted', ['title' => $recurrence->title])); - app('preferences')->mark(); + Preferences::mark(); return redirect($this->getPreviousUrl('recurrences.delete.url')); } diff --git a/app/Http/Controllers/Recurring/EditController.php b/app/Http/Controllers/Recurring/EditController.php index 0141ce94f2..c12c8b4773 100644 --- a/app/Http/Controllers/Recurring/EditController.php +++ b/app/Http/Controllers/Recurring/EditController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Recurring; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Enums\RecurrenceRepetitionWeekend; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Helpers\Attachments\AttachmentHelperInterface; @@ -193,7 +194,7 @@ class EditController extends Controller if (count($this->attachments->getMessages()->get('attachments')) > 0) { $request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); } - app('preferences')->mark(); + Preferences::mark(); $redirect = redirect($this->getPreviousUrl('recurrences.edit.url')); if (1 === (int) $request->get('return_to_edit')) { // set value so edit routine will not overwrite URL: diff --git a/app/Http/Controllers/Recurring/IndexController.php b/app/Http/Controllers/Recurring/IndexController.php index 48d840828f..24cc4556d8 100644 --- a/app/Http/Controllers/Recurring/IndexController.php +++ b/app/Http/Controllers/Recurring/IndexController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Recurring; +use FireflyIII\Support\Facades\Preferences; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Http\Controllers\Controller; @@ -82,7 +83,7 @@ class IndexController extends Controller public function index(Request $request): Factory|\Illuminate\Contracts\View\View { $page = 0 === (int) $request->get('page') ? 1 : (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $pageSize = (int) Preferences::get('listPageSize', 50)->data; $collection = $this->repository->get(); $today = today(config('app.timezone')); $year = today(config('app.timezone')); diff --git a/app/Http/Controllers/ReportController.php b/app/Http/Controllers/ReportController.php index 3cdc068f1e..02a889a320 100644 --- a/app/Http/Controllers/ReportController.php +++ b/app/Http/Controllers/ReportController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers; +use FireflyIII\Support\Facades\Preferences; use Illuminate\Support\Facades\Log; use Carbon\Carbon; use FireflyIII\Enums\AccountTypeEnum; @@ -227,7 +228,7 @@ class ReportController extends Controller /** @var Carbon $start */ $start = clone session('first', today(config('app.timezone'))); $months = $this->helper->listOfMonths($start); - $customFiscalYear = app('preferences')->get('customFiscalYear', 0)->data; + $customFiscalYear = Preferences::get('customFiscalYear', 0)->data; $accounts = $repository->getAccountsByType( [AccountTypeEnum::DEFAULT->value, AccountTypeEnum::ASSET->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value] ); diff --git a/app/Http/Controllers/Rule/CreateController.php b/app/Http/Controllers/Rule/CreateController.php index d1f0809cc3..d70ab54921 100644 --- a/app/Http/Controllers/Rule/CreateController.php +++ b/app/Http/Controllers/Rule/CreateController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Rule; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Requests\RuleFormRequest; @@ -269,7 +270,7 @@ class CreateController extends Controller $rule = $this->ruleRepos->store($data); session()->flash('success_url', route('rules.select-transactions', [$rule->id])); session()->flash('success', (string) trans('firefly.stored_new_rule', ['title' => $rule->title])); - app('preferences')->mark(); + Preferences::mark(); // redirect to show bill. if ('true' === $request->get('return_to_bill') && (int) $request->get('bill_id') > 0) { diff --git a/app/Http/Controllers/Rule/DeleteController.php b/app/Http/Controllers/Rule/DeleteController.php index f9d86b7abe..14332b7c14 100644 --- a/app/Http/Controllers/Rule/DeleteController.php +++ b/app/Http/Controllers/Rule/DeleteController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Rule; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\Rule; use FireflyIII\Repositories\Rule\RuleRepositoryInterface; @@ -82,7 +83,7 @@ class DeleteController extends Controller $this->ruleRepos->destroy($rule); session()->flash('success', (string) trans('firefly.deleted_rule', ['title' => $title])); - app('preferences')->mark(); + Preferences::mark(); return redirect($this->getPreviousUrl('rules.delete.url')); } diff --git a/app/Http/Controllers/Rule/EditController.php b/app/Http/Controllers/Rule/EditController.php index cdc80c0219..ff6b44ede7 100644 --- a/app/Http/Controllers/Rule/EditController.php +++ b/app/Http/Controllers/Rule/EditController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Rule; +use FireflyIII\Support\Facades\Preferences; use Illuminate\Support\Facades\Log; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Http\Controllers\Controller; @@ -204,7 +205,7 @@ class EditController extends Controller $this->ruleRepos->update($rule, $data); session()->flash('success', (string) trans('firefly.updated_rule', ['title' => $rule->title])); - app('preferences')->mark(); + Preferences::mark(); $redirect = redirect($this->getPreviousUrl('rules.edit.url')); if (true === $data['run_after_form']) { diff --git a/app/Http/Controllers/RuleGroup/CreateController.php b/app/Http/Controllers/RuleGroup/CreateController.php index 9f76923ce8..dfe919246b 100644 --- a/app/Http/Controllers/RuleGroup/CreateController.php +++ b/app/Http/Controllers/RuleGroup/CreateController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\RuleGroup; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Requests\RuleGroupFormRequest; use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface; @@ -89,7 +90,7 @@ class CreateController extends Controller $ruleGroup = $this->repository->store($data); session()->flash('success', (string) trans('firefly.created_new_rule_group', ['title' => $ruleGroup->title])); - app('preferences')->mark(); + Preferences::mark(); $redirect = redirect($this->getPreviousUrl('rule-groups.create.url')); if (1 === (int) $request->get('create_another')) { diff --git a/app/Http/Controllers/RuleGroup/DeleteController.php b/app/Http/Controllers/RuleGroup/DeleteController.php index 6782f5e8bb..d788955054 100644 --- a/app/Http/Controllers/RuleGroup/DeleteController.php +++ b/app/Http/Controllers/RuleGroup/DeleteController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\RuleGroup; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\RuleGroup; use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface; @@ -87,7 +88,7 @@ class DeleteController extends Controller $this->repository->destroy($ruleGroup, $moveTo); session()->flash('success', (string) trans('firefly.deleted_rule_group', ['title' => $title])); - app('preferences')->mark(); + Preferences::mark(); return redirect($this->getPreviousUrl('rule-groups.delete.url')); } diff --git a/app/Http/Controllers/RuleGroup/EditController.php b/app/Http/Controllers/RuleGroup/EditController.php index 877c8ddc97..637b004aac 100644 --- a/app/Http/Controllers/RuleGroup/EditController.php +++ b/app/Http/Controllers/RuleGroup/EditController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\RuleGroup; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Requests\RuleGroupFormRequest; use FireflyIII\Models\RuleGroup; @@ -129,7 +130,7 @@ class EditController extends Controller $this->repository->update($ruleGroup, $data); session()->flash('success', (string) trans('firefly.updated_rule_group', ['title' => $ruleGroup->title])); - app('preferences')->mark(); + Preferences::mark(); $redirect = redirect($this->getPreviousUrl('rule-groups.edit.url')); if (1 === (int) $request->get('return_to_edit')) { session()->put('rule-groups.edit.fromUpdate', true); diff --git a/app/Http/Controllers/System/InstallController.php b/app/Http/Controllers/System/InstallController.php index 8a8a163082..94b6c9771d 100644 --- a/app/Http/Controllers/System/InstallController.php +++ b/app/Http/Controllers/System/InstallController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\System; +use FireflyIII\Support\Facades\Preferences; use Exception; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Http\Controllers\Controller; @@ -149,7 +150,7 @@ class InstallController extends Controller } // clear cache as well. Cache::clear(); - app('preferences')->mark(); + Preferences::mark(); return true; } diff --git a/app/Http/Controllers/TagController.php b/app/Http/Controllers/TagController.php index 8c8e1829a2..0ed269e73d 100644 --- a/app/Http/Controllers/TagController.php +++ b/app/Http/Controllers/TagController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers; +use FireflyIII\Support\Facades\Preferences; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Helpers\Attachments\AttachmentHelperInterface; @@ -212,7 +213,7 @@ class TagController extends Controller $this->repository->destroy($tag); session()->flash('success', (string) trans('firefly.deleted_tag', ['tag' => $tagName])); - app('preferences')->mark(); + Preferences::mark(); return redirect($this->getPreviousUrl('tags.delete.url')); } @@ -231,7 +232,7 @@ class TagController extends Controller // default values: $subTitleIcon = 'fa-tag'; $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $pageSize = (int) Preferences::get('listPageSize', 50)->data; $start ??= session('start'); $end ??= session('end'); $location = $this->repository->getLocation($tag); @@ -275,7 +276,7 @@ class TagController extends Controller // default values: $subTitleIcon = 'fa-tag'; $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $pageSize = (int) Preferences::get('listPageSize', 50)->data; $periods = []; $subTitle = (string) trans('firefly.all_journals_for_tag', ['tag' => $tag->tag]); $start = $this->repository->firstUseDate($tag) ?? today(config('app.timezone')); @@ -309,7 +310,7 @@ class TagController extends Controller Log::debug('Data after storage', $result->toArray()); session()->flash('success', (string) trans('firefly.created_tag', ['tag' => $data['tag']])); - app('preferences')->mark(); + Preferences::mark(); // store attachment(s): /** @var null|array $files */ @@ -347,7 +348,7 @@ class TagController extends Controller $tag = $this->repository->update($tag, $data); session()->flash('success', (string) trans('firefly.updated_tag', ['tag' => $data['tag']])); - app('preferences')->mark(); + Preferences::mark(); // store new attachment(s): /** @var null|array $files */ diff --git a/app/Http/Controllers/Transaction/BulkController.php b/app/Http/Controllers/Transaction/BulkController.php index b0d62692c1..0e4e79bf00 100644 --- a/app/Http/Controllers/Transaction/BulkController.php +++ b/app/Http/Controllers/Transaction/BulkController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Transaction; +use FireflyIII\Support\Facades\Preferences; use Illuminate\Support\Facades\Log; use FireflyIII\Events\UpdatedTransactionGroup; use FireflyIII\Http\Controllers\Controller; @@ -122,7 +123,7 @@ class BulkController extends Controller event(new UpdatedTransactionGroup($journal->transactionGroup, true, true, false)); } - app('preferences')->mark(); + Preferences::mark(); $request->session()->flash('success', trans_choice('firefly.mass_edited_transactions_success', $count)); // redirect to previous URL: diff --git a/app/Http/Controllers/Transaction/DeleteController.php b/app/Http/Controllers/Transaction/DeleteController.php index 1e82c2cd12..436d936ece 100644 --- a/app/Http/Controllers/Transaction/DeleteController.php +++ b/app/Http/Controllers/Transaction/DeleteController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Transaction; +use FireflyIII\Support\Facades\Preferences; use Illuminate\Support\Facades\Log; use FireflyIII\Events\UpdatedAccount; use FireflyIII\Http\Controllers\Controller; @@ -129,7 +130,7 @@ class DeleteController extends Controller Log::debug(sprintf('Now going to trigger updated account event for account #%d', $account->id)); event(new UpdatedAccount($account)); } - app('preferences')->mark(); + Preferences::mark(); return redirect($this->getPreviousUrl('transactions.delete.url')); } diff --git a/app/Http/Controllers/Transaction/EditController.php b/app/Http/Controllers/Transaction/EditController.php index 00f0e0bc62..a217962960 100644 --- a/app/Http/Controllers/Transaction/EditController.php +++ b/app/Http/Controllers/Transaction/EditController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Transaction; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\TransactionGroup; use FireflyIII\Models\TransactionJournal; @@ -76,7 +77,7 @@ class EditController extends Controller */ public function edit(TransactionGroup $transactionGroup): Factory|\Illuminate\Contracts\View\View|Redirector|RedirectResponse { - app('preferences')->mark(); + Preferences::mark(); if (!$this->isEditableGroup($transactionGroup)) { return $this->redirectGroupToAccount($transactionGroup); @@ -98,7 +99,7 @@ class EditController extends Controller $previousUrl = str_replace($search, '', $previousUrl); // settings necessary for v2 - $optionalFields = app('preferences')->get('transaction_journal_optional_fields', [])->data; + $optionalFields = Preferences::get('transaction_journal_optional_fields', [])->data; if (!is_array($optionalFields)) { $optionalFields = []; } diff --git a/app/Http/Controllers/Transaction/IndexController.php b/app/Http/Controllers/Transaction/IndexController.php index 8c4d3a5db3..386ba1ec46 100644 --- a/app/Http/Controllers/Transaction/IndexController.php +++ b/app/Http/Controllers/Transaction/IndexController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Transaction; +use FireflyIII\Support\Facades\Preferences; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Helpers\Collector\GroupCollectorInterface; @@ -84,7 +85,7 @@ class IndexController extends Controller $subTitleIcon = config('firefly.transactionIconsByType.'.$objectType); $types = config('firefly.transactionTypesByType.'.$objectType); $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $pageSize = (int) Preferences::get('listPageSize', 50)->data; if (!$start instanceof Carbon) { $start = session('start'); @@ -137,7 +138,7 @@ class IndexController extends Controller $subTitleIcon = config('firefly.transactionIconsByType.'.$objectType); $types = config('firefly.transactionTypesByType.'.$objectType); $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $pageSize = (int) Preferences::get('listPageSize', 50)->data; $path = route('transactions.index.all', [$objectType]); $first = $this->repository->firstNull(); $start = $first instanceof TransactionJournal ? $first->date : new Carbon(); diff --git a/app/Http/Controllers/Transaction/LinkController.php b/app/Http/Controllers/Transaction/LinkController.php index e927ff9754..abe01f4427 100644 --- a/app/Http/Controllers/Transaction/LinkController.php +++ b/app/Http/Controllers/Transaction/LinkController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Transaction; +use FireflyIII\Support\Facades\Preferences; use Illuminate\Support\Facades\Log; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Requests\JournalLinkRequest; @@ -86,7 +87,7 @@ class LinkController extends Controller $this->repository->destroyLink($link); session()->flash('success', (string) trans('firefly.deleted_link')); - app('preferences')->mark(); + Preferences::mark(); return redirect((string) session('journal_links.delete.url')); } diff --git a/app/Http/Controllers/Transaction/MassController.php b/app/Http/Controllers/Transaction/MassController.php index 3c70dfb089..5ec860e98e 100644 --- a/app/Http/Controllers/Transaction/MassController.php +++ b/app/Http/Controllers/Transaction/MassController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Transaction; +use FireflyIII\Support\Facades\Preferences; use Carbon\Carbon; use FireflyIII\Enums\AccountTypeEnum; use FireflyIII\Enums\TransactionTypeEnum; @@ -110,7 +111,7 @@ class MassController extends Controller Log::debug(sprintf('Could not find transaction journal #%d', $journalId)); } } - app('preferences')->mark(); + Preferences::mark(); session()->flash('success', trans_choice('firefly.mass_deleted_transactions_success', $count)); // redirect to previous URL: @@ -177,7 +178,7 @@ class MassController extends Controller } } - app('preferences')->mark(); + Preferences::mark(); session()->flash('success', trans_choice('firefly.mass_edited_transactions_success', $count)); // redirect to previous URL: diff --git a/app/Http/Controllers/TransactionCurrency/EditController.php b/app/Http/Controllers/TransactionCurrency/EditController.php index 6bf640391d..b2e9a1ff86 100644 --- a/app/Http/Controllers/TransactionCurrency/EditController.php +++ b/app/Http/Controllers/TransactionCurrency/EditController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\TransactionCurrency; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Requests\CurrencyFormRequest; @@ -128,7 +129,7 @@ class EditController extends Controller $currency = $this->repository->update($currency, $data); Log::channel('audit')->info('Updated (POST) currency.', $data); $request->session()->flash('success', (string) trans('firefly.updated_currency', ['name' => $currency->name])); - app('preferences')->mark(); + Preferences::mark(); if (1 === (int) $request->get('return_to_edit')) { $request->session()->put('currencies.edit.fromUpdate', true); diff --git a/app/Http/Controllers/TransactionCurrency/IndexController.php b/app/Http/Controllers/TransactionCurrency/IndexController.php index fbaabe16ab..f2c264fd6f 100644 --- a/app/Http/Controllers/TransactionCurrency/IndexController.php +++ b/app/Http/Controllers/TransactionCurrency/IndexController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\TransactionCurrency; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; @@ -73,7 +74,7 @@ class IndexController extends Controller /** @var User $user */ $user = auth()->user(); $page = 0 === (int) $request->get('page') ? 1 : (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $pageSize = (int) Preferences::get('listPageSize', 50)->data; $collection = $this->repository->getAll(); // order so default and enabled are on top: diff --git a/app/Http/Middleware/InterestingMessage.php b/app/Http/Middleware/InterestingMessage.php index 70ca9fb2bf..4c84751eaf 100644 --- a/app/Http/Middleware/InterestingMessage.php +++ b/app/Http/Middleware/InterestingMessage.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Middleware; +use FireflyIII\Support\Facades\Preferences; use Closure; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Account; @@ -54,27 +55,27 @@ class InterestingMessage } if ($this->groupMessage($request)) { - app('preferences')->mark(); + Preferences::mark(); $this->handleGroupMessage($request); } if ($this->userGroupMessage($request)) { - app('preferences')->mark(); + Preferences::mark(); $this->handleUserGroupMessage($request); } if ($this->accountMessage($request)) { - app('preferences')->mark(); + Preferences::mark(); $this->handleAccountMessage($request); } if ($this->billMessage($request)) { - app('preferences')->mark(); + Preferences::mark(); $this->handleBillMessage($request); } if ($this->webhookMessage($request)) { - app('preferences')->mark(); + Preferences::mark(); $this->handleWebhookMessage($request); } if ($this->currencyMessage($request)) { - app('preferences')->mark(); + Preferences::mark(); $this->handleCurrencyMessage($request); } diff --git a/app/Http/Middleware/Range.php b/app/Http/Middleware/Range.php index 3d604b4afe..10f859435d 100644 --- a/app/Http/Middleware/Range.php +++ b/app/Http/Middleware/Range.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Middleware; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Support\Facades\Navigation; use Carbon\Carbon; use Closure; @@ -70,7 +71,7 @@ class Range // ignore preference. set the range to be the current month: if (!app('session')->has('start') && !app('session')->has('end')) { Log::debug('setRange: Session has no start or end.'); - $viewRange = app('preferences')->get('viewRange', '1M')->data; + $viewRange = Preferences::get('viewRange', '1M')->data; if (is_array($viewRange)) { $viewRange = '1M'; } @@ -138,7 +139,7 @@ class Range */ private function configureList(): void { - $pref = app('preferences')->get('list-length', config('firefly.list_length', 10))->data; + $pref = Preferences::get('list-length', config('firefly.list_length', 10))->data; app('view')->share('listLength', $pref); // share security message: diff --git a/app/Jobs/CreateRecurringTransactions.php b/app/Jobs/CreateRecurringTransactions.php index 9bbafdf3e4..16a3f2c9c3 100644 --- a/app/Jobs/CreateRecurringTransactions.php +++ b/app/Jobs/CreateRecurringTransactions.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Jobs; +use FireflyIII\Support\Facades\Preferences; use Carbon\Carbon; use FireflyIII\Events\RequestedReportOnJournals; use FireflyIII\Events\StoredTransactionGroup; @@ -132,7 +133,7 @@ class CreateRecurringTransactions implements ShouldQueue $this->groupRepository->setUser($recurrence->user); // clear cache for user - app('preferences')->setForUser($recurrence->user, 'lastActivity', microtime()); + Preferences::setForUser($recurrence->user, 'lastActivity', microtime()); Log::debug(sprintf('Now at recurrence #%d of user #%d', $recurrence->id, $recurrence->user_id)); $createdReps = $this->handleRepetitions($recurrence); @@ -150,7 +151,7 @@ class CreateRecurringTransactions implements ShouldQueue Log::debug('Done with handle()'); // clear cache: - app('preferences')->mark(); + Preferences::mark(); } private function filterRecurrences(Collection $recurrences): Collection @@ -414,6 +415,9 @@ class CreateRecurringTransactions implements ShouldQueue $transactions->first(); $return = []; + + + /** @var RecurrenceTransaction $transaction */ foreach ($transactions as $index => $transaction) { $single = [ diff --git a/app/Notifications/ReturnsAvailableChannels.php b/app/Notifications/ReturnsAvailableChannels.php index 523e95bbaa..0d4d5dd523 100644 --- a/app/Notifications/ReturnsAvailableChannels.php +++ b/app/Notifications/ReturnsAvailableChannels.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Notifications; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Support\Notifications\UrlValidator; use FireflyIII\User; use Illuminate\Support\Facades\Log; @@ -94,7 +95,7 @@ class ReturnsAvailableChannels $channels = ['mail']; if (true === config('notifications.channels.slack.enabled', false)) { - $slackUrl = (string) app('preferences')->getEncryptedForUser($user, 'slack_webhook_url', '')->data; + $slackUrl = (string) Preferences::getEncryptedForUser($user, 'slack_webhook_url', '')->data; if (UrlValidator::isValidWebhookURL($slackUrl)) { $channels[] = 'slack'; } @@ -102,20 +103,20 @@ class ReturnsAvailableChannels // // validate presence of of Ntfy settings. // if (true === config('notifications.channels.nfy.enabled', false)) { - // $ntfyTopic = (string) app('preferences')->getEncryptedForUser($user, 'ntfy_topic', '')->data; + // $ntfyTopic = (string) \FireflyIII\Support\Facades\Preferences::getEncryptedForUser($user, 'ntfy_topic', '')->data; // if ('' !== $ntfyTopic) { // Log::debug(sprintf('Enabled ntfy, "%s"', $ntfyTopic)); // $channels[] = NtfyChannel::class; // } - // if ('' === (string) app('preferences')->getEncryptedForUser($user, 'ntfy_topic', '')->data) { + // if ('' === (string) \FireflyIII\Support\Facades\Preferences::getEncryptedForUser($user, 'ntfy_topic', '')->data) { // Log::warning('No topic name for Ntfy, channel is disabled.'); // } // } // pushover if (true === config('notifications.channels.slack.enabled', false)) { - $pushoverAppToken = (string) app('preferences')->getEncryptedForUser($user, 'pushover_app_token', '')->data; - $pushoverUserToken = (string) app('preferences')->getEncryptedForUser($user, 'pushover_user_token', '')->data; + $pushoverAppToken = (string) Preferences::getEncryptedForUser($user, 'pushover_app_token', '')->data; + $pushoverUserToken = (string) Preferences::getEncryptedForUser($user, 'pushover_user_token', '')->data; if ('' === $pushoverAppToken || '' === $pushoverUserToken) { Log::warning('[b] No Pushover token, channel is disabled.'); } diff --git a/app/Repositories/Recurring/RecurringRepository.php b/app/Repositories/Recurring/RecurringRepository.php index 9726e41297..468abca8ad 100644 --- a/app/Repositories/Recurring/RecurringRepository.php +++ b/app/Repositories/Recurring/RecurringRepository.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Repositories\Recurring; +use FireflyIII\Support\Facades\Preferences; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Factory\RecurrenceFactory; @@ -436,7 +437,7 @@ class RecurringRepository implements RecurringRepositoryInterface, UserGroupInte Log::debug('Now in repetitionDescription()'); /** @var Preference $pref */ - $pref = app('preferences')->getForUser($this->user, 'language', config('firefly.default_language', 'en_US')); + $pref = Preferences::getForUser($this->user, 'language', config('firefly.default_language', 'en_US')); $language = $pref->data; if (is_array($language)) { $language = 'en_US'; diff --git a/app/Repositories/User/UserRepository.php b/app/Repositories/User/UserRepository.php index be9abaf4df..2069994bcf 100644 --- a/app/Repositories/User/UserRepository.php +++ b/app/Repositories/User/UserRepository.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Repositories\User; +use FireflyIII\Support\Facades\Preferences; use Illuminate\Support\Facades\Log; use Carbon\Carbon; use Exception; @@ -57,12 +58,12 @@ class UserRepository implements UserRepositoryInterface $oldEmail = $user->email; // save old email as pref - app('preferences')->setForUser($user, 'previous_email_latest', $oldEmail); - app('preferences')->setForUser($user, 'previous_email_'.Carbon::now()->format('Y-m-d-H-i-s'), $oldEmail); + Preferences::setForUser($user, 'previous_email_latest', $oldEmail); + Preferences::setForUser($user, 'previous_email_'.Carbon::now()->format('Y-m-d-H-i-s'), $oldEmail); // set undo and confirm token: - app('preferences')->setForUser($user, 'email_change_undo_token', bin2hex(random_bytes(16))); - app('preferences')->setForUser($user, 'email_change_confirm_token', bin2hex(random_bytes(16))); + Preferences::setForUser($user, 'email_change_undo_token', bin2hex(random_bytes(16))); + Preferences::setForUser($user, 'email_change_confirm_token', bin2hex(random_bytes(16))); // update user $user->email = $newEmail; @@ -367,8 +368,8 @@ class UserRepository implements UserRepositoryInterface $oldEmail = $user->email; // save old email as pref - app('preferences')->setForUser($user, 'admin_previous_email_latest', $oldEmail); - app('preferences')->setForUser($user, 'admin_previous_email_'.Carbon::now()->format('Y-m-d-H-i-s'), $oldEmail); + Preferences::setForUser($user, 'admin_previous_email_latest', $oldEmail); + Preferences::setForUser($user, 'admin_previous_email_'.Carbon::now()->format('Y-m-d-H-i-s'), $oldEmail); $user->email = $newEmail; $user->save(); diff --git a/app/Services/Internal/Support/AccountServiceTrait.php b/app/Services/Internal/Support/AccountServiceTrait.php index 245410d31f..166792d150 100644 --- a/app/Services/Internal/Support/AccountServiceTrait.php +++ b/app/Services/Internal/Support/AccountServiceTrait.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Services\Internal\Support; +use FireflyIII\Support\Facades\Preferences; use Illuminate\Support\Facades\Log; use Carbon\Carbon; use Deprecated; @@ -193,7 +194,7 @@ trait AccountServiceTrait protected function createOBGroup(Account $account, array $data): TransactionGroup { Log::debug('Now going to create an OB group.'); - $language = app('preferences')->getForUser($account->user, 'language', 'en_US')->data; + $language = Preferences::getForUser($account->user, 'language', 'en_US')->data; if (is_array($language)) { $language = 'en_US'; } @@ -425,7 +426,7 @@ trait AccountServiceTrait throw new FireflyException('Amount for new liability credit was unexpectedly 0.'); } - $language = app('preferences')->getForUser($account->user, 'language', 'en_US')->data; + $language = Preferences::getForUser($account->user, 'language', 'en_US')->data; if (is_array($language)) { $language = 'en_US'; } @@ -615,7 +616,7 @@ trait AccountServiceTrait protected function createOBGroupV2(Account $account, string $openingBalance, Carbon $openingBalanceDate): TransactionGroup { Log::debug('Now going to create an OB group.'); - $language = app('preferences')->getForUser($account->user, 'language', 'en_US')->data; + $language = Preferences::getForUser($account->user, 'language', 'en_US')->data; if (is_array($language)) { $language = 'en_US'; } diff --git a/app/Services/Internal/Update/AccountUpdateService.php b/app/Services/Internal/Update/AccountUpdateService.php index ea1b758124..44c3dfedab 100644 --- a/app/Services/Internal/Update/AccountUpdateService.php +++ b/app/Services/Internal/Update/AccountUpdateService.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Services\Internal\Update; +use FireflyIII\Support\Facades\Preferences; use Illuminate\Support\Facades\Log; use FireflyIII\Enums\AccountTypeEnum; use FireflyIII\Events\UpdatedAccount; @@ -291,7 +292,7 @@ class AccountUpdateService if (true === $account->active) { return; } - $preference = app('preferences')->getForUser($account->user, 'frontpageAccounts'); + $preference = Preferences::getForUser($account->user, 'frontpageAccounts'); if (null === $preference) { return; } @@ -310,6 +311,6 @@ class AccountUpdateService } } Log::debug('Final new array is', $new); - app('preferences')->setForUser($account->user, 'frontpageAccounts', $new); + Preferences::setForUser($account->user, 'frontpageAccounts', $new); } } diff --git a/app/Services/Internal/Update/GroupUpdateService.php b/app/Services/Internal/Update/GroupUpdateService.php index 58c245d201..db983cff16 100644 --- a/app/Services/Internal/Update/GroupUpdateService.php +++ b/app/Services/Internal/Update/GroupUpdateService.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Services\Internal\Update; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Exceptions\DuplicateTransactionException; use FireflyIII\Exceptions\FireflyException; @@ -83,7 +84,7 @@ class GroupUpdateService $this->updateTransactionJournal($transactionGroup, $first, reset($transactions)); $transactionGroup->touch(); $transactionGroup->refresh(); - app('preferences')->mark(); + Preferences::mark(); return $transactionGroup; } @@ -98,7 +99,7 @@ class GroupUpdateService Log::error('There were no transactions updated or created. Will not delete anything.'); $transactionGroup->touch(); $transactionGroup->refresh(); - app('preferences')->mark(); + Preferences::mark(); return $transactionGroup; } @@ -116,7 +117,7 @@ class GroupUpdateService $service->destroy($journal); } - app('preferences')->mark(); + Preferences::mark(); $transactionGroup->touch(); $transactionGroup->refresh(); diff --git a/app/Services/Internal/Update/JournalUpdateService.php b/app/Services/Internal/Update/JournalUpdateService.php index 44278679bb..64a901690b 100644 --- a/app/Services/Internal/Update/JournalUpdateService.php +++ b/app/Services/Internal/Update/JournalUpdateService.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Services\Internal\Update; +use FireflyIII\Support\Facades\Preferences; use Carbon\Carbon; use Carbon\Exceptions\InvalidDateException; use Carbon\Exceptions\InvalidFormatException; @@ -165,7 +166,7 @@ class JournalUpdateService $this->updateAmount(); $this->updateForeignAmount(); - app('preferences')->mark(); + Preferences::mark(); $this->transactionJournal->refresh(); Log::debug('Done with update journal routine'); diff --git a/app/Support/Binder/CLIToken.php b/app/Support/Binder/CLIToken.php index d09da8c0b1..14a5ae6172 100644 --- a/app/Support/Binder/CLIToken.php +++ b/app/Support/Binder/CLIToken.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Support\Binder; +use FireflyIII\Support\Facades\Preferences; use Illuminate\Support\Facades\Log; use FireflyIII\Repositories\User\UserRepositoryInterface; use Illuminate\Routing\Route; @@ -46,7 +47,7 @@ class CLIToken implements BinderInterface } foreach ($users as $user) { - $accessToken = app('preferences')->getForUser($user, 'access_token'); + $accessToken = Preferences::getForUser($user, 'access_token'); if (null !== $accessToken && $accessToken->data === $value) { Log::info(sprintf('Recognized user #%d (%s) from his access token.', $user->id, $user->email)); diff --git a/app/Support/CacheProperties.php b/app/Support/CacheProperties.php index 5365656511..1414e07c91 100644 --- a/app/Support/CacheProperties.php +++ b/app/Support/CacheProperties.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Support; +use FireflyIII\Support\Facades\Preferences; use Carbon\Carbon; use FireflyIII\Support\Facades\Steam; use Illuminate\Support\Collection; @@ -44,7 +45,7 @@ class CacheProperties $this->properties = new Collection(); if (auth()->check()) { $this->addProperty(auth()->user()->id); - $this->addProperty(app('preferences')->lastActivity()); + $this->addProperty(Preferences::lastActivity()); $this->addProperty(Steam::anonymous()); } } diff --git a/app/Support/Cronjobs/AutoBudgetCronjob.php b/app/Support/Cronjobs/AutoBudgetCronjob.php index e4e82d2376..c9722c87fd 100644 --- a/app/Support/Cronjobs/AutoBudgetCronjob.php +++ b/app/Support/Cronjobs/AutoBudgetCronjob.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Support\Cronjobs; +use FireflyIII\Support\Facades\Preferences; use Carbon\Carbon; use FireflyIII\Jobs\CreateAutoBudgetLimits; use FireflyIII\Models\Configuration; @@ -62,7 +63,7 @@ class AutoBudgetCronjob extends AbstractCronjob } $this->fireAutoBudget(); - app('preferences')->mark(); + Preferences::mark(); } private function fireAutoBudget(): void diff --git a/app/Support/Cronjobs/BillWarningCronjob.php b/app/Support/Cronjobs/BillWarningCronjob.php index a358d5879e..be6d9e2f0d 100644 --- a/app/Support/Cronjobs/BillWarningCronjob.php +++ b/app/Support/Cronjobs/BillWarningCronjob.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Support\Cronjobs; +use FireflyIII\Support\Facades\Preferences; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Jobs\WarnAboutBills; @@ -74,7 +75,7 @@ class BillWarningCronjob extends AbstractCronjob $this->fireWarnings(); - app('preferences')->mark(); + Preferences::mark(); } private function fireWarnings(): void diff --git a/app/Support/Cronjobs/ExchangeRatesCronjob.php b/app/Support/Cronjobs/ExchangeRatesCronjob.php index 889d6e57de..98af3966d5 100644 --- a/app/Support/Cronjobs/ExchangeRatesCronjob.php +++ b/app/Support/Cronjobs/ExchangeRatesCronjob.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Support\Cronjobs; +use FireflyIII\Support\Facades\Preferences; use Carbon\Carbon; use FireflyIII\Jobs\DownloadExchangeRates; use FireflyIII\Models\Configuration; @@ -63,7 +64,7 @@ class ExchangeRatesCronjob extends AbstractCronjob } $this->fireExchangeRateJob(); - app('preferences')->mark(); + Preferences::mark(); } private function fireExchangeRateJob(): void diff --git a/app/Support/Cronjobs/RecurringCronjob.php b/app/Support/Cronjobs/RecurringCronjob.php index 5f4e11a4c2..297bfa8d66 100644 --- a/app/Support/Cronjobs/RecurringCronjob.php +++ b/app/Support/Cronjobs/RecurringCronjob.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Support\Cronjobs; +use FireflyIII\Support\Facades\Preferences; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Jobs\CreateRecurringTransactions; @@ -73,7 +74,7 @@ class RecurringCronjob extends AbstractCronjob $this->fireRecurring(); - app('preferences')->mark(); + Preferences::mark(); } private function fireRecurring(): void diff --git a/app/Support/Cronjobs/WebhookCronjob.php b/app/Support/Cronjobs/WebhookCronjob.php index 84ea6676f5..d6c57123de 100644 --- a/app/Support/Cronjobs/WebhookCronjob.php +++ b/app/Support/Cronjobs/WebhookCronjob.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Support\Cronjobs; +use FireflyIII\Support\Facades\Preferences; use Carbon\Carbon; use FireflyIII\Events\RequestedSendWebhookMessages; use FireflyIII\Exceptions\FireflyException; @@ -74,7 +75,7 @@ class WebhookCronjob extends AbstractCronjob $this->fireWebhookmessages(); - app('preferences')->mark(); + Preferences::mark(); } private function fireWebhookmessages(): void diff --git a/app/Support/Http/Api/CollectsAccountsFromFilter.php b/app/Support/Http/Api/CollectsAccountsFromFilter.php index 2911ed61f6..3c17a34d80 100644 --- a/app/Support/Http/Api/CollectsAccountsFromFilter.php +++ b/app/Support/Http/Api/CollectsAccountsFromFilter.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Support\Http\Api; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Enums\AccountTypeEnum; use Illuminate\Support\Collection; @@ -53,7 +54,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(); - $frontpage = app('preferences')->get('frontpageAccounts', $defaultSet); + $frontpage = Preferences::get('frontpageAccounts', $defaultSet); if (!(is_array($frontpage->data) && count($frontpage->data) > 0)) { $frontpage->data = $defaultSet; diff --git a/app/Support/Http/Controllers/RequestInformation.php b/app/Support/Http/Controllers/RequestInformation.php index 5b7be59977..1f4e42b0f7 100644 --- a/app/Support/Http/Controllers/RequestInformation.php +++ b/app/Support/Http/Controllers/RequestInformation.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Support\Http\Controllers; +use FireflyIII\Support\Facades\Preferences; use Carbon\Carbon; use FireflyIII\Exceptions\ValidationException; use FireflyIII\Http\Requests\RuleFormRequest; @@ -110,7 +111,7 @@ trait RequestInformation $shownDemo = true; // both must be array and either must be > 0 if (count($intro) > 0 || count($specialIntro) > 0) { - $shownDemo = app('preferences')->get($key, false)->data; + $shownDemo = Preferences::get($key, false)->data; } if (!is_bool($shownDemo)) { return true; diff --git a/app/Support/Navigation.php b/app/Support/Navigation.php index ce78a979f1..016605a3eb 100644 --- a/app/Support/Navigation.php +++ b/app/Support/Navigation.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Support; +use FireflyIII\Support\Facades\Preferences; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\IntervalException; @@ -381,7 +382,7 @@ class Navigation */ public function getViewRange(bool $correct): string { - $range = app('preferences')->get('viewRange', '1M')->data ?? '1M'; + $range = Preferences::get('viewRange', '1M')->data ?? '1M'; if (is_array($range)) { $range = '1M'; } diff --git a/app/Support/Observers/RecalculatesAvailableBudgetsTrait.php b/app/Support/Observers/RecalculatesAvailableBudgetsTrait.php index e55405de9e..52479f2de0 100644 --- a/app/Support/Observers/RecalculatesAvailableBudgetsTrait.php +++ b/app/Support/Observers/RecalculatesAvailableBudgetsTrait.php @@ -25,6 +25,7 @@ declare(strict_types=1); namespace FireflyIII\Support\Observers; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Models\AvailableBudget; use FireflyIII\Models\Budget; use FireflyIII\Models\BudgetLimit; @@ -161,7 +162,7 @@ trait RecalculatesAvailableBudgetsTrait // either overlap multiple available budget periods or be contained in a single one. // all have to be created or updated. try { - $viewRange = app('preferences')->getForUser($user, 'viewRange', '1M')->data; + $viewRange = Preferences::getForUser($user, 'viewRange', '1M')->data; } catch (ContainerExceptionInterface|NotFoundExceptionInterface $e) { Log::error($e->getMessage()); $viewRange = '1M'; diff --git a/app/Support/Search/OperatorQuerySearch.php b/app/Support/Search/OperatorQuerySearch.php index a8b8b6b961..38133e1daf 100644 --- a/app/Support/Search/OperatorQuerySearch.php +++ b/app/Support/Search/OperatorQuerySearch.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Support\Search; +use FireflyIII\Support\Facades\Preferences; use Carbon\Carbon; use FireflyIII\Enums\AccountTypeEnum; use FireflyIII\Enums\SearchDirection; @@ -238,7 +239,7 @@ class OperatorQuerySearch implements SearchInterface $this->collector->setUser($user); $this->collector->withAccountInformation()->withCategoryInformation()->withBudgetInformation(); - $this->setLimit((int)app('preferences')->getForUser($user, 'listPageSize', 50)->data); + $this->setLimit((int)Preferences::getForUser($user, 'listPageSize', 50)->data); } private function findCurrency(string $value): ?TransactionCurrency diff --git a/app/Support/Steam.php b/app/Support/Steam.php index 45b3595a40..939a9069b4 100644 --- a/app/Support/Steam.php +++ b/app/Support/Steam.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Support; +use FireflyIII\Support\Facades\Preferences; use Deprecated; use Carbon\Carbon; use Exception; @@ -573,7 +574,7 @@ class Steam */ public function getLanguage(): string // get preference { - $preference = app('preferences')->get('language', config('firefly.default_language', 'en_US'))->data; + $preference = Preferences::get('language', config('firefly.default_language', 'en_US'))->data; if (!is_string($preference)) { throw new FireflyException(sprintf('Preference "language" must be a string, but is unexpectedly a "%s".', gettype($preference))); } @@ -611,7 +612,7 @@ class Steam if (null !== $cached) { return $cached; } - $locale = app('preferences')->get('locale', config('firefly.default_locale', 'equal'))->data; + $locale = Preferences::get('locale', config('firefly.default_locale', 'equal'))->data; if (is_array($locale)) { $locale = 'equal'; } @@ -636,7 +637,7 @@ class Steam if (null !== $cached) { return $cached; } - $anonymous = app('preferences')->get('anonymous', config('firefly.default_preferences.anonymous', false))->data; + $anonymous = Preferences::get('anonymous', config('firefly.default_preferences.anonymous', false))->data; $singleton->setPreference('anonymous', $anonymous); return $anonymous; diff --git a/app/User.php b/app/User.php index 82c3f99bf5..d97b9a767b 100644 --- a/app/User.php +++ b/app/User.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII; +use FireflyIII\Support\Facades\Preferences; use Illuminate\Support\Facades\Log; use Deprecated; use Exception; @@ -357,7 +358,7 @@ class User extends Authenticatable } $email = $this->email; // see if user has alternative email address: - $pref = app('preferences')->getForUser($this, 'remote_guard_alt_email'); + $pref = Preferences::getForUser($this, 'remote_guard_alt_email'); if (null !== $pref) { $email = $pref->data; } @@ -390,8 +391,8 @@ class User extends Authenticatable public function routeNotificationForPushover(): PushoverReceiver { - $appToken = (string) app('preferences')->getEncrypted('pushover_app_token', '')->data; - $userToken = (string) app('preferences')->getEncrypted('pushover_user_token', '')->data; + $appToken = (string) Preferences::getEncrypted('pushover_app_token', '')->data; + $userToken = (string) Preferences::getEncrypted('pushover_user_token', '')->data; return PushoverReceiver::withUserKey($userToken)->withApplicationToken($appToken); } @@ -419,7 +420,7 @@ class User extends Authenticatable if ($notification instanceof VersionCheckResult) { return $res; } - $pref = app('preferences')->getEncryptedForUser($this, 'slack_webhook_url', '')->data; + $pref = Preferences::getEncryptedForUser($this, 'slack_webhook_url', '')->data; if (is_array($pref)) { return ''; } diff --git a/app/Validation/FireflyValidator.php b/app/Validation/FireflyValidator.php index c613f0064f..37ff7a4f81 100644 --- a/app/Validation/FireflyValidator.php +++ b/app/Validation/FireflyValidator.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Validation; +use FireflyIII\Support\Facades\Preferences; use Config; use FireflyIII\Enums\AccountTypeEnum; use FireflyIII\Exceptions\FireflyException; @@ -84,7 +85,7 @@ class FireflyValidator extends Validator return false; } - $secretPreference = app('preferences')->get('temp-mfa-secret'); + $secretPreference = Preferences::get('temp-mfa-secret'); $secret = $secretPreference->data ?? ''; if (is_array($secret)) { $secret = ''; From 30937610eb824597fbc65f97e7a000e8168569dd Mon Sep 17 00:00:00 2001 From: James Cole Date: Fri, 28 Nov 2025 19:02:50 +0100 Subject: [PATCH 24/26] Update changelog. --- changelog.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/changelog.md b/changelog.md index cd8ade13b5..c262f534de 100644 --- a/changelog.md +++ b/changelog.md @@ -8,7 +8,12 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - [Discussion 11211](https://github.com/orgs/firefly-iii/discussions/11211) (question about Transaction journal ID) started by @zhiiwg +- #11247 - [Issue 11267](https://github.com/firefly-iii/firefly-iii/issues/11267) (Tags can be added to elements that can't be removed) reported by @Fmstrat +- #11281 +- #11284 +- #11288 +- #11191 ### API From 212d579c4f44b62decb6073ffeba4bf8bac30d80 Mon Sep 17 00:00:00 2001 From: JC5 Date: Fri, 28 Nov 2025 19:08:14 +0100 Subject: [PATCH 25/26] =?UTF-8?q?=F0=9F=A4=96=20Auto=20commit=20for=20rele?= =?UTF-8?q?ase=20'develop'=20on=202025-11-28?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .ci/php-cs-fixer/composer.lock | 183 +++--- app/Handlers/Events/WebhookEventHandler.php | 1 + changelog.md | 10 +- composer.lock | 602 ++++++++++---------- config/firefly.php | 4 +- package-lock.json | 36 +- 6 files changed, 426 insertions(+), 410 deletions(-) diff --git a/.ci/php-cs-fixer/composer.lock b/.ci/php-cs-fixer/composer.lock index 83bfb70f78..f5760437d6 100644 --- a/.ci/php-cs-fixer/composer.lock +++ b/.ci/php-cs-fixer/composer.lock @@ -1251,47 +1251,39 @@ }, { "name": "symfony/console", - "version": "v7.3.6", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "c28ad91448f86c5f6d9d2c70f0cf68bf135f252a" + "reference": "307d3cf852f5ead3618ac60ecbedbdd512c348b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/c28ad91448f86c5f6d9d2c70f0cf68bf135f252a", - "reference": "c28ad91448f86c5f6d9d2c70f0cf68bf135f252a", + "url": "https://api.github.com/repos/symfony/console/zipball/307d3cf852f5ead3618ac60ecbedbdd512c348b1", + "reference": "307d3cf852f5ead3618ac60ecbedbdd512c348b1", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "~1.0", + "php": ">=8.4", + "symfony/polyfill-mbstring": "^1.0", "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^7.2" - }, - "conflict": { - "symfony/dependency-injection": "<6.4", - "symfony/dotenv": "<6.4", - "symfony/event-dispatcher": "<6.4", - "symfony/lock": "<6.4", - "symfony/process": "<6.4" + "symfony/string": "^7.4|^8.0" }, "provide": { "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/lock": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0" + "symfony/config": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/event-dispatcher": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/lock": "^7.4|^8.0", + "symfony/messenger": "^7.4|^8.0", + "symfony/process": "^7.4|^8.0", + "symfony/stopwatch": "^7.4|^8.0", + "symfony/var-dumper": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -1325,7 +1317,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.3.6" + "source": "https://github.com/symfony/console/tree/v8.0.0" }, "funding": [ { @@ -1345,7 +1337,7 @@ "type": "tidelift" } ], - "time": "2025-11-04T01:21:42+00:00" + "time": "2025-11-21T13:19:49+00:00" }, { "name": "symfony/deprecation-contracts", @@ -1416,24 +1408,24 @@ }, { "name": "symfony/event-dispatcher", - "version": "v7.3.3", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191" + "reference": "573f95783a2ec6e38752979db139f09fec033f03" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b7dc69e71de420ac04bc9ab830cf3ffebba48191", - "reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/573f95783a2ec6e38752979db139f09fec033f03", + "reference": "573f95783a2ec6e38752979db139f09fec033f03", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<6.4", + "symfony/security-http": "<7.4", "symfony/service-contracts": "<2.5" }, "provide": { @@ -1442,13 +1434,14 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/error-handler": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", + "symfony/config": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/error-handler": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/framework-bundle": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^6.4|^7.0" + "symfony/stopwatch": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -1476,7 +1469,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/v7.3.3" + "source": "https://github.com/symfony/event-dispatcher/tree/v8.0.0" }, "funding": [ { @@ -1496,7 +1489,7 @@ "type": "tidelift" } ], - "time": "2025-08-13T11:49:31+00:00" + "time": "2025-10-30T14:17:19+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -1576,25 +1569,25 @@ }, { "name": "symfony/filesystem", - "version": "v7.3.6", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "e9bcfd7837928ab656276fe00464092cc9e1826a" + "reference": "7fc96ae83372620eaba3826874f46e26295768ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/e9bcfd7837928ab656276fe00464092cc9e1826a", - "reference": "e9bcfd7837928ab656276fe00464092cc9e1826a", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/7fc96ae83372620eaba3826874f46e26295768ca", + "reference": "7fc96ae83372620eaba3826874f46e26295768ca", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.8" }, "require-dev": { - "symfony/process": "^6.4|^7.0" + "symfony/process": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -1622,7 +1615,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.3.6" + "source": "https://github.com/symfony/filesystem/tree/v8.0.0" }, "funding": [ { @@ -1642,27 +1635,27 @@ "type": "tidelift" } ], - "time": "2025-11-05T09:52:27+00:00" + "time": "2025-11-05T14:36:47+00:00" }, { "name": "symfony/finder", - "version": "v7.3.5", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "9f696d2f1e340484b4683f7853b273abff94421f" + "reference": "7598dd5770580fa3517ec83e8da0c9b9e01f4291" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/9f696d2f1e340484b4683f7853b273abff94421f", - "reference": "9f696d2f1e340484b4683f7853b273abff94421f", + "url": "https://api.github.com/repos/symfony/finder/zipball/7598dd5770580fa3517ec83e8da0c9b9e01f4291", + "reference": "7598dd5770580fa3517ec83e8da0c9b9e01f4291", "shasum": "" }, "require": { - "php": ">=8.2" + "php": ">=8.4" }, "require-dev": { - "symfony/filesystem": "^6.4|^7.0" + "symfony/filesystem": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -1690,7 +1683,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.3.5" + "source": "https://github.com/symfony/finder/tree/v8.0.0" }, "funding": [ { @@ -1710,24 +1703,24 @@ "type": "tidelift" } ], - "time": "2025-10-15T18:45:57+00:00" + "time": "2025-11-05T14:36:47+00:00" }, { "name": "symfony/options-resolver", - "version": "v7.3.3", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "0ff2f5c3df08a395232bbc3c2eb7e84912df911d" + "reference": "d2b592535ffa6600c265a3893a7f7fd2bad82dd7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/0ff2f5c3df08a395232bbc3c2eb7e84912df911d", - "reference": "0ff2f5c3df08a395232bbc3c2eb7e84912df911d", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/d2b592535ffa6600c265a3893a7f7fd2bad82dd7", + "reference": "d2b592535ffa6600c265a3893a7f7fd2bad82dd7", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "symfony/deprecation-contracts": "^2.5|^3" }, "type": "library", @@ -1761,7 +1754,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v7.3.3" + "source": "https://github.com/symfony/options-resolver/tree/v8.0.0" }, "funding": [ { @@ -1781,7 +1774,7 @@ "type": "tidelift" } ], - "time": "2025-08-05T10:16:07+00:00" + "time": "2025-11-12T15:55:31+00:00" }, { "name": "symfony/polyfill-ctype", @@ -2364,20 +2357,20 @@ }, { "name": "symfony/process", - "version": "v7.3.4", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "f24f8f316367b30810810d4eb30c543d7003ff3b" + "reference": "a0a750500c4ce900d69ba4e9faf16f82c10ee149" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/f24f8f316367b30810810d4eb30c543d7003ff3b", - "reference": "f24f8f316367b30810810d4eb30c543d7003ff3b", + "url": "https://api.github.com/repos/symfony/process/zipball/a0a750500c4ce900d69ba4e9faf16f82c10ee149", + "reference": "a0a750500c4ce900d69ba4e9faf16f82c10ee149", "shasum": "" }, "require": { - "php": ">=8.2" + "php": ">=8.4" }, "type": "library", "autoload": { @@ -2405,7 +2398,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.3.4" + "source": "https://github.com/symfony/process/tree/v8.0.0" }, "funding": [ { @@ -2425,7 +2418,7 @@ "type": "tidelift" } ], - "time": "2025-09-11T10:12:26+00:00" + "time": "2025-10-16T16:25:44+00:00" }, { "name": "symfony/service-contracts", @@ -2516,20 +2509,20 @@ }, { "name": "symfony/stopwatch", - "version": "v7.3.0", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd" + "reference": "67df1914c6ccd2d7b52f70d40cf2aea02159d942" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd", - "reference": "5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/67df1914c6ccd2d7b52f70d40cf2aea02159d942", + "reference": "67df1914c6ccd2d7b52f70d40cf2aea02159d942", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "symfony/service-contracts": "^2.5|^3" }, "type": "library", @@ -2558,7 +2551,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v7.3.0" + "source": "https://github.com/symfony/stopwatch/tree/v8.0.0" }, "funding": [ { @@ -2569,43 +2562,47 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-02-24T10:49:57+00:00" + "time": "2025-08-04T07:36:47+00:00" }, { "name": "symfony/string", - "version": "v7.3.4", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "f96476035142921000338bad71e5247fbc138872" + "reference": "f929eccf09531078c243df72398560e32fa4cf4f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/f96476035142921000338bad71e5247fbc138872", - "reference": "f96476035142921000338bad71e5247fbc138872", + "url": "https://api.github.com/repos/symfony/string/zipball/f929eccf09531078c243df72398560e32fa4cf4f", + "reference": "f929eccf09531078c243df72398560e32fa4cf4f", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" + "php": ">=8.4", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-intl-grapheme": "^1.33", + "symfony/polyfill-intl-normalizer": "^1.0", + "symfony/polyfill-mbstring": "^1.0" }, "conflict": { "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/emoji": "^7.1", - "symfony/http-client": "^6.4|^7.0", - "symfony/intl": "^6.4|^7.0", + "symfony/emoji": "^7.4|^8.0", + "symfony/http-client": "^7.4|^8.0", + "symfony/intl": "^7.4|^8.0", "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.4|^7.0" + "symfony/var-exporter": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -2644,7 +2641,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.3.4" + "source": "https://github.com/symfony/string/tree/v8.0.0" }, "funding": [ { @@ -2664,7 +2661,7 @@ "type": "tidelift" } ], - "time": "2025-09-11T14:36:48+00:00" + "time": "2025-09-11T14:37:55+00:00" } ], "packages-dev": [], diff --git a/app/Handlers/Events/WebhookEventHandler.php b/app/Handlers/Events/WebhookEventHandler.php index b83079e402..41f5d1ccf8 100644 --- a/app/Handlers/Events/WebhookEventHandler.php +++ b/app/Handlers/Events/WebhookEventHandler.php @@ -53,6 +53,7 @@ class WebhookEventHandler )->splice(0, 5) ; Log::debug(sprintf('Found %d webhook message(s) ready to be send.', $messages->count())); + /** @var WebhookMessage $message */ foreach ($messages as $message) { if (false === $message->sent) { diff --git a/changelog.md b/changelog.md index c262f534de..ff77631060 100644 --- a/changelog.md +++ b/changelog.md @@ -8,12 +8,12 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - [Discussion 11211](https://github.com/orgs/firefly-iii/discussions/11211) (question about Transaction journal ID) started by @zhiiwg -- #11247 +- [Issue 11247](https://github.com/firefly-iii/firefly-iii/issues/11247) (Optional transaction information not saved when updating a recurring transaction.) reported by @Tommy78649 - [Issue 11267](https://github.com/firefly-iii/firefly-iii/issues/11267) (Tags can be added to elements that can't be removed) reported by @Fmstrat -- #11281 -- #11284 -- #11288 -- #11191 +- [Issue 11281](https://github.com/firefly-iii/firefly-iii/issues/11281) (Webhooks are triggered twice when recurring creates transaction on cronjob) reported by @MexerSam +- [Issue 11284](https://github.com/firefly-iii/firefly-iii/issues/11284) (500 Internal Server Error when deleting budget) reported by @jschollenberger +- [Issue 11288](https://github.com/firefly-iii/firefly-iii/issues/11288) (Piggy bank creation form doesn't respect primary currency) reported by @jschollenberger +- [Issue 11191](https://github.com/firefly-iii/firefly-iii/issues/11191) (Going beyond 6.4.2 displays wrong balance) reported by @The24KFool ### API diff --git a/composer.lock b/composer.lock index 78730a5800..b594cdac45 100644 --- a/composer.lock +++ b/composer.lock @@ -1938,16 +1938,16 @@ }, { "name": "laravel/framework", - "version": "v12.40.1", + "version": "v12.40.2", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "2e986acbf9acf62cba13400bc23c4d639bf188b9" + "reference": "1ccd99220b474500e672b373f32bd709ec38de50" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/2e986acbf9acf62cba13400bc23c4d639bf188b9", - "reference": "2e986acbf9acf62cba13400bc23c4d639bf188b9", + "url": "https://api.github.com/repos/laravel/framework/zipball/1ccd99220b474500e672b373f32bd709ec38de50", + "reference": "1ccd99220b474500e672b373f32bd709ec38de50", "shasum": "" }, "require": { @@ -2153,7 +2153,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-11-25T16:16:33+00:00" + "time": "2025-11-26T19:24:25+00:00" }, { "name": "laravel/passport", @@ -2681,16 +2681,16 @@ }, { "name": "league/commonmark", - "version": "2.7.1", + "version": "2.8.0", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "10732241927d3971d28e7ea7b5712721fa2296ca" + "reference": "4efa10c1e56488e658d10adf7b7b7dcd19940bfb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/10732241927d3971d28e7ea7b5712721fa2296ca", - "reference": "10732241927d3971d28e7ea7b5712721fa2296ca", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/4efa10c1e56488e658d10adf7b7b7dcd19940bfb", + "reference": "4efa10c1e56488e658d10adf7b7b7dcd19940bfb", "shasum": "" }, "require": { @@ -2727,7 +2727,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.8-dev" + "dev-main": "2.9-dev" } }, "autoload": { @@ -2784,7 +2784,7 @@ "type": "tidelift" } ], - "time": "2025-07-20T12:47:49+00:00" + "time": "2025-11-26T21:48:24+00:00" }, { "name": "league/config", @@ -5973,16 +5973,16 @@ }, { "name": "sentry/sentry", - "version": "4.18.1", + "version": "4.19.0", "source": { "type": "git", "url": "https://github.com/getsentry/sentry-php.git", - "reference": "04dcf20b39742b731b676f8b8d4f02d1db488af8" + "reference": "1d29a07c8fb68ae9ad9bb8c3fecfaad3cbc23053" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/04dcf20b39742b731b676f8b8d4f02d1db488af8", - "reference": "04dcf20b39742b731b676f8b8d4f02d1db488af8", + "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/1d29a07c8fb68ae9ad9bb8c3fecfaad3cbc23053", + "reference": "1d29a07c8fb68ae9ad9bb8c3fecfaad3cbc23053", "shasum": "" }, "require": { @@ -6045,7 +6045,7 @@ ], "support": { "issues": "https://github.com/getsentry/sentry-php/issues", - "source": "https://github.com/getsentry/sentry-php/tree/4.18.1" + "source": "https://github.com/getsentry/sentry-php/tree/4.19.0" }, "funding": [ { @@ -6057,7 +6057,7 @@ "type": "custom" } ], - "time": "2025-11-11T09:34:53+00:00" + "time": "2025-11-27T14:53:55+00:00" }, { "name": "sentry/sentry-laravel", @@ -6664,32 +6664,30 @@ }, { "name": "symfony/cache", - "version": "v7.3.6", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "1277a1ec61c8d93ea61b2a59738f1deb9bfb6701" + "reference": "1005fe1988f719db8e0c6db5b8ce24284336530f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/1277a1ec61c8d93ea61b2a59738f1deb9bfb6701", - "reference": "1277a1ec61c8d93ea61b2a59738f1deb9bfb6701", + "url": "https://api.github.com/repos/symfony/cache/zipball/1005fe1988f719db8e0c6db5b8ce24284336530f", + "reference": "1005fe1988f719db8e0c6db5b8ce24284336530f", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "psr/cache": "^2.0|^3.0", "psr/log": "^1.1|^2|^3", "symfony/cache-contracts": "^3.6", - "symfony/deprecation-contracts": "^2.5|^3.0", "symfony/service-contracts": "^2.5|^3", - "symfony/var-exporter": "^6.4|^7.0" + "symfony/var-exporter": "^7.4|^8.0" }, "conflict": { - "doctrine/dbal": "<3.6", - "symfony/dependency-injection": "<6.4", - "symfony/http-kernel": "<6.4", - "symfony/var-dumper": "<6.4" + "doctrine/dbal": "<4.3", + "ext-redis": "<6.1", + "ext-relay": "<0.12.1" }, "provide": { "psr/cache-implementation": "2.0|3.0", @@ -6698,16 +6696,16 @@ }, "require-dev": { "cache/integration-tests": "dev-master", - "doctrine/dbal": "^3.6|^4", + "doctrine/dbal": "^4.3", "predis/predis": "^1.1|^2.0", "psr/simple-cache": "^1.0|^2.0|^3.0", - "symfony/clock": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/filesystem": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0" + "symfony/clock": "^7.4|^8.0", + "symfony/config": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/filesystem": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/messenger": "^7.4|^8.0", + "symfony/var-dumper": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -6742,7 +6740,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v7.3.6" + "source": "https://github.com/symfony/cache/tree/v8.0.0" }, "funding": [ { @@ -6762,7 +6760,7 @@ "type": "tidelift" } ], - "time": "2025-10-30T13:22:58+00:00" + "time": "2025-11-16T10:17:21+00:00" }, { "name": "symfony/cache-contracts", @@ -6842,16 +6840,16 @@ }, { "name": "symfony/clock", - "version": "v7.3.0", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/clock.git", - "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24" + "reference": "9169f24776edde469914c1e7a1442a50f7a4e110" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/clock/zipball/b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", - "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "url": "https://api.github.com/repos/symfony/clock/zipball/9169f24776edde469914c1e7a1442a50f7a4e110", + "reference": "9169f24776edde469914c1e7a1442a50f7a4e110", "shasum": "" }, "require": { @@ -6896,7 +6894,7 @@ "time" ], "support": { - "source": "https://github.com/symfony/clock/tree/v7.3.0" + "source": "https://github.com/symfony/clock/tree/v7.4.0" }, "funding": [ { @@ -6907,25 +6905,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-25T14:21:43+00:00" + "time": "2025-11-12T15:39:26+00:00" }, { "name": "symfony/console", - "version": "v7.3.6", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "c28ad91448f86c5f6d9d2c70f0cf68bf135f252a" + "reference": "0bc0f45254b99c58d45a8fbf9fb955d46cbd1bb8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/c28ad91448f86c5f6d9d2c70f0cf68bf135f252a", - "reference": "c28ad91448f86c5f6d9d2c70f0cf68bf135f252a", + "url": "https://api.github.com/repos/symfony/console/zipball/0bc0f45254b99c58d45a8fbf9fb955d46cbd1bb8", + "reference": "0bc0f45254b99c58d45a8fbf9fb955d46cbd1bb8", "shasum": "" }, "require": { @@ -6933,7 +6935,7 @@ "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^7.2" + "symfony/string": "^7.2|^8.0" }, "conflict": { "symfony/dependency-injection": "<6.4", @@ -6947,16 +6949,16 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/lock": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0" + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/event-dispatcher": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/lock": "^6.4|^7.0|^8.0", + "symfony/messenger": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/stopwatch": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -6990,7 +6992,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.3.6" + "source": "https://github.com/symfony/console/tree/v7.4.0" }, "funding": [ { @@ -7010,20 +7012,20 @@ "type": "tidelift" } ], - "time": "2025-11-04T01:21:42+00:00" + "time": "2025-11-27T13:27:24+00:00" }, { "name": "symfony/css-selector", - "version": "v7.3.6", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "84321188c4754e64273b46b406081ad9b18e8614" + "reference": "ab862f478513e7ca2fe9ec117a6f01a8da6e1135" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/84321188c4754e64273b46b406081ad9b18e8614", - "reference": "84321188c4754e64273b46b406081ad9b18e8614", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/ab862f478513e7ca2fe9ec117a6f01a8da6e1135", + "reference": "ab862f478513e7ca2fe9ec117a6f01a8da6e1135", "shasum": "" }, "require": { @@ -7059,7 +7061,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v7.3.6" + "source": "https://github.com/symfony/css-selector/tree/v7.4.0" }, "funding": [ { @@ -7079,7 +7081,7 @@ "type": "tidelift" } ], - "time": "2025-10-29T17:24:25+00:00" + "time": "2025-10-30T13:39:42+00:00" }, { "name": "symfony/deprecation-contracts", @@ -7150,32 +7152,33 @@ }, { "name": "symfony/error-handler", - "version": "v7.3.6", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "bbe40bfab84323d99dab491b716ff142410a92a8" + "reference": "48be2b0653594eea32dcef130cca1c811dcf25c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/bbe40bfab84323d99dab491b716ff142410a92a8", - "reference": "bbe40bfab84323d99dab491b716ff142410a92a8", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/48be2b0653594eea32dcef130cca1c811dcf25c2", + "reference": "48be2b0653594eea32dcef130cca1c811dcf25c2", "shasum": "" }, "require": { "php": ">=8.2", "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^6.4|^7.0" + "symfony/polyfill-php85": "^1.32", + "symfony/var-dumper": "^6.4|^7.0|^8.0" }, "conflict": { "symfony/deprecation-contracts": "<2.5", "symfony/http-kernel": "<6.4" }, "require-dev": { - "symfony/console": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0|^8.0", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/serializer": "^6.4|^7.0|^8.0", "symfony/webpack-encore-bundle": "^1.0|^2.0" }, "bin": [ @@ -7207,7 +7210,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.3.6" + "source": "https://github.com/symfony/error-handler/tree/v7.4.0" }, "funding": [ { @@ -7227,28 +7230,28 @@ "type": "tidelift" } ], - "time": "2025-10-31T19:12:50+00:00" + "time": "2025-11-05T14:29:59+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v7.3.3", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191" + "reference": "573f95783a2ec6e38752979db139f09fec033f03" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b7dc69e71de420ac04bc9ab830cf3ffebba48191", - "reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/573f95783a2ec6e38752979db139f09fec033f03", + "reference": "573f95783a2ec6e38752979db139f09fec033f03", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<6.4", + "symfony/security-http": "<7.4", "symfony/service-contracts": "<2.5" }, "provide": { @@ -7257,13 +7260,14 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/error-handler": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", + "symfony/config": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/error-handler": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/framework-bundle": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^6.4|^7.0" + "symfony/stopwatch": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -7291,7 +7295,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/v7.3.3" + "source": "https://github.com/symfony/event-dispatcher/tree/v8.0.0" }, "funding": [ { @@ -7311,7 +7315,7 @@ "type": "tidelift" } ], - "time": "2025-08-13T11:49:31+00:00" + "time": "2025-10-30T14:17:19+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -7391,21 +7395,21 @@ }, { "name": "symfony/expression-language", - "version": "v7.3.2", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/expression-language.git", - "reference": "32d2d19c62e58767e6552166c32fb259975d2b23" + "reference": "8b9bbbb8c71f79a09638f6ea77c531e511139efa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/expression-language/zipball/32d2d19c62e58767e6552166c32fb259975d2b23", - "reference": "32d2d19c62e58767e6552166c32fb259975d2b23", + "url": "https://api.github.com/repos/symfony/expression-language/zipball/8b9bbbb8c71f79a09638f6ea77c531e511139efa", + "reference": "8b9bbbb8c71f79a09638f6ea77c531e511139efa", "shasum": "" }, "require": { "php": ">=8.2", - "symfony/cache": "^6.4|^7.0", + "symfony/cache": "^6.4|^7.0|^8.0", "symfony/deprecation-contracts": "^2.5|^3", "symfony/service-contracts": "^2.5|^3" }, @@ -7435,7 +7439,7 @@ "description": "Provides an engine that can compile and evaluate expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/expression-language/tree/v7.3.2" + "source": "https://github.com/symfony/expression-language/tree/v7.4.0" }, "funding": [ { @@ -7455,27 +7459,27 @@ "type": "tidelift" } ], - "time": "2025-07-10T08:29:33+00:00" + "time": "2025-11-12T15:39:26+00:00" }, { "name": "symfony/finder", - "version": "v7.3.5", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "9f696d2f1e340484b4683f7853b273abff94421f" + "reference": "340b9ed7320570f319028a2cbec46d40535e94bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/9f696d2f1e340484b4683f7853b273abff94421f", - "reference": "9f696d2f1e340484b4683f7853b273abff94421f", + "url": "https://api.github.com/repos/symfony/finder/zipball/340b9ed7320570f319028a2cbec46d40535e94bd", + "reference": "340b9ed7320570f319028a2cbec46d40535e94bd", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { - "symfony/filesystem": "^6.4|^7.0" + "symfony/filesystem": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -7503,7 +7507,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.3.5" + "source": "https://github.com/symfony/finder/tree/v7.4.0" }, "funding": [ { @@ -7523,20 +7527,20 @@ "type": "tidelift" } ], - "time": "2025-10-15T18:45:57+00:00" + "time": "2025-11-05T05:42:40+00:00" }, { "name": "symfony/http-client", - "version": "v7.3.6", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "3c0a55a2c8e21e30a37022801c11c7ab5a6cb2de" + "reference": "ee5e0e0139ab506f6063a230e631bed677c650a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/3c0a55a2c8e21e30a37022801c11c7ab5a6cb2de", - "reference": "3c0a55a2c8e21e30a37022801c11c7ab5a6cb2de", + "url": "https://api.github.com/repos/symfony/http-client/zipball/ee5e0e0139ab506f6063a230e631bed677c650a4", + "reference": "ee5e0e0139ab506f6063a230e631bed677c650a4", "shasum": "" }, "require": { @@ -7567,12 +7571,13 @@ "php-http/httplug": "^1.0|^2.0", "psr/http-client": "^1.0", "symfony/amphp-http-client-meta": "^1.0|^2.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/rate-limiter": "^6.4|^7.0", - "symfony/stopwatch": "^6.4|^7.0" + "symfony/cache": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/messenger": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/rate-limiter": "^6.4|^7.0|^8.0", + "symfony/stopwatch": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -7603,7 +7608,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.3.6" + "source": "https://github.com/symfony/http-client/tree/v7.4.0" }, "funding": [ { @@ -7623,7 +7628,7 @@ "type": "tidelift" } ], - "time": "2025-11-05T17:41:46+00:00" + "time": "2025-11-20T12:32:50+00:00" }, { "name": "symfony/http-client-contracts", @@ -7705,23 +7710,22 @@ }, { "name": "symfony/http-foundation", - "version": "v7.3.7", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "db488a62f98f7a81d5746f05eea63a74e55bb7c4" + "reference": "769c1720b68e964b13b58529c17d4a385c62167b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/db488a62f98f7a81d5746f05eea63a74e55bb7c4", - "reference": "db488a62f98f7a81d5746f05eea63a74e55bb7c4", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/769c1720b68e964b13b58529c17d4a385c62167b", + "reference": "769c1720b68e964b13b58529c17d4a385c62167b", "shasum": "" }, "require": { "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3.0", - "symfony/polyfill-mbstring": "~1.1", - "symfony/polyfill-php83": "^1.27" + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "^1.1" }, "conflict": { "doctrine/dbal": "<3.6", @@ -7730,13 +7734,13 @@ "require-dev": { "doctrine/dbal": "^3.6|^4", "predis/predis": "^1.1|^2.0", - "symfony/cache": "^6.4.12|^7.1.5", - "symfony/clock": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/mime": "^6.4|^7.0", - "symfony/rate-limiter": "^6.4|^7.0" + "symfony/cache": "^6.4.12|^7.1.5|^8.0", + "symfony/clock": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/mime": "^6.4|^7.0|^8.0", + "symfony/rate-limiter": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -7764,7 +7768,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.3.7" + "source": "https://github.com/symfony/http-foundation/tree/v7.4.0" }, "funding": [ { @@ -7784,29 +7788,29 @@ "type": "tidelift" } ], - "time": "2025-11-08T16:41:12+00:00" + "time": "2025-11-13T08:49:24+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.3.7", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "10b8e9b748ea95fa4539c208e2487c435d3c87ce" + "reference": "7348193cd384495a755554382e4526f27c456085" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/10b8e9b748ea95fa4539c208e2487c435d3c87ce", - "reference": "10b8e9b748ea95fa4539c208e2487c435d3c87ce", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/7348193cd384495a755554382e4526f27c456085", + "reference": "7348193cd384495a755554382e4526f27c456085", "shasum": "" }, "require": { "php": ">=8.2", "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/error-handler": "^6.4|^7.0", - "symfony/event-dispatcher": "^7.3", - "symfony/http-foundation": "^7.3", + "symfony/error-handler": "^6.4|^7.0|^8.0", + "symfony/event-dispatcher": "^7.3|^8.0", + "symfony/http-foundation": "^7.4|^8.0", "symfony/polyfill-ctype": "^1.8" }, "conflict": { @@ -7816,6 +7820,7 @@ "symfony/console": "<6.4", "symfony/dependency-injection": "<6.4", "symfony/doctrine-bridge": "<6.4", + "symfony/flex": "<2.10", "symfony/form": "<6.4", "symfony/http-client": "<6.4", "symfony/http-client-contracts": "<2.5", @@ -7833,27 +7838,27 @@ }, "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", - "symfony/browser-kit": "^6.4|^7.0", - "symfony/clock": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/css-selector": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/dom-crawler": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", + "symfony/browser-kit": "^6.4|^7.0|^8.0", + "symfony/clock": "^6.4|^7.0|^8.0", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/css-selector": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/dom-crawler": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/finder": "^6.4|^7.0|^8.0", "symfony/http-client-contracts": "^2.5|^3", - "symfony/process": "^6.4|^7.0", - "symfony/property-access": "^7.1", - "symfony/routing": "^6.4|^7.0", - "symfony/serializer": "^7.1", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/translation": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/property-access": "^7.1|^8.0", + "symfony/routing": "^6.4|^7.0|^8.0", + "symfony/serializer": "^7.1|^8.0", + "symfony/stopwatch": "^6.4|^7.0|^8.0", + "symfony/translation": "^6.4|^7.0|^8.0", "symfony/translation-contracts": "^2.5|^3", - "symfony/uid": "^6.4|^7.0", - "symfony/validator": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0", - "symfony/var-exporter": "^6.4|^7.0", + "symfony/uid": "^6.4|^7.0|^8.0", + "symfony/validator": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0", + "symfony/var-exporter": "^6.4|^7.0|^8.0", "twig/twig": "^3.12" }, "type": "library", @@ -7882,7 +7887,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.3.7" + "source": "https://github.com/symfony/http-kernel/tree/v7.4.0" }, "funding": [ { @@ -7902,20 +7907,20 @@ "type": "tidelift" } ], - "time": "2025-11-12T11:38:40+00:00" + "time": "2025-11-27T13:38:24+00:00" }, { "name": "symfony/mailer", - "version": "v7.3.5", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "fd497c45ba9c10c37864e19466b090dcb60a50ba" + "reference": "a3d9eea8cfa467ece41f0f54ba28185d74bd53fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/fd497c45ba9c10c37864e19466b090dcb60a50ba", - "reference": "fd497c45ba9c10c37864e19466b090dcb60a50ba", + "url": "https://api.github.com/repos/symfony/mailer/zipball/a3d9eea8cfa467ece41f0f54ba28185d74bd53fd", + "reference": "a3d9eea8cfa467ece41f0f54ba28185d74bd53fd", "shasum": "" }, "require": { @@ -7923,8 +7928,8 @@ "php": ">=8.2", "psr/event-dispatcher": "^1", "psr/log": "^1|^2|^3", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/mime": "^7.2", + "symfony/event-dispatcher": "^6.4|^7.0|^8.0", + "symfony/mime": "^7.2|^8.0", "symfony/service-contracts": "^2.5|^3" }, "conflict": { @@ -7935,10 +7940,10 @@ "symfony/twig-bridge": "<6.4" }, "require-dev": { - "symfony/console": "^6.4|^7.0", - "symfony/http-client": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/twig-bridge": "^6.4|^7.0" + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/http-client": "^6.4|^7.0|^8.0", + "symfony/messenger": "^6.4|^7.0|^8.0", + "symfony/twig-bridge": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -7966,7 +7971,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v7.3.5" + "source": "https://github.com/symfony/mailer/tree/v7.4.0" }, "funding": [ { @@ -7986,32 +7991,32 @@ "type": "tidelift" } ], - "time": "2025-10-24T14:27:20+00:00" + "time": "2025-11-21T15:26:00+00:00" }, { "name": "symfony/mailgun-mailer", - "version": "v7.3.1", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/mailgun-mailer.git", - "reference": "8c18f2bff4e70ed5669ab8228302edd2fecd689b" + "reference": "ffbcdbf93ed0700f083a6307acfb8f78dd3f091b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailgun-mailer/zipball/8c18f2bff4e70ed5669ab8228302edd2fecd689b", - "reference": "8c18f2bff4e70ed5669ab8228302edd2fecd689b", + "url": "https://api.github.com/repos/symfony/mailgun-mailer/zipball/ffbcdbf93ed0700f083a6307acfb8f78dd3f091b", + "reference": "ffbcdbf93ed0700f083a6307acfb8f78dd3f091b", "shasum": "" }, "require": { "php": ">=8.2", - "symfony/mailer": "^7.2" + "symfony/mailer": "^7.2|^8.0" }, "conflict": { "symfony/http-foundation": "<6.4" }, "require-dev": { - "symfony/http-client": "^6.4|^7.0", - "symfony/webhook": "^6.4|^7.0" + "symfony/http-client": "^6.4|^7.0|^8.0", + "symfony/webhook": "^6.4|^7.0|^8.0" }, "type": "symfony-mailer-bridge", "autoload": { @@ -8039,7 +8044,7 @@ "description": "Symfony Mailgun Mailer Bridge", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailgun-mailer/tree/v7.3.1" + "source": "https://github.com/symfony/mailgun-mailer/tree/v7.4.0" }, "funding": [ { @@ -8050,29 +8055,34 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-06-20T16:15:52+00:00" + "time": "2025-08-04T07:05:15+00:00" }, { "name": "symfony/mime", - "version": "v7.3.4", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "b1b828f69cbaf887fa835a091869e55df91d0e35" + "reference": "bdb02729471be5d047a3ac4a69068748f1a6be7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/b1b828f69cbaf887fa835a091869e55df91d0e35", - "reference": "b1b828f69cbaf887fa835a091869e55df91d0e35", + "url": "https://api.github.com/repos/symfony/mime/zipball/bdb02729471be5d047a3ac4a69068748f1a6be7a", + "reference": "bdb02729471be5d047a3ac4a69068748f1a6be7a", "shasum": "" }, "require": { "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-mbstring": "^1.0" }, @@ -8087,11 +8097,11 @@ "egulias/email-validator": "^2.1.10|^3.1|^4", "league/html-to-markdown": "^5.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/property-access": "^6.4|^7.0", - "symfony/property-info": "^6.4|^7.0", - "symfony/serializer": "^6.4.3|^7.0.3" + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/property-access": "^6.4|^7.0|^8.0", + "symfony/property-info": "^6.4|^7.0|^8.0", + "symfony/serializer": "^6.4.3|^7.0.3|^8.0" }, "type": "library", "autoload": { @@ -8123,7 +8133,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.3.4" + "source": "https://github.com/symfony/mime/tree/v7.4.0" }, "funding": [ { @@ -8143,20 +8153,20 @@ "type": "tidelift" } ], - "time": "2025-09-16T08:38:17+00:00" + "time": "2025-11-16T10:14:42+00:00" }, { "name": "symfony/options-resolver", - "version": "v7.3.3", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "0ff2f5c3df08a395232bbc3c2eb7e84912df911d" + "reference": "b38026df55197f9e39a44f3215788edf83187b80" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/0ff2f5c3df08a395232bbc3c2eb7e84912df911d", - "reference": "0ff2f5c3df08a395232bbc3c2eb7e84912df911d", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/b38026df55197f9e39a44f3215788edf83187b80", + "reference": "b38026df55197f9e39a44f3215788edf83187b80", "shasum": "" }, "require": { @@ -8194,7 +8204,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v7.3.3" + "source": "https://github.com/symfony/options-resolver/tree/v7.4.0" }, "funding": [ { @@ -8214,7 +8224,7 @@ "type": "tidelift" } ], - "time": "2025-08-05T10:16:07+00:00" + "time": "2025-11-12T15:39:26+00:00" }, { "name": "symfony/polyfill-ctype", @@ -9047,16 +9057,16 @@ }, { "name": "symfony/process", - "version": "v7.3.4", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "f24f8f316367b30810810d4eb30c543d7003ff3b" + "reference": "7ca8dc2d0dcf4882658313aba8be5d9fd01026c8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/f24f8f316367b30810810d4eb30c543d7003ff3b", - "reference": "f24f8f316367b30810810d4eb30c543d7003ff3b", + "url": "https://api.github.com/repos/symfony/process/zipball/7ca8dc2d0dcf4882658313aba8be5d9fd01026c8", + "reference": "7ca8dc2d0dcf4882658313aba8be5d9fd01026c8", "shasum": "" }, "require": { @@ -9088,7 +9098,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.3.4" + "source": "https://github.com/symfony/process/tree/v7.4.0" }, "funding": [ { @@ -9108,26 +9118,26 @@ "type": "tidelift" } ], - "time": "2025-09-11T10:12:26+00:00" + "time": "2025-10-16T11:21:06+00:00" }, { "name": "symfony/psr-http-message-bridge", - "version": "v7.3.0", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/psr-http-message-bridge.git", - "reference": "03f2f72319e7acaf2a9f6fcbe30ef17eec51594f" + "reference": "0101ff8bd0506703b045b1670960302d302a726c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/03f2f72319e7acaf2a9f6fcbe30ef17eec51594f", - "reference": "03f2f72319e7acaf2a9f6fcbe30ef17eec51594f", + "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/0101ff8bd0506703b045b1670960302d302a726c", + "reference": "0101ff8bd0506703b045b1670960302d302a726c", "shasum": "" }, "require": { "php": ">=8.2", "psr/http-message": "^1.0|^2.0", - "symfony/http-foundation": "^6.4|^7.0" + "symfony/http-foundation": "^6.4|^7.0|^8.0" }, "conflict": { "php-http/discovery": "<1.15", @@ -9137,11 +9147,12 @@ "nyholm/psr7": "^1.1", "php-http/discovery": "^1.15", "psr/log": "^1.1.4|^2|^3", - "symfony/browser-kit": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/framework-bundle": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0" + "symfony/browser-kit": "^6.4|^7.0|^8.0", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/event-dispatcher": "^6.4|^7.0|^8.0", + "symfony/framework-bundle": "^6.4.13|^7.1.6|^8.0", + "symfony/http-kernel": "^6.4.13|^7.1.6|^8.0", + "symfony/runtime": "^6.4.13|^7.1.6|^8.0" }, "type": "symfony-bridge", "autoload": { @@ -9175,7 +9186,7 @@ "psr-7" ], "support": { - "source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.3.0" + "source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.4.0" }, "funding": [ { @@ -9186,25 +9197,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-26T08:57:56+00:00" + "time": "2025-11-13T08:38:49+00:00" }, { "name": "symfony/routing", - "version": "v7.3.6", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "c97abe725f2a1a858deca629a6488c8fc20c3091" + "reference": "4720254cb2644a0b876233d258a32bf017330db7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/c97abe725f2a1a858deca629a6488c8fc20c3091", - "reference": "c97abe725f2a1a858deca629a6488c8fc20c3091", + "url": "https://api.github.com/repos/symfony/routing/zipball/4720254cb2644a0b876233d258a32bf017330db7", + "reference": "4720254cb2644a0b876233d258a32bf017330db7", "shasum": "" }, "require": { @@ -9218,11 +9233,11 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/yaml": "^6.4|^7.0" + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", + "symfony/yaml": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -9256,7 +9271,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.3.6" + "source": "https://github.com/symfony/routing/tree/v7.4.0" }, "funding": [ { @@ -9276,7 +9291,7 @@ "type": "tidelift" } ], - "time": "2025-11-05T07:57:47+00:00" + "time": "2025-11-27T13:27:24+00:00" }, { "name": "symfony/service-contracts", @@ -9367,34 +9382,34 @@ }, { "name": "symfony/string", - "version": "v7.3.4", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "f96476035142921000338bad71e5247fbc138872" + "reference": "f929eccf09531078c243df72398560e32fa4cf4f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/f96476035142921000338bad71e5247fbc138872", - "reference": "f96476035142921000338bad71e5247fbc138872", + "url": "https://api.github.com/repos/symfony/string/zipball/f929eccf09531078c243df72398560e32fa4cf4f", + "reference": "f929eccf09531078c243df72398560e32fa4cf4f", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" + "php": ">=8.4", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-intl-grapheme": "^1.33", + "symfony/polyfill-intl-normalizer": "^1.0", + "symfony/polyfill-mbstring": "^1.0" }, "conflict": { "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/emoji": "^7.1", - "symfony/http-client": "^6.4|^7.0", - "symfony/intl": "^6.4|^7.0", + "symfony/emoji": "^7.4|^8.0", + "symfony/http-client": "^7.4|^8.0", + "symfony/intl": "^7.4|^8.0", "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.4|^7.0" + "symfony/var-exporter": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -9433,7 +9448,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.3.4" + "source": "https://github.com/symfony/string/tree/v8.0.0" }, "funding": [ { @@ -9453,27 +9468,27 @@ "type": "tidelift" } ], - "time": "2025-09-11T14:36:48+00:00" + "time": "2025-09-11T14:37:55+00:00" }, { "name": "symfony/translation", - "version": "v7.3.4", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "ec25870502d0c7072d086e8ffba1420c85965174" + "reference": "2d01ca0da3f092f91eeedb46f24aa30d2fca8f68" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/ec25870502d0c7072d086e8ffba1420c85965174", - "reference": "ec25870502d0c7072d086e8ffba1420c85965174", + "url": "https://api.github.com/repos/symfony/translation/zipball/2d01ca0da3f092f91eeedb46f24aa30d2fca8f68", + "reference": "2d01ca0da3f092f91eeedb46f24aa30d2fca8f68", "shasum": "" }, "require": { "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/translation-contracts": "^2.5|^3.0" + "symfony/translation-contracts": "^2.5.3|^3.3" }, "conflict": { "nikic/php-parser": "<5.0", @@ -9492,17 +9507,17 @@ "require-dev": { "nikic/php-parser": "^5.0", "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/finder": "^6.4|^7.0|^8.0", "symfony/http-client-contracts": "^2.5|^3.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/intl": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/intl": "^6.4|^7.0|^8.0", "symfony/polyfill-intl-icu": "^1.21", - "symfony/routing": "^6.4|^7.0", + "symfony/routing": "^6.4|^7.0|^8.0", "symfony/service-contracts": "^2.5|^3", - "symfony/yaml": "^6.4|^7.0" + "symfony/yaml": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -9533,7 +9548,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v7.3.4" + "source": "https://github.com/symfony/translation/tree/v7.4.0" }, "funding": [ { @@ -9553,7 +9568,7 @@ "type": "tidelift" } ], - "time": "2025-09-07T11:39:36+00:00" + "time": "2025-11-27T13:27:24+00:00" }, { "name": "symfony/translation-contracts", @@ -9639,16 +9654,16 @@ }, { "name": "symfony/uid", - "version": "v7.3.1", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "a69f69f3159b852651a6bf45a9fdd149520525bb" + "reference": "2498e9f81b7baa206f44de583f2f48350b90142c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/a69f69f3159b852651a6bf45a9fdd149520525bb", - "reference": "a69f69f3159b852651a6bf45a9fdd149520525bb", + "url": "https://api.github.com/repos/symfony/uid/zipball/2498e9f81b7baa206f44de583f2f48350b90142c", + "reference": "2498e9f81b7baa206f44de583f2f48350b90142c", "shasum": "" }, "require": { @@ -9656,7 +9671,7 @@ "symfony/polyfill-uuid": "^1.15" }, "require-dev": { - "symfony/console": "^6.4|^7.0" + "symfony/console": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -9693,7 +9708,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v7.3.1" + "source": "https://github.com/symfony/uid/tree/v7.4.0" }, "funding": [ { @@ -9704,25 +9719,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-06-27T19:55:54+00:00" + "time": "2025-09-25T11:02:55+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.3.5", + "version": "v7.4.0", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "476c4ae17f43a9a36650c69879dcf5b1e6ae724d" + "reference": "41fd6c4ae28c38b294b42af6db61446594a0dece" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/476c4ae17f43a9a36650c69879dcf5b1e6ae724d", - "reference": "476c4ae17f43a9a36650c69879dcf5b1e6ae724d", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/41fd6c4ae28c38b294b42af6db61446594a0dece", + "reference": "41fd6c4ae28c38b294b42af6db61446594a0dece", "shasum": "" }, "require": { @@ -9734,10 +9753,10 @@ "symfony/console": "<6.4" }, "require-dev": { - "symfony/console": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/uid": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/uid": "^6.4|^7.0|^8.0", "twig/twig": "^3.12" }, "bin": [ @@ -9776,7 +9795,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.3.5" + "source": "https://github.com/symfony/var-dumper/tree/v7.4.0" }, "funding": [ { @@ -9796,30 +9815,29 @@ "type": "tidelift" } ], - "time": "2025-09-27T09:00:46+00:00" + "time": "2025-10-27T20:36:44+00:00" }, { "name": "symfony/var-exporter", - "version": "v7.3.4", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "0f020b544a30a7fe8ba972e53ee48a74c0bc87f4" + "reference": "7345f46c251f2eb27c7b3ebdb5bb076b3ffcae04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/0f020b544a30a7fe8ba972e53ee48a74c0bc87f4", - "reference": "0f020b544a30a7fe8ba972e53ee48a74c0bc87f4", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/7345f46c251f2eb27c7b3ebdb5bb076b3ffcae04", + "reference": "7345f46c251f2eb27c7b3ebdb5bb076b3ffcae04", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3" + "php": ">=8.4" }, "require-dev": { - "symfony/property-access": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0" + "symfony/property-access": "^7.4|^8.0", + "symfony/serializer": "^7.4|^8.0", + "symfony/var-dumper": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -9857,7 +9875,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v7.3.4" + "source": "https://github.com/symfony/var-exporter/tree/v8.0.0" }, "funding": [ { @@ -9877,7 +9895,7 @@ "type": "tidelift" } ], - "time": "2025-09-11T10:12:26+00:00" + "time": "2025-11-05T18:53:00+00:00" }, { "name": "thecodingmachine/safe", @@ -12124,16 +12142,16 @@ }, { "name": "rector/rector", - "version": "2.2.8", + "version": "2.2.9", "source": { "type": "git", "url": "https://github.com/rectorphp/rector.git", - "reference": "303aa811649ccd1d32e51e62d5c85949d01b5f1b" + "reference": "0b8e49ec234877b83244d2ecd0df7a4c16471f05" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rectorphp/rector/zipball/303aa811649ccd1d32e51e62d5c85949d01b5f1b", - "reference": "303aa811649ccd1d32e51e62d5c85949d01b5f1b", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/0b8e49ec234877b83244d2ecd0df7a4c16471f05", + "reference": "0b8e49ec234877b83244d2ecd0df7a4c16471f05", "shasum": "" }, "require": { @@ -12172,7 +12190,7 @@ ], "support": { "issues": "https://github.com/rectorphp/rector/issues", - "source": "https://github.com/rectorphp/rector/tree/2.2.8" + "source": "https://github.com/rectorphp/rector/tree/2.2.9" }, "funding": [ { @@ -12180,7 +12198,7 @@ "type": "github" } ], - "time": "2025-11-12T18:38:00+00:00" + "time": "2025-11-28T14:21:22+00:00" }, { "name": "sebastian/cli-parser", diff --git a/config/firefly.php b/config/firefly.php index 09170a77b3..754138d20f 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -78,8 +78,8 @@ return [ 'running_balance_column' => env('USE_RUNNING_BALANCE', false), // see cer.php for exchange rates feature flag. ], - 'version' => 'develop/2025-11-26', - 'build_time' => 1764180641, + 'version' => 'develop/2025-11-28', + 'build_time' => 1764353187, 'api_version' => '2.1.0', // field is no longer used. 'db_version' => 28, // field is no longer used. diff --git a/package-lock.json b/package-lock.json index c34128d7a8..45425ee814 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4075,9 +4075,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.8.31", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.31.tgz", - "integrity": "sha512-a28v2eWrrRWPpJSzxc+mKwm0ZtVx/G8SepdQZDArnXYU/XS+IF6mp8aB/4E+hH1tyGCoDo3KlUCdlSxGDsRkAw==", + "version": "2.8.32", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.32.tgz", + "integrity": "sha512-OPz5aBThlyLFgxyhdwf/s2+8ab3OvT7AdTNvKHBwpXomIYeXqpUUuT8LrdtxZSsWJ4R4CU1un4XGh5Ez3nlTpw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -5736,9 +5736,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.260", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.260.tgz", - "integrity": "sha512-ov8rBoOBhVawpzdre+Cmz4FB+y66Eqrk6Gwqd8NGxuhv99GQ8XqMAr351KEkOt7gukXWDg6gJWEMKgL2RLMPtA==", + "version": "1.5.262", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.262.tgz", + "integrity": "sha512-NlAsMteRHek05jRUxUR0a5jpjYq9ykk6+kO0yRaMi5moe7u0fVIOeQ3Y30A8dIiWFBNUoQGi1ljb1i5VtS9WQQ==", "dev": true, "license": "ISC" }, @@ -5820,9 +5820,9 @@ } }, "node_modules/envinfo": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.20.0.tgz", - "integrity": "sha512-+zUomDcLXsVkQ37vUqWBvQwLaLlj8eZPSi61llaEFAVBY5mhcXdaSw1pSJVl4yTYD5g/gEfpNl28YYk4IPvrrg==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.21.0.tgz", + "integrity": "sha512-Lw7I8Zp5YKHFCXL7+Dz95g4CcbMEpgvqZNNq3AmlT5XAV6CgAAk6gyAMqn2zjw08K9BHfcNuKrMiCPLByGafow==", "dev": true, "license": "MIT", "bin": { @@ -7338,9 +7338,9 @@ } }, "node_modules/ipaddr.js": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", - "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.3.0.tgz", + "integrity": "sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==", "dev": true, "license": "MIT", "engines": { @@ -9313,9 +9313,9 @@ } }, "node_modules/postcss-modules-local-by-default/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "dev": true, "license": "MIT", "dependencies": { @@ -9343,9 +9343,9 @@ } }, "node_modules/postcss-modules-scope/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "dev": true, "license": "MIT", "dependencies": { From 962a7290255c524ac1aff7f34fe7ce7dfa72c125 Mon Sep 17 00:00:00 2001 From: JC5 Date: Fri, 28 Nov 2025 21:35:58 +0100 Subject: [PATCH 26/26] =?UTF-8?q?=F0=9F=A4=96=20Auto=20commit=20for=20rele?= =?UTF-8?q?ase=20'v6.4.9'=20on=202025-11-28?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/firefly.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/firefly.php b/config/firefly.php index 754138d20f..2d8b05fb7b 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -78,8 +78,8 @@ return [ 'running_balance_column' => env('USE_RUNNING_BALANCE', false), // see cer.php for exchange rates feature flag. ], - 'version' => 'develop/2025-11-28', - 'build_time' => 1764353187, + 'version' => '6.4.9', + 'build_time' => 1764362024, 'api_version' => '2.1.0', // field is no longer used. 'db_version' => 28, // field is no longer used.
{{ trans('list.id') }}#{{ transactionGroup.id }}
{{ trans('list.type') }} {{ first.transaction_type_type|_ }}