Compare commits

..

280 Commits

Author SHA1 Message Date
github-actions
2a3ba9799e Auto commit for release 'develop' on 2024-04-08 2024-04-08 05:09:59 +02:00
James Cole
d121aad28f Check the directory, not the file. 2024-04-07 16:27:15 +02:00
github-actions
dc808fa807 Auto commit for release 'develop' on 2024-04-07 2024-04-07 16:22:39 +02:00
James Cole
a1be6ff62b Limit the number of error messages Firefly III will send. 2024-04-07 16:12:41 +02:00
James Cole
20dc5b0256 Fix layout errors. 2024-04-07 15:57:51 +02:00
James Cole
edd54e23c5 Merge branch 'main' into develop 2024-04-07 10:40:03 +02:00
James Cole
1238df8784 Switch to v38 2024-04-07 10:38:17 +02:00
github-actions
b8c62652b0 Auto commit for release 'develop' on 2024-04-07 2024-04-07 10:37:19 +02:00
James Cole
54b2d02f63 Build JS in one go. 2024-04-07 10:31:24 +02:00
James Cole
47faf89a5c Update script to apply patch. 2024-04-07 10:29:54 +02:00
James Cole
b7fb5a3854 This configuration works but patch-package doesn't take (yt) 2024-04-07 10:12:23 +02:00
James Cole
a384b4202a Add gitkeep file 2024-04-07 07:26:31 +02:00
James Cole
99ecac0ce4 Clean up some scripts. 2024-04-07 07:25:54 +02:00
James Cole
6102982456 Move more JS files 2024-04-07 07:21:08 +02:00
James Cole
b88e981b4b Move v2 files 2024-04-07 07:17:34 +02:00
James Cole
827263b03e Move v1 assets 2024-04-07 07:16:38 +02:00
James Cole
d44e74d334 Merge branch 'main' into develop 2024-04-07 06:52:49 +02:00
github-actions
911f46c590 Auto commit for release 'develop' on 2024-04-07 2024-04-07 06:51:34 +02:00
James Cole
7d42c4ee5d Move to v37 2024-04-07 06:45:48 +02:00
James Cole
ea89f6177f Move selected translations to Firefly III 2024-04-07 06:44:45 +02:00
James Cole
74291b3870 Expand API administration validation 2024-04-07 06:06:40 +02:00
James Cole
2c4f2082fe Update workflows. 2024-04-06 06:26:21 +02:00
github-actions
d8d58cc29b Auto commit for release 'develop' on 2024-04-04 2024-04-04 05:11:18 +02:00
James Cole
85b17e4035 Drop the type for now, fixes https://github.com/orgs/firefly-iii/discussions/8750 2024-04-03 20:07:18 +02:00
James Cole
83de5667b3 Fix icons en styling 2024-04-03 08:59:44 +02:00
James Cole
5fffe873c6 Update PR template 2024-04-03 05:55:39 +02:00
James Cole
78c09c82d6 Merge branch 'main' into develop 2024-04-03 05:48:55 +02:00
James Cole
704abc315d New template 2024-04-03 05:48:38 +02:00
github-actions
86b4965458 Auto commit for release 'develop' on 2024-04-03 2024-04-03 05:19:06 +02:00
James Cole
d2dc0c2bf0 Merge branch 'main' into develop 2024-04-03 05:12:51 +02:00
James Cole
9f4894bbb5 Fix https://github.com/firefly-iii/firefly-iii/issues/8748 2024-04-03 05:12:28 +02:00
James Cole
76a8675a34 make sure boxes are empty 2024-04-02 18:04:42 +02:00
James Cole
6988301da1 Merge pull request #8746 from imlonghao/patch-1
Set date to now when cloning journal
2024-04-02 18:03:52 +02:00
imlonghao
109cd37211 Set date to now when cloning journal
Signed-off-by: imlonghao <git@imlonghao.com>
2024-04-02 23:44:45 +08:00
James Cole
284ff4d1b0 Merge branch 'main' into develop 2024-04-02 16:53:31 +02:00
James Cole
bc0ab7af99 Spelling error in nightly release instructions 2024-04-02 16:53:18 +02:00
James Cole
a17bc7258f Fix phpstan error courtesy of the laravel 11 upgrade (changed signatures and return types) 2024-04-02 15:40:33 +02:00
James Cole
87911c2438 Catch empty preference, just in case. 2024-04-02 12:38:31 +02:00
github-actions
746f1fd300 Auto commit for release 'develop' on 2024-04-02 2024-04-02 07:47:24 +02:00
James Cole
9e5faf919f Add space 2024-04-02 07:40:40 +02:00
James Cole
cc6cbe6605 Add something to changelog before I forget. 2024-04-02 07:01:13 +02:00
James Cole
dc6d708897 Replace frontpageAccounts variable name. 2024-04-02 06:59:40 +02:00
James Cole
6189d24b98 Replace variable names. 2024-04-01 20:26:02 +02:00
James Cole
f6e28dc88f Fine tune preferences to handle multi-administration options. 2024-04-01 19:59:21 +02:00
James Cole
75ea035630 Preferences can be administration specific. Not yet really working. 2024-04-01 18:18:48 +02:00
James Cole
4cdb14301d Add administration specific thing to preferences. 2024-04-01 18:03:43 +02:00
James Cole
9f95221ba3 Various code cleanup. 2024-04-01 17:43:31 +02:00
James Cole
e3a67be412 Clear user groups when loading 2024-04-01 16:07:14 +02:00
James Cole
5749b642ce Wrong response code. 2024-04-01 16:07:03 +02:00
James Cole
baff7c67f9 Expand user group views and translations 2024-04-01 15:41:16 +02:00
James Cole
ccc005942f Expand user group pages. 2024-04-01 15:40:53 +02:00
James Cole
5b83c33039 Turns out it's pointless to add "default_administration", you can force that already through the owner role (which is already in place). 2024-04-01 14:15:35 +02:00
James Cole
cc32578c5f Add new strings. 2024-04-01 14:04:36 +02:00
James Cole
80f410835b Expand models, user groups need more properties. 2024-04-01 14:04:22 +02:00
James Cole
b537a3145d Expand financial administrations views. 2024-04-01 14:01:52 +02:00
James Cole
bfa1fcbaf8 make sure output.txt is writeable. 2024-04-01 09:08:19 +02:00
James Cole
56243907c4 Add some debug info 2024-04-01 09:01:53 +02:00
James Cole
5928dd72e6 Forgot the zip name 2024-04-01 08:53:56 +02:00
github-actions
c6bf0ff1cd Auto commit for release 'v6.1.13' on 2024-04-01 2024-04-01 08:51:46 +02:00
James Cole
19d1cf192b Fix tests, update changelog. 2024-04-01 08:46:13 +02:00
James Cole
37d7dc7e3e Merge branch 'main' into develop 2024-04-01 08:37:57 +02:00
James Cole
95a3a194b8 Better instructions 2024-04-01 08:37:49 +02:00
James Cole
3542387188 Merge branch 'main' into develop 2024-04-01 08:36:25 +02:00
James Cole
da1b002a64 Clean up and expand normal release 2024-04-01 08:36:15 +02:00
James Cole
46daee28e7 Merge branch 'main' into develop 2024-04-01 08:33:02 +02:00
James Cole
9ade5635d4 Add file with revision of the used branch. 2024-04-01 08:32:51 +02:00
James Cole
e14e80f33c Merge branch 'main' into develop 2024-04-01 08:31:32 +02:00
github-actions
0c824e21c8 Auto commit for release 'develop' on 2024-04-01 2024-04-01 05:10:33 +02:00
James Cole
fab1c68569 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2024-03-31 19:32:00 +02:00
James Cole
c1534657f2 Fix the installation template. 2024-03-31 19:31:52 +02:00
github-actions
39841de680 Auto commit for release 'develop' on 2024-03-31 2024-03-31 17:12:02 +02:00
James Cole
43a720b62b It helps when you actually add 1 2024-03-31 17:06:37 +02:00
James Cole
5ec54de29e Fix shitty test 2024-03-31 16:51:53 +02:00
James Cole
397e37f344 Fix another division by zero 2024-03-31 16:46:38 +02:00
James Cole
b6f84c2b99 Expand v2 layout, add user administration pages. 2024-03-31 16:46:20 +02:00
James Cole
843f86fc66 Merge branch 'main' into develop 2024-03-31 11:29:35 +02:00
James Cole
0e8e364074 Can now release multiple development builds per day 2024-03-31 10:01:21 +02:00
James Cole
bbccbef578 Fix loop 2024-03-31 09:55:17 +02:00
James Cole
ee11a8e3a0 Add check for duplicate tags 2024-03-31 09:48:20 +02:00
James Cole
e8618047bd More readable fix for division by zero error. 2024-03-31 08:40:47 +02:00
James Cole
f104b76f73 Merge pull request #8735 from mansuf/develop
Fix `Division error by zero` in budget views
2024-03-31 08:37:09 +02:00
Rahman Yusuf
cb701d8506 Fix Division error by zero in budget views 2024-03-31 12:03:54 +07:00
James Cole
70a334c56e Merge branch 'main' into develop 2024-03-31 03:16:54 +02:00
github-actions
e6b2db1e29 Auto commit for release 'develop' on 2024-03-31 2024-03-31 03:14:08 +02:00
James Cole
e8dffa0052 Update script version 2024-03-31 03:09:00 +02:00
James Cole
c4f0512f39 Run another composer, and dump the autoload files. 2024-03-31 03:06:58 +02:00
James Cole
3268019d0c Fix #8732 2024-03-31 01:24:18 +01:00
James Cole
a0ef6a1fc8 Fix https://github.com/firefly-iii/firefly-iii/issues/8725 2024-03-30 09:56:51 +01:00
James Cole
99d0098b20 Merge branch 'main' into develop 2024-03-28 05:59:30 +01:00
James Cole
a7a54c042c Touch and exclude tar name 2024-03-28 05:53:31 +01:00
github-actions
c44e48a793 Auto commit for release 'develop' on 2024-03-28 2024-03-28 04:10:19 +01:00
James Cole
53b501ca73 Add tar.gz file 2024-03-27 20:04:14 +01:00
James Cole
322f70bcca Merge branch 'main' into develop
# Conflicts:
#	.github/workflows/release.yml
2024-03-27 07:10:24 +01:00
James Cole
35559c077b Update text in output. 2024-03-27 06:59:48 +01:00
github-actions
590ffe7c76 Auto commit for release 'develop' on 2024-03-27 2024-03-27 06:58:44 +01:00
James Cole
8a2d8f148e Expand text under development release 2024-03-27 06:50:39 +01:00
James Cole
4f0e15e07d Expand text in dev release. 2024-03-27 06:49:56 +01:00
James Cole
7463861e0c Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2024-03-26 07:40:51 +01:00
James Cole
1e70fa28be Fix https://github.com/firefly-iii/firefly-iii/issues/8648 2024-03-26 07:37:21 +01:00
github-actions
26c6ca470b Auto commit for release 'develop' on 2024-03-26 2024-03-26 07:37:05 +01:00
James Cole
5e54034e0e Merge branch 'main' into develop
# Conflicts:
#	.github/workflows/release.yml
2024-03-26 07:32:26 +01:00
James Cole
25873ef734 add npm update. 2024-03-26 07:31:33 +01:00
James Cole
1092b04b22 Merge branch 'main' into develop 2024-03-26 07:30:27 +01:00
James Cole
01ce74dd72 Expand release script with shasum 2024-03-26 07:30:15 +01:00
James Cole
41430d8386 Fix bill box and hover CSS 2024-03-26 07:25:36 +01:00
James Cole
01eb19169c Merge pull request #8714 from firefly-iii/dependabot/npm_and_yarn/develop/vite-4.5.3 2024-03-25 07:08:14 +01:00
dependabot[bot]
cfaa7d7c68 Bump vite from 4.5.2 to 4.5.3
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 4.5.2 to 4.5.3.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v4.5.3/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v4.5.3/packages/vite)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-25 03:13:52 +00:00
github-actions
14d3312a10 Auto commit for release 'develop' on 2024-03-25 2024-03-25 04:10:34 +01:00
James Cole
87be478dd8 Expand dashboard view 2024-03-24 16:22:27 +01:00
James Cole
0b6877a20e Fix null pointer 2024-03-24 14:11:30 +01:00
James Cole
7186f0ef60 Improve boxes 2024-03-24 14:10:07 +01:00
James Cole
538933691e Add sort column to account overview. and some css fixes 2024-03-24 13:24:48 +01:00
James Cole
46c49ddbd8 Add translations, fix error message. 2024-03-24 12:07:26 +01:00
James Cole
bcfb134b6e Clean up 2024-03-24 11:43:37 +01:00
James Cole
57981f1cf9 Read and remember sort order by URL 2024-03-24 11:08:24 +01:00
James Cole
0310186fb7 Expand accounts page. 2024-03-23 20:37:15 +01:00
James Cole
4dcb38290e Better inline editor. 2024-03-23 15:20:49 +01:00
James Cole
2f5c37048b Update vite.config.js
Add relative path.

Signed-off-by: James Cole <james@firefly-iii.org>
2024-03-21 13:44:51 +01:00
github-actions
370c8b16ae Auto commit for release 'develop' on 2024-03-21 2024-03-21 04:11:26 +01:00
github-actions
af0555592a Auto commit for release 'v6.1.12' on 2024-03-20 2024-03-20 17:55:25 +01:00
James Cole
9c07ddaed6 Replace shitty Laravel Passport command. 2024-03-20 17:48:13 +01:00
James Cole
bb7355a566 Fix https://github.com/orgs/firefly-iii/discussions/8696 2024-03-20 17:32:06 +01:00
James Cole
1d48347f8c Update release notes for new version. 2024-03-20 17:28:56 +01:00
James Cole
060b76ca9c Replace command in composer.json 2024-03-20 11:45:56 +01:00
James Cole
2b2b9b6f7a Drop duplicate index 2024-03-20 06:14:32 +01:00
James Cole
f3dd05a0c0 Move jobs to better times. 2024-03-20 06:12:56 +01:00
James Cole
47a91aa273 Exclude file from release. 2024-03-19 17:52:00 +01:00
github-actions
41bc236603 Auto commit for release 'v6.1.11' on 2024-03-19 2024-03-19 17:44:55 +01:00
James Cole
65349451ea Update changelog. 2024-03-19 17:39:54 +01:00
James Cole
e77b6a55a4 Merge branch 'main' into develop 2024-03-19 17:33:49 +01:00
James Cole
2379bcff11 git Merge branch 'develop' of https://github.com/firefly-iii/firefly-iii into develop 2024-03-19 14:28:46 +01:00
James Cole
7133156fa1 add empty dir 2024-03-19 14:28:40 +01:00
github-actions
a59176689d Auto commit for release 'develop' on 2024-03-19 2024-03-19 14:23:12 +01:00
James Cole
bc2d8f3dfb Deleted generated JS 2024-03-19 14:06:57 +01:00
James Cole
ddf89a9d5a remove build dir 2024-03-19 11:10:05 +01:00
James Cole
7daaba17f6 Update git ignore file 2024-03-19 10:23:17 +01:00
James Cole
9cb5b1384f Remove generated files 2024-03-19 10:23:01 +01:00
github-actions
7d13263482 Auto commit for release 'develop' on 2024-03-18 2024-03-18 21:08:27 +01:00
James Cole
d9ff252915 Unignore files 2024-03-18 21:03:17 +01:00
James Cole
51ba550251 Ignore generated files. 2024-03-18 20:29:09 +01:00
James Cole
fd21c467ad Remove generated files. 2024-03-18 20:28:58 +01:00
github-actions
9aa90650b4 Auto commit for release 'develop' on 2024-03-18 2024-03-18 20:25:30 +01:00
James Cole
d892257e8b Add artifact. 2024-03-18 20:19:18 +01:00
James Cole
db0dbcfcf1 Disable exchange rates by default. 2024-03-18 06:20:33 +01:00
James Cole
f591996f04 Remove deferrable interface 2024-03-18 06:14:17 +01:00
James Cole
b08d385586 Merge pull request #8683 from firefly-iii/dependabot/npm_and_yarn/develop/axios-1.6.8 2024-03-18 05:45:38 +01:00
James Cole
20ef22f67e Merge pull request #8682 from firefly-iii/dependabot/npm_and_yarn/develop/sass-1.72.0 2024-03-18 05:45:31 +01:00
James Cole
c888baf542 Merge pull request #8681 from firefly-iii/dependabot/npm_and_yarn/develop/date-fns-3.6.0 2024-03-18 05:45:22 +01:00
dependabot[bot]
8b0af3f666 Bump axios from 1.6.7 to 1.6.8
Bumps [axios](https://github.com/axios/axios) from 1.6.7 to 1.6.8.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.6.7...v1.6.8)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-18 03:07:58 +00:00
dependabot[bot]
7043e1e7c0 Bump sass from 1.71.1 to 1.72.0
Bumps [sass](https://github.com/sass/dart-sass) from 1.71.1 to 1.72.0.
- [Release notes](https://github.com/sass/dart-sass/releases)
- [Changelog](https://github.com/sass/dart-sass/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sass/dart-sass/compare/1.71.1...1.72.0)

---
updated-dependencies:
- dependency-name: sass
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-18 03:07:43 +00:00
dependabot[bot]
c5854eba23 Bump date-fns from 3.3.1 to 3.6.0
Bumps [date-fns](https://github.com/date-fns/date-fns) from 3.3.1 to 3.6.0.
- [Release notes](https://github.com/date-fns/date-fns/releases)
- [Changelog](https://github.com/date-fns/date-fns/blob/main/CHANGELOG.md)
- [Commits](https://github.com/date-fns/date-fns/compare/v3.3.1...v3.6.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-18 03:07:29 +00:00
github-actions
ddf1a8cebb Auto commit for release 'develop' on 2024-03-18 2024-03-18 01:30:56 +01:00
James Cole
7dcaf167e9 Replace blade template with twig template 2024-03-17 15:54:18 +01:00
James Cole
b359d51d3a Fix code and tests. 2024-03-17 12:26:56 +01:00
James Cole
3913fa5086 Restore old behavior 2024-03-17 12:00:28 +01:00
James Cole
ab2772abe0 Remove deferrable. 2024-03-17 11:44:58 +01:00
James Cole
bc7875b17b Add stub component. 2024-03-17 09:30:26 +01:00
James Cole
4938fa9990 Add stub component. 2024-03-17 09:29:49 +01:00
James Cole
84df2c80ee Fix missing var 2024-03-17 09:27:04 +01:00
James Cole
dc17060754 Remove deferrable. 2024-03-17 09:24:50 +01:00
James Cole
e2fa81dddc Remove deferrable. 2024-03-17 09:24:25 +01:00
James Cole
182dfc95fe Remove deferrable. 2024-03-17 09:23:44 +01:00
James Cole
c8979b6c33 Remove deferrable. 2024-03-17 09:23:12 +01:00
James Cole
ab872e8912 Remove deferrable. 2024-03-17 09:22:45 +01:00
James Cole
d36b94fabf Remove deferrable. 2024-03-17 09:22:13 +01:00
James Cole
e3d4ceaecb Merge branch 'main' into develop 2024-03-17 09:19:26 +01:00
James Cole
e3a6e5b788 Upgrade to laravel 11 2024-03-17 09:19:01 +01:00
James Cole
57235c0e00 Merge pull request #8675 from firefly-iii/dependabot/npm_and_yarn/follow-redirects-1.15.6 2024-03-17 07:43:18 +01:00
dependabot[bot]
2298c3ddaf Bump follow-redirects from 1.15.5 to 1.15.6
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.5 to 1.15.6.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.5...v1.15.6)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-16 23:39:53 +00:00
James Cole
7224f1be6f Small code cleanup. 2024-03-16 23:06:16 +01:00
James Cole
1bd3019c16 Small code cleanup. 2024-03-16 22:57:48 +01:00
James Cole
f0fa21dead First version of line edit. 2024-03-16 22:00:25 +01:00
James Cole
845eaed8d7 Code cleanup. 2024-03-16 11:27:07 +01:00
James Cole
b3649cd4d0 Add migration routine for https://github.com/firefly-iii/firefly-iii/pull/8650 2024-03-16 07:03:50 +01:00
James Cole
55f14c587b New funding file. 2024-03-16 06:33:31 +01:00
James Cole
441a8a8408 Some code cleanup 2024-03-16 06:28:21 +01:00
James Cole
060c9648f1 Fix https://github.com/firefly-iii/firefly-iii/issues/8668 2024-03-16 06:25:56 +01:00
James Cole
7680c8733f Expand. include discussions. 2024-03-16 06:09:10 +01:00
James Cole
5a0af5c93b Fix https://github.com/firefly-iii/firefly-iii/issues/8672 2024-03-15 06:13:40 +01:00
James Cole
f4b066add1 Fix https://github.com/firefly-iii/firefly-iii/issues/8671 2024-03-14 21:20:30 +01:00
github-actions
9ecb414b02 Auto commit for release 'develop' on 2024-03-14 2024-03-14 01:29:53 +01:00
James Cole
ad4f908c24 CI will stop complaining about code base, bi-weekly release picks this up. 2024-03-13 06:52:16 +01:00
James Cole
025f739442 Reformat some code. 2024-03-13 06:51:31 +01:00
James Cole
6df7354c48 Rebuild frontend cause lazy. 2024-03-13 06:51:22 +01:00
James Cole
3f77c845ca Add last activity column 2024-03-13 06:50:08 +01:00
James Cole
d4771f7a5c Remove old configuration file. 2024-03-13 06:29:39 +01:00
James Cole
ec4e2bfa4f Fix https://github.com/firefly-iii/firefly-iii/issues/8663 2024-03-12 20:36:31 +01:00
github-actions
dfdbfae4b5 Auto commit for release 'develop' on 2024-03-11 2024-03-11 06:17:46 +01:00
James Cole
349d38b956 Merge branch 'main' into develop 2024-03-11 06:12:38 +01:00
James Cole
2267aa3ac4 Fix workflow 2024-03-11 06:12:29 +01:00
James Cole
2323aa454e Add git keep 2024-03-11 06:10:17 +01:00
James Cole
8b3317b665 Merge pull request #8658 from firefly-iii/dependabot/composer/develop/symfony/expression-language-7.0.3 2024-03-11 05:26:48 +01:00
James Cole
15f893c343 Merge pull request #8657 from firefly-iii/dependabot/npm_and_yarn/develop/alpinejs-3.13.7 2024-03-11 05:26:21 +01:00
James Cole
309b3e765e Merge pull request #8656 from firefly-iii/dependabot/npm_and_yarn/develop/i18next-23.10.1 2024-03-11 05:26:12 +01:00
dependabot[bot]
d3fad06e00 Bump symfony/expression-language from 6.4.3 to 7.0.3
Bumps [symfony/expression-language](https://github.com/symfony/expression-language) from 6.4.3 to 7.0.3.
- [Release notes](https://github.com/symfony/expression-language/releases)
- [Changelog](https://github.com/symfony/expression-language/blob/7.0/CHANGELOG.md)
- [Commits](https://github.com/symfony/expression-language/compare/v6.4.3...v7.0.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-11 03:55:59 +00:00
dependabot[bot]
834f24c99c Bump alpinejs from 3.13.6 to 3.13.7
Bumps [alpinejs](https://github.com/alpinejs/alpine/tree/HEAD/packages/alpinejs) from 3.13.6 to 3.13.7.
- [Release notes](https://github.com/alpinejs/alpine/releases)
- [Commits](https://github.com/alpinejs/alpine/commits/v3.13.7/packages/alpinejs)

---
updated-dependencies:
- dependency-name: alpinejs
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-11 03:39:56 +00:00
dependabot[bot]
35291e1298 Bump i18next from 23.10.0 to 23.10.1
Bumps [i18next](https://github.com/i18next/i18next) from 23.10.0 to 23.10.1.
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v23.10.0...v23.10.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-11 03:39:44 +00:00
James Cole
ac4e9dcbc5 Code cleanup. 2024-03-10 17:15:38 +01:00
James Cole
d57806f2ba Drop hashes 2024-03-10 16:52:59 +01:00
James Cole
3b005c317d Remove 'strict-dynamic' 2024-03-10 16:49:16 +01:00
James Cole
e91903fed2 Different orderRemove self 2024-03-10 16:47:59 +01:00
James Cole
fee2002b0f Remove self 2024-03-10 16:47:36 +01:00
James Cole
f12e502eb8 Fix header 2024-03-10 16:46:33 +01:00
James Cole
24e62b1cee Fix header 2024-03-10 16:45:19 +01:00
James Cole
f559ec73e0 Add exception catch. 2024-03-10 16:44:41 +01:00
James Cole
530b501fcf Disable engine. [skip ci] 2024-03-10 11:57:54 +01:00
James Cole
d5ea78025e Fix a few small bugs and rearrange code. 2024-03-10 11:57:21 +01:00
James Cole
3413b9b5b5 Refresh notes in various actions. 2024-03-10 08:11:58 +01:00
James Cole
0b45c1aa76 Better validation, can now also use notes in expression. 2024-03-10 08:08:26 +01:00
James Cole
5718d1690a Add debug logging 2024-03-10 08:07:47 +01:00
James Cole
67b16cc070 Overrule "constant" and "enum" actions. 2024-03-10 06:46:38 +01:00
James Cole
5746ac3247 Add feature flag for expression engine and disable it by default. 2024-03-10 06:46:24 +01:00
James Cole
8a2c520b11 Update packages 2024-03-10 06:29:24 +01:00
James Cole
f46c14df8c Validation over GET, take precedence over other routes 2024-03-10 06:29:15 +01:00
James Cole
009fbba491 Drop "failedValidation" method because this is handled by the system already. 2024-03-10 06:28:58 +01:00
James Cole
53d84347c2 sprintf the rules 2024-03-10 06:24:32 +01:00
James Cole
1961487055 Reformat code. 2024-03-10 06:17:31 +01:00
James Cole
c9ce5df74b Merge pull request #8650 from michaelhthomas/feat/expression-engine
[feat] Rules Expression Engine
2024-03-10 06:04:06 +01:00
Michael Thomas
1371b6773e chore: ignore PHPMD unused parameter errors 2024-03-09 14:09:36 -05:00
James Cole
b9f1baf150 Update packages 2024-03-09 19:50:46 +01:00
James Cole
66b322e844 Fix methods and clean up code. 2024-03-09 19:46:16 +01:00
James Cole
487b65b669 Rebuild frontend. 2024-03-09 19:33:43 +01:00
James Cole
9078781d61 New endpoint, fixed logo, better account overview. 2024-03-09 19:31:27 +01:00
Michael Thomas
1ec830521a fix: resolve PHPstan errors 2024-03-09 13:02:04 -05:00
Michael Thomas
c4bf2aae7d fix: migrate action expression validation to separate rule class 2024-03-09 12:57:34 -05:00
Michael Thomas
69ca88d9f8 fix(api): use kebab case route for validate-expression endpoint 2024-03-09 12:07:20 -05:00
Michael Thomas
b38b7b2534 fix: drop unnecessary changes to composer.lock 2024-03-09 12:05:56 -05:00
Michael Thomas
f19bfc3b4b fix(ActionExpression): update list of valid variable names to reflect actual values 2024-03-09 12:03:46 -05:00
Michael Thomas
d22f9c09d7 fix(RuleAction): add return type to getValue 2024-03-09 12:02:47 -05:00
Michael Thomas
fc2da9eb42 fix(ExpressionController): remove unnecessary rule repository 2024-03-09 11:27:21 -05:00
James Cole
f2c9e20aef Fix other pages 2024-03-09 13:35:22 +01:00
James Cole
16b8ca2746 Add some spacing 2024-03-09 13:20:43 +01:00
James Cole
46ea074821 Merge branch 'main' into develop 2024-03-09 13:20:03 +01:00
James Cole
d2c89781e2 Rebuild frontend 2024-03-09 13:19:39 +01:00
James Cole
e54d711891 Improve colors. 2024-03-09 13:17:58 +01:00
James Cole
84d3ad4764 Remove unused local files. 2024-03-09 13:12:33 +01:00
James Cole
b908951a2d Refactor views 2024-03-09 13:08:23 +01:00
James Cole
8b87deea58 Refactor error pages 2024-03-09 13:03:02 +01:00
James Cole
0d7325b3dc Fix CSS and JS (on dashboard) 2024-03-09 12:21:45 +01:00
James Cole
a3fd99a498 Rename (unused) files. 2024-03-09 12:11:18 +01:00
James Cole
0ff405d1e0 Refactor views and CSS 2024-03-09 12:11:06 +01:00
James Cole
46a60af966 Clean up authentication views. 2024-03-09 08:13:53 +01:00
James Cole
591c9e3b39 Move old login screen. 2024-03-09 07:00:35 +01:00
James Cole
c30461b20b Update lock.yml
Signed-off-by: James Cole <james@firefly-iii.org>
2024-03-09 05:20:30 +01:00
James Cole
2c3f86d9bc Update lock.yml
Signed-off-by: James Cole <james@firefly-iii.org>
2024-03-09 05:19:17 +01:00
Michael Thomas
34349e4475 chore: fix typo 2024-03-07 21:37:24 -05:00
Michael Thomas
6acd5be5dc chore: remove accidental changes 2024-03-07 21:10:11 -05:00
Michael Thomas
55a2b4e789 feat: make all transaction journal variables globals
removes redundant reference to the `transaction` object by making all its properties global
2024-03-07 20:58:43 -05:00
Michael Thomas
f41397eb43 refactor: add method on RuleAction to compute action value 2024-03-07 19:02:40 -05:00
Michael Thomas
41fc1e8f82 Merge remote-tracking branch 'upstream/develop' into feat/expression-engine 2024-03-07 13:09:43 -05:00
Michael Thomas
bee219ebf7 refactor: inject ExpressionLanguage singleton using DI 2024-03-07 13:00:57 -05:00
Michael Thomas
438f602961 feat: surface expression validation errors when creating or updating rules 2024-03-07 12:23:32 -05:00
James Cole
429e72e681 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2024-03-07 06:08:09 +01:00
James Cole
7a134781f2 Fix route name. 2024-03-07 06:01:39 +01:00
Michael Thomas
b572c1dcd3 Merge remote-tracking branch 'upstream/main' into feat/expression-engine 2024-03-06 21:38:40 -05:00
Michael Thomas
95593f847b feat: update all rules to support action value expressions 2024-03-06 20:54:50 -05:00
github-actions
b82fcbd97b Auto commit for release 'develop' on 2024-03-07 2024-03-07 01:29:08 +01:00
Michael Thomas
daddee7806 feat: support action expression parsing, validation, and evaluation 2024-03-06 17:50:16 -05:00
James Cole
930a08ec90 Better index for accounts. 2024-03-06 19:54:09 +01:00
James Cole
fd2edf3b23 Various code cleanup. 2024-03-06 07:16:01 +01:00
James Cole
0597255c08 Fix #8632 2024-03-06 07:01:21 +01:00
James Cole
955ab38a85 Merge pull request #8634 from WardenJakx/develop 2024-03-06 06:10:29 +01:00
WardenJakx
1311a0db8b fix broken link 2024-03-05 22:35:23 -05:00
James Cole
0ce9ee6a6c Ignore phpstan error [skip ci] 2024-03-05 19:39:20 +01:00
James Cole
3a339382d4 Add a button to go back to the v1 layout. 2024-03-05 19:38:45 +01:00
James Cole
a5b15bbc16 Rebuild frontend for basic account list. 2024-03-05 05:54:04 +01:00
James Cole
fbf89fd514 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2024-03-04 20:42:05 +01:00
James Cole
b3223feba2 Add debug log 2024-03-04 20:41:59 +01:00
James Cole
88a9bc379e Expand account list 2024-03-04 20:41:34 +01:00
James Cole
b442b91b7c Merge pull request #8621 from firefly-iii/dependabot/composer/develop/barryvdh/laravel-ide-helper-3.0.0 2024-03-04 06:01:38 +01:00
dependabot[bot]
9fadbbe087 Bump barryvdh/laravel-ide-helper from 2.15.1 to 3.0.0
Bumps [barryvdh/laravel-ide-helper](https://github.com/barryvdh/laravel-ide-helper) from 2.15.1 to 3.0.0.
- [Release notes](https://github.com/barryvdh/laravel-ide-helper/releases)
- [Changelog](https://github.com/barryvdh/laravel-ide-helper/blob/master/CHANGELOG.md)
- [Commits](https://github.com/barryvdh/laravel-ide-helper/compare/v2.15.1...v3.0.0)

---
updated-dependencies:
- dependency-name: barryvdh/laravel-ide-helper
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-04 03:49:45 +00:00
github-actions
1ef7239276 Auto commit for release 'develop' on 2024-03-04 2024-03-04 01:30:26 +01:00
James Cole
ea573e9434 Remove some. 2024-03-03 20:07:47 +01:00
James Cole
34fa24e4a8 Remove some indices 2024-03-03 20:01:35 +01:00
James Cole
a1be4a4d8a Add indices 2024-03-03 19:58:51 +01:00
James Cole
b8e8af1e2a Update database version. 2024-03-03 17:58:13 +01:00
James Cole
c13a3fb30c Add missing indices. 2024-03-03 17:55:59 +01:00
James Cole
cb8fa4e1f4 Fix https://github.com/firefly-iii/firefly-iii/issues/8616 2024-03-03 13:45:05 +01:00
James Cole
bf7f4f9887 Fix https://github.com/firefly-iii/firefly-iii/issues/8597 2024-03-03 10:13:49 +01:00
James Cole
af48548e81 Fix https://github.com/firefly-iii/firefly-iii/issues/8608 2024-03-02 19:20:54 +01:00
899 changed files with 23868 additions and 80526 deletions

View File

@@ -22,6 +22,9 @@
SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
echo "Running PHP CS Fixer"
$SCRIPT_DIR/phpcs.sh
echo "Running PHPStan"
$SCRIPT_DIR/phpstan.sh
echo "Running PHPMD"
$SCRIPT_DIR/phpmd.sh

View File

@@ -1,5 +1,5 @@
{
"require": {
"friendsofphp/php-cs-fixer": "^3.12"
}
"require": {
"friendsofphp/php-cs-fixer": "^3.12"
}
}

View File

@@ -8,16 +8,16 @@
"packages": [
{
"name": "composer/pcre",
"version": "3.1.1",
"version": "3.1.3",
"source": {
"type": "git",
"url": "https://github.com/composer/pcre.git",
"reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9"
"reference": "5b16e25a5355f1f3afdfc2f954a0a80aec4826a8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/pcre/zipball/00104306927c7a0919b4ced2aaa6782c1e61a3c9",
"reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9",
"url": "https://api.github.com/repos/composer/pcre/zipball/5b16e25a5355f1f3afdfc2f954a0a80aec4826a8",
"reference": "5b16e25a5355f1f3afdfc2f954a0a80aec4826a8",
"shasum": ""
},
"require": {
@@ -59,7 +59,7 @@
],
"support": {
"issues": "https://github.com/composer/pcre/issues",
"source": "https://github.com/composer/pcre/tree/3.1.1"
"source": "https://github.com/composer/pcre/tree/3.1.3"
},
"funding": [
{
@@ -75,7 +75,7 @@
"type": "tidelift"
}
],
"time": "2023-10-11T07:11:09+00:00"
"time": "2024-03-19T10:26:25+00:00"
},
{
"name": "composer/semver",
@@ -160,16 +160,16 @@
},
{
"name": "composer/xdebug-handler",
"version": "3.0.3",
"version": "3.0.4",
"source": {
"type": "git",
"url": "https://github.com/composer/xdebug-handler.git",
"reference": "ced299686f41dce890debac69273b47ffe98a40c"
"reference": "4f988f8fdf580d53bdb2d1278fe93d1ed5462255"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c",
"reference": "ced299686f41dce890debac69273b47ffe98a40c",
"url": "https://api.github.com/repos/composer/xdebug-handler/zipball/4f988f8fdf580d53bdb2d1278fe93d1ed5462255",
"reference": "4f988f8fdf580d53bdb2d1278fe93d1ed5462255",
"shasum": ""
},
"require": {
@@ -180,7 +180,7 @@
"require-dev": {
"phpstan/phpstan": "^1.0",
"phpstan/phpstan-strict-rules": "^1.1",
"symfony/phpunit-bridge": "^6.0"
"phpunit/phpunit": "^8.5 || ^9.6 || ^10.5"
},
"type": "library",
"autoload": {
@@ -204,9 +204,9 @@
"performance"
],
"support": {
"irc": "irc://irc.freenode.org/composer",
"irc": "ircs://irc.libera.chat:6697/composer",
"issues": "https://github.com/composer/xdebug-handler/issues",
"source": "https://github.com/composer/xdebug-handler/tree/3.0.3"
"source": "https://github.com/composer/xdebug-handler/tree/3.0.4"
},
"funding": [
{
@@ -222,20 +222,20 @@
"type": "tidelift"
}
],
"time": "2022-02-25T21:32:43+00:00"
"time": "2024-03-26T18:29:49+00:00"
},
{
"name": "friendsofphp/php-cs-fixer",
"version": "v3.51.0",
"version": "v3.52.1",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "127fa74f010da99053e3f5b62672615b72dd6efd"
"reference": "6e77207f0d851862ceeb6da63e6e22c01b1587bc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/127fa74f010da99053e3f5b62672615b72dd6efd",
"reference": "127fa74f010da99053e3f5b62672615b72dd6efd",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/6e77207f0d851862ceeb6da63e6e22c01b1587bc",
"reference": "6e77207f0d851862ceeb6da63e6e22c01b1587bc",
"shasum": ""
},
"require": {
@@ -306,7 +306,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.51.0"
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.52.1"
},
"funding": [
{
@@ -314,7 +314,7 @@
"type": "github"
}
],
"time": "2024-02-28T19:50:06+00:00"
"time": "2024-03-19T21:02:43+00:00"
},
{
"name": "psr/container",
@@ -538,16 +538,16 @@
},
{
"name": "symfony/console",
"version": "v7.0.4",
"version": "v7.0.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "6b099f3306f7c9c2d2786ed736d0026b2903205f"
"reference": "fde915cd8e7eb99b3d531d3d5c09531429c3f9e5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/6b099f3306f7c9c2d2786ed736d0026b2903205f",
"reference": "6b099f3306f7c9c2d2786ed736d0026b2903205f",
"url": "https://api.github.com/repos/symfony/console/zipball/fde915cd8e7eb99b3d531d3d5c09531429c3f9e5",
"reference": "fde915cd8e7eb99b3d531d3d5c09531429c3f9e5",
"shasum": ""
},
"require": {
@@ -611,7 +611,7 @@
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v7.0.4"
"source": "https://github.com/symfony/console/tree/v7.0.6"
},
"funding": [
{
@@ -627,7 +627,7 @@
"type": "tidelift"
}
],
"time": "2024-02-22T20:27:20+00:00"
"time": "2024-04-01T11:04:53+00:00"
},
{
"name": "symfony/deprecation-contracts",
@@ -778,16 +778,16 @@
},
{
"name": "symfony/event-dispatcher-contracts",
"version": "v3.4.0",
"version": "v3.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher-contracts.git",
"reference": "a76aed96a42d2b521153fb382d418e30d18b59df"
"reference": "4e64b49bf370ade88e567de29465762e316e4224"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/a76aed96a42d2b521153fb382d418e30d18b59df",
"reference": "a76aed96a42d2b521153fb382d418e30d18b59df",
"url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/4e64b49bf370ade88e567de29465762e316e4224",
"reference": "4e64b49bf370ade88e567de29465762e316e4224",
"shasum": ""
},
"require": {
@@ -834,7 +834,7 @@
"standards"
],
"support": {
"source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.4.0"
"source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.4.2"
},
"funding": [
{
@@ -850,20 +850,20 @@
"type": "tidelift"
}
],
"time": "2023-05-23T14:45:45+00:00"
"time": "2024-01-23T14:51:35+00:00"
},
{
"name": "symfony/filesystem",
"version": "v7.0.3",
"version": "v7.0.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "2890e3a825bc0c0558526c04499c13f83e1b6b12"
"reference": "408105dff4c104454100730bdfd1a9cdd993f04d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/2890e3a825bc0c0558526c04499c13f83e1b6b12",
"reference": "2890e3a825bc0c0558526c04499c13f83e1b6b12",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/408105dff4c104454100730bdfd1a9cdd993f04d",
"reference": "408105dff4c104454100730bdfd1a9cdd993f04d",
"shasum": ""
},
"require": {
@@ -897,7 +897,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/filesystem/tree/v7.0.3"
"source": "https://github.com/symfony/filesystem/tree/v7.0.6"
},
"funding": [
{
@@ -913,7 +913,7 @@
"type": "tidelift"
}
],
"time": "2024-01-23T15:02:46+00:00"
"time": "2024-03-21T19:37:36+00:00"
},
{
"name": "symfony/finder",
@@ -1583,16 +1583,16 @@
},
{
"name": "symfony/service-contracts",
"version": "v3.4.1",
"version": "v3.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
"reference": "fe07cbc8d837f60caf7018068e350cc5163681a0"
"reference": "11bbf19a0fb7b36345861e85c5768844c552906e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0",
"reference": "fe07cbc8d837f60caf7018068e350cc5163681a0",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/11bbf19a0fb7b36345861e85c5768844c552906e",
"reference": "11bbf19a0fb7b36345861e85c5768844c552906e",
"shasum": ""
},
"require": {
@@ -1645,7 +1645,7 @@
"standards"
],
"support": {
"source": "https://github.com/symfony/service-contracts/tree/v3.4.1"
"source": "https://github.com/symfony/service-contracts/tree/v3.4.2"
},
"funding": [
{
@@ -1661,7 +1661,7 @@
"type": "tidelift"
}
],
"time": "2023-12-26T14:02:43+00:00"
"time": "2023-12-19T21:51:00+00:00"
},
{
"name": "symfony/stopwatch",

View File

@@ -9,16 +9,16 @@
"packages-dev": [
{
"name": "composer/pcre",
"version": "3.1.1",
"version": "3.1.3",
"source": {
"type": "git",
"url": "https://github.com/composer/pcre.git",
"reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9"
"reference": "5b16e25a5355f1f3afdfc2f954a0a80aec4826a8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/pcre/zipball/00104306927c7a0919b4ced2aaa6782c1e61a3c9",
"reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9",
"url": "https://api.github.com/repos/composer/pcre/zipball/5b16e25a5355f1f3afdfc2f954a0a80aec4826a8",
"reference": "5b16e25a5355f1f3afdfc2f954a0a80aec4826a8",
"shasum": ""
},
"require": {
@@ -60,7 +60,7 @@
],
"support": {
"issues": "https://github.com/composer/pcre/issues",
"source": "https://github.com/composer/pcre/tree/3.1.1"
"source": "https://github.com/composer/pcre/tree/3.1.3"
},
"funding": [
{
@@ -76,20 +76,20 @@
"type": "tidelift"
}
],
"time": "2023-10-11T07:11:09+00:00"
"time": "2024-03-19T10:26:25+00:00"
},
{
"name": "composer/xdebug-handler",
"version": "3.0.3",
"version": "3.0.4",
"source": {
"type": "git",
"url": "https://github.com/composer/xdebug-handler.git",
"reference": "ced299686f41dce890debac69273b47ffe98a40c"
"reference": "4f988f8fdf580d53bdb2d1278fe93d1ed5462255"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c",
"reference": "ced299686f41dce890debac69273b47ffe98a40c",
"url": "https://api.github.com/repos/composer/xdebug-handler/zipball/4f988f8fdf580d53bdb2d1278fe93d1ed5462255",
"reference": "4f988f8fdf580d53bdb2d1278fe93d1ed5462255",
"shasum": ""
},
"require": {
@@ -100,7 +100,7 @@
"require-dev": {
"phpstan/phpstan": "^1.0",
"phpstan/phpstan-strict-rules": "^1.1",
"symfony/phpunit-bridge": "^6.0"
"phpunit/phpunit": "^8.5 || ^9.6 || ^10.5"
},
"type": "library",
"autoload": {
@@ -124,9 +124,9 @@
"performance"
],
"support": {
"irc": "irc://irc.freenode.org/composer",
"irc": "ircs://irc.libera.chat:6697/composer",
"issues": "https://github.com/composer/xdebug-handler/issues",
"source": "https://github.com/composer/xdebug-handler/tree/3.0.3"
"source": "https://github.com/composer/xdebug-handler/tree/3.0.4"
},
"funding": [
{
@@ -142,7 +142,7 @@
"type": "tidelift"
}
],
"time": "2022-02-25T21:32:43+00:00"
"time": "2024-03-26T18:29:49+00:00"
},
{
"name": "pdepend/pdepend",

View File

@@ -19,9 +19,9 @@
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<ruleset name="pcsg-generated-ruleset"
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
name="pcsg-generated-ruleset"
xmlns="http://pmd.sf.net/ruleset/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
<description>Firefly III ruleset.</description>

View File

@@ -111,7 +111,10 @@ PGSQL_SSL_CERT=null
PGSQL_SSL_KEY=null
PGSQL_SSL_CRL_FILE=null
# more PostgreSQL settings
# For postgresql 15 and up, setting this to public will no longer work as expected, becasuse the
# 'public' schema is without grants. This can be worked around by having a super user grant those
# necessary privileges, but in security conscious setups that's not viable.
# You will need to set this to the schema you want to use.
PGSQL_SCHEMA=public
# If you're looking for performance improvements, you could install memcached or redis
@@ -184,6 +187,11 @@ SEND_REPORT_JOURNALS=true
# Since this involves an external service, it's optional and disabled by default.
ENABLE_EXTERNAL_MAP=false
#
# Enable or disable exchange rate conversion. This function isn't used yet by Firefly III
#
ENABLE_EXCHANGE_RATES=false
# Set this value to true if you want Firefly III to download currency exchange rates
# from the internet. These rates are hosted by the creator of Firefly III inside
# an Azure Storage Container.

2
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1,2 @@
# code owners for this Firefly III related repository
* @JC5 @SDx3

4
.github/funding.yml vendored
View File

@@ -1,4 +1,6 @@
# These are supported funding model platforms
# Firefly III sponsor options
github: jc5
patreon: JC5
ko_fi: jamesc5
liberapay: JC5

View File

@@ -1,13 +1,19 @@
<!--
Before you create a new PR, please consider:
Thank you for submitting new code to Firefly III, or any of the related projects. Please read the following rules carefully.
1) Pull requests for the MAIN branch will be closed.
2) DO NOT include translations in your PR. Only English US sentences.
- Do not submit solutions for problems that are not already reported in an issue
- Firefly III can't be your learning experience. If you're new to all of this, please go be new somewhere else
- Do not open PRs to "discuss" possible solutions or to "get feedback" on your code. I don't have time for that.
- Pull requests for the MAIN branch will be closed.
- DO NOT include translated strings in your PR.
Perhaps open an issue first, before you open a PR?
See also: https://docs.firefly-iii.org/explanation/support/#contributing-code
Thanks.
-->
Fixes issue # (if relevant)
This PR fixes issue # (if relevant).
Changes in this pull request:

58
.github/stale.yml vendored
View File

@@ -1,58 +0,0 @@
# Configuration for probot-stale - https://github.com/probot/stale
# Number of days of inactivity before an Issue or Pull Request becomes stale
daysUntilStale: 14
# Number of days of inactivity before a stale Issue or Pull Request is closed.
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
daysUntilClose: 14
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
# - "[Status] Maybe Later"
exemptLabels:
- enhancement
- feature
- bug
- announcement
- "layout-v3"
# Set to true to ignore issues in a project (defaults to false)
exemptProjects: false
# Set to true to ignore issues in a milestone (defaults to false)
exemptMilestones: false
# Label to use when marking as stale
staleLabel: stale
# Comment to post when marking as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when removing the stale label.
# unmarkComment: >
# Your comment here.
# Comment to post when closing a stale Issue or Pull Request.
# closeComment: >
# Your comment here.
# Limit the number of actions per hour, from 1-30. Default is 30
limitPerRun: 30
# Limit to only `issues` or `pulls`
# only: issues
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
# pulls:
# daysUntilStale: 30
# markComment: >
# This pull request has been automatically marked as stale because it has not had
# recent activity. It will be closed if no further activity occurs. Thank you
# for your contributions.
# issues:
# exemptLabels:
# - confirmed

View File

@@ -7,7 +7,7 @@ permissions:
on:
schedule:
- cron: '0 0 * * *'
- cron: '0 1 * * *'
workflow_dispatch:
jobs:
prune:

View File

@@ -3,7 +3,7 @@ name: "Issues - Command to close duplicate issues"
# the workflow to execute on is comments that are newly created
on:
issue_comment:
types: [created]
types: [ created ]
permissions:
issues: write

View File

@@ -3,9 +3,9 @@ name: 'Issues - Respond to hidden commands'
# the workflow to execute on is comments that are newly created
on:
issues:
types: [opened, edited]
types: [ opened, edited ]
issue_comment:
types: [created]
types: [ created ]
# permissions needed for reacting to IssueOps commands on issues and PRs
permissions:

View File

@@ -2,11 +2,11 @@ name: 'Issues - Reply to specific labels'
on:
issues:
types: [labeled, unlabeled]
types: [ labeled, unlabeled ]
pull_request_target:
types: [labeled, unlabeled]
types: [ labeled, unlabeled ]
discussion:
types: [labeled, unlabeled]
types: [ labeled, unlabeled ]
permissions:
contents: read

View File

@@ -3,17 +3,27 @@ name: 'Issues - Lock old issues'
on:
workflow_dispatch:
schedule:
- cron: '0 0 * * *'
- cron: '0 2 * * *'
concurrency:
group: lock-threads
permissions:
issues: write
pull-requests: write
discussions: write
jobs:
lock:
permissions:
issues: write
pull-requests: write
discussions: write
runs-on: ubuntu-latest
steps:
- uses: JC5/lock-threads@main
- uses: dessant/lock-threads@v5
with:
github-token: ${{ github.token }}
issue-inactive-days: 7
pr-inactive-days: 7
issue-inactive-days: 21
pr-inactive-days: 21
discussion-inactive-days: 21
log-output: true

View File

@@ -4,11 +4,11 @@ on:
workflow_dispatch:
inputs:
version:
description: 'Version to release'
description: 'Release "v1.2.3" or "develop"'
required: true
default: 'develop'
schedule:
- cron: '15 0 * * MON,THU'
- cron: '0 3 * * MON,THU'
jobs:
build:
@@ -51,7 +51,7 @@ jobs:
CROWDIN_TOKEN: ${{ secrets.CROWDIN_TOKEN }}
- name: Cleanup translations
id: cleanup-transactions
uses: JC5/firefly-iii-dev@v34
uses: JC5/firefly-iii-dev@v38
with:
action: 'ff3:crowdin-warning'
output: ''
@@ -60,7 +60,7 @@ jobs:
GH_TOKEN: ''
- name: Cleanup changelog
id: cleanup-changelog
uses: JC5/firefly-iii-dev@v34
uses: JC5/firefly-iii-dev@v38
with:
action: 'ff3:changelog'
output: ''
@@ -69,7 +69,7 @@ jobs:
GH_TOKEN: ${{ secrets.CHANGELOG_TOKEN }}
- name: Extract changelog
id: extract-changelog
uses: JC5/firefly-iii-dev@v34
uses: JC5/firefly-iii-dev@v38
with:
action: 'ff3:extract-changelog'
output: 'output'
@@ -78,7 +78,7 @@ jobs:
GH_TOKEN: ""
- name: Replace version
id: replace-version
uses: JC5/firefly-iii-dev@v34
uses: JC5/firefly-iii-dev@v38
with:
action: 'ff3:version'
output: ''
@@ -88,7 +88,7 @@ jobs:
FF_III_VERSION: ${{ github.event_name == 'schedule' && 'develop' || github.event.inputs.version }}
- name: Generate JSON v1
id: json-v1
uses: JC5/firefly-iii-dev@v34
uses: JC5/firefly-iii-dev@v38
with:
action: 'ff3:json-translations v1'
output: ''
@@ -97,7 +97,7 @@ jobs:
GH_TOKEN: ''
- name: Generate JSON v2
id: json-v2
uses: JC5/firefly-iii-dev@v34
uses: JC5/firefly-iii-dev@v38
with:
action: 'ff3:json-translations v2'
output: ''
@@ -106,26 +106,19 @@ jobs:
GH_TOKEN: ''
- name: Code cleanup
id: code-cleanup
uses: JC5/firefly-iii-dev@v34
uses: JC5/firefly-iii-dev@v38
with:
action: 'ff3:code'
output: ''
env:
FIREFLY_III_ROOT: /github/workspace
GH_TOKEN: ''
- name: Build new JS
- name: Build JS
run: |
npm upgrade
npm run build
- name: Build old JS
id: old-js
uses: JC5/firefly-iii-dev@v34
with:
action: 'ff3:old-js'
output: ''
env:
FIREFLY_III_ROOT: /github/workspace
GH_TOKEN: ''
npm install
npm update
npm run prod --workspace=v1
npm run build --workspace=v2
- name: Run CI
run: |
rm -rf vendor composer.lock
@@ -135,15 +128,51 @@ jobs:
.ci/phpcs.sh
- name: Release
run: |
# do some configuration
sudo timedatectl set-timezone Europe/Amsterdam
git config user.name github-actions
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
git config advice.addIgnoredFile false
# set some variables
releaseName=$version
originalName=$version
zipName=FireflyIII-$version.zip
tarName=FireflyIII-$version.tar.gz
# update composer (again)
composer validate --strict
composer update --no-dev --no-scripts --no-plugins
composer dump-autoload
# if this is a develop build, slightly different variable names.
if [[ "develop" == "$version" ]]; then
[[ -z $(git status --untracked-files=normal --porcelain) ]] && echo "this branch is clean, no need to push..." && exit 0;
releaseName=$version-$(date +'%Y%m%d')
originalName=$releaseName
zipName=FireflyIII-develop.zip
tarName=FireflyIII-develop.tar.gz
fi
# in both cases, if the release or tag already exists, add ".1" until it no longer exists.
tagFound=true
tagCount=1
while [ "$tagFound" = true ]
do
if [ $(git tag -l "$releaseName") ]; then
echo "Tag $releaseName exists already."
releaseName="$originalName"."$tagCount"
echo "Tag for release is now $releaseName"
tagCount=$((tagCount+1))
else
echo "Tag $releaseName does not exist, can continue"
tagFound=false
fi
done
echo "Will use tag and release name $releaseName."
# add all content, except output.txt (this contains the changelog and/or the download instructions)
echo 'Add all and reset output.txt'
git add -A
if test -f "output.txt"; then
git reset output.txt
@@ -151,19 +180,88 @@ jobs:
git commit -m "Auto commit for release '$version' on $(date +'%Y-%m-%d')" || true
git push
# zip and tar everything
echo 'Zip and tar...'
zip -rq $zipName . -x "*.git*" "*.ci*" "*.github*" "*node_modules*" "*output.txt*"
touch $tarName
tar --exclude=$tarName --exclude=$zipName --exclude='./.git' --exclude='./.ci' --exclude='./.github' --exclude='./node_modules' --exclude='./output.txt' -czf $tarName .
# add sha256 sum
echo 'Sha sum ...'
sha256sum -b $zipName > $zipName.sha256
sha256sum -b $tarName > $tarName.sha256
# create a development (nightly) release:
if [[ "develop" == "$version" ]]; then
echo "Create nightly release."
git tag -a $version-$(date +'%Y%m%d') -m "Nightly development release '$version' on $(date +'%Y-%m-%d')"
git push origin $version-$(date +'%Y%m%d')
gh release create $version-$(date +'%Y%m%d') -p --verify-tag \
-t "Development release for $(date +'%Y-%m-%d')" \
-n "Bi-weekly development release of Firefly III with the latest fixes, translations and features. This release was created on **$(date +'%Y-%m-%d')** and may contain bugs. Use at your own risk. Docker users can find this release under the \`develop\` tag."
else
echo "Create default release."
git tag -a $version -m "Here be changelog"
git push origin $version
gh release create $version -F output.txt -t "$version" --verify-tag
echo 'Develop release.'
# add text to output.txt (instructions)
rm output.txt
echo "Bi-weekly development release of Firefly III with the latest fixes, translations and features. Docker users can find this release under the \`develop\` tag." >> output.txt
echo "" >> output.txt
echo "This release was created on **$(date +'%Y-%m-%d')** and may contain unexpected bugs. Data loss is rare but is not impossible." >> output.txt
echo "" >> output.txt
echo "* Please read the installation instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/installation/docker/), [Portainer](https://docs.firefly-iii.org/how-to/firefly-iii/installation/portainer/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/installation/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/installation/self-managed/)" >> output.txt
echo "* Or read the upgrade instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/docker/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/self-managed/)" >> output.txt
echo "" >> output.txt
echo ":warning: Please be careful with this pre-release, as it may not work as expected." >> output.txt
# create the release:
echo "Create nightly release."
git tag -a $releaseName -m "Nightly development release '$version' on $(date +'%Y-%m-%d')"
git push origin $releaseName
gh release create $releaseName -p --verify-tag \
-t "Development release for $(date +'%Y-%m-%d')" \
-F output.txt
# add zip file to release.
gh release upload $releaseName $zipName
gh release upload $releaseName $tarName
# add sha256 sum to release
gh release upload $releaseName $zipName.sha256
gh release upload $releaseName $tarName.sha256
# get current HEAD and add as file to the release
HEAD=$(git rev-parse HEAD)
echo $HEAD > HEAD.txt
gh release upload $releaseName HEAD.txt
else
echo 'MAIN (real) release'
sudo chown -R runner:docker output.txt
# add text to output.txt (more instructions)
echo '' >> output.txt
echo '### Instructions' >> output.txt
echo '' >> output.txt
echo "* Installation instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/installation/docker/), [Portainer](https://docs.firefly-iii.org/how-to/firefly-iii/installation/portainer/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/installation/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/installation/self-managed/)" >> output.txt
echo "* Or read the upgrade instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/docker/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/self-managed/)" >> output.txt
echo "Create default release."
git tag -a $releaseName -m "Here be changelog"
git push origin $releaseName
gh release create $releaseName -F output.txt -t "$releaseName" --verify-tag
# add archive files to release
gh release upload $releaseName $zipName
gh release upload $releaseName $tarName
# add sha256 sums to release
gh release upload $releaseName $zipName.sha256
gh release upload $releaseName $tarName.sha256
# get current HEAD and add as file to the release
HEAD=$(git rev-parse HEAD)
echo $HEAD > HEAD.txt
gh release upload $releaseName HEAD.txt
# remove all temporary files
rm output.txt
rm HEAD.txt
rm $zipName
rm $zipName.sha256
rm $tarName
rm $tarName.sha256
# merge main back into develop
git checkout develop
git merge main
git push

View File

@@ -45,15 +45,6 @@ jobs:
- name: Install Composer dependencies
run: composer install --prefer-dist --no-interaction --no-progress --no-scripts
- name: PHPStan
run: .ci/phpstan.sh
- name: PHPMD
run: .ci/phpmd.sh
- name: PHP CS Fixer
run: .ci/phpcs.sh
- name: "Create database file"
run: touch storage/database/database.sqlite

View File

@@ -1,7 +1,7 @@
name: "Issues - Mark and close stale issues"
on:
schedule:
- cron: "30 1 * * *"
- cron: "0 4 * * *"
workflow_dispatch:
permissions:
@@ -17,17 +17,17 @@ jobs:
- uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: >
Hi there!
stale-issue-message: |
Hi there!
This is an automatic reply. `Share and enjoy`
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
Thank you for your contributions.
stale-pr-message: >
Hi there!
stale-pr-message: |
Hi there!
This is an automatic reply. `Share and enjoy`
This PR has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

11
.gitignore vendored
View File

@@ -7,3 +7,14 @@ yarn-error.log
.env
/.ci/php-cs-fixer/vendor
coverage.xml
# ignore generated files.
public/build
# ignore v1 build files
resources/assets/v1/node_modules
resources/assets/v1/build
# ignore v2 build files
resources/assets/v2/node_modules
resources/assets/v2/build

View File

@@ -83,17 +83,17 @@ class AccountController extends Controller
// user's preferences
$defaultSet = $this->repository->getAccountsByType([AccountType::ASSET])->pluck('id')->toArray();
/** @var Preference $frontPage */
$frontPage = app('preferences')->get('frontPageAccounts', $defaultSet);
/** @var Preference $frontpage */
$frontpage = app('preferences')->get('frontpageAccounts', $defaultSet);
$default = app('amount')->getDefaultCurrency();
if (!(is_array($frontPage->data) && count($frontPage->data) > 0)) {
$frontPage->data = $defaultSet;
$frontPage->save();
if (!(is_array($frontpage->data) && count($frontpage->data) > 0)) {
$frontpage->data = $defaultSet;
$frontpage->save();
}
// get accounts:
$accounts = $this->repository->getAccountsById($frontPage->data);
$accounts = $this->repository->getAccountsById($frontpage->data);
$chartData = [];
/** @var Account $account */

View File

@@ -0,0 +1,47 @@
<?php
/*
* ExpressionController.php
* Copyright (c) 2024 Michael Thomas
*
* 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\Models\Rule;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Models\Rule\ValidateExpressionRequest;
use Illuminate\Http\JsonResponse;
/**
* Class ExpressionController
*/
class ExpressionController extends Controller
{
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/rules/validateExpression
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function validateExpression(ValidateExpressionRequest $request): JsonResponse
{
return response()->json([
'valid' => true,
]);
}
}

View File

@@ -72,6 +72,11 @@ class UpdateController extends Controller
app('log')->debug('Now in update routine for transaction group!');
$data = $request->getAll();
// Fixes 8750.
foreach ($data['transactions'] as $index => $info) {
unset($data['transactions'][$index]['type']);
}
$transactionGroup = $this->groupRepository->update($transactionGroup, $data);
$manager = $this->getManager();

View File

@@ -281,7 +281,7 @@ class BasicController extends Controller
$spentInCurrency = $row['sum'];
$leftToSpend = bcadd($amount, $spentInCurrency);
$days = $today->diffInDays($end) + 1;
$days = (int)$today->diffInDays($end, true) + 1;
$perDay = '0';
if (0 !== $days && bccomp($leftToSpend, '0') > -1) {
$perDay = bcdiv($leftToSpend, (string)$days);

View File

@@ -46,7 +46,7 @@ class DateRequest extends FormRequest
{
$start = $this->getCarbonDate('start');
$end = $this->getCarbonDate('end');
if ($start->diffInYears($end) > 5) {
if ($start->diffInYears($end, true) > 5) {
throw new FireflyException('Date range out of range.');
}

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Models\Rule;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Rules\IsValidActionExpression;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\Support\Request\GetRuleConfiguration;
@@ -57,7 +58,6 @@ class StoreRequest extends FormRequest
'active' => ['active', 'boolean'],
];
$data = $this->getAllData($fields);
$data['triggers'] = $this->getRuleTriggers();
$data['actions'] = $this->getRuleActions();
@@ -123,7 +123,7 @@ class StoreRequest extends FormRequest
'triggers.*.stop_processing' => [new IsBoolean()],
'triggers.*.active' => [new IsBoolean()],
'actions.*.type' => 'required|in:'.implode(',', $validActions),
'actions.*.value' => 'required_if:actions.*.type,'.$contextActions.'|ruleActionValue',
'actions.*.value' => [sprintf('required_if:actions.*.type,%s', $contextActions), new IsValidActionExpression(), 'ruleActionValue'],
'actions.*.stop_processing' => [new IsBoolean()],
'actions.*.active' => [new IsBoolean()],
'strict' => [new IsBoolean()],

View File

@@ -54,17 +54,13 @@ class TestRequest extends FormRequest
private function getDate(string $field): ?Carbon
{
$value = $this->query($field);
$value = $this->query($field);
if (is_array($value)) {
return null;
}
$value = (string)$value;
$result = null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
if (false === $result) {
return null;
}
$value = (string)$value;
return $result;
return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
}
private function getAccounts(): array

View File

@@ -48,17 +48,13 @@ class TriggerRequest extends FormRequest
private function getDate(string $field): ?Carbon
{
$value = $this->query($field);
$value = $this->query($field);
if (is_array($value)) {
return null;
}
$value = (string)$value;
$result = null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
if (false === $result) {
return null;
}
$value = (string)$value;
return $result;
return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
}
private function getAccounts(): array

View File

@@ -25,6 +25,7 @@ namespace FireflyIII\Api\V1\Requests\Models\Rule;
use FireflyIII\Models\Rule;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Rules\IsValidActionExpression;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\Support\Request\GetRuleConfiguration;
@@ -140,7 +141,7 @@ class UpdateRequest extends FormRequest
'triggers.*.stop_processing' => [new IsBoolean()],
'triggers.*.active' => [new IsBoolean()],
'actions.*.type' => 'required|in:'.implode(',', $validActions),
'actions.*.value' => 'required_if:actions.*.type,'.$contextActions.'|ruleActionValue',
'actions.*.value' => [sprintf('required_if:actions.*.type,%s', $contextActions), new IsValidActionExpression(), 'ruleActionValue'],
'actions.*.stop_processing' => [new IsBoolean()],
'actions.*.active' => [new IsBoolean()],
'strict' => [new IsBoolean()],

View File

@@ -0,0 +1,42 @@
<?php
/**
* ValidateExpressionRequest.php
* Copyright (c) 2024 Michael Thomas
*
* 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\Requests\Models\Rule;
use FireflyIII\Rules\IsValidActionExpression;
use FireflyIII\Support\Request\ChecksLogin;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class ValidateExpressionRequest
*/
class ValidateExpressionRequest extends FormRequest
{
use ChecksLogin;
public function rules(): array
{
return ['expression' => ['required', new IsValidActionExpression()]];
}
}

View File

@@ -48,17 +48,13 @@ class TestRequest extends FormRequest
private function getDate(string $field): ?Carbon
{
$value = $this->query($field);
$value = $this->query($field);
if (is_array($value)) {
return null;
}
$value = (string)$value;
$result = null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
if (false === $result) {
return null;
}
$value = (string)$value;
return $result;
return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
}
private function getAccounts(): array

View File

@@ -48,17 +48,13 @@ class TriggerRequest extends FormRequest
private function getDate(string $field): ?Carbon
{
$value = $this->query($field);
$value = $this->query($field);
if (is_array($value)) {
return null;
}
$value = (string)$value;
$result = null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
if (false === $result) {
return null;
}
$value = (string)$value;
return $result;
return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
}
private function getAccounts(): array

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Api\V2\Controllers\Chart;
use Carbon\Carbon;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Chart\DashboardChartRequest;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
@@ -46,6 +47,7 @@ class AccountController extends Controller
use ValidatesUserGroupTrait;
private AccountRepositoryInterface $repository;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
public function __construct()
{
@@ -54,9 +56,7 @@ class AccountController extends Controller
function ($request, $next) {
$this->repository = app(AccountRepositoryInterface::class);
$userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) {
$this->repository->setUserGroup($userGroup);
}
$this->repository->setUserGroup($userGroup);
return $next($request);
}
@@ -98,14 +98,14 @@ class AccountController extends Controller
// user's preferences
if (0 === $accounts->count()) {
$defaultSet = $this->repository->getAccountsByType([AccountType::ASSET, AccountType::DEFAULT])->pluck('id')->toArray();
$frontPage = app('preferences')->get('frontPageAccounts', $defaultSet);
$frontpage = app('preferences')->get('frontpageAccounts', $defaultSet);
if (!(is_array($frontPage->data) && count($frontPage->data) > 0)) {
$frontPage->data = $defaultSet;
$frontPage->save();
if (!(is_array($frontpage->data) && count($frontpage->data) > 0)) {
$frontpage->data = $defaultSet;
$frontpage->save();
}
$accounts = $this->repository->getAccountsById($frontPage->data);
$accounts = $this->repository->getAccountsById($frontpage->data);
}
// both options are overruled by "preselected"

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Api\V2\Controllers;
use Carbon\Carbon;
use Carbon\Exceptions\InvalidDateException;
use Carbon\Exceptions\InvalidFormatException;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Transformers\V2\AbstractTransformer;
use Illuminate\Database\Eloquent\Model;
@@ -55,6 +56,7 @@ class Controller extends BaseController
protected const string CONTENT_TYPE = 'application/vnd.api+json';
protected ParameterBag $parameters;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
public function __construct()
{
@@ -158,7 +160,8 @@ class Controller extends BaseController
// the transformer, at this point, needs to collect information that ALL items in the collection
// require, like meta-data and stuff like that, and save it for later.
$transformer->collectMetaData($objects);
$objects = $transformer->collectMetaData($objects);
$paginator->setCollection($objects);
$resource = new FractalCollection($objects, $transformer, $key);
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));

View File

@@ -0,0 +1,104 @@
<?php
/*
* IndexController.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Model\Account;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Model\Account\IndexRequest;
use FireflyIII\Api\V2\Request\Model\Transaction\InfiniteListRequest;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface;
use FireflyIII\Transformers\V2\AccountTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator;
class IndexController extends Controller
{
public const string RESOURCE_KEY = 'accounts';
private AccountRepositoryInterface $repository;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY, UserRoleEnum::MANAGE_TRANSACTIONS];
/**
* AccountController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(AccountRepositoryInterface::class);
// new way of user group validation
$userGroup = $this->validateUserGroup($request);
$this->repository->setUserGroup($userGroup);
return $next($request);
}
);
}
/**
* TODO see autocomplete/accountcontroller for list.
*/
public function index(IndexRequest $request): JsonResponse
{
$this->repository->resetAccountOrder();
$types = $request->getAccountTypes();
$instructions = $request->getSortInstructions('accounts');
$accounts = $this->repository->getAccountsByType($types, $instructions);
$pageSize = $this->parameters->get('limit');
$count = $accounts->count();
$accounts = $accounts->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page'));
$transformer = new AccountTransformer();
$this->parameters->set('sort', $instructions);
$transformer->setParameters($this->parameters); // give params to transformer
return response()
->json($this->jsonApiList('accounts', $paginator, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
public function infiniteList(InfiniteListRequest $request): JsonResponse
{
$this->repository->resetAccountOrder();
// get accounts of the specified type, and return.
$types = $request->getAccountTypes();
// get from repository
$accounts = $this->repository->getAccountsInOrder($types, $request->getSortInstructions('accounts'), $request->getStartRow(), $request->getEndRow());
$total = $this->repository->countAccounts($types);
$count = $request->getEndRow() - $request->getStartRow();
$paginator = new LengthAwarePaginator($accounts, $total, $count, $this->parameters->get('page'));
$transformer = new AccountTransformer();
$transformer->setParameters($this->parameters); // give params to transformer
return response()
->json($this->jsonApiList(self::RESOURCE_KEY, $paginator, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
}

View File

@@ -25,7 +25,9 @@ declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Model\Account;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\Account;
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface;
use FireflyIII\Transformers\V2\AccountTransformer;
use Illuminate\Http\JsonResponse;
@@ -36,6 +38,29 @@ use Illuminate\Http\JsonResponse;
*/
class ShowController extends Controller
{
public const string RESOURCE_KEY = 'accounts';
private AccountRepositoryInterface $repository;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY, UserRoleEnum::MANAGE_TRANSACTIONS];
/**
* AccountController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(AccountRepositoryInterface::class);
// new way of user group validation
$userGroup = $this->validateUserGroup($request);
$this->repository->setUserGroup($userGroup);
return $next($request);
}
);
}
/**
* TODO this endpoint is not yet reachable.
*/

View File

@@ -0,0 +1,79 @@
<?php
/*
* UpdateController.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Model\Account;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Model\Account\UpdateRequest;
use FireflyIII\Models\Account;
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface;
use FireflyIII\Transformers\V2\AccountTransformer;
use Illuminate\Http\JsonResponse;
class UpdateController extends Controller
{
public const string RESOURCE_KEY = 'accounts';
private AccountRepositoryInterface $repository;
/**
* AccountController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(AccountRepositoryInterface::class);
// new way of user group validation
$userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) {
$this->repository->setUserGroup($userGroup);
}
return $next($request);
}
);
}
/**
* TODO this endpoint is not yet reachable.
*/
public function update(UpdateRequest $request, Account $account): JsonResponse
{
app('log')->debug(sprintf('Now in %s', __METHOD__));
$data = $request->getUpdateData();
$data['type'] = config('firefly.shortNamesByFullName.'.$account->accountType->type);
$account = $this->repository->update($account, $data);
$account->refresh();
app('preferences')->mark();
$transformer = new AccountTransformer();
$transformer->setParameters($this->parameters);
return response()
->api($this->jsonApiObject('accounts', $account, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
}

View File

@@ -77,13 +77,11 @@ class BasicController extends Controller
$this->opsRepository = app(OperationsRepositoryInterface::class);
$userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) {
$this->abRepository->setUserGroup($userGroup);
$this->accountRepository->setUserGroup($userGroup);
$this->billRepository->setUserGroup($userGroup);
$this->budgetRepository->setUserGroup($userGroup);
$this->opsRepository->setUserGroup($userGroup);
}
$this->abRepository->setUserGroup($userGroup);
$this->accountRepository->setUserGroup($userGroup);
$this->billRepository->setUserGroup($userGroup);
$this->budgetRepository->setUserGroup($userGroup);
$this->opsRepository->setUserGroup($userGroup);
return $next($request);
}
@@ -298,7 +296,7 @@ class BasicController extends Controller
app('log')->debug(sprintf('Amount left is %s', $left));
// how much left per day?
$days = $today->diffInDays($end) + 1;
$days = (int)$today->diffInDays($end, true) + 1;
$perDay = '0';
$perDayNative = '0';
if (0 !== $days && bccomp($left, '0') > -1) {

View File

@@ -35,6 +35,47 @@ use Illuminate\Http\JsonResponse;
*/
class TransactionController extends Controller
{
public function infiniteList(InfiniteListRequest $request): JsonResponse
{
// get sort instructions
$instructions = $request->getSortInstructions('transactions');
// collect transactions:
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setUserGroup(auth()->user()->userGroup)
->withAPIInformation()
->setStartRow($request->getStartRow())
->setEndRow($request->getEndRow())
->setTypes($request->getTransactionTypes())
->setSorting($instructions)
;
$start = $this->parameters->get('start');
$end = $this->parameters->get('end');
if (null !== $start) {
$collector->setStart($start);
}
if (null !== $end) {
$collector->setEnd($end);
}
$paginator = $collector->getPaginatedGroups();
$params = $request->buildParams();
$paginator->setPath(
sprintf(
'%s?%s',
route('api.v2.infinite.transactions.list'),
$params
)
);
return response()
->json($this->jsonApiList('transactions', $paginator, new TransactionGroupTransformer()))
->header('Content-Type', self::CONTENT_TYPE)
;
}
public function list(ListRequest $request): JsonResponse
{
// collect transactions:
@@ -75,45 +116,4 @@ class TransactionController extends Controller
->header('Content-Type', self::CONTENT_TYPE)
;
}
public function infiniteList(InfiniteListRequest $request): JsonResponse
{
// get sort instructions
$instructions = $request->getSortInstructions();
// collect transactions:
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setUserGroup(auth()->user()->userGroup)
->withAPIInformation()
->setStartRow($request->getStartRow())
->setEndRow($request->getEndRow())
->setTypes($request->getTransactionTypes())
->setSorting($instructions)
;
$start = $this->parameters->get('start');
$end = $this->parameters->get('end');
if (null !== $start) {
$collector->setStart($start);
}
if (null !== $end) {
$collector->setEnd($end);
}
$paginator = $collector->getPaginatedGroups();
$params = $request->buildParams();
$paginator->setPath(
sprintf(
'%s?%s',
route('api.v2.infinite.transactions.list'),
$params
)
);
return response()
->json($this->jsonApiList('transactions', $paginator, new TransactionGroupTransformer()))
->header('Content-Type', self::CONTENT_TYPE)
;
}
}

View File

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

View File

@@ -79,4 +79,12 @@ class UpdateController extends Controller
->header('Content-Type', self::CONTENT_TYPE)
;
}
public function useUserGroup(UserGroup $userGroup): JsonResponse
{
// group validation is already in place, so can just update the user.
$this->repository->useUserGroup($userGroup);
return response()->json([], 204);
}
}

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\Chart;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
@@ -39,6 +40,8 @@ class DashboardChartRequest extends FormRequest
use ConvertsDataTypes;
use ValidatesUserGroupTrait;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
/**
* Get all data from the request.
*/

View File

@@ -0,0 +1,69 @@
<?php
/*
* IndexRequest.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\Model\Account;
use Carbon\Carbon;
use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\Support\Request\GetSortInstructions;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class IndexRequest
*
* Lots of code stolen from the SingleDateRequest.
*/
class IndexRequest extends FormRequest
{
use AccountFilter;
use ChecksLogin;
use ConvertsDataTypes;
use GetSortInstructions;
public function getAccountTypes(): array
{
$type = (string)$this->get('type', 'default');
return $this->mapAccountTypes($type);
}
/**
* Get all data from the request.
*/
public function getDate(): Carbon
{
return $this->getCarbonDate('date');
}
/**
* The rules that the incoming request must be matched against.
*/
public function rules(): array
{
return [
'date' => 'date|after:1900-01-01|before:2099-12-31',
];
}
}

View File

@@ -0,0 +1,116 @@
<?php
/*
* UpdateRequest.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\Model\Account;
use FireflyIII\Models\Account;
use FireflyIII\Models\Location;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Rules\UniqueAccountNumber;
use FireflyIII\Rules\UniqueIban;
use FireflyIII\Support\Request\AppendsLocationData;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
class UpdateRequest extends FormRequest
{
use AppendsLocationData;
use ChecksLogin;
use ConvertsDataTypes;
/**
* TODO is a duplicate of the v1 update thing.
*/
public function getUpdateData(): array
{
$fields = [
'name' => ['name', 'convertString'],
'active' => ['active', 'boolean'],
'include_net_worth' => ['include_net_worth', 'boolean'],
'account_type_name' => ['type', 'convertString'],
'virtual_balance' => ['virtual_balance', 'convertString'],
'iban' => ['iban', 'convertString'],
'BIC' => ['bic', 'convertString'],
'account_number' => ['account_number', 'convertString'],
'account_role' => ['account_role', 'convertString'],
'liability_type' => ['liability_type', 'convertString'],
'opening_balance' => ['opening_balance', 'convertString'],
'opening_balance_date' => ['opening_balance_date', 'convertDateTime'],
'cc_type' => ['credit_card_type', 'convertString'],
'cc_monthly_payment_date' => ['monthly_payment_date', 'convertDateTime'],
'notes' => ['notes', 'stringWithNewlines'],
'interest' => ['interest', 'convertString'],
'interest_period' => ['interest_period', 'convertString'],
'order' => ['order', 'convertInteger'],
'currency_id' => ['currency_id', 'convertInteger'],
'currency_code' => ['currency_code', 'convertString'],
'liability_direction' => ['liability_direction', 'convertString'],
'liability_amount' => ['liability_amount', 'convertString'],
'liability_start_date' => ['liability_start_date', 'date'],
];
$data = $this->getAllData($fields);
return $this->appendLocationData($data, null);
}
/**
* TODO is a duplicate of the v1 UpdateRequest method.
*
* The rules that the incoming request must be matched against.
*/
public function rules(): array
{
/** @var Account $account */
$account = $this->route()->parameter('account');
$accountRoles = implode(',', config('firefly.accountRoles'));
$types = implode(',', array_keys(config('firefly.subTitlesByIdentifier')));
$ccPaymentTypes = implode(',', array_keys(config('firefly.ccTypes')));
$rules = [
'name' => sprintf('min:1|max:1024|uniqueAccountForUser:%d', $account->id),
'type' => sprintf('in:%s', $types),
'iban' => ['iban', 'nullable', new UniqueIban($account, $this->convertString('type'))],
'bic' => 'bic|nullable',
'account_number' => ['min:1', 'max:255', 'nullable', new UniqueAccountNumber($account, $this->convertString('type'))],
'opening_balance' => 'numeric|required_with:opening_balance_date|nullable',
'opening_balance_date' => 'date|required_with:opening_balance|nullable',
'virtual_balance' => 'numeric|nullable',
'order' => 'numeric|nullable',
'currency_id' => 'numeric|exists:transaction_currencies,id',
'currency_code' => 'min:3|max:51|exists:transaction_currencies,code',
'active' => [new IsBoolean()],
'include_net_worth' => [new IsBoolean()],
'account_role' => sprintf('in:%s|nullable|required_if:type,asset', $accountRoles),
'credit_card_type' => sprintf('in:%s|nullable|required_if:account_role,ccAsset', $ccPaymentTypes),
'monthly_payment_date' => 'date|nullable|required_if:account_role,ccAsset|required_if:credit_card_type,monthlyFull',
'liability_type' => 'required_if:type,liability|in:loan,debt,mortgage',
'liability_direction' => 'required_if:type,liability|in:credit,debit',
'interest' => 'required_if:type,liability|min:0|max:100|numeric',
'interest_period' => 'required_if:type,liability|in:daily,monthly,yearly',
'notes' => 'min:0|max:32768',
];
return Location::requestRules($rules);
}
}

View File

@@ -25,9 +25,11 @@ declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\Model\Transaction;
use Carbon\Carbon;
use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Support\Http\Api\TransactionFilter;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\Support\Request\GetSortInstructions;
use Illuminate\Foundation\Http\FormRequest;
/**
@@ -36,8 +38,10 @@ use Illuminate\Foundation\Http\FormRequest;
*/
class InfiniteListRequest extends FormRequest
{
use AccountFilter;
use ChecksLogin;
use ConvertsDataTypes;
use GetSortInstructions;
use TransactionFilter;
public function buildParams(): string
@@ -81,6 +85,13 @@ class InfiniteListRequest extends FormRequest
return $this->getCarbonDate('end');
}
public function getAccountTypes(): array
{
$type = (string)$this->get('type', 'default');
return $this->mapAccountTypes($type);
}
public function getPage(): int
{
$page = $this->convertInteger('page');
@@ -88,31 +99,6 @@ class InfiniteListRequest extends FormRequest
return 0 === $page || $page > 65536 ? 1 : $page;
}
public function getSortInstructions(): array
{
$allowed = config('firefly.sorting.allowed.transactions');
$set = $this->get('sorting', []);
$result = [];
if (0 === count($set)) {
return [];
}
foreach ($set as $info) {
$column = $info['column'] ?? 'NOPE';
$direction = $info['direction'] ?? 'NOPE';
if ('asc' !== $direction && 'desc' !== $direction) {
// skip invalid direction
continue;
}
if (false === in_array($column, $allowed, true)) {
// skip invalid column
continue;
}
$result[$column] = $direction;
}
return $result;
}
public function getTransactionTypes(): array
{
$type = (string)$this->get('type', 'default');

View File

@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V2\Request\UserGroup;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\UserGroup;
use FireflyIII\Rules\IsDefaultUserGroupName;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
@@ -53,7 +54,7 @@ class UpdateRequest extends FormRequest
$userGroup = $this->route()->parameter('userGroup');
return [
'title' => sprintf('required|min:1|max:255|unique:user_groups,title,%d', $userGroup->id),
'title' => ['required', 'min:1', 'max:255', sprintf('unique:user_groups,title,%d', $userGroup->id), new IsDefaultUserGroupName($userGroup)],
];
}
}

View File

@@ -73,6 +73,7 @@ class CorrectDatabase extends Command
// new!
'firefly-iii:unify-group-accounts',
'firefly-iii:trigger-credit-recalculation',
'firefly-iii:migrate-preferences',
];
foreach ($commands as $command) {
$this->friendlyLine(sprintf('Now executing command "%s"', $command));

View File

@@ -50,7 +50,7 @@ class FixFrontpageAccounts extends Command
/** @var User $user */
foreach ($users as $user) {
$preference = app('preferences')->getForUser($user, 'frontPageAccounts');
$preference = app('preferences')->getForUser($user, 'frontpageAccounts');
if (null !== $preference) {
$this->fixPreference($preference);
}
@@ -83,6 +83,6 @@ class FixFrontpageAccounts extends Command
}
}
}
app('preferences')->setForUser($preference->user, 'frontPageAccounts', $fixed);
app('preferences')->setForUser($preference->user, 'frontpageAccounts', $fixed);
}
}

View File

@@ -0,0 +1,66 @@
<?php
declare(strict_types=1);
/*
* MigratePreferences.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Models\Preference;
use FireflyIII\User;
use Illuminate\Console\Command;
use Symfony\Component\Console\Command\Command as CommandAlias;
class MigratePreferences extends Command
{
protected $description = 'Give Firefly III preferences a user group ID so they can be made administration specific.';
protected $signature = 'firefly-iii:migrate-preferences';
/**
* Execute the console command.
*/
public function handle(): int
{
$items = config('firefly.admin_specific_prefs');
$users = User::get();
/** @var User $user */
foreach ($users as $user) {
$count = 0;
foreach ($items as $item) {
$preference = Preference::where('name', $item)->where('user_id', $user->id)->first();
if (null === $preference) {
continue;
}
if (null !== $preference->user_group_id) {
$preference->user_group_id = $user->user_group_id;
$preference->save();
++$count;
}
}
if ($count > 0) {
$this->info(sprintf('Migrated %d preference(s) for user #%d ("%s").', $count, $user->id, $user->email));
}
}
return CommandAlias::SUCCESS;
}
}

View File

@@ -191,7 +191,7 @@ class ExportData extends Command
$this->friendlyError(sprintf('%s date "%s" must be formatted YYYY-MM-DD. Field will be ignored.', $field, $this->option('start')));
$error = true;
}
if (false === $date) {
if (null === $date) {
$this->friendlyError(sprintf('%s date "%s" must be formatted YYYY-MM-DD.', $field, $this->option('start')));
throw new FireflyException(sprintf('%s date "%s" must be formatted YYYY-MM-DD.', $field, $this->option('start')));

View File

@@ -80,7 +80,7 @@ class CreateGroupMemberships extends Command
// check if membership exists
$userGroup = UserGroup::where('title', $user->email)->first();
if (null === $userGroup) {
$userGroup = UserGroup::create(['title' => $user->email]);
$userGroup = UserGroup::create(['title' => $user->email, 'default_administration' => true]);
}
$userRole = UserRole::where('title', UserRoleEnum::OWNER->value)->first();

View File

@@ -53,40 +53,40 @@ class ForceDecimalSize extends Command
{
use ShowsFriendlyMessages;
protected $description = 'This command resizes DECIMAL columns in MySQL or PostgreSQL and correct amounts (only MySQL).';
protected $signature = 'firefly-iii:force-decimal-size';
protected $description = 'This command resizes DECIMAL columns in MySQL or PostgreSQL and correct amounts (only MySQL).';
protected $signature = 'firefly-iii:force-decimal-size';
private string $cast;
private array $classes
= [
'accounts' => Account::class,
'auto_budgets' => AutoBudget::class,
'available_budgets' => AvailableBudget::class,
'bills' => Bill::class,
'budget_limits' => BudgetLimit::class,
'piggy_bank_events' => PiggyBankEvent::class,
'piggy_bank_repetitions' => PiggyBankRepetition::class,
'piggy_banks' => PiggyBank::class,
'recurrences_transactions' => RecurrenceTransaction::class,
'transactions' => Transaction::class,
];
= [
'accounts' => Account::class,
'auto_budgets' => AutoBudget::class,
'available_budgets' => AvailableBudget::class,
'bills' => Bill::class,
'budget_limits' => BudgetLimit::class,
'piggy_bank_events' => PiggyBankEvent::class,
'piggy_bank_repetitions' => PiggyBankRepetition::class,
'piggy_banks' => PiggyBank::class,
'recurrences_transactions' => RecurrenceTransaction::class,
'transactions' => Transaction::class,
];
private string $operator;
private string $regularExpression;
private array $tables
= [
'accounts' => ['virtual_balance'],
'auto_budgets' => ['amount'],
'available_budgets' => ['amount'],
'bills' => ['amount_min', 'amount_max'],
'budget_limits' => ['amount'],
'currency_exchange_rates' => ['rate', 'user_rate'],
'limit_repetitions' => ['amount'],
'piggy_bank_events' => ['amount'],
'piggy_bank_repetitions' => ['currentamount'],
'piggy_banks' => ['targetamount'],
'recurrences_transactions' => ['amount', 'foreign_amount'],
'transactions' => ['amount', 'foreign_amount'],
];
= [
'accounts' => ['virtual_balance'],
'auto_budgets' => ['amount'],
'available_budgets' => ['amount'],
'bills' => ['amount_min', 'amount_max'],
'budget_limits' => ['amount'],
'currency_exchange_rates' => ['rate', 'user_rate'],
'limit_repetitions' => ['amount'],
'piggy_bank_events' => ['amount'],
'piggy_bank_repetitions' => ['currentamount'],
'piggy_banks' => ['targetamount'],
'recurrences_transactions' => ['amount', 'foreign_amount'],
'transactions' => ['amount', 'foreign_amount'],
];
/**
* Execute the console command.

View File

@@ -0,0 +1,54 @@
<?php
declare(strict_types=1);
/*
* LaravelPassportKeys.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
namespace FireflyIII\Console\Commands\System;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Artisan;
use Symfony\Component\Console\Command\Command as CommandAlias;
class LaravelPassportKeys extends Command
{
use ShowsFriendlyMessages;
protected $description = 'Calls the Laravel "passport:keys" but doesn\'t exit 1.';
protected $signature = 'firefly-iii:laravel-passport-keys';
/**
* Execute the console command.
*/
public function handle(): int
{
Artisan::call('passport:keys --no-interaction', []);
$result = Artisan::output();
if (str_contains($result, 'Encryption keys already exist')) {
$this->friendlyInfo('Encryption keys exist already.');
return CommandAlias::SUCCESS;
}
$this->friendlyPositive('Encryption keys have been created, nice!');
return CommandAlias::SUCCESS;
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
/*
* ApplyRules.php
* Copyright (c) 2020 james@firefly-iii.org
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@@ -16,7 +16,7 @@
* 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);
@@ -285,7 +285,7 @@ class ApplyRules extends Command
if (null !== $endString && '' !== $endString) {
$inputEnd = Carbon::createFromFormat('Y-m-d', $endString);
}
if (false === $inputEnd || false === $inputStart) {
if (null === $inputEnd || null === $inputStart) {
Log::error('Could not parse start or end date in verifyInputDate().');
return;

View File

@@ -1,8 +1,8 @@
<?php
/**
/*
* Cron.php
* Copyright (c) 2020 james@firefly-iii.org
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@@ -17,7 +17,7 @@
* 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);

View File

@@ -110,7 +110,7 @@ class AppendBudgetLimitPeriods extends Command
return 'daily';
}
// is weekly
if ('1' === $limit->start_date->format('N') && '7' === $limit->end_date->format('N') && 6 === $limit->end_date->diffInDays($limit->start_date)) {
if ('1' === $limit->start_date->format('N') && '7' === $limit->end_date->format('N') && 6 === (int)$limit->end_date->diffInDays($limit->start_date, true)) {
return 'weekly';
}
@@ -129,7 +129,7 @@ class AppendBudgetLimitPeriods extends Command
if (
in_array($limit->start_date->format('j-n'), $start, true) // start of quarter
&& in_array($limit->end_date->format('j-n'), $end, true) // end of quarter
&& 2 === $limit->start_date->diffInMonths($limit->end_date)
&& 2 === (int)$limit->start_date->diffInMonths($limit->end_date, true)
) {
return 'quarterly';
}
@@ -139,7 +139,7 @@ class AppendBudgetLimitPeriods extends Command
if (
in_array($limit->start_date->format('j-n'), $start, true) // start of quarter
&& in_array($limit->end_date->format('j-n'), $end, true) // end of quarter
&& 5 === $limit->start_date->diffInMonths($limit->end_date)
&& 5 === (int)$limit->start_date->diffInMonths($limit->end_date, true)
) {
return 'half_year';
}

View File

@@ -0,0 +1,182 @@
<?php
declare(strict_types=1);
/*
* MigrateRuleActions.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
namespace FireflyIII\Console\Commands\Upgrade;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Models\RuleAction;
use Illuminate\Console\Command;
class MigrateRuleActions extends Command
{
use ShowsFriendlyMessages;
public const string CONFIG_NAME = '610_migrate_rule_actions';
protected $description = 'Migrate rule actions away from expression engine';
protected $signature = 'firefly-iii:migrate-rule-actions {--F|force : Force the execution of this command.}';
/**
* Execute the console command.
*/
public function handle(): int
{
if ($this->isExecuted() && true !== $this->option('force')) {
$this->friendlyInfo('This command has already been executed.');
return 0;
}
if (false === config('firefly.feature_flags.expression_engine')) {
$this->friendlyInfo('Expression engine is not enabled. Nothing to do.');
return 0;
}
$this->replaceEqualSign();
$this->replaceObsoleteActions();
return 0;
}
private function isExecuted(): bool
{
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
if (null !== $configVar) {
return (bool)$configVar->data;
}
return false;
}
private function replaceEqualSign(): void
{
$count = 0;
$actions = RuleAction::get();
/** @var RuleAction $action */
foreach ($actions as $action) {
if (str_starts_with($action->action_value, '=')) {
$action->action_value = sprintf('%s%s', '\=', substr($action->action_value, 1));
$action->save();
++$count;
}
}
if ($count > 0) {
$this->friendlyInfo(sprintf('Upgrading %d rule action(s) for the new expression engine.', $count));
}
if (0 === $count) {
$this->friendlyInfo('All rule actions are up to date.');
}
}
private function replaceObsoleteActions(): void
{
$obsolete = [
'append_description',
'prepend_description',
'append_notes',
'prepend_notes',
'append_descr_to_notes',
'append_notes_to_descr',
'move_descr_to_notes',
'move_notes_to_descr',
];
$actions = RuleAction::whereIn('action_type', $obsolete)->get();
/** @var RuleAction $action */
foreach ($actions as $action) {
$oldType = $action->action_type;
switch ($action->action_type) {
default:
$this->friendlyError(sprintf('Cannot deal with action type "%s", skip it.', $action->action_type));
break;
case 'append_description':
$action->action_type = 'set_description';
$action->action_value = sprintf('=description~"%s"', str_replace('"', '\"', $action->action_value));
$action->save();
$this->friendlyInfo(sprintf('Upgraded action #%d from "%s" to "%s".', $action->id, $oldType, $action->action_type));
break;
case 'prepend_description':
$action->action_type = 'set_description';
$action->action_value = sprintf('="%s"~description', str_replace('"', '\"', $action->action_value));
$action->save();
$this->friendlyInfo(sprintf('Upgraded action #%d from "%s" to "%s".', $action->id, $oldType, $action->action_type));
break;
case 'append_notes':
$action->action_type = 'set_notes';
$action->action_value = sprintf('=notes~"%s"', str_replace('"', '\"', $action->action_value));
$action->save();
$this->friendlyInfo(sprintf('Upgraded action #%d from "%s" to "%s".', $action->id, $oldType, $action->action_type));
break;
case 'prepend_notes':
$action->action_type = 'set_notes';
$action->action_value = sprintf('="%s"~notes', str_replace('"', '\"', $action->action_value));
$action->save();
$this->friendlyInfo(sprintf('Upgraded action #%d from "%s" to "%s".', $action->id, $oldType, $action->action_type));
break;
case 'append_descr_to_notes':
$action->action_type = 'set_notes';
$action->action_value = '=notes~" "~description';
$action->save();
$this->friendlyInfo(sprintf('Upgraded action #%d from "%s" to "%s".', $action->id, $oldType, $action->action_type));
break;
case 'append_notes_to_descr':
$action->action_type = 'set_description';
$action->action_value = '=description~" "~notes';
$action->save();
$this->friendlyInfo(sprintf('Upgraded action #%d from "%s" to "%s".', $action->id, $oldType, $action->action_type));
break;
case 'move_descr_to_notes':
$action->action_type = 'set_notes';
$action->action_value = '=description';
$action->save();
$this->friendlyInfo(sprintf('Upgraded action #%d from "%s" to "%s".', $action->id, $oldType, $action->action_type));
break;
case 'move_notes_to_descr':
$action->action_type = 'set_description';
$action->action_value = '=notes';
$action->save();
$this->friendlyInfo(sprintf('Upgraded action #%d from "%s" to "%s".', $action->id, $oldType, $action->action_type));
break;
}
}
}
}

View File

@@ -63,11 +63,13 @@ class UpgradeDatabase extends Command
'firefly-iii:upgrade-liabilities',
'firefly-iii:liabilities-600',
'firefly-iii:budget-limit-periods',
'firefly-iii:migrate-rule-actions',
'firefly-iii:restore-oauth-keys',
// also just in case, some integrity commands:
'firefly-iii:create-group-memberships',
'firefly-iii:upgrade-group-information',
'firefly-iii:upgrade-currency-preferences',
'firefly-iii:correct-database',
];
$args = [];
if ($this->option('force')) {

View File

@@ -26,11 +26,11 @@ class UpgradeSkeleton extends Command
{
$start = microtime(true);
if ($this->isExecuted() && true !== $this->option('force')) {
$this->info('FRIENDLY This command has already been executed.');
$this->friendlyInfo('This command has already been executed.');
return 0;
}
$this->warn('Congrats, you found the skeleton command. Boo!');
$this->friendlyWarning('Congrats, you found the skeleton command. Boo!');
//$this->markAsExecuted();

View File

@@ -41,7 +41,6 @@ enum UserRoleEnum: string
// manage other financial objects:
case MANAGE_BUDGETS = 'mng_budgets';
case MANAGE_PIGGY_BANKS = 'mng_piggies';
case MANAGE_REPETITIONS = 'mng_reps';
case MANAGE_SUBSCRIPTIONS = 'mng_subscriptions';
case MANAGE_RULES = 'mng_rules';
case MANAGE_RECURRING = 'mng_recurring';
@@ -51,7 +50,7 @@ enum UserRoleEnum: string
// view and generate reports
case VIEW_REPORTS = 'view_reports';
// view memberships. needs FULL to manage them.
// view memberships AND roles. needs FULL to manage them.
case VIEW_MEMBERSHIPS = 'view_memberships';
// everything the creator can, except remove/change original creator and delete group

View File

@@ -117,6 +117,7 @@ class GracefulNotFoundHandler extends ExceptionHandler
return redirect(route('tags.index'));
case 'categories.show':
case 'categories.edit':
case 'categories.show.all':
$request->session()->reflash();

View File

@@ -25,6 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Exceptions;
use FireflyIII\Jobs\MailError;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Database\QueryException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
@@ -98,6 +99,13 @@ class Handler extends ExceptionHandler
return response()->json(['message' => 'Resource not found', 'exception' => 'NotFoundHttpException'], 404);
}
if ($e instanceof AuthorizationException && $expectsJson) {
// somehow Laravel handler does not catch this:
app('log')->debug('Return JSON unauthorized error.');
return response()->json(['message' => $e->getMessage(), 'exception' => 'AuthorizationException'], 401);
}
if ($e instanceof AuthenticationException && $expectsJson) {
// somehow Laravel handler does not catch this:
app('log')->debug('Return JSON unauthenticated error.');

View File

@@ -40,12 +40,12 @@ class ReportGeneratorFactory
{
$period = 'Month';
// more than two months date difference means year report.
if ($start->diffInMonths($end) > 1) {
if ($start->diffInMonths($end, true) > 1) {
$period = 'Year';
}
// more than one year date difference means multi year report.
if ($start->diffInMonths($end) > 12) {
// more than one year date difference means multi-year report.
if ($start->diffInMonths($end, true) > 12) {
$period = 'MultiYear';
}

View File

@@ -72,31 +72,6 @@ class StandardMessageGenerator implements MessageGeneratorInterface
$this->run();
}
public function getVersion(): int
{
return $this->version;
}
public function setObjects(Collection $objects): void
{
$this->objects = $objects;
}
public function setTrigger(int $trigger): void
{
$this->trigger = $trigger;
}
public function setUser(User $user): void
{
$this->user = $user;
}
public function setWebhooks(Collection $webhooks): void
{
$this->webhooks = $webhooks;
}
private function getWebhooks(): Collection
{
return $this->user->webhooks()->where('active', true)->where('trigger', $this->trigger)->get(['webhooks.*']);
@@ -206,6 +181,11 @@ class StandardMessageGenerator implements MessageGeneratorInterface
$this->storeMessage($webhook, $basicMessage);
}
public function getVersion(): int
{
return $this->version;
}
private function collectAccounts(TransactionGroup $transactionGroup): Collection
{
$accounts = new Collection();
@@ -232,4 +212,24 @@ class StandardMessageGenerator implements MessageGeneratorInterface
$webhookMessage->save();
app('log')->debug(sprintf('Stored new webhook message #%d', $webhookMessage->id));
}
public function setObjects(Collection $objects): void
{
$this->objects = $objects;
}
public function setTrigger(int $trigger): void
{
$this->trigger = $trigger;
}
public function setUser(User $user): void
{
$this->user = $user;
}
public function setWebhooks(Collection $webhooks): void
{
$this->webhooks = $webhooks;
}
}

View File

@@ -405,7 +405,7 @@ class UserEventHandler
}
// clean up old entries (6 months)
$carbon = Carbon::createFromFormat('Y-m-d H:i:s', $preference[$index]['time']);
if (false !== $carbon && $carbon->diffInMonths(today()) > 6) {
if (null !== $carbon && $carbon->diffInMonths(today(), true) > 6) {
app('log')->debug(sprintf('Entry for %s is very old, remove it.', $row['ip']));
unset($preference[$index]);
}

View File

@@ -236,7 +236,9 @@ class AttachmentHelper implements AttachmentHelperInterface
$fileObject->rewind();
if (0 === $file->getSize()) {
throw new FireflyException('Cannot upload empty or non-existent file.');
$this->errors->add('attachments', trans('validation.file_zero_length'));
return null;
}
$content = (string)$fileObject->fread($file->getSize());

View File

@@ -33,10 +33,11 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
*/
trait CollectorProperties
{
/** @var array<int, string> */
public array $sorting;
public const string TEST = 'Test';
private ?int $endRow;
/** @var array<int, string> */
public array $sorting;
private ?int $endRow;
private bool $expandGroupSearch;
private array $fields;
private bool $hasAccountInfo;
@@ -52,7 +53,7 @@ trait CollectorProperties
private ?int $page;
private array $postFilters;
private HasMany $query;
private ?int $startRow;
private ?int $startRow;
private array $stringFields;
/*
* This array is used to collect ALL tags the user may search for (using 'setTags').

View File

@@ -25,6 +25,7 @@ namespace FireflyIII\Helpers\Collector;
use Carbon\Carbon;
use Carbon\Exceptions\InvalidFormatException;
use Exception;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\Extensions\AccountCollection;
use FireflyIII\Helpers\Collector\Extensions\AmountCollection;
@@ -782,6 +783,35 @@ class GroupCollector implements GroupCollectorInterface
return $currentCollection;
}
#[\Override]
public function sortCollection(Collection $collection): Collection
{
/**
* @var string $field
* @var string $direction
*/
foreach ($this->sorting as $field => $direction) {
$func = 'ASC' === $direction ? 'sortBy' : 'sortByDesc';
$collection = $collection->{$func}(function (array $product, int $key) use ($field) { // @phpstan-ignore-line
// depends on $field:
if ('description' === $field) {
if (1 === count($product['transactions'])) {
return array_values($product['transactions'])[0][$field];
}
if (count($product['transactions']) > 1) {
return $product['title'];
}
return 'zzz';
}
exit('here we are');
});
}
return $collection;
}
/**
* Same as getGroups but everything is in a paginator.
*/
@@ -792,6 +822,7 @@ class GroupCollector implements GroupCollectorInterface
$this->setLimit(50);
}
if (null !== $this->startRow && null !== $this->endRow) {
/** @var int $total */
$total = $this->endRow - $this->startRow;
return new LengthAwarePaginator($set, $this->total, $total, 1);
@@ -931,6 +962,14 @@ class GroupCollector implements GroupCollectorInterface
return $this;
}
#[\Override]
public function setSorting(array $instructions): GroupCollectorInterface
{
$this->sorting = $instructions;
return $this;
}
public function setStartRow(int $startRow): self
{
$this->startRow = $startRow;
@@ -1091,41 +1130,4 @@ class GroupCollector implements GroupCollectorInterface
return $this;
}
#[\Override]
public function sortCollection(Collection $collection): Collection
{
/**
* @var string $field
* @var string $direction
*/
foreach ($this->sorting as $field => $direction) {
$func = 'ASC' === $direction ? 'sortBy' : 'sortByDesc';
$collection = $collection->{$func}(function (array $product, int $key) use ($field) { // @phpstan-ignore-line
// depends on $field:
if ('description' === $field) {
if (1 === count($product['transactions'])) {
return array_values($product['transactions'])[0][$field];
}
if (count($product['transactions']) > 1) {
return $product['title'];
}
return 'zzz';
}
exit('here we are');
});
}
return $collection;
}
#[\Override]
public function setSorting(array $instructions): GroupCollectorInterface
{
$this->sorting = $instructions;
return $this;
}
}

View File

@@ -285,13 +285,6 @@ interface GroupCollectorInterface
*/
public function getPaginatedGroups(): LengthAwarePaginator;
public function setSorting(array $instructions): self;
/**
* Sort the collection on a column.
*/
public function sortCollection(Collection $collection): Collection;
public function hasAnyTag(): self;
/**
@@ -560,6 +553,8 @@ interface GroupCollectorInterface
public function setSepaCT(string $sepaCT): self;
public function setSorting(array $instructions): self;
/**
* Set source accounts.
*/
@@ -620,6 +615,11 @@ interface GroupCollectorInterface
*/
public function setXorAccounts(Collection $accounts): self;
/**
* Sort the collection on a column.
*/
public function sortCollection(Collection $collection): Collection;
/**
* Automatically include all stuff required to make API calls work.
*/

View File

@@ -51,7 +51,7 @@ class NetWorth implements NetWorthInterface
private CurrencyRepositoryInterface $currencyRepos;
private User $user;
private ?UserGroup $userGroup;
private ?UserGroup $userGroup;
/**
* This method collects the user's net worth in ALL the user's currencies

View File

@@ -145,13 +145,13 @@ class CreateController extends Controller
Log::channel('audit')->info('Stored new account.', $data);
// update preferences if necessary:
$frontPage = app('preferences')->get('frontPageAccounts', [])->data;
if (!is_array($frontPage)) {
$frontPage = [];
$frontpage = app('preferences')->get('frontpageAccounts', [])->data;
if (!is_array($frontpage)) {
$frontpage = [];
}
if (AccountType::ASSET === $account->accountType->type) {
$frontPage[] = $account->id;
app('preferences')->set('frontPageAccounts', $frontPage);
$frontpage[] = $account->id;
app('preferences')->set('frontpageAccounts', $frontpage);
}
// store attachment(s):

View File

@@ -75,7 +75,7 @@ class ReconcileController extends Controller
*
* @throws FireflyException
* */
public function reconcile(Account $account, Carbon $start = null, Carbon $end = null)
public function reconcile(Account $account, ?Carbon $start = null, ?Carbon $end = null)
{
if (!$this->isEditableAccount($account)) {
return $this->redirectAccountToAccount($account);

View File

@@ -75,7 +75,7 @@ class ShowController extends Controller
*
* @throws FireflyException
* */
public function show(Request $request, Account $account, Carbon $start = null, Carbon $end = null)
public function show(Request $request, Account $account, ?Carbon $start = null, ?Carbon $end = null)
{
$objectType = config(sprintf('firefly.shortNamesByFullName.%s', $account->accountType->type));

View File

@@ -80,7 +80,18 @@ class LoginController extends Controller
Log::channel('audit')->info(sprintf('User is trying to login using "%s"', $request->get($this->username())));
app('log')->debug('User is trying to login.');
$this->validateLogin($request);
try {
$this->validateLogin($request);
} catch (ValidationException $e) {
return redirect(route('login'))
->withErrors(
[
$this->username => trans('auth.failed'),
]
)
->onlyInput($this->username)
;
}
app('log')->debug('Login data is present.');
// Copied directly from AuthenticatesUsers, but with logging added:
@@ -91,7 +102,6 @@ class LoginController extends Controller
Log::channel('audit')->warning(sprintf('Login for user "%s" was locked out.', $request->get($this->username())));
app('log')->error(sprintf('Login for user "%s" was locked out.', $request->get($this->username())));
$this->fireLockoutEvent($request);
$this->sendLockoutResponse($request);
}
// Copied directly from AuthenticatesUsers, but with logging added:

View File

@@ -128,7 +128,7 @@ class BudgetLimitController extends Controller
$start = Carbon::createFromFormat('Y-m-d', $request->get('start'));
$end = Carbon::createFromFormat('Y-m-d', $request->get('end'));
if (false === $start || false === $end) {
if (null === $start || null === $end) {
return response()->json([]);
}
@@ -235,12 +235,12 @@ class BudgetLimitController extends Controller
new Collection([$budgetLimit->budget]),
$budgetLimit->transactionCurrency
);
$daysLeft = $this->activeDaysLeft($limit->start_date, $limit->end_date);
$array['spent'] = $spentArr[$budgetLimit->transactionCurrency->id]['sum'] ?? '0';
$array['left_formatted'] = app('amount')->formatAnything($limit->transactionCurrency, bcadd($array['spent'], $array['amount']));
$array['amount_formatted'] = app('amount')->formatAnything($limit->transactionCurrency, $limit['amount']);
$array['days_left'] = (string)$this->activeDaysLeft($limit->start_date, $limit->end_date);
// left per day:
$array['left_per_day'] = bcdiv(bcadd($array['spent'], $array['amount']), $array['days_left']);
$array['days_left'] = (string)$daysLeft;
$array['left_per_day'] = 0 === $daysLeft ? bcadd($array['spent'], $array['amount']) : bcdiv(bcadd($array['spent'], $array['amount']), $array['days_left']);
// left per day formatted.
$array['amount'] = app('steam')->bcround($limit['amount'], $limit->transactionCurrency->decimal_places);

View File

@@ -85,7 +85,7 @@ class IndexController extends Controller
*
* @throws FireflyException
* */
public function index(Carbon $start = null, Carbon $end = null)
public function index(?Carbon $start = null, ?Carbon $end = null)
{
$this->abRepository->cleanup();
app('log')->debug(sprintf('Start of IndexController::index("%s", "%s")', $start?->format('Y-m-d'), $end?->format('Y-m-d')));

View File

@@ -75,7 +75,7 @@ class ShowController extends Controller
*
* @throws FireflyException
*/
public function noBudget(Request $request, Carbon $start = null, Carbon $end = null)
public function noBudget(Request $request, ?Carbon $start = null, ?Carbon $end = null)
{
// @var Carbon $start
$start ??= session('start');

View File

@@ -70,7 +70,7 @@ class NoCategoryController extends Controller
*
* @throws FireflyException
*/
public function show(Request $request, Carbon $start = null, Carbon $end = null)
public function show(Request $request, ?Carbon $start = null, ?Carbon $end = null)
{
app('log')->debug('Start of noCategory()');
// @var Carbon $start

View File

@@ -71,7 +71,7 @@ class ShowController extends Controller
*
* @throws FireflyException
*/
public function show(Request $request, Category $category, Carbon $start = null, Carbon $end = null)
public function show(Request $request, Category $category, ?Carbon $start = null, ?Carbon $end = null)
{
// @var Carbon $start
$start ??= session('start', today(config('app.timezone'))->startOfMonth());

View File

@@ -301,14 +301,14 @@ class AccountController extends Controller
$end = clone session('end', today(config('app.timezone'))->endOfMonth());
$defaultSet = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET])->pluck('id')->toArray();
app('log')->debug('Default set is ', $defaultSet);
$frontPage = app('preferences')->get('frontPageAccounts', $defaultSet);
$frontPageArray = !is_array($frontPage->data) ? [] : $frontPage->data;
app('log')->debug('Frontpage preference set is ', $frontPageArray);
if (0 === count($frontPageArray)) {
app('preferences')->set('frontPageAccounts', $defaultSet);
$frontpage = app('preferences')->get('frontpageAccounts', $defaultSet);
$frontpageArray = !is_array($frontpage->data) ? [] : $frontpage->data;
app('log')->debug('Frontpage preference set is ', $frontpageArray);
if (0 === count($frontpageArray)) {
app('preferences')->set('frontpageAccounts', $defaultSet);
app('log')->debug('frontpage set is empty!');
}
$accounts = $repository->getAccountsById($frontPageArray);
$accounts = $repository->getAccountsById($frontpageArray);
return response()->json($this->accountBalanceChart($accounts, $start, $end));
}

View File

@@ -116,8 +116,8 @@ class CategoryController extends Controller
return response()->json($cache->get());
}
$frontPageGenerator = new FrontpageChartGenerator($start, $end);
$chartData = $frontPageGenerator->generate();
$frontpageGenerator = new FrontpageChartGenerator($start, $end);
$chartData = $frontpageGenerator->generate();
$data = $this->generator->multiSet($chartData);
$cache->store($data);

View File

@@ -143,7 +143,7 @@ class ReportController extends Controller
$cache->addProperty($accounts);
$cache->addProperty($end);
if ($cache->has()) {
return response()->json($cache->get());
// return response()->json($cache->get());
}
app('log')->debug('Going to do operations for accounts ', $accounts->pluck('id')->toArray());
@@ -220,11 +220,14 @@ class ReportController extends Controller
$currentEnd = app('navigation')->endOfPeriod($currentEnd, $preferredRange);
}
while ($currentStart <= $currentEnd) {
$key = $currentStart->format($format);
$title = $currentStart->isoFormat($titleFormat);
$income['entries'][$title] = app('steam')->bcround($currency[$key]['earned'] ?? '0', $currency['currency_decimal_places']);
$expense['entries'][$title] = app('steam')->bcround($currency[$key]['spent'] ?? '0', $currency['currency_decimal_places']);
$currentStart = app('navigation')->addPeriod($currentStart, $preferredRange, 0);
$key = $currentStart->format($format);
$title = $currentStart->isoFormat($titleFormat);
// #8663 make sure the period exists in the data previously collected.
if (array_key_exists($key, $currency)) {
$income['entries'][$title] = app('steam')->bcround($currency[$key]['earned'] ?? '0', $currency['currency_decimal_places']);
$expense['entries'][$title] = app('steam')->bcround($currency[$key]['spent'] ?? '0', $currency['currency_decimal_places']);
}
$currentStart = app('navigation')->addPeriod($currentStart, $preferredRange, 0);
}
$chartData[] = $income;

View File

@@ -69,6 +69,11 @@ abstract class Controller extends BaseController
$authGuard = config('firefly.authentication_guard');
$logoutUrl = config('firefly.custom_logout_url');
// overrule v2 layout back to v1.
if ('true' === request()->get('force_default_layout') && 'v2' === config('firefly.layout')) {
app('view')->getFinder()->setPaths([realpath(base_path('resources/views'))]); // @phpstan-ignore-line
}
app('view')->share('authGuard', $authGuard);
app('view')->share('logoutUrl', $logoutUrl);

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers;
use Carbon\Carbon;
use Exception;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Middleware\IsDemoUser;
use FireflyIII\Models\AccountType;

View File

@@ -79,17 +79,17 @@ class HomeController extends Controller
app('log')->error(sprintf('End could not parse date string "%s" so ignore it.', $stringEnd));
$end = Carbon::now()->endOfMonth();
}
if (false === $start) {
if (null === $start) {
$start = Carbon::now()->startOfMonth();
}
if (false === $end) {
if (null === $end) {
$end = Carbon::now()->endOfMonth();
}
$label = $request->get('label');
$isCustomRange = false;
app('log')->debug('Received dateRange', ['start' => $stringStart, 'end' => $stringEnd, 'label' => $request->get('label')]);
app('log')->debug('dateRange: Received dateRange', ['start' => $stringStart, 'end' => $stringEnd, 'label' => $request->get('label')]);
// check if the label is "everything" or "Custom range" which will betray
// a possible problem with the budgets.
if ($label === (string)trans('firefly.everything') || $label === (string)trans('firefly.customRange')) {
@@ -97,10 +97,10 @@ class HomeController extends Controller
app('log')->debug('Range is now marked as "custom".');
}
$diff = $start->diffInDays($end) + 1;
$diff = $start->diffInDays($end, true) + 1;
if ($diff > 50) {
$request->session()->flash('warning', (string)trans('firefly.warning_much_data', ['days' => $diff]));
if ($diff > 366) {
$request->session()->flash('warning', (string)trans('firefly.warning_much_data', ['days' => (int)$diff]));
}
$request->session()->put('is_custom_range', $isCustomRange);
@@ -120,33 +120,45 @@ class HomeController extends Controller
*/
public function index(AccountRepositoryInterface $repository): mixed
{
$types = config('firefly.accountTypesByIdentifier.asset');
$count = $repository->count($types);
$types = config('firefly.accountTypesByIdentifier.asset');
$count = $repository->count($types);
Log::channel('audit')->info('User visits homepage.');
if (0 === $count) {
return redirect(route('new-user.index'));
}
if ('v1' === (string)config('view.layout')) {
return $this->indexV1($repository);
}
if ('v2' === (string)config('view.layout')) {
return $this->indexV2();
}
throw new FireflyException('Invalid layout configuration');
}
private function indexV1(AccountRepositoryInterface $repository): mixed
{
$types = config('firefly.accountTypesByIdentifier.asset');
$count = $repository->count($types);
$subTitle = (string)trans('firefly.welcome_back');
$transactions = [];
$frontPage = app('preferences')->getFresh('frontPageAccounts', $repository->getAccountsByType([AccountType::ASSET])->pluck('id')->toArray());
$frontPageArray = $frontPage->data;
if (!is_array($frontPageArray)) {
$frontPageArray = [];
$frontpage = app('preferences')->getFresh('frontpageAccounts', $repository->getAccountsByType([AccountType::ASSET])->pluck('id')->toArray());
$frontpageArray = $frontpage->data;
if (!is_array($frontpageArray)) {
$frontpageArray = [];
}
/** @var Carbon $start */
$start = session('start', today(config('app.timezone'))->startOfMonth());
/** @var Carbon $end */
$start = session('start', today(config('app.timezone'))->startOfMonth());
$end = session('end', today(config('app.timezone'))->endOfMonth());
$accounts = $repository->getAccountsById($frontPageArray);
$accounts = $repository->getAccountsById($frontpageArray);
$today = today(config('app.timezone'));
$accounts = $accounts->sortBy('order'); // sort frontpage accounts by order
// sort frontpage accounts by order
$accounts = $accounts->sortBy('order');
app('log')->debug('Frontpage accounts are ', $frontPageArray);
app('log')->debug('Frontpage accounts are ', $frontpageArray);
/** @var BillRepositoryInterface $billRepository */
$billRepository = app(BillRepositoryInterface::class);
@@ -166,4 +178,18 @@ class HomeController extends Controller
return view('index', compact('count', 'subTitle', 'transactions', 'billCount', 'start', 'end', 'today'));
}
private function indexV2(): mixed
{
$subTitle = (string)trans('firefly.welcome_back');
$start = session('start', today(config('app.timezone'))->startOfMonth());
$end = session('end', today(config('app.timezone'))->endOfMonth());
/** @var User $user */
$user = auth()->user();
event(new RequestedVersionCheckStatus($user));
return view('index', compact('subTitle', 'start', 'end'));
}
}

View File

@@ -113,7 +113,7 @@ class BoxController extends Controller
$spentAmount = $spent[$currency->id]['sum'] ?? '0';
app('log')->debug(sprintf('Spent for default currency for all budgets in this period: %s', $spentAmount));
$days = $today->between($start, $end) ? $today->diffInDays($start) + 1 : $end->diffInDays($start) + 1;
$days = (int)($today->between($start, $end) ? $today->diffInDays($start, true) + 1 : $end->diffInDays($start, true) + 1);
app('log')->debug(sprintf('Number of days left: %d', $days));
$spentPerDay = bcdiv($spentAmount, (string)$days);
app('log')->debug(sprintf('Available to spend per day: %s', $spentPerDay));
@@ -130,7 +130,7 @@ class BoxController extends Controller
$boxTitle = (string)trans('firefly.left_to_spend');
$activeDaysLeft = $this->activeDaysLeft($start, $end); // see method description.
$display = 1; // not overspent
$leftPerDayAmount = bcdiv($leftToSpendAmount, (string)$activeDaysLeft);
$leftPerDayAmount = 0 === $activeDaysLeft ? $leftToSpendAmount : bcdiv($leftToSpendAmount, (string)$activeDaysLeft);
app('log')->debug(sprintf('Left to spend per day is %s', $leftPerDayAmount));
}
}

View File

@@ -38,7 +38,7 @@ class IntroController extends Controller
/**
* Returns the introduction wizard for a page.
*/
public function getIntroSteps(string $route, string $specificPage = null): JsonResponse
public function getIntroSteps(string $route, ?string $specificPage = null): JsonResponse
{
app('log')->debug(sprintf('getIntroSteps for route "%s" and page "%s"', $route, $specificPage));
$specificPage ??= '';
@@ -91,7 +91,7 @@ class IntroController extends Controller
*
* @throws FireflyException
*/
public function postEnable(string $route, string $specialPage = null): JsonResponse
public function postEnable(string $route, ?string $specialPage = null): JsonResponse
{
$specialPage ??= '';
$route = str_replace('.', '_', $route);
@@ -111,7 +111,7 @@ class IntroController extends Controller
*
* @throws FireflyException
*/
public function postFinished(string $route, string $specialPage = null): JsonResponse
public function postFinished(string $route, ?string $specialPage = null): JsonResponse
{
$specialPage ??= '';
$key = 'shown_demo_'.$route;

View File

@@ -34,6 +34,7 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
/**
* Class ReconcileController
@@ -66,14 +67,13 @@ class ReconcileController extends Controller
*
* @throws FireflyException
*/
public function overview(Request $request, Account $account = null, Carbon $start = null, Carbon $end = null): JsonResponse
public function overview(Request $request, ?Account $account = null, ?Carbon $start = null, ?Carbon $end = null): JsonResponse
{
$startBalance = $request->get('startBalance');
$endBalance = $request->get('endBalance');
$accountCurrency = $this->accountRepos->getAccountCurrency($account) ?? app('amount')->getDefaultCurrency();
$amount = '0';
$clearedAmount = '0';
$route = '';
if (null === $start && null === $end) {
throw new FireflyException('Invalid dates submitted.');
@@ -103,14 +103,11 @@ class ReconcileController extends Controller
$clearedJournals = $collector->getExtractedJournals();
}
app('log')->debug('Start transaction loop');
/** @var array $journal */
foreach ($journals as $journal) {
$amount = $this->processJournal($account, $accountCurrency, $journal, $amount);
}
app('log')->debug(sprintf('Final amount is %s', $amount));
app('log')->debug('End transaction loop');
/** @var array $journal */
foreach ($clearedJournals as $journal) {
@@ -118,31 +115,17 @@ class ReconcileController extends Controller
$clearedAmount = $this->processJournal($account, $accountCurrency, $journal, $clearedAmount);
}
}
Log::debug(sprintf('Start balance: "%s"', $startBalance));
Log::debug(sprintf('End balance: "%s"', $endBalance));
Log::debug(sprintf('Cleared amount: "%s"', $clearedAmount));
Log::debug(sprintf('Amount: "%s"', $amount));
$difference = bcadd(bcadd(bcsub($startBalance, $endBalance), $clearedAmount), $amount);
$diffCompare = bccomp($difference, '0');
$countCleared = count($clearedJournals);
$reconSum = bcadd(bcadd($startBalance, $amount), $clearedAmount);
try {
$view = view(
'accounts.reconcile.overview',
compact(
'account',
'start',
'diffCompare',
'difference',
'end',
'clearedAmount',
'startBalance',
'endBalance',
'amount',
'route',
'countCleared',
'reconSum',
'selectedIds'
)
)->render();
$view = view('accounts.reconcile.overview', compact('account', 'start', 'diffCompare', 'difference', 'end', 'clearedAmount', 'startBalance', 'endBalance', 'amount', 'route', 'countCleared', 'reconSum', 'selectedIds'))->render();
} catch (\Throwable $e) {
app('log')->debug(sprintf('View error: %s', $e->getMessage()));
app('log')->error($e->getTraceAsString());
@@ -151,14 +134,42 @@ class ReconcileController extends Controller
throw new FireflyException($view, 0, $e);
}
$return = [
'post_url' => $route,
'html' => $view,
];
$return = ['post_url' => $route, 'html' => $view];
return response()->json($return);
}
private function processJournal(Account $account, TransactionCurrency $currency, array $journal, string $amount): string
{
$toAdd = '0';
app('log')->debug(sprintf('User submitted %s #%d: "%s"', $journal['transaction_type_type'], $journal['transaction_journal_id'], $journal['description']));
// not much magic below we need to cover using tests.
if ($account->id === $journal['source_account_id']) {
if ($currency->id === $journal['currency_id']) {
$toAdd = $journal['amount'];
}
if (null !== $journal['foreign_currency_id'] && $journal['foreign_currency_id'] === $currency->id) {
$toAdd = $journal['foreign_amount'];
}
}
if ($account->id === $journal['destination_account_id']) {
if ($currency->id === $journal['currency_id']) {
$toAdd = bcmul($journal['amount'], '-1');
}
if (null !== $journal['foreign_currency_id'] && $journal['foreign_currency_id'] === $currency->id) {
$toAdd = bcmul($journal['foreign_amount'], '-1');
}
}
app('log')->debug(sprintf('Going to add %s to %s', $toAdd, $amount));
$amount = bcadd($amount, $toAdd);
app('log')->debug(sprintf('Result is %s', $amount));
return $amount;
}
/**
* Returns a list of transactions in a modal.
*
@@ -166,7 +177,7 @@ class ReconcileController extends Controller
*
* @throws FireflyException
*/
public function transactions(Account $account, Carbon $start = null, Carbon $end = null)
public function transactions(Account $account, ?Carbon $start = null, ?Carbon $end = null)
{
if (null === $start || null === $end) {
throw new FireflyException('Invalid dates submitted.');
@@ -176,6 +187,7 @@ class ReconcileController extends Controller
}
$startDate = clone $start;
$startDate->subDay();
$end->endOfDay();
$currency = $this->accountRepos->getAccountCurrency($account) ?? app('amount')->getDefaultCurrency();
$startBalance = app('steam')->bcround(app('steam')->balance($account, $startDate), $currency->decimal_places);
@@ -214,37 +226,6 @@ class ReconcileController extends Controller
return response()->json(['html' => $html, 'startBalance' => $startBalance, 'endBalance' => $endBalance]);
}
private function processJournal(Account $account, TransactionCurrency $currency, array $journal, string $amount): string
{
$toAdd = '0';
app('log')->debug(sprintf('User submitted %s #%d: "%s"', $journal['transaction_type_type'], $journal['transaction_journal_id'], $journal['description']));
// not much magic below we need to cover using tests.
if ($account->id === $journal['source_account_id']) {
if ($currency->id === $journal['currency_id']) {
$toAdd = $journal['amount'];
}
if (null !== $journal['foreign_currency_id'] && $journal['foreign_currency_id'] === $currency->id) {
$toAdd = $journal['foreign_amount'];
}
}
if ($account->id === $journal['destination_account_id']) {
if ($currency->id === $journal['currency_id']) {
$toAdd = bcmul($journal['amount'], '-1');
}
if (null !== $journal['foreign_currency_id'] && $journal['foreign_currency_id'] === $currency->id) {
$toAdd = bcmul($journal['foreign_amount'], '-1');
}
}
app('log')->debug(sprintf('Going to add %s to %s', $toAdd, $amount));
$amount = bcadd($amount, $toAdd);
app('log')->debug(sprintf('Result is %s', $amount));
return $amount;
}
/**
* "fix" amounts to make it easier on the reconciliation overview:
*/

View File

@@ -81,7 +81,7 @@ class RecurrenceController extends Controller
$skip = $skip < 0 || $skip > 31 ? 0 : $skip;
$weekend = $weekend < 1 || $weekend > 4 ? 1 : $weekend;
if (false === $start || false === $end || false === $firstDate || false === $endDate) {
if (null === $start || null === $end || null === $firstDate || null === $endDate) {
return response()->json();
}
@@ -112,7 +112,7 @@ class RecurrenceController extends Controller
$actualEnd = clone $end;
if ('until_date' === $endsAt) {
$actualEnd = $endDate ?? clone $end;
$actualEnd = $endDate;
$occurrences = $this->recurring->getOccurrencesInRange($repetition, $actualStart, $actualEnd);
}
if ('times' === $endsAt) {
@@ -155,7 +155,7 @@ class RecurrenceController extends Controller
} catch (InvalidFormatException $e) {
$date = Carbon::today(config('app.timezone'));
}
if (false === $date) {
if (null === $date) {
return response()->json();
}
$date->startOfDay();

View File

@@ -115,7 +115,7 @@ class NewUserController extends Controller
// store frontpage preferences:
$accounts = $this->repository->getAccountsByType([AccountType::ASSET])->pluck('id')->toArray();
app('preferences')->set('frontPageAccounts', $accounts);
app('preferences')->set('frontpageAccounts', $accounts);
// mark.
app('preferences')->mark();

View File

@@ -89,10 +89,10 @@ class PreferencesController extends Controller
/** @var array<int, int> $accountIds */
$accountIds = $accounts->pluck('id')->toArray();
$viewRange = app('navigation')->getViewRange(false);
$frontPageAccountsPref = app('preferences')->get('frontPageAccounts', $accountIds);
$frontPageAccounts = $frontPageAccountsPref->data;
if (!is_array($frontPageAccounts)) {
$frontPageAccounts = $accountIds;
$frontpageAccountsPref = app('preferences')->get('frontpageAccounts', $accountIds);
$frontpageAccounts = $frontpageAccountsPref->data;
if (!is_array($frontpageAccounts)) {
$frontpageAccounts = $accountIds;
}
$language = app('steam')->getLanguage();
$languages = config('firefly.languages');
@@ -128,8 +128,8 @@ class PreferencesController extends Controller
$locales = ['equal' => (string)trans('firefly.equal_to_language')] + $locales;
// an important fallback is that the frontPageAccount array gets refilled automatically
// when it turns up empty.
if (0 === count($frontPageAccounts)) {
$frontPageAccounts = $accountIds;
if (0 === count($frontpageAccounts)) {
$frontpageAccounts = $accountIds;
}
// for the demo user, the slackUrl is automatically emptied.
@@ -139,7 +139,7 @@ class PreferencesController extends Controller
$slackUrl = '';
}
return view('preferences.index', compact('language', 'groupedAccounts', 'isDocker', 'frontPageAccounts', 'languages', 'darkMode', 'availableDarkModes', 'notifications', 'slackUrl', 'locales', 'locale', 'tjOptionalFields', 'viewRange', 'customFiscalYear', 'listPageSize', 'fiscalYearStart'));
return view('preferences.index', compact('language', 'groupedAccounts', 'isDocker', 'frontpageAccounts', 'languages', 'darkMode', 'availableDarkModes', 'notifications', 'slackUrl', 'locales', 'locale', 'tjOptionalFields', 'viewRange', 'customFiscalYear', 'listPageSize', 'fiscalYearStart'));
}
/**
@@ -155,12 +155,12 @@ class PreferencesController extends Controller
public function postIndex(Request $request)
{
// front page accounts
$frontPageAccounts = [];
if (is_array($request->get('frontPageAccounts')) && count($request->get('frontPageAccounts')) > 0) {
foreach ($request->get('frontPageAccounts') as $id) {
$frontPageAccounts[] = (int)$id;
$frontpageAccounts = [];
if (is_array($request->get('frontpageAccounts')) && count($request->get('frontpageAccounts')) > 0) {
foreach ($request->get('frontpageAccounts') as $id) {
$frontpageAccounts[] = (int)$id;
}
app('preferences')->set('frontPageAccounts', $frontPageAccounts);
app('preferences')->set('frontpageAccounts', $frontpageAccounts);
}
// extract notifications:
@@ -223,8 +223,8 @@ class PreferencesController extends Controller
// same for locale:
if (!auth()->user()->hasRole('demo')) {
/** @var Preference $locale */
$locale = $request->get('locale');
$locale = (string) $request->get('locale');
$locale = '' === $locale ? null : $locale;
app('preferences')->set('locale', $locale);
}

View File

@@ -23,7 +23,6 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers;
use Auth;
use FireflyIII\Events\UserChangedEmail;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Exceptions\ValidationException;
@@ -467,9 +466,7 @@ class ProfileController extends Controller
if (is_array($secret)) {
$secret = null;
}
if (is_int($secret)) {
$secret = (string)$secret;
}
$secret = (string)$secret;
$repository->setMFACode($user, $secret);

View File

@@ -76,7 +76,7 @@ class CreateController extends Controller
*
* @throws FireflyException
*/
public function create(Request $request, RuleGroup $ruleGroup = null)
public function create(Request $request, ?RuleGroup $ruleGroup = null)
{
$this->createDefaultRuleGroup();
$preFilled = [

View File

@@ -215,7 +215,7 @@ class TagController extends Controller
*
* @throws FireflyException
*/
public function show(Request $request, Tag $tag, Carbon $start = null, Carbon $end = null)
public function show(Request $request, Tag $tag, ?Carbon $start = null, ?Carbon $end = null)
{
// default values:
$subTitleIcon = 'fa-tag';
@@ -312,6 +312,9 @@ class TagController extends Controller
if (count($this->attachmentsHelper->getMessages()->get('attachments')) > 0) {
$request->session()->flash('info', $this->attachmentsHelper->getMessages()->get('attachments'));
}
if (count($this->attachmentsHelper->getErrors()->get('attachments')) > 0) {
$request->session()->flash('error', $this->attachmentsHelper->getErrors()->get('attachments'));
}
$redirect = redirect($this->getPreviousUrl('tags.create.url'));
if (1 === (int)$request->get('create_another')) {
session()->put('tags.create.fromStore', true);
@@ -347,6 +350,9 @@ class TagController extends Controller
if (count($this->attachmentsHelper->getMessages()->get('attachments')) > 0) {
$request->session()->flash('info', $this->attachmentsHelper->getMessages()->get('attachments'));
}
if (count($this->attachmentsHelper->getErrors()->get('attachments')) > 0) {
$request->session()->flash('error', $this->attachmentsHelper->getErrors()->get('attachments'));
}
$redirect = redirect($this->getPreviousUrl('tags.edit.url'));
if (1 === (int)$request->get('return_to_edit')) {
session()->put('tags.edit.fromUpdate', true);

View File

@@ -69,58 +69,51 @@ class IndexController extends Controller
*
* @throws FireflyException
*/
public function index(Request $request, string $objectType, Carbon $start = null, Carbon $end = null)
public function index(Request $request, string $objectType, ?Carbon $start = null, ?Carbon $end = null)
{
if ('transfers' === $objectType) {
$objectType = 'transfer';
}
// add a split for the (future) v2 release.
$periods = [];
$groups = [];
$subTitle = 'TODO page subtitle in v2';
$subTitleIcon = config('firefly.transactionIconsByType.'.$objectType);
$types = config('firefly.transactionTypesByType.'.$objectType);
$page = (int)$request->get('page');
$pageSize = (int)app('preferences')->get('listPageSize', 50)->data;
$subTitleIcon = config('firefly.transactionIconsByType.'.$objectType);
$types = config('firefly.transactionTypesByType.'.$objectType);
$page = (int)$request->get('page');
$pageSize = (int)app('preferences')->get('listPageSize', 50)->data;
if ('v2' !== (string)config('firefly.layout')) {
if (null === $start) {
$start = session('start');
$end = session('end');
}
if (null === $end) {
// get last transaction ever?
$last = $this->repository->getLast();
$end = null !== $last ? $last->date : session('end');
}
[$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
$startStr = $start->isoFormat($this->monthAndDayFormat);
$endStr = $end->isoFormat($this->monthAndDayFormat);
$subTitle = (string)trans(sprintf('firefly.title_%s_between', $objectType), ['start' => $startStr, 'end' => $endStr]);
$path = route('transactions.index', [$objectType, $start->format('Y-m-d'), $end->format('Y-m-d')]);
$firstJournal = $this->repository->firstNull();
$startPeriod = null === $firstJournal ? new Carbon() : $firstJournal->date;
$endPeriod = clone $end;
$periods = $this->getTransactionPeriodOverview($objectType, $startPeriod, $endPeriod);
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setRange($start, $end)
->setTypes($types)
->setLimit($pageSize)
->setPage($page)
->withBudgetInformation()
->withCategoryInformation()
->withAccountInformation()
->withAttachmentInformation()
;
$groups = $collector->getPaginatedGroups();
$groups->setPath($path);
if (null === $start) {
$start = session('start');
$end = session('end');
}
if (null === $end) {
// get last transaction ever?
$last = $this->repository->getLast();
$end = null !== $last ? $last->date : session('end');
}
[$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
$startStr = $start->isoFormat($this->monthAndDayFormat);
$endStr = $end->isoFormat($this->monthAndDayFormat);
$subTitle = (string)trans(sprintf('firefly.title_%s_between', $objectType), ['start' => $startStr, 'end' => $endStr]);
$path = route('transactions.index', [$objectType, $start->format('Y-m-d'), $end->format('Y-m-d')]);
$firstJournal = $this->repository->firstNull();
$startPeriod = null === $firstJournal ? new Carbon() : $firstJournal->date;
$endPeriod = clone $end;
$periods = $this->getTransactionPeriodOverview($objectType, $startPeriod, $endPeriod);
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setRange($start, $end)
->setTypes($types)
->setLimit($pageSize)
->setPage($page)
->withBudgetInformation()
->withCategoryInformation()
->withAccountInformation()
->withAttachmentInformation()
;
$groups = $collector->getPaginatedGroups();
$groups->setPath($path);
return view('transactions.index', compact('subTitle', 'objectType', 'subTitleIcon', 'groups', 'periods', 'start', 'end'));
}

View File

@@ -0,0 +1,45 @@
<?php
/*
* CreateController.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\UserGroup;
use FireflyIII\Http\Controllers\Controller;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Foundation\Application;
class CreateController extends Controller
{
/**
* @return Application|Factory|\Illuminate\Contracts\Foundation\Application|View
*/
public function create()
{
$title = (string)trans('firefly.administrations_page_title');
$subTitle = (string)trans('firefly.administrations_page_create_sub_title');
$mainTitleIcon = 'fa-book';
app('log')->debug(sprintf('Now at %s', __METHOD__));
return view('administrations.create')->with(compact('title', 'subTitle', 'mainTitleIcon'));
}
}

View File

@@ -0,0 +1,46 @@
<?php
/*
* CreateController.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\UserGroup;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\UserGroup;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Foundation\Application;
class EditController extends Controller
{
/**
* @return Application|Factory|\Illuminate\Contracts\Foundation\Application|View
*/
public function edit(UserGroup $userGroup)
{
$title = (string)trans('firefly.administrations_page_title');
$subTitle = (string)trans('firefly.administrations_page_edit_sub_title', ['title' => $userGroup->title]);
$mainTitleIcon = 'fa-book';
app('log')->debug(sprintf('Now at %s', __METHOD__));
return view('administrations.edit')->with(compact('title', 'subTitle', 'mainTitleIcon'));
}
}

View File

@@ -0,0 +1,47 @@
<?php
/*
* IndexController.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\UserGroup;
use FireflyIII\Http\Controllers\Controller;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\Request;
use Illuminate\View\View;
class IndexController extends Controller
{
/**
* Show all administrations.
*
* @return Factory|View
*/
public function index(Request $request)
{
$title = (string)trans('firefly.administrations_page_title');
$subTitle = (string)trans('firefly.administrations_page_sub_title');
$mainTitleIcon = 'fa-book';
app('log')->debug(sprintf('Now at %s', __METHOD__));
return view('administrations.index')->with(compact('title', 'subTitle', 'mainTitleIcon'));
}
}

View File

@@ -50,12 +50,12 @@ class SecureHeaders
$csp = [
"default-src 'none'",
"object-src 'none'",
sprintf("script-src 'unsafe-eval' 'strict-dynamic' 'self' 'unsafe-inline' 'nonce-%1s' %2s", $nonce, $trackingScriptSrc),
sprintf("script-src 'unsafe-eval' 'strict-dynamic' 'nonce-%1s'", $nonce),
"style-src 'unsafe-inline' 'self'",
"base-uri 'self'",
"font-src 'self' data:",
sprintf("connect-src 'self' %s", $trackingScriptSrc),
sprintf("img-src data: 'strict-dynamic' 'self' *.tile.openstreetmap.org %s", $trackingScriptSrc),
sprintf("img-src 'self' 'nonce-%1s'", $nonce),
"manifest-src 'self'",
];

View File

@@ -34,10 +34,10 @@ class TrustProxies extends Middleware
// After...
protected $headers
= Request::HEADER_X_FORWARDED_FOR |
Request::HEADER_X_FORWARDED_HOST |
Request::HEADER_X_FORWARDED_PORT |
Request::HEADER_X_FORWARDED_PROTO |
Request::HEADER_X_FORWARDED_AWS_ELB;
Request::HEADER_X_FORWARDED_HOST |
Request::HEADER_X_FORWARDED_PORT |
Request::HEADER_X_FORWARDED_PROTO |
Request::HEADER_X_FORWARDED_AWS_ELB;
/**
* TrustProxies constructor.

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Requests;
use FireflyIII\Models\Rule;
use FireflyIII\Rules\IsValidActionExpression;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\Support\Request\GetRuleConfiguration;
@@ -147,7 +148,7 @@ class RuleFormRequest extends FormRequest
'triggers.*.type' => 'required|in:'.implode(',', $validTriggers),
'triggers.*.value' => sprintf('required_if:triggers.*.type,%s|max:1024|min:1|ruleTriggerValue', $contextTriggers),
'actions.*.type' => 'required|in:'.implode(',', $validActions),
'actions.*.value' => sprintf('required_if:actions.*.type,%s|min:0|max:1024|ruleActionValue', $contextActions),
'actions.*.value' => [sprintf('required_if:actions.*.type,%s|min:0|max:1024', $contextActions), new IsValidActionExpression(), 'ruleActionValue'],
'strict' => 'in:0,1',
];

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