Compare commits

..

90 Commits

Author SHA1 Message Date
github-actions[bot]
22448a825b Merge pull request #11390 from firefly-iii/release-1766158480
🤖 Automatically merge the PR into the develop branch.
2025-12-19 16:34:48 +01:00
JC5
476a9ac6e4 🤖 Auto commit for release 'develop' on 2025-12-19 2025-12-19 16:34:41 +01:00
James Cole
0acd07405b Fix #11388 2025-12-19 16:30:39 +01:00
James Cole
1daacb80b1 Fix #11383 2025-12-17 19:27:59 +01:00
github-actions[bot]
2bf841627a Merge pull request #11382 from firefly-iii/release-1765957651
🤖 Automatically merge the PR into the develop branch.
2025-12-17 08:47:38 +01:00
JC5
012df6bb24 🤖 Auto commit for release 'develop' on 2025-12-17 2025-12-17 08:47:31 +01:00
Sander Dorigo
486e0d5ed5 Update reference to Steam 2025-12-17 08:43:39 +01:00
James Cole
e8fe9db181 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-12-17 06:04:23 +01:00
James Cole
05f0cb26f8 Remove sentry. 2025-12-17 06:04:17 +01:00
github-actions[bot]
bdaed65207 Merge pull request #11375 from firefly-iii/release-1765863733
🤖 Automatically merge the PR into the develop branch.
2025-12-16 06:42:20 +01:00
JC5
62a9195acc 🤖 Auto commit for release 'v6.4.14' on 2025-12-16 2025-12-16 06:42:13 +01:00
James Cole
40d1e36ba8 Fix changelog. 2025-12-16 06:38:14 +01:00
James Cole
61a8525d26 Merge branch 'main' into develop 2025-12-16 06:36:32 +01:00
James Cole
ef01fbe5f4 Update changelog. 2025-12-16 06:36:17 +01:00
James Cole
9413f49c84 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-12-16 06:36:12 +01:00
github-actions[bot]
d9ae99b5fe Merge pull request #11374 from firefly-iii/develop
🤖 Automatically merge the PR into the main branch.
2025-12-16 06:35:19 +01:00
github-actions[bot]
45d2d86bba Merge pull request #11373 from firefly-iii/release-1765863308
🤖 Automatically merge the PR into the develop branch.
2025-12-16 06:35:15 +01:00
JC5
e21d5e5d01 🤖 Auto commit for release 'v6.4.13' on 2025-12-16 2025-12-16 06:35:08 +01:00
James Cole
8781e2a870 Fix #11368 2025-12-16 06:31:19 +01:00
github-actions[bot]
9e4bfd9d1a Merge pull request #11372 from firefly-iii/release-1765862987
🤖 Automatically merge the PR into the develop branch.
2025-12-16 06:29:55 +01:00
JC5
d61d6aa2e2 🤖 Auto commit for release 'develop' on 2025-12-16 2025-12-16 06:29:47 +01:00
github-actions[bot]
230a3a0180 Merge pull request #11371 from firefly-iii/develop
🤖 Automatically merge the PR into the main branch.
2025-12-16 06:25:04 +01:00
github-actions[bot]
002454b995 Merge pull request #11370 from firefly-iii/release-1765862692
🤖 Automatically merge the PR into the develop branch.
2025-12-16 06:24:59 +01:00
JC5
e6d9c2e218 🤖 Auto commit for release 'v6.4.12' on 2025-12-16 2025-12-16 06:24:52 +01:00
github-actions[bot]
eaa5054b00 Merge pull request #11369 from firefly-iii/release-1765861996
🤖 Automatically merge the PR into the develop branch.
2025-12-16 06:13:25 +01:00
JC5
4e9e63ed08 🤖 Auto commit for release 'develop' on 2025-12-16 2025-12-16 06:13:16 +01:00
James Cole
76ea5b6e34 Fix #11367 2025-12-16 06:08:38 +01:00
Sander Dorigo
2f788f7397 Merge branch 'develop' of https://github.com/firefly-iii/firefly-iii into develop 2025-12-15 15:51:13 +01:00
Sander Dorigo
29766aa9b7 Add better running balance 2025-12-15 14:56:58 +01:00
github-actions[bot]
cc30376297 Merge pull request #11364 from firefly-iii/release-1765805210
🤖 Automatically merge the PR into the develop branch.
2025-12-15 14:26:58 +01:00
JC5
5b007fbe01 🤖 Auto commit for release 'develop' on 2025-12-15 2025-12-15 14:26:50 +01:00
Sander Dorigo
e1f8ea3b1a Fix missing user property 2025-12-15 14:19:43 +01:00
James Cole
6f019f0bb4 Merge pull request #11363 from firefly-iii/main
Merge main into develop
2025-12-15 10:48:19 +01:00
github-actions[bot]
f475947776 Merge pull request #11362 from firefly-iii/develop
🤖 Automatically merge the PR into the main branch.
2025-12-15 09:01:26 +01:00
github-actions[bot]
ee6901eb92 Merge pull request #11361 from firefly-iii/release-1765785673
🤖 Automatically merge the PR into the develop branch.
2025-12-15 09:01:21 +01:00
JC5
84d7523d6c 🤖 Auto commit for release 'v6.4.11' on 2025-12-15 2025-12-15 09:01:13 +01:00
github-actions[bot]
6900dc7dae Merge pull request #11360 from firefly-iii/release-1765785184
🤖 Automatically merge the PR into the develop branch.
2025-12-15 08:53:14 +01:00
JC5
6247e516c6 🤖 Auto commit for release 'develop' on 2025-12-15 2025-12-15 08:53:05 +01:00
Sander Dorigo
cdf970a88c Add changelog 2025-12-15 08:42:10 +01:00
Sander Dorigo
a447c387f9 Fix #11357 2025-12-15 08:41:07 +01:00
Sander Dorigo
ce2c94efed Fix #11356 2025-12-15 08:40:19 +01:00
James Cole
205ea4270b Merge pull request #11358 from firefly-iii/dependabot/github_actions/dessant/label-actions-5 2025-12-15 07:27:43 +01:00
github-actions[bot]
dcbb2428f2 Merge pull request #11359 from firefly-iii/release-1765769737
🤖 Automatically merge the PR into the develop branch.
2025-12-15 04:35:45 +01:00
JC5
319916fc8f 🤖 Auto commit for release 'develop' on 2025-12-15 2025-12-15 04:35:37 +01:00
dependabot[bot]
088b0e2f30 Bump dessant/label-actions from 4 to 5
Bumps [dessant/label-actions](https://github.com/dessant/label-actions) from 4 to 5.
- [Release notes](https://github.com/dessant/label-actions/releases)
- [Changelog](https://github.com/dessant/label-actions/blob/main/CHANGELOG.md)
- [Commits](https://github.com/dessant/label-actions/compare/v4...v5)

---
updated-dependencies:
- dependency-name: dessant/label-actions
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-15 03:06:09 +00:00
github-actions[bot]
b45aadf8a3 Merge pull request #11355 from firefly-iii/develop
🤖 Automatically merge the PR into the main branch.
2025-12-14 19:13:25 +01:00
github-actions[bot]
1fafeb1515 Merge pull request #11354 from firefly-iii/release-1765735989
🤖 Automatically merge the PR into the develop branch.
2025-12-14 19:13:19 +01:00
JC5
f60c64c9c1 🤖 Auto commit for release 'v6.4.10' on 2025-12-14 2025-12-14 19:13:09 +01:00
James Cole
564dcb1c6d Expand changelog. 2025-12-14 19:09:08 +01:00
github-actions[bot]
4044bb85a9 Merge pull request #11353 from firefly-iii/release-1765725243
🤖 Automatically merge the PR into the develop branch.
2025-12-14 16:14:10 +01:00
JC5
18bb0eecff 🤖 Auto commit for release 'develop' on 2025-12-14 2025-12-14 16:14:03 +01:00
James Cole
9af95907e3 Fix patch etc. 2025-12-14 16:10:21 +01:00
James Cole
40ecba4b5a No longer need patch. 2025-12-14 10:31:35 +01:00
James Cole
73312a4ccc Fix #11310 2025-12-14 10:24:27 +01:00
James Cole
d747ac237b Validate title, fix running balance display 2025-12-13 06:36:20 +01:00
github-actions[bot]
b6c4253d76 Merge pull request #11349 from firefly-iii/release-1765602800
🤖 Automatically merge the PR into the develop branch.
2025-12-13 06:13:28 +01:00
JC5
d74d67633d 🤖 Auto commit for release 'develop' on 2025-12-13 2025-12-13 06:13:20 +01:00
James Cole
0b00f35101 Update packages, another fix for the same issue. 2025-12-13 06:08:58 +01:00
James Cole
8f81cb8cc4 Fix #11346 2025-12-13 06:05:39 +01:00
github-actions[bot]
fa665286b5 Merge pull request #11344 from firefly-iii/release-1765164810
🤖 Automatically merge the PR into the develop branch.
2025-12-08 04:33:39 +01:00
JC5
58ae0c1c9b 🤖 Auto commit for release 'develop' on 2025-12-08 2025-12-08 04:33:30 +01:00
github-actions[bot]
7eab4834c8 Merge pull request #11340 from firefly-iii/release-1765124558
🤖 Automatically merge the PR into the develop branch.
2025-12-07 17:22:47 +01:00
JC5
d1332eb592 🤖 Auto commit for release 'develop' on 2025-12-07 2025-12-07 17:22:38 +01:00
James Cole
346f2dfaea Add amount event. 2025-12-07 16:47:04 +01:00
James Cole
f6037318f4 Fix #11337 2025-12-07 07:00:50 +01:00
James Cole
babf9fe96f Add file permissions checks. #11323 2025-12-06 14:55:15 +01:00
James Cole
ca3922d00a Fix #11313 2025-12-06 13:50:51 +01:00
James Cole
aadb685b57 Add YTD fix. 2025-12-06 08:12:18 +01:00
github-actions[bot]
bee62b2115 Merge pull request #11335 from firefly-iii/release-1765004138
🤖 Automatically merge the PR into the develop branch.
2025-12-06 07:55:46 +01:00
JC5
205169a8ad 🤖 Auto commit for release 'develop' on 2025-12-06 2025-12-06 07:55:38 +01:00
James Cole
5f36bb84a4 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-12-06 07:51:19 +01:00
James Cole
5b395d870b Fix #11333 2025-12-06 07:32:43 +01:00
github-actions[bot]
bceb526cb3 Merge pull request #11334 from firefly-iii/release-1765002701
🤖 Automatically merge the PR into the develop branch.
2025-12-06 07:31:52 +01:00
JC5
1f89dddb08 🤖 Auto commit for release 'develop' on 2025-12-06 2025-12-06 07:31:41 +01:00
James Cole
a93f2d66af Fix #11329 2025-12-06 07:27:41 +01:00
James Cole
551909ea60 Merge branch 'main' into develop 2025-12-05 08:21:34 +01:00
Sander Dorigo
5667044349 Fix #11328 2025-12-04 17:27:20 +01:00
James Cole
6f73e4f2c9 Merge pull request #11316 from firefly-iii/dependabot/composer/develop/symfony/mailgun-mailer-8.0.0
Bump symfony/mailgun-mailer from 7.4.0 to 8.0.0
2025-12-01 14:32:55 +01:00
dependabot[bot]
1f19f20734 Bump symfony/mailgun-mailer from 7.4.0 to 8.0.0
Bumps [symfony/mailgun-mailer](https://github.com/symfony/mailgun-mailer) from 7.4.0 to 8.0.0.
- [Release notes](https://github.com/symfony/mailgun-mailer/releases)
- [Changelog](https://github.com/symfony/mailgun-mailer/blob/7.3/CHANGELOG.md)
- [Commits](https://github.com/symfony/mailgun-mailer/compare/v7.4.0...v8.0.0)

---
updated-dependencies:
- dependency-name: symfony/mailgun-mailer
  dependency-version: 8.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-01 10:45:09 +00:00
James Cole
91c8f0db80 Merge pull request #11317 from firefly-iii/dependabot/composer/develop/symfony/expression-language-8.0.0
Bump symfony/expression-language from 7.4.0 to 8.0.0
2025-12-01 11:41:22 +01:00
dependabot[bot]
2cdd1aa147 Bump symfony/expression-language from 7.4.0 to 8.0.0
Bumps [symfony/expression-language](https://github.com/symfony/expression-language) from 7.4.0 to 8.0.0.
- [Release notes](https://github.com/symfony/expression-language/releases)
- [Changelog](https://github.com/symfony/expression-language/blob/7.3/CHANGELOG.md)
- [Commits](https://github.com/symfony/expression-language/compare/v7.4.0...v8.0.0)

---
updated-dependencies:
- dependency-name: symfony/expression-language
  dependency-version: 8.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-01 08:17:15 +00:00
James Cole
5ac51218aa Merge pull request #11319 from firefly-iii/dependabot/github_actions/github/command-2.0.3 2025-12-01 05:15:37 +01:00
James Cole
80abd277a0 Merge pull request #11315 from firefly-iii/dependabot/composer/develop/symfony/http-client-8.0.0 2025-12-01 05:14:44 +01:00
mergify[bot]
b644f28882 Merge branch 'develop' into dependabot/composer/develop/symfony/http-client-8.0.0 2025-12-01 03:40:11 +00:00
github-actions[bot]
35a81fd2de Merge pull request #11321 from firefly-iii/release-1764560258
🤖 Automatically merge the PR into the develop branch.
2025-12-01 04:37:44 +01:00
JC5
51e8a1dbe2 🤖 Auto commit for release 'develop' on 2025-12-01 2025-12-01 04:37:38 +01:00
dependabot[bot]
b799379a0a Bump github/command from 2.0.2 to 2.0.3
Bumps [github/command](https://github.com/github/command) from 2.0.2 to 2.0.3.
- [Release notes](https://github.com/github/command/releases)
- [Commits](https://github.com/github/command/compare/v2.0.2...v2.0.3)

---
updated-dependencies:
- dependency-name: github/command
  dependency-version: 2.0.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-01 03:10:25 +00:00
dependabot[bot]
c8edaee848 Bump symfony/http-client from 7.4.0 to 8.0.0
Bumps [symfony/http-client](https://github.com/symfony/http-client) from 7.4.0 to 8.0.0.
- [Release notes](https://github.com/symfony/http-client/releases)
- [Changelog](https://github.com/symfony/http-client/blob/7.3/CHANGELOG.md)
- [Commits](https://github.com/symfony/http-client/compare/v7.4.0...v8.0.0)

---
updated-dependencies:
- dependency-name: symfony/http-client
  dependency-version: 8.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-01 03:03:40 +00:00
github-actions[bot]
bbe47635d3 Merge pull request #11304 from firefly-iii/release-1764397418
🤖 Automatically merge the PR into the develop branch.
2025-11-29 07:23:46 +01:00
JC5
5c73d238a0 🤖 Auto commit for release 'develop' on 2025-11-29 2025-11-29 07:23:38 +01:00
96 changed files with 1432 additions and 1468 deletions

View File

@@ -402,16 +402,16 @@
}, },
{ {
"name": "friendsofphp/php-cs-fixer", "name": "friendsofphp/php-cs-fixer",
"version": "v3.90.0", "version": "v3.92.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "ad732c2e9299c9743f9c55ae53cc0e7642ab1155" "reference": "2ba8f5a60f6f42fb65758cfb3768434fa2d1c7e8"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/ad732c2e9299c9743f9c55ae53cc0e7642ab1155", "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/2ba8f5a60f6f42fb65758cfb3768434fa2d1c7e8",
"reference": "ad732c2e9299c9743f9c55ae53cc0e7642ab1155", "reference": "2ba8f5a60f6f42fb65758cfb3768434fa2d1c7e8",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -451,6 +451,7 @@
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6", "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6",
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6", "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6",
"phpunit/phpunit": "^9.6.25 || ^10.5.53 || ^11.5.34", "phpunit/phpunit": "^9.6.25 || ^10.5.53 || ^11.5.34",
"symfony/polyfill-php85": "^1.33",
"symfony/var-dumper": "^5.4.48 || ^6.4.24 || ^7.3.2 || ^8.0", "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" "symfony/yaml": "^5.4.45 || ^6.4.24 || ^7.3.2 || ^8.0"
}, },
@@ -467,7 +468,7 @@
"PhpCsFixer\\": "src/" "PhpCsFixer\\": "src/"
}, },
"exclude-from-classmap": [ "exclude-from-classmap": [
"src/Fixer/Internal/*" "src/**/Internal/"
] ]
}, },
"notification-url": "https://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
@@ -493,7 +494,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.90.0" "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.92.3"
}, },
"funding": [ "funding": [
{ {
@@ -501,7 +502,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2025-11-20T15:15:16+00:00" "time": "2025-12-18T10:45:02+00:00"
}, },
{ {
"name": "psr/container", "name": "psr/container",
@@ -1251,16 +1252,16 @@
}, },
{ {
"name": "symfony/console", "name": "symfony/console",
"version": "v8.0.0", "version": "v8.0.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/console.git", "url": "https://github.com/symfony/console.git",
"reference": "307d3cf852f5ead3618ac60ecbedbdd512c348b1" "reference": "fcb73f69d655b48fcb894a262f074218df08bd58"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/307d3cf852f5ead3618ac60ecbedbdd512c348b1", "url": "https://api.github.com/repos/symfony/console/zipball/fcb73f69d655b48fcb894a262f074218df08bd58",
"reference": "307d3cf852f5ead3618ac60ecbedbdd512c348b1", "reference": "fcb73f69d655b48fcb894a262f074218df08bd58",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1317,7 +1318,7 @@
"terminal" "terminal"
], ],
"support": { "support": {
"source": "https://github.com/symfony/console/tree/v8.0.0" "source": "https://github.com/symfony/console/tree/v8.0.1"
}, },
"funding": [ "funding": [
{ {
@@ -1337,7 +1338,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-11-21T13:19:49+00:00" "time": "2025-12-05T15:25:33+00:00"
}, },
{ {
"name": "symfony/deprecation-contracts", "name": "symfony/deprecation-contracts",
@@ -1569,16 +1570,16 @@
}, },
{ {
"name": "symfony/filesystem", "name": "symfony/filesystem",
"version": "v8.0.0", "version": "v8.0.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/filesystem.git", "url": "https://github.com/symfony/filesystem.git",
"reference": "7fc96ae83372620eaba3826874f46e26295768ca" "reference": "d937d400b980523dc9ee946bb69972b5e619058d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/7fc96ae83372620eaba3826874f46e26295768ca", "url": "https://api.github.com/repos/symfony/filesystem/zipball/d937d400b980523dc9ee946bb69972b5e619058d",
"reference": "7fc96ae83372620eaba3826874f46e26295768ca", "reference": "d937d400b980523dc9ee946bb69972b5e619058d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1615,7 +1616,7 @@
"description": "Provides basic utilities for the filesystem", "description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/filesystem/tree/v8.0.0" "source": "https://github.com/symfony/filesystem/tree/v8.0.1"
}, },
"funding": [ "funding": [
{ {
@@ -1635,7 +1636,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-11-05T14:36:47+00:00" "time": "2025-12-01T09:13:36+00:00"
}, },
{ {
"name": "symfony/finder", "name": "symfony/finder",
@@ -2575,16 +2576,16 @@
}, },
{ {
"name": "symfony/string", "name": "symfony/string",
"version": "v8.0.0", "version": "v8.0.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/string.git", "url": "https://github.com/symfony/string.git",
"reference": "f929eccf09531078c243df72398560e32fa4cf4f" "reference": "ba65a969ac918ce0cc3edfac6cdde847eba231dc"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/f929eccf09531078c243df72398560e32fa4cf4f", "url": "https://api.github.com/repos/symfony/string/zipball/ba65a969ac918ce0cc3edfac6cdde847eba231dc",
"reference": "f929eccf09531078c243df72398560e32fa4cf4f", "reference": "ba65a969ac918ce0cc3edfac6cdde847eba231dc",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -2641,7 +2642,7 @@
"utf8" "utf8"
], ],
"support": { "support": {
"source": "https://github.com/symfony/string/tree/v8.0.0" "source": "https://github.com/symfony/string/tree/v8.0.1"
}, },
"funding": [ "funding": [
{ {
@@ -2661,7 +2662,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-09-11T14:37:55+00:00" "time": "2025-12-01T09:13:36+00:00"
} }
], ],
"packages-dev": [], "packages-dev": [],

View File

@@ -275,16 +275,6 @@ DISABLE_CSP_HEADER=false
TRACKER_SITE_ID= TRACKER_SITE_ID=
TRACKER_URL= TRACKER_URL=
#
# You can automatically submit errors to the Firefly III developer using sentry.io
#
# This is entirely optional of course. If you run into errors, I will gladly accept GitHub
# issues or a forwared email message.
#
# If you set this to true, your installation will try to contact sentry.io when it runs into errors.
#
REPORT_ERRORS_ONLINE=false
# #
# Firefly III supports webhooks. These are security sensitive and must be enabled manually first. # Firefly III supports webhooks. These are security sensitive and must be enabled manually first.
# #

View File

@@ -13,7 +13,7 @@ jobs:
close_duplicates: close_duplicates:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: github/command@v2.0.2 - uses: github/command@v2.0.3
id: command id: command
with: with:
allowed_contexts: "issue" allowed_contexts: "issue"

View File

@@ -18,4 +18,4 @@ jobs:
action: action:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: dessant/label-actions@v4 - uses: dessant/label-actions@v5

View File

@@ -24,7 +24,6 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Chart; namespace FireflyIII\Api\V1\Controllers\Chart;
use Illuminate\Http\Request;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Chart\ChartRequest; use FireflyIII\Api\V1\Requests\Chart\ChartRequest;
use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Enums\UserRoleEnum;
@@ -32,11 +31,13 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Facades\Navigation;
use FireflyIII\Support\Facades\Steam; use FireflyIII\Support\Facades\Steam;
use FireflyIII\Support\Http\Api\ApiSupport; use FireflyIII\Support\Http\Api\ApiSupport;
use FireflyIII\Support\Http\Api\CleansChartData; use FireflyIII\Support\Http\Api\CleansChartData;
use FireflyIII\Support\Http\Api\CollectsAccountsFromFilter; use FireflyIII\Support\Http\Api\CollectsAccountsFromFilter;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
/** /**
@@ -48,9 +49,9 @@ class AccountController extends Controller
use CleansChartData; use CleansChartData;
use CollectsAccountsFromFilter; use CollectsAccountsFromFilter;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY]; protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
private array $chartData = []; private array $chartData = [];
private AccountRepositoryInterface $repository; private AccountRepositoryInterface $repository;
/** /**
@@ -103,7 +104,7 @@ class AccountController extends Controller
$currency = $this->repository->getAccountCurrency($account); $currency = $this->repository->getAccountCurrency($account);
$currentStart = clone $params['start']; $currentStart = clone $params['start'];
$range = Steam::finalAccountBalanceInRange($account, $params['start'], clone $params['end'], $this->convertToPrimary); $range = Steam::finalAccountBalanceInRange($account, $params['start'], clone $params['end'], $this->convertToPrimary);
$period = $params['period'] ?? '1D';
$previous = array_values($range)[0]['balance']; $previous = array_values($range)[0]['balance'];
$pcPrevious = null; $pcPrevious = null;
@@ -129,7 +130,7 @@ class AccountController extends Controller
'end_date' => $params['end']->toAtomString(), 'end_date' => $params['end']->toAtomString(),
'type' => 'line', 'type' => 'line',
'yAxisID' => 0, 'yAxisID' => 0,
'period' => '1D', 'period' => $period,
'entries' => [], 'entries' => [],
'pc_entries' => [], 'pc_entries' => [],
]; ];
@@ -141,7 +142,7 @@ class AccountController extends Controller
$currentSet['primary_currency_decimal_places'] = $this->primaryCurrency->decimal_places; $currentSet['primary_currency_decimal_places'] = $this->primaryCurrency->decimal_places;
$pcPrevious = array_values($range)[0]['pc_balance']; $pcPrevious = array_values($range)[0]['pc_balance'];
} }
// create array of values to collect.
while ($currentStart <= $params['end']) { while ($currentStart <= $params['end']) {
$format = $currentStart->format('Y-m-d'); $format = $currentStart->format('Y-m-d');
@@ -158,8 +159,8 @@ class AccountController extends Controller
$pcPrevious = $pcBalance; $pcPrevious = $pcBalance;
$currentSet['pc_entries'][$label] = $pcBalance; $currentSet['pc_entries'][$label] = $pcBalance;
} }
$currentStart = Navigation::addPeriod($currentStart, $period);
$currentStart->addDay(); // $currentStart->addDay();
} }
$this->chartData[] = $currentSet; $this->chartData[] = $currentSet;
} }

View File

@@ -42,6 +42,7 @@ use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class BudgetController * Class BudgetController
@@ -286,7 +287,7 @@ class BudgetController extends Controller
} }
if (null !== $limit && $this->convertToPrimary) { if (null !== $limit && $this->convertToPrimary) {
// convert and add all amounts. // convert and add all amounts.
$limit->amount = app('steam')->positive($amount); $limit->amount = Steam::positive($amount);
Log::debug(sprintf('Final amount in limit with converted amount %s', $limit->amount)); Log::debug(sprintf('Final amount in limit with converted amount %s', $limit->amount));
} }

View File

@@ -486,7 +486,7 @@ class BasicController extends Controller
'currency_decimal_places' => $currencies[$currencyId]->decimal_places, 'currency_decimal_places' => $currencies[$currencyId]->decimal_places,
'value_parsed' => Amount::formatFlat($currencies[$currencyId]->symbol, $currencies[$currencyId]->decimal_places, $availableBudget, false), 'value_parsed' => Amount::formatFlat($currencies[$currencyId]->symbol, $currencies[$currencyId]->decimal_places, $availableBudget, false),
'local_icon' => 'money', 'local_icon' => 'money',
'sub_title' => Amount::formatFlat($currencies[$currencyId]->symbol, $currencies[$currencyId]->decimal_places, $availableBudget, false), 'sub_title' => Amount::formatFlat($currencies[$currencyId]->symbol, $currencies[$currencyId]->decimal_places, bcdiv($availableBudget, (string)$days), false),
]; ];
} }
foreach ($spent as $row) { foreach ($spent as $row) {

View File

@@ -339,6 +339,9 @@ class UpdateRequest extends FormRequest
// if more than one, verify that there are journal ID's present. // if more than one, verify that there are journal ID's present.
$this->validateJournalIds($validator, $transactionGroup); $this->validateJournalIds($validator, $transactionGroup);
// if more than one split, needs group title
$this->validateGroupDescription($validator);
// all transaction types must be equal: // all transaction types must be equal:
$this->validateTransactionTypesForUpdate($validator); $this->validateTransactionTypesForUpdate($validator);

View File

@@ -0,0 +1,68 @@
<?php
declare(strict_types=1);
/*
* ClearsEmptyForeignAmounts.php
* Copyright (c) 2025 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Models\Transaction;
use Illuminate\Console\Command;
class ClearsEmptyForeignAmounts extends Command
{
use ShowsFriendlyMessages;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'correction:clears-empty-foreign-amounts';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Removes references to foreign amounts if there is no amount.';
/**
* Execute the console command.
*/
public function handle(): int
{
// transaction: has no amount, but reference to currency.
$count = Transaction::whereNull('foreign_amount')->whereNotNull('foreign_currency_id')->count();
if ($count > 0) {
Transaction::whereNull('foreign_amount')->whereNotNull('foreign_currency_id')->update(['foreign_currency_id' => null]);
$this->friendlyInfo(sprintf('Corrected %d invalid foreign amount reference(s)', $count));
}
// transaction: has amount, but no currency.
$count = Transaction::whereNull('foreign_currency_id')->whereNotNull('foreign_amount')->count();
if ($count > 0) {
Transaction::whereNull('foreign_currency_id')->whereNotNull('foreign_amount')->update(['foreign_amount' => null]);
$this->friendlyInfo(sprintf('Corrected %d invalid foreign amount reference(s)', $count));
}
return self::SUCCESS;
}
}

View File

@@ -43,6 +43,7 @@ use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use ValueError; use ValueError;
use FireflyIII\Support\Facades\Steam;
class CorrectsAmounts extends Command class CorrectsAmounts extends Command
{ {
@@ -99,6 +100,10 @@ class CorrectsAmounts extends Command
if (null === $source->foreign_currency_id || null === $destination->foreign_currency_id) { if (null === $source->foreign_currency_id || null === $destination->foreign_currency_id) {
continue; continue;
} }
if (null === $source->foreign_amount || null === $destination->foreign_amount) {
continue;
}
$sourceAccount = $source->account; $sourceAccount = $source->account;
$destAccount = $destination->account; $destAccount = $destination->account;
if (null === $sourceAccount || null === $destAccount) { if (null === $sourceAccount || null === $destAccount) {
@@ -244,7 +249,7 @@ class CorrectsAmounts extends Command
return false; return false;
} }
if (-1 === $check) { if (-1 === $check) {
$item->trigger_value = app('steam')->positive($item->trigger_value); $item->trigger_value = Steam::positive($item->trigger_value);
$item->save(); $item->save();
return true; return true;

View File

@@ -78,6 +78,7 @@ class CorrectsDatabase extends Command
// 'correction:transaction-types', // resource heavy, disabled. // 'correction:transaction-types', // resource heavy, disabled.
'correction:recalculate-pc-amounts', 'correction:recalculate-pc-amounts',
'correction:remove-links-to-deleted-objects', 'correction:remove-links-to-deleted-objects',
'correction:clears-empty-foreign-amounts',
'firefly-iii:report-integrity', 'firefly-iii:report-integrity',
]; ];
foreach ($commands as $command) { foreach ($commands as $command) {

View File

@@ -29,6 +29,7 @@ use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use FireflyIII\Support\Facades\Steam;
class CorrectsIbans extends Command class CorrectsIbans extends Command
{ {
@@ -55,7 +56,7 @@ class CorrectsIbans extends Command
/** @var Account $account */ /** @var Account $account */
foreach ($accounts as $account) { foreach ($accounts as $account) {
$iban = (string) $account->iban; $iban = (string) $account->iban;
$newIban = app('steam')->filterSpaces($iban); $newIban = Steam::filterSpaces($iban);
if ('' !== $iban && $iban !== $newIban) { if ('' !== $iban && $iban !== $newIban) {
$account->iban = $newIban; $account->iban = $newIban;
$account->save(); $account->save();
@@ -66,7 +67,7 @@ class CorrectsIbans extends Command
$accountNumber = $account->accountMeta->where('name', 'account_number')->first(); $accountNumber = $account->accountMeta->where('name', 'account_number')->first();
if (null !== $accountNumber) { if (null !== $accountNumber) {
$number = (string) $accountNumber->value; $number = (string) $accountNumber->value;
$newNumber = app('steam')->filterSpaces($number); $newNumber = Steam::filterSpaces($number);
if ('' !== $number && $number !== $newNumber) { if ('' !== $number && $number !== $newNumber) {
$accountNumber->value = $newNumber; $accountNumber->value = $newNumber;
$accountNumber->save(); $accountNumber->save();

View File

@@ -112,9 +112,9 @@ class CorrectsUnevenAmount extends Command
if ($source->transaction_currency_id === $destination->transaction_currency_id) { if ($source->transaction_currency_id === $destination->transaction_currency_id) {
Log::debug('Ready to swap data between transactions.'); Log::debug('Ready to swap data between transactions.');
$destination->foreign_currency_id = $source->transaction_currency_id; $destination->foreign_currency_id = $source->transaction_currency_id;
$destination->foreign_amount = app('steam')->positive($source->amount); $destination->foreign_amount = Steam::positive($source->amount);
$destination->transaction_currency_id = $source->foreign_currency_id; $destination->transaction_currency_id = $source->foreign_currency_id;
$destination->amount = app('steam')->positive($source->foreign_amount); $destination->amount = Steam::positive($source->foreign_amount);
$destination->balance_dirty = true; $destination->balance_dirty = true;
$source->balance_dirty = true; $source->balance_dirty = true;
$destination->save(); $destination->save();
@@ -132,11 +132,7 @@ class CorrectsUnevenAmount extends Command
private function fixUnevenAmounts(): void private function fixUnevenAmounts(): void
{ {
Log::debug('fixUnevenAmounts()'); Log::debug('fixUnevenAmounts()');
$journals = DB::table('transactions') $journals = DB::table('transactions')->groupBy('transaction_journal_id')->whereNull('deleted_at')->get(['transaction_journal_id', DB::raw('SUM(amount) AS the_sum')]);
->groupBy('transaction_journal_id')
->whereNull('deleted_at')
->get(['transaction_journal_id', DB::raw('SUM(amount) AS the_sum')])
;
/** @var stdClass $entry */ /** @var stdClass $entry */
foreach ($journals as $entry) { foreach ($journals as $entry) {
@@ -146,11 +142,7 @@ class CorrectsUnevenAmount extends Command
|| '' === $sum // @phpstan-ignore-line || '' === $sum // @phpstan-ignore-line
|| str_contains($sum, 'e') || str_contains($sum, 'e')
|| str_contains($sum, ',')) { || str_contains($sum, ',')) {
$message = sprintf( $message = sprintf('Journal #%d has an invalid sum ("%s"). No sure what to do.', $entry->transaction_journal_id, $entry->the_sum);
'Journal #%d has an invalid sum ("%s"). No sure what to do.',
$entry->transaction_journal_id,
$entry->the_sum
);
$this->friendlyWarning($message); $this->friendlyWarning($message);
Log::warning($message); Log::warning($message);
++$this->count; ++$this->count;
@@ -184,13 +176,7 @@ class CorrectsUnevenAmount extends Command
$source = $journal->transactions()->where('amount', '<', 0)->first(); $source = $journal->transactions()->where('amount', '<', 0)->first();
if (null === $source) { if (null === $source) {
$this->friendlyError( $this->friendlyError(sprintf('Journal #%d ("%s") has no source transaction. It will be deleted to maintain database consistency.', $journal->id ?? 0, $journal->description ?? ''));
sprintf(
'Journal #%d ("%s") has no source transaction. It will be deleted to maintain database consistency.',
$journal->id ?? 0,
$journal->description ?? ''
)
);
Transaction::where('transaction_journal_id', $journal->id ?? 0)->forceDelete(); Transaction::where('transaction_journal_id', $journal->id ?? 0)->forceDelete();
TransactionJournal::where('id', $journal->id ?? 0)->forceDelete(); TransactionJournal::where('id', $journal->id ?? 0)->forceDelete();
++$this->count; ++$this->count;
@@ -205,13 +191,7 @@ class CorrectsUnevenAmount extends Command
$destination = $journal->transactions()->where('amount', '>', 0)->first(); $destination = $journal->transactions()->where('amount', '>', 0)->first();
if (null === $destination) { if (null === $destination) {
$this->friendlyError( $this->friendlyError(sprintf('Journal #%d ("%s") has no destination transaction. It will be deleted to maintain database consistency.', $journal->id ?? 0, $journal->description ?? ''));
sprintf(
'Journal #%d ("%s") has no destination transaction. It will be deleted to maintain database consistency.',
$journal->id ?? 0,
$journal->description ?? ''
)
);
Transaction::where('transaction_journal_id', $journal->id ?? 0)->forceDelete(); Transaction::where('transaction_journal_id', $journal->id ?? 0)->forceDelete();
TransactionJournal::where('id', $journal->id ?? 0)->forceDelete(); TransactionJournal::where('id', $journal->id ?? 0)->forceDelete();
@@ -257,8 +237,8 @@ class CorrectsUnevenAmount extends Command
// source currency = dest foreign currency // source currency = dest foreign currency
// dest amount = source foreign currency // dest amount = source foreign currency
// dest currency = source foreign currency // dest currency = source foreign currency
// Log::debug(sprintf('[a] %s', bccomp(app('steam')->positive($source->amount), app('steam')->positive($destination->foreign_amount)))); // Log::debug(sprintf('[a] %s', bccomp(\FireflyIII\Support\Facades\Steam::positive($source->amount), \FireflyIII\Support\Facades\Steam::positive($destination->foreign_amount))));
// Log::debug(sprintf('[b] %s', bccomp(app('steam')->positive($destination->amount), app('steam')->positive($source->foreign_amount)))); // Log::debug(sprintf('[b] %s', bccomp(\FireflyIII\Support\Facades\Steam::positive($destination->amount), \FireflyIII\Support\Facades\Steam::positive($source->foreign_amount))));
// Log::debug(sprintf('[c] %s', var_export($source->transaction_currency_id === $destination->foreign_currency_id,true))); // Log::debug(sprintf('[c] %s', var_export($source->transaction_currency_id === $destination->foreign_currency_id,true)));
// Log::debug(sprintf('[d] %s', var_export((int) $destination->transaction_currency_id ===(int) $source->foreign_currency_id, true))); // Log::debug(sprintf('[d] %s', var_export((int) $destination->transaction_currency_id ===(int) $source->foreign_currency_id, true)));
return 0 === bccomp(Steam::positive($source->amount), Steam::positive($destination->foreign_amount)) return 0 === bccomp(Steam::positive($source->amount), Steam::positive($destination->foreign_amount))
@@ -428,9 +408,9 @@ class CorrectsUnevenAmount extends Command
// // only fix the destination transaction // // only fix the destination transaction
// $destination->foreign_currency_id = $source->transaction_currency_id; // $destination->foreign_currency_id = $source->transaction_currency_id;
// $destination->foreign_amount = app('steam')->positive($source->amount); // $destination->foreign_amount = \FireflyIII\Support\Facades\Steam::positive($source->amount);
// $destination->transaction_currency_id = $source->foreign_currency_id; // $destination->transaction_currency_id = $source->foreign_currency_id;
// $destination->amount = app('steam')->positive($source->foreign_amount); // $destination->amount = \FireflyIII\Support\Facades\Steam::positive($source->foreign_amount);
// $destination->balance_dirty = true; // $destination->balance_dirty = true;
// $source->balance_dirty = true; // $source->balance_dirty = true;
// $destination->save(); // $destination->save();

View File

@@ -86,17 +86,27 @@ class RemovesLinksToDeletedObjects extends Command
private function cleanupJournals(array $journals): void private function cleanupJournals(array $journals): void
{ {
$count = DB::table('tag_transaction_journal')->whereIn('transaction_journal_id', $journals)->delete(); $countTags = 0;
if ($count > 0) { $countBudgets = 0;
$this->friendlyInfo(sprintf('Removed %d old relationship(s) between tags and transactions.', $count)); $countCategories = 0;
// #11333
foreach (array_chunk($journals, 1337) as $set) {
$countTags += DB::table('tag_transaction_journal')->whereIn('transaction_journal_id', $set)->delete();
$countBudgets += DB::table('budget_transaction_journal')->whereIn('transaction_journal_id', $set)->delete();
$countCategories += DB::table('category_transaction_journal')->whereIn('transaction_journal_id', $set)->delete();
} }
$count = DB::table('budget_transaction_journal')->whereIn('transaction_journal_id', $journals)->delete();
if ($count > 0) {
$this->friendlyInfo(sprintf('Removed %d old relationship(s) between budgets and transactions.', $count));
if ($countTags > 0) {
$this->friendlyInfo(sprintf('Removed %d old relationship(s) between tags and transactions.', $countTags));
} }
$count = DB::table('category_transaction_journal')->whereIn('transaction_journal_id', $journals)->delete();
if ($count > 0) { if ($countBudgets > 0) {
$this->friendlyInfo(sprintf('Removed %d old relationship(s) categories and transactions.', $count)); $this->friendlyInfo(sprintf('Removed %d old relationship(s) between budgets and transactions.', $countBudgets));
}
if ($countCategories > 0) {
$this->friendlyInfo(sprintf('Removed %d old relationship(s) categories and transactions.', $countCategories));
} }
} }

View File

@@ -1,26 +0,0 @@
<?php
namespace FireflyIII\Console\Commands\Integrity;
use Illuminate\Console\Command;
class ReportSkeleton extends Command
{
protected $description = 'DESCRIPTION HERE';
protected $signature = 'firefly-iii:INT_COMMAND';
/**
* Execute the console command.
*
* @return int
*/
public function handle(): int
{
//
$this->warn('Congrats, you found the skeleton command. Boo!');
return 0;
}
}

View File

@@ -48,6 +48,7 @@ class ReportsIntegrity extends Command
$commands = [ $commands = [
'integrity:empty-objects', 'integrity:empty-objects',
'integrity:total-sums', 'integrity:total-sums',
'integrity:file-permissions',
]; ];
foreach ($commands as $command) { foreach ($commands as $command) {
$this->friendlyLine(sprintf('Now executing %s', $command)); $this->friendlyLine(sprintf('Now executing %s', $command));

View File

@@ -0,0 +1,74 @@
<?php
declare(strict_types=1);
/*
* ValidatesFilePermissions.php
* Copyright (c) 2025 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Console\Commands\Integrity;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use Illuminate\Console\Command;
class ValidatesFilePermissions extends Command
{
use ShowsFriendlyMessages;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'integrity:file-permissions';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Execute the console command.
*/
public function handle(): int
{
$directories = [storage_path('upload')];
$errors = false;
/** @var string $directory */
foreach ($directories as $directory) {
if (!is_dir($directory)) {
$this->friendlyError(sprintf('Directory "%s" cannot found. It is necessary to allow files to be uploaded.', $directory));
$errors = true;
continue;
}
if (!is_writable($directory)) {
$this->friendlyError(sprintf('Directory "%s" is not writeable. Uploading attachments may fail silently.', $directory));
$errors = true;
}
}
if (false === $errors) {
$this->friendlyInfo('All necessary file paths seem to exist, and are writeable.');
}
return self::SUCCESS;
}
}

View File

@@ -120,7 +120,7 @@ class RemovesDatabaseDecryption extends Command
if (null === $original) { if (null === $original) {
return; return;
} }
$id = (int) $row->id; $id = (int)$row->id;
$value = ''; $value = '';
try { try {
@@ -133,7 +133,7 @@ class RemovesDatabaseDecryption extends Command
} }
// A separate routine for preferences table: // A separate routine for preferences table:
if ('preferences' === $table) { if ('preferences' === $table && is_string($value)) {
$this->decryptPreferencesRow($id, $value); $this->decryptPreferencesRow($id, $value);
return; return;

View File

@@ -1,7 +1,7 @@
<?php <?php
/* /*
* CorrectAccountBalance.php * RepairsAccountBalances.php
* Copyright (c) 2024 james@firefly-iii.org. * Copyright (c) 2024 james@firefly-iii.org.
* *
* This file is part of Firefly III (https://github.com/firefly-iii). * This file is part of Firefly III (https://github.com/firefly-iii).

View File

@@ -137,7 +137,7 @@ class UpgradesLiabilitiesEight extends Command
return false; return false;
} }
return (bool) $openingJournal->date->isSameDay($liabilityJournal->date); return (bool)$openingJournal->date->isSameDay($liabilityJournal->date);
} }
private function deleteCreditTransaction(Account $account): void private function deleteCreditTransaction(Account $account): void
@@ -148,7 +148,7 @@ class UpgradesLiabilitiesEight extends Command
->where('transaction_journals.transaction_type_id', $liabilityType->id) ->where('transaction_journals.transaction_type_id', $liabilityType->id)
->first(['transaction_journals.*']) ->first(['transaction_journals.*'])
; ;
if (null !== $liabilityJournal) { if (null !== $liabilityJournal && null !== $liabilityJournal->transactionGroup) {
$group = $liabilityJournal->transactionGroup; $group = $liabilityJournal->transactionGroup;
$service = new TransactionGroupDestroyService(); $service = new TransactionGroupDestroyService();
$service->destroy($group); $service->destroy($group);
@@ -192,11 +192,14 @@ class UpgradesLiabilitiesEight extends Command
->where('transactions.account_id', $account->id)->get(['transaction_journals.*']) ->where('transactions.account_id', $account->id)->get(['transaction_journals.*'])
; ;
$service = app(TransactionGroupDestroyService::class);
/** @var TransactionJournal $journal */ /** @var TransactionJournal $journal */
foreach ($journals as $journal) { foreach ($journals as $journal) {
$service = app(TransactionGroupDestroyService::class); if (null !== $journal->transactionGroup) {
$service->destroy($journal->transactionGroup); $service->destroy($journal->transactionGroup);
++$count; ++$count;
}
} }
return $count; return $count;

View File

@@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
/*
* TriggeredStoredTransactionGroup.php
* Copyright (c) 2025 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Events\Model\TransactionGroup;
use FireflyIII\Events\Event;
use FireflyIII\Models\TransactionGroup;
use Illuminate\Queue\SerializesModels;
class TriggeredStoredTransactionGroup extends Event
{
use SerializesModels;
/**
* Create a new event instance.
*/
public function __construct(public TransactionGroup $transactionGroup) {}
}

View File

@@ -42,7 +42,6 @@ use Illuminate\Validation\ValidationException as LaravelValidationException;
use Laravel\Passport\Exceptions\OAuthServerException as LaravelOAuthException; use Laravel\Passport\Exceptions\OAuthServerException as LaravelOAuthException;
use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\Exception\OAuthServerException;
use Override; use Override;
use Sentry\Laravel\Integration;
use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException; use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
@@ -50,6 +49,7 @@ use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Throwable; use Throwable;
use FireflyIII\Support\Facades\Steam;
use function Safe\json_encode; use function Safe\json_encode;
use function Safe\parse_url; use function Safe\parse_url;
@@ -83,14 +83,7 @@ class Handler extends ExceptionHandler
* Register the exception handling callbacks for the application. * Register the exception handling callbacks for the application.
*/ */
#[Override] #[Override]
public function register(): void public function register(): void {}
{
if (true === config('firefly.report_errors_online')) {
$this->reportable(function (Throwable $e): void {
Integration::captureUnhandledException($e);
});
}
}
/** /**
* Render an exception into an HTTP response. It's complex but lucky for us, we never use it because * Render an exception into an HTTP response. It's complex but lucky for us, we never use it because
@@ -287,7 +280,7 @@ class Handler extends ExceptionHandler
protected function invalid($request, LaravelValidationException $exception): \Illuminate\Http\Response|JsonResponse|RedirectResponse protected function invalid($request, LaravelValidationException $exception): \Illuminate\Http\Response|JsonResponse|RedirectResponse
{ {
// protect against open redirect when submitting invalid forms. // protect against open redirect when submitting invalid forms.
$previous = app('steam')->getSafePreviousUrl(); $previous = Steam::getSafePreviousUrl();
$redirect = $this->getRedirectUrl($exception); $redirect = $this->getRedirectUrl($exception);
return redirect($redirect ?? $previous) return redirect($redirect ?? $previous)

View File

@@ -34,6 +34,7 @@ use FireflyIII\Services\Internal\Update\AccountUpdateService;
use Illuminate\Database\QueryException; use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class TransactionFactory * Class TransactionFactory
@@ -58,10 +59,10 @@ class TransactionFactory
$foreignAmount = null; $foreignAmount = null;
} }
if (null !== $foreignAmount) { if (null !== $foreignAmount) {
$foreignAmount = app('steam')->negative($foreignAmount); $foreignAmount = Steam::negative($foreignAmount);
} }
return $this->create(app('steam')->negative($amount), $foreignAmount); return $this->create(Steam::negative($amount), $foreignAmount);
} }
/** /**
@@ -170,10 +171,10 @@ class TransactionFactory
$foreignAmount = null; $foreignAmount = null;
} }
if (null !== $foreignAmount) { if (null !== $foreignAmount) {
$foreignAmount = app('steam')->positive($foreignAmount); $foreignAmount = Steam::positive($foreignAmount);
} }
return $this->create(app('steam')->positive($amount), $foreignAmount); return $this->create(Steam::positive($amount), $foreignAmount);
} }
public function setAccount(Account $account): void public function setAccount(Account $account): void

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Generator\Chart\Basic; namespace FireflyIII\Generator\Chart\Basic;
use FireflyIII\Support\ChartColour; use FireflyIII\Support\ChartColour;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class ChartJsGenerator. * Class ChartJsGenerator.
@@ -56,7 +57,7 @@ class ChartJsGenerator implements GeneratorInterface
$index = 0; $index = 0;
foreach ($data as $key => $valueArray) { foreach ($data as $key => $valueArray) {
// make larger than 0 // make larger than 0
$chartData['datasets'][0]['data'][] = app('steam')->positive((string) $valueArray['amount']); $chartData['datasets'][0]['data'][] = Steam::positive((string) $valueArray['amount']);
$chartData['datasets'][0]['backgroundColor'][] = ChartColour::getColour($index); $chartData['datasets'][0]['backgroundColor'][] = ChartColour::getColour($index);
$chartData['datasets'][0]['currency_symbol'][] = $valueArray['currency_symbol']; $chartData['datasets'][0]['currency_symbol'][] = $valueArray['currency_symbol'];
$chartData['labels'][] = $key; $chartData['labels'][] = $key;
@@ -163,7 +164,7 @@ class ChartJsGenerator implements GeneratorInterface
$index = 0; $index = 0;
foreach ($data as $key => $value) { foreach ($data as $key => $value) {
// make larger than 0 // make larger than 0
$chartData['datasets'][0]['data'][] = app('steam')->positive((string) $value); $chartData['datasets'][0]['data'][] = Steam::positive((string) $value);
$chartData['datasets'][0]['backgroundColor'][] = ChartColour::getColour($index); $chartData['datasets'][0]['backgroundColor'][] = ChartColour::getColour($index);
$chartData['labels'][] = $key; $chartData['labels'][] = $key;

View File

@@ -153,13 +153,13 @@ class MonthReportGenerator implements ReportGeneratorInterface
// make sure amount is in the right "direction". // make sure amount is in the right "direction".
if ($account->id === $journal['destination_account_id']) { if ($account->id === $journal['destination_account_id']) {
$transactionAmount = app('steam')->positive($journal['amount']); $transactionAmount = Steam::positive($journal['amount']);
} }
if ($currency->id === $journal['foreign_currency_id']) { if ($currency->id === $journal['foreign_currency_id']) {
$transactionAmount = $journal['foreign_amount']; $transactionAmount = $journal['foreign_amount'];
if ($account->id === $journal['destination_account_id']) { if ($account->id === $journal['destination_account_id']) {
$transactionAmount = app('steam')->positive($journal['foreign_amount']); $transactionAmount = Steam::positive($journal['foreign_amount']);
} }
} }
@@ -175,7 +175,7 @@ class MonthReportGenerator implements ReportGeneratorInterface
$journals[$index]['payment_date'] = $journalRepository->getMetaDateById($journal['transaction_journal_id'], 'payment_date'); $journals[$index]['payment_date'] = $journalRepository->getMetaDateById($journal['transaction_journal_id'], 'payment_date');
$journals[$index]['invoice_date'] = $journalRepository->getMetaDateById($journal['transaction_journal_id'], 'invoice_date'); $journals[$index]['invoice_date'] = $journalRepository->getMetaDateById($journal['transaction_journal_id'], 'invoice_date');
} }
$locale = app('steam')->getLocale(); $locale = Steam::getLocale();
// call is correct. // call is correct.
Log::debug(sprintf('getAuditReport end: Call finalAccountBalance with date/time "%s"', $this->end->toIso8601String())); Log::debug(sprintf('getAuditReport end: Call finalAccountBalance with date/time "%s"', $this->end->toIso8601String()));

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Handlers\Events; namespace FireflyIII\Handlers\Events;
use FireflyIII\Enums\WebhookTrigger; use FireflyIII\Enums\WebhookTrigger;
use FireflyIII\Events\Model\TransactionGroup\TriggeredStoredTransactionGroup;
use FireflyIII\Events\RequestedSendWebhookMessages; use FireflyIII\Events\RequestedSendWebhookMessages;
use FireflyIII\Events\StoredTransactionGroup; use FireflyIII\Events\StoredTransactionGroup;
use FireflyIII\Generator\Webhook\MessageGeneratorInterface; use FireflyIII\Generator\Webhook\MessageGeneratorInterface;
@@ -51,6 +52,12 @@ class StoredGroupEventHandler
$this->removePeriodStatistics($event); $this->removePeriodStatistics($event);
} }
public function triggerRulesManually(TriggeredStoredTransactionGroup $event): void
{
$newEvent = new StoredTransactionGroup($event->transactionGroup, true, false);
$this->processRules($newEvent);
}
/** /**
* This method grabs all the users rules and processes them. * This method grabs all the users rules and processes them.
*/ */

View File

@@ -26,6 +26,7 @@ namespace FireflyIII\Helpers\Collector\Extensions;
use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder; use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use FireflyIII\Support\Facades\Steam;
/** /**
* Trait AmountCollection * Trait AmountCollection
@@ -39,7 +40,7 @@ trait AmountCollection
{ {
$this->query->where( $this->query->where(
static function (EloquentBuilder $q) use ($amount): void { // @phpstan-ignore-line static function (EloquentBuilder $q) use ($amount): void { // @phpstan-ignore-line
$q->where('source.amount', app('steam')->negative($amount)); $q->where('source.amount', Steam::negative($amount));
} }
); );
@@ -50,7 +51,7 @@ trait AmountCollection
{ {
$this->query->where( $this->query->where(
static function (EloquentBuilder $q) use ($amount): void { // @phpstan-ignore-line static function (EloquentBuilder $q) use ($amount): void { // @phpstan-ignore-line
$q->where('source.amount', '!=', app('steam')->negative($amount)); $q->where('source.amount', '!=', Steam::negative($amount));
} }
); );
@@ -64,7 +65,7 @@ trait AmountCollection
{ {
$this->query->where( $this->query->where(
static function (EloquentBuilder $q) use ($amount): void { // @phpstan-ignore-line static function (EloquentBuilder $q) use ($amount): void { // @phpstan-ignore-line
$q->where('destination.amount', '<=', app('steam')->positive($amount)); $q->where('destination.amount', '<=', Steam::positive($amount));
} }
); );
@@ -78,7 +79,7 @@ trait AmountCollection
{ {
$this->query->where( $this->query->where(
static function (EloquentBuilder $q) use ($amount): void { // @phpstan-ignore-line static function (EloquentBuilder $q) use ($amount): void { // @phpstan-ignore-line
$q->where('destination.amount', '>=', app('steam')->positive($amount)); $q->where('destination.amount', '>=', Steam::positive($amount));
} }
); );
@@ -93,7 +94,7 @@ trait AmountCollection
$this->query->where( $this->query->where(
static function (EloquentBuilder $q) use ($amount): void { // @phpstan-ignore-line static function (EloquentBuilder $q) use ($amount): void { // @phpstan-ignore-line
$q->whereNotNull('source.foreign_amount'); $q->whereNotNull('source.foreign_amount');
$q->where('source.foreign_amount', app('steam')->negative($amount)); $q->where('source.foreign_amount', Steam::negative($amount));
} }
); );
@@ -108,7 +109,7 @@ trait AmountCollection
$this->query->where( $this->query->where(
static function (EloquentBuilder $q) use ($amount): void { // @phpstan-ignore-line static function (EloquentBuilder $q) use ($amount): void { // @phpstan-ignore-line
$q->whereNull('source.foreign_amount'); $q->whereNull('source.foreign_amount');
$q->orWhere('source.foreign_amount', '!=', app('steam')->negative($amount)); $q->orWhere('source.foreign_amount', '!=', Steam::negative($amount));
} }
); );
@@ -123,7 +124,7 @@ trait AmountCollection
$this->query->where( $this->query->where(
static function (EloquentBuilder $q) use ($amount): void { // @phpstan-ignore-line static function (EloquentBuilder $q) use ($amount): void { // @phpstan-ignore-line
$q->whereNotNull('destination.foreign_amount'); $q->whereNotNull('destination.foreign_amount');
$q->where('destination.foreign_amount', '<=', app('steam')->positive($amount)); $q->where('destination.foreign_amount', '<=', Steam::positive($amount));
} }
); );
@@ -138,7 +139,7 @@ trait AmountCollection
$this->query->where( $this->query->where(
static function (EloquentBuilder $q) use ($amount): void { // @phpstan-ignore-line static function (EloquentBuilder $q) use ($amount): void { // @phpstan-ignore-line
$q->whereNotNull('destination.foreign_amount'); $q->whereNotNull('destination.foreign_amount');
$q->where('destination.foreign_amount', '>=', app('steam')->positive($amount)); $q->where('destination.foreign_amount', '>=', Steam::positive($amount));
} }
); );

View File

@@ -38,6 +38,7 @@ use Illuminate\Http\Request;
use Illuminate\Routing\Redirector; use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Illuminate\View\View; use Illuminate\View\View;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class EditController * Class EditController
@@ -148,9 +149,9 @@ class EditController extends Controller
'BIC' => $repository->getMetaValue($account, 'BIC'), 'BIC' => $repository->getMetaValue($account, 'BIC'),
'opening_balance_date' => substr((string) $openingBalanceDate, 0, 10), 'opening_balance_date' => substr((string) $openingBalanceDate, 0, 10),
'liability_type_id' => $account->account_type_id, 'liability_type_id' => $account->account_type_id,
'opening_balance' => app('steam')->bcround($openingBalanceAmount, $currency->decimal_places), 'opening_balance' => Steam::bcround($openingBalanceAmount, $currency->decimal_places),
'liability_direction' => $this->repository->getMetaValue($account, 'liability_direction'), 'liability_direction' => $this->repository->getMetaValue($account, 'liability_direction'),
'virtual_balance' => app('steam')->bcround($virtualBalance, $currency->decimal_places), 'virtual_balance' => Steam::bcround($virtualBalance, $currency->decimal_places),
'currency_id' => $currency->id, 'currency_id' => $currency->id,
'include_net_worth' => $hasOldInput ? (bool) $request->old('include_net_worth') : $includeNetWorth, 'include_net_worth' => $hasOldInput ? (bool) $request->old('include_net_worth') : $includeNetWorth,
'interest' => $repository->getMetaValue($account, 'interest'), 'interest' => $repository->getMetaValue($account, 'interest'),

View File

@@ -31,6 +31,7 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Providers\RouteServiceProvider; use FireflyIII\Providers\RouteServiceProvider;
use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Support\Facades\Steam;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\Factory;
@@ -132,7 +133,7 @@ class LoginController extends Controller
return $this->sendLoginResponse($request); return $this->sendLoginResponse($request);
} }
Log::warning('Login attempt failed.'); Log::warning('Login attempt failed.');
$username = (string) $request->get($this->username()); $username = (string)$request->get($this->username());
$user = $this->repository->findByEmail($username); $user = $this->repository->findByEmail($username);
if (!$user instanceof User) { if (!$user instanceof User) {
// send event to owner. // send event to owner.
@@ -228,7 +229,7 @@ class LoginController extends Controller
$count = DB::table('users')->count(); $count = DB::table('users')->count();
$guard = config('auth.defaults.guard'); $guard = config('auth.defaults.guard');
$title = (string) trans('firefly.login_page_title'); $title = (string)trans('firefly.login_page_title');
if (0 === $count && 'web' === $guard) { if (0 === $count && 'web' === $guard) {
return redirect(route('register')); return redirect(route('register'));
@@ -260,4 +261,23 @@ class LoginController extends Controller
return view('auth.login', ['allowRegistration' => $allowRegistration, 'email' => $email, 'remember' => $remember, 'allowReset' => $allowReset, 'title' => $title, 'usernameField' => $usernameField]); return view('auth.login', ['allowRegistration' => $allowRegistration, 'email' => $email, 'remember' => $remember, 'allowReset' => $allowReset, 'title' => $title, 'usernameField' => $usernameField]);
} }
/**
* Send the response after the user was authenticated.
*
* @return JsonResponse|RedirectResponse
*/
protected function sendLoginResponse(Request $request)
{
$request->session()->regenerate();
$this->clearLoginAttempts($request);
if ($response = $this->authenticated($request, $this->guard()->user())) {
return $response;
}
$path = Steam::getSafeUrl(session()->pull('url.intended', route('index')), route('index'));
Log::debug(sprintf('SafeURL is %s', $path));
return $request->wantsJson() ? new JsonResponse([], 204) : redirect()->to($path);
}
} }

View File

@@ -35,6 +35,7 @@ use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse; use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class EditController * Class EditController
@@ -84,8 +85,8 @@ class EditController extends Controller
$this->rememberPreviousUrl('bills.edit.url'); $this->rememberPreviousUrl('bills.edit.url');
} }
$bill->amount_min = app('steam')->bcround($bill->amount_min, $bill->transactionCurrency->decimal_places); $bill->amount_min = Steam::bcround($bill->amount_min, $bill->transactionCurrency->decimal_places);
$bill->amount_max = app('steam')->bcround($bill->amount_max, $bill->transactionCurrency->decimal_places); $bill->amount_max = Steam::bcround($bill->amount_max, $bill->transactionCurrency->decimal_places);
$rules = $this->repository->getRulesForBill($bill); $rules = $this->repository->getRulesForBill($bill);
// code to handle active-checkboxes // code to handle active-checkboxes

View File

@@ -44,6 +44,7 @@ use Illuminate\Http\Request;
use Illuminate\Routing\Redirector; use Illuminate\Routing\Redirector;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\View\View; use Illuminate\View\View;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class BudgetLimitController * Class BudgetLimitController
@@ -274,7 +275,7 @@ class BudgetLimitController extends Controller
$array['left_per_day'] = 0 === $daysLeft ? bcadd((string) $array['spent'], (string) $array['amount']) : bcdiv(bcadd((string) $array['spent'], (string) $array['amount']), $array['days_left']); $array['left_per_day'] = 0 === $daysLeft ? bcadd((string) $array['spent'], (string) $array['amount']) : bcdiv(bcadd((string) $array['spent'], (string) $array['amount']), $array['days_left']);
// left per day formatted. // left per day formatted.
$array['amount'] = app('steam')->bcround($limit['amount'], $limit->transactionCurrency->decimal_places); $array['amount'] = Steam::bcround($limit['amount'], $limit->transactionCurrency->decimal_places);
$array['left_per_day_formatted'] = app('amount')->formatAnything($limit->transactionCurrency, $array['left_per_day']); $array['left_per_day_formatted'] = app('amount')->formatAnything($limit->transactionCurrency, $array['left_per_day']);
if ('true' === $request->get('redirect')) { if ('true' === $request->get('redirect')) {
return redirect(route('budgets.index')); return redirect(route('budgets.index'));

View File

@@ -37,6 +37,7 @@ use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Illuminate\View\View; use Illuminate\View\View;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class EditController * Class EditController
@@ -104,7 +105,7 @@ class EditController extends Controller
$amount = '0'; $amount = '0';
} }
$amount = (string) $amount; $amount = (string) $amount;
$preFilled['auto_budget_amount'] = app('steam')->bcround($amount, $autoBudget->transactionCurrency->decimal_places); $preFilled['auto_budget_amount'] = Steam::bcround($amount, $autoBudget->transactionCurrency->decimal_places);
} }
// put previous url in session if not redirect from store (not "return_to_edit"). // put previous url in session if not redirect from store (not "return_to_edit").

View File

@@ -46,6 +46,7 @@ use Illuminate\Http\Request;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Illuminate\View\View; use Illuminate\View\View;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class IndexController * Class IndexController
@@ -122,6 +123,9 @@ class IndexController extends Controller
$availableBudgets = $this->getAllAvailableBudgets($start, $end); $availableBudgets = $this->getAllAvailableBudgets($start, $end);
// get all active budgets: // get all active budgets:
$budgets = $this->getAllBudgets($start, $end, $currencies, $this->primaryCurrency); $budgets = $this->getAllBudgets($start, $end, $currencies, $this->primaryCurrency);
// echo '<pre>';
// var_dump($budgets[0]);exit;
$sums = $this->getSums($budgets); $sums = $this->getSums($budgets);
// get budgeted for default currency: // get budgeted for default currency:
@@ -200,7 +204,7 @@ class IndexController extends Controller
foreach ($budgetLimits as $limit) { foreach ($budgetLimits as $limit) {
Log::debug(sprintf('Working on budget limit #%d', $limit->id)); Log::debug(sprintf('Working on budget limit #%d', $limit->id));
$currency = $limit->transactionCurrency ?? $primaryCurrency; $currency = $limit->transactionCurrency ?? $primaryCurrency;
$amount = app('steam')->bcround($limit->amount, $currency->decimal_places); $amount = Steam::bcround($limit->amount, $currency->decimal_places);
$array['budgeted'][] = [ $array['budgeted'][] = [
'id' => $limit->id, 'id' => $limit->id,
'amount' => $amount, 'amount' => $amount,

View File

@@ -31,6 +31,7 @@ use FireflyIII\Models\Bill;
use FireflyIII\Repositories\Bill\BillRepositoryInterface; use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Support\CacheProperties; use FireflyIII\Support\CacheProperties;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class BillController. * Class BillController.
@@ -113,7 +114,7 @@ class BillController extends Controller
if ($cache->has()) { if ($cache->has()) {
return response()->json($cache->get()); return response()->json($cache->get());
} }
$locale = app('steam')->getLocale(); $locale = Steam::getLocale();
/** @var GroupCollectorInterface $collector */ /** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class); $collector = app(GroupCollectorInterface::class);

View File

@@ -44,6 +44,7 @@ use FireflyIII\Support\Http\Controllers\DateCalculation;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class BudgetController. * Class BudgetController.
@@ -166,7 +167,7 @@ class BudgetController extends Controller
if ($cache->has()) { if ($cache->has()) {
return response()->json($cache->get()); return response()->json($cache->get());
} }
$locale = app('steam')->getLocale(); $locale = Steam::getLocale();
$entries = []; $entries = [];
$amount = $budgetLimit->amount ?? '0'; $amount = $budgetLimit->amount ?? '0';
$budgetCollection = new Collection()->push($budget); $budgetCollection = new Collection()->push($budget);
@@ -531,13 +532,13 @@ class BudgetController extends Controller
// get budget limit in this period for this currency. // get budget limit in this period for this currency.
$limit = $this->blRepository->find($budget, $currency, $currentStart, $currentEnd); $limit = $this->blRepository->find($budget, $currency, $currentStart, $currentEnd);
if ($limit instanceof BudgetLimit) { if ($limit instanceof BudgetLimit) {
$chartData[1]['entries'][$title] = app('steam')->bcround($limit->amount, $currency->decimal_places); $chartData[1]['entries'][$title] = Steam::bcround($limit->amount, $currency->decimal_places);
} }
// get spent amount in this period for this currency. // get spent amount in this period for this currency.
$sum = $this->opsRepository->sumExpenses($currentStart, $currentEnd, $accounts, new Collection()->push($budget), $currency); $sum = $this->opsRepository->sumExpenses($currentStart, $currentEnd, $accounts, new Collection()->push($budget), $currency);
$amount = app('steam')->positive($sum[$currency->id]['sum'] ?? '0'); $amount = Steam::positive($sum[$currency->id]['sum'] ?? '0');
$chartData[0]['entries'][$title] = app('steam')->bcround($amount, $currency->decimal_places); $chartData[0]['entries'][$title] = Steam::bcround($amount, $currency->decimal_places);
$currentStart = clone $currentEnd; $currentStart = clone $currentEnd;
$currentStart->addDay()->startOfDay(); $currentStart->addDay()->startOfDay();
@@ -574,8 +575,8 @@ class BudgetController extends Controller
$currentEnd = Navigation::endOfPeriod($currentStart, $preferredRange); $currentEnd = Navigation::endOfPeriod($currentStart, $preferredRange);
$title = $currentStart->isoFormat($titleFormat); $title = $currentStart->isoFormat($titleFormat);
$sum = $this->nbRepository->sumExpenses($currentStart, $currentEnd, $accounts, $currency); $sum = $this->nbRepository->sumExpenses($currentStart, $currentEnd, $accounts, $currency);
$amount = app('steam')->positive($sum[$currency->id]['sum'] ?? '0'); $amount = Steam::positive($sum[$currency->id]['sum'] ?? '0');
$chartData[$title] = app('steam')->bcround($amount, $currency->decimal_places); $chartData[$title] = Steam::bcround($amount, $currency->decimal_places);
$currentStart = Navigation::addPeriod($currentStart, $preferredRange, 0); $currentStart = Navigation::addPeriod($currentStart, $preferredRange, 0);
} }

View File

@@ -33,6 +33,7 @@ use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Support\CacheProperties; use FireflyIII\Support\CacheProperties;
use FireflyIII\Support\Http\Controllers\DateCalculation; use FireflyIII\Support\Http\Controllers\DateCalculation;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class PiggyBankController. * Class PiggyBankController.
@@ -70,7 +71,7 @@ class PiggyBankController extends Controller
} }
$set = $repository->getEvents($piggyBank); $set = $repository->getEvents($piggyBank);
$set = $set->reverse(); $set = $set->reverse();
$locale = app('steam')->getLocale(); $locale = Steam::getLocale();
// get first event or start date of piggy bank or today // get first event or start date of piggy bank or today
$startDate = $piggyBank->start_date ?? today(config('app.timezone')); $startDate = $piggyBank->start_date ?? today(config('app.timezone'));

View File

@@ -105,7 +105,7 @@ class JavascriptController extends Controller
if ($account instanceof Account) { if ($account instanceof Account) {
$currency = $repository->getAccountCurrency($account) ?? $this->primaryCurrency; $currency = $repository->getAccountCurrency($account) ?? $this->primaryCurrency;
} }
$locale = app('steam')->getLocale(); $locale = Steam::getLocale();
$accounting = app('amount')->getJsConfig(); $accounting = app('amount')->getJsConfig();
$accounting['frac_digits'] = $currency->decimal_places; $accounting['frac_digits'] = $currency->decimal_places;
$pref = Preferences::get('language', config('firefly.default_language', 'en_US')); $pref = Preferences::get('language', config('firefly.default_language', 'en_US'));

View File

@@ -278,9 +278,9 @@ class ReconcileController extends Controller
} }
if ($inverse) { if ($inverse) {
$journal['amount'] = app('steam')->positive($journal['amount']); $journal['amount'] = Steam::positive($journal['amount']);
if (null !== $journal['foreign_amount']) { if (null !== $journal['foreign_amount']) {
$journal['foreign_amount'] = app('steam')->positive($journal['foreign_amount']); $journal['foreign_amount'] = Steam::positive($journal['foreign_amount']);
} }
} }

View File

@@ -33,6 +33,7 @@ use FireflyIII\Models\RecurrenceRepetition;
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class RecurrenceController * Class RecurrenceController
@@ -167,7 +168,7 @@ class RecurrenceController extends Controller
} }
$date->startOfDay(); $date->startOfDay();
$preSelected = (string) $request->get('pre_select'); $preSelected = (string) $request->get('pre_select');
$locale = app('steam')->getLocale(); $locale = Steam::getLocale();
Log::debug(sprintf('date = %s, today = %s. date > today? %s', $date->toAtomString(), $today->toAtomString(), var_export($date > $today, true))); Log::debug(sprintf('date = %s, today = %s. date > today? %s', $date->toAtomString(), $today->toAtomString(), var_export($date > $today, true)));
Log::debug(sprintf('past = true? %s', var_export('true' === (string) $request->get('past'), true))); Log::debug(sprintf('past = true? %s', var_export('true' === (string) $request->get('past'), true)));

View File

@@ -35,6 +35,7 @@ use Illuminate\Http\RedirectResponse;
use Illuminate\Routing\Redirector; use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Illuminate\View\View; use Illuminate\View\View;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class EditController * Class EditController
@@ -89,7 +90,7 @@ class EditController extends Controller
$preFilled = [ $preFilled = [
'name' => $piggyBank->name, 'name' => $piggyBank->name,
'transaction_currency_id' => (int) $piggyBank->transaction_currency_id, 'transaction_currency_id' => (int) $piggyBank->transaction_currency_id,
'target_amount' => app('steam')->bcround($piggyBank->target_amount, $piggyBank->transactionCurrency->decimal_places), 'target_amount' => Steam::bcround($piggyBank->target_amount, $piggyBank->transactionCurrency->decimal_places),
'target_date' => $targetDate, 'target_date' => $targetDate,
'start_date' => $startDate, 'start_date' => $startDate,
'accounts' => [], 'accounts' => [],

View File

@@ -44,6 +44,7 @@ use Illuminate\Support\Facades\Log;
use Illuminate\View\View; use Illuminate\View\View;
use JsonException; use JsonException;
use Safe\Exceptions\FilesystemException; use Safe\Exceptions\FilesystemException;
use FireflyIII\Support\Facades\Steam;
use function Safe\file_get_contents; use function Safe\file_get_contents;
use function Safe\json_decode; use function Safe\json_decode;
@@ -108,7 +109,7 @@ class PreferencesController extends Controller
if (!is_array($frontpageAccounts)) { if (!is_array($frontpageAccounts)) {
$frontpageAccounts = $accountIds; $frontpageAccounts = $accountIds;
} }
$language = app('steam')->getLanguage(); $language = Steam::getLanguage();
$languages = config('firefly.languages'); $languages = config('firefly.languages');
$locale = Preferences::get('locale', config('firefly.default_locale', 'equal'))->data; $locale = Preferences::get('locale', config('firefly.default_locale', 'equal'))->data;
$listPageSize = Preferences::get('listPageSize', 50)->data; $listPageSize = Preferences::get('listPageSize', 50)->data;

View File

@@ -113,6 +113,8 @@ class ProfileController extends Controller
throw new FireflyException('Invalid token.'); throw new FireflyException('Invalid token.');
} }
$repository->unblockUser($user); $repository->unblockUser($user);
// also remove the "remote_guard_alt_email" preference.
Preferences::delete('remote_guard_alt_email');
// return to log in. // return to log in.
session()->flash('success', (string) trans('firefly.login_with_new_email')); session()->flash('success', (string) trans('firefly.login_with_new_email'));

View File

@@ -26,14 +26,16 @@ namespace FireflyIII\Http\Controllers\RuleGroup;
use Carbon\Carbon; use Carbon\Carbon;
use Exception; use Exception;
use FireflyIII\Events\Model\TransactionGroup\TriggeredStoredTransactionGroup;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Requests\SelectTransactionsRequest; use FireflyIII\Http\Requests\SelectTransactionsRequest;
use FireflyIII\Models\RuleGroup; use FireflyIII\Models\RuleGroup;
use FireflyIII\TransactionRules\Engine\RuleEngineInterface; use FireflyIII\Models\TransactionGroup;
use FireflyIII\User; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse; use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Collection; use Illuminate\Support\Facades\Log;
use Illuminate\View\View; use Illuminate\View\View;
/** /**
@@ -41,18 +43,20 @@ use Illuminate\View\View;
*/ */
class ExecutionController extends Controller class ExecutionController extends Controller
{ {
private readonly AccountRepositoryInterface $repository;
/** /**
* ExecutionController constructor. * ExecutionController constructor.
*/ */
public function __construct() public function __construct()
{ {
parent::__construct(); parent::__construct();
$this->repository = app(AccountRepositoryInterface::class);
$this->middleware( $this->middleware(
function ($request, $next) { function ($request, $next) {
app('view')->share('title', (string) trans('firefly.rules')); app('view')->share('title', (string)trans('firefly.rules'));
app('view')->share('mainTitleIcon', 'fa-random'); app('view')->share('mainTitleIcon', 'fa-random');
$this->repository->setUser(auth()->user());
return $next($request); return $next($request);
} }
@@ -67,34 +71,37 @@ class ExecutionController extends Controller
public function execute(SelectTransactionsRequest $request, RuleGroup $ruleGroup): RedirectResponse public function execute(SelectTransactionsRequest $request, RuleGroup $ruleGroup): RedirectResponse
{ {
// Get parameters specified by the user // Get parameters specified by the user
/** @var User $user */ $accounts = $request->get('accounts');
$user = auth()->user(); $set = $this->repository->getAccountsById($accounts);
$accounts = implode(',', $request->get('accounts'));
// create new rule engine:
$newRuleEngine = app(RuleEngineInterface::class);
$newRuleEngine->setUser($user);
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setAccounts($set);
// add date operators. // add date operators.
if (null !== $request->get('start')) { if (null !== $request->get('start')) {
$startDate = new Carbon($request->get('start')); $startDate = new Carbon($request->get('start'));
$newRuleEngine->addOperator(['type' => 'date_after', 'value' => $startDate->format('Y-m-d')]); $collector->setStart($startDate);
} }
if (null !== $request->get('end')) { if (null !== $request->get('end')) {
$endDate = new Carbon($request->get('end')); $endDate = new Carbon($request->get('end'));
$newRuleEngine->addOperator(['type' => 'date_before', 'value' => $endDate->format('Y-m-d')]); $collector->setEnd($endDate);
}
$final = $collector->getGroups();
$ids = $final->pluck('id')->toArray();
Log::debug(sprintf('Found %d groups collected from %d account(s)', $final->count(), $set->count()));
foreach (array_chunk($ids, 1337) as $setOfIds) {
Log::debug(sprintf('Now processing %d groups', count($setOfIds)));
$groups = TransactionGroup::whereIn('id', $setOfIds)->get();
/** @var TransactionGroup $group */
foreach ($groups as $group) {
Log::debug(sprintf('Processing group #%d.', $group->id));
event(new TriggeredStoredTransactionGroup($group));
}
} }
// add extra operators:
$newRuleEngine->addOperator(['type' => 'account_id', 'value' => $accounts]);
// set rules:
// #10427, file rule group and not the set of rules.
$collection = new Collection()->push($ruleGroup);
$newRuleEngine->setRuleGroups($collection);
$newRuleEngine->fire();
// Tell the user that the job is queued // Tell the user that the job is queued
session()->flash('success', (string) trans('firefly.applied_rule_group_selection', ['title' => $ruleGroup->title])); session()->flash('success', (string)trans('firefly.applied_rule_group_selection', ['title' => $ruleGroup->title]));
return redirect()->route('rules.index'); return redirect()->route('rules.index');
} }
@@ -106,7 +113,7 @@ class ExecutionController extends Controller
*/ */
public function selectTransactions(RuleGroup $ruleGroup): Factory|\Illuminate\Contracts\View\View public function selectTransactions(RuleGroup $ruleGroup): Factory|\Illuminate\Contracts\View\View
{ {
$subTitle = (string) trans('firefly.apply_rule_group_selection', ['title' => $ruleGroup->title]); $subTitle = (string)trans('firefly.apply_rule_group_selection', ['title' => $ruleGroup->title]);
return view('rules.rule-group.select-transactions', ['ruleGroup' => $ruleGroup, 'subTitle' => $subTitle]); return view('rules.rule-group.select-transactions', ['ruleGroup' => $ruleGroup, 'subTitle' => $subTitle]);
} }

View File

@@ -38,6 +38,7 @@ use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse; use Illuminate\Http\RedirectResponse;
use Illuminate\Routing\Redirector; use Illuminate\Routing\Redirector;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class DeleteController * Class DeleteController
@@ -83,7 +84,7 @@ class DeleteController extends Controller
} }
$objectType = strtolower($journal->transaction_type_type ?? $journal->transactionType->type); $objectType = strtolower($journal->transaction_type_type ?? $journal->transactionType->type);
$subTitle = (string) trans('firefly.delete_'.$objectType, ['description' => $group->title ?? $journal->description]); $subTitle = (string) trans('firefly.delete_'.$objectType, ['description' => $group->title ?? $journal->description]);
$previous = app('steam')->getSafePreviousUrl(); $previous = Steam::getSafePreviousUrl();
// put previous url in session // put previous url in session
Log::debug('Will try to remember previous URL'); Log::debug('Will try to remember previous URL');
$this->rememberPreviousUrl('transactions.delete.url'); $this->rememberPreviousUrl('transactions.delete.url');

View File

@@ -24,13 +24,13 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Transaction; namespace FireflyIII\Http\Controllers\Transaction;
use FireflyIII\Support\Facades\Preferences;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\Http\Controllers\PeriodOverview; use FireflyIII\Support\Http\Controllers\PeriodOverview;
use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\Factory;
use Illuminate\Http\Request; use Illuminate\Http\Request;
@@ -58,7 +58,7 @@ class IndexController extends Controller
$this->middleware( $this->middleware(
function ($request, $next) { function ($request, $next) {
app('view')->share('mainTitleIcon', 'fa-exchange'); app('view')->share('mainTitleIcon', 'fa-exchange');
app('view')->share('title', (string) trans('firefly.transactions')); app('view')->share('title', (string)trans('firefly.transactions'));
$this->repository = app(JournalRepositoryInterface::class); $this->repository = app(JournalRepositoryInterface::class);
@@ -84,8 +84,8 @@ class IndexController extends Controller
$subTitleIcon = config('firefly.transactionIconsByType.'.$objectType); $subTitleIcon = config('firefly.transactionIconsByType.'.$objectType);
$types = config('firefly.transactionTypesByType.'.$objectType); $types = config('firefly.transactionTypesByType.'.$objectType);
$page = (int) $request->get('page'); $page = (int)$request->get('page');
$pageSize = (int) Preferences::get('listPageSize', 50)->data; $pageSize = (int)Preferences::get('listPageSize', 50)->data;
if (!$start instanceof Carbon) { if (!$start instanceof Carbon) {
$start = session('start'); $start = session('start');
@@ -100,11 +100,17 @@ class IndexController extends Controller
[$start, $end] = $end < $start ? [$end, $start] : [$start, $end]; [$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
$startStr = $start->isoFormat($this->monthAndDayFormat); $startStr = $start->isoFormat($this->monthAndDayFormat);
$endStr = $end->isoFormat($this->monthAndDayFormat); $endStr = $end->isoFormat($this->monthAndDayFormat);
$subTitle = (string) trans(sprintf('firefly.title_%s_between', $objectType), ['start' => $startStr, 'end' => $endStr]); $subTitle = (string)trans(sprintf('firefly.title_%s_between', $objectType), ['start' => $startStr, 'end' => $endStr]);
$path = route('transactions.index', [$objectType, $start->format('Y-m-d'), $end->format('Y-m-d')]); $path = route('transactions.index', [$objectType, $start->format('Y-m-d'), $end->format('Y-m-d')]);
$firstJournal = $this->repository->firstNull(); $firstJournal = $this->repository->firstNull();
$startPeriod = $firstJournal instanceof TransactionJournal ? $firstJournal->date : new Carbon(); $startPeriod = $firstJournal instanceof TransactionJournal ? $firstJournal->date : new Carbon();
$endPeriod = clone $end; $endPeriod = clone $end;
// limit to 3 years for the time being.
if (now()->diffInYears($startPeriod, true) > 3) {
$startPeriod = now()->subYears(3);
}
$periods = $this->getTransactionPeriodOverview($objectType, $startPeriod, $endPeriod); $periods = $this->getTransactionPeriodOverview($objectType, $startPeriod, $endPeriod);
/** @var GroupCollectorInterface $collector */ /** @var GroupCollectorInterface $collector */
@@ -137,14 +143,14 @@ class IndexController extends Controller
{ {
$subTitleIcon = config('firefly.transactionIconsByType.'.$objectType); $subTitleIcon = config('firefly.transactionIconsByType.'.$objectType);
$types = config('firefly.transactionTypesByType.'.$objectType); $types = config('firefly.transactionTypesByType.'.$objectType);
$page = (int) $request->get('page'); $page = (int)$request->get('page');
$pageSize = (int) Preferences::get('listPageSize', 50)->data; $pageSize = (int)Preferences::get('listPageSize', 50)->data;
$path = route('transactions.index.all', [$objectType]); $path = route('transactions.index.all', [$objectType]);
$first = $this->repository->firstNull(); $first = $this->repository->firstNull();
$start = $first instanceof TransactionJournal ? $first->date : new Carbon(); $start = $first instanceof TransactionJournal ? $first->date : new Carbon();
$last = $this->repository->getLast(); $last = $this->repository->getLast();
$end = $last instanceof TransactionJournal ? $last->date : today(config('app.timezone')); $end = $last instanceof TransactionJournal ? $last->date : today(config('app.timezone'));
$subTitle = (string) trans('firefly.all_'.$objectType); $subTitle = (string)trans('firefly.all_'.$objectType);
/** @var GroupCollectorInterface $collector */ /** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class); $collector = app(GroupCollectorInterface::class);

View File

@@ -36,6 +36,7 @@ use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Routing\Redirector; use Illuminate\Routing\Redirector;
use Illuminate\View\View; use Illuminate\View\View;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class LinkController. * Class LinkController.
@@ -145,6 +146,6 @@ class LinkController extends Controller
$linkId = (int) $request->get('id'); $linkId = (int) $request->get('id');
$this->repository->switchLinkById($linkId); $this->repository->switchLinkById($linkId);
return redirect(app('steam')->getSafePreviousUrl()); return redirect(Steam::getSafePreviousUrl());
} }
} }

View File

@@ -43,6 +43,7 @@ use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Illuminate\View\View as IlluminateView; use Illuminate\View\View as IlluminateView;
use InvalidArgumentException; use InvalidArgumentException;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class MassController. * Class MassController.
@@ -142,9 +143,9 @@ class MassController extends Controller
// reverse amounts // reverse amounts
foreach ($journals as $index => $journal) { foreach ($journals as $index => $journal) {
$journals[$index]['amount'] = app('steam')->bcround(app('steam')->positive($journal['amount']), $journal['currency_decimal_places']); $journals[$index]['amount'] = Steam::bcround(Steam::positive($journal['amount']), $journal['currency_decimal_places']);
$journals[$index]['foreign_amount'] = null === $journal['foreign_amount'] $journals[$index]['foreign_amount'] = null === $journal['foreign_amount']
? null : app('steam')->positive($journal['foreign_amount']); ? null : Steam::positive($journal['foreign_amount']);
} }
$this->rememberPreviousUrl('transactions.mass-edit.url'); $this->rememberPreviousUrl('transactions.mass-edit.url');

View File

@@ -27,6 +27,7 @@ use Illuminate\Contracts\Session\Session;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Session\Middleware\StartSession; use Illuminate\Session\Middleware\StartSession;
use Override; use Override;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class StartFireflySession. * Class StartFireflySession.
@@ -42,7 +43,7 @@ class StartFireflySession extends StartSession
protected function storeCurrentUrl(Request $request, $session): void protected function storeCurrentUrl(Request $request, $session): void
{ {
$url = $request->fullUrl(); $url = $request->fullUrl();
$safeUrl = app('steam')->getSafeUrl($url, route('index')); $safeUrl = Steam::getSafeUrl($url, route('index'));
if ($url !== $safeUrl) { if ($url !== $safeUrl) {
return; return;

View File

@@ -34,6 +34,7 @@ use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class AccountFormRequest. * Class AccountFormRequest.
@@ -87,7 +88,7 @@ class AccountFormRequest extends FormRequest
$data['account_type_id'] = $this->convertInteger('liability_type_id'); $data['account_type_id'] = $this->convertInteger('liability_type_id');
if ('' !== $data['opening_balance']) { if ('' !== $data['opening_balance']) {
// opening balance is always positive for liabilities // opening balance is always positive for liabilities
$data['opening_balance'] = app('steam')->positive($data['opening_balance']); $data['opening_balance'] = Steam::positive($data['opening_balance']);
} }
} }

View File

@@ -29,6 +29,7 @@ use FireflyIII\Exceptions\FireflyException;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable; use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class NewIPAddressWarningMail * Class NewIPAddressWarningMail
@@ -57,7 +58,7 @@ class NewIPAddressWarningMail extends Mailable
$this->host = ''; $this->host = '';
try { try {
$hostName = app('steam')->getHostName($this->ipAddress); $hostName = Steam::getHostName($this->ipAddress);
} catch (FireflyException $e) { } catch (FireflyException $e) {
Log::error($e->getMessage()); Log::error($e->getMessage());
$hostName = $this->ipAddress; $hostName = $this->ipAddress;

View File

@@ -33,6 +33,7 @@ use FireflyIII\Events\Model\PiggyBank\ChangedAmount;
use FireflyIII\Events\Model\PiggyBank\ChangedName; use FireflyIII\Events\Model\PiggyBank\ChangedName;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnObject; use FireflyIII\Events\Model\Rule\RuleActionFailedOnObject;
use FireflyIII\Events\Model\TransactionGroup\TriggeredStoredTransactionGroup;
use FireflyIII\Events\NewVersionAvailable; use FireflyIII\Events\NewVersionAvailable;
use FireflyIII\Events\Preferences\UserGroupChangedPrimaryCurrency; use FireflyIII\Events\Preferences\UserGroupChangedPrimaryCurrency;
use FireflyIII\Events\RegisteredUser; use FireflyIII\Events\RegisteredUser;
@@ -131,6 +132,9 @@ class EventServiceProvider extends ServiceProvider
StoredTransactionGroup::class => [ StoredTransactionGroup::class => [
'FireflyIII\Handlers\Events\StoredGroupEventHandler@runAllHandlers', 'FireflyIII\Handlers\Events\StoredGroupEventHandler@runAllHandlers',
], ],
TriggeredStoredTransactionGroup::class => [
'FireflyIII\Handlers\Events\StoredGroupEventHandler@triggerRulesManually',
],
// is a Transaction Journal related event. // is a Transaction Journal related event.
UpdatedTransactionGroup::class => [ UpdatedTransactionGroup::class => [
'FireflyIII\Handlers\Events\UpdatedGroupEventHandler@runAllHandlers', 'FireflyIII\Handlers\Events\UpdatedGroupEventHandler@runAllHandlers',

View File

@@ -167,12 +167,6 @@ class AccountRepository implements AccountRepositoryInterface, UserGroupInterfac
return $account; return $account;
} }
#[Override]
public function getAccountBalances(Account $account): Collection
{
return $account->accountBalances;
}
/** /**
* Return account type or null if not found. * Return account type or null if not found.
*/ */

View File

@@ -71,8 +71,6 @@ interface AccountRepositoryInterface
public function findByName(string $name, array $types): ?Account; public function findByName(string $name, array $types): ?Account;
public function getAccountBalances(Account $account): Collection;
public function getAccountCurrency(Account $account): ?TransactionCurrency; public function getAccountCurrency(Account $account): ?TransactionCurrency;
/** /**

View File

@@ -41,6 +41,7 @@ use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Override; use Override;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class OperationsRepository * Class OperationsRepository
@@ -157,7 +158,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
]; ];
foreach ($journals as $journal) { foreach ($journals as $journal) {
$amount = app('steam')->negative($journal['amount']); $amount = Steam::negative($journal['amount']);
$journalCurrencyId = (int) $journal['currency_id']; $journalCurrencyId = (int) $journal['currency_id'];
if (false === $convertToPrimary) { if (false === $convertToPrimary) {
$currencyId = $journalCurrencyId; $currencyId = $journalCurrencyId;

View File

@@ -78,7 +78,7 @@ class NoCategoryRepository implements NoCategoryRepositoryInterface, UserGroupIn
$journalId = (int) $journal['transaction_journal_id']; $journalId = (int) $journal['transaction_journal_id'];
$array[$currencyId]['categories'][0]['transaction_journals'][$journalId] $array[$currencyId]['categories'][0]['transaction_journals'][$journalId]
= [ = [
'amount' => app('steam')->negative($journal['amount']), 'amount' => Steam::negative($journal['amount']),
'date' => $journal['date'], 'date' => $journal['date'],
]; ];
} }
@@ -124,7 +124,7 @@ class NoCategoryRepository implements NoCategoryRepositoryInterface, UserGroupIn
$journalId = (int) $journal['transaction_journal_id']; $journalId = (int) $journal['transaction_journal_id'];
$array[$currencyId]['categories'][0]['transaction_journals'][$journalId] $array[$currencyId]['categories'][0]['transaction_journals'][$journalId]
= [ = [
'amount' => app('steam')->positive($journal['amount']), 'amount' => Steam::positive($journal['amount']),
'date' => $journal['date'], 'date' => $journal['date'],
]; ];
} }

View File

@@ -100,7 +100,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
// only a subset of the fields. // only a subset of the fields.
$journalId = (int) $journal['transaction_journal_id']; $journalId = (int) $journal['transaction_journal_id'];
$array[$currencyId]['categories'][$categoryId]['transaction_journals'][$journalId] = [ $array[$currencyId]['categories'][$categoryId]['transaction_journals'][$journalId] = [
'amount' => app('steam')->negative($journal['amount']), 'amount' => Steam::negative($journal['amount']),
'date' => $journal['date'], 'date' => $journal['date'],
'source_account_id' => (string) $journal['source_account_id'], 'source_account_id' => (string) $journal['source_account_id'],
'budget_name' => $journal['budget_name'], 'budget_name' => $journal['budget_name'],
@@ -178,7 +178,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
// only a subset of the fields. // only a subset of the fields.
$journalId = (int) $journal['transaction_journal_id']; $journalId = (int) $journal['transaction_journal_id'];
$array[$currencyId]['categories'][$categoryId]['transaction_journals'][$journalId] = [ $array[$currencyId]['categories'][$categoryId]['transaction_journals'][$journalId] = [
'amount' => app('steam')->positive($journal['amount']), 'amount' => Steam::positive($journal['amount']),
'date' => $journal['date'], 'date' => $journal['date'],
'source_account_id' => (string) $journal['source_account_id'], 'source_account_id' => (string) $journal['source_account_id'],
'destination_account_id' => (string) $journal['destination_account_id'], 'destination_account_id' => (string) $journal['destination_account_id'],
@@ -240,7 +240,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
// only a subset of the fields. // only a subset of the fields.
$journalId = (int) $journal['transaction_journal_id']; $journalId = (int) $journal['transaction_journal_id'];
$array[$currencyId]['categories'][$categoryId]['transaction_journals'][$journalId] = [ $array[$currencyId]['categories'][$categoryId]['transaction_journals'][$journalId] = [
'amount' => app('steam')->positive($journal['amount']), 'amount' => Steam::positive($journal['amount']),
'date' => $journal['date'], 'date' => $journal['date'],
'source_account_id' => (string) $journal['source_account_id'], 'source_account_id' => (string) $journal['source_account_id'],
'category_name' => $journal['category_name'], 'category_name' => $journal['category_name'],
@@ -303,7 +303,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
// only a subset of the fields. // only a subset of the fields.
$journalId = (int) $journal['transaction_journal_id']; $journalId = (int) $journal['transaction_journal_id'];
$array[$currencyId]['categories'][$categoryId]['transaction_journals'][$journalId] = [ $array[$currencyId]['categories'][$categoryId]['transaction_journals'][$journalId] = [
'amount' => app('steam')->negative($journal['amount']), 'amount' => Steam::negative($journal['amount']),
'date' => $journal['date'], 'date' => $journal['date'],
'source_account_id' => (string) $journal['source_account_id'], 'source_account_id' => (string) $journal['source_account_id'],
'category_name' => $journal['category_name'], 'category_name' => $journal['category_name'],

View File

@@ -31,6 +31,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Support\Repositories\UserGroup\UserGroupInterface; use FireflyIII\Support\Repositories\UserGroup\UserGroupInterface;
use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait; use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class OperationsRepository * Class OperationsRepository
@@ -97,7 +98,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
]; ];
$array[$currencyId]['tags'][$tagId]['transaction_journals'][$journalId] = [ $array[$currencyId]['tags'][$tagId]['transaction_journals'][$journalId] = [
'amount' => app('steam')->negative($journal['amount']), 'amount' => Steam::negative($journal['amount']),
'date' => $journal['date'], 'date' => $journal['date'],
'source_account_id' => $journal['source_account_id'], 'source_account_id' => $journal['source_account_id'],
'budget_name' => $journal['budget_name'], 'budget_name' => $journal['budget_name'],
@@ -182,7 +183,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
]; ];
$journalId = (int) $journal['transaction_journal_id']; $journalId = (int) $journal['transaction_journal_id'];
$array[$currencyId]['tags'][$tagId]['transaction_journals'][$journalId] = [ $array[$currencyId]['tags'][$tagId]['transaction_journals'][$journalId] = [
'amount' => app('steam')->positive($journal['amount']), 'amount' => Steam::positive($journal['amount']),
'date' => $journal['date'], 'date' => $journal['date'],
'source_account_id' => $journal['source_account_id'], 'source_account_id' => $journal['source_account_id'],
'budget_name' => $journal['budget_name'], 'budget_name' => $journal['budget_name'],

View File

@@ -50,6 +50,7 @@ use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use FireflyIII\Support\Facades\Steam;
use function Safe\json_decode; use function Safe\json_decode;
@@ -245,9 +246,9 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface,
$transaction = $journal->transactions->first(); $transaction = $journal->transactions->first();
$currency = $transaction->transactionCurrency; $currency = $transaction->transactionCurrency;
$type = $journal->transactionType->type; $type = $journal->transactionType->type;
$amount = app('steam')->positive($transaction->amount); $amount = Steam::positive($transaction->amount);
if (TransactionTypeEnum::WITHDRAWAL->value === $type) { if (TransactionTypeEnum::WITHDRAWAL->value === $type) {
return Amount::formatAnything($currency, app('steam')->negative($amount)); return Amount::formatAnything($currency, Steam::negative($amount));
} }
return Amount::formatAnything($currency, $amount); return Amount::formatAnything($currency, $amount);
@@ -267,9 +268,9 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface,
$currency = $transaction->foreignCurrency; $currency = $transaction->foreignCurrency;
$type = $journal->transactionType->type; $type = $journal->transactionType->type;
$amount = app('steam')->positive($transaction->foreign_amount); $amount = Steam::positive($transaction->foreign_amount);
if (TransactionTypeEnum::WITHDRAWAL->value === $type) { if (TransactionTypeEnum::WITHDRAWAL->value === $type) {
return Amount::formatAnything($currency, app('steam')->negative($amount)); return Amount::formatAnything($currency, Steam::negative($amount));
} }
return Amount::formatAnything($currency, $amount); return Amount::formatAnything($currency, $amount);

View File

@@ -43,6 +43,7 @@ use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Services\Internal\Destroy\TransactionGroupDestroyService; use FireflyIII\Services\Internal\Destroy\TransactionGroupDestroyService;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
use FireflyIII\Support\Facades\Steam;
/** /**
* Trait AccountServiceTrait * Trait AccountServiceTrait
@@ -65,7 +66,7 @@ trait AccountServiceTrait
return null; return null;
} }
return app('steam')->filterSpaces($iban); return Steam::filterSpaces($iban);
} }
/** /**
@@ -225,7 +226,7 @@ trait AccountServiceTrait
} }
// make amount positive, regardless: // make amount positive, regardless:
$amount = app('steam')->positive($amount); $amount = Steam::positive($amount);
// get or grab currency: // get or grab currency:
$currency = $this->accountRepository->getAccountCurrency($account); $currency = $this->accountRepository->getAccountCurrency($account);
@@ -371,12 +372,12 @@ trait AccountServiceTrait
} }
// if direction is "debit" (I owe this debt), amount is negative. // if direction is "debit" (I owe this debt), amount is negative.
// which means the liability will have a negative balance which the user must fill. // which means the liability will have a negative balance which the user must fill.
$openingBalance = app('steam')->negative($openingBalance); $openingBalance = Steam::negative($openingBalance);
// if direction is "credit" (I am owed this debt), amount is positive. // if direction is "credit" (I am owed this debt), amount is positive.
// which means the liability will have a positive balance which is drained when its paid back into any asset. // which means the liability will have a positive balance which is drained when its paid back into any asset.
if ('credit' === $direction) { if ('credit' === $direction) {
$openingBalance = app('steam')->positive($openingBalance); $openingBalance = Steam::positive($openingBalance);
} }
// create if not exists: // create if not exists:
@@ -398,11 +399,11 @@ trait AccountServiceTrait
$journal->transactionCurrency()->associate($currency); $journal->transactionCurrency()->associate($currency);
// account always gains money: // account always gains money:
$accountTransaction->amount = app('steam')->positive($openingBalance); $accountTransaction->amount = Steam::positive($openingBalance);
$accountTransaction->transaction_currency_id = $currency->id; $accountTransaction->transaction_currency_id = $currency->id;
// CL account always loses money: // CL account always loses money:
$clTransaction->amount = app('steam')->negative($openingBalance); $clTransaction->amount = Steam::negative($openingBalance);
$clTransaction->transaction_currency_id = $currency->id; $clTransaction->transaction_currency_id = $currency->id;
// save both // save both
$accountTransaction->save(); $accountTransaction->save();
@@ -448,7 +449,7 @@ trait AccountServiceTrait
} }
// amount must be positive for the transaction to work. // amount must be positive for the transaction to work.
$amount = app('steam')->positive($openingBalance); $amount = Steam::positive($openingBalance);
// get or grab currency: // get or grab currency:
$currency = $this->accountRepository->getAccountCurrency($account); $currency = $this->accountRepository->getAccountCurrency($account);
@@ -584,21 +585,21 @@ trait AccountServiceTrait
if (1 === bccomp('0', $openingBalance)) { if (1 === bccomp('0', $openingBalance)) {
Log::debug('Amount is negative.'); Log::debug('Amount is negative.');
// account transaction loses money: // account transaction loses money:
$accountTransaction->amount = app('steam')->negative($openingBalance); $accountTransaction->amount = Steam::negative($openingBalance);
$accountTransaction->transaction_currency_id = $currency->id; $accountTransaction->transaction_currency_id = $currency->id;
// OB account transaction gains money // OB account transaction gains money
$obTransaction->amount = app('steam')->positive($openingBalance); $obTransaction->amount = Steam::positive($openingBalance);
$obTransaction->transaction_currency_id = $currency->id; $obTransaction->transaction_currency_id = $currency->id;
} }
if (-1 === bccomp('0', $openingBalance)) { if (-1 === bccomp('0', $openingBalance)) {
Log::debug('Amount is positive.'); Log::debug('Amount is positive.');
// account gains money: // account gains money:
$accountTransaction->amount = app('steam')->positive($openingBalance); $accountTransaction->amount = Steam::positive($openingBalance);
$accountTransaction->transaction_currency_id = $currency->id; $accountTransaction->transaction_currency_id = $currency->id;
// OB account loses money: // OB account loses money:
$obTransaction->amount = app('steam')->negative($openingBalance); $obTransaction->amount = Steam::negative($openingBalance);
$obTransaction->transaction_currency_id = $currency->id; $obTransaction->transaction_currency_id = $currency->id;
} }
// save both // save both
@@ -646,7 +647,7 @@ trait AccountServiceTrait
} }
// make amount positive, regardless: // make amount positive, regardless:
$amount = app('steam')->positive($openingBalance); $amount = Steam::positive($openingBalance);
// get or grab currency: // get or grab currency:
$currency = $this->accountRepository->getAccountCurrency($account); $currency = $this->accountRepository->getAccountCurrency($account);

View File

@@ -34,6 +34,7 @@ use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class CreditRecalculateService * Class CreditRecalculateService
@@ -159,8 +160,8 @@ class CreditRecalculateService
$this->validateOpeningBalance($account, $openingBalance); $this->validateOpeningBalance($account, $openingBalance);
} }
$startOfDebt = $this->repository->getOpeningBalanceAmount($account, false) ?? '0'; $startOfDebt = $this->repository->getOpeningBalanceAmount($account, false) ?? '0';
$leftOfDebt = app('steam')->positive($startOfDebt); $leftOfDebt = Steam::positive($startOfDebt);
// Log::debug(sprintf('Start of debt is "%s", so initial left of debt is "%s"', app('steam')->bcround($startOfDebt, 2), app('steam')->bcround($leftOfDebt, 2))); // Log::debug(sprintf('Start of debt is "%s", so initial left of debt is "%s"', \FireflyIII\Support\Facades\Steam::bcround($startOfDebt, 2), \FireflyIII\Support\Facades\Steam::bcround($leftOfDebt, 2)));
/** @var AccountMetaFactory $factory */ /** @var AccountMetaFactory $factory */
$factory = app(AccountMetaFactory::class); $factory = app(AccountMetaFactory::class);
@@ -200,17 +201,17 @@ class CreditRecalculateService
$dest = $openingBalance->transactions()->where('amount', '>', 0)->first(); $dest = $openingBalance->transactions()->where('amount', '>', 0)->first();
if ($source->account_id !== $account->id) { if ($source->account_id !== $account->id) {
Log::info(sprintf('Liability #%d has a reversed opening balance. Will fix this now.', $account->id)); Log::info(sprintf('Liability #%d has a reversed opening balance. Will fix this now.', $account->id));
Log::debug(sprintf('Source amount "%s" is now "%s"', $source->amount, app('steam')->positive($source->amount))); Log::debug(sprintf('Source amount "%s" is now "%s"', $source->amount, Steam::positive($source->amount)));
Log::debug(sprintf('Destination amount "%s" is now "%s"', $dest->amount, app('steam')->negative($dest->amount))); Log::debug(sprintf('Destination amount "%s" is now "%s"', $dest->amount, Steam::negative($dest->amount)));
$source->amount = app('steam')->positive($source->amount); $source->amount = Steam::positive($source->amount);
$dest->amount = app('steam')->negative($source->amount); $dest->amount = Steam::negative($source->amount);
if (null !== $source->foreign_amount && '' !== $source->foreign_amount) { if (null !== $source->foreign_amount && '' !== $source->foreign_amount) {
$source->foreign_amount = app('steam')->positive($source->foreign_amount); $source->foreign_amount = Steam::positive($source->foreign_amount);
Log::debug(sprintf('Source foreign amount "%s" is now "%s"', $source->foreign_amount, app('steam')->positive($source->foreign_amount))); Log::debug(sprintf('Source foreign amount "%s" is now "%s"', $source->foreign_amount, Steam::positive($source->foreign_amount)));
} }
if (null !== $dest->foreign_amount && '' !== $dest->foreign_amount) { if (null !== $dest->foreign_amount && '' !== $dest->foreign_amount) {
$dest->foreign_amount = app('steam')->negative($dest->foreign_amount); $dest->foreign_amount = Steam::negative($dest->foreign_amount);
Log::debug(sprintf('Destination amount "%s" is now "%s"', $dest->foreign_amount, app('steam')->negative($dest->foreign_amount))); Log::debug(sprintf('Destination amount "%s" is now "%s"', $dest->foreign_amount, Steam::negative($dest->foreign_amount)));
} }
$source->save(); $source->save();
$dest->save(); $dest->save();
@@ -241,7 +242,7 @@ class CreditRecalculateService
$foreignCurrency = $transaction->foreignCurrency; $foreignCurrency = $transaction->foreignCurrency;
$accountCurrency = $this->repository->getAccountCurrency($account); $accountCurrency = $this->repository->getAccountCurrency($account);
$type = $journal->transactionType->type; $type = $journal->transactionType->type;
// Log::debug(sprintf('Left of debt is: %s', app('steam')->bcround($leftOfDebt, 2))); // Log::debug(sprintf('Left of debt is: %s', \FireflyIII\Support\Facades\Steam::bcround($leftOfDebt, 2)));
if ('' === $direction) { if ('' === $direction) {
// Log::warning('Direction is empty, so do nothing.'); // Log::warning('Direction is empty, so do nothing.');
@@ -262,81 +263,81 @@ class CreditRecalculateService
$isCredit = 'credit' === $direction; $isCredit = 'credit' === $direction;
if ($isSameAccount && $isCredit && $this->isWithdrawalIn($usedAmount, $type)) { // case 1 if ($isSameAccount && $isCredit && $this->isWithdrawalIn($usedAmount, $type)) { // case 1
$usedAmount = app('steam')->positive($usedAmount); $usedAmount = Steam::positive($usedAmount);
return bcadd($leftOfDebt, (string) $usedAmount); return bcadd($leftOfDebt, (string) $usedAmount);
// Log::debug(sprintf('Case 1 (withdrawal into credit liability): %s + %s = %s', app('steam')->bcround($leftOfDebt, 2), app('steam')->bcround($usedAmount, 2), app('steam')->bcround($result, 2))); // Log::debug(sprintf('Case 1 (withdrawal into credit liability): %s + %s = %s', \FireflyIII\Support\Facades\Steam::bcround($leftOfDebt, 2), \FireflyIII\Support\Facades\Steam::bcround($usedAmount, 2), \FireflyIII\Support\Facades\Steam::bcround($result, 2)));
} }
if ($isSameAccount && $isCredit && $this->isWithdrawalOut($usedAmount, $type)) { // case 2 if ($isSameAccount && $isCredit && $this->isWithdrawalOut($usedAmount, $type)) { // case 2
$usedAmount = app('steam')->positive($usedAmount); $usedAmount = Steam::positive($usedAmount);
return bcsub($leftOfDebt, (string) $usedAmount); return bcsub($leftOfDebt, (string) $usedAmount);
// Log::debug(sprintf('Case 2 (withdrawal away from liability): %s - %s = %s', app('steam')->bcround($leftOfDebt, 2), app('steam')->bcround($usedAmount, 2), app('steam')->bcround($result, 2))); // Log::debug(sprintf('Case 2 (withdrawal away from liability): %s - %s = %s', \FireflyIII\Support\Facades\Steam::bcround($leftOfDebt, 2), \FireflyIII\Support\Facades\Steam::bcround($usedAmount, 2), \FireflyIII\Support\Facades\Steam::bcround($result, 2)));
} }
if ($isSameAccount && $isCredit && $this->isDepositOut($usedAmount, $type)) { // case 3 if ($isSameAccount && $isCredit && $this->isDepositOut($usedAmount, $type)) { // case 3
$usedAmount = app('steam')->positive($usedAmount); $usedAmount = Steam::positive($usedAmount);
return bcsub($leftOfDebt, (string) $usedAmount); return bcsub($leftOfDebt, (string) $usedAmount);
// Log::debug(sprintf('Case 3 (deposit away from liability): %s - %s = %s', app('steam')->bcround($leftOfDebt, 2), app('steam')->bcround($usedAmount, 2), app('steam')->bcround($result, 2))); // Log::debug(sprintf('Case 3 (deposit away from liability): %s - %s = %s', \FireflyIII\Support\Facades\Steam::bcround($leftOfDebt, 2), \FireflyIII\Support\Facades\Steam::bcround($usedAmount, 2), \FireflyIII\Support\Facades\Steam::bcround($result, 2)));
} }
if ($isSameAccount && $isCredit && $this->isDepositIn($usedAmount, $type)) { // case 4 if ($isSameAccount && $isCredit && $this->isDepositIn($usedAmount, $type)) { // case 4
$usedAmount = app('steam')->positive($usedAmount); $usedAmount = Steam::positive($usedAmount);
return bcadd($leftOfDebt, (string) $usedAmount); return bcadd($leftOfDebt, (string) $usedAmount);
// Log::debug(sprintf('Case 4 (deposit into credit liability): %s + %s = %s', app('steam')->bcround($leftOfDebt, 2), app('steam')->bcround($usedAmount, 2), app('steam')->bcround($result, 2))); // Log::debug(sprintf('Case 4 (deposit into credit liability): %s + %s = %s', \FireflyIII\Support\Facades\Steam::bcround($leftOfDebt, 2), \FireflyIII\Support\Facades\Steam::bcround($usedAmount, 2), \FireflyIII\Support\Facades\Steam::bcround($result, 2)));
} }
if ($isSameAccount && $isCredit && $this->isTransferIn($usedAmount, $type)) { // case 5 if ($isSameAccount && $isCredit && $this->isTransferIn($usedAmount, $type)) { // case 5
$usedAmount = app('steam')->positive($usedAmount); $usedAmount = Steam::positive($usedAmount);
return bcadd($leftOfDebt, (string) $usedAmount); return bcadd($leftOfDebt, (string) $usedAmount);
// Log::debug(sprintf('Case 5 (transfer into credit liability): %s + %s = %s', app('steam')->bcround($leftOfDebt, 2), app('steam')->bcround($usedAmount, 2), app('steam')->bcround($result, 2))); // Log::debug(sprintf('Case 5 (transfer into credit liability): %s + %s = %s', \FireflyIII\Support\Facades\Steam::bcround($leftOfDebt, 2), \FireflyIII\Support\Facades\Steam::bcround($usedAmount, 2), \FireflyIII\Support\Facades\Steam::bcround($result, 2)));
} }
if ($isSameAccount && $isDebit && $this->isWithdrawalIn($usedAmount, $type)) { // case 6 if ($isSameAccount && $isDebit && $this->isWithdrawalIn($usedAmount, $type)) { // case 6
$usedAmount = app('steam')->positive($usedAmount); $usedAmount = Steam::positive($usedAmount);
return bcsub($leftOfDebt, (string) $usedAmount); return bcsub($leftOfDebt, (string) $usedAmount);
// Log::debug(sprintf('Case 6 (withdrawal into debit liability): %s - %s = %s', app('steam')->bcround($leftOfDebt, 2), app('steam')->bcround($usedAmount, 2), app('steam')->bcround($result, 2))); // Log::debug(sprintf('Case 6 (withdrawal into debit liability): %s - %s = %s', \FireflyIII\Support\Facades\Steam::bcround($leftOfDebt, 2), \FireflyIII\Support\Facades\Steam::bcround($usedAmount, 2), \FireflyIII\Support\Facades\Steam::bcround($result, 2)));
} }
if ($isSameAccount && $isDebit && $this->isDepositOut($usedAmount, $type)) { // case 7 if ($isSameAccount && $isDebit && $this->isDepositOut($usedAmount, $type)) { // case 7
$usedAmount = app('steam')->positive($usedAmount); $usedAmount = Steam::positive($usedAmount);
return bcadd($leftOfDebt, (string) $usedAmount); return bcadd($leftOfDebt, (string) $usedAmount);
// Log::debug(sprintf('Case 7 (deposit away from liability): %s + %s = %s', app('steam')->bcround($leftOfDebt, 2), app('steam')->bcround($usedAmount, 2), app('steam')->bcround($result, 2))); // Log::debug(sprintf('Case 7 (deposit away from liability): %s + %s = %s', \FireflyIII\Support\Facades\Steam::bcround($leftOfDebt, 2), \FireflyIII\Support\Facades\Steam::bcround($usedAmount, 2), \FireflyIII\Support\Facades\Steam::bcround($result, 2)));
} }
if ($isSameAccount && $isDebit && $this->isWithdrawalOut($usedAmount, $type)) { // case 8 if ($isSameAccount && $isDebit && $this->isWithdrawalOut($usedAmount, $type)) { // case 8
$usedAmount = app('steam')->positive($usedAmount); $usedAmount = Steam::positive($usedAmount);
return bcadd($leftOfDebt, (string) $usedAmount); return bcadd($leftOfDebt, (string) $usedAmount);
// Log::debug(sprintf('Case 8 (withdrawal away from liability): %s + %s = %s', app('steam')->bcround($leftOfDebt, 2), app('steam')->bcround($usedAmount, 2), app('steam')->bcround($result, 2))); // Log::debug(sprintf('Case 8 (withdrawal away from liability): %s + %s = %s', \FireflyIII\Support\Facades\Steam::bcround($leftOfDebt, 2), \FireflyIII\Support\Facades\Steam::bcround($usedAmount, 2), \FireflyIII\Support\Facades\Steam::bcround($result, 2)));
} }
if ($isSameAccount && $isDebit && $this->isTransferIn($usedAmount, $type)) { // case 9 if ($isSameAccount && $isDebit && $this->isTransferIn($usedAmount, $type)) { // case 9
$usedAmount = app('steam')->positive($usedAmount); $usedAmount = Steam::positive($usedAmount);
return bcsub($leftOfDebt, (string) $usedAmount); return bcsub($leftOfDebt, (string) $usedAmount);
// 2024-10-05, #9225 this used to say you would owe more, but a transfer INTO a debit from wherever means you owe LESS. // 2024-10-05, #9225 this used to say you would owe more, but a transfer INTO a debit from wherever means you owe LESS.
// Log::debug(sprintf('Case 9 (transfer into debit liability, means you owe LESS): %s - %s = %s', app('steam')->bcround($leftOfDebt, 2), app('steam')->bcround($usedAmount, 2), app('steam')->bcround($result, 2))); // Log::debug(sprintf('Case 9 (transfer into debit liability, means you owe LESS): %s - %s = %s', \FireflyIII\Support\Facades\Steam::bcround($leftOfDebt, 2), \FireflyIII\Support\Facades\Steam::bcround($usedAmount, 2), \FireflyIII\Support\Facades\Steam::bcround($result, 2)));
} }
if ($isSameAccount && $isDebit && $this->isTransferOut($usedAmount, $type)) { // case 10 if ($isSameAccount && $isDebit && $this->isTransferOut($usedAmount, $type)) { // case 10
$usedAmount = app('steam')->positive($usedAmount); $usedAmount = Steam::positive($usedAmount);
return bcadd($leftOfDebt, (string) $usedAmount); return bcadd($leftOfDebt, (string) $usedAmount);
// 2024-10-05, #9225 this used to say you would owe less, but a transfer OUT OF a debit from wherever means you owe MORE. // 2024-10-05, #9225 this used to say you would owe less, but a transfer OUT OF a debit from wherever means you owe MORE.
// Log::debug(sprintf('Case 10 (transfer out of debit liability, means you owe MORE): %s + %s = %s', app('steam')->bcround($leftOfDebt, 2), app('steam')->bcround($usedAmount, 2), app('steam')->bcround($result, 2))); // Log::debug(sprintf('Case 10 (transfer out of debit liability, means you owe MORE): %s + %s = %s', \FireflyIII\Support\Facades\Steam::bcround($leftOfDebt, 2), \FireflyIII\Support\Facades\Steam::bcround($usedAmount, 2), \FireflyIII\Support\Facades\Steam::bcround($result, 2)));
} }
// in any other case, remove amount from left of debt. // in any other case, remove amount from left of debt.
if (in_array($type, [TransactionTypeEnum::WITHDRAWAL->value, TransactionTypeEnum::DEPOSIT->value, TransactionTypeEnum::TRANSFER->value], true)) { if (in_array($type, [TransactionTypeEnum::WITHDRAWAL->value, TransactionTypeEnum::DEPOSIT->value, TransactionTypeEnum::TRANSFER->value], true)) {
$usedAmount = app('steam')->negative($usedAmount); $usedAmount = Steam::negative($usedAmount);
return bcadd($leftOfDebt, (string) $usedAmount); return bcadd($leftOfDebt, (string) $usedAmount);
// Log::debug(sprintf('Case X (all other cases): %s + %s = %s', app('steam')->bcround($leftOfDebt, 2), app('steam')->bcround($usedAmount, 2), app('steam')->bcround($result, 2))); // Log::debug(sprintf('Case X (all other cases): %s + %s = %s', \FireflyIII\Support\Facades\Steam::bcround($leftOfDebt, 2), \FireflyIII\Support\Facades\Steam::bcround($usedAmount, 2), \FireflyIII\Support\Facades\Steam::bcround($result, 2)));
} }
Log::warning(sprintf('[-1] Catch-all, should not happen. Left of debt = %s', app('steam')->bcround($leftOfDebt, 2))); Log::warning(sprintf('[-1] Catch-all, should not happen. Left of debt = %s', Steam::bcround($leftOfDebt, 2)));
return $leftOfDebt; return $leftOfDebt;
} }
@@ -344,10 +345,10 @@ class CreditRecalculateService
private function getAmountToUse(Transaction $transaction, TransactionCurrency $accountCurrency, ?TransactionCurrency $foreignCurrency): string private function getAmountToUse(Transaction $transaction, TransactionCurrency $accountCurrency, ?TransactionCurrency $foreignCurrency): string
{ {
$usedAmount = $transaction->amount; $usedAmount = $transaction->amount;
// Log::debug(sprintf('Amount of transaction is %s', app('steam')->bcround($usedAmount, 2))); // Log::debug(sprintf('Amount of transaction is %s', \FireflyIII\Support\Facades\Steam::bcround($usedAmount, 2)));
if ($foreignCurrency instanceof TransactionCurrency && $foreignCurrency->id === $accountCurrency->id) { if ($foreignCurrency instanceof TransactionCurrency && $foreignCurrency->id === $accountCurrency->id) {
$usedAmount = $transaction->foreign_amount; $usedAmount = $transaction->foreign_amount;
// Log::debug(sprintf('Overruled by foreign amount. Amount of transaction is now %s', app('steam')->bcround($usedAmount, 2))); // Log::debug(sprintf('Overruled by foreign amount. Amount of transaction is now %s', \FireflyIII\Support\Facades\Steam::bcround($usedAmount, 2)));
} }
return $usedAmount; return $usedAmount;

View File

@@ -35,6 +35,7 @@ use FireflyIII\Models\Location;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Services\Internal\Support\AccountServiceTrait; use FireflyIII\Services\Internal\Support\AccountServiceTrait;
use FireflyIII\User; use FireflyIII\User;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class AccountUpdateService * Class AccountUpdateService
@@ -123,7 +124,7 @@ class AccountUpdateService
$account->active = $data['active']; $account->active = $data['active'];
} }
if (array_key_exists('iban', $data)) { if (array_key_exists('iban', $data)) {
$account->iban = app('steam')->filterSpaces((string) $data['iban']); $account->iban = Steam::filterSpaces((string) $data['iban']);
} }
// set liability, but account must already be a liability. // set liability, but account must already be a liability.
@@ -269,7 +270,7 @@ class AccountUpdateService
// if liability, make sure the amount is positive for a credit, and negative for a debit. // if liability, make sure the amount is positive for a credit, and negative for a debit.
if ($this->isLiability($account)) { if ($this->isLiability($account)) {
$openingBalance = 'credit' === $data['liability_direction'] ? app('steam')->positive($openingBalance) : app('steam')->negative( $openingBalance = 'credit' === $data['liability_direction'] ? Steam::positive($openingBalance) : Steam::negative(
$openingBalance $openingBalance
); );
} }

View File

@@ -78,9 +78,7 @@ class GroupUpdateService
if (1 === count($transactions) && 1 === $transactionGroup->transactionJournals()->count()) { if (1 === count($transactions) && 1 === $transactionGroup->transactionJournals()->count()) {
/** @var TransactionJournal $first */ /** @var TransactionJournal $first */
$first = $transactionGroup->transactionJournals()->first(); $first = $transactionGroup->transactionJournals()->first();
Log::debug( Log::debug(sprintf('Will now update journal #%d (only journal in group #%d)', $first->id, $transactionGroup->id));
sprintf('Will now update journal #%d (only journal in group #%d)', $first->id, $transactionGroup->id)
);
$this->updateTransactionJournal($transactionGroup, $first, reset($transactions)); $this->updateTransactionJournal($transactionGroup, $first, reset($transactions));
$transactionGroup->touch(); $transactionGroup->touch();
$transactionGroup->refresh(); $transactionGroup->refresh();

View File

@@ -24,7 +24,6 @@ declare(strict_types=1);
namespace FireflyIII\Services\Internal\Update; namespace FireflyIII\Services\Internal\Update;
use FireflyIII\Support\Facades\Preferences;
use Carbon\Carbon; use Carbon\Carbon;
use Carbon\Exceptions\InvalidDateException; use Carbon\Exceptions\InvalidDateException;
use Carbon\Exceptions\InvalidFormatException; use Carbon\Exceptions\InvalidFormatException;
@@ -47,6 +46,8 @@ use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface; use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
use FireflyIII\Services\Internal\Support\JournalServiceTrait; use FireflyIII\Services\Internal\Support\JournalServiceTrait;
use FireflyIII\Support\Facades\FireflyConfig; use FireflyIII\Support\Facades\FireflyConfig;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\Facades\Steam;
use FireflyIII\Support\NullArrayObject; use FireflyIII\Support\NullArrayObject;
use FireflyIII\Validation\AccountValidator; use FireflyIII\Validation\AccountValidator;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
@@ -60,34 +61,36 @@ class JournalUpdateService
{ {
use JournalServiceTrait; use JournalServiceTrait;
private BillRepositoryInterface $billRepository; private BillRepositoryInterface $billRepository;
private CurrencyRepositoryInterface $currencyRepository; private CurrencyRepositoryInterface $currencyRepository;
private TransactionGroupRepositoryInterface $transactionGroupRepository; private TransactionGroupRepositoryInterface $transactionGroupRepository;
private array $data; private array $data;
private ?Account $destinationAccount = null; private ?Account $destinationAccount = null;
private ?Transaction $destinationTransaction = null; private ?Transaction $destinationTransaction = null;
private array $metaDate = ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', private array $metaDate
'invoice_date', ]; = ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date',
private array $metaString = [ 'invoice_date', ];
'sepa_cc', private array $metaString
'sepa_ct_op', = [
'sepa_ct_id', 'sepa_cc',
'sepa_db', 'sepa_ct_op',
'sepa_country', 'sepa_ct_id',
'sepa_ep', 'sepa_db',
'sepa_ci', 'sepa_country',
'sepa_batch_id', 'sepa_ep',
'recurrence_id', 'sepa_ci',
'internal_reference', 'sepa_batch_id',
'bunq_payment_id', 'recurrence_id',
'external_id', 'internal_reference',
'external_url', 'bunq_payment_id',
]; 'external_id',
private ?Account $sourceAccount = null; 'external_url',
private ?Transaction $sourceTransaction = null; ];
private ?TransactionGroup $transactionGroup = null; private ?Account $sourceAccount = null;
private ?TransactionJournal $transactionJournal = null; private ?Transaction $sourceTransaction = null;
private string $startCompareHash = ''; private ?TransactionGroup $transactionGroup = null;
private ?TransactionJournal $transactionJournal = null;
private string $startCompareHash = '';
/** /**
* JournalUpdateService constructor. * JournalUpdateService constructor.
@@ -492,15 +495,7 @@ class JournalUpdateService
Log::debug(sprintf('Create date value from string "%s".', $value)); Log::debug(sprintf('Create date value from string "%s".', $value));
$this->transactionJournal->date_tz = $value->format('e'); $this->transactionJournal->date_tz = $value->format('e');
} }
event( event(new TriggeredAuditLog($this->transactionJournal->user, $this->transactionJournal, sprintf('update_%s', $fieldName), $this->transactionJournal->{$fieldName}, $value));
new TriggeredAuditLog(
$this->transactionJournal->user,
$this->transactionJournal,
sprintf('update_%s', $fieldName),
$this->transactionJournal->{$fieldName}, // @phpstan-ignore-line
$value
)
);
$this->transactionJournal->{$fieldName} = $value; // @phpstan-ignore-line $this->transactionJournal->{$fieldName} = $value; // @phpstan-ignore-line
Log::debug(sprintf('Updated %s', $fieldName)); Log::debug(sprintf('Updated %s', $fieldName));
@@ -667,17 +662,44 @@ class JournalUpdateService
return; return;
} }
$origSourceTransaction = $this->getSourceTransaction(); $origSourceTransaction = $this->getSourceTransaction();
$origSourceTransaction->amount = app('steam')->negative($amount); $origSourceTransaction->amount = Steam::negative($amount);
$origSourceTransaction->balance_dirty = true; $origSourceTransaction->balance_dirty = true;
$origSourceTransaction->save(); $origSourceTransaction->save();
$destTransaction = $this->getDestinationTransaction(); $destTransaction = $this->getDestinationTransaction();
$destTransaction->amount = app('steam')->positive($amount); $originalAmount = $destTransaction->amount;
$destTransaction->amount = Steam::positive($amount);
$destTransaction->balance_dirty = true; $destTransaction->balance_dirty = true;
$destTransaction->save(); $destTransaction->save();
// refresh transactions. // refresh transactions.
$this->sourceTransaction->refresh(); $this->sourceTransaction->refresh();
$this->destinationTransaction->refresh(); $this->destinationTransaction->refresh();
Log::debug(sprintf('Updated amount to "%s"', $amount)); Log::debug(sprintf('Updated amount to "%s"', $amount));
$group = $this->transactionGroup;
if (null === $group) {
$group = $this->transactionJournal?->transactionGroup;
}
if (null === $group) {
return;
}
// should not return in NULL but seems to do.
event(new TriggeredAuditLog(
$group->user,
$group,
'update_amount',
[
'currency_symbol' => $destTransaction->transactionCurrency->symbol,
'decimal_places' => $destTransaction->transactionCurrency->decimal_places,
'amount' => $originalAmount,
],
[
'currency_symbol' => $destTransaction->transactionCurrency->symbol,
'decimal_places' => $destTransaction->transactionCurrency->decimal_places,
'amount' => $value,
]
));
} }
private function updateForeignAmount(): void private function updateForeignAmount(): void
@@ -697,7 +719,7 @@ class JournalUpdateService
$newForeignId = $this->data['foreign_currency_id'] ?? null; $newForeignId = $this->data['foreign_currency_id'] ?? null;
$newForeignCode = $this->data['foreign_currency_code'] ?? null; $newForeignCode = $this->data['foreign_currency_code'] ?? null;
$foreignCurrency = $this->currencyRepository->findCurrencyNull($newForeignId, $newForeignCode) $foreignCurrency = $this->currencyRepository->findCurrencyNull($newForeignId, $newForeignCode)
?? $foreignCurrency; ?? $foreignCurrency;
// not the same as normal currency // not the same as normal currency
if (null !== $foreignCurrency && $foreignCurrency->id === $this->transactionJournal->transaction_currency_id) { if (null !== $foreignCurrency && $foreignCurrency->id === $this->transactionJournal->transaction_currency_id) {
@@ -709,7 +731,7 @@ class JournalUpdateService
// add foreign currency info to source and destination if possible. // add foreign currency info to source and destination if possible.
if (null !== $foreignCurrency && null !== $foreignAmount) { if (null !== $foreignCurrency && null !== $foreignAmount) {
$source->foreign_currency_id = $foreignCurrency->id; $source->foreign_currency_id = $foreignCurrency->id;
$source->foreign_amount = app('steam')->negative($foreignAmount); $source->foreign_amount = Steam::negative($foreignAmount);
$source->save(); $source->save();
// if the transaction is a TRANSFER, and the foreign amount and currency are set (like they seem to be) // if the transaction is a TRANSFER, and the foreign amount and currency are set (like they seem to be)
@@ -722,13 +744,13 @@ class JournalUpdateService
if ($isTransfer || $isBetween) { if ($isTransfer || $isBetween) {
Log::debug('Switch amounts, store in amount and not foreign_amount'); Log::debug('Switch amounts, store in amount and not foreign_amount');
$dest->transaction_currency_id = $foreignCurrency->id; $dest->transaction_currency_id = $foreignCurrency->id;
$dest->amount = app('steam')->positive($foreignAmount); $dest->amount = Steam::positive($foreignAmount);
$dest->foreign_amount = app('steam')->positive($source->amount); $dest->foreign_amount = Steam::positive($source->amount);
$dest->foreign_currency_id = $source->transaction_currency_id; $dest->foreign_currency_id = $source->transaction_currency_id;
} }
if (!$isTransfer && !$isBetween) { if (!$isTransfer && !$isBetween) {
$dest->foreign_currency_id = $foreignCurrency->id; $dest->foreign_currency_id = $foreignCurrency->id;
$dest->foreign_amount = app('steam')->positive($foreignAmount); $dest->foreign_amount = Steam::positive($foreignAmount);
} }
$dest->save(); $dest->save();

View File

@@ -34,6 +34,8 @@ class Balance
{ {
/** /**
* Returns the accounts balances as an array, on the account ID. * Returns the accounts balances as an array, on the account ID.
*
* @deprecated
*/ */
public function getAccountBalances(Collection $accounts, Carbon $date): array public function getAccountBalances(Collection $accounts, Carbon $date): array
{ {

View File

@@ -33,6 +33,7 @@ use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class FrontpageChartGenerator * Class FrontpageChartGenerator
@@ -102,7 +103,7 @@ class FrontpageChartGenerator
$this->blRepository->setUser($user); $this->blRepository->setUser($user);
$this->opsRepository->setUser($user); $this->opsRepository->setUser($user);
$locale = app('steam')->getLocale(); $locale = Steam::getLocale();
$this->monthAndDayFormat = (string)trans('config.month_and_day_js', [], $locale); $this->monthAndDayFormat = (string)trans('config.month_and_day_js', [], $locale);
} }

View File

@@ -31,6 +31,7 @@ use FireflyIII\Models\Category;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Category\OperationsRepositoryInterface; use FireflyIII\Repositories\Category\OperationsRepositoryInterface;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class WholePeriodChartGenerator * Class WholePeriodChartGenerator
@@ -102,8 +103,8 @@ class WholePeriodChartGenerator
$earnedInfoKey = sprintf('earned-in-%s', $code); $earnedInfoKey = sprintf('earned-in-%s', $code);
$spentAmount = $spent[$key][$currencyId]['sum'] ?? '0'; $spentAmount = $spent[$key][$currencyId]['sum'] ?? '0';
$earnedAmount = $earned[$key][$currencyId]['sum'] ?? '0'; $earnedAmount = $earned[$key][$currencyId]['sum'] ?? '0';
$chartData[$spentInfoKey]['entries'][$label] = app('steam')->bcround($spentAmount, $currency['currency_decimal_places']); $chartData[$spentInfoKey]['entries'][$label] = Steam::bcround($spentAmount, $currency['currency_decimal_places']);
$chartData[$earnedInfoKey]['entries'][$label] = app('steam')->bcround($earnedAmount, $currency['currency_decimal_places']); $chartData[$earnedInfoKey]['entries'][$label] = Steam::bcround($earnedAmount, $currency['currency_decimal_places']);
} }
$current = Navigation::addPeriod($current, $step); $current = Navigation::addPeriod($current, $step);
} }

View File

@@ -30,6 +30,7 @@ use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Throwable; use Throwable;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class CurrencyForm * Class CurrencyForm
@@ -150,7 +151,7 @@ class CurrencyForm
// make sure value is formatted nicely: // make sure value is formatted nicely:
if (null !== $value && '' !== $value) { if (null !== $value && '' !== $value) {
$value = app('steam')->bcround($value, $primaryCurrency->decimal_places); $value = Steam::bcround($value, $primaryCurrency->decimal_places);
} }
try { try {
@@ -202,7 +203,7 @@ class CurrencyForm
// make sure value is formatted nicely: // make sure value is formatted nicely:
if (null !== $value && '' !== $value) { if (null !== $value && '' !== $value) {
$value = app('steam')->bcround($value, $primaryCurrency->decimal_places); $value = Steam::bcround($value, $primaryCurrency->decimal_places);
} }
try { try {

View File

@@ -59,7 +59,7 @@ trait ChartGeneration
return $cache->get(); return $cache->get();
} }
Log::debug('Regenerate chart.account.account-balance-chart from scratch.'); Log::debug('Regenerate chart.account.account-balance-chart from scratch.');
$locale = app('steam')->getLocale(); $locale = Steam::getLocale();
/** @var GeneratorInterface $generator */ /** @var GeneratorInterface $generator */
$generator = app(GeneratorInterface::class); $generator = app(GeneratorInterface::class);

View File

@@ -33,6 +33,7 @@ use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use Illuminate\Http\RedirectResponse; use Illuminate\Http\RedirectResponse;
use Illuminate\Routing\Redirector; use Illuminate\Routing\Redirector;
use FireflyIII\Support\Facades\Steam;
/** /**
* Trait UserNavigation * Trait UserNavigation
@@ -53,7 +54,7 @@ trait UserNavigation
$url = (string)session($identifier); $url = (string)session($identifier);
Log::debug(sprintf('The URL is %s', $url)); Log::debug(sprintf('The URL is %s', $url));
return app('steam')->getSafeUrl($url, route('index')); return Steam::getSafeUrl($url, route('index'));
} }
/** /**
@@ -137,7 +138,7 @@ trait UserNavigation
final protected function rememberPreviousUrl(string $identifier): ?string final protected function rememberPreviousUrl(string $identifier): ?string
{ {
$return = app('steam')->getSafePreviousUrl(); $return = Steam::getSafePreviousUrl();
session()->put($identifier, $return); session()->put($identifier, $return);
Log::debug(sprintf('rememberPreviousUrl: %s: "%s"', $identifier, $return)); Log::debug(sprintf('rememberPreviousUrl: %s: "%s"', $identifier, $return));

View File

@@ -161,7 +161,7 @@ class AccountBalanceCalculator
// then update all transactions. // then update all transactions.
// save all collected balances in their respective account objects. // save all collected balances in their respective account objects.
$this->storeAccountBalances($balances); // $this->storeAccountBalances($balances);
} }
private function storeAccountBalances(array $balances): void private function storeAccountBalances(array $balances): void

View File

@@ -32,6 +32,7 @@ use FireflyIII\Support\Calendar\Calculator;
use FireflyIII\Support\Calendar\Periodicity; use FireflyIII\Support\Calendar\Periodicity;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Throwable; use Throwable;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class Navigation. * Class Navigation.
@@ -151,13 +152,7 @@ class Navigation
public function diffInPeriods(string $period, int $skip, Carbon $beginning, Carbon $end): int public function diffInPeriods(string $period, int $skip, Carbon $beginning, Carbon $end): int
{ {
Log::debug(sprintf( Log::debug(sprintf('diffInPeriods: %s (skip: %d), between %s and %s.', $period, $skip, $beginning->format('Y-m-d'), $end->format('Y-m-d')));
'diffInPeriods: %s (skip: %d), between %s and %s.',
$period,
$skip,
$beginning->format('Y-m-d'),
$end->format('Y-m-d')
));
$map = [ $map = [
'daily' => 'diffInDays', 'daily' => 'diffInDays',
'weekly' => 'diffInWeeks', 'weekly' => 'diffInWeeks',
@@ -211,9 +206,14 @@ class Navigation
// Log::debug(sprintf('Now in endOfPeriod("%s", "%s").', $currentEnd->toIso8601String(), $repeatFreq)); // 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. // fall back to a monthly schedule if the requested period is MTD.
Log::debug('endOfPeriod() requests "MTD", set it to "1M" instead.'); Log::debug('endOfPeriod() requests "MTD" + future, set it to "1M" instead.');
$repeatFreq = '1M'; $repeatFreq = '1M';
} }
if ('YTD' === $repeatFreq && $end->isFuture()) {
// fall back to a yearly schedule if the requested period is YTD.
Log::debug('endOfPeriod() requests "YTD" + future, set it to "1Y" instead.');
$repeatFreq = '1Y';
}
$functionMap = [ $functionMap = [
'1D' => 'endOfDay', '1D' => 'endOfDay',
@@ -405,7 +405,7 @@ class Navigation
*/ */
public function listOfPeriods(Carbon $start, Carbon $end): array public function listOfPeriods(Carbon $start, Carbon $end): array
{ {
$locale = app('steam')->getLocale(); $locale = Steam::getLocale();
// define period to increment // define period to increment
$increment = 'addDay'; $increment = 'addDay';
$format = $this->preferredCarbonFormat($start, $end); $format = $this->preferredCarbonFormat($start, $end);
@@ -537,7 +537,7 @@ class Navigation
*/ */
public function preferredCarbonLocalizedFormat(Carbon $start, Carbon $end): string public function preferredCarbonLocalizedFormat(Carbon $start, Carbon $end): string
{ {
$locale = app('steam')->getLocale(); $locale = Steam::getLocale();
$diff = $start->diffInMonths($end, true); $diff = $start->diffInMonths($end, true);
if ($diff >= 1.001 && $diff < 12.001) { if ($diff >= 1.001 && $diff < 12.001) {
return (string)trans('config.month_js', [], $locale); return (string)trans('config.month_js', [], $locale);

View File

@@ -38,6 +38,7 @@ use Psr\Container\NotFoundExceptionInterface;
use Spatie\Period\Boundaries; use Spatie\Period\Boundaries;
use Spatie\Period\Period; use Spatie\Period\Period;
use Spatie\Period\Precision; use Spatie\Period\Precision;
use FireflyIII\Support\Facades\Steam;
trait RecalculatesAvailableBudgetsTrait trait RecalculatesAvailableBudgetsTrait
{ {
@@ -103,7 +104,7 @@ trait RecalculatesAvailableBudgetsTrait
return; return;
} }
Log::debug(sprintf('Concluded new amount for this AB must be %s', $newAmount)); Log::debug(sprintf('Concluded new amount for this AB must be %s', $newAmount));
$availableBudget->amount = app('steam')->bcround($newAmount, $availableBudget->transactionCurrency->decimal_places); $availableBudget->amount = Steam::bcround($newAmount, $availableBudget->transactionCurrency->decimal_places);
$availableBudget->save(); $availableBudget->save();
} }

View File

@@ -139,7 +139,7 @@ class TransactionSummarizer
} }
} }
// $array[$currencyId]['sum'] = bcadd($array[$currencyId]['sum'], app('steam')->{$method}($amount)); // $array[$currencyId]['sum'] = bcadd($array[$currencyId]['sum'], \FireflyIII\Support\Facades\Steam::{$method}($amount));
// Log::debug(sprintf('Journal #%d adds amount %s %s', $journal['transaction_journal_id'], $currencyCode, $amount)); // Log::debug(sprintf('Journal #%d adds amount %s %s', $journal['transaction_journal_id'], $currencyCode, $amount));
} }
Log::debug('End of sumExpenses.', $array); Log::debug('End of sumExpenses.', $array);

View File

@@ -52,6 +52,7 @@ use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use LogicException; use LogicException;
use TypeError; use TypeError;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class OperatorQuerySearch * Class OperatorQuerySearch
@@ -2287,7 +2288,7 @@ class OperatorQuerySearch implements SearchInterface
// strip comma's, make dots. // strip comma's, make dots.
Log::debug(sprintf('Original value "%s"', $value)); Log::debug(sprintf('Original value "%s"', $value));
$value = str_replace(',', '.', $value); $value = str_replace(',', '.', $value);
$amount = app('steam')->positive($value); $amount = Steam::positive($value);
Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount)); Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount));
$this->collector->amountIs($amount); $this->collector->amountIs($amount);
@@ -2297,7 +2298,7 @@ class OperatorQuerySearch implements SearchInterface
// strip comma's, make dots. // strip comma's, make dots.
Log::debug(sprintf('Original value "%s"', $value)); Log::debug(sprintf('Original value "%s"', $value));
$value = str_replace(',', '.', $value); $value = str_replace(',', '.', $value);
$amount = app('steam')->positive($value); $amount = Steam::positive($value);
Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount)); Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount));
$this->collector->amountIsNot($amount); $this->collector->amountIsNot($amount);
@@ -2307,7 +2308,7 @@ class OperatorQuerySearch implements SearchInterface
// strip comma's, make dots. // strip comma's, make dots.
$value = str_replace(',', '.', $value); $value = str_replace(',', '.', $value);
$amount = app('steam')->positive($value); $amount = Steam::positive($value);
Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount)); Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount));
$this->collector->foreignAmountIs($amount); $this->collector->foreignAmountIs($amount);
@@ -2317,7 +2318,7 @@ class OperatorQuerySearch implements SearchInterface
// strip comma's, make dots. // strip comma's, make dots.
$value = str_replace(',', '.', $value); $value = str_replace(',', '.', $value);
$amount = app('steam')->positive($value); $amount = Steam::positive($value);
Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount)); Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount));
$this->collector->foreignAmountIsNot($amount); $this->collector->foreignAmountIsNot($amount);
@@ -2328,7 +2329,7 @@ class OperatorQuerySearch implements SearchInterface
// strip comma's, make dots. // strip comma's, make dots.
$value = str_replace(',', '.', $value); $value = str_replace(',', '.', $value);
$amount = app('steam')->positive($value); $amount = Steam::positive($value);
Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount)); Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount));
$this->collector->amountLess($amount); $this->collector->amountLess($amount);
@@ -2339,7 +2340,7 @@ class OperatorQuerySearch implements SearchInterface
// strip comma's, make dots. // strip comma's, make dots.
$value = str_replace(',', '.', $value); $value = str_replace(',', '.', $value);
$amount = app('steam')->positive($value); $amount = Steam::positive($value);
Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount)); Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount));
$this->collector->foreignAmountLess($amount); $this->collector->foreignAmountLess($amount);
@@ -2350,7 +2351,7 @@ class OperatorQuerySearch implements SearchInterface
Log::debug(sprintf('Now handling operator "%s"', $operator)); Log::debug(sprintf('Now handling operator "%s"', $operator));
// strip comma's, make dots. // strip comma's, make dots.
$value = str_replace(',', '.', $value); $value = str_replace(',', '.', $value);
$amount = app('steam')->positive($value); $amount = Steam::positive($value);
Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount)); Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount));
$this->collector->amountMore($amount); $this->collector->amountMore($amount);
@@ -2361,7 +2362,7 @@ class OperatorQuerySearch implements SearchInterface
Log::debug(sprintf('Now handling operator "%s"', $operator)); Log::debug(sprintf('Now handling operator "%s"', $operator));
// strip comma's, make dots. // strip comma's, make dots.
$value = str_replace(',', '.', $value); $value = str_replace(',', '.', $value);
$amount = app('steam')->positive($value); $amount = Steam::positive($value);
Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount)); Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount));
$this->collector->foreignAmountMore($amount); $this->collector->foreignAmountMore($amount);

View File

@@ -23,9 +23,8 @@ declare(strict_types=1);
namespace FireflyIII\Support; namespace FireflyIII\Support;
use FireflyIII\Support\Facades\Preferences;
use Deprecated;
use Carbon\Carbon; use Carbon\Carbon;
use Deprecated;
use Exception; use Exception;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
@@ -33,6 +32,7 @@ use FireflyIII\Models\AccountMeta;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Support\Facades\Amount; use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\Http\Api\ExchangeRateConverter; use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use FireflyIII\Support\Singleton\PreferencesSingleton; use FireflyIII\Support\Singleton\PreferencesSingleton;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@@ -131,7 +131,8 @@ class Steam
} }
/** /**
* Calls accountsBalancesOptimized for the given accounts and makes sure that inclusive is set to false, so it properly gets the balance of a range. * Calls accountsBalancesOptimized for the given accounts and makes sure that inclusive is set to false, so it
* properly gets the balance of a range.
*/ */
public function accountsBalancesInRange(Collection $accounts, Carbon $start, Carbon $end, ?TransactionCurrency $primary = null, ?bool $convertToPrimary = null): array public function accountsBalancesInRange(Collection $accounts, Carbon $start, Carbon $end, ?TransactionCurrency $primary = null, ?bool $convertToPrimary = null): array
{ {
@@ -291,21 +292,23 @@ class Steam
return str_replace($search, '', $string); return str_replace($search, '', $string);
} }
#[Deprecated(message: <<<'TXT' #[Deprecated(
message: <<<'TXT'
By default this method returns "smaller than or equal to", so be careful with END OF DAY. By default this method returns "smaller than or equal to", so be careful with END OF DAY.
If you need end of day balance, use "inclusive = false". If you need end of day balance, use "inclusive = false".
Returns the balance of an account at exact moment given. Array with at least one value. Returns the balance of an account at exact moment given. Array with at least one value.
Always returns: Always returns:
"balance": balance in the account's currency OR user's primary currency if the account has no currency "balance": balance in the account's currency OR user's primary currency if the account has no currency
"EUR": balance in EUR (or whatever currencies the account has balance in) "EUR": balance in EUR (or whatever currencies the account has balance in)
If the user has $convertToPrimary: If the user has $convertToPrimary:
"balance": balance in the account's currency OR user's primary currency if the account has no currency "balance": balance in the account's currency OR user's primary currency if the account has no currency
--> "pc_balance": balance in the user's primary currency, with all amounts converted to the primary currency. --> "pc_balance": balance in the user's primary currency, with all amounts converted to the primary currency.
"EUR": balance in EUR (or whatever currencies the account has balance in) "EUR": balance in EUR (or whatever currencies the account has balance in)
TXT)] TXT
)]
public function finalAccountBalance(Account $account, Carbon $date, ?TransactionCurrency $primary = null, ?bool $convertToPrimary = null, bool $inclusive = true): array public function finalAccountBalance(Account $account, Carbon $date, ?TransactionCurrency $primary = null, ?bool $convertToPrimary = null, bool $inclusive = true): array
{ {
@@ -663,8 +666,8 @@ class Steam
*/ */
public function getSafePreviousUrl(): string public function getSafePreviousUrl(): string
{ {
// Log::debug(sprintf('getSafePreviousUrl: "%s"', session()->previousUrl())); $res = $this->getSafeUrl(session()->previousUrl() ?? route('index'), route('index'));
return session()->previousUrl() ?? route('index'); Log::debug(sprintf('getSafePreviousUrl: "%s"', $res));
} }
/** /**
@@ -675,6 +678,7 @@ class Steam
// Log::debug(sprintf('getSafeUrl(%s, %s)', $unknownUrl, $safeUrl)); // Log::debug(sprintf('getSafeUrl(%s, %s)', $unknownUrl, $safeUrl));
$returnUrl = $safeUrl; $returnUrl = $safeUrl;
// die('in get safe url');
try { try {
$unknownHost = parse_url($unknownUrl, PHP_URL_HOST); $unknownHost = parse_url($unknownUrl, PHP_URL_HOST);
} catch (UrlException $e) { } catch (UrlException $e) {

View File

@@ -200,7 +200,7 @@ class General extends AbstractExtension
} }
return implode(', ', $strings); return implode(', ', $strings);
// return app('steam')->balance($account, $date); // return \FireflyIII\Support\Facades\Steam::balance($account, $date);
} }
); );
} }

View File

@@ -24,7 +24,6 @@ declare(strict_types=1);
namespace FireflyIII\TransactionRules\Actions; namespace FireflyIII\TransactionRules\Actions;
use Illuminate\Support\Facades\Log;
use FireflyIII\Enums\TransactionTypeEnum; use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnObject; use FireflyIII\Events\Model\Rule\RuleActionFailedOnObject;
@@ -33,10 +32,13 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Models\RuleAction; use FireflyIII\Models\RuleAction;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Facades\Steam;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
/** /**
* Class ConvertToTransfer * Class ConvertToTransfer
@@ -77,10 +79,8 @@ class ConvertToTransfer implements ActionInterface
$user = $object->user; $user = $object->user;
$journalId = $object->id; $journalId = $object->id;
if (TransactionTypeEnum::TRANSFER->value === $type) { if (TransactionTypeEnum::TRANSFER->value === $type) {
Log::error( Log::error(sprintf('Journal #%d is already a transfer so cannot be converted (rule #%d).', $object->id, $this->action->rule_id));
sprintf('Journal #%d is already a transfer so cannot be converted (rule #%d).', $object->id, $this->action->rule_id) // event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.is_already_transfer')));
);
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.is_already_transfer')));
return false; return false;
} }
@@ -106,15 +106,7 @@ class ConvertToTransfer implements ActionInterface
$opposing = $repository->findByName($accountName, [$expectedType]); $opposing = $repository->findByName($accountName, [$expectedType]);
if (null === $opposing) { if (null === $opposing) {
Log::error( Log::error(sprintf('Journal #%d cannot be converted because no valid %s account with name "%s" exists (rule #%d).', $expectedType, $journalId, $accountName, $this->action->rule_id));
sprintf(
'Journal #%d cannot be converted because no valid %s account with name "%s" exists (rule #%d).',
$expectedType,
$journalId,
$accountName,
$this->action->rule_id
)
);
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.no_valid_opposing', ['name' => $accountName]))); event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.no_valid_opposing', ['name' => $accountName])));
return false; return false;
@@ -167,7 +159,7 @@ class ConvertToTransfer implements ActionInterface
return ''; return '';
} }
return (string) $journal->transactions()->where('amount', '<', 0)->first()?->account?->accountType?->type; return (string)$journal->transactions()->where('amount', '<', 0)->first()?->account?->accountType?->type;
} }
private function getDestinationType(int $journalId): string private function getDestinationType(int $journalId): string
@@ -180,7 +172,7 @@ class ConvertToTransfer implements ActionInterface
return ''; return '';
} }
return (string) $journal->transactions()->where('amount', '>', 0)->first()?->account?->accountType?->type; return (string)$journal->transactions()->where('amount', '>', 0)->first()?->account?->accountType?->type;
} }
/** /**
@@ -192,33 +184,57 @@ class ConvertToTransfer implements ActionInterface
*/ */
private function convertWithdrawalArray(TransactionJournal $journal, Account $opposing): bool private function convertWithdrawalArray(TransactionJournal $journal, Account $opposing): bool
{ {
$sourceAccount = $this->getSourceAccount($journal); $repository = app(AccountRepositoryInterface::class);
$sourceAccount = $this->getSourceAccount($journal);
$repository->setUser($sourceAccount->user);
if ($sourceAccount->id === $opposing->id) { if ($sourceAccount->id === $opposing->id) {
Log::error( Log::error(vsprintf('Journal #%d has already has "%s" as a source asset. ConvertToTransfer failed. (rule #%d).', [$journal->id, $opposing->name, $this->action->rule_id]));
vsprintf(
'Journal #%d has already has "%s" as a source asset. ConvertToTransfer failed. (rule #%d).',
[$journal->id, $opposing->name, $this->action->rule_id]
)
);
event(new RuleActionFailedOnObject($this->action, $journal, trans('rules.already_has_source_asset', ['name' => $opposing->name]))); event(new RuleActionFailedOnObject($this->action, $journal, trans('rules.already_has_source_asset', ['name' => $opposing->name])));
return false; return false;
} }
/** @var Transaction $sourceTransaction */
$sourceTransaction = Transaction::where('transaction_journal_id', '=', $journal->id)->where('amount', '<', 0)->first();
/** @var Transaction $destTransaction */
$destTransaction = Transaction::where('transaction_journal_id', '=', $journal->id)->where('amount', '>', 0)->first();
// update destination transaction: // update destination transaction:
DB::table('transactions') $destTransaction->account_id = $opposing->id;
->where('transaction_journal_id', '=', $journal->id) $destTransaction->save();
->where('amount', '>', 0)
->update(['account_id' => $opposing->id]) // check if the currencies are a match.
; /** @var TransactionCurrency $sourceCurrency */
$sourceCurrency = $repository->getAccountCurrency($sourceAccount);
/** @var TransactionCurrency $destCurrency */
$destCurrency = $repository->getAccountCurrency($opposing);
// if the currencies do not match, need to be smart about the involved amounts:
if ($sourceCurrency->id !== $destCurrency->id) {
Log::debug(sprintf('Accounts have different currencies. Source has %s, dest has %s', $sourceCurrency->code, $destCurrency->code));
$foreignAmount = '' === (string)$sourceTransaction->foreign_amount ? $sourceTransaction->amount : $sourceTransaction->foreign_amount;
Log::debug(sprintf('Foreign amount: %s', $foreignAmount));
// source transaction: set the foreign currency ID and leave as is.
$sourceTransaction->foreign_currency_id = $destCurrency->id;
$sourceTransaction->foreign_amount = Steam::negative($foreignAmount);
$sourceTransaction->save();
Log::debug(sprintf('Set source transaction #%d foreign currency ID to #%d (amount: %s)', $sourceTransaction->id, $destCurrency->id, $foreignAmount));
// dest transaction: set reverse amounts and currency IDs from source transaction.
$destTransaction->foreign_currency_id = $sourceCurrency->transaction_currency_id;
$destTransaction->transaction_currency_id = $sourceTransaction->foreign_currency_id;
$destTransaction->amount = Steam::positive($foreignAmount);
$destTransaction->foreign_amount = Steam::positive($sourceTransaction->amount);
$destTransaction->save();
Log::debug(sprintf('Set dest transaction #%d to #%d %s and foreign #%d %s', $destTransaction->id, $destTransaction->transaction_currency_id, $destTransaction->amount, $destTransaction->foreign_currency_id, $destTransaction->foreign_amount));
}
// change transaction type of journal: // change transaction type of journal:
$newType = TransactionType::whereType(TransactionTypeEnum::TRANSFER->value)->first(); $newType = TransactionType::whereType(TransactionTypeEnum::TRANSFER->value)->first();
DB::table('transaction_journals') DB::table('transaction_journals')->where('id', '=', $journal->id)->update(['transaction_type_id' => $newType->id, 'bill_id' => null]);
->where('id', '=', $journal->id)
->update(['transaction_type_id' => $newType->id, 'bill_id' => null])
;
Log::debug('Converted withdrawal to transfer.'); Log::debug('Converted withdrawal to transfer.');

View File

@@ -31,6 +31,7 @@ use FireflyIII\Models\RuleAction;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\TransactionRules\Traits\RefreshNotesTrait; use FireflyIII\TransactionRules\Traits\RefreshNotesTrait;
use FireflyIII\Support\Facades\Steam;
class SetAmount implements ActionInterface class SetAmount implements ActionInterface
{ {
@@ -66,8 +67,8 @@ class SetAmount implements ActionInterface
/** @var TransactionJournal $object */ /** @var TransactionJournal $object */
$object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
$positive = app('steam')->positive($value); $positive = Steam::positive($value);
$negative = app('steam')->negative($value); $negative = Steam::negative($value);
$this->updatePositive($object, $positive); $this->updatePositive($object, $positive);
$this->updateNegative($object, $negative); $this->updateNegative($object, $negative);

View File

@@ -3,7 +3,50 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/). This project adheres to [Semantic Versioning](http://semver.org/).
## 6.4.9 - 2025-11-xx ## v6.4.14 - 2025-12-17
### Fixed
- [Issue 11368](https://github.com/firefly-iii/firefly-iii/issues/11368) (Attempt to read property "user" on null) reported by @simonwiles
## v6.4.13 - 2025-12-17
### Fixed
- [Issue 11368](https://github.com/firefly-iii/firefly-iii/issues/11368) (Attempt to read property "user" on null) reported by @simonwiles
## v6.4.12 - 2025-12-17
### Fixed
- [Issue 11368](https://github.com/firefly-iii/firefly-iii/issues/11368) (Attempt to read property "user" on null) reported by @simonwiles
- [Issue 11367](https://github.com/firefly-iii/firefly-iii/issues/11367) (Expenses page has incorrect summary values) reported by @purplemeteorite
## v6.4.11 - 2025-12-16
### Fixed
- [Issue 11356](https://github.com/firefly-iii/firefly-iii/issues/11356) (Dashboard - Budget - Left To Spend "Per day" shows total budget value) reported by @lucasarrudadev
- [Issue 11357](https://github.com/firefly-iii/firefly-iii/issues/11357) (Firefly III v6.4.10 ran into an error: Undefined variable $uploadDir.) reported by @jgmm81
## v6.4.10 - 2025-12-15
### Added
- Added amount event audit log
### Fixed
- [Issue 11328](https://github.com/firefly-iii/firefly-iii/issues/11328) (Three budget / account display bugs in latest version (annual budget + account list balance)) reported by @qingxianaaa
- [Issue 11329](https://github.com/firefly-iii/firefly-iii/issues/11329) (Imported and auto-converted transfer from different currency issue) reported by @bozho
- [Issue 11333](https://github.com/firefly-iii/firefly-iii/issues/11333) (Prepared statement contains too many placeholders) reported by @wendyliga
- [Issue 11313](https://github.com/firefly-iii/firefly-iii/issues/11313) (Stop Processing and Executing Rule Group on Existing Transaction) reported by @watertrainer
- [Discussion 11323](https://github.com/orgs/firefly-iii/discussions/11323) (File ownership problem) started by @enboig
- [Issue 11337](https://github.com/firefly-iii/firefly-iii/issues/11337) (email notifications are sent to old email address after changing it through the web UI) reported by @xsolinsx
- [Issue 11346](https://github.com/firefly-iii/firefly-iii/issues/11346) (Running balance restart from zero for no reason) reported by @Arkarr
- [Issue 11310](https://github.com/firefly-iii/firefly-iii/issues/11310) (Period parameter doesn't work in API) reported by @kvdb06
## 6.4.9 - 2025-11-28
### Fixed ### Fixed

View File

@@ -103,13 +103,12 @@
"psr/log": "<4", "psr/log": "<4",
"ramsey/uuid": "^4.7", "ramsey/uuid": "^4.7",
"rcrowe/twigbridge": "^0.14", "rcrowe/twigbridge": "^0.14",
"sentry/sentry-laravel": "^4.18",
"spatie/laravel-html": "^3.2", "spatie/laravel-html": "^3.2",
"spatie/laravel-ignition": "^2", "spatie/laravel-ignition": "^2",
"spatie/period": "^2.4", "spatie/period": "^2.4",
"symfony/expression-language": "^7.0", "symfony/expression-language": "^8.0",
"symfony/http-client": "^7.1", "symfony/http-client": "^8.0",
"symfony/mailgun-mailer": "^7.1", "symfony/mailgun-mailer": "^8.0",
"thecodingmachine/safe": "^3.1" "thecodingmachine/safe": "^3.1"
}, },
"require-dev": { "require-dev": {

766
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -78,8 +78,8 @@ return [
'running_balance_column' => env('USE_RUNNING_BALANCE', false), 'running_balance_column' => env('USE_RUNNING_BALANCE', false),
// see cer.php for exchange rates feature flag. // see cer.php for exchange rates feature flag.
], ],
'version' => '6.4.9', 'version' => 'develop/2025-12-19',
'build_time' => 1764362024, 'build_time' => 1766158365,
'api_version' => '2.1.0', // field is no longer used. 'api_version' => '2.1.0', // field is no longer used.
'db_version' => 28, // field is no longer used. 'db_version' => 28, // field is no longer used.
@@ -107,7 +107,6 @@ return [
'demo_password' => env('DEMO_PASSWORD', ''), 'demo_password' => env('DEMO_PASSWORD', ''),
'tracker_site_id' => env('TRACKER_SITE_ID', ''), 'tracker_site_id' => env('TRACKER_SITE_ID', ''),
'tracker_url' => env('TRACKER_URL', ''), 'tracker_url' => env('TRACKER_URL', ''),
'report_errors_online' => env('REPORT_ERRORS_ONLINE', false),
// authentication settings // authentication settings
'authentication_guard' => envNonEmpty('AUTHENTICATION_GUARD', 'web'), 'authentication_guard' => envNonEmpty('AUTHENTICATION_GUARD', 'web'),

919
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -8,5 +8,8 @@
], ],
"devDependencies": { "devDependencies": {
"postcss": "^8.4.47" "postcss": "^8.4.47"
},
"dependencies": {
"patch-package": "^8.0.1"
} }
} }

View File

@@ -1,10 +1,8 @@
diff --git a/node_modules/admin-lte/src/scss/_app-sidebar.scss b/node_modules/admin-lte/src/scss/_app-sidebar.scss diff --git a/node_modules/admin-lte/src/scss/_app-sidebar.scss b/node_modules/admin-lte/src/scss/_app-sidebar.scss
old mode 100644 index 4420bd0..35da532
new mode 100755
index 69dfc16..dc341eb
--- a/node_modules/admin-lte/src/scss/_app-sidebar.scss --- a/node_modules/admin-lte/src/scss/_app-sidebar.scss
+++ b/node_modules/admin-lte/src/scss/_app-sidebar.scss +++ b/node_modules/admin-lte/src/scss/_app-sidebar.scss
@@ -577,7 +577,6 @@ body:not(.app-loaded) { @@ -599,7 +599,6 @@ body:not(.app-loaded) {
@if $enable-dark-mode { @if $enable-dark-mode {
@include color-mode(dark) { @include color-mode(dark) {

View File

@@ -7,7 +7,7 @@
"administration_currency_form_help": "It may take a long time for the page to load if you change the primary currency because transaction may need to be converted to your (new) primary currency.", "administration_currency_form_help": "It may take a long time for the page to load if you change the primary currency because transaction may need to be converted to your (new) primary currency.",
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"", "administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",
"table": "Tabel", "table": "Tabel",
"welcome_back": "Ce se red\u0103?", "welcome_back": "Situa\u021bia ta financiar\u0103",
"flash_error": "Eroare!", "flash_error": "Eroare!",
"flash_warning": "Avertizare!", "flash_warning": "Avertizare!",
"flash_success": "Succes!", "flash_success": "Succes!",

View File

@@ -366,13 +366,21 @@
</span> </span>
<br/> <br/>
{% endif %} {% endif %}
{% if spentInfo.currency_id == budgetLimit.currency_id and not budgetLimit.in_range %} {% if spentInfo.currency_id == budgetLimit.currency_id and not budgetLimit.in_range and 0.0 == budgetLimit.total_days %}
<span class="left_span" data-currency="{{ spentInfo.currency_id }}" data-limit="{{ budgetLimit.id }}" <span class="left_span" data-currency="{{ spentInfo.currency_id }}" data-limit="{{ budgetLimit.id }}"
data-value="{{ spentInfo.spent + budgetLimit.amount }}" class="amount_left"> data-value="{{ spentInfo.spent + budgetLimit.amount }}" class="amount_left">
{{ formatAmountBySymbol(spentInfo.spent + budgetLimit.amount, spentInfo.currency_symbol, spentInfo.currency_decimal_places) }} {{ formatAmountBySymbol(spentInfo.spent + budgetLimit.amount, spentInfo.currency_symbol, spentInfo.currency_decimal_places) }}
</span> </span>
<span class="text-muted">({{ 'unknown'|_ }})</span> <span class="text-muted">({{ 'unknown'|_ }})</span>
{% endif %} {% endif %}
{% if spentInfo.currency_id == budgetLimit.currency_id and not budgetLimit.in_range and 0.0 != budgetLimit.total_days %}
<span class="left_span" data-currency="{{ spentInfo.currency_id }}" data-limit="{{ budgetLimit.id }}"
data-value="{{ spentInfo.spent + budgetLimit.amount }}" class="amount_left">
{{ formatAmountBySymbol(spentInfo.spent + budgetLimit.amount, spentInfo.currency_symbol, spentInfo.currency_decimal_places) }}
</span>
({{ formatAmountBySymbol((spentInfo.spent + budgetLimit.amount) / budgetLimit.total_days, spentInfo.currency_symbol, spentInfo.currency_decimal_places) }})
{% endif %}
{% endfor %} {% endfor %}
{% if countLimit == 0 %} {% if countLimit == 0 %}

View File

@@ -272,27 +272,42 @@
{% if transaction.transaction_type_type == 'Deposit' %} {% if transaction.transaction_type_type == 'Deposit' %}
{% if transaction.source_account_id == account.id %} {% if transaction.source_account_id == account.id %}
{{ formatAmountBySymbol(transaction.source_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }} {{ formatAmountBySymbol(transaction.source_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }}
{% else %} {% else %}
{{ formatAmountBySymbol(transaction.destination_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }} {{ formatAmountBySymbol(transaction.destination_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }}
{% endif %} {% endif %}
{% elseif transaction.transaction_type_type == 'Withdrawal' %} {% elseif transaction.transaction_type_type == 'Withdrawal' %}
{# withdrawal into a liability #}
{% if 'Loan' == transaction.destination_account_type or 'Mortgage' == transaction.destination_account_type or 'Debt' == transaction.destination_account_type %} {% if 'Loan' == transaction.destination_account_type or 'Mortgage' == transaction.destination_account_type or 'Debt' == transaction.destination_account_type %}
{% if currency.id == transaction.currency_id %} {% if currency.id == transaction.currency_id %}
{{ formatAmountBySymbol(transaction.destination_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }} {% if account.id == transaction.source_account_id %}
{{ formatAmountBySymbol(transaction.source_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }}
{% elseif account.id == transaction.destination_account_id %}
{{ formatAmountBySymbol(transaction.destination_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }}
{% else %}
-
{% endif %}
{% endif %} {% endif %}
{% if currency.id == transaction.foreign_currency_id and null != transaction.destination_balance_after and null != transaction.destination_balance_after %} {% if currency.id == transaction.foreign_currency_id and null != transaction.destination_balance_after and null != transaction.destination_balance_after %}
{{ formatAmountBySymbol(transaction.destination_balance_after, transaction.foreign_currency_symbol ?? transaction.currency_symbol, transaction.foreign_currency_decimal_places ?? transaction.currency_decimal_places) }} {{ formatAmountBySymbol(transaction.destination_balance_after, transaction.foreign_currency_symbol ?? transaction.currency_symbol, transaction.foreign_currency_decimal_places ?? transaction.currency_decimal_places) }}
{% endif %} {% endif %}
{# withdrawal into an expense account #}
{% else %} {% else %}
{{ formatAmountBySymbol(transaction.source_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }} {% if account.id == transaction.source_account_id %}
{{ formatAmountBySymbol(transaction.source_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }}
{% elseif account.id == transaction.destination_account_id %}
{{ formatAmountBySymbol(transaction.destination_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }}
{% else %}
-
{% endif %}
{% endif %} {% endif %}
{% elseif transaction.transaction_type_type == 'Opening balance' %} {% elseif transaction.transaction_type_type == 'Opening balance' %}
{% if transaction.source_account_type == 'Initial balance account' %} {% if account.id == transaction.source_account_id %}
{{ formatAmountBySymbol(transaction.destination_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }} {{ formatAmountBySymbol(transaction.destination_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }}
{% else %} {% elseif account.id == transaction.destination_account_id %}
{{ formatAmountBySymbol(transaction.source_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }} {{ formatAmountBySymbol(transaction.source_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }}
{% else %}
-
{% endif %} {% endif %}
{% elseif transaction.transaction_type_type == 'Transfer' %} {% elseif transaction.transaction_type_type == 'Transfer' %}
{% if account.id == transaction.source_account_id %} {% if account.id == transaction.source_account_id %}

View File

@@ -27,7 +27,6 @@ namespace Tests\unit\Support\Calendar\Periodicity;
use FireflyIII\Support\Calendar\Periodicity\Bimonthly; use FireflyIII\Support\Calendar\Periodicity\Bimonthly;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Support\Calendar\Periodicity; use FireflyIII\Support\Calendar\Periodicity;
use FireflyIII\Support\Calendar\Periodicity\Interval;
/** /**
* @group unit-test * @group unit-test
@@ -41,7 +40,7 @@ use FireflyIII\Support\Calendar\Periodicity\Interval;
*/ */
final class BimonthlyTest extends IntervalTestCase final class BimonthlyTest extends IntervalTestCase
{ {
public static function factory(): Interval public static function factory(): Bimonthly
{ {
return new Bimonthly(); return new Bimonthly();
} }

View File

@@ -27,7 +27,6 @@ namespace Tests\unit\Support\Calendar\Periodicity;
use FireflyIII\Support\Calendar\Periodicity\Daily; use FireflyIII\Support\Calendar\Periodicity\Daily;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Support\Calendar\Periodicity; use FireflyIII\Support\Calendar\Periodicity;
use FireflyIII\Support\Calendar\Periodicity\Interval;
/** /**
* @group unit-test * @group unit-test
@@ -41,7 +40,7 @@ use FireflyIII\Support\Calendar\Periodicity\Interval;
*/ */
final class DailyTest extends IntervalTestCase final class DailyTest extends IntervalTestCase
{ {
public static function factory(): Interval public static function factory(): Daily
{ {
return new Daily(); return new Daily();
} }

View File

@@ -27,7 +27,6 @@ namespace Tests\unit\Support\Calendar\Periodicity;
use FireflyIII\Support\Calendar\Periodicity\Fortnightly; use FireflyIII\Support\Calendar\Periodicity\Fortnightly;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Support\Calendar\Periodicity; use FireflyIII\Support\Calendar\Periodicity;
use FireflyIII\Support\Calendar\Periodicity\Interval;
/** /**
* @group unit-test * @group unit-test
@@ -41,7 +40,7 @@ use FireflyIII\Support\Calendar\Periodicity\Interval;
*/ */
final class FortnightlyTest extends IntervalTestCase final class FortnightlyTest extends IntervalTestCase
{ {
public static function factory(): Interval public static function factory(): Fortnightly
{ {
return new Fortnightly(); return new Fortnightly();
} }

View File

@@ -27,7 +27,6 @@ namespace Tests\unit\Support\Calendar\Periodicity;
use FireflyIII\Support\Calendar\Periodicity\HalfYearly; use FireflyIII\Support\Calendar\Periodicity\HalfYearly;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Support\Calendar\Periodicity; use FireflyIII\Support\Calendar\Periodicity;
use FireflyIII\Support\Calendar\Periodicity\Interval;
/** /**
* @group unit-test * @group unit-test
@@ -41,7 +40,7 @@ use FireflyIII\Support\Calendar\Periodicity\Interval;
*/ */
final class HalfYearlyTest extends IntervalTestCase final class HalfYearlyTest extends IntervalTestCase
{ {
public static function factory(): Interval public static function factory(): HalfYearly
{ {
return new HalfYearly(); return new HalfYearly();
} }

View File

@@ -27,7 +27,6 @@ namespace Tests\unit\Support\Calendar\Periodicity;
use FireflyIII\Support\Calendar\Periodicity\Monthly; use FireflyIII\Support\Calendar\Periodicity\Monthly;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Support\Calendar\Periodicity; use FireflyIII\Support\Calendar\Periodicity;
use FireflyIII\Support\Calendar\Periodicity\Interval;
/** /**
* @group unit-test * @group unit-test
@@ -41,7 +40,7 @@ use FireflyIII\Support\Calendar\Periodicity\Interval;
*/ */
final class MonthlyTest extends IntervalTestCase final class MonthlyTest extends IntervalTestCase
{ {
public static function factory(): Interval public static function factory(): Monthly
{ {
return new Monthly(); return new Monthly();
} }

View File

@@ -27,7 +27,6 @@ namespace Tests\unit\Support\Calendar\Periodicity;
use FireflyIII\Support\Calendar\Periodicity\Quarterly; use FireflyIII\Support\Calendar\Periodicity\Quarterly;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Support\Calendar\Periodicity; use FireflyIII\Support\Calendar\Periodicity;
use FireflyIII\Support\Calendar\Periodicity\Interval;
/** /**
* @group unit-test * @group unit-test
@@ -41,7 +40,7 @@ use FireflyIII\Support\Calendar\Periodicity\Interval;
*/ */
final class QuarterlyTest extends IntervalTestCase final class QuarterlyTest extends IntervalTestCase
{ {
public static function factory(): Interval public static function factory(): Quarterly
{ {
return new Quarterly(); return new Quarterly();
} }

View File

@@ -27,7 +27,6 @@ namespace Tests\unit\Support\Calendar\Periodicity;
use FireflyIII\Support\Calendar\Periodicity\Weekly; use FireflyIII\Support\Calendar\Periodicity\Weekly;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Support\Calendar\Periodicity; use FireflyIII\Support\Calendar\Periodicity;
use FireflyIII\Support\Calendar\Periodicity\Interval;
/** /**
* @group unit-test * @group unit-test
@@ -41,7 +40,7 @@ use FireflyIII\Support\Calendar\Periodicity\Interval;
*/ */
final class WeeklyTest extends IntervalTestCase final class WeeklyTest extends IntervalTestCase
{ {
public static function factory(): Interval public static function factory(): Weekly
{ {
return new Weekly(); return new Weekly();
} }

View File

@@ -27,7 +27,6 @@ namespace Tests\unit\Support\Calendar\Periodicity;
use FireflyIII\Support\Calendar\Periodicity\Yearly; use FireflyIII\Support\Calendar\Periodicity\Yearly;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Support\Calendar\Periodicity; use FireflyIII\Support\Calendar\Periodicity;
use FireflyIII\Support\Calendar\Periodicity\Interval;
/** /**
* @group unit-test * @group unit-test
@@ -41,7 +40,7 @@ use FireflyIII\Support\Calendar\Periodicity\Interval;
*/ */
final class YearlyTest extends IntervalTestCase final class YearlyTest extends IntervalTestCase
{ {
public static function factory(): Interval public static function factory(): Yearly
{ {
return new Yearly(); return new Yearly();
} }