Compare commits

...

290 Commits

Author SHA1 Message Date
github-actions[bot]
667cbb1332 Merge pull request #10991 from firefly-iii/release-1759381485
🤖 Automatically merge the PR into the develop branch.
2025-10-02 07:04:53 +02:00
JC5
d1bae875f7 🤖 Auto commit for release 'develop' on 2025-10-02 2025-10-02 07:04:45 +02:00
James Cole
c5cf529413 Update changelog. 2025-10-02 06:59:56 +02:00
James Cole
62b9f2785f Ignore db version in scripts. 2025-10-02 06:55:09 +02:00
James Cole
3b85f87502 Stop using "db_version", check versions instead. 2025-10-02 06:53:23 +02:00
James Cole
87d3d14504 Fix #10990 2025-10-01 20:28:24 +02:00
github-actions[bot]
5637573fd0 Merge pull request #10982 from firefly-iii/release-1759116145
🤖 Automatically merge the PR into the develop branch.
2025-09-29 05:22:35 +02:00
JC5
48255ae6ee 🤖 Auto commit for release 'develop' on 2025-09-29 2025-09-29 05:22:25 +02:00
James Cole
ea02986170 Merge pull request #10979 from maksimkurb/patch-1
Add Kazakhstani Tenge (KZT) currency
2025-09-28 15:28:15 +02:00
mergify[bot]
f4fbc15ac6 Merge branch 'develop' into patch-1 2025-09-28 07:17:01 +00:00
Maxim Kurbatov
a02c4b42a4 Add Kazakhstani Tenge (KZT) currency
Signed-off-by: Maxim Kurbatov <maxim@kurb.me>
2025-09-28 11:49:37 +05:00
James Cole
1ff47441ce Also add no budget and no category overview. 2025-09-27 16:07:03 +02:00
James Cole
2cc8568077 Clean up code. 2025-09-27 06:40:56 +02:00
github-actions[bot]
408687ec6b Merge pull request #10975 from firefly-iii/release-1758945886
🤖 Automatically merge the PR into the develop branch.
2025-09-27 06:04:55 +02:00
JC5
308abffb0b 🤖 Auto commit for release 'develop' on 2025-09-27 2025-09-27 06:04:46 +02:00
James Cole
6743b3fe83 Remove stats for other objects as well. 2025-09-27 06:01:14 +02:00
James Cole
ac0113e445 Fix some rector code. 2025-09-27 05:57:58 +02:00
James Cole
0f0a28c3d9 Add cached periods for tags. 2025-09-27 05:49:22 +02:00
James Cole
79f2d70211 Fix #10974 2025-09-27 05:35:20 +02:00
James Cole
8a06c0f7ec Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop
# Conflicts:
#	app/Support/Http/Controllers/PeriodOverview.php
2025-09-27 05:32:41 +02:00
James Cole
c54da62005 Enable period statistics for category. 2025-09-27 05:31:26 +02:00
github-actions[bot]
e5923202af Merge pull request #10973 from firefly-iii/release-1758914746
🤖 Automatically merge the PR into the develop branch.
2025-09-26 21:25:55 +02:00
JC5
eb6f78406e 🤖 Auto commit for release 'develop' on 2025-09-26 2025-09-26 21:25:46 +02:00
James Cole
d61f87f649 Fix URL 2025-09-26 20:47:44 +02:00
James Cole
33dcce7525 Optimize query for collecting transactions. 2025-09-26 20:46:23 +02:00
James Cole
b1d86c3a37 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop
# Conflicts:
#	app/Models/PeriodStatistic.php
2025-09-26 19:48:46 +02:00
James Cole
822dee6e70 Allow statistics to be removed from /flush 2025-09-26 19:48:20 +02:00
github-actions[bot]
f6dac83777 Merge pull request #10972 from firefly-iii/release-1758908619
🤖 Automatically merge the PR into the develop branch.
2025-09-26 19:43:52 +02:00
JC5
d3c557ca22 🤖 Auto commit for release 'develop' on 2025-09-26 2025-09-26 19:43:39 +02:00
James Cole
853a99852e Also remove them when updating transactions. 2025-09-26 19:39:18 +02:00
James Cole
8f24ac4fcd Remove statistics when creating a new journal. 2025-09-26 19:38:26 +02:00
James Cole
8b09cfb8c9 Optimize query for period statistics. 2025-09-26 19:32:53 +02:00
James Cole
18ae950d2e Optimize queries. 2025-09-26 06:09:44 +02:00
James Cole
69dfbda847 Add empty statistic if necessary. 2025-09-26 06:06:43 +02:00
James Cole
4ec2fcdb8a Optimize queries for statistics. 2025-09-26 06:05:37 +02:00
James Cole
08879d31ba Rearrange some code. 2025-09-26 05:33:35 +02:00
James Cole
66d09450d3 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-09-25 19:17:20 +02:00
James Cole
74f7c07a76 Add filter for transfer type. 2025-09-25 19:17:10 +02:00
github-actions[bot]
ae3d0a3e49 Merge pull request #10964 from firefly-iii/release-1758820271
🤖 Automatically merge the PR into the develop branch.
2025-09-25 19:11:21 +02:00
JC5
61e8d7d7a2 🤖 Auto commit for release 'develop' on 2025-09-25 2025-09-25 19:11:11 +02:00
James Cole
62c5440605 Add table for period statistics, and see what happens re: performance. 2025-09-25 19:07:02 +02:00
James Cole
0aa90b9453 Fix #10960 2025-09-24 19:51:39 +02:00
Sander Dorigo
855bc2f8e7 attempted fix for #10956 2025-09-24 14:39:54 +02:00
github-actions[bot]
d8f05492c3 Merge pull request #10955 from firefly-iii/release-1758652896
🤖 Automatically merge the PR into the develop branch.
2025-09-23 20:41:46 +02:00
JC5
4a264f34fa 🤖 Auto commit for release 'develop' on 2025-09-23 2025-09-23 20:41:36 +02:00
James Cole
5a1413e758 Fix #10954 2025-09-23 20:22:58 +02:00
github-actions[bot]
84dbeeb0ce Merge pull request #10946 from firefly-iii/release-1758511378
🤖 Automatically merge the PR into the develop branch.
2025-09-22 05:23:04 +02:00
JC5
d868dc0945 🤖 Auto commit for release 'develop' on 2025-09-22 2025-09-22 05:22:58 +02:00
James Cole
beecf9c229 Make sure demo user cannot send notifications. 2025-09-21 18:00:23 +02:00
github-actions[bot]
e39ba46398 Merge pull request #10943 from firefly-iii/release-1758470243
🤖 Automatically merge the PR into the develop branch.
2025-09-21 17:57:31 +02:00
JC5
e6b6a3cee5 🤖 Auto commit for release 'develop' on 2025-09-21 2025-09-21 17:57:23 +02:00
James Cole
b5483f6ad3 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-09-21 17:52:16 +02:00
James Cole
a751218d53 Fix rule order for #10938 2025-09-21 17:52:07 +02:00
github-actions[bot]
2af5e6eeef Merge pull request #10942 from firefly-iii/release-1758460508
🤖 Automatically merge the PR into the develop branch.
2025-09-21 15:15:17 +02:00
JC5
013c43f9f2 🤖 Auto commit for release 'develop' on 2025-09-21 2025-09-21 15:15:08 +02:00
James Cole
7e08a1f33c Possible fix for #10940, not sure. 2025-09-21 15:11:16 +02:00
James Cole
e592b56d7a Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-09-21 15:06:32 +02:00
github-actions[bot]
a2479f71fe Merge pull request #10937 from firefly-iii/release-1758437913
🤖 Automatically merge the PR into the develop branch.
2025-09-21 08:58:42 +02:00
JC5
7d3b993b98 🤖 Auto commit for release 'develop' on 2025-09-21 2025-09-21 08:58:33 +02:00
James Cole
90623101a3 Add earned + spent, needs cleaning up still. 2025-09-21 08:54:26 +02:00
github-actions[bot]
e2eca79b25 Merge pull request #10936 from firefly-iii/release-1758436089
🤖 Automatically merge the PR into the develop branch.
2025-09-21 08:28:16 +02:00
JC5
8c0ee8f024 🤖 Auto commit for release 'develop' on 2025-09-21 2025-09-21 08:28:09 +02:00
James Cole
69cae3ae55 Fix autocomplete. 2025-09-21 08:13:13 +02:00
James Cole
8a06298385 Repair charts and balances. 2025-09-21 07:35:46 +02:00
James Cole
acc3c294d8 Fix #10924 2025-09-17 20:46:03 +02:00
James Cole
dbf7dba421 Fix #10916 2025-09-17 20:04:24 +02:00
James Cole
65813f290d Expand changelog. 2025-09-17 13:48:56 +02:00
James Cole
3491fbb99d Force account search to validate it did not just find the source account. #10920 2025-09-17 07:09:40 +02:00
James Cole
cb6b3d5f85 Fix #10891 2025-09-16 21:09:29 +02:00
github-actions[bot]
956d4e09c3 Merge pull request #10917 from firefly-iii/release-1758048927
🤖 Automatically merge the PR into the develop branch.
2025-09-16 20:55:35 +02:00
JC5
6a7c35e7bc 🤖 Auto commit for release 'develop' on 2025-09-16 2025-09-16 20:55:27 +02:00
James Cole
090aecb5f5 Clean up command. 2025-09-16 20:50:25 +02:00
James Cole
b653d63d3d Add new correction command, will probably fix #10833 2025-09-16 20:44:54 +02:00
github-actions[bot]
258dbf4a98 Merge pull request #10913 from firefly-iii/release-1757957159
🤖 Automatically merge the PR into the develop branch.
2025-09-15 19:26:09 +02:00
JC5
53335077ff 🤖 Auto commit for release 'develop' on 2025-09-15 2025-09-15 19:25:59 +02:00
James Cole
ecfb3e2f95 Fix #10854 and another issue (again). 2025-09-15 19:20:51 +02:00
github-actions[bot]
f512e6724e Merge pull request #10911 from firefly-iii/release-1757906627
🤖 Automatically merge the PR into the develop branch.
2025-09-15 05:23:56 +02:00
JC5
de9efb0727 🤖 Auto commit for release 'develop' on 2025-09-15 2025-09-15 05:23:47 +02:00
James Cole
9075fa8ac8 Allow webhooks to be send for budget limit update. 2025-09-14 09:21:32 +02:00
James Cole
768bd892c8 Allow sending of webhooks from budget limit store. 2025-09-14 09:14:41 +02:00
James Cole
9d9483e20f Refactor models. 2025-09-14 09:00:01 +02:00
James Cole
935453796e Allow budget update to have webhooks controlled with "fire_webhooks" 2025-09-14 08:59:00 +02:00
James Cole
c2d3f5da16 Allow budget store to have optional webhook using "fire_webhooks". 2025-09-14 08:55:29 +02:00
James Cole
9e6f9d16e4 Move observers to attributes. 2025-09-14 08:55:08 +02:00
James Cole
fad016f92f Update changelog. 2025-09-14 07:46:46 +02:00
James Cole
30df6684cb Fix another missing filter for #10803 2025-09-14 07:45:54 +02:00
James Cole
4aa911420a Merge branch 'main' into develop 2025-09-13 18:53:00 +02:00
github-actions[bot]
19555a7046 Merge pull request #10907 from firefly-iii/release-1757782324
🤖 Automatically merge the PR into the develop branch.
2025-09-13 18:52:14 +02:00
JC5
e5c409a8fc 🤖 Auto commit for release 'develop' on 2025-09-13 2025-09-13 18:52:04 +02:00
github-actions[bot]
3adf3d2fdb Merge pull request #10906 from firefly-iii/develop
🤖 Automatically merge the PR into the main branch.
2025-09-13 18:38:12 +02:00
github-actions[bot]
0923d5a23e Merge pull request #10905 from firefly-iii/release-1757781480
🤖 Automatically merge the PR into the develop branch.
2025-09-13 18:38:07 +02:00
JC5
76b8cdc385 🤖 Auto commit for release 'v6.4.0' on 2025-09-13 2025-09-13 18:38:00 +02:00
James Cole
0a27da83eb Merge branch 'main' into develop
# Conflicts:
#	.github/workflows/release.yml
2025-09-13 18:33:47 +02:00
github-actions[bot]
17d6e2be85 Merge pull request #10903 from firefly-iii/release-1757781134
🤖 Automatically merge the PR into the develop branch.
2025-09-13 18:32:20 +02:00
JC5
7381f3eba9 🤖 Auto commit for release 'v6.4.0' on 2025-09-13 2025-09-13 18:32:14 +02:00
James Cole
7f2ef1b8e1 Should not be necessary, but OK/ 2025-09-13 18:28:26 +02:00
github-actions[bot]
9dccae2402 Merge pull request #10901 from firefly-iii/release-1757780827
🤖 Automatically merge the PR into the develop branch.
2025-09-13 18:27:17 +02:00
JC5
073afd5b6e 🤖 Auto commit for release 'v6.4.0' on 2025-09-13 2025-09-13 18:27:07 +02:00
James Cole
4167d85be2 Expand changelog. 2025-09-13 07:30:50 +02:00
James Cole
ee28d1307d Fix #10871 2025-09-13 07:30:30 +02:00
James Cole
7562215666 Add some extra explanation. 2025-09-13 07:24:03 +02:00
github-actions[bot]
0203b918e9 Merge pull request #10899 from firefly-iii/release-1757740712
🤖 Automatically merge the PR into the develop branch.
2025-09-13 07:18:41 +02:00
JC5
ae7c664418 🤖 Auto commit for release 'develop' on 2025-09-13 2025-09-13 07:18:32 +02:00
James Cole
f13e0991fb Fix #10898 2025-09-13 07:13:30 +02:00
James Cole
deae94b658 Set user ID from object, fix #10891 2025-09-11 19:37:34 +02:00
James Cole
c38c752520 Fix #10888 2025-09-10 20:42:15 +02:00
James Cole
28e7df2527 Small php fixes. 2025-09-10 16:16:31 +02:00
James Cole
cb0b42e44b Replace method calls. 2025-09-10 16:07:19 +02:00
James Cole
a3674c4dfe No need to use the exception either. 2025-09-10 07:03:41 +02:00
James Cole
27480561ee Catch random exception because why not. 2025-09-10 07:03:23 +02:00
github-actions[bot]
6ea7152423 Merge pull request #10886 from firefly-iii/release-1757480185
🤖 Automatically merge the PR into the develop branch.
2025-09-10 06:56:34 +02:00
JC5
dab95f7a86 🤖 Auto commit for release 'develop' on 2025-09-10 2025-09-10 06:56:25 +02:00
James Cole
adf34805a8 Shiny release PR. 2025-09-10 06:52:51 +02:00
James Cole
93e926465f Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-09-10 06:51:11 +02:00
github-actions[bot]
5b0be91f93 Merge pull request #10885 from firefly-iii/release-1757479782
🤖 Automatically merge the PR into the develop branch.
2025-09-10 06:49:50 +02:00
JC5
01e7b604da 🤖 Auto commit for release 'develop' on 2025-09-10 2025-09-10 06:49:42 +02:00
James Cole
974a550d22 Merge branch 'main' into develop 2025-09-10 06:44:16 +02:00
James Cole
58d175444b Fix #10883 2025-09-10 06:43:24 +02:00
James Cole
29d8861e96 Merge pull request #10882 from firefly-iii/dependabot/npm_and_yarn/npm_and_yarn-f5c1666f0c 2025-09-10 06:02:57 +02:00
dependabot[bot]
eb832c750f Bump vite in the npm_and_yarn group across 1 directory
Bumps the npm_and_yarn group with 1 update in the / directory: [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).


Updates `vite` from 7.1.2 to 7.1.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/v7.1.5/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 7.1.5
  dependency-type: direct:development
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-09 20:59:51 +00:00
James Cole
134770644a Fix amounts in transaction. 2025-09-09 17:14:53 +02:00
James Cole
a9f21c9371 Extra text in the PR. 2025-09-09 15:53:25 +02:00
github-actions[bot]
781947beeb Merge pull request #10879 from firefly-iii/release-1757425805
🤖 Automatically merge the PR into the develop branch.
2025-09-09 15:50:18 +02:00
JC5
9760cd2f97 🤖 Auto commit for release 'develop' on 2025-09-09 2025-09-09 15:50:06 +02:00
James Cole
d317e9ec32 Update changelog. 2025-09-09 15:41:19 +02:00
James Cole
534f7fcadb Merge branch 'main' into develop 2025-09-09 15:36:55 +02:00
James Cole
fb3f7a1d4b Merge pull request #10874 from firefly-iii/dependabot/github_actions/actions/stale-10
Bump actions/stale from 9 to 10
2025-09-08 11:41:37 +02:00
James Cole
bf2c3e3561 Merge pull request #10873 from firefly-iii/dependabot/github_actions/actions/github-script-8
Bump actions/github-script from 7 to 8
2025-09-08 11:41:12 +02:00
github-actions[bot]
b670f81dcd Merge pull request #10875 from firefly-iii/release-1757313349
🤖 Automatically merge the PR into the develop branch.
2025-09-08 08:36:01 +02:00
JC5
7aac1cdf67 🤖 Auto commit for release 'develop' on 2025-09-08 2025-09-08 08:35:49 +02:00
Sander Dorigo
fa0ac8a16c Fix php files 2025-09-08 08:31:09 +02:00
dependabot[bot]
0990b1f0b4 Bump actions/stale from 9 to 10
Bumps [actions/stale](https://github.com/actions/stale) from 9 to 10.
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/stale/compare/v9...v10)

---
updated-dependencies:
- dependency-name: actions/stale
  dependency-version: '10'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-08 03:08:14 +00:00
dependabot[bot]
c1922670c8 Bump actions/github-script from 7 to 8
Bumps [actions/github-script](https://github.com/actions/github-script) from 7 to 8.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v7...v8)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-08 03:08:10 +00:00
James Cole
81cd89d66f Final nestor and phpstan fixes. 2025-09-07 17:42:16 +02:00
James Cole
f5c202543c Clean up code. 2025-09-07 17:31:08 +02:00
James Cole
034f437c6b Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-09-07 17:30:43 +02:00
James Cole
8550ba6138 Remove unused code. 2025-09-07 17:30:34 +02:00
github-actions[bot]
a51501025b Merge pull request #10872 from firefly-iii/release-1757249926
🤖 Automatically merge the PR into the develop branch.
2025-09-07 14:58:53 +02:00
JC5
a9d26e4586 🤖 Auto commit for release 'develop' on 2025-09-07 2025-09-07 14:58:46 +02:00
James Cole
949691935f Catch exceptions. 2025-09-07 14:54:44 +02:00
James Cole
4835b05304 Optimize currency search. 2025-09-07 14:49:49 +02:00
James Cole
cce5a73dd2 Clean up and fix phpstan issues. 2025-09-07 14:28:58 +02:00
github-actions[bot]
3152f635dd Merge pull request #10868 from firefly-iii/release-1757235851
🤖 Automatically merge the PR into the develop branch.
2025-09-07 11:04:21 +02:00
JC5
12e8651017 🤖 Auto commit for release 'develop' on 2025-09-07 2025-09-07 11:04:11 +02:00
James Cole
f88286c848 Merge branches 'develop' and 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-09-07 10:59:12 +02:00
James Cole
39cf0533d9 Fix various phpstan issues. 2025-09-07 10:59:07 +02:00
github-actions[bot]
6d82887960 Merge pull request #10867 from firefly-iii/release-1757224570
🤖 Automatically merge the PR into the develop branch.
2025-09-07 07:56:20 +02:00
JC5
262f1bae34 🤖 Auto commit for release 'develop' on 2025-09-07 2025-09-07 07:56:10 +02:00
James Cole
75dfdcc220 Fix final phpstan issue. 2025-09-07 07:51:35 +02:00
James Cole
c3a3bdf525 Fix phpstan issues. 2025-09-07 07:51:01 +02:00
James Cole
602df95f3c Fix phpstan issues. 2025-09-07 07:43:04 +02:00
James Cole
296a64e284 Fix phpstan issues 2025-09-07 07:31:00 +02:00
James Cole
b87b99a755 Fix phpstan issues. 2025-09-07 06:25:26 +02:00
James Cole
bf53f5d6b7 Fix various phpstan issues. 2025-09-05 05:09:46 +02:00
James Cole
bcbb868acc Update packages. 2025-09-04 19:46:52 +02:00
James Cole
b3a9e6569e Fix #10854 2025-09-04 06:26:28 +02:00
James Cole
f174f124ef Fix # 2025-09-04 06:26:12 +02:00
James Cole
8745377f31 Fix #10833 2025-09-04 06:22:18 +02:00
James Cole
cf76e93f31 Remove primary currency from views, add some debug for #10854 2025-09-04 06:22:04 +02:00
James Cole
19e36f6f6e Share primary currency to all pages. 2025-09-03 21:02:13 +02:00
James Cole
2a7bb6f048 Fix #10853 2025-09-03 20:34:40 +02:00
James Cole
536eacbc0c Fix sort params 2025-09-03 20:34:28 +02:00
James Cole
af78158d0b Fix minor issues. 2025-09-02 18:38:34 +02:00
github-actions[bot]
fb97910a34 Merge pull request #10848 from firefly-iii/release-1756787147
🤖 Automatically merge the PR into the develop branch.
2025-09-02 06:25:54 +02:00
JC5
66b4d14129 🤖 Auto commit for release 'develop' on 2025-09-02 2025-09-02 06:25:47 +02:00
James Cole
fd53047dbc Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-09-02 06:03:17 +02:00
James Cole
5f6fc1bab4 Fix #10846 2025-09-02 06:03:11 +02:00
github-actions[bot]
cd0b64bd24 Merge pull request #10845 from firefly-iii/release-1756752249
🤖 Automatically merge the PR into the develop branch.
2025-09-01 20:44:18 +02:00
JC5
91b26bce0e 🤖 Auto commit for release 'develop' on 2025-09-01 2025-09-01 20:44:09 +02:00
James Cole
26a8bd921d Fix columns, improve views. 2025-09-01 20:39:40 +02:00
github-actions[bot]
ad77d55c16 Merge pull request #10844 from firefly-iii/release-1756729274
🤖 Automatically merge the PR into the develop branch.
2025-09-01 14:21:21 +02:00
JC5
445a383dd0 🤖 Auto commit for release 'develop' on 2025-09-01 2025-09-01 14:21:14 +02:00
Sander Dorigo
1666af939e Fix null 2025-09-01 14:03:21 +02:00
github-actions[bot]
35447f5eee Merge pull request #10843 from firefly-iii/release-1756727799
🤖 Automatically merge the PR into the develop branch.
2025-09-01 13:56:46 +02:00
JC5
7c6fcb5731 🤖 Auto commit for release 'develop' on 2025-09-01 2025-09-01 13:56:39 +02:00
Sander Dorigo
fabd9bf765 Merge branch 'develop' of https://github.com/firefly-iii/firefly-iii into develop 2025-09-01 13:38:39 +02:00
Sander Dorigo
6352d26633 fix argument 2025-09-01 13:38:32 +02:00
github-actions[bot]
ebef145bd6 Merge pull request #10842 from firefly-iii/release-1756723300
🤖 Automatically merge the PR into the develop branch.
2025-09-01 12:41:48 +02:00
JC5
acc89eb5f9 🤖 Auto commit for release 'develop' on 2025-09-01 2025-09-01 12:41:40 +02:00
Sander Dorigo
6523596415 fix bad call 2025-09-01 12:36:36 +02:00
github-actions[bot]
b6c2d23116 Merge pull request #10838 from firefly-iii/release-1756697534
🤖 Automatically merge the PR into the develop branch.
2025-09-01 05:32:22 +02:00
JC5
2a123354f9 🤖 Auto commit for release 'develop' on 2025-09-01 2025-09-01 05:32:14 +02:00
James Cole
1e7ea4b76c Improve account list and view. 2025-08-31 19:20:02 +02:00
James Cole
d959526eb3 Fix #10837 2025-08-31 19:07:45 +02:00
James Cole
8846ee9091 Fix #10827 2025-08-30 07:51:28 +02:00
github-actions[bot]
6eb8d0fc8c Merge pull request #10826 from firefly-iii/release-1756445011
🤖 Automatically merge the PR into the develop branch.
2025-08-29 07:23:42 +02:00
JC5
1b0e16b6a5 🤖 Auto commit for release 'develop' on 2025-08-29 2025-08-29 07:23:32 +02:00
James Cole
2e4df28288 Less logging. 2025-08-29 06:51:20 +02:00
James Cole
f3b7a3015d Fix #10824 2025-08-27 19:00:12 +02:00
James Cole
5de5e08b1d Fix #10820 2025-08-26 16:05:36 +02:00
James Cole
0a116cd04c Add API autocomplete tests. 2025-08-25 17:17:51 +02:00
James Cole
fd32a692c1 Add some API tests. 2025-08-25 15:31:51 +02:00
James Cole
1ac762aba8 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-08-25 15:31:15 +02:00
James Cole
315dc532b6 Fix #10819 2025-08-25 15:31:07 +02:00
github-actions[bot]
e19ed1be15 Merge pull request #10817 from firefly-iii/release-1756092462
🤖 Automatically merge the PR into the develop branch.
2025-08-25 05:27:50 +02:00
JC5
cbb0621fd9 🤖 Auto commit for release 'develop' on 2025-08-25 2025-08-25 05:27:42 +02:00
James Cole
049cbab861 Remove superfluous logging. 2025-08-24 20:31:12 +02:00
James Cole
28b620fb5c Remove superfluous logging. 2025-08-24 20:30:40 +02:00
James Cole
c183f91ff6 Add issue to changelog 2025-08-24 20:29:39 +02:00
github-actions[bot]
172efae41c Merge pull request #10816 from firefly-iii/release-1756060004
🤖 Automatically merge the PR into the develop branch.
2025-08-24 20:26:54 +02:00
JC5
756e857ba0 🤖 Auto commit for release 'develop' on 2025-08-24 2025-08-24 20:26:44 +02:00
James Cole
1cde7aab0c Fix #10815 2025-08-24 20:14:02 +02:00
James Cole
2d67eece5d Various code cleanup. 2025-08-24 17:14:07 +02:00
James Cole
b1f79c4c0f Fix #10814 2025-08-24 13:31:00 +02:00
James Cole
33bd2ceae8 Fix amounts in transaction show. 2025-08-24 13:30:41 +02:00
James Cole
e68850f192 Fix changelog. 2025-08-24 06:51:48 +02:00
James Cole
450ac7e6ee Fix #10813 2025-08-24 06:51:28 +02:00
James Cole
91f52b5dbc Add copyright statements. 2025-08-23 11:26:04 +02:00
James Cole
eed2405d76 Update changelog before I forget about it. 2025-08-23 11:17:05 +02:00
github-actions[bot]
c956df7790 Merge pull request #10809 from firefly-iii/release-1755940492
🤖 Automatically merge the PR into the develop branch.
2025-08-23 11:15:02 +02:00
JC5
0fdccec6a8 🤖 Auto commit for release 'develop' on 2025-08-23 2025-08-23 11:14:52 +02:00
James Cole
8ded54d7a8 Fix #10808 2025-08-23 08:56:25 +02:00
James Cole
bb1b4ca5ca Fix #10807 2025-08-23 08:54:50 +02:00
James Cole
e90d60113b Extra validation and a new config variable for #10806 2025-08-23 08:47:34 +02:00
James Cole
d95dada0e0 Update changelog for #10804 2025-08-22 20:20:07 +02:00
James Cole
8722456595 Fix #10804 2025-08-22 20:19:52 +02:00
James Cole
b5ad226451 Remove unused headers. 2025-08-22 15:45:39 +02:00
James Cole
ddb0e66651 Update changelog. 2025-08-22 15:45:05 +02:00
James Cole
e802899608 Pre-filter expenses, fixes #10803 2025-08-22 11:53:08 +02:00
James Cole
0894d3bf42 Fix #10802 2025-08-22 11:09:17 +02:00
James Cole
80bcfd3bcd Small issues to fix #5532 2025-08-22 09:52:27 +02:00
James Cole
8c410f42bd Expand changelog. 2025-08-22 09:15:34 +02:00
James Cole
7a1021dffc Add spent + earned info to category chart. 2025-08-22 09:15:13 +02:00
github-actions[bot]
63883c9a84 Merge pull request #10801 from firefly-iii/release-1755840718
🤖 Automatically merge the PR into the develop branch.
2025-08-22 07:32:06 +02:00
JC5
50d7f9d1ec 🤖 Auto commit for release 'develop' on 2025-08-22 2025-08-22 07:31:58 +02:00
James Cole
ebc7ea0eb6 Fix amount display 2025-08-22 07:28:09 +02:00
github-actions[bot]
b905efd0aa Merge pull request #10800 from firefly-iii/release-1755839053
🤖 Automatically merge the PR into the develop branch.
2025-08-22 07:04:20 +02:00
JC5
93085599b7 🤖 Auto commit for release 'develop' on 2025-08-22 2025-08-22 07:04:13 +02:00
James Cole
8a8bbaf827 Remove test webhook, no longer necessary. 2025-08-22 06:57:25 +02:00
James Cole
96a66b894a Fix #10799 2025-08-22 06:49:16 +02:00
James Cole
1ba641c279 Prevent a loop. 2025-08-21 20:31:32 +02:00
James Cole
6c5ddfcb8a Add newsletter link. 2025-08-21 20:10:53 +02:00
James Cole
65ddc246dc Merge branch 'main' into develop 2025-08-21 20:07:32 +02:00
James Cole
e4aff5ff4c Update webhook code. 2025-08-21 20:07:12 +02:00
James Cole
dfece91541 Update label-actions.yml
Signed-off-by: James Cole <james@firefly-iii.org>
2025-08-21 08:28:54 +02:00
James Cole
6ddda13c3a Fix #10794 2025-08-20 10:13:23 +02:00
James Cole
46219c4678 Fix #10791 2025-08-20 09:09:38 +02:00
James Cole
a1595d0647 Fix #10790 2025-08-20 07:26:18 +02:00
James Cole
4ee9f9bb27 Fix collection and message generation. 2025-08-20 06:38:53 +02:00
James Cole
bcaa0bddea Update message generator. 2025-08-20 06:32:25 +02:00
James Cole
01cce49070 Expand webhook API, edit and create screen. 2025-08-20 06:22:55 +02:00
James Cole
293be04d40 Expand webhooks to support multiple delivery payloads, event triggers and responses. 2025-08-19 19:35:12 +02:00
James Cole
44a00ec8eb Use 6. 2025-08-19 06:41:07 +02:00
James Cole
d84e772945 Use nr. 5 2025-08-19 06:36:19 +02:00
James Cole
b475f6c51d Refer to nr 4 2025-08-19 06:32:26 +02:00
James Cole
2712662510 Refer to exact version. 2025-08-19 06:30:50 +02:00
James Cole
1f2eeba862 Refer to latest 2025-08-19 06:30:15 +02:00
James Cole
46a60134f4 Refer to JC5, 6. 2025-08-19 06:28:09 +02:00
James Cole
f3f7820816 Fix lock threads action. 2025-08-19 06:10:03 +02:00
github-actions[bot]
a57f8076b2 Merge pull request #10788 from firefly-iii/develop
🤖 Automatically merge the PR into the main branch.
2025-08-19 06:08:27 +02:00
github-actions[bot]
517afa2273 Merge pull request #10787 from firefly-iii/release-1755576495
🤖 Automatically merge the PR into the develop branch.
2025-08-19 06:08:22 +02:00
JC5
2142b23aec 🤖 Auto commit for release 'v6.3.2' on 2025-08-19 2025-08-19 06:08:15 +02:00
James Cole
1bec43b111 Expand changelog. 2025-08-19 06:04:22 +02:00
James Cole
d2978a5ee8 Remove references to deleted code. 2025-08-19 06:03:58 +02:00
github-actions[bot]
39b61c71e8 Merge pull request #10786 from firefly-iii/develop
🤖 Automatically merge the PR into the main branch.
2025-08-18 20:08:34 +02:00
github-actions[bot]
fa2c964790 Merge pull request #10785 from firefly-iii/release-1755540498
🤖 Automatically merge the PR into the develop branch.
2025-08-18 20:08:29 +02:00
JC5
134aeb3a46 🤖 Auto commit for release 'v6.3.1' on 2025-08-18 2025-08-18 20:08:18 +02:00
James Cole
6f6e1a4ff4 Delete unused events. 2025-08-18 20:01:51 +02:00
James Cole
b743bf3d9e Include budget events. 2025-08-18 20:01:22 +02:00
James Cole
84ee6f16c9 Replace call to log 2025-08-18 19:35:02 +02:00
James Cole
9fe39e42b3 Update views to edit webhook. 2025-08-18 19:34:49 +02:00
James Cole
4013c7e316 Refactor methods so they're static and can be called from elsewhere. 2025-08-18 19:34:29 +02:00
github-actions[bot]
0b76747531 Merge pull request #10783 from firefly-iii/release-1755530286
🤖 Automatically merge the PR into the develop branch.
2025-08-18 17:18:15 +02:00
JC5
3129756b37 🤖 Auto commit for release 'develop' on 2025-08-18 2025-08-18 17:18:06 +02:00
James Cole
b0df383004 Update changelog. 2025-08-18 17:13:46 +02:00
James Cole
9c5b1df86c Fix #10782 2025-08-18 17:11:56 +02:00
James Cole
5854e24775 Merge branch 'main' into develop 2025-08-18 17:09:18 +02:00
Sander Dorigo
3f873422f2 Merge branch 'develop' of https://github.com/firefly-iii/firefly-iii into develop 2025-08-18 13:37:46 +02:00
Sander Dorigo
f898990773 Fix #10782 2025-08-18 13:11:59 +02:00
github-actions[bot]
a5759ab1c6 Merge pull request #10781 from firefly-iii/release-1755509351
🤖 Automatically merge the PR into the develop branch.
2025-08-18 11:29:20 +02:00
JC5
9bd6417e02 🤖 Auto commit for release 'develop' on 2025-08-18 2025-08-18 11:29:11 +02:00
Sander Dorigo
cd12a10214 Merge branch 'develop' of https://github.com/firefly-iii/firefly-iii into develop 2025-08-18 11:15:49 +02:00
Sander Dorigo
ee8cb62e04 Fix missing reference 2025-08-18 11:15:42 +02:00
github-actions[bot]
87ee95a852 Merge pull request #10780 from firefly-iii/release-1755508370
🤖 Automatically merge the PR into the develop branch.
2025-08-18 11:12:59 +02:00
JC5
10f8436885 🤖 Auto commit for release 'develop' on 2025-08-18 2025-08-18 11:12:50 +02:00
Sander Dorigo
6955846a1c Catch integer error 2025-08-18 11:05:41 +02:00
James Cole
11d2f8d471 Update release.yml
Signed-off-by: James Cole <james@firefly-iii.org>
2025-08-18 10:21:37 +02:00
github-actions[bot]
99347ffff1 Merge pull request #10779 from firefly-iii/release-1755503969
🤖 Automatically merge the PR into the develop branch.
2025-08-18 09:59:37 +02:00
JC5
3ddc11a905 🤖 Auto commit for release 'develop' on 2025-08-18 2025-08-18 09:59:29 +02:00
James Cole
0a48c0c20f Update release.yml
Signed-off-by: James Cole <james@firefly-iii.org>
2025-08-18 09:55:08 +02:00
James Cole
8bc764d6ef Merge pull request #10778 from firefly-iii/dependabot/github_actions/actions/checkout-5 2025-08-18 07:44:35 +02:00
dependabot[bot]
4b4f568558 Bump actions/checkout from 4 to 5
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-18 05:24:29 +00:00
github-actions[bot]
d42117281a Merge pull request #10777 from firefly-iii/release-1755488100
🤖 Automatically merge the PR into the develop branch.
2025-08-18 05:35:09 +02:00
JC5
d68ed5a713 🤖 Auto commit for release 'develop' on 2025-08-18 2025-08-18 05:35:01 +02:00
github-actions[bot]
2f6f36c3f0 Merge pull request #10776 from firefly-iii/release-1755442560
🤖 Automatically merge the PR into the develop branch.
2025-08-17 16:56:07 +02:00
JC5
984aa02e35 🤖 Auto commit for release 'develop' on 2025-08-17 2025-08-17 16:56:00 +02:00
James Cole
cdadc7d533 Fix #10773 for budget limits. 2025-08-17 16:47:39 +02:00
James Cole
4d59955cc5 Fix #10773 for piggies. 2025-08-17 16:47:29 +02:00
James Cole
fc547ba59a Fix #10773 for budget limits. 2025-08-17 16:47:19 +02:00
James Cole
1b2ded3167 Fix #10775 2025-08-17 16:46:31 +02:00
578 changed files with 14365 additions and 13108 deletions

View File

@@ -151,16 +151,16 @@
},
{
"name": "composer/semver",
"version": "3.4.3",
"version": "3.4.4",
"source": {
"type": "git",
"url": "https://github.com/composer/semver.git",
"reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12"
"reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12",
"reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12",
"url": "https://api.github.com/repos/composer/semver/zipball/198166618906cb2de69b95d7d47e5fa8aa1b2b95",
"reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95",
"shasum": ""
},
"require": {
@@ -212,7 +212,7 @@
"support": {
"irc": "ircs://irc.libera.chat:6697/composer",
"issues": "https://github.com/composer/semver/issues",
"source": "https://github.com/composer/semver/tree/3.4.3"
"source": "https://github.com/composer/semver/tree/3.4.4"
},
"funding": [
{
@@ -222,13 +222,9 @@
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2024-09-19T14:15:21+00:00"
"time": "2025-08-20T19:15:30+00:00"
},
{
"name": "composer/xdebug-handler",
@@ -406,16 +402,16 @@
},
{
"name": "friendsofphp/php-cs-fixer",
"version": "v3.86.0",
"version": "v3.88.2",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "4a952bd19dc97879b0620f495552ef09b55f7d36"
"reference": "a8d15584bafb0f0d9d938827840060fd4a3ebc99"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/4a952bd19dc97879b0620f495552ef09b55f7d36",
"reference": "4a952bd19dc97879b0620f495552ef09b55f7d36",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/a8d15584bafb0f0d9d938827840060fd4a3ebc99",
"reference": "a8d15584bafb0f0d9d938827840060fd4a3ebc99",
"shasum": ""
},
"require": {
@@ -426,39 +422,38 @@
"ext-hash": "*",
"ext-json": "*",
"ext-tokenizer": "*",
"fidry/cpu-core-counter": "^1.2",
"fidry/cpu-core-counter": "^1.3",
"php": "^7.4 || ^8.0",
"react/child-process": "^0.6.6",
"react/event-loop": "^1.5",
"react/promise": "^3.2",
"react/promise": "^3.3",
"react/socket": "^1.16",
"react/stream": "^1.4",
"sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0",
"symfony/console": "^5.4.47 || ^6.4.13 || ^7.0",
"symfony/event-dispatcher": "^5.4.45 || ^6.4.13 || ^7.0",
"symfony/filesystem": "^5.4.45 || ^6.4.13 || ^7.0",
"symfony/finder": "^5.4.45 || ^6.4.17 || ^7.0",
"symfony/options-resolver": "^5.4.45 || ^6.4.16 || ^7.0",
"symfony/polyfill-mbstring": "^1.32",
"symfony/polyfill-php80": "^1.32",
"symfony/polyfill-php81": "^1.32",
"symfony/process": "^5.4.47 || ^6.4.20 || ^7.2",
"symfony/stopwatch": "^5.4.45 || ^6.4.19 || ^7.0"
"symfony/console": "^5.4.47 || ^6.4.24 || ^7.0",
"symfony/event-dispatcher": "^5.4.45 || ^6.4.24 || ^7.0",
"symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.0",
"symfony/finder": "^5.4.45 || ^6.4.24 || ^7.0",
"symfony/options-resolver": "^5.4.45 || ^6.4.24 || ^7.0",
"symfony/polyfill-mbstring": "^1.33",
"symfony/polyfill-php80": "^1.33",
"symfony/polyfill-php81": "^1.33",
"symfony/polyfill-php84": "^1.33",
"symfony/process": "^5.4.47 || ^6.4.24 || ^7.2",
"symfony/stopwatch": "^5.4.45 || ^6.4.24 || ^7.0"
},
"require-dev": {
"facile-it/paraunit": "^1.3.1 || ^2.6",
"infection/infection": "^0.29.14",
"justinrainbow/json-schema": "^5.3 || ^6.4",
"facile-it/paraunit": "^1.3.1 || ^2.7",
"infection/infection": "^0.31.0",
"justinrainbow/json-schema": "^6.5",
"keradus/cli-executor": "^2.2",
"mikey179/vfsstream": "^1.6.12",
"php-coveralls/php-coveralls": "^2.8",
"php-cs-fixer/accessible-object": "^1.1",
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6",
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6",
"phpunit/phpunit": "^9.6.23 || ^10.5.47 || ^11.5.25",
"symfony/polyfill-php84": "^1.32",
"symfony/var-dumper": "^5.4.48 || ^6.4.23 || ^7.3.1",
"symfony/yaml": "^5.4.45 || ^6.4.23 || ^7.3.1"
"phpunit/phpunit": "^9.6.25 || ^10.5.53 || ^11.5.34",
"symfony/var-dumper": "^5.4.48 || ^6.4.24 || ^7.3.2",
"symfony/yaml": "^5.4.45 || ^6.4.24 || ^7.3.2"
},
"suggest": {
"ext-dom": "For handling output formats in XML",
@@ -499,7 +494,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.86.0"
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.88.2"
},
"funding": [
{
@@ -507,7 +502,7 @@
"type": "github"
}
],
"time": "2025-08-13T22:36:21+00:00"
"time": "2025-09-27T00:24:15+00:00"
},
{
"name": "psr/container",
@@ -959,23 +954,23 @@
},
{
"name": "react/promise",
"version": "v3.2.0",
"version": "v3.3.0",
"source": {
"type": "git",
"url": "https://github.com/reactphp/promise.git",
"reference": "8a164643313c71354582dc850b42b33fa12a4b63"
"reference": "23444f53a813a3296c1368bb104793ce8d88f04a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/reactphp/promise/zipball/8a164643313c71354582dc850b42b33fa12a4b63",
"reference": "8a164643313c71354582dc850b42b33fa12a4b63",
"url": "https://api.github.com/repos/reactphp/promise/zipball/23444f53a813a3296c1368bb104793ce8d88f04a",
"reference": "23444f53a813a3296c1368bb104793ce8d88f04a",
"shasum": ""
},
"require": {
"php": ">=7.1.0"
},
"require-dev": {
"phpstan/phpstan": "1.10.39 || 1.4.10",
"phpstan/phpstan": "1.12.28 || 1.4.10",
"phpunit/phpunit": "^9.6 || ^7.5"
},
"type": "library",
@@ -1020,7 +1015,7 @@
],
"support": {
"issues": "https://github.com/reactphp/promise/issues",
"source": "https://github.com/reactphp/promise/tree/v3.2.0"
"source": "https://github.com/reactphp/promise/tree/v3.3.0"
},
"funding": [
{
@@ -1028,7 +1023,7 @@
"type": "open_collective"
}
],
"time": "2024-05-24T10:39:05+00:00"
"time": "2025-08-19T18:57:03+00:00"
},
{
"name": "react/socket",
@@ -1257,16 +1252,16 @@
},
{
"name": "symfony/console",
"version": "v7.3.2",
"version": "v7.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "5f360ebc65c55265a74d23d7fe27f957870158a1"
"reference": "2b9c5fafbac0399a20a2e82429e2bd735dcfb7db"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/5f360ebc65c55265a74d23d7fe27f957870158a1",
"reference": "5f360ebc65c55265a74d23d7fe27f957870158a1",
"url": "https://api.github.com/repos/symfony/console/zipball/2b9c5fafbac0399a20a2e82429e2bd735dcfb7db",
"reference": "2b9c5fafbac0399a20a2e82429e2bd735dcfb7db",
"shasum": ""
},
"require": {
@@ -1331,7 +1326,7 @@
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v7.3.2"
"source": "https://github.com/symfony/console/tree/v7.3.4"
},
"funding": [
{
@@ -1351,7 +1346,7 @@
"type": "tidelift"
}
],
"time": "2025-07-30T17:13:41+00:00"
"time": "2025-09-22T15:31:00+00:00"
},
{
"name": "symfony/deprecation-contracts",
@@ -1422,16 +1417,16 @@
},
{
"name": "symfony/event-dispatcher",
"version": "v7.3.0",
"version": "v7.3.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
"reference": "497f73ac996a598c92409b44ac43b6690c4f666d"
"reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/497f73ac996a598c92409b44ac43b6690c4f666d",
"reference": "497f73ac996a598c92409b44ac43b6690c4f666d",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b7dc69e71de420ac04bc9ab830cf3ffebba48191",
"reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191",
"shasum": ""
},
"require": {
@@ -1482,7 +1477,7 @@
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/event-dispatcher/tree/v7.3.0"
"source": "https://github.com/symfony/event-dispatcher/tree/v7.3.3"
},
"funding": [
{
@@ -1493,12 +1488,16 @@
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2025-04-22T09:11:45+00:00"
"time": "2025-08-13T11:49:31+00:00"
},
{
"name": "symfony/event-dispatcher-contracts",
@@ -1716,16 +1715,16 @@
},
{
"name": "symfony/options-resolver",
"version": "v7.3.2",
"version": "v7.3.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/options-resolver.git",
"reference": "119bcf13e67dbd188e5dbc74228b1686f66acd37"
"reference": "0ff2f5c3df08a395232bbc3c2eb7e84912df911d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/119bcf13e67dbd188e5dbc74228b1686f66acd37",
"reference": "119bcf13e67dbd188e5dbc74228b1686f66acd37",
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/0ff2f5c3df08a395232bbc3c2eb7e84912df911d",
"reference": "0ff2f5c3df08a395232bbc3c2eb7e84912df911d",
"shasum": ""
},
"require": {
@@ -1763,7 +1762,7 @@
"options"
],
"support": {
"source": "https://github.com/symfony/options-resolver/tree/v7.3.2"
"source": "https://github.com/symfony/options-resolver/tree/v7.3.3"
},
"funding": [
{
@@ -1783,11 +1782,11 @@
"type": "tidelift"
}
],
"time": "2025-07-15T11:36:08+00:00"
"time": "2025-08-05T10:16:07+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.32.0",
"version": "v1.33.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
@@ -1846,7 +1845,7 @@
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0"
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0"
},
"funding": [
{
@@ -1857,6 +1856,10 @@
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
@@ -1866,16 +1869,16 @@
},
{
"name": "symfony/polyfill-intl-grapheme",
"version": "v1.32.0",
"version": "v1.33.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
"reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe"
"reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe",
"reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70",
"reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70",
"shasum": ""
},
"require": {
@@ -1924,7 +1927,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0"
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0"
},
"funding": [
{
@@ -1935,16 +1938,20 @@
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-09-09T11:45:10+00:00"
"time": "2025-06-27T09:58:17+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.32.0",
"version": "v1.33.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
@@ -2005,7 +2012,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0"
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0"
},
"funding": [
{
@@ -2016,6 +2023,10 @@
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
@@ -2025,7 +2036,7 @@
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.32.0",
"version": "v1.33.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
@@ -2086,7 +2097,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0"
},
"funding": [
{
@@ -2097,6 +2108,10 @@
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
@@ -2106,7 +2121,7 @@
},
{
"name": "symfony/polyfill-php80",
"version": "v1.32.0",
"version": "v1.33.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
@@ -2166,7 +2181,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.32.0"
"source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0"
},
"funding": [
{
@@ -2177,6 +2192,10 @@
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
@@ -2186,7 +2205,7 @@
},
{
"name": "symfony/polyfill-php81",
"version": "v1.32.0",
"version": "v1.33.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php81.git",
@@ -2242,7 +2261,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php81/tree/v1.32.0"
"source": "https://github.com/symfony/polyfill-php81/tree/v1.33.0"
},
"funding": [
{
@@ -2253,6 +2272,10 @@
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
@@ -2261,17 +2284,97 @@
"time": "2024-09-09T11:45:10+00:00"
},
{
"name": "symfony/process",
"version": "v7.3.0",
"name": "symfony/polyfill-php84",
"version": "v1.33.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af"
"url": "https://github.com/symfony/polyfill-php84.git",
"reference": "d8ced4d875142b6a7426000426b8abc631d6b191"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/40c295f2deb408d5e9d2d32b8ba1dd61e36f05af",
"reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af",
"url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191",
"reference": "d8ced4d875142b6a7426000426b8abc631d6b191",
"shasum": ""
},
"require": {
"php": ">=7.2"
},
"type": "library",
"extra": {
"thanks": {
"url": "https://github.com/symfony/polyfill",
"name": "symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Php84\\": ""
},
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2025-06-24T13:30:11+00:00"
},
{
"name": "symfony/process",
"version": "v7.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "f24f8f316367b30810810d4eb30c543d7003ff3b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/f24f8f316367b30810810d4eb30c543d7003ff3b",
"reference": "f24f8f316367b30810810d4eb30c543d7003ff3b",
"shasum": ""
},
"require": {
@@ -2303,7 +2406,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/process/tree/v7.3.0"
"source": "https://github.com/symfony/process/tree/v7.3.4"
},
"funding": [
{
@@ -2314,12 +2417,16 @@
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2025-04-17T09:11:12+00:00"
"time": "2025-09-11T10:12:26+00:00"
},
{
"name": "symfony/service-contracts",
@@ -2468,16 +2575,16 @@
},
{
"name": "symfony/string",
"version": "v7.3.2",
"version": "v7.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "42f505aff654e62ac7ac2ce21033818297ca89ca"
"reference": "f96476035142921000338bad71e5247fbc138872"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/42f505aff654e62ac7ac2ce21033818297ca89ca",
"reference": "42f505aff654e62ac7ac2ce21033818297ca89ca",
"url": "https://api.github.com/repos/symfony/string/zipball/f96476035142921000338bad71e5247fbc138872",
"reference": "f96476035142921000338bad71e5247fbc138872",
"shasum": ""
},
"require": {
@@ -2492,7 +2599,6 @@
},
"require-dev": {
"symfony/emoji": "^7.1",
"symfony/error-handler": "^6.4|^7.0",
"symfony/http-client": "^6.4|^7.0",
"symfony/intl": "^6.4|^7.0",
"symfony/translation-contracts": "^2.5|^3.0",
@@ -2535,7 +2641,7 @@
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v7.3.2"
"source": "https://github.com/symfony/string/tree/v7.3.4"
},
"funding": [
{
@@ -2555,7 +2661,7 @@
"type": "tidelift"
}
],
"time": "2025-07-10T08:47:49+00:00"
"time": "2025-09-11T14:36:48+00:00"
}
],
"packages-dev": [],

View File

@@ -1,6 +1,4 @@
parameters:
scanFiles:
- ../_ide_helper.php
paths:
- ../app
- ../database
@@ -9,28 +7,24 @@ parameters:
- ../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
# all errors below I will never fix.
- '#expects view-string\|null, string given#'
- '#expects view-string, string given#'
- "#Parameter \\#[1-2] \\$num[1-2] of function bc[a-z]+ expects numeric-string, [a-z\\-|&]+ given#"
- identifier: missingType.generics # not interesting enough to fix.
-
identifier: larastan.noEnvCallsOutsideOfConfig
path: ../app/Console/Commands/System/CreatesDatabase.php
- 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#'
- identifier: varTag.type # needs a custom extension for every repository, not gonna happen.
- '#Dynamic call to static method Illuminate#'
- '#Call to an undefined method Illuminate\\Database\\Eloquent\\Relations\\HasMany::before#' # is custom scope
- '#Call to an undefined method Illuminate\\Database\\Eloquent\\Relations\\HasMany::after#' # is custom scope
- '#Call to an undefined method Illuminate\\Database\\Eloquent\\Relations\\HasMany::withTrashed#' # is to allow soft delete
- '#Call to an undefined method Illuminate\\Database\\Eloquent\\Relations\\HasMany::accountTypeIn#' # is a custom scope
- '#Call to an undefined method Illuminate\\Database\\Eloquent\\Relations\\BelongsTo::withTrashed#' # is to allow soft delete
# The level 8 is the highest level. original was 5
# 7 is more than enough, higher just leaves NULL things.

View File

@@ -314,8 +314,9 @@ DEMO_USERNAME=
DEMO_PASSWORD=
#
# Disable or enable the running balance column data
# Please disable this. It's a very experimental feature.
# Disable or enable the running balance column data.
# If you enable this, please also run "php artisan firefly-iii:correct-database"
# This will take some time the first run.
#
USE_RUNNING_BALANCE=false

View File

@@ -25,7 +25,7 @@ feature:
This issue has been marked as a feature request.
If you come across this issue, please be aware there is NO need to reply with "+1" or "me too" or "I need this too" or whatever. Such comments are not helpful, and do not influence [the roadmap](https://roadmap.firefly-iii.org/). Your comment may be :skull: deleted. You can subscribe to this issue to get updates.
If you come across this issue, please be aware there is NO need to reply with "+1" or "I need this too" or "any updates?" or whatever. Such comments are not helpful, and do not influence [the roadmap](https://roadmap.firefly-iii.org/). Your comment may be :skull: deleted. You can subscribe to this issue to get updates.
Thank you for your contributions.
@@ -39,7 +39,7 @@ epic:
This issue has been marked as an epic. In epics, large amounts of works are collected that will be part of a major new feature. If you have more ideas that could be a part of this epic, feel free to reply.
*However*, please be aware there is NO need to reply with "+1" or "me too" or "I need this too" or whatever. Such comments are not helpful, and do not influence [the roadmap](https://roadmap.firefly-iii.org/). Your comment may be :skull: deleted.
*However*, please be aware there is NO need to reply with "+1" or "I need this too" or "any updates?" or whatever. Such comments are not helpful, and do not influence [the roadmap](https://roadmap.firefly-iii.org/). Your comment may be :skull: deleted.
If you are merely interested in this epic's progress, you can subscribe to this issue to get updates.
@@ -56,7 +56,7 @@ enhancement:
This issue has been marked as an enhancement.
If you come across this issue, please be aware there is NO need to reply with "+1" or "me too" or "I need this too" or whatever. Such comments are not helpful, and do not influence [the roadmap](https://roadmap.firefly-iii.org/). Your comment may be :skull: deleted. You can subscribe to this issue to get updates.
If you come across this issue, please be aware there is NO need to reply with "+1" or "I need this too" or "any updates?" or whatever. Such comments are not helpful, and do not influence [the roadmap](https://roadmap.firefly-iii.org/). Your comment may be :skull: deleted. You can subscribe to this issue to get updates.
Thank you for your contributions.

View File

@@ -16,6 +16,10 @@ Alpha releases are created to test new features and fixes before they are includ
The release files are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/).
## Develop with Firefly III
Are you interested in (future) API changes to Firefly III, or other interesting dev-related updates? Sign up to the [Firefly III developer newsletter](https://firefly-iii.kit.com/dev) to receive low-frequency updates about the development of Firefly III.
## Support Firefly III
Did you know you can support the development of Firefly III? You can donate in many ways, like GitHub Sponsors or Patreon. Please [follow this link](https://bit.ly/donate-to-Firefly-III) for more information. Thank you for your consideration.

View File

@@ -16,6 +16,10 @@ Alpha releases are created to test new features and fixes before they are includ
The release files are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/).
## Develop with Firefly III
Are you interested in (future) API changes to Firefly III, or other interesting dev-related updates? Sign up to the [Firefly III developer newsletter](https://firefly-iii.kit.com/dev) to receive low-frequency updates about the development of Firefly III.
## Support Firefly III
Did you know you can support the development of Firefly III? You can donate in many ways, like GitHub Sponsors or Patreon. Please [follow this link](https://bit.ly/donate-to-Firefly-III) for more information. Thank you for your consideration.

View File

@@ -16,6 +16,10 @@ There is no changelog for this release, as it is not final. However, [changelog.
The release files are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/).
## Develop with Firefly III
Are you interested in (future) API changes to Firefly III, or other interesting dev-related updates? Sign up to the [Firefly III developer newsletter](https://firefly-iii.kit.com/dev) to receive low-frequency updates about the development of Firefly III.
## Support Firefly III
Did you know you can support the development of Firefly III? You can donate in many ways, like GitHub Sponsors or Patreon. Please [follow this link](https://bit.ly/donate-to-Firefly-III) for more information. Thank you for your consideration.

View File

@@ -16,6 +16,10 @@ The changelog for this release may not be up-to-date, so it is not included. How
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/).
## Develop with Firefly III
Are you interested in (future) API changes to Firefly III, or other interesting dev-related updates? Sign up to the [Firefly III developer newsletter](https://firefly-iii.kit.com/dev) to receive low-frequency updates about the development of Firefly III.
## Support Firefly III
Did you know you can support the development of Firefly III? You can donate in many ways, like GitHub Sponsors or Patreon. Please [follow this link](https://bit.ly/donate-to-Firefly-III) for more information. Thank you for your consideration.

View File

@@ -11,6 +11,10 @@ Welcome to release %version of Firefly III. It contains the latest fixes, transl
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/).
## Develop with Firefly III
Are you interested in (future) API changes to Firefly III, or other interesting dev-related updates? Sign up to the [Firefly III developer newsletter](https://firefly-iii.kit.com/dev) to receive low-frequency updates about the development of Firefly III.
## Support Firefly III
Did you know you can support the development of Firefly III? You can donate in many ways, like GitHub Sponsors or Patreon. Please [follow this link](https://bit.ly/donate-to-Firefly-III) for more information. Thank you for your consideration.

View File

@@ -15,7 +15,7 @@ jobs:
timeout-minutes: 10
steps:
- name: Prune cancelled/skipped runs
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
@@ -45,7 +45,7 @@ jobs:
}
- name: Prune runs older than 3 days
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |

View File

@@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: 'Checkout repository'
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: 'Dependency review'

View File

@@ -21,7 +21,7 @@ jobs:
discussions: write
runs-on: ubuntu-latest
steps:
- uses: JC5/lock-threads@v6.0.2
- uses: JC5/lock-threads@v6.0.6
with:
issue-inactive-days: 21
pr-inactive-days: 21

View File

@@ -50,7 +50,7 @@ jobs:
git pull
echo "Current branch is $(git branch --show-current)"
env:
version: ${{ github.event_name == 'schedule' && 'develop' || github.event.inputs.version }}
version: ${{ github.event_name == 'schedule' && 'develop' || inputs.version }}
- name: Configure Git
run: |
# do some configuration
@@ -118,7 +118,7 @@ jobs:
env:
FIREFLY_III_ROOT: /github/workspace
GH_TOKEN: ""
FF_III_VERSION: ${{ github.event_name == 'schedule' && 'develop' || github.event.inputs.version }}
FF_III_VERSION: ${{ github.event_name == 'schedule' && 'develop' || inputs.version }}
- name: Generate JSON v1
id: json-v1
uses: JC5/firefly-iii-dev@main
@@ -221,7 +221,7 @@ jobs:
echo "tarName=$tarName" >> "$GITHUB_ENV"
echo "BRANCH_NAME=$BRANCH_NAME" >> "$GITHUB_ENV"
env:
version: ${{ github.event_name == 'schedule' && 'develop' || github.event.inputs.version }}
version: ${{ github.event_name == 'schedule' && 'develop' || inputs.version }}
- name: Commit all changes
run: |
# add all content, except output.txt (this contains the changelog and/or the download instructions)
@@ -232,12 +232,12 @@ jobs:
git commit -m "🤖 Auto commit for release '$version' on $(date +'%Y-%m-%d')" || true
git push
env:
version: ${{ github.event_name == 'schedule' && 'develop' || github.event.inputs.version }}
version: ${{ github.event_name == 'schedule' && 'develop' || inputs.version }}
- name: Generate release description
id: release-description
uses: JC5/firefly-iii-dev@main
with:
action: "ff3:generate-release-notes firefly-iii ${{ github.event.inputs.version }}"
action: "ff3:generate-release-notes firefly-iii ${{ inputs.version || 'develop' }}"
output: 'output'
env:
FIREFLY_III_ROOT: /github/workspace
@@ -250,7 +250,7 @@ jobs:
fi
echo "Merge all changes from $BRANCH_NAME back into '$MERGE_INTO' using a PR"
PR_URL=$(gh pr create -B $MERGE_INTO -H $BRANCH_NAME --title "🤖 Automatic PR to merge all changes into the '$MERGE_INTO' branch." --body '🤖 Created by GitHub action')
PR_URL=$(gh pr create -B $MERGE_INTO -H $BRANCH_NAME --title "🤖 Automatic PR to merge all changes into the '$MERGE_INTO' branch." --body '🤖 This PR was created automatically by a GitHub action to merge the changed files into this branch. It will be merged automatically. `Share and enjoy`')
echo "PR URL is '$PR_URL'"
IFS='/' read -ra parts <<< "$PR_URL"
PR_NR=$(printf %s\\n "${parts[@]:(-1)}")
@@ -272,7 +272,7 @@ jobs:
echo "Also merge everything into main since this is a release."
echo 'create PR'
PR_URL=$(gh pr create -B main -H develop --title "🤖 Automatic PR to merge all changes into the main branch." --body "🤖 Created by GitHub action")
PR_URL=$(gh pr create -B main -H develop --title "🤖 Automatic PR to merge all changes into the main branch." --body '🤖 This PR was created automatically by a GitHub action to merge the changed files into this branch. It will be merged automatically. `Share and enjoy`')
echo "PR URL is '$PR_URL'"
IFS='/' read -ra parts <<< "$PR_URL"
@@ -291,7 +291,7 @@ jobs:
echo "DONE!"
env:
GH_TOKEN: ${{ github.token }}
version: ${{ github.event_name == 'schedule' && 'develop' || github.event.inputs.version }}
version: ${{ github.event_name == 'schedule' && 'develop' || inputs.version }}
- name: Create archives
run: |
echo "Create zip file $zipName"
@@ -375,7 +375,7 @@ jobs:
fi
env:
GH_TOKEN: ${{ github.token }}
version: ${{ github.event_name == 'schedule' && 'develop' || github.event.inputs.version }}
version: ${{ github.event_name == 'schedule' && 'develop' || inputs.version }}
- name: Upload artifacts
run: |
# add zip file to release.
@@ -411,4 +411,4 @@ jobs:
rm -f $tarName.sha256
env:
GH_TOKEN: ${{ github.token }}
version: ${{ github.event_name == 'schedule' && 'develop' || github.event.inputs.version }}
version: ${{ github.event_name == 'schedule' && 'develop' || inputs.version }}

View File

@@ -15,7 +15,7 @@ jobs:
actions: write
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v9
- uses: actions/stale@v10
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: |

View File

@@ -114,6 +114,7 @@ class AccountController extends Controller
'id' => (string) $account->id,
'name' => $account->name,
'name_with_balance' => $nameWithBalance,
'active' => $account->active,
'type' => $account->accountType->type,
'currency_id' => (string) $useCurrency->id,
'currency_name' => $useCurrency->name,

View File

@@ -67,8 +67,9 @@ class BudgetController extends Controller
$result = $this->repository->searchBudget($data['query'], $this->parameters->get('limit'));
$filtered = $result->map(
static fn (Budget $item) => [
'id' => (string) $item->id,
'name' => $item->name,
'id' => (string) $item->id,
'name' => $item->name,
'active' => $item->active,
]
);

View File

@@ -28,8 +28,10 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Support\Facades\Amount;
use Illuminate\Http\JsonResponse;
/**
@@ -96,6 +98,7 @@ class PiggyBankController extends Controller
/** @var PiggyBank $piggy */
foreach ($piggies as $piggy) {
/** @var TransactionCurrency $currency */
$currency = $piggy->transactionCurrency;
$currentAmount = $this->piggyRepository->getCurrentAmount($piggy);
$objectGroup = $piggy->objectGroups()->first();
@@ -105,8 +108,8 @@ class PiggyBankController extends Controller
'name_with_balance' => sprintf(
'%s (%s / %s)',
$piggy->name,
app('amount')->formatAnything($currency, $currentAmount, false),
app('amount')->formatAnything($currency, $piggy->target_amount, false),
Amount::formatAnything($currency, $currentAmount, false),
Amount::formatAnything($currency, $piggy->target_amount, false),
),
'currency_id' => (string) $currency->id,
'currency_name' => $currency->name,

View File

@@ -69,6 +69,7 @@ class RecurrenceController extends Controller
'id' => (string) $recurrence->id,
'name' => $recurrence->title,
'description' => $recurrence->description,
'active' => $recurrence->active,
];
}

View File

@@ -37,7 +37,7 @@ use Illuminate\Http\JsonResponse;
class RuleController extends Controller
{
private RuleRepositoryInterface $repository;
protected array $acceptedRoles = [UserRoleEnum::READ_RULES];
protected array $acceptedRoles = [UserRoleEnum::READ_RULES];
/**
* RuleController constructor.
@@ -66,9 +66,10 @@ class RuleController extends Controller
/** @var Rule $rule */
foreach ($rules as $rule) {
$response[] = [
'id' => (string) $rule->id,
'id' => (string)$rule->id,
'name' => $rule->title,
'description' => $rule->description,
'active' => $rule->active,
];
}

View File

@@ -69,6 +69,7 @@ class RuleGroupController extends Controller
'id' => (string) $group->id,
'name' => $group->title,
'description' => $group->description,
'active' => $group->active,
];
}

View File

@@ -130,6 +130,7 @@ class AccountController extends Controller
'yAxisID' => 0,
'period' => '1D',
'entries' => [],
'pc_entries' => [],
];
if ($this->convertToPrimary) {
$currentSet['pc_entries'] = [];

View File

@@ -1,5 +1,26 @@
<?php
/*
* BalanceController.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\Api\V1\Controllers\Chart;
@@ -10,9 +31,7 @@ use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Http\Api\AccountBalanceGrouped;
use FireflyIII\Support\Http\Api\CleansChartData;
use FireflyIII\Support\Http\Api\CollectsAccountsFromFilter;

View File

@@ -31,10 +31,10 @@ use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Budget;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Http\Api\CleansChartData;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
@@ -55,7 +55,6 @@ class BudgetController extends Controller
protected OperationsRepositoryInterface $opsRepository;
private BudgetLimitRepositoryInterface $blRepository;
private array $currencies = [];
private TransactionCurrency $currency;
private BudgetRepositoryInterface $repository;
public function __construct()
@@ -115,7 +114,7 @@ class BudgetController extends Controller
// get all limits:
$limits = $this->blRepository->getBudgetLimits($budget, $start, $end);
$rows = [];
$spent = $this->opsRepository->listExpenses($start, $end, null, new Collection([$budget]));
$spent = $this->opsRepository->listExpenses($start, $end, null, new Collection()->push($budget));
$expenses = $this->processExpenses($budget->id, $spent, $start, $end);
$converter = new ExchangeRateConverter();
$currencies = [$this->primaryCurrency->id => $this->primaryCurrency];
@@ -134,9 +133,9 @@ class BudgetController extends Controller
$row['pc_left'] = '0';
$row['pc_overspent'] = '0';
if (null !== $limit) {
if ($limit instanceof BudgetLimit) {
$row['budgeted'] = $limit->amount;
$row['left'] = bcsub($row['budgeted'], bcmul($row['spent'], '-1'));
$row['left'] = bcsub((string) $row['budgeted'], bcmul((string) $row['spent'], '-1'));
$row['overspent'] = bcmul($row['left'], '-1');
$row['left'] = 1 === bccomp($row['left'], '0') ? $row['left'] : '0';
$row['overspent'] = 1 === bccomp($row['overspent'], '0') ? $row['overspent'] : '0';
@@ -144,7 +143,7 @@ class BudgetController extends Controller
// convert data if necessary.
if (true === $this->convertToPrimary && $currencyId !== $this->primaryCurrency->id) {
$currencies[$currencyId] ??= TransactionCurrency::find($currencyId);
$currencies[$currencyId] ??= Amount::getTransactionCurrencyById($currencyId);
$row['pc_budgeted'] = $converter->convert($currencies[$currencyId], $this->primaryCurrency, $start, $row['budgeted']);
$row['pc_spent'] = $converter->convert($currencies[$currencyId], $this->primaryCurrency, $start, $row['spent']);
$row['pc_left'] = $converter->convert($currencies[$currencyId], $this->primaryCurrency, $start, $row['left']);
@@ -201,18 +200,18 @@ class BudgetController extends Controller
return $return;
}
/**
* When no budget limits are present, the expenses of the whole period are collected and grouped.
* This is grouped per currency. Because there is no limit set, "left to spend" and "overspent" are empty.
*
* @throws FireflyException
*/
private function noBudgetLimits(Budget $budget, Carbon $start, Carbon $end): array
{
$spent = $this->opsRepository->listExpenses($start, $end, null, new Collection([$budget]));
return $this->processExpenses($budget->id, $spent, $start, $end);
}
// /**
// * When no budget limits are present, the expenses of the whole period are collected and grouped.
// * This is grouped per currency. Because there is no limit set, "left to spend" and "overspent" are empty.
// *
// * @throws FireflyException
// */
// private function noBudgetLimits(Budget $budget, Carbon $start, Carbon $end): array
// {
// $spent = $this->opsRepository->listExpenses($start, $end, null, new Collection()->push($budget));
//
// return $this->processExpenses($budget->id, $spent, $start, $end);
// }
/**
* Shared between the "noBudgetLimits" function and "processLimit". Will take a single set of expenses and return
@@ -232,7 +231,7 @@ class BudgetController extends Controller
* @var array $block
*/
foreach ($spent as $currencyId => $block) {
$this->currencies[$currencyId] ??= TransactionCurrency::find($currencyId);
$this->currencies[$currencyId] ??= Amount::getTransactionCurrencyById($currencyId);
$return[$currencyId] ??= [
'currency_id' => (string)$currencyId,
'currency_code' => $block['currency_code'],
@@ -251,66 +250,68 @@ class BudgetController extends Controller
// var_dump($return);
/** @var array $journal */
foreach ($currentBudgetArray['transaction_journals'] as $journal) {
$return[$currencyId]['spent'] = bcadd($return[$currencyId]['spent'], (string)$journal['amount']);
/** @var numeric-string $amount */
$amount = (string)$journal['amount'];
$return[$currencyId]['spent'] = bcadd($return[$currencyId]['spent'], $amount);
}
}
return $return;
}
/**
* Function that processes each budget limit (per budget).
*
* If you have a budget limit in EUR, only transactions in EUR will be considered.
* If you have a budget limit in GBP, only transactions in GBP will be considered.
*
* If you have a budget limit in EUR, and a transaction in GBP, it will not be considered for the EUR budget limit.
*
* @throws FireflyException
*/
private function budgetLimits(Budget $budget, Collection $limits): array
{
Log::debug(sprintf('Now in budgetLimits(#%d)', $budget->id));
$data = [];
// /**
// * Function that processes each budget limit (per budget).
// *
// * If you have a budget limit in EUR, only transactions in EUR will be considered.
// * If you have a budget limit in GBP, only transactions in GBP will be considered.
// *
// * If you have a budget limit in EUR, and a transaction in GBP, it will not be considered for the EUR budget limit.
// *
// * @throws FireflyException
// */
// private function budgetLimits(Budget $budget, Collection $limits): array
// {
// Log::debug(sprintf('Now in budgetLimits(#%d)', $budget->id));
// $data = [];
//
// /** @var BudgetLimit $limit */
// foreach ($limits as $limit) {
// $data = array_merge($data, $this->processLimit($budget, $limit));
// }
//
// return $data;
// }
/** @var BudgetLimit $limit */
foreach ($limits as $limit) {
$data = array_merge($data, $this->processLimit($budget, $limit));
}
return $data;
}
/**
* @throws FireflyException
*/
private function processLimit(Budget $budget, BudgetLimit $limit): array
{
Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__));
$end = clone $limit->end_date;
$end->endOfDay();
$spent = $this->opsRepository->listExpenses($limit->start_date, $end, null, new Collection([$budget]));
$limitCurrencyId = $limit->transaction_currency_id;
/** @var array $entry */
// only spent the entry where the entry's currency matches the budget limit's currency
// so $filtered will only have 1 or 0 entries
$filtered = array_filter($spent, fn ($entry) => $entry['currency_id'] === $limitCurrencyId);
$result = $this->processExpenses($budget->id, $filtered, $limit->start_date, $end);
if (1 === count($result)) {
$compare = bccomp($limit->amount, (string)app('steam')->positive($result[$limitCurrencyId]['spent']));
$result[$limitCurrencyId]['budgeted'] = $limit->amount;
if (1 === $compare) {
// convert this amount into the primary currency:
$result[$limitCurrencyId]['left'] = bcadd($limit->amount, (string)$result[$limitCurrencyId]['spent']);
}
if ($compare <= 0) {
$result[$limitCurrencyId]['overspent'] = app('steam')->positive(bcadd($limit->amount, (string)$result[$limitCurrencyId]['spent']));
}
}
return $result;
}
// /**
// * @throws FireflyException
// */
// private function processLimit(Budget $budget, BudgetLimit $limit): array
// {
// Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__));
// $end = clone $limit->end_date;
// $end->endOfDay();
// $spent = $this->opsRepository->listExpenses($limit->start_date, $end, null, new Collection()->push($budget));
// $limitCurrencyId = $limit->transaction_currency_id;
//
// /** @var array $entry */
// // only spent the entry where the entry's currency matches the budget limit's currency
// // so $filtered will only have 1 or 0 entries
// $filtered = array_filter($spent, fn ($entry) => $entry['currency_id'] === $limitCurrencyId);
// $result = $this->processExpenses($budget->id, $filtered, $limit->start_date, $end);
// if (1 === count($result)) {
// $compare = bccomp($limit->amount, (string)app('steam')->positive($result[$limitCurrencyId]['spent']));
// $result[$limitCurrencyId]['budgeted'] = $limit->amount;
// if (1 === $compare) {
// // convert this amount into the primary currency:
// $result[$limitCurrencyId]['left'] = bcadd($limit->amount, (string)$result[$limitCurrencyId]['spent']);
// }
// if ($compare <= 0) {
// $result[$limitCurrencyId]['overspent'] = app('steam')->positive(bcadd($limit->amount, (string)$result[$limitCurrencyId]['spent']));
// }
// }
//
// return $result;
// }
private function filterLimit(int $currencyId, Collection $limits): ?BudgetLimit
{

View File

@@ -97,22 +97,23 @@ class CategoryController extends Controller
$collector = app(GroupCollectorInterface::class);
$collector->setRange($start, $end)->withAccountInformation();
$collector->setXorAccounts($accounts)->withCategoryInformation();
$collector->setTypes([TransactionTypeEnum::WITHDRAWAL->value, TransactionTypeEnum::RECONCILIATION->value]);
$collector->setTypes([TransactionTypeEnum::WITHDRAWAL->value, TransactionTypeEnum::DEPOSIT->value]);
$journals = $collector->getExtractedJournals();
/** @var array $journal */
foreach ($journals as $journal) {
// find journal:
$journalCurrencyId = (int)$journal['currency_id'];
$currency = $currencies[$journalCurrencyId] ?? $this->currencyRepos->find($journalCurrencyId);
$currencies[$journalCurrencyId] = $currency;
$currencyId = (int)$currency->id;
$currencyName = (string)$currency->name;
$currencyCode = (string)$currency->code;
$currencySymbol = (string)$currency->symbol;
$currencyDecimalPlaces = (int)$currency->decimal_places;
$amount = Steam::positive($journal['amount']);
$pcAmount = null;
$journalCurrencyId = (int)$journal['currency_id'];
$type = $journal['transaction_type_type'];
$currency = $currencies[$journalCurrencyId] ?? $this->currencyRepos->find($journalCurrencyId);
$currencies[$journalCurrencyId] = $currency;
$currencyId = (int)$currency->id;
$currencyName = (string)$currency->name;
$currencyCode = (string)$currency->code;
$currencySymbol = (string)$currency->symbol;
$currencyDecimalPlaces = (int)$currency->decimal_places;
$amount = Steam::positive((string)$journal['amount']);
$pcAmount = null;
// overrule if necessary:
if ($this->convertToPrimary && $journalCurrencyId === $this->primaryCurrency->id) {
@@ -129,8 +130,8 @@ class CategoryController extends Controller
}
$categoryName = $journal['category_name'] ?? (string)trans('firefly.no_category');
$key = sprintf('%s-%s', $categoryName, $currencyCode);
$categoryName = $journal['category_name'] ?? (string)trans('firefly.no_category');
$key = sprintf('%s-%s', $categoryName, $currencyCode);
// create arrays
$return[$key] ??= [
'label' => $categoryName,
@@ -150,23 +151,37 @@ class CategoryController extends Controller
'yAxisID' => 0,
'type' => 'bar',
'entries' => [
'spent' => '0',
'spent' => '0',
'earned' => '0',
],
'pc_entries' => [
'spent' => '0',
'spent' => '0',
'earned' => '0',
],
];
// add monies
$return[$key]['entries']['spent'] = bcadd($return[$key]['entries']['spent'], (string)$amount);
if (null !== $pcAmount) {
$return[$key]['pc_entries']['spent'] = bcadd($return[$key]['pc_entries']['spent'], (string)$pcAmount);
// expenses to spent
if (TransactionTypeEnum::WITHDRAWAL->value === $type) {
$return[$key]['entries']['spent'] = bcadd($return[$key]['entries']['spent'], $amount);
if (null !== $pcAmount) {
$return[$key]['pc_entries']['spent'] = bcadd($return[$key]['pc_entries']['spent'], $pcAmount);
}
continue;
}
// positive amount = earned
if (TransactionTypeEnum::DEPOSIT->value === $type) {
$return[$key]['entries']['earned'] = bcadd($return[$key]['entries']['earned'], $amount);
if (null !== $pcAmount) {
$return[$key]['pc_entries']['earned'] = bcadd($return[$key]['pc_entries']['earned'], $pcAmount);
}
}
}
$return = array_values($return);
// order by amount
usort($return, static fn (array $a, array $b) => (float)$a['entries']['spent'] < (float)$b['entries']['spent'] ? 1 : -1);
usort($return, static fn (array $a, array $b) => ((float)$a['entries']['spent'] + (float)$a['entries']['earned']) < ((float)$b['entries']['spent'] + (float)$b['entries']['earned']) ? 1 : -1);
return response()->json($this->clean($return));
}

View File

@@ -27,7 +27,6 @@ namespace FireflyIII\Api\V1\Controllers;
use Carbon\Carbon;
use Carbon\Exceptions\InvalidFormatException;
use FireflyIII\Exceptions\BadHttpHeaderException;
use FireflyIII\Models\Preference;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Facades\Steam;
@@ -66,8 +65,6 @@ abstract class Controller extends BaseController
protected const string JSON_CONTENT_TYPE = 'application/json';
protected array $accepts = ['application/json', 'application/vnd.api+json'];
/** @var array<int, string> */
protected array $allowedSort;
protected bool $convertToPrimary = false;
protected TransactionCurrency $primaryCurrency;
protected ParameterBag $parameters;
@@ -78,7 +75,6 @@ abstract class Controller extends BaseController
public function __construct()
{
// get global parameters
$this->allowedSort = config('firefly.allowed_sort_parameters');
$this->middleware(
function ($request, $next) {
$this->parameters = $this->getParameters();
@@ -108,12 +104,7 @@ abstract class Controller extends BaseController
{
$bag = new ParameterBag();
$page = (int)request()->get('page');
if ($page < 1) {
$page = 1;
}
if ($page > 2 ** 16) {
$page = 2 ** 16;
}
$page = min(max(1, $page), 2 ** 16);
$bag->set('page', $page);
// some date fields:
@@ -131,19 +122,15 @@ abstract class Controller extends BaseController
$obj = null;
if (null !== $date) {
try {
$obj = Carbon::parse((string)$date);
$obj = Carbon::parse((string)$date, config('app.timezone'));
} catch (InvalidFormatException $e) {
// don't care
Log::warning(
sprintf(
'Ignored invalid date "%s" in API controller parameter check: %s',
substr((string)$date, 0, 20),
$e->getMessage()
)
);
Log::warning(sprintf('Ignored invalid date "%s" in API controller parameter check: %s', substr((string)$date, 0, 20), $e->getMessage()));
}
}
$bag->set($field, $obj);
if ($obj instanceof Carbon) {
$bag->set($field, $obj);
}
}
// integer fields:
@@ -159,13 +146,7 @@ abstract class Controller extends BaseController
}
if (null !== $value) {
$value = (int)$value;
if ($value < 1) {
$value = 1;
}
if ($value > 2 ** 16) {
$value = 2 ** 16;
}
$value = min(max(1, $value), 2 ** 16);
$bag->set($integer, $value);
}
if (null === $value
@@ -175,46 +156,14 @@ abstract class Controller extends BaseController
/** @var User $user */
$user = auth()->user();
/** @var Preference $pageSize */
$pageSize = (int)app('preferences')->getForUser($user, 'listPageSize', 50)->data;
$bag->set($integer, $pageSize);
}
}
// sort fields:
return $this->getSortParameters($bag);
}
private function getSortParameters(ParameterBag $bag): ParameterBag
{
$sortParameters = [];
try {
$param = (string)request()->query->get('sort');
} catch (BadRequestException $e) {
Log::error('Request field "sort" contains a non-scalar value. Value set to NULL.');
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
$param = '';
}
if ('' === $param) {
return $bag;
}
$parts = explode(',', $param);
foreach ($parts as $part) {
$part = trim($part);
$direction = 'asc';
if ('-' === $part[0]) {
$part = substr($part, 1);
$direction = 'desc';
}
if (in_array($part, $this->allowedSort, true)) {
$sortParameters[] = [$part, $direction];
}
}
$bag->set('sort', $sortParameters);
return $bag;
// return $this->getSortParameters($bag);
}
/**
@@ -283,8 +232,6 @@ abstract class Controller extends BaseController
$baseUrl = sprintf('%s/api/v1', request()->getSchemeAndHttpHost());
$manager->setSerializer(new JsonApiSerializer($baseUrl));
// $transformer->collectMetaData(new Collection([$object]));
$resource = new Item($object, $transformer, $key);
return $manager->createData($resource)->toArray();

View File

@@ -76,7 +76,7 @@ class BudgetController extends Controller
/** @var Budget $budget */
foreach ($budgets as $budget) {
$expenses = $this->opsRepository->sumExpenses($start, $end, $assetAccounts, new Collection([$budget]));
$expenses = $this->opsRepository->sumExpenses($start, $end, $assetAccounts, new Collection()->push($budget));
/** @var array $expense */
foreach ($expenses as $expense) {

View File

@@ -76,7 +76,7 @@ class CategoryController extends Controller
/** @var Category $category */
foreach ($categories as $category) {
$expenses = $this->opsRepository->sumExpenses($start, $end, $assetAccounts, new Collection([$category]));
$expenses = $this->opsRepository->sumExpenses($start, $end, $assetAccounts, new Collection()->push($category));
/** @var array $expense */
foreach ($expenses as $expense) {

View File

@@ -76,7 +76,7 @@ class CategoryController extends Controller
/** @var Category $category */
foreach ($categories as $category) {
$expenses = $this->opsRepository->sumIncome($start, $end, $assetAccounts, new Collection([$category]));
$expenses = $this->opsRepository->sumIncome($start, $end, $assetAccounts, new Collection()->push($category));
/** @var array $expense */
foreach ($expenses as $expense) {

View File

@@ -29,6 +29,7 @@ use FireflyIII\Api\V1\Requests\Insight\GenericRequest;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Facades\Steam;
use Illuminate\Http\JsonResponse;
/**
@@ -71,7 +72,7 @@ class PeriodController extends Controller
'currency_id' => (string) $currencyId,
'currency_code' => $currencyCode,
];
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], (string) app('steam')->positive($journal[$field]));
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], Steam::positive($journal[$field]));
$response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; // float but on purpose.
}

View File

@@ -30,6 +30,7 @@ use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Facades\Steam;
use Illuminate\Http\JsonResponse;
/**
@@ -97,7 +98,7 @@ class TagController extends Controller
'currency_id' => (string) $currencyId,
'currency_code' => $currencyCode,
];
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], (string) app('steam')->positive($journal[$field]));
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], Steam::positive($journal[$field]));
$response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference'];
}
@@ -148,7 +149,7 @@ class TagController extends Controller
'currency_id' => (string) $currencyId,
'currency_code' => $journal['currency_code'],
];
$response[$key]['difference'] = bcadd((string) $response[$key]['difference'], (string) app('steam')->positive($journal['amount']));
$response[$key]['difference'] = bcadd((string) $response[$key]['difference'], Steam::positive($journal['amount']));
$response[$key]['difference_float'] = (float) $response[$key]['difference'];
}
@@ -160,10 +161,7 @@ class TagController extends Controller
'currency_id' => (string) $foreignCurrencyId,
'currency_code' => $journal['foreign_currency_code'],
];
$response[$foreignKey]['difference'] = bcadd(
(string) $response[$foreignKey]['difference'],
(string) app('steam')->positive($journal['foreign_amount'])
);
$response[$foreignKey]['difference'] = bcadd((string) $response[$foreignKey]['difference'], Steam::positive($journal['foreign_amount']));
$response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference'];
}
}

View File

@@ -76,7 +76,7 @@ class CategoryController extends Controller
/** @var Category $category */
foreach ($categories as $category) {
$expenses = $this->opsRepository->sumTransfers($start, $end, $assetAccounts, new Collection([$category]));
$expenses = $this->opsRepository->sumTransfers($start, $end, $assetAccounts, new Collection()->push($category));
/** @var array $expense */
foreach ($expenses as $expense) {

View File

@@ -29,6 +29,7 @@ use FireflyIII\Api\V1\Requests\Insight\GenericRequest;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Facades\Steam;
use Illuminate\Http\JsonResponse;
/**
@@ -71,7 +72,7 @@ class PeriodController extends Controller
'currency_id' => (string) $currencyId,
'currency_code' => $currencyCode,
];
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], (string) app('steam')->positive($journal[$field]));
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], Steam::positive($journal[$field]));
$response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference'];
}

View File

@@ -30,6 +30,7 @@ use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Facades\Steam;
use Illuminate\Http\JsonResponse;
/**
@@ -95,7 +96,7 @@ class TagController extends Controller
'currency_id' => (string) $currencyId,
'currency_code' => $currencyCode,
];
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], (string) app('steam')->positive($journal[$field]));
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], Steam::positive($journal[$field]));
$response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference'];
}
@@ -146,7 +147,7 @@ class TagController extends Controller
'currency_id' => (string) $currencyId,
'currency_code' => $journal['currency_code'],
];
$response[$key]['difference'] = bcadd((string) $response[$key]['difference'], (string) app('steam')->positive($journal['amount']));
$response[$key]['difference'] = bcadd((string) $response[$key]['difference'], Steam::positive($journal['amount']));
$response[$key]['difference_float'] = (float) $response[$key]['difference'];
}
@@ -160,7 +161,7 @@ class TagController extends Controller
];
$response[$foreignKey]['difference'] = bcadd(
(string) $response[$foreignKey]['difference'],
(string) app('steam')->positive($journal['foreign_amount'])
Steam::positive($journal['foreign_amount'])
);
$response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference']; // intentional float
}

View File

@@ -152,7 +152,7 @@ class ListController extends Controller
// use new group collector:
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setUser($admin)->setAccounts(new Collection([$account]))
$collector->setUser($admin)->setAccounts(new Collection()->push($account))
->withAPIInformation()->setLimit($pageSize)->setPage($this->parameters->get('page'))->setTypes($types)
;

View File

@@ -25,6 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Models\Account;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Models\Account\ShowRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
@@ -33,7 +34,6 @@ use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
use FireflyIII\Transformers\AccountTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Resource\Collection as FractalCollection;
@@ -71,34 +71,38 @@ class ShowController extends Controller
*
* @throws FireflyException
*/
public function index(Request $request): JsonResponse
public function index(ShowRequest $request): JsonResponse
{
$manager = $this->getManager();
$type = $request->get('type') ?? 'all';
$this->parameters->set('type', $type);
$params = $request->getParameters();
$this->parameters->set('type', $params['type']);
// types to get, page size:
$types = $this->mapAccountTypes($this->parameters->get('type'));
$pageSize = $this->parameters->get('limit');
$types = $this->mapAccountTypes($params['type']);
// get list of accounts. Count it and split it.
$this->repository->resetAccountOrder();
$collection = $this->repository->getAccountsByType($types, $this->parameters->get('sort') ?? []);
$collection = $this->repository->getAccountsByType($types, $params['sort']);
$count = $collection->count();
// continue sort:
$accounts = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// TODO if the user sorts on DB dependent field there must be no slice before enrichment, only after.
// TODO still need to figure out how to do this easily.
$accounts = $collection->slice(($this->parameters->get('page') - 1) * $params['limit'], $params['limit']);
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new AccountEnrichment();
$enrichment->setSort($params['sort']);
$enrichment->setDate($this->parameters->get('date'));
$enrichment->setStart($this->parameters->get('start'));
$enrichment->setEnd($this->parameters->get('end'));
$enrichment->setUser($admin);
$accounts = $enrichment->enrich($accounts);
// make paginator:
$paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page'));
$paginator = new LengthAwarePaginator($accounts, $count, $params['limit'], $this->parameters->get('page'));
$paginator->setPath(route('api.v1.accounts.index').$this->buildParams());
/** @var AccountTransformer $transformer */
@@ -117,7 +121,7 @@ class ShowController extends Controller
*
* Show single instance.
*/
public function show(Account $account): JsonResponse
public function show(ShowRequest $request, Account $account): JsonResponse
{
// get list of accounts. Count it and split it.
$this->repository->resetAccountOrder();
@@ -129,6 +133,8 @@ class ShowController extends Controller
$admin = auth()->user();
$enrichment = new AccountEnrichment();
$enrichment->setDate($this->parameters->get('date'));
$enrichment->setStart($this->parameters->get('start'));
$enrichment->setEnd($this->parameters->get('end'));
$enrichment->setUser($admin);
$account = $enrichment->enrichSingle($account);

View File

@@ -114,8 +114,8 @@ class ShowController extends Controller
public function show(AvailableBudget $availableBudget): JsonResponse
{
$manager = $this->getManager();
$start = $this->parameters->get('start');
$end = $this->parameters->get('end');
// $start = $this->parameters->get('start');
// $end = $this->parameters->get('end');
/** @var AvailableBudgetTransformer $transformer */
$transformer = app(AvailableBudgetTransformer::class);
@@ -126,8 +126,8 @@ class ShowController extends Controller
$admin = auth()->user();
$enrichment = new AvailableBudgetEnrichment();
$enrichment->setUser($admin);
$enrichment->setStart($start);
$enrichment->setEnd($end);
// $enrichment->setStart($start);
// $enrichment->setEnd($end);
$availableBudget = $enrichment->enrichSingle($availableBudget);

View File

@@ -67,7 +67,9 @@ class StoreController extends Controller
*/
public function store(StoreRequest $request): JsonResponse
{
$budget = $this->repository->store($request->getAll());
$data = $request->getAll();
$data['fire_webhooks'] ??= true;
$budget = $this->repository->store($data);
$budget->refresh();
$manager = $this->getManager();

View File

@@ -57,15 +57,10 @@ class UpdateController extends Controller
);
}
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/budgets/updateBudget
*
* Update a budget.
*/
public function update(UpdateRequest $request, Budget $budget): JsonResponse
{
$data = $request->getAll();
$data['fire_webhooks'] ??= true;
$budget = $this->repository->update($budget, $data);
$manager = $this->getManager();

View File

@@ -84,6 +84,8 @@ class ShowController extends Controller
$enrichment->setUser($admin);
$enrichment->setStart($this->parameters->get('start'));
$enrichment->setEnd($this->parameters->get('end'));
/** @var Budget $budget */
$budget = $enrichment->enrichSingle($budget);
@@ -96,7 +98,6 @@ class ShowController extends Controller
$paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.budgets.limits.index', [$budget->id]).$this->buildParams());
// enrich
$enrichment = new BudgetLimitEnrichment();
$enrichment->setUser($admin);

View File

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

View File

@@ -77,6 +77,7 @@ class UpdateController extends Controller
throw new FireflyException('20028: The budget limit does not belong to the budget.');
}
$data = $request->getAll();
$data['fire_webhooks'] ??= true;
$data['budget_id'] = $budget->id;
$budgetLimit = $this->blRepository->update($budgetLimit, $data);
$manager = $this->getManager();
@@ -86,7 +87,7 @@ class UpdateController extends Controller
$admin = auth()->user();
$enrichment = new BudgetLimitEnrichment();
$enrichment->setUser($admin);
$budgetLimit = $enrichment->enrich($budgetLimit);
$budgetLimit = $enrichment->enrichSingle($budgetLimit);
/** @var BudgetLimitTransformer $transformer */
$transformer = app(BudgetLimitTransformer::class);

View File

@@ -72,7 +72,7 @@ class DestroyController extends Controller
public function destroySingleByDate(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): JsonResponse
{
$exchangeRate = $this->repository->getSpecificRateOnDate($from, $to, $date);
if (null !== $exchangeRate) {
if ($exchangeRate instanceof CurrencyExchangeRate) {
$this->repository->deleteRate($exchangeRate);
}

View File

@@ -95,7 +95,7 @@ class ShowController extends Controller
$transformer->setParameters($this->parameters);
$exchangeRate = $this->repository->getSpecificRateOnDate($from, $to, $date);
if (null === $exchangeRate) {
if (!$exchangeRate instanceof CurrencyExchangeRate) {
throw new NotFoundHttpException();
}

View File

@@ -33,6 +33,7 @@ use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\CurrencyExchangeRate;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\ExchangeRate\ExchangeRateRepositoryInterface;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Transformers\ExchangeRateTransformer;
use Illuminate\Http\JsonResponse;
@@ -69,7 +70,7 @@ class StoreController extends Controller
foreach ($data as $date => $rate) {
$date = Carbon::createFromFormat('Y-m-d', $date);
$existing = $this->repository->getSpecificRateOnDate($from, $to, $date);
if (null !== $existing) {
if ($existing instanceof CurrencyExchangeRate) {
// update existing rate.
$existing = $this->repository->updateExchangeRate($existing, $rate);
$collection->push($existing);
@@ -98,12 +99,9 @@ class StoreController extends Controller
$from = $request->getFromCurrency();
$collection = new Collection();
foreach ($data['rates'] as $key => $rate) {
$to = TransactionCurrency::where('code', $key)->first();
if (null === $to) {
continue; // should not happen.
}
$to = Amount::getTransactionCurrencyByCode($key);
$existing = $this->repository->getSpecificRateOnDate($from, $to, $date);
if (null !== $existing) {
if ($existing instanceof CurrencyExchangeRate) {
// update existing rate.
$existing = $this->repository->updateExchangeRate($existing, $rate);
$collection->push($existing);

View File

@@ -74,7 +74,7 @@ class UpdateController extends Controller
public function updateByDate(UpdateRequest $request, TransactionCurrency $from, TransactionCurrency $to, Carbon $date): JsonResponse
{
$exchangeRate = $this->repository->getSpecificRateOnDate($from, $to, $date);
if (null === $exchangeRate) {
if (!$exchangeRate instanceof CurrencyExchangeRate) {
throw new NotFoundHttpException();
}
$date = $request->getDate();

View File

@@ -68,10 +68,6 @@ class UpdateController extends Controller
$data = $request->getAll();
$piggyBank = $this->repository->update($piggyBank, $data);
if (array_key_exists('current_amount', $data) && '' !== $data['current_amount']) {
$this->repository->setCurrentAmount($piggyBank, $data['current_amount']);
}
// enrich
/** @var User $admin */
$admin = auth()->user();

View File

@@ -0,0 +1,126 @@
<?php
declare(strict_types=1);
/*
* TriggerController.php
* Copyright (c) 2025 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Api\V1\Controllers\Models\Recurrence;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Generic\SingleDateRequest;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Jobs\CreateRecurringTransactions;
use FireflyIII\Models\Recurrence;
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
use FireflyIII\Transformers\TransactionGroupTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Resource\Collection as FractalCollection;
class TriggerController extends Controller
{
private RecurringRepositoryInterface $repository;
/**
* RecurrenceController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(RecurringRepositoryInterface::class);
$this->repository->setUser(auth()->user());
return $next($request);
}
);
}
public function trigger(SingleDateRequest $request, Recurrence $recurrence): JsonResponse
{
// find recurrence occurrence for this date and trigger it.
// grab the date from the last time the recurrence fired:
$backupDate = $recurrence->latest_date;
$date = $request->getDate();
// fire the recurring cron job on the given date, then post-date the created transaction.
Log::info(sprintf('Trigger: will now fire recurring cron job task for date "%s".', $date->format('Y-m-d H:i:s')));
/** @var CreateRecurringTransactions $job */
$job = app(CreateRecurringTransactions::class);
$job->setRecurrences(new Collection()->push($recurrence));
$job->setDate($date);
$job->setForce(false);
$job->handle();
Log::debug('Done with recurrence.');
$groups = $job->getGroups();
$this->repository->markGroupsAsNow($groups);
$recurrence->latest_date = $backupDate;
$recurrence->latest_date_tz = $backupDate?->format('e');
$recurrence->save();
Preferences::mark();
// enrich groups and return them:
if (0 === $groups->count()) {
$paginator = new LengthAwarePaginator(new Collection(), 0, 1);
}
if ($groups->count() > 0) {
/** @var User $admin */
$admin = auth()->user();
// use new group collector:
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector
->setUser($admin)
->setIds($groups->pluck('id')->toArray())
->withAPIInformation()
;
$paginator = $collector->getPaginatedGroups();
}
$manager = $this->getManager();
$paginator->setPath(route('api.v1.recurrences.trigger', [$recurrence->id]).$this->buildParams());
// enrich
$admin = auth()->user();
$enrichment = new TransactionGroupEnrichment();
$enrichment->setUser($admin);
$transactions = $enrichment->enrich($paginator->getCollection());
/** @var TransactionGroupTransformer $transformer */
$transformer = app(TransactionGroupTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($transactions, $transformer, 'transactions');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
}
}

View File

@@ -75,7 +75,7 @@ class TriggerController extends Controller
/** @var RuleEngineInterface $ruleEngine */
$ruleEngine = app(RuleEngineInterface::class);
$ruleEngine->setRules(new Collection([$rule]));
$ruleEngine->setRules(new Collection()->push($rule));
// overrule the rule(s) if necessary.
if (array_key_exists('start', $parameters) && null !== $parameters['start']) {
@@ -129,7 +129,7 @@ class TriggerController extends Controller
/** @var RuleEngineInterface $ruleEngine */
$ruleEngine = app(RuleEngineInterface::class);
$ruleEngine->setRules(new Collection([$rule]));
$ruleEngine->setRules(new Collection()->push($rule));
// overrule the rule(s) if necessary.
if (array_key_exists('start', $parameters) && null !== $parameters['start']) {

View File

@@ -30,9 +30,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\Account;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Recurrence;
use FireflyIII\Models\RecurrenceTransaction;
use FireflyIII\Models\Rule;
use FireflyIII\Models\RuleTrigger;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
@@ -192,7 +190,7 @@ class ListController extends Controller
$enrichment->setUser($admin);
$enrichment->setStart($this->parameters->get('start'));
$enrichment->setEnd($this->parameters->get('end'));
$bills = $enrichment->enrichSingle($bills);
$bills = $enrichment->enrich($bills);
// make paginator:
$paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page'));
@@ -268,7 +266,6 @@ class ListController extends Controller
// filter selection
$collection = $unfiltered->filter(
static function (Recurrence $recurrence) use ($currency) { // @phpstan-ignore-line
/** @var RecurrenceTransaction $transaction */
if (array_any($recurrence->recurrenceTransactions, fn ($transaction) => $transaction->transaction_currency_id === $currency->id || $transaction->foreign_currency_id === $currency->id)) {
return $recurrence;
}
@@ -320,7 +317,6 @@ class ListController extends Controller
$collection = $unfiltered->filter(
static function (Rule $rule) use ($currency) { // @phpstan-ignore-line
/** @var RuleTrigger $trigger */
if (array_any($rule->ruleTriggers, fn ($trigger) => 'currency_is' === $trigger->trigger_type && $currency->name === $trigger->trigger_value)) {
return $rule;
}

View File

@@ -481,7 +481,7 @@ class BasicController extends Controller
$currencies = [];
// first, create an entry for each entry in the "available" array.
/** @var array $availableBudget */
/** @var string $availableBudget */
foreach ($available as $currencyId => $availableBudget) {
$currencies[$currencyId] ??= $this->currencyRepos->find($currencyId);
$return[$currencyId] = [

View File

@@ -133,7 +133,6 @@ class ConfigurationController extends Controller
*/
public function show(string $configKey): JsonResponse
{
$data = [];
$dynamic = $this->getDynamicConfiguration();
$shortKey = str_replace('configuration.', '', $configKey);
if (str_starts_with($configKey, 'configuration.')) {
@@ -156,13 +155,11 @@ class ConfigurationController extends Controller
}
// fallback
if (!str_starts_with($configKey, 'configuration.')) {
$data = [
'title' => $configKey,
'value' => config($configKey),
'editable' => false,
];
}
$data = [
'title' => $configKey,
'value' => config($shortKey),
'editable' => false,
];
return response()->api(['data' => $data])->header('Content-Type', self::JSON_CONTENT_TYPE);
}

View File

@@ -32,7 +32,9 @@ use FireflyIII\Generator\Webhook\MessageGeneratorInterface;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\Webhook;
use FireflyIII\Repositories\Webhook\WebhookRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\WebhookEnrichment;
use FireflyIII\Transformers\WebhookTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
@@ -90,6 +92,13 @@ class ShowController extends Controller
$paginator = new LengthAwarePaginator($webhooks, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.webhooks.index').$this->buildParams());
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new WebhookEnrichment();
$enrichment->setUser($admin);
$webhooks = $enrichment->enrich($webhooks);
/** @var WebhookTransformer $transformer */
$transformer = app(WebhookTransformer::class);
$transformer->setParameters($this->parameters);
@@ -117,6 +126,13 @@ class ShowController extends Controller
Log::channel('audit')->info(sprintf('User views webhook #%d.', $webhook->id));
$manager = $this->getManager();
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new WebhookEnrichment();
$enrichment->setUser($admin);
$webhook = $enrichment->enrichSingle($webhook);
/** @var WebhookTransformer $transformer */
$transformer = app(WebhookTransformer::class);
$transformer->setParameters($this->parameters);
@@ -142,21 +158,26 @@ class ShowController extends Controller
Log::debug(sprintf('Now in triggerTransaction(%d, %d)', $webhook->id, $group->id));
Log::channel('audit')->info(sprintf('User triggers webhook #%d on transaction group #%d.', $webhook->id, $group->id));
/** @var MessageGeneratorInterface $engine */
$engine = app(MessageGeneratorInterface::class);
$engine->setUser(auth()->user());
// tell the generator which trigger it should look for
$engine->setTrigger(WebhookTrigger::tryFrom($webhook->trigger));
// tell the generator which objects to process
$engine->setObjects(new Collection([$group]));
// set the webhook to trigger
$engine->setWebhooks(new Collection([$webhook]));
// tell the generator to generate the messages
$engine->generateMessages();
/** @var \FireflyIII\Models\WebhookTrigger $trigger */
foreach ($webhook->webhookTriggers as $trigger) {
/** @var MessageGeneratorInterface $engine */
$engine = app(MessageGeneratorInterface::class);
$engine->setUser(auth()->user());
// tell the generator which trigger it should look for
$engine->setTrigger(WebhookTrigger::tryFrom((int)$trigger->key));
// tell the generator which objects to process
$engine->setObjects(new Collection()->push($group));
// set the webhook to trigger
$engine->setWebhooks(new Collection()->push($webhook));
// tell the generator to generate the messages
$engine->generateMessages();
}
// trigger event to send them:
Log::debug('send event RequestedSendWebhookMessages');
Log::debug('send event RequestedSendWebhookMessages from ShowController::triggerTransaction()');
event(new RequestedSendWebhookMessages());
return response()->json([], 204);

View File

@@ -27,7 +27,9 @@ namespace FireflyIII\Api\V1\Controllers\Webhook;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Models\Webhook\CreateRequest;
use FireflyIII\Repositories\Webhook\WebhookRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\WebhookEnrichment;
use FireflyIII\Transformers\WebhookTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
use League\Fractal\Resource\Item;
@@ -68,6 +70,15 @@ class StoreController extends Controller
}
$webhook = $this->repository->store($data);
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new WebhookEnrichment();
$enrichment->setUser($admin);
$webhook = $enrichment->enrichSingle($webhook);
$manager = $this->getManager();
Log::channel('audit')->info('User stores new webhook', $data);

View File

@@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Models\Webhook\UpdateRequest;
use FireflyIII\Models\Webhook;
use FireflyIII\Repositories\Webhook\WebhookRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\WebhookEnrichment;
use FireflyIII\Transformers\WebhookTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
use League\Fractal\Resource\Item;
@@ -70,6 +72,15 @@ class UpdateController extends Controller
$webhook = $this->repository->update($webhook, $data);
$manager = $this->getManager();
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new WebhookEnrichment();
$enrichment->setUser($admin);
/** @var Webhook $webhook */
$webhook = $enrichment->enrichSingle($webhook);
Log::channel('audit')->info(sprintf('User updates webhook #%d', $webhook->id), $data);
/** @var WebhookTransformer $transformer */

View File

@@ -24,7 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Chart;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Validation\Validator;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Support\Request\ChecksLogin;
@@ -64,6 +64,7 @@ class ChartRequest extends FormRequest
'end' => 'required|date|after:1970-01-02|before:2038-01-17|after_or_equal:start',
'preselected' => sprintf('nullable|in:%s', implode(',', config('firefly.preselected_accounts'))),
'period' => sprintf('nullable|in:%s', implode(',', config('firefly.valid_view_ranges'))),
'accounts' => 'nullable|array',
'accounts.*' => 'exists:accounts,id',
];

View File

@@ -24,7 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Data\Bulk;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Validation\Validator;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;

View File

@@ -24,7 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Data\Bulk;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Validation\Validator;
use JsonException;
use FireflyIII\Enums\ClauseType;
use FireflyIII\Rules\IsValidBulkClause;

View File

@@ -0,0 +1,99 @@
<?php
declare(strict_types=1);
/*
* ShowRequest.php
* Copyright (c) 2025 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Api\V1\Requests\Models\Account;
use Illuminate\Validation\Validator;
use Carbon\Carbon;
use FireflyIII\Models\Account;
use FireflyIII\Rules\IsValidSortInstruction;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\User;
use Illuminate\Foundation\Http\FormRequest;
class ShowRequest extends FormRequest
{
use AccountFilter;
use ConvertsDataTypes;
public function getParameters(): array
{
$limit = $this->convertInteger('limit');
if (0 === $limit) {
// get default for user:
/** @var User $user */
$user = auth()->user();
$limit = (int)Preferences::getForUser($user, 'listPageSize', 50)->data;
}
$page = $this->convertInteger('page');
$page = min(max(1, $page), 2 ** 16);
return [
'type' => $this->convertString('type', 'all'),
'limit' => $limit,
'sort' => $this->convertSortParameters('sort', Account::class),
'page' => $page,
];
}
public function rules(): array
{
$keys = implode(',', array_keys($this->types));
return [
'date' => 'date',
'start' => 'date|present_with:end|before_or_equal:end|before:2038-01-17|after:1970-01-02',
'end' => 'date|present_with:start|after_or_equal:start|before:2038-01-17|after:1970-01-02',
'sort' => ['nullable', new IsValidSortInstruction(Account::class)],
'type' => sprintf('in:%s', $keys),
'limit' => 'numeric|min:1|max:131337',
'page' => 'numeric|min:1|max:131337',
];
}
public function withValidator(Validator $validator): void
{
$validator->after(
function (Validator $validator): void {
if (count($validator->failed()) > 0) {
return;
}
$data = $validator->getData();
if (array_key_exists('date', $data) && array_key_exists('start', $data) && array_key_exists('end', $data)) {
// assume valid dates, before we got here.
$start = Carbon::parse($data['start'], config('app.timezone'))->startOfDay();
$end = Carbon::parse($data['end'], config('app.timezone'))->endOfDay();
$date = Carbon::parse($data['date'], config('app.timezone'));
if (!$date->between($start, $end)) {
$validator->errors()->add('date', (string)trans('validation.between_date'));
}
}
}
);
}
}

View File

@@ -24,7 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Models\Account;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Validation\Validator;
use FireflyIII\Models\Account;
use FireflyIII\Models\Location;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;

View File

@@ -24,7 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Models\AvailableBudget;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Validation\Validator;
use Carbon\Carbon;
use FireflyIII\Rules\IsValidPositiveAmount;
use FireflyIII\Support\Request\ChecksLogin;

View File

@@ -24,7 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Models\Bill;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Validation\Validator;
use ValueError;
use TypeError;
use FireflyIII\Rules\IsBoolean;

View File

@@ -24,7 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Models\Bill;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Validation\Validator;
use FireflyIII\Models\Bill;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Rules\IsValidPositiveAmount;

View File

@@ -24,7 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Models\Budget;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Validation\Validator;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Rules\IsValidPositiveAmount;
use FireflyIII\Support\Request\ChecksLogin;
@@ -48,17 +48,20 @@ class StoreRequest extends FormRequest
public function getAll(): array
{
$fields = [
'name' => ['name', 'convertString'],
'active' => ['active', 'boolean'],
'order' => ['active', 'convertInteger'],
'notes' => ['notes', 'convertString'],
'name' => ['name', 'convertString'],
'active' => ['active', 'boolean'],
'order' => ['active', 'convertInteger'],
'notes' => ['notes', 'convertString'],
// auto budget currency:
'currency_id' => ['auto_budget_currency_id', 'convertInteger'],
'currency_code' => ['auto_budget_currency_code', 'convertString'],
'auto_budget_type' => ['auto_budget_type', 'convertString'],
'auto_budget_amount' => ['auto_budget_amount', 'convertString'],
'auto_budget_period' => ['auto_budget_period', 'convertString'],
'currency_id' => ['auto_budget_currency_id', 'convertInteger'],
'currency_code' => ['auto_budget_currency_code', 'convertString'],
'auto_budget_type' => ['auto_budget_type', 'convertString'],
'auto_budget_amount' => ['auto_budget_amount', 'convertString'],
'auto_budget_period' => ['auto_budget_period', 'convertString'],
// webhooks
'fire_webhooks' => ['fire_webhooks', 'boolean'],
];
return $this->getAllData($fields);
@@ -70,15 +73,18 @@ class StoreRequest extends FormRequest
public function rules(): array
{
return [
'name' => 'required|min:1|max:255|uniqueObjectForUser:budgets,name',
'active' => [new IsBoolean()],
'currency_id' => 'exists:transaction_currencies,id',
'currency_code' => 'exists:transaction_currencies,code',
'notes' => 'nullable|min:1|max:32768',
'name' => 'required|min:1|max:255|uniqueObjectForUser:budgets,name',
'active' => [new IsBoolean()],
'currency_id' => 'exists:transaction_currencies,id',
'currency_code' => 'exists:transaction_currencies,code',
'notes' => 'nullable|min:1|max:32768',
// auto budget info
'auto_budget_type' => 'in:reset,rollover,adjusted,none',
'auto_budget_amount' => ['required_if:auto_budget_type,reset', 'required_if:auto_budget_type,rollover', 'required_if:auto_budget_type,adjusted', new IsValidPositiveAmount()],
'auto_budget_period' => 'in:daily,weekly,monthly,quarterly,half_year,yearly|required_if:auto_budget_type,reset|required_if:auto_budget_type,rollover|required_if:auto_budget_type,adjusted',
'auto_budget_type' => 'in:reset,rollover,adjusted,none',
'auto_budget_amount' => ['required_if:auto_budget_type,reset', 'required_if:auto_budget_type,rollover', 'required_if:auto_budget_type,adjusted', new IsValidPositiveAmount()],
'auto_budget_period' => 'in:daily,weekly,monthly,quarterly,half_year,yearly|required_if:auto_budget_type,reset|required_if:auto_budget_type,rollover|required_if:auto_budget_type,adjusted',
// webhooks
'fire_webhooks' => [new IsBoolean()],
];
}

View File

@@ -24,7 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Models\Budget;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Validation\Validator;
use FireflyIII\Models\Budget;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Rules\IsValidPositiveAmount;
@@ -50,15 +50,18 @@ class UpdateRequest extends FormRequest
{
// this is the way:
$fields = [
'name' => ['name', 'convertString'],
'active' => ['active', 'boolean'],
'order' => ['order', 'convertInteger'],
'notes' => ['notes', 'convertString'],
'currency_id' => ['auto_budget_currency_id', 'convertInteger'],
'currency_code' => ['auto_budget_currency_code', 'convertString'],
'auto_budget_type' => ['auto_budget_type', 'convertString'],
'auto_budget_amount' => ['auto_budget_amount', 'convertString'],
'auto_budget_period' => ['auto_budget_period', 'convertString'],
'name' => ['name', 'convertString'],
'active' => ['active', 'boolean'],
'order' => ['order', 'convertInteger'],
'notes' => ['notes', 'convertString'],
'currency_id' => ['auto_budget_currency_id', 'convertInteger'],
'currency_code' => ['auto_budget_currency_code', 'convertString'],
'auto_budget_type' => ['auto_budget_type', 'convertString'],
'auto_budget_amount' => ['auto_budget_amount', 'convertString'],
'auto_budget_period' => ['auto_budget_period', 'convertString'],
// webhooks
'fire_webhooks' => ['fire_webhooks', 'boolean'],
];
$allData = $this->getAllData($fields);
if (array_key_exists('auto_budget_type', $allData)) {
@@ -83,14 +86,17 @@ class UpdateRequest extends FormRequest
$budget = $this->route()->parameter('budget');
return [
'name' => sprintf('min:1|max:100|uniqueObjectForUser:budgets,name,%d', $budget->id),
'active' => [new IsBoolean()],
'notes' => 'nullable|min:1|max:32768',
'auto_budget_type' => 'in:reset,rollover,adjusted,none',
'auto_budget_currency_id' => 'exists:transaction_currencies,id',
'auto_budget_currency_code' => 'exists:transaction_currencies,code',
'auto_budget_amount' => ['nullable', new IsValidPositiveAmount()],
'auto_budget_period' => 'in:daily,weekly,monthly,quarterly,half_year,yearly',
'name' => sprintf('min:1|max:100|uniqueObjectForUser:budgets,name,%d', $budget->id),
'active' => [new IsBoolean()],
'notes' => 'nullable|min:1|max:32768',
'auto_budget_type' => 'in:reset,rollover,adjusted,none',
'auto_budget_currency_id' => 'exists:transaction_currencies,id',
'auto_budget_currency_code' => 'exists:transaction_currencies,code',
'auto_budget_amount' => ['nullable', new IsValidPositiveAmount()],
'auto_budget_period' => 'in:daily,weekly,monthly,quarterly,half_year,yearly',
// webhooks
'fire_webhooks' => [new IsBoolean()],
];
}

View File

@@ -24,10 +24,16 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Models\BudgetLimit;
use Carbon\Carbon;
use FireflyIII\Factory\TransactionCurrencyFactory;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Rules\IsValidPositiveAmount;
use FireflyIII\Support\Facades\Amount;
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
@@ -49,6 +55,9 @@ class StoreRequest extends FormRequest
'currency_id' => $this->convertInteger('currency_id'),
'currency_code' => $this->convertString('currency_code'),
'notes' => $this->stringWithNewlines('notes'),
// for webhooks:
'fire_webhooks' => $this->boolean('fire_webhooks', true),
];
}
@@ -58,12 +67,59 @@ class StoreRequest extends FormRequest
public function rules(): array
{
return [
'start' => 'required|before:end|date',
'end' => 'required|after:start|date',
'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',
'start' => 'required|before:end|date',
'end' => 'required|after:start|date',
'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',
// webhooks
'fire_webhooks' => [new IsBoolean()],
];
}
/**
* Configure the validator instance.
*/
public function withValidator(Validator $validator): void
{
$budget = $this->route()->parameter('budget');
$validator->after(
static function (Validator $validator) use ($budget): void {
if (0 !== count($validator->failed())) {
return;
}
$data = $validator->getData();
// if no currency has been provided, use the user's default currency:
/** @var TransactionCurrencyFactory $factory */
$factory = app(TransactionCurrencyFactory::class);
$currency = $factory->find($data['currency_id'] ?? null, $data['currency_code'] ?? null);
if (null === $currency) {
$currency = Amount::getPrimaryCurrency();
}
$currency->enabled = true;
$currency->save();
// validator already concluded start and end are valid dates:
$start = Carbon::parse($data['start'], config('app.timezone'));
$end = Carbon::parse($data['end'], config('app.timezone'));
// find limit with same date range and currency.
$limit = $budget->budgetlimits()
->where('budget_limits.start_date', $start->format('Y-m-d'))
->where('budget_limits.end_date', $end->format('Y-m-d'))
->where('budget_limits.transaction_currency_id', $currency->id)
->first(['budget_limits.*'])
;
if (null !== $limit) {
$validator->errors()->add('start', trans('validation.limit_exists'));
}
}
);
if ($validator->fails()) {
Log::channel('audit')->error(sprintf('Validation errors in %s', self::class), $validator->errors()->toArray());
}
}
}

View File

@@ -24,7 +24,8 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Models\BudgetLimit;
use Illuminate\Contracts\Validation\Validator;
use FireflyIII\Rules\IsBoolean;
use Illuminate\Validation\Validator;
use Carbon\Carbon;
use FireflyIII\Rules\IsValidPositiveAmount;
use FireflyIII\Support\Request\ChecksLogin;
@@ -46,12 +47,15 @@ class UpdateRequest extends FormRequest
public function getAll(): array
{
$fields = [
'start' => ['start', 'date'],
'end' => ['end', 'date'],
'amount' => ['amount', 'convertString'],
'currency_id' => ['currency_id', 'convertInteger'],
'currency_code' => ['currency_code', 'convertString'],
'notes' => ['notes', 'stringWithNewlines'],
'start' => ['start', 'date'],
'end' => ['end', 'date'],
'amount' => ['amount', 'convertString'],
'currency_id' => ['currency_id', 'convertInteger'],
'currency_code' => ['currency_code', 'convertString'],
'notes' => ['notes', 'stringWithNewlines'],
// webhooks
'fire_webhooks' => ['fire_webhooks', 'boolean'],
];
if (false === $this->has('notes')) {
// ignore notes, not submitted.
@@ -67,12 +71,15 @@ class UpdateRequest extends FormRequest
public function rules(): array
{
return [
'start' => 'date|after:1970-01-02|before:2038-01-17',
'end' => 'date|after:1970-01-02|before:2038-01-17',
'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',
'start' => 'date|after:1970-01-02|before:2038-01-17',
'end' => 'date|after:1970-01-02|before:2038-01-17',
'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',
// webhooks
'fire_webhooks' => [new IsBoolean()],
];
}

View File

@@ -28,7 +28,7 @@ use Carbon\Carbon;
use Carbon\Exceptions\InvalidFormatException;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
class StoreByCurrenciesRequest extends FormRequest
@@ -55,11 +55,11 @@ class StoreByCurrenciesRequest extends FormRequest
{
$validator->after(
static function (Validator $validator): void {
$data = $validator->getData() ?? [];
$data = $validator->getData();
foreach ($data as $date => $rate) {
try {
$date = Carbon::createFromFormat('Y-m-d', $date);
} catch (InvalidFormatException $e) {
Carbon::createFromFormat('Y-m-d', $date);
} catch (InvalidFormatException) {
$validator->errors()->add('date', trans('validation.date', ['attribute' => 'date']));
return;

View File

@@ -24,10 +24,12 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Models\CurrencyExchangeRate;
use Illuminate\Validation\Validator;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
class StoreByDateRequest extends FormRequest
@@ -35,6 +37,9 @@ class StoreByDateRequest extends FormRequest
use ChecksLogin;
use ConvertsDataTypes;
/**
* @return array<string, mixed>
*/
public function getAll(): array
{
return [
@@ -45,11 +50,13 @@ class StoreByDateRequest extends FormRequest
public function getFromCurrency(): TransactionCurrency
{
return TransactionCurrency::where('code', $this->get('from'))->first();
return Amount::getTransactionCurrencyByCode((string)$this->get('from'));
}
/**
* The rules that the incoming request must be matched against.
*
* @return array<string, string>
*/
public function rules(): array
{
@@ -79,8 +86,10 @@ class StoreByDateRequest extends FormRequest
continue;
}
$to = TransactionCurrency::where('code', $key)->first();
if (null === $to) {
try {
Amount::getTransactionCurrencyByCode((string)$key);
} catch (FireflyException) {
$validator->errors()->add(sprintf('rates.%s', $key), trans('validation.invalid_currency_code', ['code' => $key]));
}
}

View File

@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Requests\Models\CurrencyExchangeRate;
use Carbon\Carbon;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
@@ -42,7 +43,7 @@ class StoreRequest extends FormRequest
public function getFromCurrency(): TransactionCurrency
{
return TransactionCurrency::where('code', $this->get('from'))->first();
return Amount::getTransactionCurrencyByCode((string) $this->get('from'));
}
public function getRate(): string
@@ -52,7 +53,7 @@ class StoreRequest extends FormRequest
public function getToCurrency(): TransactionCurrency
{
return TransactionCurrency::where('code', $this->get('to'))->first();
return Amount::getTransactionCurrencyByCode((string) $this->get('to'));
}
/**

View File

@@ -24,7 +24,8 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Models\PiggyBank;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Validation\Validator;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Rules\IsValidZeroOrMoreAmount;
@@ -78,7 +79,7 @@ class StoreRequest extends FormRequest
'object_group_id' => 'numeric|belongsToUser:object_groups,id',
'object_group_title' => ['min:1', 'max:255'],
'target_amount' => ['required', new IsValidZeroOrMoreAmount()],
'start_date' => 'date|nullable',
'start_date' => 'required|date|after:1970-01-01|before:2038-01-17',
'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',
@@ -96,7 +97,7 @@ class StoreRequest extends FormRequest
// validate start before end only if both are there.
$data = $validator->getData();
$currency = $this->getCurrencyFromData($validator, $data);
if (null === $currency) {
if (!$currency instanceof TransactionCurrency) {
return;
}
$targetAmount = (string) ($data['target_amount'] ?? '0');
@@ -135,16 +136,10 @@ class StoreRequest extends FormRequest
private function getCurrencyFromData(Validator $validator, 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;
}
return Amount::getTransactionCurrencyByCode((string) $data['transaction_currency_code']);
}
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;
}
return Amount::getTransactionCurrencyById((int) $data['transaction_currency_id']);
}
$validator->errors()->add('transaction_currency_id', trans('validation.require_currency_id_code'));

View File

@@ -24,7 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Models\Recurrence;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Validation\Validator;
use FireflyIII\Rules\BelongsUser;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Rules\IsValidPositiveAmount;

View File

@@ -24,7 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Models\Recurrence;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Validation\Validator;
use FireflyIII\Models\Recurrence;
use FireflyIII\Rules\BelongsUser;
use FireflyIII\Rules\IsBoolean;

View File

@@ -24,7 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Models\Rule;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Validation\Validator;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Rules\IsValidActionExpression;
use FireflyIII\Support\Request\ChecksLogin;

View File

@@ -24,7 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Models\Rule;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Validation\Validator;
use FireflyIII\Models\Rule;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Rules\IsValidActionExpression;

View File

@@ -24,7 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Models\Transaction;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Validation\Validator;
use FireflyIII\Models\Location;
use FireflyIII\Rules\BelongsUser;
use FireflyIII\Rules\IsBoolean;
@@ -183,6 +183,7 @@ class StoreRequest extends FormRequest
// basic fields for group:
'group_title' => 'min:1|max:1000|nullable',
'error_if_duplicate_hash' => [new IsBoolean()],
'fire_webhooks' => [new IsBoolean()],
'apply_rules' => [new IsBoolean()],
// location rules

View File

@@ -24,7 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Models\Transaction;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Validation\Validator;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Rules\BelongsUser;
@@ -64,7 +64,7 @@ class UpdateRequest extends FormRequest
*/
public function getAll(): array
{
app('log')->debug(sprintf('Now in %s', __METHOD__));
Log::debug(sprintf('Now in %s', __METHOD__));
$this->integerFields = ['order', 'currency_id', 'foreign_currency_id', 'transaction_journal_id', 'source_id', 'destination_id', 'budget_id', 'category_id', 'bill_id', 'recurrence_id'];
$this->dateFields = ['date', 'interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date'];
$this->textareaFields = ['notes'];
@@ -97,7 +97,7 @@ class UpdateRequest extends FormRequest
*/
private function getTransactionData(): array
{
app('log')->debug(sprintf('Now in %s', __METHOD__));
Log::debug(sprintf('Now in %s', __METHOD__));
$return = [];
/** @var null|array $transactions */
@@ -181,7 +181,7 @@ class UpdateRequest extends FormRequest
private function getDateData(array $current, array $transaction): array
{
foreach ($this->dateFields as $fieldName) {
app('log')->debug(sprintf('Now at date field %s', $fieldName));
Log::debug(sprintf('Now at date field %s', $fieldName));
if (array_key_exists($fieldName, $transaction)) {
Log::debug(sprintf('New value: "%s"', $transaction[$fieldName]));
$current[$fieldName] = $this->dateFromValue((string) $transaction[$fieldName]);
@@ -247,7 +247,7 @@ class UpdateRequest extends FormRequest
*/
public function rules(): array
{
app('log')->debug(sprintf('Now in %s', __METHOD__));
Log::debug(sprintf('Now in %s', __METHOD__));
$validProtocols = config('firefly.valid_url_protocols');
return [
@@ -330,7 +330,7 @@ class UpdateRequest extends FormRequest
*/
public function withValidator(Validator $validator): void
{
app('log')->debug('Now in withValidator');
Log::debug('Now in withValidator');
/** @var TransactionGroup $transactionGroup */
$transactionGroup = $this->route()->parameter('transactionGroup');

View File

@@ -24,7 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Models\TransactionLink;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Validation\Validator;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
use FireflyIII\Support\Request\ChecksLogin;

View File

@@ -24,7 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Models\TransactionLink;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Validation\Validator;
use FireflyIII\Models\TransactionJournalLink;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;

View File

@@ -24,15 +24,13 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Models\Webhook;
use FireflyIII\Enums\WebhookResponse;
use FireflyIII\Enums\WebhookTrigger;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Webhook;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Contracts\Validation\Validator;
use FireflyIII\Support\Request\ValidatesWebhooks;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Log;
/**
* Class CreateRequest
@@ -41,27 +39,28 @@ class CreateRequest extends FormRequest
{
use ChecksLogin;
use ConvertsDataTypes;
use ValidatesWebhooks;
public function getData(): array
{
$triggers = Webhook::getTriggersForValidation();
$responses = Webhook::getResponsesForValidation();
$deliveries = Webhook::getDeliveriesForValidation();
$fields = [
'title' => ['title', 'convertString'],
'active' => ['active', 'boolean'],
'trigger' => ['trigger', 'convertString'],
'response' => ['response', 'convertString'],
'delivery' => ['delivery', 'convertString'],
'url' => ['url', 'convertString'],
$fields = [
'title' => ['title', 'convertString'],
'active' => ['active', 'boolean'],
'url' => ['url', 'convertString'],
];
$triggers = $this->get('triggers', []);
$responses = $this->get('responses', []);
$deliveries = $this->get('deliveries', []);
// this is the way.
$return = $this->getAllData($fields);
$return['trigger'] = $triggers[$return['trigger']] ?? (int)$return['trigger'];
$return['response'] = $responses[$return['response']] ?? (int)$return['response'];
$return['delivery'] = $deliveries[$return['delivery']] ?? (int)$return['delivery'];
if (0 === count($triggers) || 0 === count($responses) || 0 === count($deliveries)) {
throw new FireflyException('Unexpectedly got no responses, triggers or deliveries.');
}
$return = $this->getAllData($fields);
$return['triggers'] = $triggers;
$return['responses'] = $responses;
$return['deliveries'] = $deliveries;
return $return;
}
@@ -71,59 +70,24 @@ class CreateRequest extends FormRequest
*/
public function rules(): array
{
$triggers = implode(',', array_keys(Webhook::getTriggersForValidation()));
$responses = implode(',', array_keys(Webhook::getResponsesForValidation()));
$deliveries = implode(',', array_keys(Webhook::getDeliveriesForValidation()));
$triggers = implode(',', array_values(Webhook::getTriggers()));
$responses = implode(',', array_values(Webhook::getResponses()));
$deliveries = implode(',', array_values(Webhook::getDeliveries()));
$validProtocols = config('firefly.valid_url_protocols');
return [
'title' => 'required|min:1|max:255|uniqueObjectForUser:webhooks,title',
'active' => [new IsBoolean()],
'trigger' => sprintf('required|in:%s', $triggers),
'response' => sprintf('required|in:%s', $responses),
'delivery' => sprintf('required|in:%s', $deliveries),
'url' => ['required', sprintf('url:%s', $validProtocols), 'uniqueWebhook'],
'title' => 'required|min:1|max:255|uniqueObjectForUser:webhooks,title',
'active' => [new IsBoolean()],
'trigger' => 'prohibited',
'triggers' => 'required|array|min:1|max:10',
'triggers.*' => sprintf('required|in:%s', $triggers),
'response' => 'prohibited',
'responses' => 'required|array|min:1|max:1',
'responses.*' => sprintf('required|in:%s', $responses),
'delivery' => 'prohibited',
'deliveries' => 'required|array|min:1|max:1',
'deliveries.*' => sprintf('required|in:%s', $deliveries),
'url' => ['required', sprintf('url:%s', $validProtocols)],
];
}
public function withValidator(Validator $validator): void
{
$validator->after(
function (Validator $validator): void {
Log::debug('Validating webhook');
$data = $validator->getData();
$trigger = $data['trigger'] ?? null;
$response = $data['response'] ?? null;
if (null === $trigger || null === $response) {
Log::debug('No trigger or response, return.');
return;
}
$triggers = array_keys(Webhook::getTriggersForValidation());
$responses = array_keys(Webhook::getResponsesForValidation());
if (!in_array($trigger, $triggers, true) || !in_array($response, $responses, true)) {
return;
}
// cannot deliver budget info.
if (is_int($trigger)) {
Log::debug(sprintf('Trigger was integer (%d).', $trigger));
$trigger = WebhookTrigger::from($trigger)->name;
}
if (is_int($response)) {
Log::debug(sprintf('Response was integer (%d).', $response));
$response = WebhookResponse::from($response)->name;
}
Log::debug(sprintf('Trigger is %s, response is %s', $trigger, $response));
if (str_contains($trigger, 'TRANSACTION') && str_contains($response, 'BUDGET')) {
$validator->errors()->add('response', trans('validation.webhook_budget_info'));
}
if (str_contains($trigger, 'BUDGET') && str_contains($response, 'ACCOUNT')) {
$validator->errors()->add('response', trans('validation.webhook_account_info'));
}
if (str_contains($trigger, 'BUDGET') && str_contains($response, 'TRANSACTION')) {
$validator->errors()->add('response', trans('validation.webhook_transaction_info'));
}
}
);
}
}

View File

@@ -24,15 +24,13 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Models\Webhook;
use FireflyIII\Enums\WebhookResponse;
use FireflyIII\Enums\WebhookTrigger;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Webhook;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Contracts\Validation\Validator;
use FireflyIII\Support\Request\ValidatesWebhooks;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Log;
/**
* Class UpdateRequest
@@ -41,38 +39,29 @@ class UpdateRequest extends FormRequest
{
use ChecksLogin;
use ConvertsDataTypes;
use ValidatesWebhooks;
public function getData(): array
{
$triggers = Webhook::getTriggersForValidation();
$responses = Webhook::getResponsesForValidation();
$deliveries = Webhook::getDeliveriesForValidation();
$fields = [
$fields = [
'title' => ['title', 'convertString'],
'active' => ['active', 'boolean'],
'trigger' => ['trigger', 'convertString'],
'response' => ['response', 'convertString'],
'delivery' => ['delivery', 'convertString'],
'url' => ['url', 'convertString'],
];
// this is the way.
$return = $this->getAllData($fields);
if (array_key_exists('trigger', $return)) {
$return['trigger'] = $triggers[$return['trigger']] ?? 0;
}
if (array_key_exists('response', $return)) {
$return['response'] = $responses[$return['response']] ?? 0;
}
if (array_key_exists('delivery', $return)) {
$return['delivery'] = $deliveries[$return['delivery']] ?? 0;
}
$return['secret'] = null !== $this->get('secret');
if (null !== $this->get('title')) {
$return['title'] = $this->convertString('title');
$triggers = $this->get('triggers', []);
$responses = $this->get('responses', []);
$deliveries = $this->get('deliveries', []);
if (0 === count($triggers) || 0 === count($responses) || 0 === count($deliveries)) {
throw new FireflyException('Unexpectedly got no responses, triggers or deliveries.');
}
$return = $this->getAllData($fields);
$return['triggers'] = $triggers;
$return['responses'] = $responses;
$return['deliveries'] = $deliveries;
return $return;
}
@@ -81,62 +70,29 @@ class UpdateRequest extends FormRequest
*/
public function rules(): array
{
$triggers = implode(',', array_keys(Webhook::getTriggersForValidation()));
$responses = implode(',', array_keys(Webhook::getResponsesForValidation()));
$deliveries = implode(',', array_keys(Webhook::getDeliveriesForValidation()));
$triggers = implode(',', array_values(Webhook::getTriggers()));
$responses = implode(',', array_values(Webhook::getResponses()));
$deliveries = implode(',', array_values(Webhook::getDeliveries()));
$validProtocols = config('firefly.valid_url_protocols');
/** @var Webhook $webhook */
$webhook = $this->route()->parameter('webhook');
return [
'title' => sprintf('min:1|max:255|uniqueObjectForUser:webhooks,title,%d', $webhook->id),
'active' => [new IsBoolean()],
'trigger' => sprintf('in:%s', $triggers),
'response' => sprintf('in:%s', $responses),
'delivery' => sprintf('in:%s', $deliveries),
'url' => [sprintf('url:%s', $validProtocols), sprintf('uniqueExistingWebhook:%d', $webhook->id)],
'title' => sprintf('min:1|max:255|uniqueObjectForUser:webhooks,title,%d', $webhook->id),
'active' => [new IsBoolean()],
'trigger' => 'prohibited',
'triggers' => 'required|array|min:1|max:10',
'triggers.*' => sprintf('required|in:%s', $triggers),
'response' => 'prohibited',
'responses' => 'required|array|min:1|max:1',
'responses.*' => sprintf('required|in:%s', $responses),
'delivery' => 'prohibited',
'deliveries' => 'required|array|min:1|max:1',
'deliveries.*' => sprintf('required|in:%s', $deliveries),
'url' => [sprintf('url:%s', $validProtocols), sprintf('uniqueExistingWebhook:%d', $webhook->id)],
];
}
public function withValidator(Validator $validator): void
{
$validator->after(
function (Validator $validator): void {
Log::debug('Validating webhook');
$data = $validator->getData();
$trigger = $data['trigger'] ?? null;
$response = $data['response'] ?? null;
if (null === $trigger || null === $response) {
Log::debug('No trigger or response, return.');
return;
}
$triggers = array_keys(Webhook::getTriggersForValidation());
$responses = array_keys(Webhook::getResponsesForValidation());
if (!in_array($trigger, $triggers, true) || !in_array($response, $responses, true)) {
return;
}
// cannot deliver budget info.
if (is_int($trigger)) {
Log::debug(sprintf('Trigger was integer (%d).', $trigger));
$trigger = WebhookTrigger::from($trigger)->name;
}
if (is_int($response)) {
Log::debug(sprintf('Response was integer (%d).', $response));
$response = WebhookResponse::from($response)->name;
}
Log::debug(sprintf('Trigger is %s, response is %s', $trigger, $response));
if (str_contains($trigger, 'TRANSACTION') && str_contains($response, 'BUDGET')) {
$validator->errors()->add('response', trans('validation.webhook_budget_info'));
}
if (str_contains($trigger, 'BUDGET') && str_contains($response, 'ACCOUNT')) {
$validator->errors()->add('response', trans('validation.webhook_account_info'));
}
if (str_contains($trigger, 'BUDGET') && str_contains($response, 'TRANSACTION')) {
$validator->errors()->add('response', trans('validation.webhook_transaction_info'));
}
}
);
}
}

View File

@@ -24,7 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\System;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Validation\Validator;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;

View File

@@ -51,6 +51,7 @@ class SeparateTimezoneCaster implements CastsAttributes
$timeZone = $attributes[sprintf('%s_tz', $key)] ?? config('app.timezone');
return Carbon::parse($value, $timeZone)->setTimezone(config('app.timezone'));
// Log::debug(sprintf('SeparateTimezoneCaster: %s.%s = %s', str_replace('FireflyIII\\Models\\','',get_class($model)), $key, $result->toAtomString()));
}
/**

View File

@@ -29,12 +29,15 @@ use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Factory\AccountFactory;
use FireflyIII\Models\Account;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Facades\Log;
class CorrectsAccountTypes extends Command
{
@@ -45,6 +48,7 @@ class CorrectsAccountTypes extends Command
private int $count;
private array $expected;
private AccountFactory $factory;
private AccountRepositoryInterface $repository;
/**
* Execute the console command.
@@ -110,7 +114,7 @@ class CorrectsAccountTypes extends Command
if ($resultSet->count() > 0) {
$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));
Log::debug(sprintf('Now fixing journal #%d', $entry->id));
/** @var null|TransactionJournal $journal */
$journal = TransactionJournal::find($entry->id);
@@ -120,7 +124,7 @@ class CorrectsAccountTypes extends Command
}
}
if (0 !== $this->count) {
app('log')->debug(sprintf('%d journals had to be fixed.', $this->count));
Log::debug(sprintf('%d journals had to be fixed.', $this->count));
$this->friendlyInfo(sprintf('Acted on %d transaction(s)', $this->count));
}
@@ -134,10 +138,10 @@ class CorrectsAccountTypes extends Command
private function inspectJournal(TransactionJournal $journal): void
{
app('log')->debug(sprintf('Now inspecting journal #%d', $journal->id));
Log::debug(sprintf('Now inspecting journal #%d', $journal->id));
$transactions = $journal->transactions()->count();
if (2 !== $transactions) {
app('log')->debug(sprintf('Journal has %d transactions, so can\'t fix.', $transactions));
Log::debug(sprintf('Journal has %d transactions, so can\'t fix.', $transactions));
$this->friendlyError(sprintf('Cannot inspect transaction journal #%d because it has %d transaction(s) instead of 2.', $journal->id, $transactions));
return;
@@ -151,20 +155,20 @@ class CorrectsAccountTypes extends Command
$destAccountType = $destAccount->accountType->type;
if (!array_key_exists($type, $this->expected)) {
app('log')->info(sprintf('No source/destination info for transaction type %s.', $type));
Log::info(sprintf('No source/destination info for transaction type %s.', $type));
$this->friendlyError(sprintf('No source/destination info for transaction type %s.', $type));
return;
}
if (!array_key_exists($sourceAccountType, $this->expected[$type])) {
app('log')->debug(sprintf('[a] Going to fix journal #%d', $journal->id));
Log::debug(sprintf('[a] Going to fix journal #%d', $journal->id));
$this->fixJournal($journal, $type, $sourceTransaction, $destTransaction);
return;
}
$expectedTypes = $this->expected[$type][$sourceAccountType];
if (!in_array($destAccountType, $expectedTypes, true)) {
app('log')->debug(sprintf('[b] Going to fix journal #%d', $journal->id));
Log::debug(sprintf('[b] Going to fix journal #%d', $journal->id));
$this->fixJournal($journal, $type, $sourceTransaction, $destTransaction);
}
}
@@ -181,13 +185,15 @@ class CorrectsAccountTypes extends Command
private function fixJournal(TransactionJournal $journal, string $transactionType, Transaction $source, Transaction $dest): void
{
app('log')->debug(sprintf('Going to fix journal #%d', $journal->id));
Log::debug(sprintf('Going to fix journal #%d', $journal->id));
$this->repository = app(AccountRepositoryInterface::class);
$this->repository->setUser($journal->user);
++$this->count;
// variables:
$sourceType = $source->account->accountType->type;
$destinationType = $dest->account->accountType->type;
$combination = sprintf('%s%s%s', $transactionType, $source->account->accountType->type, $dest->account->accountType->type);
app('log')->debug(sprintf('Combination is "%s"', $combination));
$sourceType = $source->account->accountType->type;
$destinationType = $dest->account->accountType->type;
$combination = sprintf('%s%s%s', $transactionType, $source->account->accountType->type, $dest->account->accountType->type);
Log::debug(sprintf('Combination is "%s"', $combination));
if ($this->shouldBeTransfer($transactionType, $sourceType, $destinationType)) {
$this->makeTransfer($journal);
@@ -211,37 +217,45 @@ class CorrectsAccountTypes extends Command
}
// transaction has no valid source.
$validSources = array_keys($this->expected[$transactionType]);
$canCreateSource = $this->canCreateSource($validSources);
$hasValidSource = $this->hasValidAccountType($validSources, $sourceType);
$validSources = array_keys($this->expected[$transactionType]);
$canCreateSource = $this->canCreateSource($validSources);
$hasValidSource = $this->hasValidAccountType($validSources, $sourceType);
if (!$hasValidSource && $canCreateSource) {
$this->giveNewRevenue($journal, $source);
return;
}
if (!$canCreateSource && !$hasValidSource) {
app('log')->debug('This transaction type has no source we can create. Just give error.');
Log::debug('This transaction type has no source we can create. Just give error.');
$message = sprintf('The source account of %s #%d cannot be of type "%s". Firefly III cannot fix this. You may have to remove the transaction yourself.', $transactionType, $journal->id, $source->account->accountType->type);
$this->friendlyError($message);
app('log')->debug($message);
Log::debug($message);
return;
}
/** @var array $validDestinations */
$validDestinations = $this->expected[$transactionType][$sourceType] ?? [];
$canCreateDestination = $this->canCreateDestination($validDestinations);
$hasValidDestination = $this->hasValidAccountType($validDestinations, $destinationType);
$validDestinations = $this->expected[$transactionType][$sourceType] ?? [];
$canCreateDestination = $this->canCreateDestination($validDestinations);
$hasValidDestination = $this->hasValidAccountType($validDestinations, $destinationType);
$alternativeDestination = $this->repository->findByName($dest->account->name, $validDestinations);
if (!$hasValidDestination && $canCreateDestination) {
$this->giveNewExpense($journal, $dest);
return;
}
if (!$canCreateDestination && !$hasValidDestination) {
app('log')->debug('This transaction type has no destination we can create. Just give error.');
if (!$canCreateDestination && !$hasValidDestination && null === $alternativeDestination) {
Log::debug('This transaction type has no destination we can create. Just give error.');
$message = sprintf('The destination account of %s #%d cannot be of type "%s". Firefly III cannot fix this. You may have to remove the transaction yourself.', $transactionType, $journal->id, $dest->account->accountType->type);
$this->friendlyError($message);
app('log')->debug($message);
Log::debug($message);
}
if (!$canCreateDestination && !$hasValidDestination && null !== $alternativeDestination) {
Log::debug('This transaction type has no destination we can create, but found alternative with the same name.');
$message = sprintf('The destination account of %s #%d cannot be of type "%s". Firefly III found an alternative account. Please make sure this transaction is correct.', $transactionType, $journal->transaction_group_id, $dest->account->accountType->type);
$this->friendlyInfo($message);
Log::debug($message);
$this->giveNewDestinationAccount($journal, $alternativeDestination);
}
}
@@ -263,7 +277,7 @@ class CorrectsAccountTypes extends Command
$journal->save();
$message = sprintf('Converted transaction #%d from a transfer to a withdrawal.', $journal->id);
$this->friendlyInfo($message);
app('log')->debug($message);
Log::debug($message);
// check it again:
$this->inspectJournal($journal);
}
@@ -281,7 +295,7 @@ class CorrectsAccountTypes extends Command
$journal->save();
$message = sprintf('Converted transaction #%d from a transfer to a deposit.', $journal->id);
$this->friendlyInfo($message);
app('log')->debug($message);
Log::debug($message);
// check it again:
$this->inspectJournal($journal);
}
@@ -308,7 +322,7 @@ class CorrectsAccountTypes extends Command
$result->name
);
$this->friendlyWarning($message);
app('log')->debug($message);
Log::debug($message);
$this->inspectJournal($journal);
}
@@ -335,7 +349,7 @@ class CorrectsAccountTypes extends Command
$result->name
);
$this->friendlyWarning($message);
app('log')->debug($message);
Log::debug($message);
$this->inspectJournal($journal);
}
@@ -354,14 +368,14 @@ class CorrectsAccountTypes extends Command
private function giveNewRevenue(TransactionJournal $journal, Transaction $source): void
{
app('log')->debug(sprintf('An account of type "%s" could be a valid source.', AccountTypeEnum::REVENUE->value));
Log::debug(sprintf('An account of type "%s" could be a valid source.', AccountTypeEnum::REVENUE->value));
$this->factory->setUser($journal->user);
$name = $source->account->name;
$newSource = $this->factory->findOrCreate($name, AccountTypeEnum::REVENUE->value);
$source->account()->associate($newSource);
$source->save();
$this->friendlyPositive(sprintf('Firefly III gave transaction #%d a new source %s: #%d ("%s").', $journal->transaction_group_id, AccountTypeEnum::REVENUE->value, $newSource->id, $newSource->name));
app('log')->debug(sprintf('Associated account #%d with transaction #%d', $newSource->id, $source->id));
Log::debug(sprintf('Associated account #%d with transaction #%d', $newSource->id, $source->id));
$this->inspectJournal($journal);
}
@@ -372,14 +386,33 @@ class CorrectsAccountTypes extends Command
private function giveNewExpense(TransactionJournal $journal, Transaction $destination): void
{
app('log')->debug(sprintf('An account of type "%s" could be a valid destination.', AccountTypeEnum::EXPENSE->value));
Log::debug(sprintf('An account of type "%s" could be a valid destination.', AccountTypeEnum::EXPENSE->value));
$this->factory->setUser($journal->user);
$name = $destination->account->name;
$newDestination = $this->factory->findOrCreate($name, AccountTypeEnum::EXPENSE->value);
$destination->account()->associate($newDestination);
$destination->save();
$this->friendlyPositive(sprintf('Firefly III gave transaction #%d a new destination %s: #%d ("%s").', $journal->transaction_group_id, AccountTypeEnum::EXPENSE->value, $newDestination->id, $newDestination->name));
app('log')->debug(sprintf('Associated account #%d with transaction #%d', $newDestination->id, $destination->id));
Log::debug(sprintf('Associated account #%d with transaction #%d', $newDestination->id, $destination->id));
$this->inspectJournal($journal);
}
private function giveNewDestinationAccount(TransactionJournal $journal, Account $newDestination): void
{
$destTransaction = $this->getDestinationTransaction($journal);
$oldDest = $destTransaction->account;
$destTransaction->account_id = $newDestination->id;
$destTransaction->save();
$message = sprintf(
'Transaction journal #%d, destination account changed from #%d ("%s") to #%d ("%s").',
$journal->id,
$oldDest->id,
$oldDest->name,
$newDestination->id,
$newDestination->name
);
$this->friendlyInfo($message);
$journal->refresh();
Log::debug($message);
}
}

View File

@@ -75,7 +75,8 @@ class CorrectsDatabase extends Command
'correction:recalculates-liabilities',
'correction:preferences',
// 'correction:transaction-types', // resource heavy, disabled.
'correction:recalculate-pc-amounts', // not necessary, disabled.
'correction:recalculate-pc-amounts',
'correction:remove-links-to-deleted-objects',
'firefly-iii:report-integrity',
];
foreach ($commands as $command) {

View File

@@ -45,9 +45,7 @@ class CorrectsGroupAccounts extends Command
public function handle(): int
{
$groups = [];
$res = TransactionJournal::groupBy('transaction_group_id')
->get(['transaction_group_id', DB::raw('COUNT(transaction_group_id) as the_count')])// @phpstan-ignore-line
;
$res = TransactionJournal::groupBy('transaction_group_id')->get(['transaction_group_id', DB::raw('COUNT(transaction_group_id) as the_count')]);
/** @var TransactionJournal $journal */
foreach ($res as $journal) {

View File

@@ -57,8 +57,6 @@ class CorrectsPiggyBanks extends Command
$event->transaction_journal_id = null;
$event->save();
++$count;
continue;
}
}
if (0 !== $count) {

View File

@@ -263,9 +263,9 @@ class CorrectsUnevenAmount extends Command
// Log::debug(sprintf('[c] %s', var_export($source->transaction_currency_id === $destination->foreign_currency_id,true)));
// Log::debug(sprintf('[d] %s', var_export((int) $destination->transaction_currency_id ===(int) $source->foreign_currency_id, true)));
if (0 === bccomp((string) app('steam')->positive($source->amount), (string) app('steam')->positive($destination->foreign_amount))
if (0 === bccomp(Steam::positive($source->amount), Steam::positive($destination->foreign_amount))
&& $source->transaction_currency_id === $destination->foreign_currency_id
&& 0 === bccomp((string) app('steam')->positive($destination->amount), (string) app('steam')->positive($source->foreign_amount))
&& 0 === bccomp(Steam::positive($destination->amount), Steam::positive($source->foreign_amount))
&& (int) $destination->transaction_currency_id === (int) $source->foreign_currency_id
) {
return true;
@@ -302,10 +302,10 @@ class CorrectsUnevenAmount extends Command
private function isBetweenAssetAndLiability(TransactionJournal $journal): bool
{
/** @var Transaction $sourceTransaction */
/** @var null|Transaction $sourceTransaction */
$sourceTransaction = $journal->transactions()->where('amount', '<', 0)->first();
/** @var Transaction $destinationTransaction */
/** @var null|Transaction $destinationTransaction */
$destinationTransaction = $journal->transactions()->where('amount', '>', 0)->first();
if (null === $sourceTransaction || null === $destinationTransaction) {
Log::warning('Either transaction is false, stop.');

View File

@@ -55,10 +55,7 @@ class RemovesEmptyJournals extends Command
*/
private function deleteUnevenJournals(): void
{
$set = Transaction::whereNull('deleted_at')
->groupBy('transactions.transaction_journal_id')
->get([DB::raw('COUNT(transactions.transaction_journal_id) as the_count'), 'transaction_journal_id']) // @phpstan-ignore-line
;
$set = Transaction::whereNull('deleted_at')->groupBy('transactions.transaction_journal_id')->get([DB::raw('COUNT(transactions.transaction_journal_id) as the_count'), 'transaction_journal_id']);
$total = 0;
/** @var Transaction $row */

View File

@@ -0,0 +1,118 @@
<?php
declare(strict_types=1);
/*
* RemovesLinksToDeletedObjects.php
* Copyright (c) 2025 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Models\Budget;
use FireflyIII\Models\Category;
use FireflyIII\Models\Tag;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
class RemovesLinksToDeletedObjects extends Command
{
use ShowsFriendlyMessages;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'correction:remove-links-to-deleted-objects';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Removes deleted entries from intermediate tables.';
/**
* Execute the console command.
*/
public function handle(): void
{
$deletedTags = Tag::withTrashed()->whereNotNull('deleted_at')->get('tags.id')->pluck('id')->toArray();
$deletedJournals = TransactionJournal::withTrashed()->whereNotNull('deleted_at')->get('transaction_journals.id')->pluck('id')->toArray();
$deletedBudgets = Budget::withTrashed()->whereNotNull('deleted_at')->get('budgets.id')->pluck('id')->toArray();
$deletedCategories = Category::withTrashed()->whereNotNull('deleted_at')->get('categories.id')->pluck('id')->toArray();
if (count($deletedTags) > 0) {
$this->cleanupTags($deletedTags);
}
if (count($deletedJournals) > 0) {
$this->cleanupJournals($deletedJournals);
}
if (count($deletedBudgets) > 0) {
$this->cleanupBudgets($deletedBudgets);
}
if (count($deletedCategories) > 0) {
$this->cleanupCategories($deletedCategories);
}
$this->friendlyNeutral('Validated links to deleted objects.');
}
private function cleanupTags(array $tags): void
{
$count = DB::table('tag_transaction_journal')->whereIn('tag_id', $tags)->delete();
if ($count > 0) {
$this->friendlyInfo(sprintf('Removed %d old relationship(s) categories transactions and tags.', $count));
}
}
private function cleanupJournals(array $journals): void
{
$count = DB::table('tag_transaction_journal')->whereIn('transaction_journal_id', $journals)->delete();
if ($count > 0) {
$this->friendlyInfo(sprintf('Removed %d old relationship(s) between tags and transactions.', $count));
}
$count = DB::table('budget_transaction_journal')->whereIn('transaction_journal_id', $journals)->delete();
if ($count > 0) {
$this->friendlyInfo(sprintf('Removed %d old relationship(s) between budgets and transactions.', $count));
}
$count = DB::table('category_transaction_journal')->whereIn('transaction_journal_id', $journals)->delete();
if ($count > 0) {
$this->friendlyInfo(sprintf('Removed %d old relationship(s) categories and transactions.', $count));
}
}
private function cleanupBudgets(array $budgets): void
{
$count = DB::table('budget_transaction_journal')->whereIn('budget_id', $budgets)->delete();
if ($count > 0) {
$this->friendlyInfo(sprintf('Removed %d old relationship(s) between budgets and transactions.', $count));
}
}
private function cleanupCategories(array $categories): void
{
$count = DB::table('category_transaction_journal')->whereIn('category_id', $categories)->delete();
if ($count > 0) {
$this->friendlyInfo(sprintf('Removed %d old relationship(s) categories categories and transactions.', $count));
}
}
}

View File

@@ -71,7 +71,6 @@ class RestoresOAuthKeys extends Command
$this->storeKeysInDB();
$this->friendlyInfo('Stored OAuth keys in database.');
return;
}
}

View File

@@ -1,9 +1,9 @@
<?php
declare(strict_types=1);
/*
* ValidatesEnvironmentVariables.php
* Copyright (c) 2025 james@firefly-iii.org.
* Copyright (c) 2025 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@@ -18,9 +18,11 @@ declare(strict_types=1);
* 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;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
@@ -30,18 +32,7 @@ class ValidatesEnvironmentVariables extends Command
{
use ShowsFriendlyMessages;
/**
* The console command description.
*
* @var null|string
*/
protected $description = 'Makes sure you use the correct variables.';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'integrity:validates-environment-variables';
/**

View File

@@ -515,7 +515,7 @@ class ForcesDecimalSize extends Command
continue;
}
// fix $field by rounding it down correctly.
$pow = (float) 10 ** $currency->decimal_places;
$pow = 10.0 ** $currency->decimal_places;
$correct = bcdiv((string) round((float) $value * $pow), (string) $pow, 12);
$this->friendlyWarning(sprintf('Transaction #%d has amount with value "%s", this has been corrected to "%s".', $item->id, $value, $correct));
@@ -546,7 +546,7 @@ class ForcesDecimalSize extends Command
continue;
}
// fix $field by rounding it down correctly.
$pow = (float) 10 ** $currency->decimal_places;
$pow = 10.0 ** $currency->decimal_places;
$correct = bcdiv((string) round((float) $value * $pow), (string) $pow, 12);
$this->friendlyWarning(
sprintf('Transaction #%d has foreign amount with value "%s", this has been corrected to "%s".', $item->id, $value, $correct)

View File

@@ -26,11 +26,14 @@ namespace FireflyIII\Console\Commands\System;
use Carbon\Carbon;
use FireflyIII\Support\System\GeneratesInstallationId;
use FireflyIII\Support\System\IsOldVersion;
use Illuminate\Console\Command;
use Random\RandomException;
class OutputsInstructions extends Command
{
use GeneratesInstallationId;
use IsOldVersion;
protected $description = 'Instructions in case of upgrade trouble.';
@@ -57,7 +60,7 @@ class OutputsInstructions extends Command
*/
private function updateInstructions(): void
{
$version = (string) config('firefly.version');
$version = (string)config('firefly.version');
/** @var array $config */
$config = config('upgrade.text.upgrade');
@@ -67,12 +70,12 @@ class OutputsInstructions extends Command
foreach (array_keys($config) as $compare) {
// if string starts with:
if (str_starts_with($version, $compare)) {
$text = (string) $config[$compare];
$text = (string)$config[$compare];
}
}
// validate some settings.
if ('' === $text && 'local' === (string) config('app.env')) {
if ('' === $text && 'local' === (string)config('app.env')) {
$text = 'Please set APP_ENV=production for a safer environment.';
}
@@ -133,6 +136,9 @@ class OutputsInstructions extends Command
if ('03-31' === $today) {
$colors = ['bright-blue', 'bright-red', 'white', 'white', 'bright-red', 'bright-blue', 'default', 'default'];
}
if ('ru_RU' === config('firefly.default_language')) {
$colors = ['blue', 'blue', 'blue', 'yellow', 'yellow', 'yellow', 'default', 'default'];
}
$this->line(sprintf('<fg=%s> ______ _ __ _ _____ _____ _____ </>', $colors[0]));
$this->line(sprintf('<fg=%s> | ____(_) / _| | |_ _|_ _|_ _| </>', $colors[1]));
@@ -187,7 +193,7 @@ class OutputsInstructions extends Command
*/
private function installInstructions(): void
{
$version = (string) config('firefly.version');
$version = (string)config('firefly.version');
/** @var array $config */
$config = config('upgrade.text.install');
@@ -197,12 +203,12 @@ class OutputsInstructions extends Command
foreach (array_keys($config) as $compare) {
// if string starts with:
if (str_starts_with($version, $compare)) {
$text = (string) $config[$compare];
$text = (string)$config[$compare];
}
}
// validate some settings.
if ('' === $text && 'local' === (string) config('app.env')) {
if ('' === $text && 'local' === (string)config('app.env')) {
$text = 'Please set APP_ENV=production for a safer environment.';
}
@@ -238,14 +244,37 @@ class OutputsInstructions extends Command
private function someQuote(): void
{
$lines = [
'Forgive yourself for not being at peace.',
'Doesn\'t look like anything to me.',
'Be proud of what you make.',
'Be there or forever wonder.',
'A year from now you will wish you had started today.',
$lines = [
'"Forgive yourself for not being at peace."',
'"Doesn\'t look like anything to me."',
'"Be proud of what you make."',
'"Be there or forever wonder."',
'"A year from now you will wish you had started today."',
'🇺🇦 Слава Україні!',
'🇺🇦 Slava Ukraini!',
];
$random = random_int(0, count($lines) - 1);
$this->line(sprintf(' "%s"', $lines[$random]));
// fuck the Russian aggression in Ukraine.
// There is no point even trying to be neutral, because you cant. When I say you cant be neutral on
// a moving train, it means the world is already moving in certain directions. Children are going
// hungry, wars are taking place. In a situation like that, to be neutral or to try to be neutral,
// to stand aside, not to take a stand, not to participate, is to collaborate with whatever is
// going on, to allow that to happen.
if ('ru_RU' === config('firefly.default_language')) {
$lines = [
'🇺🇦 Слава Україні!',
'🇺🇦 Slava Ukraini!',
];
}
try {
$random = random_int(0, count($lines) - 1);
} catch (RandomException) {
$random = 0;
}
$this->line(sprintf(' %s', $lines[$random]));
}
}

View File

@@ -1,9 +1,9 @@
<?php
declare(strict_types=1);
/*
* RecalculatesRunningBalance.php
* Copyright (c) 2025 james@firefly-iii.org.
* Copyright (c) 2025 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@@ -18,9 +18,11 @@ declare(strict_types=1);
* 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\System;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
@@ -48,7 +50,7 @@ class RecalculatesRunningBalance extends Command
/**
* Execute the console command.
*/
public function handle()
public function handle(): int
{
if (true === config('firefly.feature_flags.running_balance_column')) {
$this->friendlyInfo('Will recalculate account balances. This may take a LONG time. Please be patient.');
@@ -58,6 +60,8 @@ class RecalculatesRunningBalance extends Command
return 0;
}
$this->friendlyWarning('This command has been disabled.');
return 0;
}
private function correctBalanceAmounts(bool $forced): void

View File

@@ -1,5 +1,26 @@
<?php
/*
* ResetsErrorMailLimit.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\System;
@@ -8,6 +29,9 @@ use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use Illuminate\Console\Command;
use Symfony\Component\Console\Command\Command as CommandAlias;
use function Safe\file_put_contents;
use function Safe\json_encode;
class ResetsErrorMailLimit extends Command
{
use ShowsFriendlyMessages;

View File

@@ -78,8 +78,8 @@ class ScansAttachments extends Command
}
$tempFileName = tempnam(sys_get_temp_dir(), 'FireflyIII');
file_put_contents($tempFileName, $decryptedContent);
$attachment->md5 = (string)md5_file($tempFileName);
$attachment->mime = (string)mime_content_type($tempFileName);
$attachment->md5 = md5_file($tempFileName);
$attachment->mime = mime_content_type($tempFileName);
$attachment->save();
$this->friendlyInfo(sprintf('Fixed attachment #%d', $attachment->id));
}

View File

@@ -25,6 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\System;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Support\Facades\FireflyConfig;
use Illuminate\Console\Command;
class SetsLatestVersion extends Command
@@ -45,8 +46,7 @@ class SetsLatestVersion extends Command
return 0;
}
app('fireflyconfig')->set('db_version', config('firefly.db_version'));
app('fireflyconfig')->set('ff3_version', config('firefly.version'));
FireflyConfig::set('ff3_version', config('firefly.version'));
$this->friendlyInfo('Updated version.');
return 0;

View File

@@ -283,7 +283,7 @@ class ApplyRules extends Command
if (null !== $endString && '' !== $endString) {
$inputEnd = Carbon::createFromFormat('Y-m-d', $endString);
}
if (null === $inputEnd || null === $inputStart) {
if (!$inputEnd instanceof Carbon || null === $inputStart) {
Log::error('Could not parse start or end date in verifyInputDate().');
return;

View File

@@ -66,7 +66,7 @@ class RemovesDatabaseDecryption extends Command
* @var string $table
* @var array $fields
*/
foreach ($tables as $table => $fields) {
foreach ($tables as $table => $fields) { // @phpstan-ignore-line
$this->decryptTable($table, $fields);
}

View File

@@ -25,9 +25,11 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Upgrade;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Preference;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\UserGroup;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\User;
use Illuminate\Console\Command;
use Illuminate\Support\Collection;
@@ -65,7 +67,7 @@ class UpgradesCurrencyPreferences extends Command
{
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
if (null !== $configVar) {
return (bool) $configVar->data;
return (bool)$configVar->data;
}
return false;
@@ -104,8 +106,8 @@ class UpgradesCurrencyPreferences extends Command
private function upgradeUserPreferences(User $user): void
{
$currencies = TransactionCurrency::get();
$enabled = new Collection();
$currencies = TransactionCurrency::get();
$enabled = new Collection();
/** @var TransactionCurrency $currency */
foreach ($currencies as $currency) {
@@ -116,10 +118,11 @@ class UpgradesCurrencyPreferences extends Command
$user->currencies()->sync($enabled->pluck('id')->toArray());
// set the default currency for the user and for the group:
$preference = $this->getPreference($user);
$primaryCurrency = TransactionCurrency::where('code', $preference)->first();
if (null === $primaryCurrency) {
// get EUR
$preference = $this->getPreference($user);
try {
$primaryCurrency = Amount::getTransactionCurrencyByCode($preference);
} catch (FireflyException) {
$primaryCurrency = TransactionCurrency::where('code', 'EUR')->first();
}
$user->currencies()->updateExistingPivot($primaryCurrency->id, ['user_default' => true]);
@@ -135,7 +138,7 @@ class UpgradesCurrencyPreferences extends Command
}
if (null !== $preference->data && !is_array($preference->data)) {
return (string) $preference->data;
return (string)$preference->data;
}
return 'EUR';

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