Compare commits

..

303 Commits

Author SHA1 Message Date
github-actions
2d37177316 Auto commit for release 'develop' on 2025-01-06 2025-01-06 04:13:41 +01:00
James Cole
abb25e2015 Fix sql query error and upgrade error. 2025-01-05 14:33:33 +01:00
James Cole
d08d075e30 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-01-05 09:23:17 +01:00
github-actions
b4c67c02a7 Auto commit for release 'develop' on 2025-01-05 2025-01-05 09:23:02 +01:00
James Cole
04fb6a953e This rule is no longer necessary. 2025-01-05 09:21:29 +01:00
James Cole
5dce0bec8e This is no longer necessary since translations are no longer stored in the repository. 2025-01-05 09:20:55 +01:00
James Cole
481bb3fb0a Fix a few test cases. 2025-01-05 09:18:03 +01:00
James Cole
b6960dc299 Fix search result page. 2025-01-05 08:03:15 +01:00
James Cole
73104aae1f Fix data provider. 2025-01-05 07:52:23 +01:00
James Cole
10a284848b Drop else-statements, remove debug statement. 2025-01-05 07:45:29 +01:00
James Cole
fd6560bdd0 Fix copyright for new files. 2025-01-05 07:40:30 +01:00
James Cole
0810f617c7 Merge pull request #9598 from Sobuno/NewQueryParserV3
New Query Parser for Search Engine and Rules
2025-01-05 07:32:55 +01:00
James Cole
c3ffd39450 run phpcs 2025-01-05 07:31:26 +01:00
James Cole
0f69e0d672 Level 7 yay! 2025-01-04 19:43:58 +01:00
James Cole
1aa8ebe57f Fixed level 7! 2025-01-04 19:25:43 +01:00
James Cole
23178614d5 First fixes for level 7. 2025-01-04 19:12:04 +01:00
James Cole
d2b6829574 First fixes for level 7. 2025-01-04 19:05:24 +01:00
James Cole
5602715c96 Made it to level 6! 2025-01-04 15:16:11 +01:00
James Cole
54d0433dd4 Start with level 6. [skip ci] 2025-01-04 09:34:17 +01:00
James Cole
f4bc313d0b Fix level 5! Mostly by ignoring the errors lol. 2025-01-04 09:15:39 +01:00
James Cole
5617de3a79 Level 4 fixed! 2025-01-04 09:01:44 +01:00
James Cole
2d62f0ff06 Rename class [skip ci] 2025-01-04 08:44:02 +01:00
James Cole
1c79f6b1b6 Rename again [skip ci] 2025-01-04 08:42:57 +01:00
James Cole
bf01153c6b Rename file [skip ci] 2025-01-04 08:42:36 +01:00
James Cole
c43b37baef Various phpstan fixes [skip ci] 2025-01-04 08:42:06 +01:00
James Cole
d4942efd8e Fix various level 4 issues [skip ci] 2025-01-04 08:02:05 +01:00
James Cole
ea9f635b1a Improved cs fixer config [skip ci] 2025-01-04 07:39:33 +01:00
James Cole
7eaa0e16b3 Run phpcs locally to make sure phpstan stays fixed. [skip ci] 2025-01-04 07:39:16 +01:00
James Cole
1b97d8fd48 Fix phpcs things [skip ci] 2025-01-04 07:31:25 +01:00
James Cole
89a29b9b10 Disable a rule. 2025-01-04 07:25:45 +01:00
James Cole
2baac1a6d7 Fix phpstan level 3! 2025-01-04 07:10:37 +01:00
James Cole
cd296aa9ac Fix test run. 2025-01-04 06:35:26 +01:00
James Cole
959d168352 Fix various phpstan issues. 2025-01-03 19:16:38 +01:00
James Cole
6cd60951ba Fix for level 2 2025-01-03 19:07:29 +01:00
James Cole
3898c0c0ef Fix phpstan issues. 2025-01-03 18:16:27 +01:00
James Cole
fe4d139817 fix phpstan warnings 2025-01-03 15:53:10 +01:00
James Cole
d95f3ca59f No errors on level 1. 2025-01-03 15:07:30 +01:00
James Cole
7f6c03ce17 Fix phpstan issues. 2025-01-03 15:04:15 +01:00
James Cole
394d0eabef Fix various phpstan issues. 2025-01-03 14:56:06 +01:00
James Cole
a8ae496fda Replace enum 2025-01-03 09:15:52 +01:00
James Cole
1787f4421b Replace enum 2025-01-03 09:11:20 +01:00
James Cole
36351a5dd9 Replace enum 2025-01-03 09:09:15 +01:00
James Cole
d009ce31ca Replace enum 2025-01-03 09:05:56 +01:00
James Cole
44eafeeae5 Replace enum 2025-01-03 09:05:19 +01:00
James Cole
21165eb3e0 Update packages. 2025-01-03 08:30:04 +01:00
James Cole
2ef3a33fbf Merge branch 'main' into develop 2025-01-03 08:17:57 +01:00
James Cole
f74be0402f Add copyright statements. 2025-01-03 08:15:09 +01:00
github-actions
a60cb366b2 Auto commit for release 'develop' on 2025-01-03 2025-01-03 07:12:13 +01:00
github-actions
58e2ef187d Auto commit for release 'develop' on 2025-01-03 2025-01-03 07:01:02 +01:00
James Cole
ae80fd8578 Fix test cases. 2025-01-03 04:51:42 +01:00
James Cole
c17f2efca6 Fix missing variables. 2025-01-03 04:36:41 +01:00
James Cole
4a185639b9 Fix removal of all piggy banks. 2025-01-03 04:32:51 +01:00
Sobuno
dae7e7d507 Handle excludedWords on Rule management pages as well 2025-01-03 01:00:17 +01:00
Sobuno
e33e3cc40f Tweak UI 2025-01-03 00:45:19 +01:00
Sobuno
36ec1daf3a Update UI 2025-01-03 00:29:38 +01:00
Sobuno
50aff9cfb6 Make prohibited word search work 2025-01-03 00:13:51 +01:00
Sobuno
058a0f9fb2 Show excluded words in UI 2025-01-03 00:08:11 +01:00
Sobuno
0c955efa8b Allow flipping of subqueries 2025-01-03 00:07:57 +01:00
Sobuno
a62916a63d Simplify further 2025-01-02 23:36:00 +01:00
Sobuno
af7a4b5d3d Renaming of classes, making true recursive structure 2025-01-02 23:19:21 +01:00
Sobuno
2ae3929dd6 Give a bit better error messages in tests 2025-01-02 22:40:50 +01:00
Sobuno
ebd30f4861 Move tests to match rearranged structure + standardize tests 2025-01-02 22:18:12 +01:00
Sobuno
afc9ea08f3 Rearrange structure 2025-01-02 22:17:56 +01:00
Sobuno
78f9f7e2dd Add QUERY_PARSER_IMPLEMENTATION in .env.example 2025-01-02 20:06:11 +01:00
Sobuno
c44b827922 Fix environment-based selection of Query Parser 2025-01-02 20:03:39 +01:00
James Cole
fb30f7ec8f Update build script. 2025-01-02 19:10:39 +01:00
James Cole
e878d5ce07 Fix linking piggy banks to transactions. 2025-01-02 04:54:29 +01:00
github-actions
f727a38b69 Auto commit for release 'develop' on 2025-01-01 2025-01-01 16:47:50 +01:00
James Cole
c11a5384da Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-01-01 16:43:44 +01:00
James Cole
ed92cbd4b8 Fix piggy bank rule action 2025-01-01 16:43:31 +01:00
github-actions
a9ea32772f Auto commit for release 'develop' on 2025-01-01 2025-01-01 16:38:58 +01:00
Sobuno
92f5cca65b Add QueryParser tests to correct group 2025-01-01 14:18:56 +01:00
Sobuno
57b064f590 Remove incorrect LICENSE message at top of file 2025-01-01 14:18:19 +01:00
Sobuno
9729434926 Allow choosing QueryParser implementation 2025-01-01 05:36:22 +01:00
Sobuno
9d9dffee74 Always assert prohibited field 2025-01-01 05:32:49 +01:00
Sobuno
b3f374f4ea Introduce assertion helpers to make tests more readable 2025-01-01 05:32:49 +01:00
Sobuno
50e07d422f Small QoL additions 2025-01-01 05:32:49 +01:00
Sobuno
631ed4956a Handle right parenthesis behaviour correctly 2025-01-01 05:32:49 +01:00
Sobuno
0eca1c8d03 Fix test 2025-01-01 05:32:49 +01:00
Sobuno
e38e4574ad Fix warnings in tests and add some more 2025-01-01 05:32:49 +01:00
Sobuno
be2d3f3637 Rename QueryParser2 to QueryParser 2025-01-01 05:32:49 +01:00
Sobuno
0e3d779e24 Remove V1 2025-01-01 05:32:49 +01:00
Sobuno
4d25336d87 More WIP 2025-01-01 05:32:49 +01:00
Sobuno
74f76a2835 Fix namespace 2025-01-01 05:32:49 +01:00
Sobuno
84560a6f44 WIP 2025-01-01 05:32:49 +01:00
James Cole
6fde693e7a Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop
# Conflicts:
#	app/Support/Steam.php
2024-12-31 08:19:47 +01:00
James Cole
2e46d9ba33 Clean up some logs. 2024-12-31 08:18:40 +01:00
James Cole
e36f8deb08 Clean up some logs. 2024-12-31 08:18:21 +01:00
James Cole
1631b422f1 Clean up logs, add cache. 2024-12-31 08:17:35 +01:00
github-actions
b58d809063 Auto commit for release 'develop' on 2024-12-31 2024-12-31 08:09:51 +01:00
James Cole
9e34314dbc Fix various issues with new features, nullpointers and missing checks. 2024-12-31 08:05:25 +01:00
github-actions
e4aa218b5f Auto commit for release 'v6.2.0-alpha.1' on 2024-12-30 2024-12-30 17:09:40 +01:00
github-actions
31722477d4 Merge branch 'develop' 2024-12-30 16:07:29 +00:00
github-actions
ec82105433 Auto commit for release 'develop' on 2024-12-30 2024-12-30 15:35:26 +01:00
James Cole
146e164f04 Back to 8. 2024-12-30 15:31:27 +01:00
James Cole
7d37c93988 Expand workflow. 2024-12-30 15:25:39 +01:00
James Cole
73dffacd9a Expand to support alpha and beta versions. 2024-12-30 12:23:50 +01:00
James Cole
d37304fa68 Fix available budgets. 2024-12-30 12:22:39 +01:00
James Cole
62f4da6063 Update available budgets code. 2024-12-30 10:51:34 +01:00
James Cole
760da08ab7 Update exchange rates. 2024-12-30 07:36:22 +01:00
James Cole
e68c4d4408 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2024-12-30 07:36:12 +01:00
James Cole
46a200aa1f Fix broken variable. 2024-12-30 07:30:23 +01:00
James Cole
c422039335 Merge pull request #9589 from tasnim0tantawi/autocomplete-test
Autocomplete test - CurrencyControllerTest & ObjectGroupControllerTest
2024-12-30 07:18:05 +01:00
github-actions
0579c8565d Auto commit for release 'develop' on 2024-12-30 2024-12-30 04:12:18 +01:00
James Cole
9f25880a59 Clean up several endpoints with complex code. 2024-12-29 18:32:02 +01:00
James Cole
05f1819f7d Fix API convert to native. Still needs refactoring. 2024-12-29 14:24:20 +01:00
James Cole
fa2149f957 Update API to convert to native. 2024-12-29 13:47:48 +01:00
James Cole
c21a79e029 Better, but not perfect, currency switch. 2024-12-29 08:16:27 +01:00
James Cole
03e31ebb5e Clean up endpoint. 2024-12-29 06:36:49 +01:00
James Cole
3c20e5f3af Make sure integers are converted to strings because sqlite sucks. 2024-12-29 06:32:50 +01:00
James Cole
9a9dd9e075 Double fix. Not sure yet what causes this. 2024-12-29 06:17:29 +01:00
James Cole
7189986c03 Remove some debug logging. 2024-12-29 06:15:42 +01:00
James Cole
b407d8d315 Add usergroup, clean up some code. 2024-12-29 06:14:40 +01:00
James Cole
41fa2a6208 Include user group in test set. 2024-12-29 06:10:54 +01:00
James Cole
fe00c4c373 Fix unauthenticated get default currency. 2024-12-29 06:08:35 +01:00
James Cole
7248a76c63 Fix chart, expand changelog. 2024-12-29 05:58:12 +01:00
James Cole
ee3c618797 Fix https://github.com/firefly-iii/firefly-iii/issues/9586 2024-12-29 05:55:49 +01:00
James Cole
a1241ebedb Various multi-currency things in the autocomplete API. 2024-12-28 18:38:19 +01:00
James Cole
af78d998db Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2024-12-28 14:09:42 +01:00
James Cole
d96c235ffe Fix path 2024-12-28 14:09:22 +01:00
James Cole
79ca1b5f4e Change some CS fixer settings. 2024-12-28 14:08:34 +01:00
github-actions
0f68735e1c Auto commit for release 'develop' on 2024-12-28 2024-12-28 13:59:31 +01:00
James Cole
82abee37de Fix a string of text. 2024-12-28 13:45:45 +01:00
James Cole
507040f1fd Update various code for sqlite compatibility. 2024-12-28 13:36:25 +01:00
James Cole
42dc8486e9 Fix string. 2024-12-28 11:16:55 +01:00
github-actions
6c655634bc Auto commit for release 'develop' on 2024-12-28 2024-12-28 10:58:01 +01:00
James Cole
f2166b97b8 Various fixes for sqlite databases 2024-12-28 10:52:46 +01:00
James Cole
da88e02be0 Catch exception. 2024-12-28 07:47:32 +01:00
James Cole
0d56b7d251 Ignore error. Must test more with sqlite. 2024-12-28 07:39:39 +01:00
James Cole
0a089efcac Clean up commands. 2024-12-28 07:35:20 +01:00
James Cole
89ab360391 Remove reference to cacheable models 2024-12-28 07:10:33 +01:00
James Cole
2bd97d9a99 Remove references to laravel json api 2024-12-28 07:09:25 +01:00
James Cole
103b9056e4 Expand changelog, remove unused packages. 2024-12-28 06:55:17 +01:00
github-actions
23c4352c18 Auto commit for release 'develop' on 2024-12-27 2024-12-27 22:03:16 +01:00
James Cole
2dddaa36d5 Actions will default to php 8.4 2024-12-27 19:51:20 +01:00
James Cole
8ab7cf2388 Merge branch 'v6.2' into develop
# Conflicts:
#	composer.lock
#	config/firefly.php
#	package-lock.json
2024-12-27 19:50:05 +01:00
James Cole
f191086adb Enable cache again. 2024-12-27 19:47:35 +01:00
James Cole
68b446db18 Final changes. 2024-12-27 19:46:40 +01:00
James Cole
3d49d81856 Expand some multi currency things. 2024-12-27 16:36:01 +01:00
James Cole
96493425d1 Convert more of the budget view to native currency. 2024-12-27 13:42:48 +01:00
James Cole
419975285c Fix nullpointer 2024-12-27 13:02:23 +01:00
github-actions
aa5bde122e Auto commit for release 'branch-v6.2' on 2024-12-27 2024-12-27 12:43:57 +01:00
James Cole
0fa3c2bd8d Fix issue with prefilled piggy banks. 2024-12-27 12:39:26 +01:00
James Cole
b9249a4d96 Update commands. 2024-12-27 09:30:41 +01:00
James Cole
6638ca270f Merge branch 'v6.2' of github.com:firefly-iii/firefly-iii into v6.2 2024-12-27 07:36:37 +01:00
James Cole
9bfef892f8 Remove lots of debug logs 2024-12-27 07:36:30 +01:00
github-actions
32e5efec7c Auto commit for release 'branch-v6.2' on 2024-12-27 2024-12-27 07:29:17 +01:00
James Cole
36457455ca Rename and clean up commands. 2024-12-27 07:24:47 +01:00
James Cole
062c148e43 Rename all correction commands. 2024-12-27 06:56:08 +01:00
James Cole
2314ce8004 Refactor and renam commands. 2024-12-27 06:48:58 +01:00
James Cole
a3ff73903a Fix bad error message. 2024-12-27 05:44:03 +01:00
James Cole
7c8445707e Add moar debug. 2024-12-26 14:12:05 +01:00
James Cole
291e73da4b Rename bills to subscriptions 2024-12-26 13:41:57 +01:00
James Cole
286a29ca3e Display for bills. 2024-12-26 11:28:31 +01:00
github-actions
71cf6c6a5e Auto commit for release 'branch-v6.2' on 2024-12-26 2024-12-26 10:24:39 +01:00
James Cole
1e8f0adaf8 Fix broken account balance. 2024-12-26 10:20:40 +01:00
James Cole
33531244aa Merge branch 'v6.2' of github.com:firefly-iii/firefly-iii into v6.2
# Conflicts:
#	app/Http/Controllers/Chart/AccountController.php
#	app/Support/Steam.php
2024-12-26 09:19:04 +01:00
James Cole
06049a9a28 Update various pages, clean up some code. 2024-12-26 09:16:17 +01:00
James Cole
d313f5fdf5 Fix chart balance. 2024-12-26 08:53:16 +01:00
github-actions
f4868126c1 Auto commit for release 'branch-v6.2' on 2024-12-26 2024-12-26 05:25:46 +01:00
James Cole
00147e98dd Fix home chart. 2024-12-26 05:21:28 +01:00
James Cole
6d22663ca2 Fix charts and balances. 2024-12-26 05:11:32 +01:00
James Cole
756bb9cf5e Fix overview, skip chart for now. 2024-12-25 11:59:15 +01:00
James Cole
399d7968f5 Fix another null. 2024-12-25 08:30:00 +01:00
James Cole
966b68f42e Merge branch 'v6.2' of github.com:firefly-iii/firefly-iii into v6.2 2024-12-25 08:29:50 +01:00
James Cole
134c551c12 Remove some comments, add others. 2024-12-25 08:23:17 +01:00
github-actions
9aeca15355 Auto commit for release 'branch-v6.2' on 2024-12-25 2024-12-25 08:17:59 +01:00
James Cole
6c6d31830b Fix nullpointer 2024-12-25 08:14:07 +01:00
github-actions
e8cc321898 Auto commit for release 'branch-v6.2' on 2024-12-25 2024-12-25 07:13:41 +01:00
James Cole
e73fe06f7e Expand currency view in accounts. 2024-12-25 07:10:02 +01:00
James Cole
98b579c042 Fix native display. 2024-12-24 19:03:47 +01:00
James Cole
7b3a5c1afd Frontpage seems to be multi currency aware. 2024-12-24 16:56:31 +01:00
James Cole
7e2e49e129 Convert more charts. 2024-12-24 10:29:07 +01:00
James Cole
e8ef630424 Expand native amount things. 2024-12-24 06:34:12 +01:00
James Cole
8805bcf6f6 Various updates to display native/foreign amounts. 2024-12-23 17:32:15 +01:00
James Cole
ff5c9a3aa0 Merge branch 'v6.2' of github.com:firefly-iii/firefly-iii into v6.2 2024-12-23 14:35:34 +01:00
James Cole
3a274dcaa7 Little debug page with routes. 2024-12-23 14:35:27 +01:00
github-actions
ddfededf02 Auto commit for release 'branch-v6.2' on 2024-12-23 2024-12-23 08:40:29 +01:00
James Cole
e1785898ba Add notes to audit report. 2024-12-23 08:35:33 +01:00
James Cole
ae09200f42 Fix import 2024-12-23 08:26:35 +01:00
James Cole
847984f678 New rule triggers for account balance. 2024-12-23 08:22:54 +01:00
TasneemTantawy
5971d155ef fixed create authenticated user 2024-12-23 09:37:06 +03:00
James Cole
42305672ac Merge branch 'v6.2' of github.com:firefly-iii/firefly-iii into v6.2 2024-12-23 07:14:12 +01:00
James Cole
25a56d9f72 Chart no longer as a line chart. 2024-12-23 07:13:59 +01:00
James Cole
cea52c0ac7 Merge pull request #9571 from firefly-iii/dependabot/composer/develop/phpunit/phpunit-10.5.40
Bump phpunit/phpunit from 10.5.39 to 10.5.40
2024-12-23 07:02:55 +01:00
James Cole
1b33ff9c25 Merge pull request #9573 from firefly-iii/dependabot/npm_and_yarn/develop/i18next-24.2.0
Bump i18next from 24.1.2 to 24.2.0
2024-12-23 07:02:41 +01:00
github-actions
8f9f08b96f Auto commit for release 'branch-v6.2' on 2024-12-23 2024-12-23 07:01:44 +01:00
James Cole
594ba205bb Merge pull request #9574 from firefly-iii/dependabot/npm_and_yarn/develop/vite-6.0.5
Bump vite from 6.0.3 to 6.0.5
2024-12-23 07:01:29 +01:00
James Cole
3c65b46aa5 Merge branch 'v6.2' of github.com:firefly-iii/firefly-iii into v6.2
# Conflicts:
#	app/Support/Steam.php
2024-12-23 06:56:31 +01:00
James Cole
1cf9c76329 Fix array bug. 2024-12-23 06:55:14 +01:00
dependabot[bot]
495f5c71c3 Bump vite from 6.0.3 to 6.0.5
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.0.3 to 6.0.5.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.0.5/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-23 03:12:47 +00:00
dependabot[bot]
7e80f607b7 Bump i18next from 24.1.2 to 24.2.0
Bumps [i18next](https://github.com/i18next/i18next) from 24.1.2 to 24.2.0.
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v24.1.2...v24.2.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-23 03:12:31 +00:00
github-actions
d93732e451 Auto commit for release 'develop' on 2024-12-23 2024-12-23 04:12:14 +01:00
dependabot[bot]
1b57bc7889 Bump phpunit/phpunit from 10.5.39 to 10.5.40
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 10.5.39 to 10.5.40.
- [Release notes](https://github.com/sebastianbergmann/phpunit/releases)
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/10.5.40/ChangeLog-10.5.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/10.5.39...10.5.40)

---
updated-dependencies:
- dependency-name: phpunit/phpunit
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-23 03:01:52 +00:00
github-actions
c0499df4ec Auto commit for release 'branch-v6.2' on 2024-12-22 2024-12-22 20:37:54 +01:00
James Cole
d90ac519f7 Clean up balance methods. 2024-12-22 20:32:58 +01:00
James Cole
a0e92b6969 Clean up variety of account balance methods. 2024-12-22 19:42:06 +01:00
James Cole
df49dd23e2 Try to convert balance to native, still internal debates. 2024-12-22 16:41:55 +01:00
James Cole
d4525da6bc Merge branch 'v6.2' of github.com:firefly-iii/firefly-iii into v6.2 2024-12-22 15:54:06 +01:00
James Cole
25b11bd20b Add preference for native amounts. 2024-12-22 15:53:59 +01:00
TasneemTantawy
9e373a9b0d object group controller test 2024-12-22 16:29:56 +03:00
github-actions
705aac419a Auto commit for release 'branch-v6.2' on 2024-12-22 2024-12-22 14:00:37 +01:00
TasneemTantawy
4fb61646b4 currency controller test 2024-12-22 15:54:18 +03:00
James Cole
f6e642f72e Add and remove exchange rates 2024-12-22 13:19:23 +01:00
James Cole
565bd87959 Code cleanup 2024-12-22 08:43:12 +01:00
James Cole
5751f7e5a3 Merge branch 'v6.2' of github.com:firefly-iii/firefly-iii into v6.2
# Conflicts:
#	app/Api/V2/Controllers/Model/ExchangeRate/ShowController.php
#	app/Repositories/UserGroups/ExchangeRate/ExchangeRateRepository.php
#	routes/api.php
2024-12-22 08:28:44 +01:00
James Cole
f5a755d4fc Various changes 2024-12-22 08:27:01 +01:00
github-actions
a500de8ab1 Auto commit for release 'branch-v6.2' on 2024-12-22 2024-12-22 07:05:15 +01:00
James Cole
303548a5fe Clean up command. 2024-12-22 07:01:16 +01:00
James Cole
68de905698 Remove command. 2024-12-22 06:59:05 +01:00
James Cole
9240b9868b Optimize memory usage. 2024-12-22 06:55:07 +01:00
James Cole
0e2e155cc6 Expand notifications. 2024-12-22 06:44:01 +01:00
James Cole
bffa0088b4 Extend warning with IP + host etc. 2024-12-22 06:33:37 +01:00
James Cole
2e993857e8 APIs and views for exchange rates. 2024-12-22 06:24:45 +01:00
James Cole
117a376fc3 Expand page for currency exchange rates. 2024-12-21 21:31:28 +01:00
James Cole
1daffedde0 First page for currency exchange rates. 2024-12-21 21:01:03 +01:00
James Cole
0e8fdd76a6 Index for exchange rates. 2024-12-21 18:35:05 +01:00
James Cole
7ff4f29bcb Merge branch 'v6.2' of github.com:firefly-iii/firefly-iii into v6.2 2024-12-21 12:51:52 +01:00
James Cole
9e4cff2b23 Add a little debug, less massive recalculations. 2024-12-21 12:51:40 +01:00
github-actions
4aaea89f2c Auto commit for release 'branch-v6.2' on 2024-12-21 2024-12-21 12:27:07 +01:00
James Cole
4fbf7b38fb Do not pull in invalid transactions 2024-12-21 11:40:34 +01:00
James Cole
76075401f9 Recalculate amounts. 2024-12-21 11:33:58 +01:00
James Cole
e2a20dd63d Command to recalculate foreign amounts. 2024-12-21 11:20:48 +01:00
James Cole
b52a1f3eb1 Respond to currency changes. 2024-12-21 07:12:11 +01:00
James Cole
7fd5a88122 Add more column conversions. 2024-12-20 05:31:16 +01:00
James Cole
1a1baa5cda Add observers for amounts. 2024-12-20 05:20:37 +01:00
James Cole
577d671a0c Add native amount column 2024-12-19 06:21:17 +01:00
James Cole
380029ffd8 Fix missing method. 2024-12-18 16:57:11 +01:00
github-actions
e2f1fc307f Auto commit for release 'develop' on 2024-12-18 2024-12-18 16:52:40 +01:00
github-actions
76cc27a267 Auto commit for release 'branch-v6.2' on 2024-12-18 2024-12-18 16:45:41 +01:00
James Cole
e8a6f30e4e Merge branch 'develop' into v6.2
# Conflicts:
#	composer.lock
#	config/firefly.php
#	package-lock.json
2024-12-18 16:39:22 +01:00
github-actions
fe6021a3d6 Auto commit for release 'v6.1.25' on 2024-12-18 2024-12-18 16:36:08 +01:00
James Cole
563c54702b Update changelog. 2024-12-18 16:31:37 +01:00
James Cole
4d67d27ba0 Fix #9546 2024-12-18 16:29:19 +01:00
James Cole
edf3876a57 Merge branch 'main' into develop 2024-12-18 16:26:35 +01:00
James Cole
2d10f255c2 Fix reference to old method. 2024-12-18 16:18:06 +01:00
James Cole
ee76cc6761 Fix methods 2024-12-18 16:13:32 +01:00
James Cole
f197e6623b Merge pull request #9551 from firefly-iii/dependabot/github_actions/github/command-1.3.0 2024-12-16 06:59:19 +01:00
James Cole
42a9809450 Merge pull request #9550 from firefly-iii/dependabot/npm_and_yarn/develop/chartjs-chart-sankey-0.14.0 2024-12-16 06:59:10 +01:00
James Cole
444f80a933 Merge pull request #9549 from firefly-iii/dependabot/npm_and_yarn/develop/ag-grid-community/styles-33.0.2 2024-12-16 06:59:01 +01:00
dependabot[bot]
4b985c818a Bump github/command from 1.2.2 to 1.3.0
Bumps [github/command](https://github.com/github/command) from 1.2.2 to 1.3.0.
- [Release notes](https://github.com/github/command/releases)
- [Commits](https://github.com/github/command/compare/v1.2.2...v1.3.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-16 03:49:31 +00:00
github-actions
2e62fe7b72 Auto commit for release 'develop' on 2024-12-16 2024-12-16 04:22:19 +01:00
dependabot[bot]
ccd182aed9 Bump chartjs-chart-sankey from 0.13.0 to 0.14.0
Bumps [chartjs-chart-sankey](https://github.com/kurkle/chartjs-chart-sankey) from 0.13.0 to 0.14.0.
- [Release notes](https://github.com/kurkle/chartjs-chart-sankey/releases)
- [Commits](https://github.com/kurkle/chartjs-chart-sankey/compare/v0.13.0...v0.14.0)

---
updated-dependencies:
- dependency-name: chartjs-chart-sankey
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-16 03:06:22 +00:00
dependabot[bot]
615eef3fdd Bump @ag-grid-community/styles from 32.3.3 to 33.0.2
Bumps [@ag-grid-community/styles](https://github.com/ag-grid/ag-grid) from 32.3.3 to 33.0.2.
- [Release notes](https://github.com/ag-grid/ag-grid/releases)
- [Commits](https://github.com/ag-grid/ag-grid/compare/v32.3.3...v33.0.2)

---
updated-dependencies:
- dependency-name: "@ag-grid-community/styles"
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-16 03:06:13 +00:00
James Cole
d4e4907363 Add option for manual activation. 2024-12-15 19:59:36 +01:00
James Cole
c205e93876 Fix https://github.com/firefly-iii/firefly-iii/issues/7288 2024-12-15 19:51:46 +01:00
James Cole
3b24bb99bb Merge branch 'v6.2' of github.com:firefly-iii/firefly-iii into v6.2 2024-12-15 19:51:37 +01:00
James Cole
2814cd1b2a Better name 2024-12-15 19:51:30 +01:00
github-actions
5285e1ac14 Auto commit for release 'branch-v6.2' on 2024-12-15 2024-12-15 16:16:13 +01:00
James Cole
48a999cf91 Fix old reference. 2024-12-15 16:11:48 +01:00
James Cole
3117c8846e Rename branch release. 2024-12-15 12:31:36 +01:00
github-actions
6bb297e76f Auto commit for release 'branch-v6.2' on 2024-12-15 2024-12-15 10:32:00 +01:00
James Cole
bc698f67ea Merge branch 'main' into v6.2 2024-12-15 09:07:04 +01:00
James Cole
f1c859aaa3 Update build job 2024-12-15 08:57:55 +01:00
James Cole
2d0aa207d4 Fix various piggy bank errors 2024-12-15 08:50:57 +01:00
James Cole
4a75e9c262 Merge branch 'v6.2' of github.com:firefly-iii/firefly-iii into v6.2 2024-12-15 08:20:52 +01:00
James Cole
ee7c4b8863 Fix user test notification. 2024-12-15 08:20:42 +01:00
github-actions
53cce6510c Auto commit for release 'branch-v6.2' on 2024-12-14 2024-12-14 22:20:13 +01:00
James Cole
8f3cf38f77 Remove exception because it breaks the upgrade. 2024-12-14 22:12:56 +01:00
James Cole
f33766a062 Make column nullable so migration does not fail. 2024-12-14 22:06:53 +01:00
James Cole
ac5e62c65d Merge branch 'main' into v6.2 2024-12-14 21:56:26 +01:00
github-actions
e2289ce1e6 Auto commit for release 'branch-v6.2' on 2024-12-14 2024-12-14 21:55:42 +01:00
James Cole
f0e2913802 Ignore phpcs errors. 2024-12-14 21:50:46 +01:00
James Cole
1fa928b98f Should work from here 2024-12-14 21:45:20 +01:00
James Cole
1c691cca33 Duh, that wasn't smart. 2024-12-14 21:39:30 +01:00
James Cole
69e1eb3eff echo debug and upgrade to 8.4 2024-12-14 21:37:45 +01:00
James Cole
90794cb515 Experimental branch build. 2024-12-14 21:35:14 +01:00
James Cole
28d7e24d30 Fix piggy bank orders 2024-12-14 20:16:08 +01:00
James Cole
6a62f781e9 Multi account piggy banks. 2024-12-14 17:32:03 +01:00
James Cole
fb6c67fa04 Fix https://github.com/firefly-iii/firefly-iii/issues/9532 2024-12-14 08:10:58 +01:00
James Cole
03e9e3dbdb Expand all notifications. 2024-12-14 08:03:18 +01:00
James Cole
5520992861 Clean up and fix notifications. 2024-12-14 07:52:02 +01:00
James Cole
5f1502eea7 Clean up code. 2024-12-14 07:22:46 +01:00
James Cole
b3560ff525 Clean up notifications 2024-12-14 07:13:01 +01:00
James Cole
8030167ffc Clean up notifications, fix first user notification. 2024-12-14 07:05:08 +01:00
James Cole
fd2c1615cf Start cleaning up notifications. 2024-12-14 06:57:57 +01:00
James Cole
b976239580 Fix all test channels for user and owner. 2024-12-14 06:30:27 +01:00
James Cole
7d8d773f8f Clean up some code. 2024-12-14 05:45:54 +01:00
James Cole
b930ad4da7 Update code and packages 2024-12-14 05:43:13 +01:00
James Cole
abad7cdf16 Update packages and notification settings 2024-12-14 05:39:55 +01:00
James Cole
0e5eb036b0 Unknown user warning. 2024-12-12 07:09:17 +01:00
James Cole
d995bfc081 Update all owner events so they support all channels 2024-12-12 06:33:48 +01:00
James Cole
c920070ce2 Expand settings for notifications. 2024-12-11 07:23:46 +01:00
James Cole
277f5e538f Merge pull request #9534 from firefly-iii/dependabot/composer/composer-736964bd2b 2024-12-10 04:33:36 +01:00
dependabot[bot]
89f197b9d4 Bump league/commonmark in the composer group across 1 directory
Bumps the composer group with 1 update in the / directory: [league/commonmark](https://github.com/thephpleague/commonmark).


Updates `league/commonmark` from 2.5.3 to 2.6.0
- [Release notes](https://github.com/thephpleague/commonmark/releases)
- [Changelog](https://github.com/thephpleague/commonmark/blob/2.6/CHANGELOG.md)
- [Commits](https://github.com/thephpleague/commonmark/compare/2.5.3...2.6.0)

---
updated-dependencies:
- dependency-name: league/commonmark
  dependency-type: direct:production
  dependency-group: composer
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-10 01:17:43 +00:00
James Cole
c35ff3174a Add support for Pushover 2024-12-09 07:34:01 +01:00
James Cole
94085ee940 Add config for ntfy 2024-12-09 06:27:37 +01:00
James Cole
c841fa3620 Remove references to discord. 2024-12-09 06:00:43 +01:00
James Cole
2f7a1c941e Expand test notification framework. 2024-12-08 16:28:22 +01:00
James Cole
c06fb8daf6 Expand notifications settings. 2024-12-07 09:41:09 +01:00
James Cole
26948a058a Expand UI for notifications. 2024-12-07 08:05:51 +01:00
James Cole
1220564f30 Fix creating piggies 2024-12-07 08:05:29 +01:00
James Cole
ea4be9dd0c Expand forms and improve validation for multi-account piggy banks 2024-12-06 08:10:31 +01:00
James Cole
4819b5ac5d More code for multi account piggy banks. 2024-12-04 06:38:47 +01:00
James Cole
d740814f88 API works for multi-account piggies, the rest throws an exception 2024-12-01 18:32:05 +01:00
James Cole
cdf1ebf3f7 Better ability to store piggy banks. 2024-12-01 18:16:48 +01:00
James Cole
f2fab5d4ee Update code for piggy banks. 2024-12-01 06:48:15 +01:00
James Cole
21a6927279 Rename fields for piggy bank 2024-11-30 16:02:30 +01:00
James Cole
92190bbc54 Rename fields in piggy bank. 2024-11-30 15:57:11 +01:00
James Cole
9ad005e31f Add edit button for notes https://github.com/firefly-iii/firefly-iii/issues/5523 2024-11-30 06:19:21 +01:00
James Cole
f5c56e02da API allows update/set of budget limit notes. https://github.com/firefly-iii/firefly-iii/issues/5523 2024-11-30 05:42:59 +01:00
James Cole
c25c0d37c5 Replace constants with enums. 2024-11-27 08:08:52 +01:00
James Cole
4ba1c5bcfc New set of PHP 8.4 files 2024-11-26 18:04:32 +01:00
978 changed files with 22969 additions and 17774 deletions

View File

@@ -29,7 +29,7 @@ $paths = [
$current . '/../../database',
$current . '/../../routes',
$current . '/../../tests',
$current . '/../../resources/lang',
$current . '/../../resources/lang/en_US',
];
$finder = PhpCsFixer\Finder::create()
@@ -61,6 +61,7 @@ return $config->setRules(
'comment_to_phpdoc' => false, // breaks phpstan lines in combination with PHPStorm.
'type_declaration_spaces' => false,
'cast_spaces' => false,
'phpdoc_to_comment' => false, // do not overrule single line comment style, breaks phpstan.
// complex rules
'array_syntax' => ['syntax' => 'short'],

View File

@@ -97,13 +97,13 @@
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.x-dev"
},
"phpstan": {
"includes": [
"extension.neon"
]
},
"branch-alias": {
"dev-main": "3.x-dev"
}
},
"autoload": {
@@ -406,16 +406,16 @@
},
{
"name": "friendsofphp/php-cs-fixer",
"version": "v3.65.0",
"version": "v3.66.1",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "79d4f3e77b250a7d8043d76c6af8f0695e8a469f"
"reference": "cde186799d8e92960c5a00c96e6214bf7f5547a9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/79d4f3e77b250a7d8043d76c6af8f0695e8a469f",
"reference": "79d4f3e77b250a7d8043d76c6af8f0695e8a469f",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/cde186799d8e92960c5a00c96e6214bf7f5547a9",
"reference": "cde186799d8e92960c5a00c96e6214bf7f5547a9",
"shasum": ""
},
"require": {
@@ -432,17 +432,17 @@
"react/promise": "^2.0 || ^3.0",
"react/socket": "^1.0",
"react/stream": "^1.0",
"sebastian/diff": "^4.0 || ^5.0 || ^6.0",
"symfony/console": "^5.4 || ^6.0 || ^7.0",
"symfony/event-dispatcher": "^5.4 || ^6.0 || ^7.0",
"symfony/filesystem": "^5.4 || ^6.0 || ^7.0",
"symfony/finder": "^5.4 || ^6.0 || ^7.0",
"symfony/options-resolver": "^5.4 || ^6.0 || ^7.0",
"symfony/polyfill-mbstring": "^1.28",
"symfony/polyfill-php80": "^1.28",
"symfony/polyfill-php81": "^1.28",
"symfony/process": "^5.4 || ^6.0 || ^7.0",
"symfony/stopwatch": "^5.4 || ^6.0 || ^7.0"
"sebastian/diff": "^4.0 || ^5.1 || ^6.0",
"symfony/console": "^5.4 || ^6.4 || ^7.0",
"symfony/event-dispatcher": "^5.4 || ^6.4 || ^7.0",
"symfony/filesystem": "^5.4 || ^6.4 || ^7.0",
"symfony/finder": "^5.4 || ^6.4 || ^7.0",
"symfony/options-resolver": "^5.4 || ^6.4 || ^7.0",
"symfony/polyfill-mbstring": "^1.31",
"symfony/polyfill-php80": "^1.31",
"symfony/polyfill-php81": "^1.31",
"symfony/process": "^5.4 || ^6.4 || ^7.2",
"symfony/stopwatch": "^5.4 || ^6.4 || ^7.0"
},
"require-dev": {
"facile-it/paraunit": "^1.3.1 || ^2.4",
@@ -454,9 +454,9 @@
"php-cs-fixer/accessible-object": "^1.1",
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.5",
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.5",
"phpunit/phpunit": "^9.6.21 || ^10.5.38 || ^11.4.3",
"symfony/var-dumper": "^5.4.47 || ^6.4.15 || ^7.1.8",
"symfony/yaml": "^5.4.45 || ^6.4.13 || ^7.1.6"
"phpunit/phpunit": "^9.6.22 || ^10.5.40 || ^11.5.2",
"symfony/var-dumper": "^5.4.48 || ^6.4.15 || ^7.2.0",
"symfony/yaml": "^5.4.45 || ^6.4.13 || ^7.2.0"
},
"suggest": {
"ext-dom": "For handling output formats in XML",
@@ -497,7 +497,7 @@
],
"support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.65.0"
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.66.1"
},
"funding": [
{
@@ -505,7 +505,7 @@
"type": "github"
}
],
"time": "2024-11-25T00:39:24+00:00"
"time": "2025-01-05T14:43:25+00:00"
},
{
"name": "psr/container",
@@ -734,33 +734,33 @@
},
{
"name": "react/child-process",
"version": "v0.6.5",
"version": "v0.6.6",
"source": {
"type": "git",
"url": "https://github.com/reactphp/child-process.git",
"reference": "e71eb1aa55f057c7a4a0d08d06b0b0a484bead43"
"reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/reactphp/child-process/zipball/e71eb1aa55f057c7a4a0d08d06b0b0a484bead43",
"reference": "e71eb1aa55f057c7a4a0d08d06b0b0a484bead43",
"url": "https://api.github.com/repos/reactphp/child-process/zipball/1721e2b93d89b745664353b9cfc8f155ba8a6159",
"reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159",
"shasum": ""
},
"require": {
"evenement/evenement": "^3.0 || ^2.0 || ^1.0",
"php": ">=5.3.0",
"react/event-loop": "^1.2",
"react/stream": "^1.2"
"react/stream": "^1.4"
},
"require-dev": {
"phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35",
"react/socket": "^1.8",
"phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36",
"react/socket": "^1.16",
"sebastian/environment": "^5.0 || ^3.0 || ^2.0 || ^1.0"
},
"type": "library",
"autoload": {
"psr-4": {
"React\\ChildProcess\\": "src"
"React\\ChildProcess\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -797,19 +797,15 @@
],
"support": {
"issues": "https://github.com/reactphp/child-process/issues",
"source": "https://github.com/reactphp/child-process/tree/v0.6.5"
"source": "https://github.com/reactphp/child-process/tree/v0.6.6"
},
"funding": [
{
"url": "https://github.com/WyriHaximus",
"type": "github"
},
{
"url": "https://github.com/clue",
"type": "github"
"url": "https://opencollective.com/reactphp",
"type": "open_collective"
}
],
"time": "2022-09-16T13:41:56+00:00"
"time": "2025-01-01T16:37:48+00:00"
},
{
"name": "react/dns",
@@ -1369,12 +1365,12 @@
},
"type": "library",
"extra": {
"thanks": {
"url": "https://github.com/symfony/contracts",
"name": "symfony/contracts"
},
"branch-alias": {
"dev-main": "3.5-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
@@ -1517,12 +1513,12 @@
},
"type": "library",
"extra": {
"thanks": {
"url": "https://github.com/symfony/contracts",
"name": "symfony/contracts"
},
"branch-alias": {
"dev-main": "3.5-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
@@ -1641,16 +1637,16 @@
},
{
"name": "symfony/finder",
"version": "v7.2.0",
"version": "v7.2.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "6de263e5868b9a137602dd1e33e4d48bfae99c49"
"reference": "87a71856f2f56e4100373e92529eed3171695cfb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/6de263e5868b9a137602dd1e33e4d48bfae99c49",
"reference": "6de263e5868b9a137602dd1e33e4d48bfae99c49",
"url": "https://api.github.com/repos/symfony/finder/zipball/87a71856f2f56e4100373e92529eed3171695cfb",
"reference": "87a71856f2f56e4100373e92529eed3171695cfb",
"shasum": ""
},
"require": {
@@ -1685,7 +1681,7 @@
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/finder/tree/v7.2.0"
"source": "https://github.com/symfony/finder/tree/v7.2.2"
},
"funding": [
{
@@ -1701,7 +1697,7 @@
"type": "tidelift"
}
],
"time": "2024-10-23T06:56:12+00:00"
"time": "2024-12-30T19:00:17+00:00"
},
{
"name": "symfony/options-resolver",
@@ -2329,12 +2325,12 @@
},
"type": "library",
"extra": {
"thanks": {
"url": "https://github.com/symfony/contracts",
"name": "symfony/contracts"
},
"branch-alias": {
"dev-main": "3.5-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
@@ -2390,16 +2386,16 @@
},
{
"name": "symfony/stopwatch",
"version": "v7.2.0",
"version": "v7.2.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/stopwatch.git",
"reference": "696f418b0d722a4225e1c3d95489d262971ca924"
"reference": "e46690d5b9d7164a6d061cab1e8d46141b9f49df"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/696f418b0d722a4225e1c3d95489d262971ca924",
"reference": "696f418b0d722a4225e1c3d95489d262971ca924",
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/e46690d5b9d7164a6d061cab1e8d46141b9f49df",
"reference": "e46690d5b9d7164a6d061cab1e8d46141b9f49df",
"shasum": ""
},
"require": {
@@ -2432,7 +2428,7 @@
"description": "Provides a way to profile code",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/stopwatch/tree/v7.2.0"
"source": "https://github.com/symfony/stopwatch/tree/v7.2.2"
},
"funding": [
{
@@ -2448,7 +2444,7 @@
"type": "tidelift"
}
],
"time": "2024-09-25T14:21:43+00:00"
"time": "2024-12-18T14:28:33+00:00"
},
{
"name": "symfony/string",

View File

@@ -26,10 +26,9 @@ SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
cd $SCRIPT_DIR/php-cs-fixer
composer update --quiet
rm -f .php-cs-fixer.cache
PHP_CS_FIXER_IGNORE_ENV=true
./vendor/bin/php-cs-fixer fix \
PHP_CS_FIXER_IGNORE_ENV=true ./vendor/bin/php-cs-fixer fix \
--config $SCRIPT_DIR/php-cs-fixer/.php-cs-fixer.php \
--format=txt \
--format=txt -v \
--allow-risky=yes
EXIT_CODE=$?

View File

@@ -1,61 +1,76 @@
parameters:
scanFiles:
- ../_ide_helper_models.php
universalObjectCratesClasses:
- Illuminate\Database\Eloquent\Model
# TODO: slowly remove these parameters and fix the issues found.
reportUnmatchedIgnoredErrors: false
ignoreErrors:
# TODO: slowly remove these exceptions and fix the issues found.
- '#Dynamic call to static method#' # all the Laravel ORM things depend on this.
- '#Control structures using switch should not be used.#' # switch is fine in some cases.
- '#with no value type specified in iterable type array#' # remove this rule when all other issues are solved.
- '#has no value type specified in iterable type array#' # remove this rule when all other issues are solved.
- '#is not allowed to extend#'
- '#does not specify its types#'
- '#switch is forbidden to use#'
- '#is neither abstract nor final#'
- '#on left side of \?\?\= always exists and is not nullable#'
- '#has a nullable return type declaration#' # perhaps throw errors instead?
- '#with a nullable type declaration#' # decide what action should be if param is null.
- '#with null as default value#'
-
message: '#Constructor in [a-zA-Z0-9\\_]+ has parameter \$[a-zA-Z0-9\\_]+ with default value#'
paths:
- ../app/Exceptions/IntervalException.php
- ../app/Support/Navigation.php
-
message: '#but containers should not be injected#'
paths:
- ../app/Support/Authentication/RemoteUserGuard.php
-
message: '#Function compact\(\) should not be used#' # too useful in template rendering.
paths:
- ../app/Generator/Report/Account/MonthReportGenerator.php
- ../app/Generator/Report/Audit/MonthReportGenerator.php
- ../app/Generator/Report/Budget/MonthReportGenerator.php
- ../app/Generator/Report/Category/MonthReportGenerator.php
- ../app/Generator/Report/Standard/MonthReportGenerator.php
- ../app/Generator/Report/Standard/MultiYearReportGenerator.php
- ../app/Generator/Report/Standard/YearReportGenerator.php
- ../app/Generator/Report/Tag/MonthReportGenerator.php
- ../app/Http/Controllers/Account/*.php
- ../app/Http/Controllers/Admin/*.php
- ../app/Http/Controllers/*.php
- ../app/Support/ExpandedForm.php
- ../app/Support/Form/AccountForm.php
- ../app/Support/Form/CurrencyForm.php
- ../app/Support/Form/FormSupport.php
-
message: '#Either catch a more specific exception#'
paths:
- ../app/Support/Form/FormSupport.php
- ../_ide_helper
paths:
- ../app
- ../database
- ../routes
- ../config
- ../bootstrap/app.php
universalObjectCratesClasses:
- Illuminate\Database\Eloquent\Model
# TODO: slowly remove these parameters and fix the issues found.
reportUnmatchedIgnoredErrors: true
ignoreErrors:
# TODO: slowly remove these exceptions and fix the issues found.
- '#Dynamic call to static method#' # all the Laravel ORM things depend on this.
- identifier: varTag.nativeType
- identifier: varTag.type
- identifier: missingType.iterableValue # not interesting enough to fix.
- identifier: missingType.generics # not interesting enough to fix.
- "#Parameter \\#[1-2] \\$num[1-2] of function bc[a-z]+ expects numeric-string, [a-z\\-|&]+ given#"
- '#expects view-string, string given#'
- '#expects view-string\|null, string given#'
# phpstan can't handle this so we ignore them.
- '#Call to an undefined method Illuminate\\Database\\Eloquent\\Relations\\HasMany::before#'
- '#Call to an undefined method Illuminate\\Database\\Eloquent\\Relations\\HasMany::after#'
- '#Call to an undefined method Illuminate\\Database\\Eloquent\\Relations\\HasMany::withTrashed#'
- '#Call to an undefined method Illuminate\\Database\\Eloquent\\Relations\\HasMany::accountTypeIn#'
- '#Call to an undefined method Illuminate\\Database\\Eloquent\\Relations\\BelongsTo::withTrashed#'
# - '#Control structures using switch should not be used.#' # switch is fine in some cases.
# - '#with no value type specified in iterable type array#' # remove this rule when all other issues are solved.
# - '#has no value type specified in iterable type array#' # remove this rule when all other issues are solved.
# - '#is not allowed to extend#'
# - '#does not specify its types#'
# - '#switch is forbidden to use#'
# - '#is neither abstract nor final#'
# - '#on left side of \?\?\= always exists and is not nullable#'
# - '#has a nullable return type declaration#' # perhaps throw errors instead?
# - '#with a nullable type declaration#' # decide what action should be if param is null.
# - '#with null as default value#'
# -
# message: '#Constructor in [a-zA-Z0-9\\_]+ has parameter \$[a-zA-Z0-9\\_]+ with default value#'
# paths:
# - ../app/Exceptions/IntervalException.php
# - ../app/Support/Navigation.php
# -
# message: '#but containers should not be injected#'
# paths:
# - ../app/Support/Authentication/RemoteUserGuard.php
# -
# message: '#Function compact\(\) should not be used#' # too useful in template rendering.
# paths:
# - ../app/Generator/Report/Account/MonthReportGenerator.php
# - ../app/Generator/Report/Audit/MonthReportGenerator.php
# - ../app/Generator/Report/Budget/MonthReportGenerator.php
# - ../app/Generator/Report/Category/MonthReportGenerator.php
# - ../app/Generator/Report/Standard/MonthReportGenerator.php
# - ../app/Generator/Report/Standard/MultiYearReportGenerator.php
# - ../app/Generator/Report/Standard/YearReportGenerator.php
# - ../app/Generator/Report/Tag/MonthReportGenerator.php
# - ../app/Http/Controllers/Account/*.php
# - ../app/Http/Controllers/Admin/*.php
# - ../app/Http/Controllers/*.php
# - ../app/Support/ExpandedForm.php
# - ../app/Support/Form/AccountForm.php
# - ../app/Support/Form/CurrencyForm.php
# - ../app/Support/Form/FormSupport.php
# -
# message: '#Either catch a more specific exception#'
# paths:
# - ../app/Support/Form/FormSupport.php
# The level 8 is the highest level. original was 5
# 7 is more than enough, higher just leaves NULL things.

View File

@@ -325,6 +325,12 @@ USE_RUNNING_BALANCE=false
#
FIREFLY_III_LAYOUT=v1
#
# Which Query Parser implementation to use for the search rngine and rules
# 'new' is experimental, 'legacy' is the classic one
#
QUERY_PARSER_IMPLEMENTATION=legacy
#
# Please make sure this URL matches the external URL of your Firefly III installation.
# It is used to validate specific requests and to generate URLs in emails.

53
.github/mergify.yml vendored
View File

@@ -8,56 +8,3 @@ pull_request_rules:
close:
message: Please do not open PR's on the `main` branch, but on the `develop`
branch only. Thank you!
- name: No translations
conditions:
- -author~=^dependabot(|-preview)\[bot\]$
- base=develop
- or:
- files~=^resources/lang/bg_BG
- files~=^resources/lang/ca_ES
- files~=^resources/lang/cs_CZ
- files~=^resources/lang/da_DK
- files~=^resources/lang/de_DE
- files~=^resources/lang/el_GR
- files~=^resources/lang/en_GB
- files~=^resources/lang/es_ES
- files~=^resources/lang/et_EE
- files~=^resources/lang/fa_IR
- files~=^resources/lang/fi_FI
- files~=^resources/lang/fr_FR
- files~=^resources/lang/he_IL
- files~=^resources/lang/hu_HU
- files~=^resources/lang/id_ID
- files~=^resources/lang/is_IS
- files~=^resources/lang/it_IT
- files~=^resources/lang/ja_JP
- files~=^resources/lang/ko_KR
- files~=^resources/lang/lt_LT
- files~=^resources/lang/nb_NO
- files~=^resources/lang/nl_NL
- files~=^resources/lang/pl_PL
- files~=^resources/lang/pt_BR
- files~=^resources/lang/pt_PT
- files~=^resources/lang/ro_RO
- files~=^resources/lang/ru_RU
- files~=^resources/lang/si_LK
- files~=^resources/lang/sk_SK
- files~=^resources/lang/sl_SI
- files~=^resources/lang/sr_CS
- files~=^resources/lang/sv_SE
- files~=^resources/lang/th_TH
- files~=^resources/lang/tlh_AA
- files~=^resources/lang/tr_TR
- files~=^resources/lang/uk_UA
- files~=^resources/lang/vi_VN
- files~=^resources/lang/zh_CN
- files~=^resources/lang/zh_TW
actions:
comment:
message: >
Please do not submit translated strings in your PR. If you need new
sentences to be translated, add them to the `en_US` language strings.
New or changed translations for other languages can be submitted at
https://crowdin.com/project/firefly-iii
Thank you!

View File

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

View File

@@ -4,9 +4,13 @@ on:
workflow_dispatch:
inputs:
version:
description: 'Release "v1.2.3" or "develop"'
description: 'Release "v1.2.3" or "develop" or "branch-abc"'
required: true
default: 'develop'
phpversion:
description: 'PHP version'
required: true
default: '8.4'
schedule:
- cron: '0 3 * * MON'
@@ -23,6 +27,11 @@ jobs:
if [[ "develop" == "$version" ]]; then
git checkout --track origin/develop
git pull
elif [[ "$version" == branch* ]]; then
PULLBRANCH=${version:7}
echo "The branch is '$PULLBRANCH' ($version)"
git checkout --track origin/$PULLBRANCH
git pull
else
git config user.name github-actions
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
@@ -36,7 +45,7 @@ jobs:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
php-version: ${{ github.event.inputs.phpversion }}
extensions: mbstring, intl, zip, bcmath
- name: crowdin action
uses: crowdin/github-action@v2
@@ -49,15 +58,6 @@ jobs:
GITHUB_TOKEN: ${{ github.token }}
CROWDIN_PROJECT_NR: ${{ secrets.CROWDIN_PROJECT_NR }}
CROWDIN_TOKEN: ${{ secrets.CROWDIN_TOKEN }}
- name: Cleanup translations
id: cleanup-transactions
uses: JC5/firefly-iii-dev@main
with:
action: 'ff3:crowdin-warning'
output: ''
env:
FIREFLY_III_ROOT: /github/workspace
GH_TOKEN: ''
- name: Cleanup changelog
id: cleanup-changelog
uses: JC5/firefly-iii-dev@main
@@ -133,7 +133,7 @@ jobs:
rm -rf vendor composer.lock
composer update --no-dev --no-scripts --no-plugins -q
sudo chown -R runner:docker resources/lang
.ci/phpcs.sh
.ci/phpcs.sh || true
- name: Import GPG key
uses: crazy-max/ghaction-import-gpg@v6
with:
@@ -159,13 +159,23 @@ jobs:
# if this is a develop build, slightly different variable names.
if [[ "develop" == "$version" ]]; then
[[ -z $(git status --untracked-files=normal --porcelain) ]] && echo "this branch is clean, no need to push..." && exit 0;
#[[ -z $(git status --untracked-files=normal --porcelain) ]] && echo "this branch is clean, no need to push..." && exit 0;
releaseName=$version-$(date +'%Y%m%d')
originalName=$releaseName
zipName=FireflyIII-develop.zip
tarName=FireflyIII-develop.tar.gz
fi
# if this is a branch build, also slightly different variable names.
if [[ "$version" == branch* ]]; then
#[[ -z $(git status --untracked-files=normal --porcelain) ]] && echo "this branch is clean, no need to push..." && exit 0;
# branch builds overrule develop
releaseName=$version-$(date +'%Y%m%d')
originalName=$releaseName
zipName=FireflyIII-$version.zip
tarName=FireflyIII-$version.tar.gz
fi
# in both cases, if the release or tag already exists, add ".1" until it no longer exists.
tagFound=true
tagCount=1
@@ -207,12 +217,13 @@ jobs:
gpg --armor --detach-sign $zipName
gpg --armor --detach-sign $tarName
# create a development (nightly) release:
# describe the development release.
if [[ "develop" == "$version" ]]; then
echo 'Develop release.'
# add text to output.txt (instructions)
rm output.txt
echo "Bi-weekly development release of Firefly III with the latest fixes, translations and features. Docker users can find this release under the \`develop\` tag." >> output.txt
rm -f output.txt
touch output.txt
sudo chown -R runner:docker output.txt
echo "Weekly development release of Firefly III with the latest fixes, translations and features. Docker users can find this release under the \`develop\` tag." >> output.txt
echo "" >> output.txt
echo "This release was created on **$(date +'%Y-%m-%d')** and may contain unexpected bugs. Data loss is rare but is not impossible. The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
echo "" >> output.txt
@@ -220,15 +231,100 @@ jobs:
echo "* Or read the upgrade instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/docker/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/self-managed/)" >> output.txt
echo "" >> output.txt
echo ":warning: Please be careful with this pre-release, as it may not work as expected." >> output.txt
fi
# describe a branch release
if [[ "$version" == branch* ]]; then
echo 'Branch release.'
rm -f output.txt
touch output.txt
sudo chown -R runner:docker output.txt
echo "Irregular BRANCH release of Firefly III. This release contains specific features or changes. Docker users can find this release under the \`$version\` tag." >> output.txt
echo "" >> output.txt
echo "This release was created on **$(date +'%Y-%m-%d')** and may contain unexpected bugs. Data loss is rare but is not impossible. The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
echo "" >> output.txt
echo "* Please read the installation instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/installation/docker/), [Portainer](https://docs.firefly-iii.org/how-to/firefly-iii/installation/portainer/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/installation/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/installation/self-managed/)" >> output.txt
echo "* Or read the upgrade instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/docker/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/self-managed/)" >> output.txt
echo "" >> output.txt
echo ":warning: Please be careful with this branch pre-release, as it may not work as expected." >> output.txt
fi
# describe the main release
if [[ "develop" != "$version" ]] && [[ "$version" != branch* ]] && [[ "$version" != *alpha* ]] && [[ "$version" != *beta* ]]; then
echo 'Main release.'
sudo chown -R runner:docker output.txt
echo '' >> output.txt
echo '### Instructions' >> output.txt
echo '' >> output.txt
echo "* Installation instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/installation/docker/), [Portainer](https://docs.firefly-iii.org/how-to/firefly-iii/installation/portainer/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/installation/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/installation/self-managed/)" >> output.txt
echo "* Or read the upgrade instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/docker/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/self-managed/)" >> output.txt
echo "* The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
fi
# describe alpha release
if [[ "$version" == *alpha* ]]; then
echo 'ALPHA release.'
rm -f output.txt
touch output.txt
sudo chown -R runner:docker output.txt
echo "Very early ALPHA release of Firefly III. This release contains specific features or changes. Docker users can find this release under the \`$version\` tag." >> output.txt
echo '' >> output.txt
echo "This release was created on **$(date +'%Y-%m-%d')** and may contain unexpected bugs. Data loss is rare but is not impossible. The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
echo '' >> output.txt
echo '### Instructions' >> output.txt
echo '' >> output.txt
echo "* Installation instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/installation/docker/), [Portainer](https://docs.firefly-iii.org/how-to/firefly-iii/installation/portainer/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/installation/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/installation/self-managed/)" >> output.txt
echo "* Or read the upgrade instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/docker/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/self-managed/)" >> output.txt
echo "* The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
fi
# describe beta release
if [[ "$version" == *beta* ]]; then
echo 'BETA release.'
rm -f output.txt
touch output.txt
sudo chown -R runner:docker output.txt
echo "Very early BETA release of Firefly III. This release contains specific features or changes. Docker users can find this release under the \`$version\` tag." >> output.txt
echo '' >> output.txt
echo "This release was created on **$(date +'%Y-%m-%d')** and may contain unexpected bugs. Data loss is rare but is not impossible. The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
echo '' >> output.txt
echo '### Instructions' >> output.txt
echo '' >> output.txt
echo "* Installation instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/installation/docker/), [Portainer](https://docs.firefly-iii.org/how-to/firefly-iii/installation/portainer/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/installation/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/installation/self-managed/)" >> output.txt
echo "* Or read the upgrade instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/docker/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/self-managed/)" >> output.txt
echo "* The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
fi
# create a development release:
if [[ "develop" == "$version" ]]; then
# create the release:
echo "Create nightly release."
git tag -a $releaseName -m "Nightly development release '$version' on $(date +'%Y-%m-%d')"
echo "Create develop release."
git tag -a $releaseName -m "Development release '$version' on $(date +'%Y-%m-%d')"
git push origin $releaseName
gh release create $releaseName -p --verify-tag \
-t "Development release for $(date +'%Y-%m-%d')" \
--latest=false \
-F output.txt
fi
# create a branch release:
if [[ "$version" == branch* ]]; then
# create the release:
echo "Create branch release."
git tag -a $releaseName -m "Branch release '$version' on $(date +'%Y-%m-%d')"
git push origin $releaseName
gh release create $releaseName -p --verify-tag \
-t "Branch release for $(date +'%Y-%m-%d')" \
--latest=false \
-F output.txt
fi
# create a development (nightly) release:
if [[ "develop" == "$version" ]] || [[ "$version" == branch* ]]; then
# add zip file to release.
gh release upload $releaseName $zipName
gh release upload $releaseName $tarName
@@ -247,19 +343,20 @@ jobs:
gh release upload $releaseName HEAD.txt
else
echo 'MAIN (real) release'
sudo chown -R runner:docker output.txt
# add text to output.txt (more instructions)
echo '' >> output.txt
echo '### Instructions' >> output.txt
echo '' >> output.txt
echo "* Installation instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/installation/docker/), [Portainer](https://docs.firefly-iii.org/how-to/firefly-iii/installation/portainer/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/installation/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/installation/self-managed/)" >> output.txt
echo "* Or read the upgrade instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/docker/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/self-managed/)" >> output.txt
echo "* The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
echo "Create default release."
git tag -a $releaseName -m "Here be changelog"
git push origin $releaseName
# do not tag as latest when alpha or beta.
if [[ "$version" == *alpha* ]] || [[ "$version" == *beta* ]]; then
echo 'Mark alpha or beta as NOT the latest.'
gh release create $releaseName -F output.txt -t "$releaseName" --verify-tag --latest=false
fi
# tag as latest when NOT alpha or beta.
if [[ "$version" != *alpha* ]] && [[ "$version" != *beta* ]]; then
echo 'Mark prod as the latest.'
gh release create $releaseName -F output.txt -t "$releaseName" --verify-tag
fi
# add archive files to release
gh release upload $releaseName $zipName
@@ -279,12 +376,12 @@ jobs:
gh release upload $releaseName HEAD.txt
# remove all temporary files
rm output.txt
rm HEAD.txt
rm $zipName
rm $zipName.sha256
rm $tarName
rm $tarName.sha256
rm -f output.txt
rm -f HEAD.txt
rm -f $zipName
rm -f $zipName.sha256
rm -f $tarName
rm -f $tarName.sha256
# merge main back into develop
git checkout develop

View File

@@ -8,7 +8,7 @@ on:
- develop
env:
DB_CONNECTION: sqlite
APP_KEY: UfpBqqeXx7zpNodsC6yjYQcRfDdm4Bxh
APP_KEY: TestTestTestTestTestTestTestTest
jobs:
sonarcloud:
name: SonarCloud
@@ -19,7 +19,7 @@ jobs:
- name: Setup PHP with Xdebug
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
php-version: '8.4'
coverage: xdebug
extensions: >-
bcmath
@@ -46,7 +46,9 @@ jobs:
run: composer install --prefer-dist --no-interaction --no-progress --no-scripts
- name: "Create database file"
run: touch storage/database/database.sqlite
run: |
touch storage/database/database.sqlite
wget -q https://github.com/firefly-iii/test-fixtures/raw/refs/heads/main/test-database.sqlite -O storage/database/database.sqlite
- name: "Upgrades the database to the latest version"
run: php artisan firefly-iii:upgrade-database

View File

@@ -4,6 +4,8 @@ Over time, many people have contributed to Firefly III. Their efforts are not al
Please find below all the people who contributed to the Firefly III code. Their names are mentioned in the year of their first contribution.
## 2024
- Sobuno
- TasneemTantawy
- Antônio Franco
- yparitcher
- Jhon Pedroza

View File

@@ -26,10 +26,11 @@ namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Facades\Steam;
use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
@@ -61,7 +62,7 @@ class AccountController extends Controller
return $next($request);
}
);
$this->balanceTypes = [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE];
$this->balanceTypes = [AccountTypeEnum::ASSET->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::MORTGAGE->value];
}
/**
@@ -80,20 +81,20 @@ class AccountController extends Controller
$return = [];
$result = $this->repository->searchAccount((string) $query, $types, $this->parameters->get('limit'));
// TODO this code is duplicated in the V2 Autocomplete controller, which means this code is due to be deprecated.
$defaultCurrency = app('amount')->getDefaultCurrency();
/** @var Account $account */
foreach ($result as $account) {
$nameWithBalance = $account->name;
$currency = $this->repository->getAccountCurrency($account) ?? $defaultCurrency;
$currency = $this->repository->getAccountCurrency($account) ?? $this->defaultCurrency;
$useCurrency = $currency;
if (in_array($account->accountType->type, $this->balanceTypes, true)) {
$balance = app('steam')->balance($account, $date);
$balance = Steam::finalAccountBalance($account, $date);
$key = $this->convertToNative && $currency->id !== $this->defaultCurrency->id ? 'native_balance' : 'balance';
$useCurrency = $this->convertToNative && $currency->id !== $this->defaultCurrency->id ? $this->defaultCurrency : $currency;
$amount = $balance[$key] ?? '0';
$nameWithBalance = sprintf(
'%s (%s)',
$account->name,
app('amount')->formatAnything($currency, $balance, false)
app('amount')->formatAnything($useCurrency, $amount, false)
);
}
@@ -102,11 +103,11 @@ class AccountController extends Controller
'name' => $account->name,
'name_with_balance' => $nameWithBalance,
'type' => $account->accountType->type,
'currency_id' => (string)$currency->id,
'currency_name' => $currency->name,
'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places,
'currency_id' => (string) $useCurrency->id,
'currency_name' => $useCurrency->name,
'currency_code' => $useCurrency->code,
'currency_symbol' => $useCurrency->symbol,
'currency_decimal_places' => $useCurrency->decimal_places,
];
}
@@ -114,7 +115,7 @@ class AccountController extends Controller
usort(
$return,
static function (array $left, array $right) {
$order = [AccountType::ASSET, AccountType::REVENUE, AccountType::EXPENSE];
$order = [AccountTypeEnum::ASSET->value, AccountTypeEnum::REVENUE->value, AccountTypeEnum::EXPENSE->value];
$posA = (int) array_search($left['type'], $order, true);
$posB = (int) array_search($right['type'], $order, true);

View File

@@ -68,12 +68,11 @@ class PiggyBankController extends Controller
{
$data = $request->getData();
$piggies = $this->piggyRepository->searchPiggyBank($data['query'], $this->parameters->get('limit'));
$defaultCurrency = app('amount')->getDefaultCurrency();
$response = [];
/** @var PiggyBank $piggy */
foreach ($piggies as $piggy) {
$currency = $this->accountRepository->getAccountCurrency($piggy->account) ?? $defaultCurrency;
$currency = $piggy->transactionCurrency;
$objectGroup = $piggy->objectGroups()->first();
$response[] = [
'id' => (string) $piggy->id,
@@ -99,13 +98,12 @@ class PiggyBankController extends Controller
{
$data = $request->getData();
$piggies = $this->piggyRepository->searchPiggyBank($data['query'], $this->parameters->get('limit'));
$defaultCurrency = app('amount')->getDefaultCurrency();
$response = [];
/** @var PiggyBank $piggy */
foreach ($piggies as $piggy) {
$currency = $this->accountRepository->getAccountCurrency($piggy->account) ?? $defaultCurrency;
$currentAmount = $this->piggyRepository->getRepetition($piggy)->currentamount ?? '0';
$currency = $piggy->transactionCurrency;
$currentAmount = $this->piggyRepository->getCurrentAmount($piggy);
$objectGroup = $piggy->objectGroups()->first();
$response[] = [
'id' => (string) $piggy->id,
@@ -114,7 +112,7 @@ class PiggyBankController extends Controller
'%s (%s / %s)',
$piggy->name,
app('amount')->formatAnything($currency, $currentAmount, false),
app('amount')->formatAnything($currency, $piggy->targetamount, false),
app('amount')->formatAnything($currency, $piggy->target_amount, false),
),
'currency_id' => (string) $currency->id,
'currency_name' => $currency->name,

View File

@@ -27,9 +27,9 @@ namespace FireflyIII\Api\V1\Controllers\Chart;
use Carbon\Carbon;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Data\DateRequest;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\Preference;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Http\Api\ApiSupport;
@@ -81,11 +81,10 @@ class AccountController extends Controller
$end = $dates['end'];
// user's preferences
$defaultSet = $this->repository->getAccountsByType([AccountType::ASSET])->pluck('id')->toArray();
$defaultSet = $this->repository->getAccountsByType([AccountTypeEnum::ASSET->value])->pluck('id')->toArray();
/** @var Preference $frontpage */
$frontpage = app('preferences')->get('frontpageAccounts', $defaultSet);
$default = app('amount')->getDefaultCurrency();
if (!(is_array($frontpage->data) && count($frontpage->data) > 0)) {
$frontpage->data = $defaultSet;
@@ -98,10 +97,8 @@ class AccountController extends Controller
/** @var Account $account */
foreach ($accounts as $account) {
$currency = $this->repository->getAccountCurrency($account);
if (null === $currency) {
$currency = $default;
}
$currency = $this->repository->getAccountCurrency($account) ?? $this->defaultCurrency;
$field = $this->convertToNative && $currency->id !== $this->defaultCurrency->id ? 'native_balance' : 'balance';
$currentSet = [
'label' => $account->name,
'currency_id' => (string) $currency->id,
@@ -116,13 +113,12 @@ class AccountController extends Controller
];
// TODO this code is also present in the V2 chart account controller so this method is due to be deprecated.
$currentStart = clone $start;
$range = app('steam')->balanceInRange($account, $start, clone $end);
// 2022-10-11 this method no longer converts to float.
$previous = array_values($range)[0];
$range = app('steam')->finalAccountBalanceInRange($account, $start, clone $end, $this->convertToNative);
$previous = array_values($range)[0][$field];
while ($currentStart <= $end) {
$format = $currentStart->format('Y-m-d');
$label = $currentStart->toAtomString();
$balance = array_key_exists($format, $range) ? $range[$format] : $previous;
$balance = array_key_exists($format, $range) ? $range[$format][$field] : $previous;
$previous = $balance;
$currentStart->addDay();
$currentSet['entries'][$label] = $balance;

View File

@@ -25,9 +25,11 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers;
use Carbon\Carbon;
use Carbon\Exceptions\InvalidDateException;
use Carbon\Exceptions\InvalidFormatException;
use FireflyIII\Models\Preference;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Facades\Steam;
use FireflyIII\User;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
@@ -41,8 +43,8 @@ use Symfony\Component\HttpFoundation\ParameterBag;
/**
* Class Controller.
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
* @SuppressWarnings(PHPMD.NumberOfChildren)
* @SuppressWarnings("PHPMD.CouplingBetweenObjects")
* @SuppressWarnings("PHPMD.NumberOfChildren")
*/
abstract class Controller extends BaseController
{
@@ -55,6 +57,8 @@ abstract class Controller extends BaseController
/** @var array<int, string> */
protected array $allowedSort;
protected ParameterBag $parameters;
protected bool $convertToNative = false;
protected TransactionCurrency $defaultCurrency;
/**
* Controller constructor.
@@ -67,8 +71,11 @@ abstract class Controller extends BaseController
function ($request, $next) {
$this->parameters = $this->getParameters();
if (auth()->check()) {
$language = app('steam')->getLanguage();
$language = Steam::getLanguage();
$this->convertToNative = Amount::convertToNative();
$this->defaultCurrency = Amount::getDefaultCurrency();
app()->setLocale($language);
}
return $next($request);
@@ -108,7 +115,7 @@ abstract class Controller extends BaseController
if (null !== $date) {
try {
$obj = Carbon::parse((string) $date);
} catch (InvalidDateException|InvalidFormatException $e) {
} catch (InvalidFormatException $e) {
// don't care
app('log')->warning(
sprintf(

View File

@@ -26,10 +26,10 @@ namespace FireflyIII\Api\V1\Controllers\Data;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Data\DestroyRequest;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
@@ -66,9 +66,9 @@ class DestroyController extends Controller
$objects = $request->getObjects();
$this->unused = $request->boolean('unused', false);
$allExceptAssets = [AccountType::BENEFICIARY, AccountType::CASH, AccountType::CREDITCARD, AccountType::DEFAULT, AccountType::EXPENSE, AccountType::IMPORT, AccountType::INITIAL_BALANCE, AccountType::LIABILITY_CREDIT, AccountType::RECONCILIATION, AccountType::REVENUE];
$all = [AccountType::ASSET, AccountType::BENEFICIARY, AccountType::CASH, AccountType::CREDITCARD, AccountType::DEBT, AccountType::DEFAULT, AccountType::EXPENSE, AccountType::IMPORT, AccountType::INITIAL_BALANCE, AccountType::LIABILITY_CREDIT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::RECONCILIATION];
$liabilities = [AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD];
$allExceptAssets = [AccountTypeEnum::BENEFICIARY->value, AccountTypeEnum::CASH->value, AccountTypeEnum::CREDITCARD->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::EXPENSE->value, AccountTypeEnum::IMPORT->value, AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::LIABILITY_CREDIT->value, AccountTypeEnum::RECONCILIATION->value, AccountTypeEnum::REVENUE->value];
$all = [AccountTypeEnum::ASSET->value, AccountTypeEnum::BENEFICIARY->value, AccountTypeEnum::CASH->value, AccountTypeEnum::CREDITCARD->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::EXPENSE->value, AccountTypeEnum::IMPORT->value, AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::LIABILITY_CREDIT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::RECONCILIATION->value];
$liabilities = [AccountTypeEnum::DEBT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::CREDITCARD->value];
$transactions = [TransactionTypeEnum::WITHDRAWAL->value, TransactionTypeEnum::DEPOSIT->value, TransactionTypeEnum::TRANSFER->value, TransactionTypeEnum::RECONCILIATION->value];
match ($objects) {
@@ -82,9 +82,9 @@ class DestroyController extends Controller
'object_groups' => $this->destroyObjectGroups(),
'not_assets_liabilities' => $this->destroyAccounts($allExceptAssets),
'accounts' => $this->destroyAccounts($all),
'asset_accounts' => $this->destroyAccounts([AccountType::ASSET, AccountType::DEFAULT]),
'expense_accounts' => $this->destroyAccounts([AccountType::BENEFICIARY, AccountType::EXPENSE]),
'revenue_accounts' => $this->destroyAccounts([AccountType::REVENUE]),
'asset_accounts' => $this->destroyAccounts([AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value]),
'expense_accounts' => $this->destroyAccounts([AccountTypeEnum::BENEFICIARY->value, AccountTypeEnum::EXPENSE->value]),
'revenue_accounts' => $this->destroyAccounts([AccountTypeEnum::REVENUE->value]),
'liabilities' => $this->destroyAccounts($liabilities),
'transactions' => $this->destroyTransactions($transactions),
'withdrawals' => $this->destroyTransactions([TransactionTypeEnum::WITHDRAWAL->value]),

View File

@@ -59,7 +59,7 @@ class ExportController extends Controller
*
* @throws FireflyException
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function accounts(ExportRequest $request): LaravelResponse
{
@@ -100,7 +100,7 @@ class ExportController extends Controller
*
* @throws FireflyException
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function bills(ExportRequest $request): LaravelResponse
{
@@ -115,7 +115,7 @@ class ExportController extends Controller
*
* @throws FireflyException
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function budgets(ExportRequest $request): LaravelResponse
{
@@ -130,7 +130,7 @@ class ExportController extends Controller
*
* @throws FireflyException
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function categories(ExportRequest $request): LaravelResponse
{
@@ -145,7 +145,7 @@ class ExportController extends Controller
*
* @throws FireflyException
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function piggyBanks(ExportRequest $request): LaravelResponse
{
@@ -160,7 +160,7 @@ class ExportController extends Controller
*
* @throws FireflyException
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function recurring(ExportRequest $request): LaravelResponse
{
@@ -175,7 +175,7 @@ class ExportController extends Controller
*
* @throws FireflyException
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function rules(ExportRequest $request): LaravelResponse
{
@@ -190,7 +190,7 @@ class ExportController extends Controller
*
* @throws FireflyException
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function tags(ExportRequest $request): LaravelResponse
{

View File

@@ -29,13 +29,13 @@ use FireflyIII\Models\Account;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Budget;
use FireflyIII\Models\Category;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\Recurrence;
use FireflyIII\Models\Rule;
use FireflyIII\Models\RuleGroup;
use FireflyIII\Models\Tag;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
@@ -63,14 +63,17 @@ class PurgeController extends Controller
Bill::whereUserId($user->id)->onlyTrashed()->forceDelete();
// piggies
$set = PiggyBank::leftJoin('accounts', 'accounts.id', 'piggy_banks.account_id')
->where('accounts.user_id', $user->id)->onlyTrashed()->get(['piggy_banks.*'])
;
/** @var PiggyBank $piggy */
foreach ($set as $piggy) {
$piggy->forceDelete();
}
$repository = app(PiggyBankRepositoryInterface::class);
$repository->setUser($user);
$repository->purgeAll();
// $set = PiggyBank::leftJoin('accounts', 'accounts.id', 'piggy_banks.account_id')
// ->where('accounts.user_id', $user->id)->onlyTrashed()->get(['piggy_banks.*'])
// ;
//
// /** @var PiggyBank $piggy */
// foreach ($set as $piggy) {
// $piggy->forceDelete();
// }
// rule group
RuleGroup::whereUserId($user->id)->onlyTrashed()->forceDelete();

View File

@@ -29,7 +29,9 @@ use FireflyIII\Api\V1\Requests\Insight\GenericRequest;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Support\Facades\Amount;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
/**
* Class BillController
@@ -67,6 +69,8 @@ class BillController extends Controller
$bills = $request->getBills();
$start = $request->getStart();
$end = $request->getEnd();
$convertToNative = Amount::convertToNative();
$default = Amount::getDefaultCurrency();
$response = [];
// get all bills:
@@ -83,9 +87,22 @@ class BillController extends Controller
foreach ($genericSet as $journal) {
$billId = (int) $journal['bill_id'];
$currencyId = (int) $journal['currency_id'];
$foreignCurrencyId = (int)$journal['foreign_currency_id'];
$currencyCode = $journal['currency_code'];
$field = 'amount';
// use the native amount if the user wants to convert to native currency
if ($convertToNative && $currencyId !== $default->id) {
$currencyId = $default->id;
$currencyCode = $default->code;
$field = 'native_amount';
}
// use foreign amount when the foreign currency IS the default currency.
if ($convertToNative && $journal['currency_id'] !== $default->id && $default->id === $journal['foreign_currency_id']) {
$field = 'foreign_amount';
}
Log::debug(sprintf('Journal #%d in bill #%d will use %s (%s %s)', $journal['transaction_group_id'], $billId, $field, $currencyCode, $journal[$field] ?? '0'));
$key = sprintf('%d-%d', $billId, $currencyId);
$foreignKey = sprintf('%d-%d', $billId, $foreignCurrencyId);
if (0 !== $currencyId) {
$response[$key] ??= [
@@ -94,21 +111,11 @@ class BillController extends Controller
'difference' => '0',
'difference_float' => 0,
'currency_id' => (string) $currencyId,
'currency_code' => $journal['currency_code'],
'currency_code' => $currencyCode,
];
$response[$key]['difference'] = bcadd($response[$key]['difference'], $journal['amount']);
$response[$key]['difference'] = bcadd($response[$key]['difference'], (string) ($journal[$field] ?? '0'));
$response[$key]['difference_float'] = (float) $response[$key]['difference']; // intentional float
}
if (0 !== $foreignCurrencyId) {
$response[$foreignKey] ??= [
'difference' => '0',
'difference_float' => 0,
'currency_id' => (string)$foreignCurrencyId,
'currency_code' => $journal['foreign_currency_code'],
];
$response[$foreignKey]['difference'] = bcadd($response[$foreignKey]['difference'], $journal['foreign_amount']);
$response[$foreignKey]['difference_float'] = (float)$response[$foreignKey]['difference']; // intentional float
}
}
return response()->json(array_values($response));
@@ -125,6 +132,8 @@ class BillController extends Controller
$accounts = $request->getAssetAccounts();
$start = $request->getStart();
$end = $request->getEnd();
$convertToNative = Amount::convertToNative();
$default = Amount::getDefaultCurrency();
$response = [];
// collect all expenses in this period (regardless of type) by the given bills and accounts.
@@ -136,28 +145,31 @@ class BillController extends Controller
foreach ($genericSet as $journal) {
$currencyId = (int) $journal['currency_id'];
$foreignCurrencyId = (int)$journal['foreign_currency_id'];
$currencyCode = $journal['currency_code'];
$field = 'amount';
// use the native amount if the user wants to convert to native currency
if ($convertToNative && $currencyId !== $default->id) {
$currencyId = $default->id;
$currencyCode = $default->code;
$field = 'native_amount';
}
// use foreign amount when the foreign currency IS the default currency.
if ($convertToNative && $journal['currency_id'] !== $default->id && $default->id === $journal['foreign_currency_id']) {
$field = 'foreign_amount';
}
Log::debug(sprintf('Journal #%d will use %s (%s %s)', $journal['transaction_group_id'], $field, $currencyCode, $journal[$field] ?? '0'));
if (0 !== $currencyId) {
$response[$currencyId] ??= [
'difference' => '0',
'difference_float' => 0,
'currency_id' => (string) $currencyId,
'currency_code' => $journal['currency_code'],
'currency_code' => $currencyCode,
];
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], $journal['amount']);
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], (string) ($journal[$field] ?? '0'));
$response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; // intentional float
}
if (0 !== $foreignCurrencyId) {
$response[$foreignCurrencyId] ??= [
'difference' => '0',
'difference_float' => 0,
'currency_id' => (string)$foreignCurrencyId,
'currency_code' => $journal['foreign_currency_code'],
];
$response[$foreignCurrencyId]['difference'] = bcadd($response[$foreignCurrencyId]['difference'], $journal['foreign_amount']);
$response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference']; // intentional float
}
}
return response()->json(array_values($response));

View File

@@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Insight\GenericRequest;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Support\Facades\Amount;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
/**
* Class PeriodController
@@ -45,36 +47,46 @@ class PeriodController extends Controller
$start = $request->getStart();
$end = $request->getEnd();
$response = [];
$convertToNative = Amount::convertToNative();
$default = Amount::getDefaultCurrency();
// collect all expenses in this period (regardless of type)
$collector = app(GroupCollectorInterface::class);
$collector->setTypes([TransactionTypeEnum::WITHDRAWAL->value])->setRange($start, $end)->setSourceAccounts($accounts);
$genericSet = $collector->getExtractedJournals();
foreach ($genericSet as $journal) {
// same code as many other sumExpense methods. I think this needs some kind of generic method.
$amount = '0';
$currencyId = (int) $journal['currency_id'];
$foreignCurrencyId = (int)$journal['foreign_currency_id'];
$currencyCode = $journal['currency_code'];
if ($convertToNative) {
$amount = Amount::getAmountFromJournal($journal);
if ($default->id !== (int) $journal['currency_id'] && $default->id !== (int) $journal['foreign_currency_id']) {
$currencyId = $default->id;
$currencyCode = $default->code;
}
if ($default->id !== (int) $journal['currency_id'] && $default->id === (int) $journal['foreign_currency_id']) {
$currencyId = $journal['foreign_currency_id'];
$currencyCode = $journal['foreign_currency_code'];
}
Log::debug(sprintf('[a] Add amount %s %s', $currencyCode, $amount));
}
if (!$convertToNative) {
// ignore the amount in foreign currency.
Log::debug(sprintf('[b] Add amount %s %s', $currencyCode, $journal['amount']));
$amount = $journal['amount'];
}
if (0 !== $currencyId) {
$response[$currencyId] ??= [
'difference' => '0',
'difference_float' => 0,
'currency_id' => (string) $currencyId,
'currency_code' => $journal['currency_code'],
'currency_code' => $currencyCode,
];
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], $journal['amount']);
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], $amount);
$response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; // intentional float
}
if (0 !== $foreignCurrencyId) {
$response[$foreignCurrencyId] ??= [
'difference' => '0',
'difference_float' => 0,
'currency_id' => (string)$foreignCurrencyId,
'currency_code' => $journal['foreign_currency_code'],
];
$response[$foreignCurrencyId]['difference'] = bcadd($response[$foreignCurrencyId]['difference'], $journal['foreign_amount']);
$response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference']; // intentional float
}
}
return response()->json(array_values($response));
}

View File

@@ -29,7 +29,9 @@ use FireflyIII\Api\V1\Requests\Insight\GenericRequest;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use FireflyIII\Support\Facades\Amount;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
/**
* Class TagController
@@ -66,6 +68,8 @@ class TagController extends Controller
$start = $request->getStart();
$end = $request->getEnd();
$response = [];
$convertToNative = Amount::convertToNative();
$default = Amount::getDefaultCurrency();
// collect all expenses in this period (regardless of type) by the given bills and accounts.
$collector = app(GroupCollectorInterface::class);
@@ -75,30 +79,37 @@ class TagController extends Controller
$genericSet = $collector->getExtractedJournals();
foreach ($genericSet as $journal) {
// same code as many other sumExpense methods. I think this needs some kind of generic method.
$amount = '0';
$currencyId = (int) $journal['currency_id'];
$foreignCurrencyId = (int)$journal['foreign_currency_id'];
$currencyCode = $journal['currency_code'];
if ($convertToNative) {
$amount = Amount::getAmountFromJournal($journal);
if ($default->id !== (int) $journal['currency_id'] && $default->id !== (int) $journal['foreign_currency_id']) {
$currencyId = $default->id;
$currencyCode = $default->code;
}
if ($default->id !== (int) $journal['currency_id'] && $default->id === (int) $journal['foreign_currency_id']) {
$currencyId = $journal['foreign_currency_id'];
$currencyCode = $journal['foreign_currency_code'];
}
Log::debug(sprintf('[a] Add amount %s %s', $currencyCode, $amount));
}
if (!$convertToNative) {
// ignore the amount in foreign currency.
Log::debug(sprintf('[b] Add amount %s %s', $currencyCode, $journal['amount']));
$amount = $journal['amount'];
}
if (0 !== $currencyId) {
$response[$currencyId] ??= [
'difference' => '0',
'difference_float' => 0,
'currency_id' => (string) $currencyId,
'currency_code' => $journal['currency_code'],
'currency_code' => $currencyCode,
];
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], $journal['amount']);
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], $amount);
$response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; // float but on purpose.
}
if (0 !== $foreignCurrencyId) {
$response[$foreignCurrencyId] ??= [
'difference' => '0',
'difference_float' => 0,
'currency_id' => (string)$foreignCurrencyId,
'currency_code' => $journal['foreign_currency_code'],
];
$response[$foreignCurrencyId]['difference'] = bcadd($response[$foreignCurrencyId]['difference'], $journal['foreign_amount']);
$response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference']; // float but on purpose.
}
}
return response()->json(array_values($response));
}

View File

@@ -73,6 +73,7 @@ class AccountController extends Controller
$start = $request->getStart();
$end = $request->getEnd();
$assetAccounts = $request->getAssetAccounts();
$income = $this->opsRepository->sumIncomeByDestination($start, $end, $assetAccounts);
$result = [];

View File

@@ -28,6 +28,7 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Insight\GenericRequest;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Support\Facades\Amount;
use Illuminate\Http\JsonResponse;
/**
@@ -45,39 +46,38 @@ class PeriodController extends Controller
$start = $request->getStart();
$end = $request->getEnd();
$response = [];
$convertToNative = Amount::convertToNative();
$default = Amount::getDefaultCurrency();
// collect all expenses in this period (regardless of type)
$collector = app(GroupCollectorInterface::class);
$collector->setTypes([TransactionTypeEnum::DEPOSIT->value])->setRange($start, $end)->setDestinationAccounts($accounts);
$genericSet = $collector->getExtractedJournals();
foreach ($genericSet as $journal) {
$currencyId = (int)$journal['currency_id'];
$foreignCurrencyId = (int)$journal['foreign_currency_id'];
// currency
$currencyId = $journal['currency_id'];
$currencyCode = $journal['currency_code'];
$field = $convertToNative && $currencyId !== $default->id ? 'native_amount' : 'amount';
// perhaps use default currency instead?
if ($convertToNative && $journal['currency_id'] !== $default->id) {
$currencyId = $default->id;
$currencyCode = $default->code;
}
// use foreign amount when the foreign currency IS the default currency.
if ($convertToNative && $journal['currency_id'] !== $default->id && $default->id === $journal['foreign_currency_id']) {
$field = 'foreign_amount';
}
if (0 !== $currencyId) {
$response[$currencyId] ??= [
'difference' => '0',
'difference_float' => 0,
'currency_id' => (string) $currencyId,
'currency_code' => $journal['currency_code'],
'currency_code' => $currencyCode,
];
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal['amount']));
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal[$field]));
$response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; // float but on purpose.
}
if (0 !== $foreignCurrencyId) {
$response[$foreignCurrencyId] ??= [
'difference' => '0',
'difference_float' => 0,
'currency_id' => (string)$foreignCurrencyId,
'currency_code' => $journal['foreign_currency_code'],
];
$response[$foreignCurrencyId]['difference'] = bcadd(
$response[$foreignCurrencyId]['difference'],
app('steam')->positive($journal['foreign_amount'])
);
$response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference']; // float but on purpose.
}
}
return response()->json(array_values($response));
}

View File

@@ -29,6 +29,7 @@ use FireflyIII\Api\V1\Requests\Insight\GenericRequest;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use FireflyIII\Support\Facades\Amount;
use Illuminate\Http\JsonResponse;
/**
@@ -67,6 +68,8 @@ class TagController extends Controller
$start = $request->getStart();
$end = $request->getEnd();
$response = [];
$convertToNative = Amount::convertToNative();
$default = Amount::getDefaultCurrency();
// collect all expenses in this period (regardless of type) by the given bills and accounts.
$collector = app(GroupCollectorInterface::class);
@@ -76,32 +79,30 @@ class TagController extends Controller
$genericSet = $collector->getExtractedJournals();
foreach ($genericSet as $journal) {
$currencyId = (int)$journal['currency_id'];
$foreignCurrencyId = (int)$journal['foreign_currency_id'];
// currency
$currencyId = $journal['currency_id'];
$currencyCode = $journal['currency_code'];
$field = $convertToNative && $currencyId !== $default->id ? 'native_amount' : 'amount';
// perhaps use default currency instead?
if ($convertToNative && $journal['currency_id'] !== $default->id) {
$currencyId = $default->id;
$currencyCode = $default->code;
}
// use foreign amount when the foreign currency IS the default currency.
if ($convertToNative && $journal['currency_id'] !== $default->id && $default->id === $journal['foreign_currency_id']) {
$field = 'foreign_amount';
}
if (0 !== $currencyId) {
$response[$currencyId] ??= [
'difference' => '0',
'difference_float' => 0,
'currency_id' => (string) $currencyId,
'currency_code' => $journal['currency_code'],
'currency_code' => $currencyCode,
];
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal['amount']));
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal[$field]));
$response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference'];
}
if (0 !== $foreignCurrencyId) {
$response[$foreignCurrencyId] ??= [
'difference' => '0',
'difference_float' => 0,
'currency_id' => (string)$foreignCurrencyId,
'currency_code' => $journal['foreign_currency_code'],
];
$response[$foreignCurrencyId]['difference'] = bcadd(
$response[$foreignCurrencyId]['difference'],
app('steam')->positive($journal['foreign_amount'])
);
$response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference'];
}
}
return response()->json(array_values($response));

View File

@@ -26,8 +26,9 @@ namespace FireflyIII\Api\V1\Controllers\Insight\Transfer;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Insight\GenericRequest;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\TransactionType;
use FireflyIII\Support\Facades\Amount;
use Illuminate\Http\JsonResponse;
/**
@@ -45,38 +46,38 @@ class PeriodController extends Controller
$start = $request->getStart();
$end = $request->getEnd();
$response = [];
$convertToNative = Amount::convertToNative();
$default = Amount::getDefaultCurrency();
// collect all expenses in this period (regardless of type)
$collector = app(GroupCollectorInterface::class);
$collector->setTypes([TransactionType::TRANSFER])->setRange($start, $end)->setDestinationAccounts($accounts);
$collector->setTypes([TransactionTypeEnum::TRANSFER->value])->setRange($start, $end)->setDestinationAccounts($accounts);
$genericSet = $collector->getExtractedJournals();
foreach ($genericSet as $journal) {
$currencyId = (int)$journal['currency_id'];
$foreignCurrencyId = (int)$journal['foreign_currency_id'];
// currency
$currencyId = $journal['currency_id'];
$currencyCode = $journal['currency_code'];
$field = $convertToNative && $currencyId !== $default->id ? 'native_amount' : 'amount';
// perhaps use default currency instead?
if ($convertToNative && $journal['currency_id'] !== $default->id) {
$currencyId = $default->id;
$currencyCode = $default->code;
}
// use foreign amount when the foreign currency IS the default currency.
if ($convertToNative && $journal['currency_id'] !== $default->id && $default->id === $journal['foreign_currency_id']) {
$field = 'foreign_amount';
}
if (0 !== $currencyId) {
$response[$currencyId] ??= [
'difference' => '0',
'difference_float' => 0,
'currency_id' => (string) $currencyId,
'currency_code' => $journal['currency_code'],
'currency_code' => $currencyCode,
];
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal['amount']));
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal[$field]));
$response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference'];
}
if (0 !== $foreignCurrencyId) {
$response[$foreignCurrencyId] ??= [
'difference' => '0',
'difference_float' => 0,
'currency_id' => (string)$foreignCurrencyId,
'currency_code' => $journal['foreign_currency_code'],
];
$response[$foreignCurrencyId]['difference'] = bcadd(
$response[$foreignCurrencyId]['difference'],
app('steam')->positive($journal['foreign_amount'])
);
$response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference'];
}
}
return response()->json(array_values($response));

View File

@@ -26,9 +26,10 @@ namespace FireflyIII\Api\V1\Controllers\Insight\Transfer;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Insight\GenericRequest;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use FireflyIII\Support\Facades\Amount;
use Illuminate\Http\JsonResponse;
/**
@@ -65,41 +66,42 @@ class TagController extends Controller
$start = $request->getStart();
$end = $request->getEnd();
$response = [];
$convertToNative = Amount::convertToNative();
$default = Amount::getDefaultCurrency();
// collect all expenses in this period (regardless of type) by the given bills and accounts.
$collector = app(GroupCollectorInterface::class);
$collector->setTypes([TransactionType::TRANSFER])->setRange($start, $end)->setDestinationAccounts($accounts);
$collector->setTypes([TransactionTypeEnum::TRANSFER->value])->setRange($start, $end)->setDestinationAccounts($accounts);
$collector->withoutTags();
$genericSet = $collector->getExtractedJournals();
foreach ($genericSet as $journal) {
$currencyId = (int)$journal['currency_id'];
$foreignCurrencyId = (int)$journal['foreign_currency_id'];
// currency
$currencyId = $journal['currency_id'];
$currencyCode = $journal['currency_code'];
$field = $convertToNative && $currencyId !== $default->id ? 'native_amount' : 'amount';
// perhaps use default currency instead?
if ($convertToNative && $journal['currency_id'] !== $default->id) {
$currencyId = $default->id;
$currencyCode = $default->code;
}
// use foreign amount when the foreign currency IS the default currency.
if ($convertToNative && $journal['currency_id'] !== $default->id && $default->id === $journal['foreign_currency_id']) {
$field = 'foreign_amount';
}
if (0 !== $currencyId) {
$response[$currencyId] ??= [
'difference' => '0',
'difference_float' => 0,
'currency_id' => (string) $currencyId,
'currency_code' => $journal['currency_code'],
'currency_code' => $currencyCode,
];
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal['amount']));
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal[$field]));
$response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference'];
}
if (0 !== $foreignCurrencyId) {
$response[$foreignCurrencyId] ??= [
'difference' => '0',
'difference_float' => 0,
'currency_id' => (string)$foreignCurrencyId,
'currency_code' => $journal['foreign_currency_code'],
];
$response[$foreignCurrencyId]['difference'] = bcadd(
$response[$foreignCurrencyId]['difference'],
app('steam')->positive($journal['foreign_amount'])
);
$response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference'];
}
}
return response()->json(array_values($response));
@@ -126,7 +128,7 @@ class TagController extends Controller
// collect all expenses in this period (regardless of type) by the given bills and accounts.
$collector = app(GroupCollectorInterface::class);
$collector->setTypes([TransactionType::TRANSFER])->setRange($start, $end)->setDestinationAccounts($accounts);
$collector->setTypes([TransactionTypeEnum::TRANSFER->value])->setRange($start, $end)->setDestinationAccounts($accounts);
$collector->setTags($tags);
$genericSet = $collector->getExtractedJournals();

View File

@@ -111,7 +111,7 @@ class ListController extends Controller
// types to get, page size:
$pageSize = $this->parameters->get('limit');
// get list of budgets. Count it and split it.
// get list of piggy banks. Count it and split it.
$collection = $this->repository->getPiggyBanks($account);
$count = $collection->count();
$piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);

View File

@@ -100,7 +100,7 @@ class ShowController extends Controller
*
* Display a listing of the budget limits for this budget.
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function indexAll(SameDateRequest $request): JsonResponse
{

View File

@@ -69,6 +69,7 @@ class StoreController extends Controller
$data = $request->getAll();
$data['start_date'] = $data['start'];
$data['end_date'] = $data['end'];
$data['notes'] = $data['notes'];
$data['budget_id'] = $budget->id;
$budgetLimit = $this->blRepository->store($data);

View File

@@ -28,6 +28,7 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Transformers\AccountTransformer;
use FireflyIII\Transformers\AttachmentTransformer;
use FireflyIII\Transformers\PiggyBankEventTransformer;
use Illuminate\Http\JsonResponse;
@@ -58,6 +59,38 @@ class ListController extends Controller
);
}
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/piggy_banks/listAccountByPiggyBank
*
* List single resource.
*
* @throws FireflyException
*/
public function accounts(PiggyBank $piggyBank): JsonResponse
{
// types to get, page size:
$pageSize = $this->parameters->get('limit');
$manager = $this->getManager();
$collection = $piggyBank->accounts;
$count = $collection->count();
$events = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// make paginator:
$paginator = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.piggy-banks.accounts', [$piggyBank->id]).$this->buildParams());
/** @var AccountTransformer $transformer */
$transformer = app(AccountTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($events, $transformer, 'accounts');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
}
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/piggy_banks/listAttachmentByPiggyBank

View File

@@ -72,7 +72,7 @@ class ShowController extends Controller
// types to get, page size:
$pageSize = $this->parameters->get('limit');
// get list of budgets. Count it and split it.
// get list of piggy banks. Count it and split it.
$collection = $this->repository->getPiggyBanks();
$count = $collection->count();
$piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);

View File

@@ -37,7 +37,7 @@ class ExpressionController extends Controller
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/rules/validateExpression
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function validateExpression(ValidateExpressionRequest $request): JsonResponse
{

View File

@@ -88,21 +88,21 @@ class StoreController extends Controller
try {
$transactionGroup = $this->groupRepository->store($data);
} catch (DuplicateTransactionException $e) { // @phpstan-ignore-line
} catch (DuplicateTransactionException $e) {
app('log')->warning('Caught a duplicate transaction. Return error message.');
$validator = \Validator::make(
['transactions' => [['description' => $e->getMessage()]]],
['transactions.0.description' => new IsDuplicateTransaction()]
);
throw new ValidationException($validator); // @phpstan-ignore-line
} catch (FireflyException $e) { // @phpstan-ignore-line
throw new ValidationException($validator);
} catch (FireflyException $e) {
app('log')->warning('Caught an exception. Return error message.');
app('log')->error($e->getMessage());
$message = sprintf('Internal exception: %s', $e->getMessage());
$validator = \Validator::make(['transactions' => [['description' => $message]]], ['transactions.0.description' => new IsDuplicateTransaction()]);
throw new ValidationException($validator); // @phpstan-ignore-line
throw new ValidationException($validator);
}
app('preferences')->mark();
$applyRules = $data['apply_rules'] ?? true;

View File

@@ -239,7 +239,7 @@ class ListController extends Controller
$unfiltered = $recurringRepos->getAll();
// filter selection
$collection = $unfiltered->filter( // @phpstan-ignore-line
$collection = $unfiltered->filter(
static function (Recurrence $recurrence) use ($currency) { // @phpstan-ignore-line
/** @var RecurrenceTransaction $transaction */
foreach ($recurrence->recurrenceTransactions as $transaction) {
@@ -286,7 +286,7 @@ class ListController extends Controller
$ruleRepos = app(RuleRepositoryInterface::class);
$unfiltered = $ruleRepos->getAll();
$collection = $unfiltered->filter( // @phpstan-ignore-line
$collection = $unfiltered->filter(
static function (Rule $rule) use ($currency) { // @phpstan-ignore-line
/** @var RuleTrigger $trigger */
foreach ($rule->ruleTriggers as $trigger) {

View File

@@ -107,8 +107,7 @@ class ShowController extends Controller
/** @var User $user */
$user = auth()->user();
$manager = $this->getManager();
$defaultCurrency = app('amount')->getDefaultCurrencyByUserGroup($user->userGroup);
$this->parameters->set('defaultCurrency', $defaultCurrency);
$this->parameters->set('defaultCurrency', $this->defaultCurrency);
// update fields with user info.
$currency->refreshForUser($user);
@@ -135,7 +134,7 @@ class ShowController extends Controller
/** @var User $user */
$user = auth()->user();
$manager = $this->getManager();
$currency = app('amount')->getDefaultCurrencyByUserGroup($user->userGroup);
$currency = $this->defaultCurrency;
// update fields with user info.
$currency->refreshForUser($user);

View File

@@ -62,7 +62,6 @@ class AccountController extends Controller
*/
public function search(Request $request): JsonResponse|Response
{
app('log')->debug('Now in account search()');
$manager = $this->getManager();
$query = trim((string) $request->get('query'));
$field = trim((string) $request->get('field'));
@@ -70,6 +69,7 @@ class AccountController extends Controller
if ('' === $query || !in_array($field, $this->validFields, true)) {
return response(null, 422);
}
app('log')->debug(sprintf('Now in account search("%s", "%s")', $field, $query));
$types = $this->mapAccountTypes($type);
/** @var AccountSearch $search */

View File

@@ -27,19 +27,21 @@ namespace FireflyIII\Api\V1\Controllers\Summary;
use Carbon\Carbon;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Data\DateRequest;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Helpers\Report\NetWorthInterface;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
/**
* Class BasicController
@@ -120,6 +122,9 @@ class BasicController extends Controller
private function getBalanceInformation(Carbon $start, Carbon $end): array
{
// some config settings
$convertToNative = Amount::convertToNative();
$default = Amount::getDefaultCurrency();
// prep some arrays:
$incomes = [];
$expenses = [];
@@ -133,16 +138,17 @@ class BasicController extends Controller
$set = $collector->getExtractedJournals();
/** @var array $transactionJournal */
foreach ($set as $transactionJournal) {
$currencyId = (int)$transactionJournal['currency_id'];
/** @var array $journal */
foreach ($set as $journal) {
$currencyId = $convertToNative ? $default->id : (int) $journal['currency_id'];
$amount = Amount::getAmountFromJournal($journal);
$incomes[$currencyId] ??= '0';
$incomes[$currencyId] = bcadd(
$incomes[$currencyId],
bcmul($transactionJournal['amount'], '-1')
bcmul($amount, '-1')
);
$sums[$currencyId] ??= '0';
$sums[$currencyId] = bcadd($sums[$currencyId], bcmul($transactionJournal['amount'], '-1'));
$sums[$currencyId] = bcadd($sums[$currencyId], bcmul($amount, '-1'));
}
// collect expenses of user using the new group collector.
@@ -151,13 +157,14 @@ class BasicController extends Controller
$collector->setRange($start, $end)->setPage($this->parameters->get('page'))->setTypes([TransactionTypeEnum::WITHDRAWAL->value]);
$set = $collector->getExtractedJournals();
/** @var array $transactionJournal */
foreach ($set as $transactionJournal) {
$currencyId = (int)$transactionJournal['currency_id'];
/** @var array $journal */
foreach ($set as $journal) {
$currencyId = $convertToNative ? $default->id : (int) $journal['currency_id'];
$amount = Amount::getAmountFromJournal($journal);
$expenses[$currencyId] ??= '0';
$expenses[$currencyId] = bcadd($expenses[$currencyId], $transactionJournal['amount']);
$expenses[$currencyId] = bcadd($expenses[$currencyId], $amount);
$sums[$currencyId] ??= '0';
$sums[$currencyId] = bcadd($sums[$currencyId], $transactionJournal['amount']);
$sums[$currencyId] = bcadd($sums[$currencyId], $amount);
}
// format amounts:
@@ -269,24 +276,27 @@ class BasicController extends Controller
*/
private function getLeftToSpendInfo(Carbon $start, Carbon $end): array
{
Log::debug(sprintf('Now in getLeftToSpendInfo("%s", "%s")', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
$return = [];
$today = today(config('app.timezone'));
$available = $this->abRepository->getAvailableBudgetWithCurrency($start, $end);
$budgets = $this->budgetRepository->getActiveBudgets();
$spent = $this->opsRepository->sumExpenses($start, $end, null, $budgets);
$days = (int) $today->diffInDays($end, true) + 1;
foreach ($spent as $row) {
// either an amount was budgeted or 0 is available.
$amount = (string)($available[$row['currency_id']] ?? '0');
$currencyId = $row['currency_id'];
$amount = (string) ($available[$currencyId] ?? '0');
$spentInCurrency = $row['sum'];
$leftToSpend = bcadd($amount, $spentInCurrency);
$days = (int)$today->diffInDays($end, true) + 1;
$perDay = '0';
if (0 !== $days && bccomp($leftToSpend, '0') > -1) {
$perDay = bcdiv($leftToSpend, (string) $days);
}
Log::debug(sprintf('Spent %s %s', $row['currency_code'], $row['sum']));
$return[] = [
'key' => sprintf('left-to-spend-in-%s', $row['currency_code']),
'title' => trans('firefly.box_left_to_spend_in_currency', ['currency' => $row['currency_symbol']]),
@@ -311,9 +321,11 @@ class BasicController extends Controller
private function getNetWorthInfo(Carbon $start, Carbon $end): array
{
Log::debug('getNetWorthInfo');
/** @var User $user */
$user = auth()->user();
$date = today(config('app.timezone'))->startOfDay();
$date = now(config('app.timezone'));
// start and end in the future? use $end
if ($this->notInDateRange($date, $start, $end)) {
/** @var Carbon $date */
@@ -323,9 +335,7 @@ class BasicController extends Controller
/** @var NetWorthInterface $netWorthHelper */
$netWorthHelper = app(NetWorthInterface::class);
$netWorthHelper->setUser($user);
$allAccounts = $this->accountRepository->getActiveAccountsByType(
[AccountType::ASSET, AccountType::DEFAULT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::DEBT]
);
$allAccounts = $this->accountRepository->getActiveAccountsByType([AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::DEBT->value]);
// filter list on preference of being included.
$filtered = $allAccounts->filter(
@@ -360,6 +370,7 @@ class BasicController extends Controller
'sub_title' => '',
];
}
Log::debug('End of getNetWorthInfo');
return $return;
}

View File

@@ -24,7 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Autocomplete;
use FireflyIII\Models\AccountType;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
@@ -46,7 +46,7 @@ class AutocompleteRequest extends FormRequest
}
// remove 'initial balance' from allowed types. its internal
$array = array_diff($array, [AccountType::INITIAL_BALANCE, AccountType::RECONCILIATION]);
$array = array_diff($array, [AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::RECONCILIATION->value]);
return [
'types' => $array,

View File

@@ -24,7 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Data\Export;
use FireflyIII\Models\AccountType;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
@@ -55,7 +55,7 @@ class ExportRequest extends FormRequest
$accountId = (int) $part;
if (0 !== $accountId) {
$account = $repository->find($accountId);
if (null !== $account && AccountType::ASSET === $account->accountType->type) {
if (null !== $account && AccountTypeEnum::ASSET->value === $account->accountType->type) {
$accounts->push($account);
}
}

View File

@@ -25,8 +25,8 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Insight;
use Carbon\Carbon;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
@@ -70,7 +70,7 @@ class GenericRequest extends FormRequest
/** @var Account $account */
foreach ($this->accounts as $account) {
$type = $account->accountType->type;
if (in_array($type, [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], true)) {
if (in_array($type, [AccountTypeEnum::ASSET->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::MORTGAGE->value], true)) {
$return->push($account);
}
}
@@ -191,7 +191,7 @@ class GenericRequest extends FormRequest
/** @var Account $account */
foreach ($this->accounts as $account) {
$type = $account->accountType->type;
if (AccountType::EXPENSE === $type) {
if (AccountTypeEnum::EXPENSE->value === $type) {
$return->push($account);
}
}
@@ -207,7 +207,7 @@ class GenericRequest extends FormRequest
/** @var Account $account */
foreach ($this->accounts as $account) {
$type = $account->accountType->type;
if (AccountType::REVENUE === $type) {
if (AccountTypeEnum::REVENUE->value === $type) {
$return->push($account);
}
}

View File

@@ -48,6 +48,7 @@ class StoreRequest extends FormRequest
'amount' => $this->convertString('amount'),
'currency_id' => $this->convertInteger('currency_id'),
'currency_code' => $this->convertString('currency_code'),
'notes' => $this->stringWithNewlines('notes'),
];
}
@@ -62,6 +63,7 @@ class StoreRequest extends FormRequest
'amount' => ['required', new IsValidPositiveAmount()],
'currency_id' => 'numeric|exists:transaction_currencies,id',
'currency_code' => 'min:3|max:51|exists:transaction_currencies,code',
'notes' => 'nullable|min:0|max:32768',
];
}
}

View File

@@ -51,7 +51,12 @@ class UpdateRequest extends FormRequest
'amount' => ['amount', 'convertString'],
'currency_id' => ['currency_id', 'convertInteger'],
'currency_code' => ['currency_code', 'convertString'],
'notes' => ['notes', 'stringWithNewlines'],
];
if (false === $this->has('notes')) {
// ignore notes, not submitted.
unset($fields['notes']);
}
return $this->getAllData($fields);
}
@@ -67,6 +72,7 @@ class UpdateRequest extends FormRequest
'amount' => ['nullable', new IsValidPositiveAmount()],
'currency_id' => 'numeric|exists:transaction_currencies,id',
'currency_code' => 'min:3|max:51|exists:transaction_currencies,code',
'notes' => 'nullable|min:0|max:32768',
];
}

View File

@@ -24,10 +24,15 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Models\PiggyBank;
use FireflyIII\Rules\IsValidPositiveAmount;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Rules\IsValidZeroOrMoreAmount;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\Validator;
/**
* Class StoreRequest
@@ -47,18 +52,38 @@ class StoreRequest extends FormRequest
];
$data = $this->getAllData($fields);
$data['name'] = $this->convertString('name');
$data['account_id'] = $this->convertInteger('account_id');
$data['targetamount'] = $this->convertString('target_amount');
$data['current_amount'] = $this->convertString('current_amount');
$data['startdate'] = $this->getCarbonDate('start_date');
$data['targetdate'] = $this->getCarbonDate('target_date');
$data['accounts'] = $this->parseAccounts($this->get('accounts'));
$data['target_amount'] = $this->convertString('target_amount');
$data['start_date'] = $this->getCarbonDate('start_date');
$data['target_date'] = $this->getCarbonDate('target_date');
$data['notes'] = $this->stringWithNewlines('notes');
$data['object_group_id'] = $this->convertInteger('object_group_id');
$data['transaction_currency_id'] = $this->convertInteger('transaction_currency_id');
$data['transaction_currency_code'] = $this->convertString('transaction_currency_code');
$data['object_group_title'] = $this->convertString('object_group_title');
return $data;
}
private function parseAccounts(mixed $array): array
{
if (!is_array($array)) {
return [];
}
$return = [];
foreach ($array as $entry) {
if (!is_array($entry)) {
continue;
}
$return[] = [
'account_id' => $this->integerFromValue((string) ($entry['account_id'] ?? '0')),
'current_amount' => $this->clearString((string) ($entry['current_amount'] ?? '0')),
];
}
return $return;
}
/**
* The rules that the incoming request must be matched against.
*/
@@ -66,14 +91,79 @@ class StoreRequest extends FormRequest
{
return [
'name' => 'required|min:1|max:255|uniquePiggyBankForUser',
'current_amount' => ['nullable', new IsValidPositiveAmount()],
'account_id' => 'required|numeric|belongsToUser:accounts,id',
'accounts' => 'required',
'accounts.*' => 'array|required',
'accounts.*.account_id' => 'required|numeric|belongsToUser:accounts,id',
'accounts.*.current_amount' => ['numeric', new IsValidZeroOrMoreAmount()],
'object_group_id' => 'numeric|belongsToUser:object_groups,id',
'object_group_title' => ['min:1', 'max:255'],
'target_amount' => ['required', new IsValidPositiveAmount()],
'target_amount' => ['required', new IsValidZeroOrMoreAmount()],
'start_date' => 'date|nullable',
'transaction_currency_id' => 'exists:transaction_currencies,id|required_without:transaction_currency_code',
'transaction_currency_code' => 'exists:transaction_currencies,code|required_without:transaction_currency_id',
'target_date' => 'date|nullable|after:start_date',
'notes' => 'max:65000',
];
}
/**
* Can only store money on liabilities and asset accounts.
*/
public function withValidator(Validator $validator): void
{
$validator->after(
function (Validator $validator): void {
// validate start before end only if both are there.
$data = $validator->getData();
$currency = $this->getCurrencyFromData($data);
$targetAmount = (string) ($data['target_amount'] ?? '0');
$currentAmount = '0';
if (array_key_exists('accounts', $data) && is_array($data['accounts'])) {
$repository = app(AccountRepositoryInterface::class);
$types = config('firefly.piggy_bank_account_types');
foreach ($data['accounts'] as $index => $array) {
$accountId = (int) ($array['account_id'] ?? 0);
$account = $repository->find($accountId);
if (null !== $account) {
// check currency here.
$accountCurrency = $repository->getAccountCurrency($account);
$isMultiCurrency = $repository->getMetaValue($account, 'is_multi_currency');
$currentAmount = bcadd($currentAmount, (string) ($array['current_amount'] ?? '0'));
if ($accountCurrency->id !== $currency->id && 'true' !== $isMultiCurrency) {
$validator->errors()->add(sprintf('accounts.%d', $index), trans('validation.invalid_account_currency'));
}
$type = $account->accountType->type;
if (!in_array($type, $types, true)) {
$validator->errors()->add(sprintf('accounts.%d', $index), trans('validation.invalid_account_type'));
}
}
}
}
if (-1 === bccomp($targetAmount, $currentAmount) && 1 === bccomp($targetAmount, '0')) {
$validator->errors()->add('target_amount', trans('validation.current_amount_too_much'));
}
}
);
if ($validator->fails()) {
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
}
}
private function getCurrencyFromData(array $data): TransactionCurrency
{
if (array_key_exists('transaction_currency_code', $data) && '' !== (string) $data['transaction_currency_code']) {
$currency = TransactionCurrency::whereCode($data['transaction_currency_code'])->first();
if (null !== $currency) {
return $currency;
}
}
if (array_key_exists('transaction_currency_id', $data) && '' !== (string) $data['transaction_currency_id']) {
$currency = TransactionCurrency::find((int) $data['transaction_currency_id']);
if (null !== $currency) {
return $currency;
}
}
throw new FireflyException('Unexpected empty currency.');
}
}

View File

@@ -119,7 +119,7 @@ class StoreRequest extends FormRequest
'description' => 'min:1|max:32768|nullable',
'rule_group_id' => 'belongsToUser:rule_groups|required_without:rule_group_title',
'rule_group_title' => 'nullable|min:1|max:255|required_without:rule_group_id|belongsToUser:rule_groups,title',
'trigger' => 'required|in:store-journal,update-journal',
'trigger' => 'required|in:store-journal,update-journal,manual-activation',
'triggers.*.type' => 'required|in:'.implode(',', $validTriggers),
'triggers.*.value' => 'required_if:actions.*.type,'.$contextTriggers.'|min:1|ruleTriggerValue|max:1024',
'triggers.*.stop_processing' => [new IsBoolean()],

View File

@@ -138,7 +138,7 @@ class UpdateRequest extends FormRequest
'description' => 'min:1|max:32768|nullable',
'rule_group_id' => 'belongsToUser:rule_groups',
'rule_group_title' => 'nullable|min:1|max:255|belongsToUser:rule_groups,title',
'trigger' => 'in:store-journal,update-journal',
'trigger' => 'in:store-journal,update-journal.manual-activation',
'triggers.*.type' => 'required|in:'.implode(',', $validTriggers),
'triggers.*.value' => 'required_if:actions.*.type,'.$contextTriggers.'|min:1|ruleTriggerValue|max:1024',
'triggers.*.stop_processing' => [new IsBoolean()],

View File

@@ -40,9 +40,9 @@ use Illuminate\Support\Facades\Log;
*/
class AccountController extends Controller
{
private AccountRepositoryInterface $repository;
private TransactionCurrency $default;
private ExchangeRateConverter $converter;
private TransactionCurrency $default;
private AccountRepositoryInterface $repository;
/**
* AccountController constructor.

View File

@@ -45,9 +45,9 @@ class AccountController extends Controller
use CollectsAccountsFromFilter;
use ValidatesUserGroupTrait;
private AccountRepositoryInterface $repository;
private ChartData $chartData;
private TransactionCurrency $default;
private AccountRepositoryInterface $repository;
public function __construct()
{
@@ -118,22 +118,21 @@ class AccountController extends Controller
'native_entries' => [],
];
$currentStart = clone $params['start'];
$range = app('steam')->balanceInRange($account, $params['start'], clone $params['end'], $currency);
$rangeConverted = app('steam')->balanceInRangeConverted($account, $params['start'], clone $params['end'], $this->default);
$range = app('steam')->finalAccountBalanceInRange($account, $params['start'], clone $params['end'], $this->convertToNative);
$previous = array_values($range)[0];
$previousConverted = array_values($rangeConverted)[0];
$previous = array_values($range)[0]['balance'];
$previousNative = array_values($range)[0]['native_balance'];
while ($currentStart <= $params['end']) {
$format = $currentStart->format('Y-m-d');
$label = $currentStart->toAtomString();
$balance = array_key_exists($format, $range) ? $range[$format] : $previous;
$balanceConverted = array_key_exists($format, $rangeConverted) ? $rangeConverted[$format] : $previousConverted;
$balance = array_key_exists($format, $range) ? $range[$format]['balance'] : $previous;
$balanceNative = array_key_exists($format, $range) ? $range[$format]['balance_native'] : $previousNative;
$previous = $balance;
$previousConverted = $balanceConverted;
$previousNative = $balanceNative;
$currentStart->addDay();
$currentSet['entries'][$label] = $balance;
$currentSet['native_entries'][$label] = $balanceConverted;
$currentSet['native_entries'][$label] = $balanceNative;
}
$this->chartData->add($currentSet);
}

View File

@@ -45,9 +45,10 @@ class BalanceController extends Controller
use CleansChartData;
use CollectsAccountsFromFilter;
private AccountRepositoryInterface $repository;
private GroupCollectorInterface $collector;
private ChartData $chartData;
private GroupCollectorInterface $collector;
private AccountRepositoryInterface $repository;
// private TransactionCurrency $default;
public function __construct()

View File

@@ -27,10 +27,10 @@ namespace FireflyIII\Api\V2\Controllers\Chart;
use Carbon\Carbon;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Generic\DateRequest;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Http\Api\CleansChartData;
@@ -70,7 +70,7 @@ class CategoryController extends Controller
*
* @throws FireflyException
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function dashboard(DateRequest $request): JsonResponse
{
@@ -81,7 +81,7 @@ class CategoryController extends Controller
/** @var Carbon $end */
$end = $this->parameters->get('end');
$accounts = $this->accountRepos->getAccountsByType([AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::ASSET, AccountType::DEFAULT]);
$accounts = $this->accountRepos->getAccountsByType([AccountTypeEnum::DEBT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value]);
$default = app('amount')->getDefaultCurrency();
$converter = new ExchangeRateConverter();
$currencies = [];

View File

@@ -47,16 +47,17 @@ use Symfony\Component\HttpFoundation\ParameterBag;
/**
* Class Controller
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
* @SuppressWarnings(PHPMD.NumberOfChildren)
* @SuppressWarnings("PHPMD.CouplingBetweenObjects")
* @SuppressWarnings("PHPMD.NumberOfChildren")
*/
class Controller extends BaseController
{
use ValidatesUserGroupTrait;
protected const string CONTENT_TYPE = 'application/vnd.api+json';
protected ParameterBag $parameters;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
protected ParameterBag $parameters;
protected bool $convertToNative = false;
public function __construct()
{
@@ -73,7 +74,7 @@ class Controller extends BaseController
* TODO duplicate from V1 controller
* Method to grab all parameters from the URL.
*
* @SuppressWarnings(PHPMD.NPathComplexity)
* @SuppressWarnings("PHPMD.NPathComplexity")
*/
private function getParameters(): ParameterBag
{
@@ -92,8 +93,8 @@ class Controller extends BaseController
if ($page < 1) {
$page = 1;
}
if ($page > (2 ^ 16)) {
$page = (2 ^ 16);
if ($page > 2 ** 16) {
$page = 2 ** 16;
}
$bag->set('page', $page);

View File

@@ -1,112 +0,0 @@
<?php
/*
* AccountController.php
* Copyright (c) 2024 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/.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\JsonApi;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\JsonApi\V2\Accounts\AccountCollectionQuery;
use FireflyIII\JsonApi\V2\Accounts\AccountSchema;
use FireflyIII\JsonApi\V2\Accounts\AccountSingleQuery;
use FireflyIII\Models\Account;
use Illuminate\Contracts\Support\Responsable;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Log;
use LaravelJsonApi\Core\Responses\DataResponse;
use LaravelJsonApi\Laravel\Http\Controllers\Actions;
/**
* Class AccountController
*
* This class handles api/v2 requests for accounts.
* Most stuff is default stuff.
*/
class AccountController extends Controller
{
use Actions\AttachRelationship;
use Actions\Destroy;
use Actions\DetachRelationship;
use Actions\FetchMany;
// use Actions\FetchOne;
use Actions\FetchRelated;
use Actions\FetchRelationship;
use Actions\Store;
use Actions\Update;
use Actions\UpdateRelationship;
/**
* Fetch zero to many JSON API resources.
*
* @return Responsable|Response
*/
public function index(AccountSchema $schema, AccountCollectionQuery $request)
{
Log::debug(__METHOD__);
$models = $schema
->repository()
->queryAll()
->withRequest($request)
->get()
;
// do something custom...
return new DataResponse($models);
}
/**
* Fetch zero to one JSON API resource by id.
*
* @return Responsable|Response
*/
public function show(AccountSchema $schema, AccountSingleQuery $request, Account $account)
{
Log::debug(__METHOD__);
$model = $schema->repository()
->queryOne($account)
->withRequest($request)
->first()
;
Log::debug(sprintf('%s again!', __METHOD__));
// do something custom...
return new DataResponse($model);
}
// public function readAccountBalances(AnonymousQuery $query, AccountBalanceSchema $schema, Account $account): Responsable
// {
// $schema = JsonApi::server()->schemas()->schemaFor('account-balances');
//
// $models = $schema
// ->repository()
// ->queryAll()
// ->withRequest($query)
// ->withAccount($account)
// ->get()
// ;
//
// return DataResponse::make($models);
// }
}

View File

@@ -36,9 +36,8 @@ use Illuminate\Support\Facades\Log;
class IndexController extends Controller
{
public const string RESOURCE_KEY = 'accounts';
private AccountRepositoryInterface $repository;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY, UserRoleEnum::MANAGE_TRANSACTIONS];
private AccountRepositoryInterface $repository;
/**
* AccountController constructor.

View File

@@ -39,9 +39,8 @@ use Illuminate\Http\JsonResponse;
class ShowController extends Controller
{
public const string RESOURCE_KEY = 'accounts';
private AccountRepositoryInterface $repository;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY, UserRoleEnum::MANAGE_TRANSACTIONS];
private AccountRepositoryInterface $repository;
/**
* AccountController constructor.

View File

@@ -58,7 +58,7 @@ class SumController extends Controller
*
* TODO see autocomplete/accountcontroller for list.
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function paid(DateRequest $request): JsonResponse
{
@@ -74,7 +74,7 @@ class SumController extends Controller
*
* TODO see autocomplete/accountcontroller for list.
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function unpaid(DateRequest $request): JsonResponse
{

View File

@@ -0,0 +1,67 @@
<?php
/*
* DestroyController.php
* Copyright (c) 2024 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/.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Model\ExchangeRate;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Model\ExchangeRate\DestroyRequest;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\UserGroups\ExchangeRate\ExchangeRateRepositoryInterface;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use Illuminate\Http\JsonResponse;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class DestroyController extends Controller
{
use ValidatesUserGroupTrait;
public const string RESOURCE_KEY = 'exchange-rates';
private ExchangeRateRepositoryInterface $repository;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(ExchangeRateRepositoryInterface::class);
$this->repository->setUserGroup($this->validateUserGroup($request));
return $next($request);
}
);
}
public function destroy(DestroyRequest $request, TransactionCurrency $from, TransactionCurrency $to): JsonResponse
{
$date = $request->getDate();
$rate = $this->repository->getSpecificRateOnDate($from, $to, $date);
if (null === $rate) {
throw new NotFoundHttpException();
}
$this->repository->deleteRate($rate);
return response()->json([], 204);
}
}

View File

@@ -0,0 +1,76 @@
<?php
/*
* ShowController.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Model\ExchangeRate;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Repositories\UserGroups\ExchangeRate\ExchangeRateRepositoryInterface;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Transformers\V2\ExchangeRateTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator;
/**
* Class ShowController
*/
class IndexController extends Controller
{
use ValidatesUserGroupTrait;
public const string RESOURCE_KEY = 'exchange-rates';
private ExchangeRateRepositoryInterface $repository;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(ExchangeRateRepositoryInterface::class);
$this->repository->setUserGroup($this->validateUserGroup($request));
return $next($request);
}
);
}
public function index(): JsonResponse
{
$piggies = $this->repository->getAll();
$pageSize = $this->parameters->get('limit');
$count = $piggies->count();
$piggies = $piggies->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($piggies, $count, $pageSize, $this->parameters->get('page'));
var_dump('here we are');
$transformer = new ExchangeRateTransformer();
$transformer->setParameters($this->parameters); // give params to transformer
return response()
->json($this->jsonApiList(self::RESOURCE_KEY, $paginator, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
}

View File

@@ -0,0 +1,76 @@
<?php
/*
* ShowController.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Model\ExchangeRate;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\UserGroups\ExchangeRate\ExchangeRateRepositoryInterface;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Transformers\V2\ExchangeRateTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator;
/**
* Class ShowController
*/
class ShowController extends Controller
{
use ValidatesUserGroupTrait;
public const string RESOURCE_KEY = 'exchange-rates';
private ExchangeRateRepositoryInterface $repository;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(ExchangeRateRepositoryInterface::class);
$this->repository->setUserGroup($this->validateUserGroup($request));
return $next($request);
}
);
}
public function show(TransactionCurrency $from, TransactionCurrency $to): JsonResponse
{
$pageSize = $this->parameters->get('limit');
$page = $this->parameters->get('page');
$rates = $this->repository->getRates($from, $to);
$count = $rates->count();
$rates = $rates->slice(($page - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($rates, $count, $pageSize, $page);
$transformer = new ExchangeRateTransformer();
$transformer->setParameters($this->parameters); // give params to transformer
return response()
->json($this->jsonApiList(self::RESOURCE_KEY, $paginator, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
}

View File

@@ -0,0 +1,81 @@
<?php
/*
* DestroyController.php
* Copyright (c) 2024 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/.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Model\ExchangeRate;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Model\ExchangeRate\StoreRequest;
use FireflyIII\Repositories\UserGroups\ExchangeRate\ExchangeRateRepositoryInterface;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Transformers\V2\ExchangeRateTransformer;
use Illuminate\Http\JsonResponse;
class StoreController extends Controller
{
use ValidatesUserGroupTrait;
public const string RESOURCE_KEY = 'exchange-rates';
private ExchangeRateRepositoryInterface $repository;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(ExchangeRateRepositoryInterface::class);
$this->repository->setUserGroup($this->validateUserGroup($request));
return $next($request);
}
);
}
public function store(StoreRequest $request): JsonResponse
{
$date = $request->getDate();
$rate = $request->getRate();
$from = $request->getFromCurrency();
$to = $request->getToCurrency();
// already has rate?
$object = $this->repository->getSpecificRateOnDate($from, $to, $date);
if (null !== $object) {
// just update it, no matter.
$rate = $this->repository->updateExchangeRate($object, $rate, $date);
}
if (null === $object) {
// store new
$rate = $this->repository->storeExchangeRate($from, $to, $rate, $date);
}
$transformer = new ExchangeRateTransformer();
$transformer->setParameters($this->parameters);
return response()
->api($this->jsonApiObject(self::RESOURCE_KEY, $rate, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
}

View File

@@ -0,0 +1,69 @@
<?php
/*
* DestroyController.php
* Copyright (c) 2024 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/.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Model\ExchangeRate;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Model\ExchangeRate\UpdateRequest;
use FireflyIII\Models\CurrencyExchangeRate;
use FireflyIII\Repositories\UserGroups\ExchangeRate\ExchangeRateRepositoryInterface;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Transformers\V2\ExchangeRateTransformer;
use Illuminate\Http\JsonResponse;
class UpdateController extends Controller
{
use ValidatesUserGroupTrait;
public const string RESOURCE_KEY = 'exchange-rates';
private ExchangeRateRepositoryInterface $repository;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(ExchangeRateRepositoryInterface::class);
$this->repository->setUserGroup($this->validateUserGroup($request));
return $next($request);
}
);
}
public function update(UpdateRequest $request, CurrencyExchangeRate $exchangeRate): JsonResponse
{
$date = $request->getDate();
$rate = $request->getRate();
$exchangeRate = $this->repository->updateExchangeRate($exchangeRate, $rate, $date);
$transformer = new ExchangeRateTransformer();
$transformer->setParameters($this->parameters);
return response()
->api($this->jsonApiObject(self::RESOURCE_KEY, $exchangeRate, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
}

View File

@@ -80,21 +80,21 @@ class StoreController extends Controller
try {
$transactionGroup = $this->groupRepository->store($data);
} catch (DuplicateTransactionException $e) { // @phpstan-ignore-line
} catch (DuplicateTransactionException $e) {
app('log')->warning('Caught a duplicate transaction. Return error message.');
$validator = Validator::make(
['transactions' => [['description' => $e->getMessage()]]],
['transactions.0.description' => new IsDuplicateTransaction()]
);
throw new ValidationException($validator); // @phpstan-ignore-line
} catch (FireflyException $e) { // @phpstan-ignore-line
throw new ValidationException($validator);
} catch (FireflyException $e) {
app('log')->warning('Caught an exception. Return error message.');
app('log')->error($e->getMessage());
$message = sprintf('Internal exception: %s', $e->getMessage());
$validator = Validator::make(['transactions' => [['description' => $message]]], ['transactions.0.description' => new IsDuplicateTransaction()]);
throw new ValidationException($validator); // @phpstan-ignore-line
throw new ValidationException($validator);
}
app('preferences')->mark();
$applyRules = $data['apply_rules'] ?? true;

View File

@@ -0,0 +1,83 @@
<?php
/*
* IndexController.php
* Copyright (c) 2024 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/.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Model\TransactionCurrency;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Model\TransactionCurrency\IndexRequest;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\Transformers\V2\CurrencyTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator;
class IndexController extends Controller
{
public const string RESOURCE_KEY = 'transaction-currencies';
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
private CurrencyRepositoryInterface $repository;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(CurrencyRepositoryInterface::class);
// new way of user group validation
$userGroup = $this->validateUserGroup($request);
$this->repository->setUserGroup($userGroup);
return $next($request);
}
);
}
public function index(IndexRequest $request): JsonResponse
{
$settings = $request->getAll();
if (true === $settings['enabled']) {
$currencies = $this->repository->get();
}
if (true !== $settings['enabled']) {
$currencies = $this->repository->getAll();
}
$pageSize = $this->parameters->get('limit');
$count = $currencies->count();
// depending on the sort parameters, this list must not be split, because the
// order is calculated in the account transformer and by that time it's too late.
$accounts = $currencies->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page'));
$transformer = new CurrencyTransformer();
$this->parameters->set('pageSize', $pageSize);
$transformer->setParameters($this->parameters); // give params to transformer
return response()
->json($this->jsonApiList(self::RESOURCE_KEY, $paginator, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
}

View File

@@ -0,0 +1,80 @@
<?php
/*
* ShowController.php
* Copyright (c) 2021 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/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Model\TransactionCurrency;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\UserGroup;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\Transformers\V2\CurrencyTransformer;
use Illuminate\Http\JsonResponse;
/**
* Class ShowController
*/
class ShowController extends Controller
{
public const string RESOURCE_KEY = 'transaction-currencies';
private CurrencyRepositoryInterface $repository;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(CurrencyRepositoryInterface::class);
// new way of user group validation
$userGroup = $this->validateUserGroup($request);
$this->repository->setUserGroup($userGroup);
return $next($request);
}
);
}
public function show(TransactionCurrency $currency): JsonResponse
{
$groups = $currency->userGroups()->where('user_groups.id', $this->repository->getUserGroup()->id)->get();
$enabled = $groups->count() > 0;
$default = false;
/** @var UserGroup $group */
foreach ($groups as $group) {
$default = 1 === $group->pivot->group_default;
}
$currency->userGroupEnabled = $enabled;
$currency->userGroupDefault = $default;
$transformer = new CurrencyTransformer();
$transformer->setParameters($this->parameters);
return response()
->api($this->jsonApiObject(self::RESOURCE_KEY, $currency, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
}

View File

@@ -27,12 +27,12 @@ namespace FireflyIII\Api\V2\Controllers\Summary;
use Carbon\Carbon;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Generic\DateRequest;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Helpers\Report\NetWorthInterface;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\UserGroup;
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Bill\BillRepositoryInterface;
@@ -94,7 +94,7 @@ class BasicController extends Controller
*
* @throws \Exception
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function basic(DateRequest $request): JsonResponse
{
@@ -222,7 +222,7 @@ class BasicController extends Controller
}
/**
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings("PHPMD.ExcessiveMethodLength")
*/
private function getLeftToSpendInfo(Carbon $start, Carbon $end): array
{
@@ -353,7 +353,7 @@ class BasicController extends Controller
$netWorthHelper = app(NetWorthInterface::class);
$netWorthHelper->setUserGroup($userGroup);
$allAccounts = $this->accountRepository->getActiveAccountsByType(
[AccountType::ASSET, AccountType::DEFAULT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::DEBT]
[AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::DEBT->value]
);
// filter list on preference of being included.

View File

@@ -26,9 +26,9 @@ namespace FireflyIII\Api\V2\Controllers\Summary;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Generic\SingleDateRequest;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Helpers\Report\NetWorthInterface;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use Illuminate\Http\JsonResponse;
@@ -67,7 +67,7 @@ class NetWorthController extends Controller
public function get(SingleDateRequest $request): JsonResponse
{
$date = $request->getDate();
$accounts = $this->repository->getAccountsByType([AccountType::ASSET, AccountType::DEFAULT, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE]);
$accounts = $this->repository->getAccountsByType([AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::MORTGAGE->value]);
// filter list on preference of being included.
$filtered = $accounts->filter(

View File

@@ -24,9 +24,8 @@ declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\Autocomplete;
use FireflyIII\Models\AccountType;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Support\Http\Api\ParsesQueryFilters;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
@@ -39,7 +38,6 @@ class AutocompleteRequest extends FormRequest
use AccountFilter;
use ChecksLogin;
use ConvertsDataTypes;
use ParsesQueryFilters;
/**
* Loops over all possible query parameters (these are shared over ALL auto complete requests)
@@ -67,12 +65,22 @@ class AutocompleteRequest extends FormRequest
}
// remove 'initial balance' from allowed types. its internal
$array['account_types'] = array_diff($array['account_types'], [AccountType::INITIAL_BALANCE, AccountType::RECONCILIATION, AccountType::CREDITCARD]);
$array['account_types'] = array_diff($array['account_types'], [AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::RECONCILIATION->value, AccountTypeEnum::CREDITCARD->value]);
$array['account_types'] = $this->getAccountTypeParameter($array['account_types']);
return $array;
}
private function getAccountTypeParameter(array $types): array
{
$return = [];
foreach ($types as $type) {
$return = array_merge($return, $this->mapAccountTypes($type));
}
return array_unique($return);
}
public function rules(): array
{
$valid = array_keys($this->types);
@@ -86,14 +94,4 @@ class AutocompleteRequest extends FormRequest
'transaction_types' => 'nullable|in:todo',
];
}
private function getAccountTypeParameter(array $types): array
{
$return = [];
foreach ($types as $type) {
$return = array_merge($return, $this->mapAccountTypes($type));
}
return array_unique($return);
}
}

View File

@@ -40,6 +40,7 @@ class BalanceChartRequest extends FormRequest
use ChecksLogin;
use ConvertsDataTypes;
use ValidatesUserGroupTrait;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
/**

View File

@@ -25,7 +25,6 @@ declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\Chart;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Support\Http\Api\ParsesQueryFilters;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
@@ -40,7 +39,6 @@ class ChartRequest extends FormRequest
{
use ChecksLogin;
use ConvertsDataTypes;
use ParsesQueryFilters;
use ValidatesUserGroupTrait;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];

View File

@@ -1,7 +1,7 @@
<?php
/*
* CollectsCustomParameters.php
* DestroyRequest.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
@@ -22,25 +22,30 @@
declare(strict_types=1);
namespace FireflyIII\Support\JsonApi;
namespace FireflyIII\Api\V2\Request\Model\ExchangeRate;
use Carbon\Carbon;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
trait CollectsCustomParameters
class DestroyRequest extends FormRequest
{
protected function getOtherParams(array $params): array
use ChecksLogin;
use ConvertsDataTypes;
public function getDate(): Carbon
{
$return = [];
if (array_key_exists('startPeriod', $params)) {
$return['start'] = Carbon::parse($params['startPeriod']);
}
if (array_key_exists('endPeriod', $params)) {
$return['end'] = Carbon::parse($params['endPeriod']);
}
if (array_key_exists('currentMoment', $params)) {
$return['today'] = Carbon::parse($params['currentMoment']);
return $this->getCarbonDate('date');
}
return $return;
/**
* The rules that the incoming request must be matched against.
*/
public function rules(): array
{
return [
'date' => 'required|date|after:1900-01-01|before:2099-12-31',
];
}
}

View File

@@ -0,0 +1,70 @@
<?php
/*
* DestroyRequest.php
* Copyright (c) 2024 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/.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\Model\ExchangeRate;
use Carbon\Carbon;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
class StoreRequest extends FormRequest
{
use ChecksLogin;
use ConvertsDataTypes;
public function getDate(): ?Carbon
{
return $this->getCarbonDate('date');
}
public function getRate(): string
{
return (string) $this->get('rate');
}
public function getFromCurrency(): TransactionCurrency
{
return TransactionCurrency::where('code', $this->get('from'))->first();
}
public function getToCurrency(): TransactionCurrency
{
return TransactionCurrency::where('code', $this->get('to'))->first();
}
/**
* The rules that the incoming request must be matched against.
*/
public function rules(): array
{
return [
'date' => 'required|date|after:1900-01-01|before:2099-12-31',
'rate' => 'required|numeric|gt:0',
'from' => 'required|exists:transaction_currencies,code',
'to' => 'required|exists:transaction_currencies,code',
];
}
}

View File

@@ -1,7 +1,7 @@
<?php
/*
* AccountBalanceQuery.php
* DestroyRequest.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
@@ -22,38 +22,36 @@
declare(strict_types=1);
namespace FireflyIII\JsonApi\V2\AccountBalances\Capabilities;
namespace FireflyIII\Api\V2\Request\Model\ExchangeRate;
use FireflyIII\Entities\AccountBalance;
use FireflyIII\Models\Account;
use LaravelJsonApi\NonEloquent\Capabilities\QueryAll;
use Carbon\Carbon;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
class AccountBalanceQuery extends QueryAll
class UpdateRequest extends FormRequest
{
private Account $account;
use ChecksLogin;
use ConvertsDataTypes;
public function getDate(): ?Carbon
{
return $this->getCarbonDate('date');
}
public function getRate(): string
{
return (string) $this->get('rate');
}
/**
* QuerySites constructor.
* The rules that the incoming request must be matched against.
*/
public function __construct()
{
parent::__construct();
}
public function get(): iterable
public function rules(): array
{
return [
AccountBalance::fromArray(),
AccountBalance::fromArray(),
AccountBalance::fromArray(),
AccountBalance::fromArray(),
'date' => 'date|after:1900-01-01|before:2099-12-31',
'rate' => 'required|numeric|gt:0',
];
}
public function withAccount(Account $account): self
{
$this->account = $account;
return $this;
}
}

View File

@@ -0,0 +1,64 @@
<?php
/*
* IndexRequest.php
* Copyright (c) 2024 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/.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\Model\TransactionCurrency;
use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\Support\Request\GetFilterInstructions;
use FireflyIII\Support\Request\GetSortInstructions;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class IndexRequest
*
* Lots of code stolen from the SingleDateRequest.
*/
class IndexRequest extends FormRequest
{
use AccountFilter;
use ChecksLogin;
use ConvertsDataTypes;
use GetFilterInstructions;
use GetSortInstructions;
public function getAll(): array
{
return [
'enabled' => $this->convertBoolean($this->get('enabled')),
];
}
/**
* The rules that the incoming request must be matched against.
*/
public function rules(): array
{
return [
'enabled' => 'nullable|boolean',
];
}
}

View File

@@ -1,5 +1,26 @@
<?php
/*
* SeparateTimezoneCaster.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/.
*/
declare(strict_types=1);
namespace FireflyIII\Casts;

View File

@@ -1,5 +1,25 @@
<?php
/*
* ConvertsDatesToUTC.php
* Copyright (c) 2024 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/.
*/
declare(strict_types=1);
/*
* ConvertDatesToUTC.php
@@ -21,7 +41,7 @@ declare(strict_types=1);
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
namespace FireflyIII\Console\Commands\Integrity;
namespace FireflyIII\Console\Commands\Correction;
use Carbon\Carbon;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
@@ -31,34 +51,28 @@ use Illuminate\Database\QueryException;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
class ConvertDatesToUTC extends Command
class ConvertsDatesToUTC extends Command
{
use ShowsFriendlyMessages;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'firefly-iii:migrate-to-utc';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Convert stored dates to UTC.';
protected $signature = 'correction:convert-to-utc';
/**
* Execute the console command.
*/
public function handle(): int
{
$this->friendlyWarning('Please do not use this command right now.');
// this variable is ALWAYS en_US.
// stops phpstan complaining about dead code.
if ('en_US' === config('app.fallback_locale')) {
return Command::SUCCESS;
}
/**
* @var string $model
* @var array $fields
*/
foreach (AddTimezonesToDates::$models as $model => $fields) {
foreach (CorrectsTimezoneInformation::$models as $model => $fields) {
$this->ConvertModeltoUTC($model, $fields);
}
// tell the system we are now in UTC mode.
@@ -98,10 +112,10 @@ class ConvertDatesToUTC extends Command
$items->each(
function ($item) use ($field, $timezoneField): void {
/** @var Carbon $date */
$date = Carbon::parse($item->{$field}, $item->{$timezoneField});
$date = Carbon::parse($item->{$field}, $item->{$timezoneField}); // @phpstan-ignore-line
$date->setTimezone('UTC');
$item->{$field} = $date->format('Y-m-d H:i:s');
$item->{$timezoneField} = 'UTC';
$item->{$field} = $date->format('Y-m-d H:i:s'); // @phpstan-ignore-line
$item->{$timezoneField} = 'UTC'; // @phpstan-ignore-line
$item->save();
}
);

View File

@@ -1,253 +0,0 @@
<?php
/*
* CorrectAmounts.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Models\AutoBudget;
use FireflyIII\Models\AvailableBudget;
use FireflyIII\Models\Bill;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Models\CurrencyExchangeRate;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankRepetition;
use FireflyIII\Models\RecurrenceTransaction;
use FireflyIII\Models\RuleTrigger;
use Illuminate\Console\Command;
/**
* Class ReportSkeleton
*/
class CorrectAmounts extends Command
{
use ShowsFriendlyMessages;
protected $description = 'This command makes sure positive and negative amounts are recorded correctly.';
protected $signature = 'firefly-iii:fix-amount-pos-neg';
public function handle(): int
{
// auto budgets must be positive
$this->fixAutoBudgets();
// available budgets must be positive
$this->fixAvailableBudgets();
// bills must be positive (both amounts)
$this->fixBills();
// budget limits must be positive
$this->fixBudgetLimits();
// currency_exchange_rates must be positive
$this->fixExchangeRates();
// piggy_bank_repetitions must be positive
$this->fixRepetitions();
// piggy_banks must be positive
$this->fixPiggyBanks();
// recurrences_transactions amount must be positive
$this->fixRecurrences();
// rule_triggers must be positive or zero (amount_less, amount_more, amount_is)
$this->fixRuleTriggers();
return 0;
}
private function fixAutoBudgets(): void
{
$set = AutoBudget::where('amount', '<', 0)->get();
$count = $set->count();
if (0 === $count) {
$this->friendlyPositive('All auto budget amounts are positive.');
return;
}
/** @var AutoBudget $item */
foreach ($set as $item) {
$item->amount = app('steam')->positive($item->amount);
$item->save();
}
$this->friendlyInfo(sprintf('Corrected %d auto budget amount(s).', $count));
}
private function fixAvailableBudgets(): void
{
$set = AvailableBudget::where('amount', '<', 0)->get();
$count = $set->count();
if (0 === $count) {
$this->friendlyPositive('All available budget amounts are positive.');
return;
}
/** @var AvailableBudget $item */
foreach ($set as $item) {
$item->amount = app('steam')->positive($item->amount);
$item->save();
}
$this->friendlyInfo(sprintf('Corrected %d available budget amount(s).', $count));
}
private function fixBills(): void
{
$set = Bill::where('amount_min', '<', 0)->orWhere('amount_max', '<', 0)->get();
$count = $set->count();
if (0 === $count) {
$this->friendlyPositive('All bill amounts are positive.');
return;
}
/** @var Bill $item */
foreach ($set as $item) {
$item->amount_min = app('steam')->positive($item->amount_min);
$item->amount_max = app('steam')->positive($item->amount_max);
$item->save();
}
$this->friendlyInfo(sprintf('Corrected %d bill amount(s).', $count));
}
private function fixBudgetLimits(): void
{
$set = BudgetLimit::where('amount', '<', 0)->get();
$count = $set->count();
if (0 === $count) {
$this->friendlyPositive('All budget limit amounts are positive.');
return;
}
/** @var BudgetLimit $item */
foreach ($set as $item) {
$item->amount = app('steam')->positive($item->amount);
$item->save();
}
$this->friendlyInfo(sprintf('Corrected %d budget limit amount(s).', $count));
}
private function fixExchangeRates(): void
{
$set = CurrencyExchangeRate::where('rate', '<', 0)->get();
$count = $set->count();
if (0 === $count) {
$this->friendlyPositive('All currency exchange rates are positive.');
return;
}
/** @var CurrencyExchangeRate $item */
foreach ($set as $item) {
$item->rate = app('steam')->positive($item->rate);
$item->save();
}
$this->friendlyInfo(sprintf('Corrected %d currency exchange rate(s).', $count));
}
private function fixRepetitions(): void
{
$set = PiggyBankRepetition::where('currentamount', '<', 0)->get();
$count = $set->count();
if (0 === $count) {
$this->friendlyPositive('All piggy bank repetition amounts are positive.');
return;
}
/** @var PiggyBankRepetition $item */
foreach ($set as $item) {
$item->currentamount = app('steam')->positive($item->currentamount);
$item->save();
}
$this->friendlyInfo(sprintf('Corrected %d piggy bank repetition amount(s).', $count));
}
private function fixPiggyBanks(): void
{
$set = PiggyBank::where('targetamount', '<', 0)->get();
$count = $set->count();
if (0 === $count) {
$this->friendlyPositive('All piggy bank amounts are positive.');
return;
}
/** @var PiggyBank $item */
foreach ($set as $item) {
$item->targetamount = app('steam')->positive($item->targetamount);
$item->save();
}
$this->friendlyInfo(sprintf('Corrected %d piggy bank amount(s).', $count));
}
private function fixRecurrences(): void
{
$set = RecurrenceTransaction::where('amount', '<', 0)
->orWhere('foreign_amount', '<', 0)
->get()
;
$count = $set->count();
if (0 === $count) {
$this->friendlyPositive('All recurring transaction amounts are positive.');
return;
}
/** @var RecurrenceTransaction $item */
foreach ($set as $item) {
$item->amount = app('steam')->positive($item->amount);
$item->foreign_amount = app('steam')->positive($item->foreign_amount);
$item->save();
}
$this->friendlyInfo(sprintf('Corrected %d recurring transaction amount(s).', $count));
}
private function fixRuleTriggers(): void
{
$set = RuleTrigger::whereIn('trigger_type', ['amount_less', 'amount_more', 'amount_is'])->get();
$fixed = 0;
/** @var RuleTrigger $item */
foreach ($set as $item) {
// basic check:
$check = 0;
try {
$check = bccomp((string)$item->trigger_value, '0');
} catch (\ValueError $e) {
$this->friendlyError(sprintf('Rule #%d contained invalid %s-trigger "%s". The trigger has been removed, and the rule is disabled.', $item->rule_id, $item->trigger_type, $item->trigger_value));
$item->rule->active = false;
$item->rule->save();
$item->forceDelete();
}
if (-1 === $check) {
++$fixed;
$item->trigger_value = app('steam')->positive($item->trigger_value);
$item->save();
}
}
if (0 === $fixed) {
$this->friendlyPositive('All rule trigger amounts are positive.');
return;
}
$this->friendlyInfo(sprintf('Corrected %d rule trigger amount(s).', $fixed));
}
}

View File

@@ -4,12 +4,9 @@ namespace FireflyIII\Console\Commands\Correction;
use Illuminate\Console\Command;
/**
* Class CorrectionSkeleton
* TODO DONT FORGET TO ADD THIS TO THE DOCKER BUILD
*/
class CorrectionSkeleton extends Command
{
use ShowsFriendlyMessages;
protected $description = 'DESCRIPTION HERE';
protected $signature = 'firefly-iii:CORR_COMMAND';

View File

@@ -29,15 +29,12 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\User;
use Illuminate\Console\Command;
/**
* Class FixAccountOrder
*/
class FixAccountOrder extends Command
class CorrectsAccountOrder extends Command
{
use ShowsFriendlyMessages;
protected $description = 'Make sure account order is correct.';
protected $signature = 'firefly-iii:fix-account-order';
protected $signature = 'correction:account-order';
private AccountRepositoryInterface $repository;
@@ -54,8 +51,6 @@ class FixAccountOrder extends Command
$this->repository->resetAccountOrder();
}
$this->friendlyPositive('All accounts are ordered correctly');
return 0;
}

View File

@@ -26,9 +26,9 @@ namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Factory\AccountFactory;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
@@ -36,15 +36,12 @@ use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Query\JoinClause;
/**
* Class FixAccountTypes
*/
class FixAccountTypes extends Command
class CorrectsAccountTypes extends Command
{
use ShowsFriendlyMessages;
protected $description = 'Make sure all journals have the correct from/to account types.';
protected $signature = 'firefly-iii:fix-account-types';
protected $signature = 'correction:account-types';
private int $count;
private array $expected;
private AccountFactory $factory;
@@ -114,15 +111,14 @@ class FixAccountTypes extends Command
$this->friendlyLine(sprintf('Found %d journals that need to be fixed.', $resultSet->count()));
foreach ($resultSet as $entry) {
app('log')->debug(sprintf('Now fixing journal #%d', $entry->id));
/** @var null|TransactionJournal $journal */
$journal = TransactionJournal::find($entry->id);
if (null !== $journal) {
$this->inspectJournal($journal);
}
}
}
if (0 === $this->count) {
$this->friendlyPositive('All account types are OK');
}
if (0 !== $this->count) {
app('log')->debug(sprintf('%d journals had to be fixed.', $this->count));
$this->friendlyInfo(sprintf('Acted on %d transaction(s)', $this->count));
@@ -251,18 +247,18 @@ class FixAccountTypes extends Command
private function shouldBeTransfer(string $transactionType, string $sourceType, string $destinationType): bool
{
return TransactionType::TRANSFER === $transactionType && AccountType::ASSET === $sourceType && $this->isLiability($destinationType);
return TransactionTypeEnum::TRANSFER->value === $transactionType && AccountTypeEnum::ASSET->value === $sourceType && $this->isLiability($destinationType);
}
private function isLiability(string $destinationType): bool
{
return AccountType::LOAN === $destinationType || AccountType::DEBT === $destinationType || AccountType::MORTGAGE === $destinationType;
return AccountTypeEnum::LOAN->value === $destinationType || AccountTypeEnum::DEBT->value === $destinationType || AccountTypeEnum::MORTGAGE->value === $destinationType;
}
private function makeTransfer(TransactionJournal $journal): void
{
// from an asset to a liability should be a withdrawal:
$withdrawal = TransactionType::whereType(TransactionType::WITHDRAWAL)->first();
$withdrawal = TransactionType::whereType(TransactionTypeEnum::WITHDRAWAL->value)->first();
$journal->transactionType()->associate($withdrawal);
$journal->save();
$message = sprintf('Converted transaction #%d from a transfer to a withdrawal.', $journal->id);
@@ -274,13 +270,13 @@ class FixAccountTypes extends Command
private function shouldBeDeposit(string $transactionType, string $sourceType, string $destinationType): bool
{
return TransactionType::TRANSFER === $transactionType && $this->isLiability($sourceType) && AccountType::ASSET === $destinationType;
return TransactionTypeEnum::TRANSFER->value === $transactionType && $this->isLiability($sourceType) && AccountTypeEnum::ASSET->value === $destinationType;
}
private function makeDeposit(TransactionJournal $journal): void
{
// from a liability to an asset should be a deposit.
$deposit = TransactionType::whereType(TransactionType::DEPOSIT)->first();
$deposit = TransactionType::whereType(TransactionTypeEnum::DEPOSIT->value)->first();
$journal->transactionType()->associate($deposit);
$journal->save();
$message = sprintf('Converted transaction #%d from a transfer to a deposit.', $journal->id);
@@ -292,7 +288,7 @@ class FixAccountTypes extends Command
private function shouldGoToExpenseAccount(string $transactionType, string $sourceType, string $destinationType): bool
{
return TransactionType::WITHDRAWAL === $transactionType && AccountType::ASSET === $sourceType && AccountType::REVENUE === $destinationType;
return TransactionTypeEnum::WITHDRAWAL->value === $transactionType && AccountTypeEnum::ASSET->value === $sourceType && AccountTypeEnum::REVENUE->value === $destinationType;
}
private function makeExpenseDestination(TransactionJournal $journal, Transaction $destination): void
@@ -300,7 +296,7 @@ class FixAccountTypes extends Command
// withdrawals with a revenue account as destination instead of an expense account.
$this->factory->setUser($journal->user);
$oldDest = $destination->account;
$result = $this->factory->findOrCreate($destination->account->name, AccountType::EXPENSE);
$result = $this->factory->findOrCreate($destination->account->name, AccountTypeEnum::EXPENSE->value);
$destination->account()->associate($result);
$destination->save();
$message = sprintf(
@@ -318,7 +314,7 @@ class FixAccountTypes extends Command
private function shouldComeFromRevenueAccount(string $transactionType, string $sourceType, string $destinationType): bool
{
return TransactionType::DEPOSIT === $transactionType && AccountType::EXPENSE === $sourceType && AccountType::ASSET === $destinationType;
return TransactionTypeEnum::DEPOSIT->value === $transactionType && AccountTypeEnum::EXPENSE->value === $sourceType && AccountTypeEnum::ASSET->value === $destinationType;
}
private function makeRevenueSource(TransactionJournal $journal, Transaction $source): void
@@ -326,7 +322,7 @@ class FixAccountTypes extends Command
// deposits with an expense account as source instead of a revenue account.
// find revenue account.
$this->factory->setUser($journal->user);
$result = $this->factory->findOrCreate($source->account->name, AccountType::REVENUE);
$result = $this->factory->findOrCreate($source->account->name, AccountTypeEnum::REVENUE->value);
$oldSource = $source->account;
$source->account()->associate($result);
$source->save();

View File

@@ -0,0 +1,185 @@
<?php
/*
* CorrectAmounts.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Models\AutoBudget;
use FireflyIII\Models\AvailableBudget;
use FireflyIII\Models\Bill;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Models\CurrencyExchangeRate;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\RecurrenceTransaction;
use FireflyIII\Models\RuleTrigger;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
class CorrectsAmounts extends Command
{
use ShowsFriendlyMessages;
protected $description = 'This command makes sure positive and negative amounts are recorded correctly.';
protected $signature = 'correction:amounts';
public function handle(): int
{
// auto budgets must be positive
$this->fixAutoBudgets();
// available budgets must be positive
$this->fixAvailableBudgets();
// bills must be positive (both amounts)
$this->fixBills();
// budget limits must be positive
$this->fixBudgetLimits();
// currency_exchange_rates must be positive
$this->fixExchangeRates();
// piggy_banks must be positive
$this->fixPiggyBanks();
// recurrences_transactions amount must be positive
$this->fixRecurrences();
// rule_triggers must be positive or zero (amount_less, amount_more, amount_is)
$this->fixRuleTriggers();
return 0;
}
private function fixAutoBudgets(): void
{
$count = AutoBudget::where('amount', '<', 0)->update(['amount' => DB::raw('amount * -1')]);
if (0 === $count) {
return;
}
$this->friendlyInfo(sprintf('Corrected %d auto budget amount(s).', $count));
}
private function fixAvailableBudgets(): void
{
$count = AvailableBudget::where('amount', '<', 0)->update(['amount' => DB::raw('amount * -1')]);
if (0 === $count) {
return;
}
$this->friendlyInfo(sprintf('Corrected %d available budget amount(s).', $count));
}
private function fixBills(): void
{
$count = 0;
$count += Bill::where('amount_max', '<', 0)->update(['amount_max' => DB::raw('amount_max * -1')]);
$count += Bill::where('amount_min', '<', 0)->update(['amount_min' => DB::raw('amount_min * -1')]);
if (0 === $count) {
return;
}
$this->friendlyInfo(sprintf('Corrected %d bill amount(s).', $count));
}
private function fixBudgetLimits(): void
{
$count = BudgetLimit::where('amount', '<', 0)->update(['amount' => DB::raw('amount * -1')]);
if (0 === $count) {
return;
}
$this->friendlyInfo(sprintf('Corrected %d budget limit amount(s).', $count));
}
private function fixExchangeRates(): void
{
$count = CurrencyExchangeRate::where('rate', '<', 0)->update(['rate' => DB::raw('rate * -1')]);
if (0 === $count) {
return;
}
$this->friendlyInfo(sprintf('Corrected %d currency exchange rate(s).', $count));
}
private function fixPiggyBanks(): void
{
$count = PiggyBank::where('target_amount', '<', 0)->update(['target_amount' => DB::raw('target_amount * -1')]);
if (0 === $count) {
return;
}
$this->friendlyInfo(sprintf('Corrected %d piggy bank amount(s).', $count));
}
private function fixRecurrences(): void
{
$count = 0;
$count += RecurrenceTransaction::where('amount', '<', 0)->update(['amount' => DB::raw('amount * -1')]);
$count += RecurrenceTransaction::where('foreign_amount', '<', 0)->update(['foreign_amount' => DB::raw('foreign_amount * -1')]);
if (0 === $count) {
return;
}
$this->friendlyInfo(sprintf('Corrected %d recurring transaction amount(s).', $count));
}
/**
* Foreach loop is unavoidable here.
*/
private function fixRuleTriggers(): void
{
$set = RuleTrigger::whereIn('trigger_type', ['amount_less', 'amount_more', 'amount_is'])->get();
$fixed = 0;
/** @var RuleTrigger $item */
foreach ($set as $item) {
$result = $this->fixRuleTrigger($item);
if (true === $result) {
++$fixed;
}
}
if (0 === $fixed) {
return;
}
$this->friendlyInfo(sprintf('Corrected %d rule trigger amount(s).', $fixed));
}
private function fixRuleTrigger(RuleTrigger $item): bool
{
try {
$check = bccomp((string) $item->trigger_value, '0');
} catch (\ValueError $e) {
$this->friendlyError(sprintf('Rule #%d contained invalid %s-trigger "%s". The trigger has been removed, and the rule is disabled.', $item->rule_id, $item->trigger_type, $item->trigger_value));
$item->rule->active = false;
$item->rule->save();
$item->forceDelete();
return false;
}
if (-1 === $check) {
$item->trigger_value = app('steam')->positive($item->trigger_value);
$item->save();
return true;
}
return false;
}
}

View File

@@ -37,15 +37,12 @@ use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use Symfony\Component\Console\Command\Command as CommandAlias;
/**
* Class EnableCurrencies
*/
class EnableCurrencies extends Command
class CorrectsCurrencies extends Command
{
use ShowsFriendlyMessages;
protected $description = 'Enables all currencies in use.';
protected $signature = 'firefly-iii:enable-currencies';
protected $signature = 'correction:currencies';
/**
* Execute the console command.

View File

@@ -27,14 +27,11 @@ namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use Illuminate\Console\Command;
/**
* Class CorrectDatabase
*/
class CorrectDatabase extends Command
class CorrectsDatabase extends Command
{
use ShowsFriendlyMessages;
protected $description = 'Will correct the integrity of your database, if necessary.';
protected $description = 'Will validate and correct the integrity of your database, if necessary.';
protected $signature = 'firefly-iii:correct-database';
/**
@@ -49,32 +46,36 @@ class CorrectDatabase extends Command
return 1;
}
$commands = [
'firefly-iii:fix-piggies',
'firefly-iii:create-link-types',
'firefly-iii:create-access-tokens',
'firefly-iii:remove-bills',
'firefly-iii:fix-amount-pos-neg',
'firefly-iii:enable-currencies',
'firefly-iii:fix-transfer-budgets',
'firefly-iii:fix-uneven-amount',
'firefly-iii:delete-zero-amount',
'firefly-iii:delete-orphaned-transactions',
'firefly-iii:delete-empty-journals',
'firefly-iii:delete-empty-groups',
'firefly-iii:fix-account-types',
'firefly-iii:fix-ibans',
'firefly-iii:fix-account-order',
'firefly-iii:rename-meta-fields',
'firefly-iii:fix-ob-currencies',
'firefly-iii:fix-long-descriptions',
'firefly-iii:fix-recurring-transactions',
'firefly-iii:upgrade-group-information',
'firefly-iii:fix-transaction-types',
'firefly-iii:fix-frontpage-accounts',
// new!
'firefly-iii:unify-group-accounts',
'firefly-iii:trigger-credit-recalculation',
'firefly-iii:migrate-preferences',
'correction:restore-oauth-keys',
'correction:timezones',
'correction:create-group-memberships',
'correction:group-information',
'correction:piggy-banks',
'correction:link-types',
'correction:access-tokens',
'correction:bills',
'correction:amounts',
'correction:currencies',
'correction:transfer-budgets',
'correction:uneven-amounts',
'correction:zero-amounts',
'correction:orphaned-transactions',
'correction:empty-journals',
'correction:empty-groups',
'correction:account-types',
'correction:ibans',
'correction:account-order',
'correction:meta-fields',
'correction:opening-balance-currencies',
'correction:long-descriptions',
'correction:recurring-transactions',
'correction:frontpage-accounts',
'correction:group-accounts',
'correction:recalculates-liabilities',
'correction:preferences',
// 'correction:transaction-types', // resource heavy, disabled.
'correction:recalculate-native-amounts', // not necessary, disabled.
'firefly-iii:report-integrity',
];
foreach ($commands as $command) {
$this->friendlyLine(sprintf('Now executing command "%s"', $command));

View File

@@ -25,21 +25,18 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Models\AccountType;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Models\Preference;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\User;
use Illuminate\Console\Command;
/**
* Class FixFrontpageAccounts
*/
class FixFrontpageAccounts extends Command
class CorrectsFrontpageAccounts extends Command
{
use ShowsFriendlyMessages;
protected $description = 'Fixes a preference that may include deleted accounts or accounts of another type.';
protected $signature = 'firefly-iii:fix-frontpage-accounts';
protected $signature = 'correction:frontpage-accounts';
/**
* Execute the console command.
@@ -55,7 +52,6 @@ class FixFrontpageAccounts extends Command
$this->fixPreference($preference);
}
}
$this->friendlyPositive('Account preferences are OK');
return 0;
}
@@ -77,7 +73,7 @@ class FixFrontpageAccounts extends Command
$accountIdInt = (int) $accountId;
$account = $repository->find($accountIdInt);
if (null !== $account
&& in_array($account->accountType->type, [AccountType::ASSET, AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE], true)
&& in_array($account->accountType->type, [AccountTypeEnum::ASSET->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value], true)
&& true === $account->active) {
$fixed[] = $account->id;
}

View File

@@ -31,15 +31,12 @@ use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Console\Command;
/**
* Class FixGroupAccounts
*/
class FixGroupAccounts extends Command
class CorrectsGroupAccounts extends Command
{
use ShowsFriendlyMessages;
protected $description = 'Unify the source / destination accounts of split groups.';
protected $signature = 'firefly-iii:unify-group-accounts';
protected $signature = 'correction:group-accounts';
/**
* Execute the console command.
@@ -64,8 +61,6 @@ class FixGroupAccounts extends Command
$handler->unifyAccounts($event);
}
$this->friendlyPositive('Updated possible inconsistent transaction groups.');
return 0;
}
}

View File

@@ -1,8 +1,8 @@
<?php
/*
* UpdateGroupInformation.php
* Copyright (c) 2022 james@firefly-iii.org
* CorrectsGroupInformation.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@@ -17,12 +17,12 @@
* 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/>.
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Integrity;
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Models\Account;
@@ -45,15 +45,12 @@ use FireflyIII\User;
use Illuminate\Console\Command;
use Illuminate\Database\QueryException;
/**
* Class UpdateGroupInformation
*/
class UpdateGroupInformation extends Command
class CorrectsGroupInformation extends Command
{
use ShowsFriendlyMessages;
protected $description = 'Makes sure that every object is linked to a group';
protected $signature = 'firefly-iii:upgrade-group-information';
protected $signature = 'correction:group-information';
/**
* Execute the console command.
@@ -79,7 +76,7 @@ class UpdateGroupInformation extends Command
{
$group = $user->userGroup;
if (null === $group) {
$this->friendlyWarning(sprintf('User "%s" has no group.', $user->email));
$this->friendlyWarning(sprintf('User "%s" has no group. Please run "php artisan firefly-iii:create-group-memberships"', $user->email));
return;
}

View File

@@ -25,20 +25,17 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use Illuminate\Console\Command;
use Illuminate\Support\Collection;
/**
* Class FixIbans
*/
class FixIbans extends Command
class CorrectsIbans extends Command
{
use ShowsFriendlyMessages;
protected $description = 'Removes spaces from IBANs';
protected $signature = 'firefly-iii:fix-ibans';
protected $signature = 'correction:ibans';
private int $count = 0;
/**
@@ -49,9 +46,6 @@ class FixIbans extends Command
$accounts = Account::whereNotNull('iban')->get();
$this->filterIbans($accounts);
$this->countAndCorrectIbans($accounts);
if (0 === $this->count) {
$this->friendlyPositive('All IBANs are valid.');
}
return 0;
}
@@ -84,14 +78,14 @@ class FixIbans extends Command
continue;
}
$type = $account->accountType->type;
if (in_array($type, [AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], true)) {
if (in_array($type, [AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::MORTGAGE->value], true)) {
$type = 'liabilities';
}
if (array_key_exists($iban, $set[$userId])) {
// iban already in use! two exceptions exist:
if (
!(AccountType::EXPENSE === $set[$userId][$iban] && AccountType::REVENUE === $type) // allowed combination
&& !(AccountType::REVENUE === $set[$userId][$iban] && AccountType::EXPENSE === $type) // also allowed combination.
!(AccountTypeEnum::EXPENSE->value === $set[$userId][$iban] && AccountTypeEnum::REVENUE->value === $type) // allowed combination
&& !(AccountTypeEnum::REVENUE->value === $set[$userId][$iban] && AccountTypeEnum::EXPENSE->value === $type) // also allowed combination.
) {
$this->friendlyWarning(
sprintf(

View File

@@ -28,24 +28,22 @@ use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
/**
* Class FixLongDescriptions
*/
class FixLongDescriptions extends Command
class CorrectsLongDescriptions extends Command
{
use ShowsFriendlyMessages;
private const int MAX_LENGTH = 1000;
protected $description = 'Fixes long descriptions in journals and groups.';
protected $signature = 'firefly-iii:fix-long-descriptions';
protected $signature = 'correction:long-descriptions';
/**
* Execute the console command.
*/
public function handle(): int
{
$journals = TransactionJournal::get(['id', 'description']);
$journals = TransactionJournal::where(DB::raw('LENGTH(description)'), '>', self::MAX_LENGTH)->get(['id', 'description']);
$count = 0;
/** @var TransactionJournal $journal */
@@ -58,7 +56,7 @@ class FixLongDescriptions extends Command
}
}
$groups = TransactionGroup::get(['id', 'title']);
$groups = TransactionGroup::where(DB::raw('LENGTH(title)'), '>', self::MAX_LENGTH)->get(['id', 'title']);
/** @var TransactionGroup $group */
foreach ($groups as $group) {
@@ -69,9 +67,6 @@ class FixLongDescriptions extends Command
++$count;
}
}
if (0 === $count) {
$this->friendlyPositive('All transaction group and journal title lengths are within bounds.');
}
return 0;
}

View File

@@ -26,16 +26,14 @@ namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
/**
* Class RenameMetaFields
*/
class RenameMetaFields extends Command
class CorrectsMetaDataFields extends Command
{
use ShowsFriendlyMessages;
protected $description = 'Rename changed meta fields.';
protected $signature = 'firefly-iii:rename-meta-fields';
protected $signature = 'correction:meta-fields';
private int $count = 0;
@@ -61,9 +59,6 @@ class RenameMetaFields extends Command
foreach ($changes as $original => $update) {
$this->rename($original, $update);
}
if (0 === $this->count) {
$this->friendlyPositive('All meta fields are correct.');
}
if (0 !== $this->count) {
$this->friendlyInfo(sprintf('Renamed %d meta field(s).', $this->count));
}
@@ -73,7 +68,7 @@ class RenameMetaFields extends Command
private function rename(string $original, string $update): void
{
$total = \DB::table('journal_meta')
$total = DB::table('journal_meta')
->where('name', '=', $original)
->update(['name' => $update])
;

View File

@@ -0,0 +1,246 @@
<?php
/*
* CorrectsNativeAmounts.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/.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Handlers\Observer\TransactionObserver;
use FireflyIII\Models\Account;
use FireflyIII\Models\AutoBudget;
use FireflyIII\Models\AvailableBudget;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Budget;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankEvent;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\UserGroup;
use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface;
use FireflyIII\Repositories\UserGroups\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Query\Builder as DatabaseBuilder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class CorrectsNativeAmounts extends Command
{
use ShowsFriendlyMessages;
protected $description = 'Recalculate native amounts for all objects.';
protected $signature = 'correction:recalculate-native-amounts';
/**
* Execute the console command.
*/
public function handle(): int
{
if (false === config('cer.enabled')) {
$this->friendlyInfo('This command will not run because currency exchange rates are disabled.');
return 0;
}
Log::debug('Will update all native amounts. This may take some time.');
$this->friendlyWarning('Recalculating native amounts for all objects. This may take some time!');
/** @var UserGroupRepositoryInterface $repository */
$repository = app(UserGroupRepositoryInterface::class);
/** @var UserGroup $userGroup */
foreach ($repository->getAll() as $userGroup) {
$this->recalculateForGroup($userGroup);
}
$this->friendlyInfo('Recalculated all native amounts.');
return 0;
}
private function recalculateForGroup(UserGroup $userGroup): void
{
Log::debug(sprintf('Now recalculating for user group #%d', $userGroup->id));
$this->recalculateAccounts($userGroup);
// do a check with the group's currency so we can skip some stuff.
Preferences::mark();
$currency = app('amount')->getDefaultCurrencyByUserGroup($userGroup);
$this->recalculatePiggyBanks($userGroup, $currency);
$this->recalculateBudgets($userGroup, $currency);
$this->recalculateAvailableBudgets($userGroup, $currency);
$this->recalculateBills($userGroup, $currency);
$this->calculateTransactions($userGroup, $currency);
}
private function recalculateAccounts(UserGroup $userGroup): void
{
$set = $userGroup->accounts()->where(function (EloquentBuilder $q): void {
$q->whereNotNull('virtual_balance');
$q->orWhere('virtual_balance', '!=', '');
})->get();
/** @var Account $account */
foreach ($set as $account) {
$account->touch();
}
Log::debug(sprintf('Recalculated %d accounts for user group #%d.', $set->count(), $userGroup->id));
}
private function recalculatePiggyBanks(UserGroup $userGroup, TransactionCurrency $currency): void
{
$converter = new ExchangeRateConverter();
$converter->setUserGroup($userGroup);
$converter->setIgnoreSettings(true);
$repository = app(PiggyBankRepositoryInterface::class);
$repository->setUserGroup($userGroup);
$set = $repository->getPiggyBanks();
$set = $set->filter(
static function (PiggyBank $piggyBank) use ($currency) {
return $currency->id !== $piggyBank->transaction_currency_id;
}
);
foreach ($set as $piggyBank) {
$piggyBank->encrypted = false;
$piggyBank->save();
foreach ($piggyBank->accounts as $account) {
$account->pivot->native_current_amount = null;
if (0 !== bccomp((string) $account->pivot->current_amount, '0')) {
$account->pivot->native_current_amount = $converter->convert($piggyBank->transactionCurrency, $currency, today(), (string) $account->pivot->current_amount);
}
$account->pivot->save();
}
$this->recalculatePiggyBankEvents($piggyBank);
}
Log::debug(sprintf('Recalculated %d piggy banks for user group #%d.', $set->count(), $userGroup->id));
}
private function recalculatePiggyBankEvents(PiggyBank $piggyBank): void
{
$set = $piggyBank->piggyBankEvents()->get();
$set->each(
static function (PiggyBankEvent $event): void { // @phpstan-ignore-line
$event->touch();
}
);
Log::debug(sprintf('Recalculated %d piggy bank events.', $set->count()));
}
private function recalculateBudgets(UserGroup $userGroup, TransactionCurrency $currency): void
{
$set = $userGroup->budgets()->get();
/** @var Budget $budget */
foreach ($set as $budget) {
$this->recalculateBudgetLimits($budget, $currency);
$this->recalculateAutoBudgets($budget, $currency);
}
Log::debug(sprintf('Recalculated %d budgets.', $set->count()));
}
private function recalculateBudgetLimits(Budget $budget, TransactionCurrency $currency): void
{
$set = $budget->budgetlimits()->where('transaction_currency_id', '!=', $currency->id)->get();
/** @var BudgetLimit $limit */
foreach ($set as $limit) {
Log::debug(sprintf('Will now touch BL #%d', $limit->id));
$limit->touch();
Log::debug(sprintf('Done with touch BL #%d', $limit->id));
}
Log::debug(sprintf('Recalculated %d budget limits for budget #%d.', $set->count(), $budget->id));
}
private function recalculateAutoBudgets(Budget $budget, TransactionCurrency $currency): void
{
$set = $budget->autoBudgets()->where('transaction_currency_id', '!=', $currency->id)->get();
/** @var AutoBudget $autoBudget */
foreach ($set as $autoBudget) {
$autoBudget->touch();
}
Log::debug(sprintf('Recalculated %d auto budgets for budget #%d.', $set->count(), $budget->id));
}
private function recalculateAvailableBudgets(UserGroup $userGroup, TransactionCurrency $currency): void
{
Log::debug('Start with available budgets.');
$set = $userGroup->availableBudgets()->where('transaction_currency_id', '!=', $currency->id)->get();
/** @var AvailableBudget $budget */
foreach ($set as $budget) {
$budget->touch();
}
Log::debug(sprintf('Recalculated %d available budgets.', $set->count()));
}
private function recalculateBills(UserGroup $userGroup, TransactionCurrency $currency): void
{
$set = $userGroup->bills()->where('transaction_currency_id', '!=', $currency->id)->get();
/** @var Bill $bill */
foreach ($set as $bill) {
$bill->touch();
}
Log::debug(sprintf('Recalculated %d bills.', $set->count()));
}
private function calculateTransactions(UserGroup $userGroup, TransactionCurrency $currency): void
{
// custom query because of the potential size of this update.
$set = DB::table('transactions')
->join('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.user_group_id', $userGroup->id)
->where(function (DatabaseBuilder $q1) use ($currency): void {
$q1->where(function (DatabaseBuilder $q2) use ($currency): void {
$q2->whereNot('transactions.transaction_currency_id', $currency->id)->whereNull('transactions.foreign_currency_id');
})->orWhere(function (DatabaseBuilder $q3) use ($currency): void {
$q3->whereNot('transactions.transaction_currency_id', $currency->id)->whereNot('transactions.foreign_currency_id', $currency->id);
});
})
// ->where(static function (DatabaseBuilder $q) use ($currency): void {
// $q->whereNot('transactions.transaction_currency_id', $currency->id)
// ->whereNot('transactions.foreign_currency_id', $currency->id)
// ;
// })
->get(['transactions.id'])
;
TransactionObserver::$recalculate = false;
foreach ($set as $item) {
// here we are.
/** @var null|Transaction $transaction */
$transaction = Transaction::find($item->id);
$transaction?->touch();
}
TransactionObserver::$recalculate = true;
Log::debug(sprintf('Recalculated %d transactions.', $set->count()));
}
}

View File

@@ -25,25 +25,22 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use Illuminate\Console\Command;
use Illuminate\Support\Collection;
/**
* Class CorrectOpeningBalanceCurrencies
*/
class CorrectOpeningBalanceCurrencies extends Command
class CorrectsOpeningBalanceCurrencies extends Command
{
use ShowsFriendlyMessages;
protected $description = 'Will make sure that opening balance transaction currencies match the account they\'re for.';
protected $signature = 'firefly-iii:fix-ob-currencies';
protected $signature = 'correction:opening-balance-currencies';
/**
* Execute the console command.
@@ -62,20 +59,16 @@ class CorrectOpeningBalanceCurrencies extends Command
$message = sprintf('Corrected %d opening balance transaction(s).', $count);
$this->friendlyInfo($message);
}
if (0 === $count) {
$message = 'There was nothing to fix in the opening balance transactions.';
$this->friendlyPositive($message);
}
return 0;
}
private function getJournals(): Collection
{
// @var Collection
/** @var Collection */
return TransactionJournal::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->whereNull('transaction_journals.deleted_at')
->where('transaction_types.type', TransactionType::OPENING_BALANCE)->get(['transaction_journals.*'])
->where('transaction_types.type', TransactionTypeEnum::OPENING_BALANCE->value)->get(['transaction_journals.*'])
;
}
@@ -103,7 +96,7 @@ class CorrectOpeningBalanceCurrencies extends Command
foreach ($transactions as $transaction) {
/** @var null|Account $account */
$account = $transaction->account()->first();
if (null !== $account && AccountType::INITIAL_BALANCE !== $account->accountType()->first()->type) {
if (null !== $account && AccountTypeEnum::INITIAL_BALANCE->value !== $account->accountType()->first()->type) {
return $account;
}
}

View File

@@ -29,17 +29,12 @@ use FireflyIII\Models\PiggyBankEvent;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Console\Command;
/**
* Report (and fix) piggy banks.
*
* Class FixPiggies
*/
class FixPiggies extends Command
class CorrectsPiggyBanks extends Command
{
use ShowsFriendlyMessages;
protected $description = 'Fixes common issues with piggy banks.';
protected $signature = 'firefly-iii:fix-piggies';
protected $signature = 'correction:piggy-banks';
/**
* Execute the console command.
@@ -66,9 +61,6 @@ class FixPiggies extends Command
continue;
}
}
if (0 === $count) {
$this->friendlyPositive('All piggy bank events are OK.');
}
if (0 !== $count) {
$this->friendlyInfo(sprintf('Fixed %d piggy bank event(s).', $count));
}

View File

@@ -1,9 +1,9 @@
<?php
declare(strict_types=1);
/*
* MigratePreferences.php
* Copyright (c) 2024 james@firefly-iii.org.
* CorrectsPreferences.php
* Copyright (c) 2025 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@@ -21,6 +21,8 @@ declare(strict_types=1);
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Models\Preference;
@@ -28,11 +30,11 @@ use FireflyIII\User;
use Illuminate\Console\Command;
use Symfony\Component\Console\Command\Command as CommandAlias;
class MigratePreferences extends Command
class CorrectsPreferences extends Command
{
protected $description = 'Give Firefly III preferences a user group ID so they can be made administration specific.';
protected $signature = 'firefly-iii:migrate-preferences';
protected $signature = 'correction:preferences';
/**
* Execute the console command.
@@ -50,7 +52,7 @@ class MigratePreferences extends Command
if (null === $preference) {
continue;
}
if (null !== $preference->user_group_id) {
if (null === $preference->user_group_id) {
$preference->user_group_id = $user->user_group_id;
$preference->save();
++$count;

View File

@@ -33,15 +33,12 @@ use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\User;
use Illuminate\Console\Command;
/**
* Class FixRecurringTransactions
*/
class FixRecurringTransactions extends Command
class CorrectsRecurringTransactions extends Command
{
use ShowsFriendlyMessages;
protected $description = 'Fixes recurring transactions with the wrong transaction type.';
protected $signature = 'firefly-iii:fix-recurring-transactions';
protected $signature = 'correction:recurring-transactions';
private int $count = 0;
private RecurringRepositoryInterface $recurringRepos;
private UserRepositoryInterface $userRepos;
@@ -53,9 +50,6 @@ class FixRecurringTransactions extends Command
{
$this->stupidLaravel();
$this->correctTransactions();
if (0 === $this->count) {
$this->friendlyPositive('All recurring transactions are OK.');
}
return 0;
}

View File

@@ -1,5 +1,25 @@
<?php
/*
* CorrectsTimezoneInformation.php
* Copyright (c) 2024 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/.
*/
declare(strict_types=1);
/*
* AddTimezonesToDates.php
@@ -21,7 +41,7 @@ declare(strict_types=1);
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
namespace FireflyIII\Console\Commands\Integrity;
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Models\AccountBalance;
@@ -41,25 +61,12 @@ use Illuminate\Console\Command;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\Log;
class AddTimezonesToDates extends Command
class CorrectsTimezoneInformation extends Command
{
use ShowsFriendlyMessages;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'firefly-iii:add-timezones-to-dates';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Make sure all dates have a timezone.';
public static array $models = [
public static array $models
= [
AccountBalance::class => ['date'], // done
AvailableBudget::class => ['start_date', 'end_date'], // done
Bill::class => ['date', 'end_date', 'extension_date'], // done
@@ -67,13 +74,16 @@ class AddTimezonesToDates extends Command
CurrencyExchangeRate::class => ['date'], // done
InvitedUser::class => ['expires'],
PiggyBankEvent::class => ['date'],
PiggyBankRepetition::class => ['startdate', 'targetdate'],
PiggyBank::class => ['startdate', 'targetdate'], // done
PiggyBankRepetition::class => ['start_date', 'target_date'],
PiggyBank::class => ['start_date', 'target_date'], // done
Recurrence::class => ['first_date', 'repeat_until', 'latest_date'],
Tag::class => ['date'],
TransactionJournal::class => ['date'],
];
protected $description = 'Make sure all dates have a timezone.';
protected $signature = 'correction:timezones';
/**
* Execute the console command.
*/
@@ -106,8 +116,6 @@ class AddTimezonesToDates extends Command
Log::error($e->getMessage());
}
if (0 === $count) {
$this->friendlyPositive(sprintf('Timezone information is present in field "%s" of model "%s".', $field, $shortModel));
return;
}
$this->friendlyInfo(sprintf('Adding timezone information to field "%s" of model "%s".', $field, $shortModel));

View File

@@ -32,16 +32,14 @@ use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use Illuminate\Console\Command;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
/**
* Class FixTransactionTypes
*/
class FixTransactionTypes extends Command
class CorrectsTransactionTypes extends Command
{
use ShowsFriendlyMessages;
protected $description = 'Make sure all transactions are of the correct type, based on source + dest.';
protected $signature = 'firefly-iii:fix-transaction-types';
protected $signature = 'correction:transaction-types';
/**
* Execute the console command.
@@ -50,6 +48,7 @@ class FixTransactionTypes extends Command
{
$count = 0;
$journals = $this->collectJournals();
Log::debug(sprintf('In FixTransactionTypes, found %d journals.', $journals->count()));
/** @var TransactionJournal $journal */
foreach ($journals as $journal) {

View File

@@ -25,19 +25,16 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use Illuminate\Console\Command;
/**
* Class TransferBudgets
*/
class TransferBudgets extends Command
class CorrectsTransferBudgets extends Command
{
use ShowsFriendlyMessages;
protected $description = 'Removes budgets from transfers.';
protected $signature = 'firefly-iii:fix-transfer-budgets';
protected $signature = 'correction:transfer-budgets';
/**
* Execute the console command.
@@ -47,7 +44,7 @@ class TransferBudgets extends Command
$set = TransactionJournal::distinct()
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->leftJoin('budget_transaction_journal', 'transaction_journals.id', '=', 'budget_transaction_journal.transaction_journal_id')
->whereNotIn('transaction_types.type', [TransactionType::WITHDRAWAL])
->whereNotIn('transaction_types.type', [TransactionTypeEnum::WITHDRAWAL->value])
->whereNotNull('budget_transaction_journal.budget_id')->get(['transaction_journals.*'])
;
$count = 0;
@@ -60,10 +57,6 @@ class TransferBudgets extends Command
$entry->budgets()->sync([]);
++$count;
}
if (0 === $count) {
$message = 'No invalid budget/journal entries.';
$this->friendlyPositive($message);
}
if (0 !== $count) {
$message = sprintf('Corrected %d invalid budget/journal entries (entry).', $count);
app('log')->debug($message);

View File

@@ -25,22 +25,19 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\Support\Models\AccountBalanceCalculator;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
/**
* Class FixUnevenAmount
*/
class FixUnevenAmount extends Command
class CorrectsUnevenAmount extends Command
{
use ShowsFriendlyMessages;
protected $description = 'Fix journals with uneven amounts.';
protected $signature = 'firefly-iii:fix-uneven-amount';
protected $signature = 'correction:uneven-amounts';
private int $count;
/**
@@ -52,15 +49,114 @@ class FixUnevenAmount extends Command
$this->convertOldStyleTransfers();
$this->fixUnevenAmounts();
$this->matchCurrencies();
if (config('firefly.feature_flags.running_balance_column')) {
if (true === config('firefly.feature_flags.running_balance_column')) {
$this->friendlyInfo('Will recalculate transaction running balance columns. This may take a LONG time. Please be patient.');
AccountBalanceCalculator::recalculateAll(true);
AccountBalanceCalculator::recalculateAll(false);
$this->friendlyInfo('Done recalculating transaction running balance columns.');
}
return 0;
}
private function convertOldStyleTransfers(): void
{
Log::debug('convertOldStyleTransfers()');
// select transactions with a foreign amount and a foreign currency. and it's a transfer. and they are different.
$transactions = Transaction::distinct()
->leftJoin('transaction_journals', 'transaction_journals.id', 'transactions.transaction_journal_id')
->leftJoin('transaction_types', 'transaction_types.id', 'transaction_journals.transaction_type_id')
->where('transaction_types.type', TransactionTypeEnum::TRANSFER->value)
->whereNotNull('foreign_currency_id')
->whereNotNull('foreign_amount')->get(['transactions.transaction_journal_id'])
;
$count = 0;
Log::debug(sprintf('Found %d potential journal(s)', $transactions->count()));
/** @var Transaction $transaction */
foreach ($transactions as $transaction) {
/** @var null|TransactionJournal $journal */
$journal = TransactionJournal::find($transaction->transaction_journal_id);
if (null === $journal) {
Log::debug('Found no journal, continue.');
continue;
}
// needs to be a transfer.
if (TransactionTypeEnum::TRANSFER->value !== $journal->transactionType->type) {
Log::debug('Must be a transfer, continue.');
continue;
}
/** @var null|Transaction $destination */
$destination = $journal->transactions()->where('amount', '>', 0)->first();
/** @var null|Transaction $source */
$source = $journal->transactions()->where('amount', '<', 0)->first();
if (null === $destination || null === $source) {
Log::debug('Source or destination transaction is NULL, continue.');
// will be picked up later.
continue;
}
if ($source->transaction_currency_id === $destination->transaction_currency_id) {
Log::debug('Ready to swap data between transactions.');
$destination->foreign_currency_id = $source->transaction_currency_id;
$destination->foreign_amount = app('steam')->positive($source->amount);
$destination->transaction_currency_id = $source->foreign_currency_id;
$destination->amount = app('steam')->positive($source->foreign_amount);
$destination->balance_dirty = true;
$source->balance_dirty = true;
$destination->save();
$source->save();
$this->friendlyWarning(sprintf('Corrected foreign amounts of transfer #%d.', $journal->id));
++$count;
}
}
}
private function fixUnevenAmounts(): void
{
$journals = \DB::table('transactions')
->groupBy('transaction_journal_id')
->whereNull('deleted_at')
->get(['transaction_journal_id', \DB::raw('SUM(amount) AS the_sum')]) // @phpstan-ignore-line
;
/** @var \stdClass $entry */
foreach ($journals as $entry) {
$sum = (string) $entry->the_sum;
if (!is_numeric($sum)
|| '' === $sum // @phpstan-ignore-line
|| str_contains($sum, 'e')
|| str_contains($sum, ',')) {
$message = sprintf(
'Journal #%d has an invalid sum ("%s"). No sure what to do.',
$entry->transaction_journal_id,
$entry->the_sum
);
$this->friendlyWarning($message);
app('log')->warning($message);
++$this->count;
continue;
}
$res = -1;
try {
$res = bccomp($sum, '0');
} catch (\ValueError $e) {
$this->friendlyError(sprintf('Could not bccomp("%s", "0").', $sum));
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
}
if (0 !== $res) {
$this->fixJournal($entry->transaction_journal_id);
}
}
}
private function fixJournal(int $param): void
{
// one of the transactions is bad.
@@ -129,81 +225,9 @@ class FixUnevenAmount extends Command
++$this->count;
}
private function fixUnevenAmounts(): void
{
$journals = \DB::table('transactions')
->groupBy('transaction_journal_id')
->whereNull('deleted_at')
->get(['transaction_journal_id', \DB::raw('SUM(amount) AS the_sum')])
;
/** @var \stdClass $entry */
foreach ($journals as $entry) {
$sum = (string) $entry->the_sum;
if (!is_numeric($sum)
|| '' === $sum // @phpstan-ignore-line
|| str_contains($sum, 'e')
|| str_contains($sum, ',')) {
$message = sprintf(
'Journal #%d has an invalid sum ("%s"). No sure what to do.',
$entry->transaction_journal_id,
$entry->the_sum
);
$this->friendlyWarning($message);
app('log')->warning($message);
++$this->count;
continue;
}
$res = -1;
try {
$res = bccomp($sum, '0');
} catch (\ValueError $e) {
$this->friendlyError(sprintf('Could not bccomp("%s", "0").', $sum));
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
}
if (0 !== $res) {
$this->fixJournal($entry->transaction_journal_id);
}
}
if (0 === $this->count) {
$this->friendlyPositive('Database amount integrity is OK');
}
}
private function matchCurrencies(): void
{
$journals = TransactionJournal::leftJoin('transactions', 'transaction_journals.id', 'transactions.transaction_journal_id')
->where('transactions.transaction_currency_id', '!=', \DB::raw('transaction_journals.transaction_currency_id'))
->get(['transaction_journals.*'])
;
$count = 0;
/** @var TransactionJournal $journal */
foreach ($journals as $journal) {
if (!$this->isForeignCurrencyTransfer($journal)) {
Transaction::where('transaction_journal_id', $journal->id)->update(['transaction_currency_id' => $journal->transaction_currency_id]);
++$count;
continue;
}
Log::debug(sprintf('Can skip foreign currency transfer #%d.', $journal->id));
}
if (0 === $count) {
$this->friendlyPositive('Journal currency integrity is OK');
return;
}
$this->friendlyPositive(sprintf('Fixed %d journal(s) with mismatched currencies.', $journals->count()));
}
private function isForeignCurrencyTransfer(TransactionJournal $journal): bool
{
if (TransactionType::TRANSFER !== $journal->transactionType->type) {
if (TransactionTypeEnum::TRANSFER->value !== $journal->transactionType->type) {
return false;
}
@@ -235,63 +259,29 @@ class FixUnevenAmount extends Command
return false;
}
private function convertOldStyleTransfers(): void
private function matchCurrencies(): void
{
Log::debug('convertOldStyleTransfers()');
// select transactions with a foreign amount and a foreign currency. and it's a transfer. and they are different.
$transactions = Transaction::distinct()
->whereNotNull('foreign_currency_id')
->whereNotNull('foreign_amount')->get(['transactions.transaction_journal_id'])
$journals = TransactionJournal::leftJoin('transactions', 'transaction_journals.id', 'transactions.transaction_journal_id')
->where('transactions.transaction_currency_id', '!=', \DB::raw('transaction_journals.transaction_currency_id'))
->get(['transaction_journals.*'])
;
$count = 0;
Log::debug(sprintf('Found %d potential journal(s)', $transactions->count()));
/** @var Transaction $transaction */
foreach ($transactions as $transaction) {
/** @var null|TransactionJournal $journal */
$journal = TransactionJournal::find($transaction->transaction_journal_id);
if (null === $journal) {
Log::debug('Found no journal, continue.');
continue;
}
// needs to be a transfer.
if (TransactionType::TRANSFER !== $journal->transactionType->type) {
Log::debug('Must be a transfer, continue.');
continue;
}
/** @var null|Transaction $destination */
$destination = $journal->transactions()->where('amount', '>', 0)->first();
/** @var null|Transaction $source */
$source = $journal->transactions()->where('amount', '<', 0)->first();
if (null === $destination || null === $source) {
Log::debug('Source or destination transaction is NULL, continue.');
// will be picked up later.
continue;
}
if ($source->transaction_currency_id === $destination->transaction_currency_id) {
Log::debug('Ready to swap data between transactions.');
$destination->foreign_currency_id = $source->transaction_currency_id;
$destination->foreign_amount = app('steam')->positive($source->amount);
$destination->transaction_currency_id = $source->foreign_currency_id;
$destination->amount = app('steam')->positive($source->foreign_amount);
$destination->balance_dirty = true;
$source->balance_dirty = true;
$destination->save();
$source->save();
$this->friendlyWarning(sprintf('Corrected foreign amounts of transfer #%d.', $journal->id));
/** @var TransactionJournal $journal */
foreach ($journals as $journal) {
if (!$this->isForeignCurrencyTransfer($journal)) {
Transaction::where('transaction_journal_id', $journal->id)->update(['transaction_currency_id' => $journal->transaction_currency_id]);
++$count;
continue;
}
Log::debug(sprintf('Can skip foreign currency transfer #%d.', $journal->id));
}
if (0 === $count) {
$this->friendlyPositive('No "old style" foreign currency transfers.');
return;
}
$this->friendlyPositive(sprintf('Fixed %d journal(s) with mismatched currencies.', $journals->count()));
}
}

View File

@@ -29,16 +29,13 @@ use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\User;
use Illuminate\Console\Command;
/**
* Class CreateAccessTokens
*/
class CreateAccessTokens extends Command
class CreatesAccessTokens extends Command
{
use ShowsFriendlyMessages;
protected $description = 'Creates user access tokens which are used for command line access to personal data.';
protected $signature = 'firefly-iii:create-access-tokens';
protected $signature = 'correction:access-tokens';
/**
* Execute the console command.
@@ -64,9 +61,6 @@ class CreateAccessTokens extends Command
++$count;
}
}
if (0 === $count) {
$this->friendlyPositive('Verified access tokens.');
}
return 0;
}

View File

@@ -1,8 +1,8 @@
<?php
/*
* CreateGroupMemberships.php
* Copyright (c) 2023 james@firefly-iii.org
* CreatesGroupMemberships.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@@ -17,12 +17,12 @@
* 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/>.
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Integrity;
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Enums\UserRoleEnum;
@@ -33,16 +33,13 @@ use FireflyIII\Models\UserRole;
use FireflyIII\User;
use Illuminate\Console\Command;
/**
* Class CreateGroupMemberships
*/
class CreateGroupMemberships extends Command
class CreatesGroupMemberships extends Command
{
use ShowsFriendlyMessages;
public const string CONFIG_NAME = '560_create_group_memberships';
protected $description = 'Update group memberships';
protected $signature = 'firefly-iii:create-group-memberships';
protected $signature = 'correction:create-group-memberships';
/**
* Execute the console command.
@@ -52,7 +49,6 @@ class CreateGroupMemberships extends Command
public function handle(): int
{
$this->createGroupMemberships();
$this->friendlyPositive('Validated group memberships');
return 0;
}

View File

@@ -28,16 +28,13 @@ use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Models\LinkType;
use Illuminate\Console\Command;
/**
* Class CreateLinkTypes. Created all link types in case a migration hasn't fired.
*/
class CreateLinkTypes extends Command
class CreatesLinkTypes extends Command
{
use ShowsFriendlyMessages;
protected $description = 'Creates all link types.';
protected $signature = 'firefly-iii:create-link-types';
protected $signature = 'correction:link-types';
/**
* Execute the console command.
@@ -66,9 +63,6 @@ class CreateLinkTypes extends Command
$link->editable = false;
$link->save();
}
if (0 === $count) {
$this->friendlyPositive('All link types are OK');
}
return 0;
}

View File

@@ -25,19 +25,17 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use Illuminate\Console\Command;
/**
* Class RemoveBills
*/
class RemoveBills extends Command
class RemovesBills extends Command
{
use ShowsFriendlyMessages;
protected $description = 'Remove bills from transactions that shouldn\'t have one.';
protected $signature = 'firefly-iii:remove-bills';
protected $signature = 'correction:bills';
/**
* Execute the console command.
@@ -45,7 +43,7 @@ class RemoveBills extends Command
public function handle(): int
{
/** @var null|TransactionType $withdrawal */
$withdrawal = TransactionType::where('type', TransactionType::WITHDRAWAL)->first();
$withdrawal = TransactionType::where('type', TransactionTypeEnum::WITHDRAWAL->value)->first();
if (null === $withdrawal) {
return 0;
}
@@ -60,7 +58,6 @@ class RemoveBills extends Command
if ($journals->count() > 0) {
$this->friendlyInfo('Fixed all transaction journals so they have correct bill information.');
}
$this->friendlyPositive('All bills and journals are OK');
return 0;
}

View File

@@ -24,25 +24,21 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use Exception;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Models\TransactionGroup;
use Illuminate\Console\Command;
/**
* Class DeleteEmptyGroups
*/
class DeleteEmptyGroups extends Command
class RemovesEmptyGroups extends Command
{
use ShowsFriendlyMessages;
protected $description = 'Delete empty transaction groups.';
protected $signature = 'firefly-iii:delete-empty-groups';
protected $signature = 'correction:empty-groups';
/**
* Execute the console command.
*
* @throws Exception;
* @throws \Exception
*/
public function handle(): int
{
@@ -61,9 +57,6 @@ class DeleteEmptyGroups extends Command
TransactionGroup::whereNull('deleted_at')->whereIn('id', $chunk)->delete();
}
}
if (0 === $total) {
$this->friendlyInfo('Verified there are no empty groups.');
}
return 0;
}

View File

@@ -30,16 +30,13 @@ use FireflyIII\Models\TransactionJournal;
use Illuminate\Console\Command;
use Illuminate\Database\QueryException;
/**
* Class DeleteEmptyJournals
*/
class DeleteEmptyJournals extends Command
class RemovesEmptyJournals extends Command
{
use ShowsFriendlyMessages;
protected $description = 'Delete empty and uneven transaction journals.';
protected $signature = 'firefly-iii:delete-empty-journals';
protected $signature = 'correction:empty-journals';
/**
* Execute the console command.
@@ -69,7 +66,9 @@ class DeleteEmptyJournals extends Command
if (1 === $count % 2) {
// uneven number, delete journal and transactions:
try {
TransactionJournal::find($row->transaction_journal_id)->delete();
/** @var null|TransactionJournal $journal */
$journal = TransactionJournal::find($row->transaction_journal_id);
$journal?->delete();
} catch (QueryException $e) {
app('log')->info(sprintf('Could not delete journal: %s', $e->getMessage()));
app('log')->error($e->getTraceAsString());
@@ -82,9 +81,6 @@ class DeleteEmptyJournals extends Command
++$total;
}
}
if (0 === $total) {
$this->friendlyPositive('No uneven transaction journals.');
}
}
private function deleteEmptyJournals(): void
@@ -98,7 +94,9 @@ class DeleteEmptyJournals extends Command
foreach ($set as $entry) {
try {
TransactionJournal::find($entry->id)->delete();
/** @var null|TransactionJournal $journal */
$journal = TransactionJournal::find($entry->id);
$journal?->delete();
} catch (QueryException $e) {
app('log')->info(sprintf('Could not delete entry: %s', $e->getMessage()));
app('log')->error($e->getTraceAsString());
@@ -107,8 +105,5 @@ class DeleteEmptyJournals extends Command
$this->friendlyInfo(sprintf('Deleted empty transaction journal #%d', $entry->id));
++$count;
}
if (0 === $count) {
$this->friendlyPositive('No empty transaction journals.');
}
}
}

Some files were not shown because too many files have changed in this diff Show More