Compare commits

...

573 Commits
5.1.1 ... 5.3.2

Author SHA1 Message Date
James Cole
0ba03be9a3 Merge branch 'release/5.3.2' into main 2020-07-13 16:03:36 +02:00
James Cole
f2dcb108e8 Update meta files for new release. 2020-07-13 15:57:39 +02:00
James Cole
c0e5d6dd68 Update version. 2020-07-13 15:13:57 +02:00
James Cole
0b966ed541 Less verbose error logging for https://github.com/firefly-iii/firefly-iii/issues/3559 2020-07-13 15:03:19 +02:00
James Cole
8219b51e47 Skip error fix https://github.com/firefly-iii/firefly-iii/issues/3559 2020-07-13 14:22:00 +02:00
James Cole
9b102d1cf4 Merge tag '5.3.1' into develop
5.3.1
2020-07-12 20:25:23 +02:00
James Cole
ac607483aa Merge branch 'release/5.3.1' into main 2020-07-12 20:25:20 +02:00
James Cole
3ef46a59e9 Last-minute meta files. 2020-07-12 20:24:30 +02:00
James Cole
5529fa7124 Some last-minute translations, thanks guys! 2020-07-12 20:19:54 +02:00
James Cole
7a30bc4ff6 Updated meta for new release. 2020-07-12 19:48:24 +02:00
James Cole
8a9f6b1896 Double check on integers for https://github.com/firefly-iii/firefly-iii/issues/3554 2020-07-12 17:54:51 +02:00
James Cole
da77bcde04 Update version and API. 2020-07-12 17:34:06 +02:00
James Cole
c4979bdd27 Code for #3554 2020-07-12 17:32:48 +02:00
James Cole
0c9a25a073 Code cleanup and better auth check 2020-07-12 17:31:11 +02:00
James Cole
e24c2491a6 Expand frontend 2020-07-12 17:30:24 +02:00
James Cole
72a2718a93 Fix tests 2020-07-12 17:28:43 +02:00
James Cole
54d92f5b39 Code for #3546 2020-07-11 15:13:15 +02:00
James Cole
86600d4fcf Fix timezone issues. 2020-07-11 08:16:31 +02:00
James Cole
5cfe02edf6 Small textual changes 2020-07-11 07:18:51 +02:00
James Cole
22cb9dfbe0 make sure amount is a string. 2020-07-11 07:18:41 +02:00
James Cole
3782388e45 New security policy + release document. 2020-07-11 07:16:07 +02:00
James Cole
5821256590 Fix https://github.com/firefly-iii/firefly-iii/issues/3545 2020-07-11 07:01:29 +02:00
James Cole
14e06bfedd Experimental signed commit. 2020-07-10 06:48:39 +02:00
James Cole
886475740a Fix issue with profile functions. 2020-07-09 20:03:11 +02:00
James Cole
32e0a5bd80 Fix validation for #3532 2020-07-06 06:55:27 +02:00
James Cole
26d19fab32 Slightly more robust configuration polling. 2020-07-06 06:49:48 +02:00
James Cole
4271dc1638 Better frontend code and charts. 2020-07-05 21:03:35 +02:00
James Cole
a56cefda7d Basic new dashboard. 2020-07-05 18:29:58 +02:00
James Cole
4d4d91bf84 Merge branch 'main' into develop 2020-07-05 09:36:01 +02:00
James Cole
54dfb35007 Fix .env.example 2020-07-05 09:35:44 +02:00
James Cole
3893f59773 Fix some casting 2020-07-05 09:34:56 +02:00
James Cole
7d8786a620 Update changelog 2020-07-05 09:34:48 +02:00
James Cole
f48bc8d299 Budget and category charts in new layout. 2020-07-04 12:08:38 +02:00
James Cole
d33c87c565 Add error log for #3522 2020-07-03 18:41:16 +02:00
James Cole
5a28479788 Merge tag '5.3.0' into develop
5.3.0
2020-07-03 06:24:32 +02:00
James Cole
fabd7b1bfd Merge branch 'release/5.3.0' into main 2020-07-03 06:24:31 +02:00
James Cole
e57cd13145 Fix date in changelog 2020-07-03 06:23:54 +02:00
James Cole
515ee0a503 New version. 2020-07-03 06:22:57 +02:00
James Cole
cacbef4f75 Add PHP7.4 instructions. 2020-07-03 06:19:39 +02:00
James Cole
2772275e62 Update meta files before release. 2020-07-03 05:59:36 +02:00
James Cole
34fd66c835 Remove income from category chart #3517 2020-07-03 05:42:57 +02:00
James Cole
45f5a38512 Update meta files. 2020-07-02 20:23:45 +02:00
James Cole
6874d6469d Fix bill 2020-07-02 20:13:47 +02:00
James Cole
979c1ad305 Merge tag '5.3.0-beta.2' into develop
5.3.0-beta.2
2020-07-01 19:54:32 +02:00
James Cole
80de6c78dc Merge branch 'release/5.3.0-beta.2' into main 2020-07-01 19:54:31 +02:00
James Cole
5009cb5d55 New meta files. 2020-07-01 19:53:48 +02:00
James Cole
0c90171a49 Fix range for #3513 2020-07-01 19:47:32 +02:00
James Cole
d282cb4e34 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2020-07-01 19:47:20 +02:00
James Cole
976f79b5a6 Add account info for #3513 2020-07-01 19:43:53 +02:00
James Cole
6693a5166f Merge pull request #3506 from Johnny-Malizia/searchapi
Added transaction search api support
2020-07-01 19:35:44 +02:00
johnny
7b9906d493 Added transaction search api support
Transaction search api implemented using mostly the same process as the
existing search functionality.
Updated internal_reference and external_id search support to use exact
matches, expecting values in the database to be double quoted. This is
being done to ensure a specific transaction can be looked up at a later
time without prior knowledge of the internal transaction id.
2020-07-01 10:23:44 -07:00
James Cole
f927e61b37 Fix #3509 2020-07-01 15:46:26 +02:00
James Cole
430b498caf Fix meta files. 2020-07-01 15:45:09 +02:00
James Cole
983508e291 Expand API for bills. 2020-07-01 15:33:06 +02:00
James Cole
104a2379f3 Add fancy amounts. 2020-07-01 11:47:16 +02:00
James Cole
e337bcf8bd Can sort and group bills. 2020-07-01 06:33:21 +02:00
James Cole
029774687c Add command to fix inconsistent groups. 2020-07-01 06:02:58 +02:00
James Cole
be58545999 Make sure split transactions are always consistent. 2020-07-01 05:51:15 +02:00
James Cole
d774b4e2e3 Remove locale if using Docker. 2020-06-30 20:43:53 +02:00
James Cole
cb65999124 Expand API, add new migration. 2020-06-30 20:33:08 +02:00
James Cole
77e7af75dc Update translations and routes. 2020-06-30 19:10:17 +02:00
James Cole
714184867c Piggybank thing 2020-06-30 19:06:16 +02:00
James Cole
fad2331d80 Give bills groups too. 2020-06-30 19:06:05 +02:00
James Cole
bb5de8bf7e Update copyrights. 2020-06-30 19:05:35 +02:00
James Cole
6f78c96cee Fix piggy list. 2020-06-30 17:05:25 +02:00
James Cole
883342b2c8 Updated front matter 2020-06-29 08:04:38 +02:00
James Cole
6232858b85 Fix #3469 2020-06-29 06:44:17 +02:00
James Cole
4e4b44d41d Move to main branch. 2020-06-29 06:43:53 +02:00
James Cole
daf74e11ed Bigger max upload. 2020-06-28 15:30:59 +02:00
James Cole
3e2c2e6395 Merge tag '5.3.0-beta.1' into develop
5.3.0-beta.1
2020-06-28 09:25:31 +02:00
James Cole
bc5b2085b9 Merge branch 'release/5.3.0-beta.1' into main 2020-06-28 09:25:30 +02:00
James Cole
ebcd751145 Beta to changelog. 2020-06-28 09:25:19 +02:00
James Cole
cdfde3dca8 Update meta files for new release. 2020-06-28 09:19:18 +02:00
James Cole
4e3378451c Update readme. 2020-06-27 17:54:29 +02:00
James Cole
415fb7294c Fix sonarcloud issues 2020-06-27 17:33:18 +02:00
James Cole
1e35f0e7e3 You can logout other sessions. 2020-06-27 15:42:18 +02:00
James Cole
b83d06294d Drop Sandstorm related code. 2020-06-27 15:19:00 +02:00
James Cole
7945220825 Fix #3493 2020-06-27 13:41:27 +02:00
James Cole
3e8a4d55ef Make list grouped. 2020-06-27 13:32:40 +02:00
James Cole
e1fbdca5c1 Make list grouped. 2020-06-27 13:08:51 +02:00
James Cole
1b31d20877 Skip deleted piggies. 2020-06-27 09:56:38 +02:00
James Cole
aaaab03995 New translations 2020-06-26 08:35:59 +02:00
James Cole
affa8a317a Update packages 2020-06-26 07:30:29 +02:00
James Cole
5a03f3395c Fix #3440 2020-06-26 07:28:25 +02:00
James Cole
8da6ec3f5b Fix #3488 2020-06-26 04:04:54 +02:00
James Cole
a0402ac742 Fix text 2020-06-26 04:04:30 +02:00
James Cole
654e0fc74f Pretty basic fix #3490 2020-06-25 15:49:28 +02:00
James Cole
d3bd1f4124 Escape names to fix #3489 2020-06-25 13:37:44 +02:00
James Cole
2aa6067437 New strings. 2020-06-24 06:45:40 +02:00
James Cole
356c87da49 Fix #3427 2020-06-23 20:45:10 +02:00
James Cole
0d76fcd564 Fix #3398 2020-06-23 20:26:13 +02:00
James Cole
963c3b2a68 Fix #3391 2020-06-23 20:18:59 +02:00
James Cole
7617fe3510 Fix null pointer 2020-06-23 15:30:02 +02:00
James Cole
88724be3aa Fix mailer 2020-06-22 18:31:39 +02:00
James Cole
f845c97955 Merge tag '5.3.0-alpha.1' into develop
5.3.0-alpha.1
2020-06-22 18:18:02 +02:00
James Cole
2c69a2eda2 Merge branch 'release/5.3.0-alpha.1' 2020-06-22 18:17:59 +02:00
James Cole
dcce747e92 Mysql instructions. 2020-06-22 18:17:31 +02:00
James Cole
c251ca5daf Update meta files. 2020-06-22 18:08:23 +02:00
James Cole
bcb9794315 Update meta files. 2020-06-22 18:03:57 +02:00
James Cole
1a043e35c2 New meta files 2020-06-22 18:02:28 +02:00
James Cole
4fef316ddd Fix more date issues 2020-06-21 19:16:21 +02:00
James Cole
7196ac3ec9 Fix date issues. 2020-06-21 19:08:57 +02:00
James Cole
1c74db30ed More layout stuff 2020-06-21 18:29:23 +02:00
James Cole
00440f282b API for piggies + groups. 2020-06-21 18:28:51 +02:00
James Cole
dfe099f9c6 Emergency fix for #3479 2020-06-21 14:16:23 +02:00
James Cole
0dbee47182 Fix issue with null pointer 2020-06-20 22:16:03 +02:00
James Cole
46796a8c10 Logo 2020-06-20 19:14:28 +02:00
James Cole
c381067364 New code. 2020-06-20 19:14:06 +02:00
James Cole
19573de5df Fonts 2020-06-20 19:10:44 +02:00
James Cole
77359fbc55 Code for front page 2020-06-20 19:09:37 +02:00
James Cole
45eb758583 Fix list 2020-06-20 18:57:20 +02:00
James Cole
1a154a8d45 API for object groups. 2020-06-20 16:28:23 +02:00
James Cole
c40f6f2864 Add user id. 2020-06-20 10:23:57 +02:00
James Cole
c036c5a2bc Fix user management for groups. 2020-06-20 10:22:07 +02:00
James Cole
5b29e78c4b Group management code. 2020-06-20 10:10:55 +02:00
James Cole
b54ef9f5e5 Fix bad UUID generation. 2020-06-18 18:14:10 +02:00
James Cole
b7f48a19e8 Merge pull request #3467 from sephrat/days-left-for-bills
Fix #3437
2020-06-17 18:23:13 +00:00
James Cole
c8f1e4bbd7 Expand new layout code. 2020-06-17 07:06:45 +02:00
James Cole
5cc1369191 Expand debug. 2020-06-17 07:05:33 +02:00
Florian Dupret
16a511cf79 move 7c78708 logic from transformer to controller 2020-06-16 18:02:48 +02:00
Florian Dupret
7c78708865 Fix #3437 2020-06-16 14:07:40 +02:00
James Cole
0449430ec3 I messed up 2020-06-14 19:24:23 +02:00
James Cole
dd5a179ba1 More stuff for new layout. 2020-06-14 19:17:45 +02:00
James Cole
7c1139e42b First set of code for new layout based on AdminLTE 3.0 2020-06-14 15:51:20 +02:00
James Cole
caddf3d1c6 Fix #3461 2020-06-13 13:48:52 +02:00
James Cole
54d5778bf3 Add attachment to recurring. 2020-06-12 20:56:58 +02:00
James Cole
b1732d0de8 New possibilities for date range triggers #3403 2020-06-12 07:49:39 +02:00
James Cole
48b5f749a1 Fix logout for #3184 2020-06-11 17:55:38 +02:00
James Cole
a63b8322db Updates for #3184 2020-06-11 06:55:13 +02:00
James Cole
2130eef971 Update .env.example for #3184 2020-06-11 06:54:42 +02:00
James Cole
5b829b514f Include notes in export. 2020-06-09 17:40:09 +02:00
James Cole
1bac3258da Merge pull request #3455 from sephrat/debug_translation
Translate debug page
2020-06-09 15:18:17 +00:00
James Cole
d7181100ee Merge pull request #3454 from sephrat/translations
Translations tweaks
2020-06-09 15:17:30 +00:00
James Cole
ccc82858ad Fix drag/drop + sort 2020-06-09 17:16:21 +02:00
Florian Dupret
5dd6b23b09 Translate debug page 2020-06-09 13:51:01 +02:00
James Cole
6a08f52fa5 Update packages and order. 2020-06-09 11:09:23 +02:00
James Cole
18172b7fdb Fix order, fix bar. 2020-06-09 10:33:55 +02:00
James Cole
3eccc56c7a Better column 2020-06-09 08:48:28 +02:00
Florian Dupret
f7545af17a Missing translation on budgets index page 2020-06-09 08:37:40 +02:00
Florian Dupret
aa4da1e2e1 Telemetry count pluralization 2020-06-09 08:35:10 +02:00
James Cole
b4aafefc2b Fix NULL 2020-06-08 18:22:36 +02:00
James Cole
8304ee21f3 Fix #3450 2020-06-07 21:42:52 +02:00
James Cole
ca6479ede6 Update version. 2020-06-07 16:38:25 +02:00
James Cole
471cdefcff Organise object groups 2020-06-07 16:38:15 +02:00
James Cole
16b0307b0a Piggy bank can now have a group. 2020-06-07 11:31:01 +02:00
James Cole
2f63090e7c Split controller 2020-06-07 11:30:02 +02:00
James Cole
8643034945 Upgrade to 7.4 2020-06-06 22:25:52 +02:00
James Cole
6cc4d14fcb Remove import code. 2020-06-06 21:23:26 +02:00
James Cole
389ffa820f Merge branch 'release/5.2.8' 2020-06-06 12:19:11 +02:00
James Cole
60fa0d7244 Merge tag '5.2.8' into develop
5.2.8
2020-06-06 12:19:11 +02:00
James Cole
28d6885178 Update meta files for 5.2.8 2020-06-06 12:18:42 +02:00
James Cole
00f579909e Update meta files. 2020-06-06 12:16:32 +02:00
James Cole
a35bccb940 Fix #3443 2020-06-06 12:14:55 +02:00
James Cole
1cba62aa42 Cleanup changelog, forgot some unused entries. 2020-06-06 07:26:22 +02:00
James Cole
0974591a8f Merge tag '5.2.7' into develop
5.2.7
2020-06-06 07:18:38 +02:00
James Cole
326bef66ee Merge branch 'release/5.2.7' 2020-06-06 07:18:36 +02:00
James Cole
67ba8cee09 Updated meta files. 2020-06-06 07:15:56 +02:00
James Cole
08107f7103 Fix translations. 2020-06-06 07:09:27 +02:00
James Cole
f5c075936f Better generation of installation ID. 2020-06-06 06:57:44 +02:00
James Cole
d493820cc8 Migrate default env file to MySQL 2020-06-06 06:40:59 +02:00
James Cole
af4a006192 New translations. 2020-06-06 06:40:44 +02:00
James Cole
946e3fb540 New changelog. 2020-06-06 06:37:20 +02:00
James Cole
b19338e2f3 Add db connection info. 2020-06-06 06:34:43 +02:00
James Cole
d4a44e6089 Hold the DB changes for now. 2020-06-05 19:44:40 +02:00
James Cole
c90c181785 Basic code for an object group select item thing. 2020-06-05 19:39:09 +02:00
James Cole
b75178a184 New view for #3415 2020-06-05 18:40:02 +02:00
James Cole
a77187135f Fixed #3297 2020-06-05 06:34:55 +02:00
James Cole
61e24a41a2 Add groups, and the option for objects to be linked to one (or more) groups. #3128 2020-06-05 06:25:39 +02:00
James Cole
07c7bf1d49 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2020-06-04 18:08:53 +02:00
James Cole
d4cb72cb77 Updated strings. 2020-06-04 18:08:18 +02:00
James Cole
948cdf7e5e Merge pull request #3428 from sephrat/fix-reconcile-difference
Fix reconcile difference
2020-06-04 12:23:28 +02:00
Florian Dupret
e93292d98c Fix identation from 7105d34 2020-06-04 08:34:46 +02:00
Florian Dupret
7105d34fb3 Fix wrong reconciliation difference with "select all" button 2020-06-04 08:32:17 +02:00
James Cole
29847c9711 Updated strings. 2020-06-04 06:49:44 +02:00
James Cole
3db778a2b1 Fix #3425 2020-06-04 06:31:34 +02:00
James Cole
361f78542a Add time for #3419 2020-06-04 06:26:14 +02:00
James Cole
15d0e04431 Add timeout for #3427 2020-06-04 06:20:52 +02:00
James Cole
b968ef416a Fix #3419 2020-06-02 19:11:17 +02:00
James Cole
6191362fe0 Merge pull request #3420 from sephrat/fix#3409
Display account names only once when displaying split transactions
2020-06-02 17:59:52 +02:00
Florian Dupret
6d8fd79922 Fix #3409 - Split transactions show source/destination accounts several times 2020-06-01 17:51:07 +02:00
James Cole
0227879a69 Merge pull request #3417 from sephrat/pluralization
Fix typo from #3413
2020-06-01 11:41:49 +02:00
Florian Dupret
e4d2b121c1 Merge branch 'pluralization' of https://github.com/sephrat/firefly-iii into pluralization 2020-06-01 08:25:27 +02:00
Florian Dupret
f8941ab507 Fix string displayed twice 2020-06-01 08:15:19 +02:00
James Cole
f3ac8a5888 Add newlines and remove some unused translations. 2020-05-30 07:33:06 +02:00
James Cole
64ac3927ec Pluralization. 2020-05-29 21:00:10 +02:00
James Cole
a558613189 Merge pull request #3413 from sephrat/pluralization
String pluralization
2020-05-29 20:55:56 +02:00
James Cole
7535ca9a26 Merge branch 'develop' into pluralization 2020-05-29 20:55:31 +02:00
James Cole
03670e2dfe New translations. 2020-05-29 19:53:49 +02:00
Florian Dupret
be797f5353 pluralization wave 2 2020-05-29 19:07:51 +02:00
Florian Dupret
da38df6e4b pluralization wave 1 2020-05-29 18:00:29 +02:00
James Cole
2d53eb300a Some more info in changelog. 2020-05-29 16:08:31 +02:00
James Cole
523ea78166 Error strings. 2020-05-29 07:55:59 +02:00
James Cole
3b33730e48 Remove VSCode 2020-05-29 06:45:01 +02:00
James Cole
351272cc27 Merge pull request #3408 from sephrat/issue/3407
Fix #3407
2020-05-29 06:44:34 +02:00
James Cole
a293827739 Reformat translations. 2020-05-29 06:43:42 +02:00
James Cole
ead2cf92d3 Merge pull request #3405 from sephrat/error_pages_translation
Make error pages translatable
2020-05-29 06:41:55 +02:00
James Cole
dea9e21382 Merge branch 'develop' into error_pages_translation 2020-05-29 06:41:47 +02:00
James Cole
69725eb8c3 Rebuild JS #3404 2020-05-29 06:40:45 +02:00
James Cole
d31bb1f9b6 Regenerated JSON files for all languages. #3404 2020-05-29 06:39:48 +02:00
James Cole
b64979e45a New strings in all languages for #3404 2020-05-29 06:39:24 +02:00
James Cole
3dd3d2cabb Clean up strings #3404 2020-05-29 06:34:39 +02:00
James Cole
94e7c3527f Refactor strings #3404 2020-05-29 06:30:42 +02:00
James Cole
1a71d22146 Add strings to i18n #3404 2020-05-29 06:28:34 +02:00
James Cole
fdc3b80f1f Refactor strings #3404 2020-05-29 06:28:24 +02:00
James Cole
b978de78e4 Refactor strings #3404 2020-05-29 06:22:13 +02:00
James Cole
8b6bd296e1 Refactor string identifiers #3404 2020-05-29 06:19:56 +02:00
James Cole
4d075feed6 Merge pull request #3404 from sephrat/js_translations
Make new profile settings translatable
2020-05-29 06:18:29 +02:00
James Cole
e0e16489a1 Merge branch 'develop' into js_translations 2020-05-29 06:18:22 +02:00
James Cole
deeb4933fc Reformat for readability (PHPStorm) 2020-05-29 06:16:42 +02:00
James Cole
be8a0ddb3e Merge pull request #3393 from bpatath/feature/add-ssl-to-mysql
Add SSL conf to MySQL and LDAP
2020-05-29 06:13:16 +02:00
James Cole
49b1a6d844 Alignment 2020-05-29 06:12:24 +02:00
James Cole
3c1361e377 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2020-05-29 06:09:27 +02:00
James Cole
a7ab5b7504 A note about telemetry for the next release. 2020-05-29 06:07:12 +02:00
James Cole
0c8229d689 Some language strings. 2020-05-29 06:07:03 +02:00
Florian Dupret
aebf45697f fix #3407 2020-05-28 19:08:34 +02:00
Florian Dupret
d5d5530a8e .gitgnore 2020-05-28 16:06:11 +02:00
bpatath
8aa7776072 Replace unnused MySQL SSL mode 2020-05-28 09:26:42 +02:00
bpatath
f427267f5b Add SSL configuration for LDAP 2020-05-28 09:26:42 +02:00
bpatath
3195dd0db0 Add SSL configuration for MySQL 2020-05-28 09:26:42 +02:00
Florian Dupret
e67c62e6cd ignore node.js built files and vscode files 2020-05-27 19:35:41 +02:00
Florian Dupret
d319a21b01 Make error pages translatable 2020-05-27 17:42:19 +02:00
Florian Dupret
f8963179c3 Make new profile settings translatable 2020-05-27 16:17:24 +02:00
James Cole
d3cd657501 Merge pull request #3395 from sephrat/master
Make email notifications translatable (#3387)
2020-05-27 14:00:49 +00:00
Florian Dupret
6c6bb2cd1e Email translations cleanup 2020-05-27 09:34:52 +02:00
Florian Dupret
1771b3964e Email view cleanup: confirm account is obsolete 2020-05-26 18:50:48 +02:00
Florian Dupret
351c0ee2d7 Email notifications are now translatable 2020-05-26 12:01:39 +02:00
James Cole
1c9c380c8c Expand debug 2020-05-26 06:28:42 +02:00
James Cole
24455bf980 Fix #3133 2020-05-26 06:28:02 +02:00
James Cole
e21b40b46c Remove unused var 2020-05-26 06:27:43 +02:00
James Cole
29eabf9c8a Bad type. 2020-05-25 19:40:22 +02:00
James Cole
60e20ceeb1 Add another telemetry entry 2020-05-25 19:30:38 +02:00
Florian Dupret
37b35661be most email notifications translatable 2020-05-25 19:24:21 +02:00
Florian Dupret
b54bb20617 Make admin test email translatable 2020-05-25 13:13:33 +02:00
James Cole
19ce6b71e2 Some notes. 2020-05-24 16:58:17 +02:00
James Cole
b68663c977 Fix submission command. 2020-05-24 12:32:02 +02:00
James Cole
ac385e2647 Will now accept other values too. 2020-05-24 12:20:21 +02:00
James Cole
bc70174f44 Remove and cleanup commands. 2020-05-24 12:17:53 +02:00
James Cole
b8668b44a0 Enable feature telemetry 2020-05-24 12:12:06 +02:00
James Cole
86a87cc951 More text in .env.example 2020-05-24 12:01:40 +02:00
James Cole
be58b1d2be Enable the feature flag for telemetry. 2020-05-24 12:00:14 +02:00
James Cole
61733f6553 Forgot to remove debug variable. 2020-05-24 11:47:44 +02:00
James Cole
15e772d9dc Update some (disabled) commands. 2020-05-24 11:24:28 +02:00
James Cole
ae7b81bf86 Merge pull request #3390 from sephrat/master
Fix typos and minor text inconsistency
2020-05-24 09:19:02 +00:00
Florian Dupret
2c9ac0982a Fix minor typos 2020-05-24 09:59:34 +02:00
Florian Dupret
2df390065b Minor fix: fix rule action/trigger labels consistency 2020-05-24 09:53:54 +02:00
sephrat
247c9aebf3 Merge pull request #1 from firefly-iii/master
keep up with main repo
2020-05-24 09:51:01 +02:00
James Cole
0783500eaa Fix #3309 2020-05-23 19:54:02 +02:00
James Cole
c2e542004d Add some debug. 2020-05-23 08:14:13 +02:00
James Cole
806ad918f0 Include original collection time. 2020-05-22 20:24:56 +02:00
James Cole
84406a74c3 Merge tag '5.2.6' into develop
5.2.6
2020-05-22 17:54:03 +02:00
James Cole
09990acaa2 Merge branch 'release/5.2.6' 2020-05-22 17:54:02 +02:00
James Cole
a73247ec8c Some last minute translations. 2020-05-22 17:53:09 +02:00
James Cole
e98d43dd65 New meta files for 5.2.6 2020-05-22 14:15:57 +02:00
James Cole
dbd68cedc9 Code for #3309 2020-05-22 13:52:33 +02:00
James Cole
e6e8200912 Merge pull request #3381 from bpatath/feature/add-single-sign-on
Feature/add single sign on
2020-05-22 04:27:39 +00:00
bpatath
7b1380366b Register SSO middleware if enabled in configuration 2020-05-21 21:05:03 +02:00
bpatath
1eda806c17 Fix outdated AdLdap2 configuration files 2020-05-21 21:04:17 +02:00
James Cole
782ecca6a9 Warning if people disabled update checking. Every 4 weeks. 2020-05-20 06:40:18 +02:00
James Cole
e6338705a7 Fix #3376 2020-05-19 19:37:12 +02:00
James Cole
09226e6f12 New translations. 2020-05-19 13:29:47 +02:00
James Cole
5ff1991cdc Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2020-05-19 11:19:13 +02:00
James Cole
4ebb6de520 Reset rule order on index. #3376 2020-05-19 11:18:58 +02:00
James Cole
1ba7d65582 Warning if demo user. 2020-05-18 21:21:34 +02:00
James Cole
4e6063a4f8 Demo user can't set locale 2020-05-18 21:19:45 +02:00
James Cole
85476f3549 Fix some strings. 2020-05-18 21:17:59 +02:00
James Cole
ef9714b7e0 Fix #3374 2020-05-18 14:50:07 +02:00
James Cole
8d20029557 Fix #3368 2020-05-17 19:17:19 +02:00
James Cole
0f04b44ca1 Fix # 2020-05-17 06:49:26 +02:00
James Cole
44ed45502e Change in error handling. 2020-05-16 16:57:48 +02:00
James Cole
5bcafe1311 Change in error handling. 2020-05-16 16:57:26 +02:00
James Cole
5a771ccc5f Run yarn again #3363 2020-05-16 16:56:08 +02:00
James Cole
c6145b4a3b Auto generated JSON files for new strings in other languages. #3363 2020-05-16 16:35:23 +02:00
James Cole
b20aeca849 Auto-generated translation files from crowdin #3363 2020-05-16 16:33:57 +02:00
James Cole
793918f2f3 Add new strings to global translation files. #3363 2020-05-16 16:30:17 +02:00
James Cole
5d410e577e Merge pull request #3365 from sephrat/master
Fix #3363
2020-05-16 14:27:39 +00:00
James Cole
9ec786ec3a Merge branch 'develop' into master 2020-05-16 14:27:31 +00:00
Florian Dupret
e532b4d4fc Fix #3363 2020-05-16 15:01:19 +02:00
James Cole
58585d03c6 Fix rounding thing. 2020-05-16 13:09:37 +02:00
James Cole
a4f66b3d86 Date before and after triggers 2020-05-16 12:55:54 +02:00
James Cole
c847621874 First "date is" trigger for #3049 2020-05-16 12:11:06 +02:00
James Cole
86f14885eb Added a rule action that will delete the transactions it matches. 2020-05-16 11:21:26 +02:00
James Cole
173e196bc8 Some experimental fixes for #3011 2020-05-16 10:45:40 +02:00
James Cole
7505db871f Update packages. 2020-05-16 06:59:51 +02:00
James Cole
946dde8957 Add ability to store recurring telemetry. Not enabled. 2020-05-16 06:59:41 +02:00
James Cole
9a52cfbfbe Add some debug info 2020-05-16 06:59:15 +02:00
James Cole
b248bd6d0c Remove code. 2020-05-15 19:59:23 +02:00
James Cole
3fff9ad0a2 Updated translations. 2020-05-15 19:31:19 +02:00
James Cole
a695a1bba2 Fix #3355 2020-05-12 20:40:28 +02:00
James Cole
91e384aae8 Fix #3350 2020-05-10 20:08:16 +02:00
James Cole
1ac95b6fa7 Move getCash lower, add IBAN as name when no name is submitted. Search will pick up the rest. 2020-05-09 18:03:32 +02:00
James Cole
6757b6211d https://github.com/firefly-iii/firefly-iii/issues/3348 2020-05-09 17:47:25 +02:00
James Cole
4dfb78837e Slightly smarter menu. 2020-05-09 14:51:04 +02:00
James Cole
af50ad3db4 New action 2020-05-09 14:47:47 +02:00
James Cole
01cb94aabc Room for better translation 2020-05-09 14:47:33 +02:00
James Cole
5ffc5060b9 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2020-05-07 06:44:27 +02:00
James Cole
43d7c956a4 Fix #3344 2020-05-07 06:44:01 +02:00
James Cole
863b07951a Fix #3339 2020-05-05 20:53:56 +02:00
James Cole
2101717edb Can return without split. 2020-05-05 20:32:04 +02:00
James Cole
e7ac1476c5 Merge pull request #3336 from maksimkurb/develop
WIP: Fix #3335 Reconciliation account currency is wrong when base account has non-default currency
2020-05-05 20:30:05 +02:00
Maxim Kurbatov
5d24c1fee1 #3335 Update language files for reconciliation account name 2020-05-05 22:10:11 +04:00
Maxim Kurbatov
53eb863f9d Fix #3335 Reconciliation account currency is wrong when base account has non-default currency 2020-05-05 22:07:42 +04:00
James Cole
3c3ba637b5 Make sure demo user can't upload attachments. 2020-05-05 07:44:33 +02:00
James Cole
be8286b15c Fix some things in recurring transactions. 2020-05-04 10:26:01 +02:00
James Cole
6f6087995d Add info on expired recurring transactions. 2020-05-04 10:12:38 +02:00
James Cole
2ff8a35171 Add debug. 2020-05-04 10:06:13 +02:00
James Cole
7f8ed7abb6 Merge branch 'release/5.2.5' 2020-05-04 08:59:55 +02:00
James Cole
2ff0c37c12 Merge tag '5.2.5' into develop
5.2.5
2020-05-04 08:59:55 +02:00
James Cole
c593936b32 New meta files for upcoming release. 2020-05-04 08:56:51 +02:00
James Cole
c54204ede9 Fix #3330 2020-05-03 19:38:03 +02:00
James Cole
d9132bbee3 Merge pull request #3323 from lguima/feature/page-icons-update
Update the pages and blocks icons
2020-05-02 17:11:27 +02:00
Lucas Guima
c1be98762e Update the Tags icon around the site 2020-05-01 18:55:23 -03:00
Lucas Guima
c2733e2a8f Update the Categories icon around the site 2020-05-01 18:54:08 -03:00
Lucas Guima
722cf9b4fe Update the Reports icon around the site 2020-05-01 17:39:43 -03:00
Lucas Guima
01e31e73e0 Update the Piggy Banks icon around the site 2020-05-01 17:32:35 -03:00
Lucas Guima
dba7d05296 Update the Budgets icon around the site 2020-05-01 17:29:50 -03:00
James Cole
a8709a4a45 update env. 2020-05-01 20:16:34 +02:00
James Cole
49b1435cba Fix cron controller. #3318 2020-05-01 17:51:30 +02:00
James Cole
6a25b41952 Update translations. 2020-05-01 17:50:53 +02:00
James Cole
c561f99de6 Fix #3321 2020-05-01 17:47:56 +02:00
James Cole
9d9053d828 Fix #3314 2020-05-01 06:24:24 +02:00
James Cole
c3c9a2f3c0 Slightly different icon. 2020-04-30 06:27:53 +02:00
James Cole
28465142e9 Menu changelog. 2020-04-30 06:27:10 +02:00
James Cole
5473a618c9 Warn about locale things. 2020-04-30 06:27:01 +02:00
James Cole
ac1a8d8053 Merge pull request #3305 from lguima/feature/menu-reordering
Menu reordering
2020-04-30 06:10:51 +02:00
James Cole
15ae9203b6 Fix #3307 2020-04-29 06:37:02 +02:00
Lucas Guima
9dfc2ae20b Use the translatable string for Tools 2020-04-28 20:59:22 -03:00
Lucas Guima
230de7cbdd Use the translatable string for Classification 2020-04-28 20:59:10 -03:00
Lucas Guima
feaa003a52 Use the translatable string for Others 2020-04-28 20:57:36 -03:00
Lucas Guima
295d01dc16 Use the translatable string for Automation 2020-04-28 20:57:11 -03:00
Lucas Guima
cbf1fde45e Use the translatable string for Accounting 2020-04-28 20:56:19 -03:00
Lucas Guima
6cc47287d3 Use the translatable string for Financial control 2020-04-28 20:55:52 -03:00
Lucas Guima
4bbe728376 Create translatable string for Classification 2020-04-28 20:43:02 -03:00
Lucas Guima
427a90ec85 Create translatable string for Others 2020-04-28 20:32:10 -03:00
Lucas Guima
55ddb26dac Create translatable string for Automation 2020-04-28 20:16:25 -03:00
Lucas Guima
891777f079 Create translatable string for Accounting 2020-04-28 20:14:15 -03:00
Lucas Guima
1655286b67 Create translatable string for Financial control 2020-04-28 20:10:43 -03:00
Lucas Guima
dd81636bf2 Add an icon for each sub-menu item 2020-04-28 19:29:53 -03:00
Lucas Guima
56a43a707d Update the icon of Bills menu item 2020-04-28 19:07:44 -03:00
Lucas Guima
c2f92c6e45 Update the icon of Options menu item 2020-04-28 19:07:11 -03:00
Lucas Guima
61bd2dc840 Revert "Move the menu items Profile and Logout to the user menu in the main header"
This reverts commit f6a675f2e2.
2020-04-28 18:55:49 -03:00
Lucas Guima
f6a675f2e2 Move the menu items Profile and Logout to the user menu in the main header 2020-04-27 22:29:14 -03:00
Lucas Guima
85b43055a7 Put the menu sub-items text inside a span tag 2020-04-27 21:44:23 -03:00
Lucas Guima
e63f7bcc70 Put a space between arguments 2020-04-27 21:41:00 -03:00
Lucas Guima
384dd37430 Update the menu item Logout 2020-04-27 21:37:20 -03:00
Lucas Guima
c6b336171c Update the menu item Options 2020-04-27 21:36:47 -03:00
Lucas Guima
d2f4399a1a Update the menu item Tools (Import and export) 2020-04-27 21:30:12 -03:00
Lucas Guima
02d1bc093c Update the menu item Reports 2020-04-27 21:14:38 -03:00
Lucas Guima
420e493987 Group Categories and Tags under the new menu item Classification 2020-04-27 21:12:23 -03:00
Lucas Guima
0a15479bff Update the menu item Accounts 2020-04-27 20:53:25 -03:00
Lucas Guima
a9b76a3679 Add menu header for Others 2020-04-27 20:44:39 -03:00
Lucas Guima
d1a3cd9044 Move and update the menu item Automation (Money management) 2020-04-27 20:41:40 -03:00
Lucas Guima
81735d59f8 Move and update the menu item Transactions 2020-04-27 19:59:53 -03:00
Lucas Guima
1d8da7f9f0 Add menu header for Accounting 2020-04-27 18:35:52 -03:00
Lucas Guima
c5f0684030 Place the menu item Piggy banks after Bills 2020-04-26 18:11:20 -03:00
Lucas Guima
25867adcb9 Move the menu item Piggy banks 2020-04-26 18:10:22 -03:00
Lucas Guima
d55694cd68 Move the menu item Bills 2020-04-26 18:07:08 -03:00
Lucas Guima
05f069d61e Move the menu item Budgets 2020-04-26 18:00:28 -03:00
Lucas Guima
5f6e7ad138 Add menu header for Financial Control 2020-04-26 17:50:42 -03:00
Lucas Guima
61bc38921e Update Dashboard menu item 2020-04-26 17:48:13 -03:00
Lucas Guima
94c660545d Update indentation 2020-04-26 17:44:07 -03:00
James Cole
4d3907948d Merge tag '5.2.4' into develop
5.2.4
2020-04-26 10:02:43 +02:00
James Cole
e6442dd8af Merge branch 'release/5.2.4' 2020-04-26 10:02:42 +02:00
James Cole
7905e0bd70 Bump to 5.2.4 2020-04-26 10:02:25 +02:00
James Cole
f4b1da352d no message 2020-04-26 07:08:33 +02:00
James Cole
0d33348941 Fix #3251 2020-04-26 06:57:59 +02:00
James Cole
c7c875e95f Fix #3251 2020-04-26 06:54:12 +02:00
James Cole
19d24b3e2a Clean up templates 2020-04-26 06:45:42 +02:00
James Cole
8fed6b6657 Fix #3287 2020-04-22 09:28:20 +02:00
James Cole
b5eafa1910 Merge tag '5.2.3' into develop
5.2.3
2020-04-22 06:33:23 +02:00
James Cole
c15501937f Merge branch 'release/5.2.3' 2020-04-22 06:33:22 +02:00
James Cole
4c743bd5b0 Update meta files for new release. 2020-04-22 06:29:34 +02:00
James Cole
44289cbd95 Fix #3284 2020-04-22 06:09:29 +02:00
James Cole
b2f1642cfe Fix #3281 2020-04-21 08:17:31 +02:00
James Cole
341ef0220c New translations. 2020-04-19 11:07:14 +02:00
James Cole
9df88115bc Update packages. 2020-04-19 11:05:14 +02:00
James Cole
c7273edb5e Updated language strings and meta config. 2020-04-19 06:52:12 +02:00
James Cole
c398aa2b69 Add support for British English and allow the user to set a locale. 2020-04-19 06:51:40 +02:00
James Cole
aa786eaaf3 Clean up language setting. 2020-04-19 06:11:49 +02:00
James Cole
e58a5e12d6 Fix #3270 2020-04-19 06:10:49 +02:00
James Cole
12b3575c5c Fix method reference 2020-04-19 06:09:55 +02:00
James Cole
3ca186dc8f Remove unused method. 2020-04-19 06:09:43 +02:00
James Cole
1535f596f6 Add two new support functions. 2020-04-19 06:07:43 +02:00
James Cole
2cc326caa1 Fix #3272 2020-04-19 06:05:39 +02:00
James Cole
43436ae942 Fix issue with casting. 2020-04-19 06:00:11 +02:00
James Cole
fbfd8475de Fix #3264 2020-04-15 16:17:45 +02:00
James Cole
405752f353 Merge tag '5.2.2' into develop
5.2.2
2020-04-14 21:01:03 +02:00
James Cole
2af98b259a Merge branch 'release/5.2.2' 2020-04-14 21:01:02 +02:00
James Cole
015242a666 Update meta files for new release. 2020-04-14 20:56:30 +02:00
James Cole
54933fda2e Fix #3263 2020-04-14 17:23:58 +02:00
James Cole
852d057a47 Fix #3259 2020-04-13 07:57:46 +02:00
James Cole
1778f0b4f3 Fix storing of virtual balance. 2020-04-13 07:57:32 +02:00
James Cole
6daf083b3f Clean up some code. 2020-04-12 06:24:35 +02:00
James Cole
4a7d9b130a Fix issue with multi-currency in asset accounts. 2020-04-12 06:23:35 +02:00
James Cole
4163efba55 Clean up phpdoc 2020-04-11 06:42:47 +02:00
James Cole
db5847b49b Consistent in minimum password length 2020-04-11 06:42:40 +02:00
James Cole
6829003f5e Change to safer hash methods. 2020-04-11 06:42:21 +02:00
James Cole
047927718e Merge branch 'release/5.2.1' 2020-04-10 21:23:53 +02:00
James Cole
91deb22a3f Merge tag '5.2.1' into develop
5.2.1
2020-04-10 21:23:53 +02:00
James Cole
1629ca0739 Update for some bugs. 2020-04-10 21:20:04 +02:00
James Cole
8b87204f10 User unable to store budgets without auto budget info. 2020-04-10 21:16:46 +02:00
James Cole
f920d90e3d Fix chart problem 2020-04-10 21:16:29 +02:00
James Cole
1cb91282af Merge tag '5.2.0' into develop
5.2.0
2020-04-10 13:51:23 +02:00
James Cole
a6ce294131 Merge branch 'release/5.2.0' 2020-04-10 13:51:22 +02:00
James Cole
34ceb69776 Update last minute files. 2020-04-10 13:50:37 +02:00
James Cole
eed68b5d95 Fix some code quality issues. 2020-04-10 10:47:24 +02:00
James Cole
79374c11ee Fix for #3248 2020-04-10 10:12:12 +02:00
James Cole
404f9df6d3 Bad link to model. 2020-04-10 07:29:15 +02:00
James Cole
4b716e35b9 Prep changelog for new release. 2020-04-10 07:20:45 +02:00
James Cole
166fc7a3e2 Fix trait 2020-04-09 20:33:55 +02:00
James Cole
06afbc7a0a Fix chart 2020-04-09 06:27:43 +02:00
James Cole
49a98de63a Add YNAB 2020-04-09 06:27:29 +02:00
James Cole
5b572c0da2 Expand readme. 2020-04-09 06:27:20 +02:00
James Cole
59014b1a87 Meta files for the next release. 2020-04-08 06:54:16 +02:00
James Cole
4aec1f06e0 Fix issue updating categories. 2020-04-08 06:43:58 +02:00
James Cole
136af9625a Better link for tags. 2020-04-07 18:19:29 +02:00
James Cole
edac26f757 Merge pull request #3236 from SuperSandro2000/patch-1
Add missing date based on releases page
2020-04-05 07:54:01 +02:00
Sandro
ac54dd05bf Add missing date based on releases page 2020-04-05 07:31:30 +02:00
James Cole
7948058364 Fix #3234 2020-04-05 07:14:17 +02:00
James Cole
f13a6f7bf9 New php docs [skip ci] 2020-04-05 07:10:59 +02:00
James Cole
e1a5d143c5 Merge tag '5.2.0-beta.1' into develop
5.2.0-beta.1
2020-04-02 06:54:50 +02:00
James Cole
f98011cd0d Merge branch 'release/5.2.0-beta.1' 2020-04-02 06:54:49 +02:00
James Cole
e7c10dec5c Update meta files for new release. 2020-04-02 06:39:09 +02:00
James Cole
ae2b28fdee Use correct methods. 2020-03-31 07:41:48 +02:00
James Cole
8d3fc18ca6 Use correct methods. 2020-03-31 07:40:20 +02:00
James Cole
61521cf478 Use correct methods. 2020-03-31 07:39:57 +02:00
James Cole
06c5e4df2c Use correct methods. 2020-03-31 07:39:36 +02:00
James Cole
9e4b7f8bb4 Add IBAN to account validator. 2020-03-31 07:04:00 +02:00
James Cole
144bc29eb3 Fix issue with budgets. 2020-03-31 07:03:37 +02:00
James Cole
2c0d8b9cb3 Fix #3122 2020-03-28 16:06:37 +01:00
James Cole
511b1258ba Merge pull request #3212 from rubenverhoef/CSV-ING
ING CSV
2020-03-27 05:22:02 +00:00
Ruben Verhoef
8cfe0af502 New saving acount function, supports account numbers with chars and make it easier to link when account numbers are the same but name are different 2020-03-26 20:51:07 +01:00
James Cole
54e3c7d729 Fix #3211 2020-03-26 19:59:38 +01:00
James Cole
628b493128 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2020-03-26 19:58:40 +01:00
Ruben Verhoef
8c552b8fa8 Fix functions moveValutadatumDescription and removeNameIngDescription 2020-03-26 19:52:30 +01:00
James Cole
c864d904b0 Fix #3079 2020-03-26 18:00:18 +01:00
James Cole
ecb61676ab Fix #3210 2020-03-26 12:05:15 +01:00
James Cole
ee5a4caaab Some extra code for #1376 2020-03-26 07:10:39 +01:00
James Cole
84bdd47109 update issue templates. 2020-03-25 19:25:50 +01:00
James Cole
5445752588 Update some phpdocs, courtesy of Psalm. 2020-03-25 07:03:23 +01:00
James Cole
bcfbdcf3f0 Clean up models.
Clean up models.
2020-03-25 06:58:39 +01:00
James Cole
7e6cd77203 Clean up models. 2020-03-25 06:58:29 +01:00
James Cole
5e3d00ecde Merge tag '5.2.0-alpha.1' into develop
5.2.0-alpha.1
2020-03-24 07:22:27 +01:00
James Cole
4dea3a5f55 Merge branch 'release/5.2.0-alpha.1' 2020-03-24 07:22:23 +01:00
James Cole
7303d8b899 Meta files for release 5.2.0-alpha.1 2020-03-24 07:13:13 +01:00
James Cole
fa0caa6518 Meta files for release 5.2.0-alpha.1 2020-03-24 07:11:30 +01:00
James Cole
26be90eff1 Meta files for release 5.2.0-alpha.1 2020-03-24 07:11:05 +01:00
James Cole
db3c9fbd28 Can't remove your own admin rights. 2020-03-24 05:57:04 +01:00
James Cole
87b62e2e72 New strings. 2020-03-24 05:53:05 +01:00
James Cole
1e6224f041 Fix #3203 2020-03-23 20:23:38 +01:00
James Cole
d6797b8428 Allow users to hand out admin rights. 2020-03-23 17:54:49 +01:00
James Cole
76c89a8efa Fix #3202 2020-03-23 11:01:00 +01:00
James Cole
1797880488 Code for #3057 2020-03-22 18:27:20 +01:00
James Cole
cdebde5a2b Fixed #3048 2020-03-22 17:28:25 +01:00
James Cole
5ee1f322d0 hide button and checkbox [skip ci] 2020-03-22 08:18:38 +01:00
James Cole
87273e232a hide button and checkbox [skip ci] 2020-03-22 08:18:05 +01:00
James Cole
53b77e6bf9 hide cat and bud [skip ci] 2020-03-22 08:17:02 +01:00
James Cole
b8696bf8b5 hide date [skip ci] 2020-03-22 08:15:52 +01:00
James Cole
8436a86536 Hide icon [skip ci] 2020-03-22 08:14:47 +01:00
James Cole
c598151c68 Hide some fields. 2020-03-22 08:13:39 +01:00
James Cole
53938f3c12 Make table responsive. 2020-03-22 08:10:09 +01:00
James Cole
0813464fe0 Hard stop if feature flag is disabled. 2020-03-22 08:06:36 +01:00
James Cole
4436c9939e Add error message. 2020-03-22 08:04:35 +01:00
James Cole
5e323b958f Update strings and view for telemetry (inactive) 2020-03-22 07:55:57 +01:00
James Cole
367f225f38 Limit to 50. 2020-03-22 06:59:46 +01:00
James Cole
a97d7058ff Telemetry cron job. 2020-03-21 21:32:17 +01:00
James Cole
9d7fb0efe1 Remove slash 2020-03-21 21:13:41 +01:00
James Cole
1e9596bba0 Add URL of (inactive) telemetry endpoint. 2020-03-21 21:08:41 +01:00
James Cole
c6d17e9bd7 Reformat code. 2020-03-21 15:43:41 +01:00
James Cole
f76585dc9b Update (disabled) telemetry settings. 2020-03-21 15:42:37 +01:00
James Cole
cf4f76f211 Fix bar, also multi currency #2977 2020-03-21 15:12:23 +01:00
James Cole
790e29f15e Update the amount, not yet the bar #2977 2020-03-21 14:50:54 +01:00
James Cole
2107406d8b Clean up and simplify 2020-03-21 14:20:40 +01:00
James Cole
b91a21a081 Move more code to trait. 2020-03-21 09:41:04 +01:00
James Cole
170e35aecc Wrong variable name. 2020-03-21 09:35:25 +01:00
James Cole
5701597e20 Some more moved to traits. 2020-03-21 09:01:14 +01:00
James Cole
d16389748f Move code to traits. 2020-03-21 08:54:38 +01:00
James Cole
ee844e970f Move to separate traits. 2020-03-21 08:11:14 +01:00
James Cole
62757812ff Refactor group validation 2020-03-21 06:01:27 +01:00
James Cole
c15b72b6b0 Refactor currency validation 2020-03-21 06:00:36 +01:00
James Cole
11e3834235 Refactor validation method. 2020-03-21 05:56:27 +01:00
James Cole
affc198b03 Cleanup for #2999 2020-03-21 05:47:49 +01:00
James Cole
d5b315e3c8 Experimental chart for #2999 2020-03-21 05:26:39 +01:00
James Cole
eb31ff4ebb Remove comma 2020-03-20 18:23:21 +01:00
James Cole
9ab36d4598 Update composer files. 2020-03-20 18:15:24 +01:00
James Cole
bf06f8eac3 Add telemetry config (inactive) 2020-03-20 18:06:24 +01:00
James Cole
fa9befba11 Remove TODO [skip ci] 2020-03-20 18:06:08 +01:00
James Cole
3b0c061ec7 Model and some basic code for Telemetry (inactive) 2020-03-20 18:05:58 +01:00
James Cole
d021be6a25 Add telemetry (inactive) 2020-03-20 18:05:40 +01:00
James Cole
69ee691497 Fix null pointer. 2020-03-20 17:59:56 +01:00
James Cole
5a7152ceec Clean up config. 2020-03-20 17:31:54 +01:00
James Cole
7b216543fa Update instructions 2020-03-20 17:21:45 +01:00
James Cole
cd3f3fd781 Fix #2985 2020-03-20 15:52:20 +01:00
James Cole
4b0e46af2b Whoops 2020-03-20 15:42:56 +01:00
James Cole
470ab6340c Fix #2985 2020-03-20 08:41:20 +01:00
James Cole
9e54ebe6a9 Fix #2958 2020-03-20 04:42:19 +01:00
James Cole
7eb2451e3d Improved chart for #2938 2020-03-20 04:37:45 +01:00
James Cole
6dba44ba71 Show attachments to tags #2828 2020-03-19 18:51:47 +01:00
James Cole
64683647bd Piggy supports view of attachments #2828 2020-03-19 18:44:45 +01:00
James Cole
1f919b6d0e Attachments for categories #2828 2020-03-19 18:37:57 +01:00
James Cole
417a0d0f83 Show attachments for budgets #2828 2020-03-19 18:28:02 +01:00
James Cole
9b53576fc2 Show attachments for bills #2828 2020-03-19 18:23:34 +01:00
James Cole
2a46756838 Attachments for accounts are visible #2828 2020-03-19 18:20:23 +01:00
James Cole
cdf055065f Remove unused method. 2020-03-19 15:21:44 +01:00
James Cole
2cee008e4a Clean up a little bit. 2020-03-19 15:16:59 +01:00
James Cole
d889e39aad Clean up method. 2020-03-19 14:33:41 +01:00
James Cole
72b9ecf07e Simplify trait. 2020-03-19 14:28:38 +01:00
James Cole
14f4351920 Can upload attachments for all models #2828 2020-03-19 09:14:49 +01:00
James Cole
12e81364a0 Make sure all controllers can store attachment when creating models #2828 2020-03-19 09:01:35 +01:00
James Cole
d489244c00 Add attachment helper to relevant classes #2828 2020-03-19 08:58:55 +01:00
James Cole
aceaf5f891 Add attachment thing to views #2828 2020-03-19 08:56:00 +01:00
James Cole
6129b9d25c Make upload size globally available #2828 2020-03-19 08:43:52 +01:00
James Cole
75afe35e98 API can deal with attachments for more models. #2828 2020-03-19 08:32:42 +01:00
James Cole
3246b7eb9f Allow more models to accept transactions #2828 2020-03-18 21:36:26 +01:00
James Cole
c412ffc195 Short array syntax #3197 2020-03-18 20:58:25 +01:00
James Cole
7c3b5fe714 Merge pull request #3197 from rubenverhoef/CSV-ING
Fix small issue from #3146
2020-03-18 19:57:42 +00:00
James Cole
ae967c027b Merge branch 'develop' into CSV-ING 2020-03-18 19:56:50 +00:00
James Cole
3e74fce885 Simplify method. 2020-03-18 20:55:31 +01:00
James Cole
2c7891bfb2 Merge pull request #3196 from firefly-iii/analysis-3wxmk5
Apply fixes from StyleCI
2020-03-18 19:46:02 +00:00
James Cole
712ba00c9e Apply fixes from StyleCI 2020-03-18 19:45:45 +00:00
James Cole
74683b18f2 Fix bad namespace. 2020-03-18 15:38:28 +01:00
James Cole
d0d129d965 Fix #3193 2020-03-18 15:29:32 +01:00
Ruben Verhoef
87d459c5ff Check if Valutadatum is found in row 8, when not found do nothing! 2020-03-17 19:43:03 +01:00
James Cole
5b591ff744 Whoops 2020-03-17 17:41:59 +01:00
James Cole
63f00cbb7b Remove unused index 2020-03-17 17:41:43 +01:00
James Cole
c90b26c181 Simplify method. 2020-03-17 17:41:06 +01:00
James Cole
c136c60eae Merge pull request #3195 from firefly-iii/analysis-rdjLrQ
Apply fixes from StyleCI
2020-03-17 16:07:00 +00:00
James Cole
ba4c1d95a7 Apply fixes from StyleCI 2020-03-17 16:06:30 +00:00
James Cole
9a25d6a741 Code cleanup that (hopefully) matches style CI 2020-03-17 16:46:00 +01:00
James Cole
91c067ac9f Code cleanup that (hopefully) matches style CI 2020-03-17 15:03:08 +01:00
James Cole
24129ab69c Code cleanup that (hopefully) matches style CI 2020-03-17 15:02:57 +01:00
James Cole
2b6c3fd743 Code cleanup that (hopefully) matches style CI 2020-03-17 15:01:00 +01:00
James Cole
bd2f064eeb Code cleanup that (hopefully) matches style CI 2020-03-17 14:57:04 +01:00
James Cole
b0c9fc0792 Code cleanup that (hopefully) matches style CI 2020-03-17 14:54:25 +01:00
James Cole
e02e747f1b Code cleanup that (hopefully) matches style CI 2020-03-17 14:53:17 +01:00
James Cole
64462812fc Two small method improvements. 2020-03-17 14:46:17 +01:00
James Cole
46382b0d21 Simplify method. 2020-03-16 19:45:23 +01:00
James Cole
a7fffa5868 Make method smaller. 2020-03-16 19:40:48 +01:00
James Cole
4334928fbd Add sort to language. 2020-03-16 06:54:18 +01:00
James Cole
a478d1b544 Add sort to language. 2020-03-16 06:53:10 +01:00
James Cole
08b69dfbf6 Update language strings for Vietnamese. 2020-03-16 06:50:51 +01:00
James Cole
b631adbbf2 Update language strings. 2020-03-16 06:47:06 +01:00
James Cole
fbd88d03c5 Add support for Vietnamese. 2020-03-16 06:46:48 +01:00
James Cole
4982f6f919 Cleanup method 2020-03-15 18:12:36 +01:00
James Cole
6a6bf102b6 Cleanup method. 2020-03-15 18:05:24 +01:00
James Cole
524f85b9c1 Delete import related tests 2020-03-15 15:33:00 +01:00
James Cole
328c960950 Fix API tests 2020-03-15 15:32:09 +01:00
James Cole
208bece7ea Clean up validation 2020-03-15 15:31:59 +01:00
James Cole
16f918a294 Mark all import related code as deprecated 2020-03-15 15:31:51 +01:00
James Cole
9d90beb790 update libraries for better keyboard use. 2020-03-15 15:17:07 +01:00
James Cole
d7e953d38c Clean up complicated method. 2020-03-15 09:54:44 +01:00
James Cole
6967bb003e Do some code cleanup. 2020-03-15 08:16:16 +01:00
James Cole
f63e51fea2 Fix issue with null pointers. 2020-03-15 07:48:02 +01:00
James Cole
33c73701d8 Button to duplicate rule. #2957 2020-03-14 21:01:21 +01:00
James Cole
50b710b4f6 Expand charts. 2020-03-14 20:30:31 +01:00
James Cole
d1325ffbd8 New charts for #2726 2020-03-14 19:12:32 +01:00
James Cole
bfc6a70c9f Fix #3154 2020-03-14 16:56:58 +01:00
James Cole
a00f46faa9 Also create initial budget limit. 2020-03-14 15:18:32 +01:00
James Cole
c475f05652 Updated library. 2020-03-14 10:29:32 +01:00
James Cole
d42b9ee017 Initial changelog. 2020-03-14 10:29:23 +01:00
James Cole
cccaae49a5 Dont forget to enable recurring cron job. 2020-03-14 10:27:43 +01:00
James Cole
1dd3018cb2 Basic cron job for budgeting. 2020-03-14 10:25:12 +01:00
James Cole
7ea32046af Add icon. 2020-03-14 08:03:43 +01:00
James Cole
9bb2f1cfd3 Edit works again 2020-03-14 07:55:00 +01:00
James Cole
fdffed636f Make sure create uses the right fields. 2020-03-14 07:49:11 +01:00
James Cole
bde0732135 Can now update (and remove) auto budget over api 2020-03-14 07:43:49 +01:00
James Cole
d1d11ae717 Can now create auto budget over API 2020-03-14 07:30:55 +01:00
James Cole
309633069c can edit, delete and see in api autobudget 2020-03-14 07:01:31 +01:00
James Cole
2ece754927 Can now store and validate auto budget 2020-03-13 21:35:22 +01:00
James Cole
6f98fc0dff First attempt at form. 2020-03-13 21:15:54 +01:00
James Cole
cd65971f5e Some new strings for new model. 2020-03-13 21:15:37 +01:00
James Cole
81d7b7b6a1 New model and migration. 2020-03-13 21:15:21 +01:00
James Cole
92ba56ae2b Clean up some forms. 2020-03-13 20:56:26 +01:00
James Cole
e1bcfb9ac9 Merge tag '5.1.1' into develop
5.1.1
2020-03-13 19:40:00 +01:00
1493 changed files with 109068 additions and 60613 deletions

View File

@@ -16,3 +16,4 @@ sv_SE
zh-hans_CN
zh-hant_CN
fi_FI
vi_VN

View File

@@ -10,40 +10,42 @@ APP_DEBUG=false
SITE_OWNER=mail@example.com
# The encryption key for your sessions. Keep this very secure.
# If you generate a new one existing data must be considered LOST.
# If you generate a new one all existing attachments must be considered LOST.
# Change it to a string of exactly 32 chars or use something like `php artisan key:generate` to generate it.
# If you use Docker or similar, you can set this variable from a file by using APP_KEY_FILE
APP_KEY=SomeRandomStringOf32CharsExactly
#
# Firefly III will launch using this language (for new users and unauthenticated visitors)
# For a list of available languages: https://github.com/firefly-iii/firefly-iii/tree/master/resources/lang
# For a list of available languages: https://github.com/firefly-iii/firefly-iii/tree/main/resources/lang
#
# If text is still in English, remember that not everything may have been translated.
DEFAULT_LANGUAGE=en_US
# The locale defines how numbers are formatted.
# by default this value is the same as whatever the language is.
DEFAULT_LOCALE=equal
# Change this value to your preferred time zone.
# Example: Europe/Amsterdam
# For a list of supported time zones, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
TZ=Europe/Amsterdam
# This variable must match your installation's external address but keep in mind that
# it's only used on the command line as a fallback value.
APP_URL=http://localhost
# TRUSTED_PROXIES is a useful variable when using Docker and/or a reverse proxy.
# Set it to ** and reverse proxies work just fine.
TRUSTED_PROXIES=
# The log channel defines where your log entries go to.
# - Docker + versions <= 4.8.1.8 and before: use "stdout"
# - Docker + versions > 4.8.1.8: use "docker_out"
# - For everything else, use 'daily'
# Several other options exist. You can use 'single' for one big fat error log (not recommended).
# Also available are 'syslog', 'errorlog' and 'stdout' which will log to the system itself.
# A rotating log option is 'daily', creates 5 files that (surprise) rotate.
# Default setting 'stack' will log to 'daily' and to 'stdout' at the same time.
# - Docker + versions <= 4.8.1.8 and before: use "stdout"
# - Docker + versions > 4.8.1.8 : use "docker_out"
# - Docker + versions >= 5.1.1 : use "stack"
# - For everything else (als not Docker) : use 'stack'
LOG_CHANNEL=stack
# Log level. You can set this from least severe to most severe:
@@ -55,14 +57,27 @@ APP_LOG_LEVEL=notice
# Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III
# For other database types, please see the FAQ: https://docs.firefly-iii.org/support/faq
# If you use Docker or similar, you can set these variables from a file by appending them with _FILE
# Use "mysql" for MySQL and MariaDB. Use "sqlite" for SQLite.
DB_CONNECTION=pgsql
DB_HOST=firefly_iii_db
DB_PORT=5432
# Use "pgsql" for PostgreSQL
# Use "mysql" for MySQL and MariaDB.
# Use "sqlite" for SQLite.
DB_CONNECTION=mysql
DB_HOST=fireflyiiidb
DB_PORT=3306
DB_DATABASE=firefly
DB_USERNAME=firefly
DB_PASSWORD=secret_firefly_password
# MySQL supports SSL. You can configure it here.
# If you use Docker or similar, you can set these variables from a file by appending them with _FILE
MYSQL_USE_SSL=false
MYSQL_SSL_VERIFY_SERVER_CERT=true
# You need to set at least of these options
MYSQL_SSL_CAPATH=/etc/ssl/certs/
MYSQL_SSL_CA=
MYSQL_SSL_CERT=
MYSQL_SSL_KEY=
MYSQL_SSL_CIPHER=
# PostgreSQL supports SSL. You can configure it here.
# If you use Docker or similar, you can set these variables from a file by appending them with _FILE
PGSQL_SSL_MODE=prefer
@@ -95,8 +110,8 @@ COOKIE_SECURE=false
# If you want Firefly III to mail you, update these settings
# For instructions, see: https://docs.firefly-iii.org/advanced-installation/email
# If you use Docker or similar, you can set these variables from a file by appending them with _FILE
MAIL_DRIVER=log
MAIL_HOST=smtp.mailtrap.io
MAIL_MAILER=log
MAIL_HOST=null
MAIL_PORT=2525
MAIL_FROM=changeme@example.com
MAIL_USERNAME=null
@@ -154,6 +169,23 @@ FIXER_API_KEY=
# If you use Docker or similar, you can set this variable from a file by appending it with _FILE
LOGIN_PROVIDER=eloquent
#
# It's also possible to change the way users are authenticated. You could use Authelia for example.
# Authentication via the REMOTE_USER header is supported. Change the value below to "remote_user_guard".
#
# If you do this please read the documentation for instructions and warnings:
# https://docs.firefly-iii.org/advanced-installation/authentication
#
# This function is available in Firefly III v5.3.0 and higher.
AUTHENTICATION_GUARD=web
#
# Likewise, it's impossible to log out users who's authentication is handled by an external system.
# Enter a custom URL here that will force a logout (your authentication provider can tell you).
# Setting this variable only works when AUTHENTICATION_GUARD != web
#
CUSTOM_LOGOUT_URI=
# LDAP connection configuration
# OpenLDAP, FreeIPA or ActiveDirectory
# # If you use Docker or similar, you can set this variable from a file by appending it with _FILE
@@ -168,8 +200,16 @@ ADLDAP_PORT=389
ADLDAP_TIMEOUT=5
ADLDAP_BASEDN=""
ADLDAP_FOLLOW_REFFERALS=false
# SSL/TLS settings
ADLDAP_USE_SSL=false
ADLDAP_USE_TLS=false
ADLDAP_SSL_CACERTDIR=
ADLDAP_SSL_CACERTFILE=
ADLDAP_SSL_CERTFILE=
ADLDAP_SSL_KEYFILE=
ADLDAP_SSL_CIPHER_SUITE=
ADLDAP_SSL_REQUIRE_CERT=
# You can set the following variables from a file by appending them with _FILE:
ADLDAP_ADMIN_USERNAME=
@@ -189,6 +229,7 @@ ADLDAP_AUTH_FIELD=distinguishedname
# Will allow SSO if your server provides an AUTH_USER field.
# You can set the following variables from a file by appending them with _FILE:
WINDOWS_SSO_ENABLED=false
WINDOWS_SSO_DISCOVER=samaccountname
WINDOWS_SSO_KEY=AUTH_USER
@@ -216,8 +257,9 @@ TRACKER_SITE_ID=
TRACKER_URL=
#
# Firefly III could (in the future) collect telemetry on how you use Firefly III.
# In order to allow this, change the following variable to true:
# Firefly III can collect telemetry on how you use Firefly III. This is opt-in.
# In order to allow this, change the following variable to true.
# To read more about this feature, go to this page: https://docs.firefly-iii.org/support/telemetry
SEND_TELEMETRY=false
# You can fine tune the start-up of a Docker container by editing these environment variables.
@@ -264,7 +306,17 @@ PUSHER_ID=
DEMO_USERNAME=
DEMO_PASSWORD=
USE_ENCRYPTION=false
IS_SANDSTORM=false
IS_DOCKER=false
IS_HEROKU=false
BUNQ_USE_SANDBOX=false
FIREFLY_III_LAYOUT=v1
#
# If you have trouble configuring your Firefly III installation, DON'T BOTHER setting this variable.
# It won't work. It doesn't do ANYTHING. Don't believe the lies you read online. I'm not joking.
# This configuration value WILL NOT HELP.
#
# This variable is ONLY used in some of the emails Firefly III sends around. Nowhere else.
# So when configuring anything WEB related this variable doesn't do anything. Nothing
#
# If you're stuck I understand you get desperate but look SOMEWHERE ELSE.
#
APP_URL=http://localhost

View File

@@ -16,10 +16,10 @@ I am running Firefly III version x.x.x, and my problem is:
<!-- Please add extra info here, such as OS, browser, and the output from the /debug page of your Firefly III installation (click the version at the bottom). -->
**Bonus points**
<!-- Earn bonus points by checking the boxes -->
<!-- Before you submit, verify the following please: -->
- [ ] Nobody reported this bug before
- [ ] I have added a stack trace from my log files.
- [ ] I have added a screenshot.
- [ ] I was able to replicate it on the demo site https://demo.firefly-iii.org/
<!-- - [ ] I donated money (this is a joke :wink:)-->
- I searched and nobody reported this bug before
- I have added a stack trace from my log files <!-- (see https://bit.ly/FF3-get-debug-info) -->
- I have added a screenshot.
- I was able to replicate it on the demo site https://demo.firefly-iii.org/
<!-- - I donated money (this is a joke ;)-->

View File

@@ -16,8 +16,8 @@ I am running Firefly III version x.x.x.
<!-- Complete the following checklist for bonus points -->
- [ ] I have read the FAQ at https://bit.ly/FF3-FAQ
- [ ] I added a screenshot
- [ ] I added log files (see https://bit.ly/FF3-get-logs)
- [ ] I was able to replicate the issue on the demo site.
<!-- - [ ] I donated money (this is a joke :wink:)-->
- I have read the FAQ at https://bit.ly/FF3-FAQ
- I added a screenshot
- I added log files <!-- (see https://bit.ly/FF3-get-debug-info) -->
- I was able to replicate the issue on the demo site.
<!-- - I donated money (this is a joke :wink:)-->

View File

@@ -8,7 +8,7 @@ I am always interested in expanding Firefly III's many features. Just open a tic
## Pull requests
When contributing to Firefly III, please first discuss the change you wish to make via issue, email, or any other method. I can only accept pull requests against the `develop` branch, never the `master` branch.
When contributing to Firefly III, please first discuss the change you wish to make via issue, email, or any other method. I can only accept pull requests against the `develop` branch, never the `main` branch.
## Translations :us: :fr: :de:

2
.github/lock.yml vendored
View File

@@ -32,4 +32,4 @@ setLockReason: true
# daysUntilLock: 30
# Repository to extend settings from
# _extends: repo
# _extends: repo

View File

@@ -1,8 +1,9 @@
<!--
Before you create a new PR, please consider the following two considerations.
Before you create a new PR, please consider:
1) Pull request for the MASTER branch will be closed.
1) Pull requests for the MAIN branch will be closed.
2) We cannot accept pull requests to add new currencies.
3) DO NOT include translations in your PR. Only English US sentences.
Thanks.
-->

50
.github/security.md vendored
View File

@@ -1,12 +1,54 @@
# Security Policy
Firefly III is an application to manage your personal finances. As such, the developer has adopted this security disclosure and response policy to ensure that critical issues are responsibly handled.
## Supported Versions
Only the latest Firefly III release is maintained. Applicable fixes, including security fixes, will not backported to older release branches. Please refer to [releases.md](https://github.com/firefly-iii/firefly-iii/blob/main/releases.md) for details.
Only the latest version of Firefly III is supported. If you're not running the latest version of Firefly III, please upgrade at your earliest convenience.
## Reporting a Vulnerability - Private Disclosure Process
Security is of the highest importance and all security vulnerabilities or suspected security vulnerabilities should be reported to Firefly III privately, to minimize attacks against current users of Firefly III before they are fixed. Vulnerabilities will be investigated and patched on the next patch (or minor) release as soon as possible. This information could be kept entirely internal to the project.
## Reporting a Vulnerability
If you know of a publicly disclosed security vulnerability for Firefly III, please **IMMEDIATELY** contact james@firefly-iii.org to inform the Firefly III developer. You can use my [GPG key](https://keybase.io/jc5) for extra security.
If you find something that compromises the security of Firefly III, you should [send me a message](mailto:james@firefly-iii.org) as soon as possible. These issues will be fixed immediately. You can also open an issue, but if you feel the issue is sensitive, please drop me a message instead.
**IMPORTANT: Do not file public issues on GitHub for security vulnerabilities**
You can use my [GPG key](https://keybase.io/jc5) for extra security. My [GitHub commits](https://github.com/firefly-iii/firefly-iii/commits/master) are almost always signed with this key.
To report a vulnerability or a security-related issue, please email the private address james@firefly-iii.org with the details of the vulnerability. The email will be received by the developer of Firefly III. Emails will be addressed within 3 business days, including a detailed plan to investigate the issue and any potential workarounds to perform in the meantime. Do not report non-security-impacting bugs through this channel. Use [GitHub issues](https://github.com/firefly-iii/firefly-iii/issues/new/choose) instead.
### Proposed Email Content
Provide a descriptive subject line and in the body of the email include the following information:
* Basic identity information, such as your name and your affiliation or company.
* Detailed steps to reproduce the vulnerability (POC scripts, screenshots, and compressed packet captures are all helpful to us).
* Description of the effects of the vulnerability on Firefly III and the related hardware and software configurations, so that the developer can reproduce it.
* How the vulnerability affects Firefly III usage and an estimation of the attack surface, if there is one.
* List other projects or dependencies that were used in conjunction with Firefly III to produce the vulnerability.
## When to report a vulnerability
* When you think Firefly III has a potential security vulnerability.
* When you suspect a potential vulnerability but you are unsure that it impacts Firefly III.
* When you know of or suspect a potential vulnerability on another project that is used by Firefly III. For example Firefly III has a dependency on Docker, MySQL, etc.
## Patch, Release, and Disclosure
The Firefly III developer will respond to vulnerability reports as follows:
1. The developer will investigate the vulnerability and determine its effects and criticality.
2. If the issue is not deemed to be a vulnerability, the developer will follow up with a detailed reason for rejection.
3. The developer will initiate a conversation with the reporter within 3 business days.
4. If a vulnerability is acknowledged and the timeline for a fix is determined, the developer will work on a plan to communicate with the appropriate community, including identifying mitigating steps that affected users can take to protect themselves until the fix is rolled out.
5. The developer will also create a [CVSS](https://www.first.org/cvss/specification-document) using the [CVSS Calculator](https://www.first.org/cvss/calculator/3.0). The developer makes the final call on the calculated CVSS; it is better to move quickly than making the CVSS perfect. Issues may also be reported to [Mitre](https://cve.mitre.org/) using this [scoring calculator](https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator). The CVE will initially be set to private.
6. The developer will work on fixing the vulnerability and perform internal testing before preparing to roll out the fix.
7. A public disclosure date is negotiated by the Firefly III developer and the bug submitter. We prefer to fully disclose the bug as soon as possible once a user mitigation or patch is available. It is reasonable to delay disclosure when the bug or the fix is not yet fully understood, the solution is not well-tested, or for distributor coordination. The timeframe for disclosure is from immediate (especially if its already publicly known) to a few weeks. For a critical vulnerability with a straightforward mitigation, we expect report date to public disclosure date to be on the order of 14 business days. The Firefly III developer holds the final say when setting a public disclosure date.
9. Once the fix is confirmed, the developer will patch the vulnerability in the next patch or minor release. Upon release of the patched version of Firefly III, we will follow the **Public Disclosure Process**.
### Public Disclosure Process
The developer publishes a public [advisory](https://github.com/firefly-iii/firefly-iii/security/advisories) to the Firefly III community via GitHub. In most cases, additional communication via Twitter, reddit and other channels will assist in educating Firefly III users and rolling out the patched release to affected users.
The develop will also publish any mitigating steps users can take until the fix can be applied to their Firefly III instances.
## Confidentiality, integrity and availability
We consider vulnerabilities leading to the compromise of data confidentiality, elevation of privilege, or integrity to be our highest priority concerns. Availability, in particular in areas relating to DoS and resource exhaustion, is also a serious security concern. The Firefly III developer takes all vulnerabilities, potential vulnerabilities, and suspected vulnerabilities seriously and will investigate them in an urgent and expeditious manner.
Note that we do not currently consider the default settings for Firefly III to be secure-by-default. It is necessary for operators to explicitly configure settings, role based access control, and other resource related features in Firefly III to provide a hardened Firefly III environment. We will not act on any security disclosure that relates to a lack of safe defaults. Over time, we will work towards improved safe-by-default configuration, taking into account backwards compatibility.
## Credits
This security policy is based on [Harbor](https://github.com/goharbor/harbor)'s security policy.

2
.gitignore vendored
View File

@@ -1,4 +1,6 @@
/node_modules
/frontend/node_modules
/frontend/fonts
/public/hot
/public/storage
/storage/*.key

View File

@@ -3,7 +3,7 @@
"description": "A free and open source personal finances manager",
"repository": "https://github.com/firefly-iii/firefly-iii",
"website": "https://firefly-iii.org/",
"logo": "https://raw.githubusercontent.com/firefly-iii/firefly-iii/master/public/mstile-150x150.png",
"logo": "https://raw.githubusercontent.com/firefly-iii/firefly-iii/main/public/mstile-150x150.png",
"keywords": [
"finance",
"finances",
@@ -41,7 +41,7 @@
{
"plan": "heroku-postgresql",
"options": {
"version": "9.5"
"version": "12"
}
}
],
@@ -58,8 +58,8 @@
],
"env": {
"APP_KEY": {
"description": "This key is used to encrypt your data.",
"description": "This key is used to create app cookies en secure attachments.",
"value": "base64:If1gJN4pyycXTq+WS5TjneDympKuu+8SKvTl6RZnhJg="
}
}
}
}

View File

@@ -31,6 +31,7 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Support\Http\Api\TransactionFilter;
use FireflyIII\Transformers\AccountTransformer;
use FireflyIII\Transformers\AttachmentTransformer;
use FireflyIII\Transformers\PiggyBankTransformer;
use FireflyIII\Transformers\TransactionGroupTransformer;
use FireflyIII\User;
@@ -49,8 +50,9 @@ use League\Fractal\Resource\Item;
class AccountController extends Controller
{
use AccountFilter, TransactionFilter;
/** @var AccountRepositoryInterface The account repository */
private $repository;
private AccountRepositoryInterface $repository;
public const RESOURCE_KEY = 'accounts';
/**
* AccountController constructor.
@@ -73,6 +75,35 @@ class AccountController extends Controller
);
}
/**
* @param Account $account
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function attachments(Account $account): JsonResponse
{
$manager = $this->getManager();
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$collection = $this->repository->getAttachments($account);
$count = $collection->count();
$attachments = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// make paginator:
$paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.accounts.attachments', [$account->id]) . $this->buildParams());
/** @var AttachmentTransformer $transformer */
$transformer = app(AttachmentTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($attachments, $transformer, 'attachments');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* Remove the specified resource from storage.
*
@@ -104,7 +135,7 @@ class AccountController extends Controller
// types to get, page size:
$types = $this->mapAccountTypes($this->parameters->get('type'));
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of accounts. Count it and split it.
$collection = $this->repository->getAccountsByType($types);
@@ -120,7 +151,7 @@ class AccountController extends Controller
$transformer = app(AccountTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($accounts, $transformer, 'accounts');
$resource = new FractalCollection($accounts, $transformer, self::RESOURCE_KEY);
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
@@ -142,7 +173,7 @@ class AccountController extends Controller
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of budgets. Count it and split it.
$collection = $this->repository->getPiggyBanks($account);
@@ -178,7 +209,7 @@ class AccountController extends Controller
/** @var AccountTransformer $transformer */
$transformer = app(AccountTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($account, $transformer, 'accounts');
$resource = new Item($account, $transformer, self::RESOURCE_KEY);
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
@@ -200,7 +231,7 @@ class AccountController extends Controller
$transformer = app(AccountTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($account, $transformer, 'accounts');
$resource = new Item($account, $transformer, self::RESOURCE_KEY);
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
@@ -218,7 +249,7 @@ class AccountController extends Controller
*/
public function transactions(Request $request, Account $account): JsonResponse
{
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$type = $request->get('type') ?? 'default';
$this->parameters->set('type', $type);
@@ -227,10 +258,8 @@ class AccountController extends Controller
if (null !== $limit && $limit > 0) {
$pageSize = $limit;
}
$types = $this->mapTransactionTypes($this->parameters->get('type'));
$manager = $this->getManager();
/** @var User $admin */
$admin = auth()->user();
@@ -240,7 +269,6 @@ class AccountController extends Controller
$collector->setUser($admin)->setAccounts(new Collection([$account]))
->withAPIInformation()->setLimit($pageSize)->setPage($this->parameters->get('page'))->setTypes($types);
// set range if necessary:
if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) {
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
}
@@ -277,7 +305,7 @@ class AccountController extends Controller
/** @var AccountTransformer $transformer */
$transformer = app(AccountTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($account, $transformer, 'accounts');
$resource = new Item($account, $transformer, self::RESOURCE_KEY);
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}

View File

@@ -23,10 +23,12 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers;
use FireflyIII\Api\V1\Middleware\ApiDemoUser;
use FireflyIII\Api\V1\Requests\AttachmentStoreRequest;
use FireflyIII\Api\V1\Requests\AttachmentUpdateRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
use FireflyIII\Http\Middleware\IsDemoUser;
use FireflyIII\Models\Attachment;
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
use FireflyIII\Transformers\AttachmentTransformer;
@@ -58,6 +60,7 @@ class AttachmentController extends Controller
public function __construct()
{
parent::__construct();
$this->middleware(ApiDemoUser::class)->except(['delete', 'download', 'show', 'index']);
$this->middleware(
function ($request, $next) {
/** @var User $user */
@@ -65,6 +68,7 @@ class AttachmentController extends Controller
$this->repository = app(AttachmentRepositoryInterface::class);
$this->repository->setUser($user);
return $next($request);
}
);
@@ -92,8 +96,8 @@ class AttachmentController extends Controller
* @param Attachment $attachment
*
* @codeCoverageIgnore
* @return LaravelResponse
* @throws FireflyException
* @return LaravelResponse
*/
public function download(Attachment $attachment): LaravelResponse
{
@@ -108,7 +112,7 @@ class AttachmentController extends Controller
if ('' === $content) {
throw new FireflyException('200002: File is empty (zero bytes).');
}
$quoted = sprintf('"%s"', addcslashes(basename($attachment->filename), '"\\'));
$quoted = sprintf('"%s"', addcslashes(basename($attachment->filename), '"\\'));
/** @var LaravelResponse $response */
$response = response($content);
@@ -139,7 +143,7 @@ class AttachmentController extends Controller
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of accounts. Count it and split it.
$collection = $this->repository->get();
@@ -184,8 +188,8 @@ class AttachmentController extends Controller
*
* @param AttachmentStoreRequest $request
*
* @return JsonResponse
* @throws FireflyException
* @return JsonResponse
*/
public function store(AttachmentStoreRequest $request): JsonResponse
{

View File

@@ -92,7 +92,7 @@ class AvailableBudgetController extends Controller
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$start = $this->parameters->get('start');
$end = $this->parameters->get('end');

View File

@@ -85,7 +85,7 @@ class BillController extends Controller
public function attachments(Bill $bill): JsonResponse
{
$manager = $this->getManager();
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$collection = $this->repository->getAttachments($bill);
$count = $collection->count();
@@ -130,7 +130,7 @@ class BillController extends Controller
{
$bills = $this->repository->getBills();
$manager = $this->getManager();
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$count = $bills->count();
$bills = $bills->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page'));
@@ -158,7 +158,7 @@ class BillController extends Controller
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of budgets. Count it and split it.
$collection = $this->repository->getRulesForBill($bill);
@@ -206,8 +206,8 @@ class BillController extends Controller
*
* @param BillRequest $request
*
* @return JsonResponse
* @throws FireflyException
* @return JsonResponse
*/
public function store(BillRequest $request): JsonResponse
{
@@ -235,7 +235,7 @@ class BillController extends Controller
*/
public function transactions(Request $request, Bill $bill): JsonResponse
{
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$type = $request->get('type') ?? 'default';
$this->parameters->set('type', $type);

View File

@@ -25,13 +25,15 @@ namespace FireflyIII\Api\V1\Controllers;
use Exception;
use FireflyIII\Api\V1\Requests\BudgetLimitRequest;
use FireflyIII\Api\V1\Requests\BudgetRequest;
use FireflyIII\Api\V1\Requests\BudgetStoreRequest;
use FireflyIII\Api\V1\Requests\BudgetUpdateRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\Budget;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Support\Http\Api\TransactionFilter;
use FireflyIII\Transformers\AttachmentTransformer;
use FireflyIII\Transformers\BudgetLimitTransformer;
use FireflyIII\Transformers\BudgetTransformer;
use FireflyIII\Transformers\TransactionGroupTransformer;
@@ -89,7 +91,7 @@ class BudgetController extends Controller
public function budgetLimits(Budget $budget): JsonResponse
{
$manager = $this->getManager();
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$this->parameters->set('budget_id', $budget->id);
$collection = $this->blRepository->getBudgetLimits($budget, $this->parameters->get('start'), $this->parameters->get('end'));
$count = $collection->count();
@@ -108,6 +110,35 @@ class BudgetController extends Controller
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* @param Budget $budget
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function attachments(Budget $budget): JsonResponse
{
$manager = $this->getManager();
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$collection = $this->repository->getAttachments($budget);
$count = $collection->count();
$attachments = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// make paginator:
$paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.budgets.attachments', [$budget->id]) . $this->buildParams());
/** @var AttachmentTransformer $transformer */
$transformer = app(AttachmentTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($attachments, $transformer, 'attachments');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* Remove the specified resource from storage.
*
@@ -134,7 +165,7 @@ class BudgetController extends Controller
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of budgets. Count it and split it.
$collection = $this->repository->getBudgets();
@@ -179,13 +210,13 @@ class BudgetController extends Controller
/**
* Store a budget.
*
* @param BudgetRequest $request
* @param BudgetStoreRequest $request
*
* @return JsonResponse
* @throws FireflyException
*
* @return JsonResponse
*/
public function store(BudgetRequest $request): JsonResponse
public function store(BudgetStoreRequest $request): JsonResponse
{
$budget = $this->repository->store($request->getAll());
$manager = $this->getManager();
@@ -205,8 +236,8 @@ class BudgetController extends Controller
* @param BudgetLimitRequest $request
* @param Budget $budget
*
* @return JsonResponse
* @throws Exception
* @return JsonResponse
*/
public function storeBudgetLimit(BudgetLimitRequest $request, Budget $budget): JsonResponse
{
@@ -236,7 +267,7 @@ class BudgetController extends Controller
*/
public function transactions(Request $request, Budget $budget): JsonResponse
{
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// user can overrule page size with limit parameter.
$limit = $this->parameters->get('limit');
@@ -291,12 +322,12 @@ class BudgetController extends Controller
/**
* Update a budget.
*
* @param BudgetRequest $request
* @param Budget $budget
* @param BudgetUpdateRequest $request
* @param Budget $budget
*
* @return JsonResponse
*/
public function update(BudgetRequest $request, Budget $budget): JsonResponse
public function update(BudgetUpdateRequest $request, Budget $budget): JsonResponse
{
$data = $request->getAll();
$budget = $this->repository->update($budget, $data);

View File

@@ -102,9 +102,9 @@ class BudgetLimitController extends Controller
public function index(Request $request): JsonResponse
{
$manager = $this->getManager();
$budgetId = (int)($request->get('budget_id') ?? 0);
$budgetId = (int) ($request->get('budget_id') ?? 0);
$budget = $this->repository->findNull($budgetId);
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$this->parameters->set('budget_id', $budgetId);
$collection = new Collection;
@@ -156,16 +156,16 @@ class BudgetLimitController extends Controller
*
* @param BudgetLimitRequest $request
*
* @return JsonResponse
* @throws FireflyException
*
* @return JsonResponse
*/
public function store(BudgetLimitRequest $request): JsonResponse
{
$data = $request->getAll();
$budget = $this->repository->findNull($data['budget_id']);
if (null === $budget) {
throw new FireflyException('200004: Budget does not exist.');
throw new FireflyException('200004: Budget does not exist.'); // @codeCoverageIgnore
}
$data['budget'] = $budget;
$budgetLimit = $this->blRepository->storeBudgetLimit($data);
@@ -191,7 +191,7 @@ class BudgetLimitController extends Controller
*/
public function transactions(Request $request, BudgetLimit $budgetLimit): JsonResponse
{
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$type = $request->get('type') ?? 'default';
$this->parameters->set('type', $type);

View File

@@ -29,6 +29,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\Category;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Support\Http\Api\TransactionFilter;
use FireflyIII\Transformers\AttachmentTransformer;
use FireflyIII\Transformers\CategoryTransformer;
use FireflyIII\Transformers\TransactionGroupTransformer;
use FireflyIII\User;
@@ -71,6 +72,35 @@ class CategoryController extends Controller
);
}
/**
* @param Category $category
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function attachments(Category $category): JsonResponse
{
$manager = $this->getManager();
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$collection = $this->repository->getAttachments($category);
$count = $collection->count();
$attachments = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// make paginator:
$paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.categories.attachments', [$category->id]) . $this->buildParams());
/** @var AttachmentTransformer $transformer */
$transformer = app(AttachmentTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($attachments, $transformer, 'attachments');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* Remove the specified resource from storage.
*
@@ -97,7 +127,7 @@ class CategoryController extends Controller
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of budgets. Count it and split it.
$collection = $this->repository->getCategories();
@@ -146,13 +176,13 @@ class CategoryController extends Controller
*
* @param CategoryRequest $request
*
* @return JsonResponse
* @throws FireflyException
* @return JsonResponse
*/
public function store(CategoryRequest $request): JsonResponse
{
$category = $this->repository->store($request->getAll());
$manager = $this->getManager();
$manager = $this->getManager();
/** @var CategoryTransformer $transformer */
$transformer = app(CategoryTransformer::class);
@@ -175,7 +205,7 @@ class CategoryController extends Controller
*/
public function transactions(Request $request, Category $category): JsonResponse
{
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$type = $request->get('type') ?? 'default';
$this->parameters->set('type', $type);

View File

@@ -42,10 +42,8 @@ use Illuminate\Http\JsonResponse;
class AccountController extends Controller
{
use ApiSupport;
/** @var CurrencyRepositoryInterface */
private $currencyRepository;
/** @var AccountRepositoryInterface */
private $repository;
private CurrencyRepositoryInterface $currencyRepository;
private AccountRepositoryInterface $repository;
/**
* AccountController constructor.
@@ -99,10 +97,10 @@ class AccountController extends Controller
// loop the end balances. This is an array for each account ($expenses)
foreach ($endBalances as $accountId => $expenses) {
$accountId = (int)$accountId;
$accountId = (int) $accountId;
// loop each expense entry (each entry can be a different currency).
foreach ($expenses as $currencyId => $endAmount) {
$currencyId = (int)$currencyId;
$currencyId = (int) $currencyId;
// see if there is an accompanying start amount.
// grab the difference and find the currency.
@@ -114,7 +112,7 @@ class AccountController extends Controller
$tempData[] = [
'name' => $accountNames[$accountId],
'difference' => $diff,
'diff_float' => (float)$diff,
'diff_float' => (float) $diff,
'currency_id' => $currencyId,
];
}
@@ -196,6 +194,8 @@ class AccountController extends Controller
'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places,
'start_date' => $start->format('Y-m-d'),
'end_date' => $end->format('Y-m-d'),
'type' => 'line', // line, area or bar
'yAxisID' => 0, // 0, 1, 2
'entries' => [],
@@ -247,10 +247,10 @@ class AccountController extends Controller
// loop the end balances. This is an array for each account ($expenses)
foreach ($endBalances as $accountId => $expenses) {
$accountId = (int)$accountId;
$accountId = (int) $accountId;
// loop each expense entry (each entry can be a different currency).
foreach ($expenses as $currencyId => $endAmount) {
$currencyId = (int)$currencyId;
$currencyId = (int) $currencyId;
// see if there is an accompanying start amount.
// grab the difference and find the currency.
@@ -263,7 +263,7 @@ class AccountController extends Controller
'name' => $accountNames[$accountId],
'difference' => bcmul($diff, '-1'),
// For some reason this line is never covered in code coverage:
'diff_float' => ((float)$diff) * -1, // @codeCoverageIgnore
'diff_float' => ((float) $diff) * -1, // @codeCoverageIgnore
'currency_id' => $currencyId,
];
}

View File

@@ -83,9 +83,9 @@ class AvailableBudgetController extends Controller
$spent = $spentInfo['amount'];
}
}
$left = bcadd($availableBudget->amount, (string)$spent);
$left = bcadd($availableBudget->amount, (string) $spent);
// left less than zero? Set to zero.
if (bccomp($left, '0') === -1) {
if (-1 === bccomp($left, '0')) {
$left = '0';
}

View File

@@ -0,0 +1,298 @@
<?php
/**
* BudgetController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Chart;
use Carbon\Carbon;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\DateRequest;
use FireflyIII\Models\Budget;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Collection;
/**
* Class BudgetController
*/
class BudgetController extends Controller
{
private BudgetLimitRepositoryInterface $blRepository;
private OperationsRepositoryInterface $opsRepository;
private BudgetRepositoryInterface $repository;
/**
* BudgetController constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
//$this->generator = app(GeneratorInterface::class);
$this->repository = app(BudgetRepositoryInterface::class);
$this->opsRepository = app(OperationsRepositoryInterface::class);
$this->blRepository = app(BudgetLimitRepositoryInterface::class);
//$this->nbRepository = app(NoBudgetRepositoryInterface::class);
return $next($request);
}
);
}
/**
* [
* 'label' => 'label for entire set'
* 'currency_id' => 0,
* 'currency_code' => 'EUR',
* 'currency_symbol' => '$',
* 'currency_decimal_places' => 2,
* 'type' => 'bar', // line, area or bar
* 'yAxisID' => 0, // 0, 1, 2
* 'entries' => ['a' => 1, 'b' => 4],
* ],
*
* @param DateRequest $request
*
* @return JsonResponse
*/
public function overview(DateRequest $request): JsonResponse
{
$dates = $request->getAll();
$budgets = $this->repository->getActiveBudgets();
$budgetNames = [];
$currencyNames = [];
$sets = [];
/** @var Budget $budget */
foreach ($budgets as $budget) {
$expenses = $this->getExpenses($budget, $dates['start'], $dates['end']);
$expenses = $this->filterNulls($expenses);
foreach ($expenses as $set) {
$budgetNames[] = $set['budget_name'];
$currencyNames[] = $set['currency_name'];
$sets[] = $set;
}
}
$budgetNames = array_unique($budgetNames);
$currencyNames = array_unique($currencyNames);
$basic = $this->createSets($budgetNames, $currencyNames);
$filled = $this->fillSets($basic, $sets);
$keys = array_values($filled);
return response()->json($keys);
}
/**
* @param Collection $limits
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
protected function getExpenses(Budget $budget, Carbon $start, Carbon $end): array
{
$limits = $this->blRepository->getBudgetLimits($budget, $start, $end);
if (0 === $limits->count()) {
return $this->getExpenseInRange($budget, $start, $end);
}
$arr = [];
/** @var BudgetLimit $limit */
foreach ($limits as $limit) {
$arr[] = $this->getExpensesForLimit($limit);
}
return $arr;
}
/**
* @param array $budgetNames
* @param array $currencyNames
*
* @return array
*/
private function createSets(array $budgetNames, array $currencyNames): array
{
$return = [];
foreach ($currencyNames as $currencyName) {
$entries = [];
foreach ($budgetNames as $budgetName) {
$label = sprintf('%s (%s)', $budgetName, $currencyName);
$entries[$label] = '0';
}
// left
$return['left'] = [
'label' => sprintf('%s (%s)', trans('firefly.left'), $currencyName),
'data_type' => 'left',
'currency_name' => $currencyName,
'type' => 'bar',
'yAxisID' => 0, // 0, 1, 2
'entries' => $entries,
];
// spent_capped
$return['spent_capped'] = [
'label' => sprintf('%s (%s)', trans('firefly.spent'), $currencyName),
'data_type' => 'spent_capped',
'currency_name' => $currencyName,
'type' => 'bar',
'yAxisID' => 0, // 0, 1, 2
'entries' => $entries,
];
// overspent
$return['overspent'] = [
'label' => sprintf('%s (%s)', trans('firefly.overspent'), $currencyName),
'data_type' => 'overspent',
'currency_name' => $currencyName,
'type' => 'bar',
'yAxisID' => 0, // 0, 1, 2
'entries' => $entries,
];
}
return $return;
}
/**
* @param array $basic
* @param array $sets
*
* @return array
*/
private function fillSets(array $basic, array $sets): array
{
foreach ($sets as $set) {
$label = $set['label'];
//$basic['spent']['entries'][$label] = $set['entries']['spent'];
$basic['spent_capped']['entries'][$label] = $set['entries']['spent_capped'];
$basic['left']['entries'][$label] = $set['entries']['left'];
$basic['overspent']['entries'][$label] = $set['entries']['overspent'];
}
return $basic;
}
/**
* @param array $expenses
*
* @return array
*/
private function filterNulls(array $expenses): array
{
$return = [];
/** @var array|null $arr */
foreach ($expenses as $arr) {
if (null !== $arr) {
$return[] = $arr;
}
}
return $return;
}
/**
* @param Budget $budget
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
private function getExpenseInRange(Budget $budget, Carbon $start, Carbon $end): array
{
$spent = $this->opsRepository->sumExpenses($start, $end, null, new Collection([$budget]), null);
$return = [];
/** @var array $set */
foreach ($spent as $set) {
$current = [
'label' => sprintf('%s (%s)', $budget->name, $set['currency_name']),
'budget_name' => $budget->name,
'start_date' => $start->format('Y-m-d'),
'end_date' => $end->format('Y-m-d'),
'currency_id' => (int) $set['currency_id'],
'currency_code' => $set['currency_code'],
'currency_name' => $set['currency_name'],
'currency_symbol' => $set['currency_symbol'],
'currency_decimal_places' => (int) $set['currency_decimal_places'],
'type' => 'bar', // line, area or bar,
'entries' => [],
];
$sumSpent = bcmul($set['sum'], '-1'); // spent
$current['entries']['spent'] = $sumSpent;
$current['entries']['amount'] = '0';
$current['entries']['spent_capped'] = $sumSpent;
$current['entries']['left'] = '0';
$current['entries']['overspent'] = '0';
$return[] = $current;
}
return $return;
}
/**
* @param BudgetLimit $limit
*
* @return array|null
*/
private function getExpensesForLimit(BudgetLimit $limit): ?array
{
$budget = $limit->budget;
$spent = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, null, new Collection([$budget]), $limit->transactionCurrency);
$currency = $limit->transactionCurrency;
// when limited to a currency, the count is always one. Or it's empty.
$set = array_shift($spent);
if (null === $set) {
return null;
}
$return = [
'label' => sprintf('%s (%s)', $budget->name, $set['currency_name']),
'budget_name' => $budget->name,
'start_date' => $limit->start_date->format('Y-m-d'),
'end_date' => $limit->end_date->format('Y-m-d'),
'currency_id' => (int) $currency->id,
'currency_code' => $currency->code,
'currency_name' => $currency->name,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => (int) $currency->decimal_places,
'type' => 'bar', // line, area or bar,
'entries' => [],
];
$sumSpent = bcmul($set['sum'], '-1'); // spent
$return['entries']['spent'] = $sumSpent;
$return['entries']['amount'] = $limit->amount;
$return['entries']['spent_capped'] = 1 === bccomp($sumSpent, $limit->amount) ? $limit->amount : $sumSpent;
$return['entries']['left'] = 1 === bccomp($limit->amount, $sumSpent) ? bcadd($set['sum'], $limit->amount) : '0'; // left
$return['entries']['overspent'] = 1 === bccomp($limit->amount, $sumSpent) ? '0' : bcmul(bcadd($set['sum'], $limit->amount), '-1'); // overspent
return $return;
}
}

View File

@@ -74,8 +74,6 @@ class CategoryController extends Controller
* @param DateRequest $request
*
* @return JsonResponse
*
* TODO after 4.8,0, simplify
*/
public function overview(DateRequest $request): JsonResponse
{
@@ -89,50 +87,29 @@ class CategoryController extends Controller
$tempData = [];
$spentWith = $this->opsRepository->listExpenses($start, $end);
$earnedWith = $this->opsRepository->listIncome($start, $end);
$spentWithout = $this->noCatRepository->listExpenses($start, $end); // refactored
$earnedWithout = $this->noCatRepository->listIncome($start, $end); // refactored
$spentWithout = $this->noCatRepository->listExpenses($start, $end);
$categories = [];
foreach ([$spentWith, $earnedWith, $spentWithout, $earnedWithout] as $set) {
foreach ([$spentWith, $spentWithout,] as $set) {
foreach ($set as $currency) {
foreach ($currency['categories'] as $category) {
$categories[] = $category['name'];
$inKey = sprintf('%d-i', $currency['currency_id']);
$outKey = sprintf('%d-e', $currency['currency_id']);
// make data arrays if not yet present.
$tempData[$inKey] = $tempData[$inKey] ?? [
'currency_id' => $currency['currency_id'],
'label' => (string)trans('firefly.box_earned_in_currency', ['currency' => $currency['currency_name']]),
'currency_code' => $currency['currency_code'],
'currency_symbol' => $currency['currency_symbol'],
'currency_decimal_places' => $currency['currency_decimal_places'],
'type' => 'bar', // line, area or bar
'yAxisID' => 0, // 0, 1, 2
'entries' => [
// per category:
// "category" => 5,
],
];
$tempData[$outKey] = $tempData[$outKey] ?? [
'currency_id' => $currency['currency_id'],
'label' => (string)trans('firefly.box_spent_in_currency', ['currency' => $currency['currency_name']]),
'label' => (string) trans('firefly.box_spent_in_currency', ['currency' => $currency['currency_name']]),
'currency_code' => $currency['currency_code'],
'currency_symbol' => $currency['currency_symbol'],
'currency_decimal_places' => $currency['currency_decimal_places'],
'type' => 'bar', // line, area or bar
'yAxisID' => 0, // 0, 1, 2
'entries' => [
// per category:
// "category" => 5,
],
'entries' => [],
];
foreach ($category['transaction_journals'] as $journal) {
// is it expense or income?
$letter = -1 === bccomp($journal['amount'], '0') ? 'e' : 'i';
$currentKey = sprintf('%d-%s', $currency['currency_id'], $letter);
$currentKey = sprintf('%d-%s', $currency['currency_id'], 'e');
$name = $category['name'];
$tempData[$currentKey]['entries'][$name] = $tempData[$currentKey]['entries'][$name] ?? '0';
$tempData[$currentKey]['entries'][$name] = bcadd($tempData[$currentKey]['entries'][$name], $journal['amount']);
@@ -141,49 +118,6 @@ class CategoryController extends Controller
}
}
// foreach ([] as $set) {
// foreach ($set as $currency) {
// $inKey = sprintf('%d-i', $currency['currency_id']);
// $outKey = sprintf('%d-e', $currency['currency_id']);
// $categories[] = (string)trans('firefly.no_category');
// // make data arrays if not yet present.
// $tempData[$inKey] = $tempData[$inKey] ?? [
// 'currency_id' => $currency['currency_id'],
// 'label' => (string)trans('firefly.box_earned_in_currency', ['currency' => $currency['currency_name']]),
// 'currency_code' => $currency['currency_code'],
// 'currency_symbol' => $currency['currency_symbol'],
// 'currency_decimal_places' => $currency['currency_decimal_places'],
// 'type' => 'bar', // line, area or bar
// 'yAxisID' => 0, // 0, 1, 2
// 'entries' => [
// // per category:
// // "category" => 5,
// ],
// ];
// $tempData[$outKey] = $tempData[$outKey] ?? [
// 'currency_id' => $currency['currency_id'],
// 'label' => (string)trans('firefly.box_spent_in_currency', ['currency' => $currency['currency_name']]),
// 'currency_code' => $currency['currency_code'],
// 'currency_symbol' => $currency['currency_symbol'],
// 'currency_decimal_places' => $currency['currency_decimal_places'],
// 'type' => 'bar', // line, area or bar
// 'yAxisID' => 0, // 0, 1, 2
// 'entries' => [
// // per category:
// // "category" => 5,
// ],
// ];
// foreach ($currency['transaction_journals'] as $journal) {
// // is it expense or income?
// $letter = -1 === bccomp($journal['amount'], '0') ? 'e' : 'i';
// $currentKey = sprintf('%d-%s', $currency['currency_id'], $letter);
// $name = (string)trans('firefly.no_category');
// $tempData[$currentKey]['entries'][$name] = $tempData[$currentKey]['entries'][$name] ?? '0';
// $tempData[$currentKey]['entries'][$name] = bcadd($tempData[$currentKey]['entries'][$name], $journal['amount']);
// }
// }
// }
// re-sort every spent array and add 0 for missing entries.
foreach ($tempData as $index => $set) {
$oldSet = $set['entries'];

View File

@@ -51,7 +51,6 @@ class ConfigurationController extends Controller
parent::__construct();
$this->middleware(
function ($request, $next) {
/** @noinspection UnusedConstructorDependenciesInspection */
$this->repository = app(UserRepositoryInterface::class);
/** @var User $admin */
$admin = auth()->user();
@@ -109,13 +108,12 @@ class ConfigurationController extends Controller
$lastCheck = app('fireflyconfig')->get('last_update_check');
/** @var Configuration $singleUser */
$singleUser = app('fireflyconfig')->get('single_user_mode');
$data = [
return [
'is_demo_site' => null === $isDemoSite ? null : $isDemoSite->data,
'permission_update_check' => null === $updateCheck ? null : (int)$updateCheck->data,
'last_update_check' => null === $lastCheck ? null : (int)$lastCheck->data,
'permission_update_check' => null === $updateCheck ? null : (int) $updateCheck->data,
'last_update_check' => null === $lastCheck ? null : (int) $lastCheck->data,
'single_user_mode' => null === $singleUser ? null : $singleUser->data,
];
return $data;
}
}

View File

@@ -104,7 +104,7 @@ class Controller extends BaseController
private function getParameters(): ParameterBag
{
$bag = new ParameterBag;
$page = (int)request()->get('page');
$page = (int) request()->get('page');
if (0 === $page) {
$page = 1;
}
@@ -131,7 +131,7 @@ class Controller extends BaseController
foreach ($integers as $integer) {
$value = request()->query->get($integer);
if (null !== $value) {
$bag->set($integer, (int)$value);
$bag->set($integer, (int) $value);
}
}

View File

@@ -116,7 +116,7 @@ class CurrencyController extends Controller
// types to get, page size:
$types = $this->mapAccountTypes($this->parameters->get('type'));
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of accounts. Count it and split it.
/** @var AccountRepositoryInterface $accountRepository */
@@ -126,7 +126,7 @@ class CurrencyController extends Controller
// filter list on currency preference:
$collection = $unfiltered->filter(
static function (Account $account) use ($currency, $accountRepository) {
$currencyId = (int)$accountRepository->getMetaValue($account, 'currency_id');
$currencyId = (int) $accountRepository->getMetaValue($account, 'currency_id');
return $currencyId === $currency->id;
}
@@ -165,7 +165,7 @@ class CurrencyController extends Controller
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of available budgets. Count it and split it.
@@ -209,7 +209,7 @@ class CurrencyController extends Controller
/** @var BillRepositoryInterface $repository */
$repository = app(BillRepositoryInterface::class);
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$unfiltered = $repository->getBills();
// filter and paginate list:
@@ -249,7 +249,7 @@ class CurrencyController extends Controller
$blRepository = app(BudgetLimitRepositoryInterface::class);
$manager = $this->getManager();
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$collection = $blRepository->getAllBudgetLimitsByCurrency($currency, $this->parameters->get('start'), $this->parameters->get('end'));
$count = $collection->count();
$budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
@@ -278,7 +278,7 @@ class CurrencyController extends Controller
{
// create some objects:
$manager = $this->getManager();
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$collection = $this->repository->getExchangeRates($currency);
@@ -302,9 +302,9 @@ class CurrencyController extends Controller
*
* @param TransactionCurrency $currency
*
* @return JsonResponse
* @throws FireflyException
* @codeCoverageIgnore
* @return JsonResponse
*/
public function delete(TransactionCurrency $currency): JsonResponse
{
@@ -391,7 +391,7 @@ class CurrencyController extends Controller
*/
public function index(): JsonResponse
{
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$collection = $this->repository->getAll();
$count = $collection->count();
// slice them:
@@ -455,7 +455,7 @@ class CurrencyController extends Controller
{
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of budgets. Count it and split it.
/** @var RecurringRepositoryInterface $repository */
@@ -506,7 +506,7 @@ class CurrencyController extends Controller
public function rules(TransactionCurrency $currency): JsonResponse
{
$manager = $this->getManager();
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of budgets. Count it and split it.
/** @var RuleRepositoryInterface $repository */
@@ -567,13 +567,34 @@ class CurrencyController extends Controller
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* Show a currency.
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function showDefault(): JsonResponse
{
$manager = $this->getManager();
$currency = app('amount')->getDefaultCurrencyByUser(auth()->user());
$this->parameters->set('defaultCurrency', $currency);
/** @var CurrencyTransformer $transformer */
$transformer = app(CurrencyTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($currency, $transformer, 'currencies');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* Store new currency.
*
* @param CurrencyRequest $request
*
* @return JsonResponse
* @throws FireflyException
* @return JsonResponse
*/
public function store(CurrencyRequest $request): JsonResponse
{
@@ -607,7 +628,7 @@ class CurrencyController extends Controller
*/
public function transactions(Request $request, TransactionCurrency $currency): JsonResponse
{
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$type = $request->get('type') ?? 'default';
$this->parameters->set('type', $type);

View File

@@ -69,8 +69,8 @@ class CurrencyExchangeRateController extends Controller
*
* @param Request $request
*
* @return JsonResponse
* @throws FireflyException
* @return JsonResponse
*/
public function index(Request $request): JsonResponse
{

View File

@@ -0,0 +1,278 @@
<?php
/**
* DestroyController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Data;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\DataDestroyRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use FireflyIII\Services\Internal\Destroy\AccountDestroyService;
use FireflyIII\Services\Internal\Destroy\JournalDestroyService;
use Illuminate\Http\JsonResponse;
/**
* Class DestroyController
*/
class DestroyController extends Controller
{
/**
* @return JsonResponse
*/
public function destroy(DataDestroyRequest $request): JsonResponse
{
$objects = $request->getObjects();
switch ($objects) {
default:
throw new FireflyException(sprintf('This endpoint can\'t handle object "%s"', $objects));
case 'budgets':
$this->destroyBudgets();
break;
case 'bills':
$this->destroyBills();
break;
case 'piggy_banks':
$this->destroyPiggyBanks();
break;
case 'rules':
$this->destroyRules();
break;
case 'recurring':
$this->destroyRecurringTransactions();
break;
case 'categories':
$this->destroyCategories();
break;
case 'tags':
$this->destroyTags();
break;
case 'object_groups':
$this->destroyObjectGroups();
break;
case 'accounts':
$this->destroyAccounts(
[
AccountType::ASSET, AccountType::DEFAULT,
AccountType::BENEFICIARY, AccountType::EXPENSE,
AccountType::REVENUE, AccountType::INITIAL_BALANCE,
AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD,
]
);
break;
case 'asset_accounts':
$this->destroyAccounts(
[
AccountType::ASSET, AccountType::DEFAULT,
]
);
break;
case 'expense_accounts':
$this->destroyAccounts(
[
AccountType::BENEFICIARY, AccountType::EXPENSE,
]
);
break;
case 'revenue_accounts':
$this->destroyAccounts(
[
AccountType::REVENUE,
]
);
break;
case 'liabilities':
$this->destroyAccounts(
[
AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD,
]
);
break;
case 'transactions':
$this->destroyTransactions(
[
TransactionType::WITHDRAWAL,
TransactionType::DEPOSIT,
TransactionType::TRANSFER,
TransactionType::RECONCILIATION,
TransactionType::OPENING_BALANCE,
]
);
break;
case 'withdrawals':
$this->destroyTransactions(
[
TransactionType::WITHDRAWAL,
]
);
break;
case 'deposits':
$this->destroyTransactions(
[
TransactionType::DEPOSIT,
]
);
break;
case 'transfers':
$this->destroyTransactions(
[
TransactionType::TRANSFER,
]
);
break;
}
return response()->json([], 204);
}
/**
* @param array $types
*/
private function destroyAccounts(array $types): void
{
/** @var AccountRepositoryInterface $repository */
$repository = app(AccountRepositoryInterface::class);
$collection = $repository->getAccountsByType($types);
$service = app(AccountDestroyService::class);
/** @var Account $account */
foreach ($collection as $account) {
$service->destroy($account, null);
}
}
/**
*
*/
private function destroyBills(): void
{
/** @var BillRepositoryInterface $repository */
$repository = app(BillRepositoryInterface::class);
$repository->destroyAll();
}
/**
*
*/
private function destroyBudgets(): void
{
/** @var AvailableBudgetRepositoryInterface $abRepository */
$abRepository = app(AvailableBudgetRepositoryInterface::class);
$abRepository->destroyAll();
/** @var BudgetLimitRepositoryInterface $blRepository */
$blRepository = app(BudgetLimitRepositoryInterface::class);
$blRepository->destroyAll();
/** @var BudgetRepositoryInterface $budgetRepository */
$budgetRepository = app(BudgetRepositoryInterface::class);
$budgetRepository->destroyAll();
}
/**
*
*/
private function destroyCategories(): void
{
/** @var CategoryRepositoryInterface $categoryRepos */
$categoryRepos = app(CategoryRepositoryInterface::class);
$categoryRepos->destroyAll();
}
private function destroyObjectGroups(): void
{
/** @var ObjectGroupRepositoryInterface $repository */
$repository = app(ObjectGroupRepositoryInterface::class);
$repository->deleteAll();
}
/**
*
*/
private function destroyPiggyBanks(): void
{
/** @var PiggyBankRepositoryInterface $repository */
$repository = app(PiggyBankRepositoryInterface::class);
$repository->destroyAll();
}
/**
*
*/
private function destroyRecurringTransactions(): void
{
/** @var RecurringRepositoryInterface $repository */
$repository = app(RecurringRepositoryInterface::class);
$repository->destroyAll();
}
/**
*
*/
private function destroyRules(): void
{
/** @var RuleGroupRepositoryInterface $repository */
$repository = app(RuleGroupRepositoryInterface::class);
$repository->destroyAll();
}
/**
*
*/
private function destroyTags(): void
{
/** @var TagRepositoryInterface $tagRepository */
$tagRepository = app(TagRepositoryInterface::class);
$tagRepository->destroyAll();
}
/**
* @param array $types
*/
private function destroyTransactions(array $types): void
{
/** @var JournalRepositoryInterface $repository */
$repository = app(JournalRepositoryInterface::class);
$journals = $repository->findByType($types);
$service = app(JournalDestroyService::class);
/** @var TransactionJournal $journal */
foreach($journals as $journal) {
$service->destroy($journal);
}
}
}

View File

@@ -1,178 +0,0 @@
<?php
/**
* ImportController.php
* Copyright (c) 2019 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\ImportJob;
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
use FireflyIII\Support\Http\Api\TransactionFilter;
use FireflyIII\Transformers\ImportJobTransformer;
use FireflyIII\Transformers\TransactionGroupTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Resource\Collection as FractalCollection;
use League\Fractal\Resource\Item;
/**
* Class ImportController
*/
class ImportController extends Controller
{
use TransactionFilter;
/** @var ImportJobRepositoryInterface Import job repository. */
private $repository;
/**
* ImportController constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
/** @var User $user */
$user = auth()->user();
$this->repository = app(ImportJobRepositoryInterface::class);
$this->repository->setUser($user);
return $next($request);
}
);
}
/**
* @return JsonResponse
* @codeCoverageIgnore
*/
public function listAll(): JsonResponse
{
// create some objects:
$manager = $this->getManager();
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of accounts. Count it and split it.
$collection = $this->repository->get();
$count = $collection->count();
$importJobs = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// make paginator:
$paginator = new LengthAwarePaginator($importJobs, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.import.list') . $this->buildParams());
/** @var ImportJobTransformer $transformer */
$transformer = app(ImportJobTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($importJobs, $transformer, 'import_jobs');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* @param ImportJob $importJob
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function show(ImportJob $importJob): JsonResponse
{
$manager = $this->getManager();
/** @var ImportJobTransformer $transformer */
$transformer = app(ImportJobTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($importJob, $transformer, 'import_jobs');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* Show all transactions
*
* @param Request $request
* @param ImportJob $importJob
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function transactions(Request $request, ImportJob $importJob): JsonResponse
{
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$type = $request->get('type') ?? 'default';
$this->parameters->set('type', $type);
$types = $this->mapTransactionTypes($this->parameters->get('type'));
$manager = $this->getManager();
$tag = $importJob->tag;
$transactions = new Collection();
$paginator = new LengthAwarePaginator($transactions, 0, $pageSize);
$paginator->setPath(route('api.v1.import.transactions', [$importJob->key]) . $this->buildParams());
if (null !== $tag) {
/** @var User $admin */
$admin = auth()->user();
// use new group collector:
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector
->setUser($admin)
// filter on tag.
->setTag($tag)
// all info needed for the API:
->withAPIInformation()
// set page size:
->setLimit($pageSize)
// set page to retrieve
->setPage($this->parameters->get('page'))
// set types of transactions to return.
->setTypes($types);
if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) {
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
}
$paginator = $collector->getPaginatedGroups();
$paginator->setPath(route('api.v1.transactions.index') . $this->buildParams());
$transactions = $paginator->getCollection();
}
/** @var TransactionGroupTransformer $transformer */
$transformer = app(TransactionGroupTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($transactions, $transformer, 'transactions');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
}

View File

@@ -79,9 +79,9 @@ class LinkTypeController extends Controller
*
* @param LinkType $linkType
*
* @return JsonResponse
* @throws FireflyException
* @codeCoverageIgnore
* @return JsonResponse
*/
public function delete(LinkType $linkType): JsonResponse
{
@@ -103,7 +103,7 @@ class LinkTypeController extends Controller
{
// create some objects:
$manager = $this->getManager();
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of accounts. Count it and split it.
$collection = $this->repository->get();
@@ -151,8 +151,8 @@ class LinkTypeController extends Controller
*
* @param LinkTypeRequest $request
*
* @return JsonResponse
* @throws FireflyException
* @return JsonResponse
*/
public function store(LinkTypeRequest $request): JsonResponse
{
@@ -187,7 +187,7 @@ class LinkTypeController extends Controller
*/
public function transactions(Request $request, LinkType $linkType): JsonResponse
{
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$type = $request->get('type') ?? 'default';
$this->parameters->set('type', $type);
@@ -241,8 +241,8 @@ class LinkTypeController extends Controller
* @param LinkTypeRequest $request
* @param LinkType $linkType
*
* @return JsonResponse
* @throws FireflyException
* @return JsonResponse
*/
public function update(LinkTypeRequest $request, LinkType $linkType): JsonResponse
{

View File

@@ -0,0 +1,196 @@
<?php
/**
* GroupController.php
* Copyright (c) 2019 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers;
use FireflyIII\Api\V1\Requests\ObjectGroupUpdateRequest;
use FireflyIII\Models\Account;
use FireflyIII\Models\ObjectGroup;
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface;
use FireflyIII\Transformers\ObjectGroupTransformer;
use FireflyIII\Transformers\PiggyBankTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Resource\Collection as FractalCollection;
use League\Fractal\Resource\Item;
/**
* Class GroupController.
*
*/
class ObjectGroupController extends Controller
{
private ObjectGroupRepositoryInterface $repository;
/**
* ObjectGroupController constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
/** @var User $user */
$user = auth()->user();
$this->repository = app(ObjectGroupRepositoryInterface::class);
$this->repository->setUser($user);
return $next($request);
}
);
}
/**
* Remove the specified resource from storage.
*
* @param ObjectGroup $objectGroup
*
* @codeCoverageIgnore
* @return JsonResponse
*/
public function delete(ObjectGroup $objectGroup): JsonResponse
{
$this->repository->destroy($objectGroup);
return response()->json([], 204);
}
/**
* Display a listing of the resource.
*
* @param Request $request
*
* @codeCoverageIgnore
* @return JsonResponse
*/
public function index(Request $request): JsonResponse
{
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of accounts. Count it and split it.
$collection = $this->repository->get();
$count = $collection->count();
$objectGroups = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// make paginator:
$paginator = new LengthAwarePaginator($objectGroups, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.object-groups.index') . $this->buildParams());
/** @var ObjectGroupTransformer $transformer */
$transformer = app(ObjectGroupTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($objectGroups, $transformer, 'object_groups');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* List all piggies under the object group.
*
* @param ObjectGroup $objectGroup
*
* @return JsonResponse
* @codeCoverageIgnore
*
*/
public function piggyBanks(ObjectGroup $objectGroup): JsonResponse
{
// create some objects:
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of piggy banks. Count it and split it.
$collection = $this->repository->getPiggyBanks($objectGroup);
$count = $collection->count();
$piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// make paginator:
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.object-groups.piggy_banks', [$objectGroup->id]) . $this->buildParams());
/** @var PiggyBankTransformer $transformer */
$transformer = app(PiggyBankTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($piggyBanks, $transformer, 'piggy_banks');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* Show single instance.
*
* @param ObjectGroup $objectGroup
*
* @return JsonResponse
*/
public function show(ObjectGroup $objectGroup): JsonResponse
{
$manager = $this->getManager();
/** @var ObjectGroupTransformer $transformer */
$transformer = app(ObjectGroupTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($objectGroup, $transformer, 'object_groups');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* Update object.
*
* @param ObjectGroupUpdateRequest $request
* @param Account $account
*
* @return JsonResponse
*/
public function update(ObjectGroupUpdateRequest $request, ObjectGroup $objectGroup): JsonResponse
{
$data = $request->getUpdateData();
$this->repository->update($objectGroup, $data);
$this->repository->sort();
$manager = $this->getManager();
/** @var ObjectGroupTransformer $transformer */
$transformer = app(ObjectGroupTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($objectGroup, $transformer, 'object_groups');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
}

View File

@@ -24,9 +24,11 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers;
use FireflyIII\Api\V1\Requests\PiggyBankRequest;
use FireflyIII\Api\V1\Requests\PiggyBankStoreRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Transformers\AttachmentTransformer;
use FireflyIII\Transformers\PiggyBankEventTransformer;
use FireflyIII\Transformers\PiggyBankTransformer;
use FireflyIII\User;
@@ -83,6 +85,36 @@ class PiggyBankController extends Controller
return response()->json([], 204);
}
/**
* @param PiggyBank $piggyBank
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function attachments(PiggyBank $piggyBank): JsonResponse
{
$manager = $this->getManager();
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$collection = $this->repository->getAttachments($piggyBank);
$count = $collection->count();
$attachments = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// make paginator:
$paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.piggy_banks.attachments', [$piggyBank->id]) . $this->buildParams());
/** @var AttachmentTransformer $transformer */
$transformer = app(AttachmentTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($attachments, $transformer, 'attachments');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* List all of them.
*
@@ -93,7 +125,7 @@ class PiggyBankController extends Controller
{
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of budgets. Count it and split it.
$collection = $this->repository->getPiggyBanks();
@@ -126,7 +158,7 @@ class PiggyBankController extends Controller
public function piggyBankEvents(PiggyBank $piggyBank): JsonResponse
{
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$manager = $this->getManager();
$collection = $this->repository->getEvents($piggyBank);
@@ -173,15 +205,15 @@ class PiggyBankController extends Controller
/**
* Store new object.
*
* @param PiggyBankRequest $request
* @param PiggyBankStoreRequest $request
*
* @return JsonResponse
* @throws FireflyException
* @return JsonResponse
*/
public function store(PiggyBankRequest $request): JsonResponse
public function store(PiggyBankStoreRequest $request): JsonResponse
{
$piggyBank = $this->repository->store($request->getAll());
$manager = $this->getManager();
$manager = $this->getManager();
/** @var PiggyBankTransformer $transformer */
$transformer = app(PiggyBankTransformer::class);
@@ -209,7 +241,6 @@ class PiggyBankController extends Controller
$this->repository->setCurrentAmount($piggyBank, $data['current_amount']);
}
$manager = $this->getManager();
/** @var PiggyBankTransformer $transformer */
$transformer = app(PiggyBankTransformer::class);

View File

@@ -147,10 +147,10 @@ class PreferenceController extends Controller
$newValue = explode(',', $data['data']);
break;
case 'listPageSize':
$newValue = (int)$data['data'];
$newValue = (int) $data['data'];
break;
case 'customFiscalYear':
$newValue = 1 === (int)$data['data'];
$newValue = 1 === (int) $data['data'];
break;
}
$result = app('preferences')->set($preference->name, $newValue);

View File

@@ -99,7 +99,7 @@ class RecurrenceController extends Controller
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of budgets. Count it and split it.
$collection = $this->repository->getAll();
@@ -149,8 +149,8 @@ class RecurrenceController extends Controller
*
* @param RecurrenceStoreRequest $request
*
* @return JsonResponse
* @throws FireflyException
* @return JsonResponse
*/
public function store(RecurrenceStoreRequest $request): JsonResponse
{
@@ -178,7 +178,7 @@ class RecurrenceController extends Controller
*/
public function transactions(Request $request, Recurrence $recurrence): JsonResponse
{
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$type = $request->get('type') ?? 'default';
$this->parameters->set('type', $type);
@@ -224,9 +224,9 @@ class RecurrenceController extends Controller
}
/**
* @return JsonResponse
* @throws FireflyException
* @codeCoverageIgnore
* @return JsonResponse
*/
public function trigger(): JsonResponse
{

View File

@@ -105,7 +105,7 @@ class RuleController extends Controller
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of budgets. Count it and split it.
$collection = $this->ruleRepository->getAll();
@@ -214,12 +214,12 @@ class RuleController extends Controller
* @param RuleTestRequest $request
* @param Rule $rule
*
* @return JsonResponse
* @throws FireflyException
* @return JsonResponse
*/
public function testRule(RuleTestRequest $request, Rule $rule): JsonResponse
{
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$parameters = $request->getTestParameters();
/** @var Rule $rule */
Log::debug(sprintf('Now testing rule #%d, "%s"', $rule->id, $rule->title));

View File

@@ -106,7 +106,7 @@ class RuleGroupController extends Controller
{
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of rule groups. Count it and split it.
$collection = $this->ruleGroupRepository->get();
@@ -177,7 +177,7 @@ class RuleGroupController extends Controller
{
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of budgets. Count it and split it.
$collection = $this->ruleGroupRepository->getRules($group);
@@ -246,13 +246,13 @@ class RuleGroupController extends Controller
* @param RuleGroupTestRequest $request
* @param RuleGroup $group
*
* @return JsonResponse
* @throws FireflyException
*
* @return JsonResponse
*/
public function testGroup(RuleGroupTestRequest $request, RuleGroup $group): JsonResponse
{
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
Log::debug('Now in testGroup()');
/** @var Collection $rules */
$rules = $this->ruleGroupRepository->getActiveRules($group);
@@ -305,8 +305,8 @@ class RuleGroupController extends Controller
* @param RuleGroupTriggerRequest $request
* @param RuleGroup $group
*
* @return JsonResponse
* @throws Exception
* @return JsonResponse
*/
public function triggerGroup(RuleGroupTriggerRequest $request, RuleGroup $group): JsonResponse
{

View File

@@ -1,7 +1,8 @@
<?php
/**
* AccountController.php
* Copyright (c) 2019 james@firefly-iii.org
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@@ -19,8 +20,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Api\V1\Controllers\Search;
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Search;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Support\Http\Api\AccountFilter;
@@ -41,8 +43,7 @@ class AccountController extends Controller
{
use AccountFilter;
/** @var array */
private $validFields;
private array $validFields;
public function __construct()
{
@@ -97,5 +98,4 @@ class AccountController extends Controller
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
}
}

View File

@@ -1,7 +1,8 @@
<?php
/**
* TransactionController.php
* Copyright (c) 2019 james@firefly-iii.org
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@@ -19,51 +20,51 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Api\V1\Controllers\Search;
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Search;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Support\Search\SearchInterface;
use FireflyIII\Support\Search\TransactionSearch;
use FireflyIII\Transformers\TransactionGroupTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Resource\Collection;
/**
* Class TransactionController
*/
class TransactionController extends Controller
{
/** @var string */
const SEARCH_ALL = 'all';
/** @var string */
const SEARCH_DESCRIPTION = 'description';
/** @var string */
const SEARCH_NOTES = 'notes';
/** @var string */
const SEARCH_ACCOUNTS = 'accounts';
/** @var array */
private $validFields;
public function __construct()
{
parent::__construct();
$this->validFields = [
self::SEARCH_ALL,
self::SEARCH_DESCRIPTION,
self::SEARCH_NOTES,
self::SEARCH_ACCOUNTS,
];
}
/**
* @param Request $request
* @param Request $request
* @param SearchInterface $searcher
*
* @return JsonResponse|Response
* @return JsonResponse
*/
public function search(Request $request)
public function search(Request $request, SearchInterface $searcher): JsonResponse
{
die('the route is present but nobody\'s home.');
}
$manager = $this->getManager();
$fullQuery = (string) $request->get('query');
$page = 0 === (int) $request->get('page') ? 1 : (int) $request->get('page');
}
$searcher->parseQuery($fullQuery);
$searcher->setPage($page);
$searcher->setLimit((int) config('firefly.search_result_limit'));
$groups = $searcher->searchTransactions();
$parameters = ['search' => $fullQuery];
$url = route('api.v1.search.transactions') . '?' . http_build_query($parameters);
$groups->setPath($url);
$transactions = $groups->getCollection();
/** @var TransactionGroupTransformer $transformer */
$transformer = app(TransactionGroupTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Collection($transactions, $transformer, 'transactions');
$resource->setPaginator(new IlluminatePaginatorAdapter($groups));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
}

View File

@@ -1,116 +0,0 @@
<?php
/**
* TransferController.php
* Copyright (c) 2019 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Api\V1\Controllers\Search;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Search\TransferRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Support\Search\TransferSearch;
use FireflyIII\Transformers\TransactionGroupTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Resource\Collection as FractalCollection;
/**
* Class TransferController
*/
class TransferController extends Controller
{
/**
* @param Request $request
*
* @return JsonResponse|Response
* @throws FireflyException
*/
public function search(TransferRequest $request)
{
// configure transfer search to search for a > b
$search = app(TransferSearch::class);
$search->setSource($request->get('source'));
$search->setDestination($request->get('destination'));
$search->setAmount($request->get('amount'));
$search->setDescription($request->get('description'));
$search->setDate($request->get('date'));
$left = $search->search();
// configure transfer search to search for b > a
$search->setSource($request->get('destination'));
$search->setDestination($request->get('source'));
$search->setAmount($request->get('amount'));
$search->setDescription($request->get('description'));
$search->setDate($request->get('date'));
$right = $search->search();
// add parameters to URL:
$this->parameters->set('source', $request->get('source'));
$this->parameters->set('destination', $request->get('destination'));
$this->parameters->set('amount', $request->get('amount'));
$this->parameters->set('description', $request->get('description'));
$this->parameters->set('date', $request->get('date'));
// get all journal ID's.
$total = $left->merge($right)->unique('id')->pluck('id')->toArray();
if (0 === count($total)) {
// forces search to be empty.
$total = [-1];
}
// collector to return results.
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$manager = $this->getManager();
/** @var User $admin */
$admin = auth()->user();
// use new group collector:
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector
->setUser($admin)
// all info needed for the API:
->withAPIInformation()
// set page size:
->setLimit($pageSize)
// set page to retrieve
->setPage(1)
->setJournalIds($total);
$paginator = $collector->getPaginatedGroups();
$paginator->setPath(route('api.v1.search.transfers') . $this->buildParams());
$transactions = $paginator->getCollection();
/** @var TransactionGroupTransformer $transformer */
$transformer = app(TransactionGroupTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($transactions, $transformer, 'transactions');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
}

View File

@@ -24,7 +24,6 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers;
use Carbon\Carbon;
use Exception;
use FireflyIII\Api\V1\Requests\DateRequest;
@@ -42,7 +41,6 @@ use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Collection;
/**
* Class SummaryController
@@ -98,8 +96,8 @@ class SummaryController extends Controller
/**
* @param DateRequest $request
*
* @return JsonResponse
* @throws Exception
* @return JsonResponse
*/
public function basic(DateRequest $request): JsonResponse
{
@@ -125,7 +123,6 @@ class SummaryController extends Controller
}
return response()->json($return);
}
/**
@@ -152,25 +149,6 @@ class SummaryController extends Controller
return $result;
}
/**
* This method will scroll through the results of the spentInPeriodMc() array and return the correct info.
*
* @param array $spentInfo
* @param TransactionCurrency $currency
*
* @return string
*/
private function findInSpentArray(array $spentInfo, TransactionCurrency $currency): string
{
foreach ($spentInfo as $array) {
if ($array['currency_id'] === $currency->id) {
return (string)$array['amount'];
}
}
return '0'; // @codeCoverageIgnore
}
/**
* @param Carbon $start
* @param Carbon $end
@@ -198,8 +176,7 @@ class SummaryController extends Controller
$set = $collector->getExtractedJournals();
/** @var array $transactionJournal */
foreach ($set as $transactionJournal) {
$currencyId = (int)$transactionJournal['currency_id'];
$currencyId = (int) $transactionJournal['currency_id'];
$incomes[$currencyId] = $incomes[$currencyId] ?? '0';
$incomes[$currencyId] = bcadd($incomes[$currencyId], bcmul($transactionJournal['amount'], '-1'));
$sums[$currencyId] = $sums[$currencyId] ?? '0';
@@ -221,7 +198,7 @@ class SummaryController extends Controller
/** @var array $transactionJournal */
foreach ($set as $transactionJournal) {
$currencyId = (int)$transactionJournal['currency_id'];
$currencyId = (int) $transactionJournal['currency_id'];
$expenses[$currencyId] = $expenses[$currencyId] ?? '0';
$expenses[$currencyId] = bcadd($expenses[$currencyId], $transactionJournal['amount']);
$sums[$currencyId] = $sums[$currencyId] ?? '0';
@@ -295,7 +272,7 @@ class SummaryController extends Controller
$return = [];
foreach ($paidAmount as $currencyId => $amount) {
$amount = bcmul($amount, '-1');
$currency = $this->currencyRepos->findNull((int)$currencyId);
$currency = $this->currencyRepos->findNull((int) $currencyId);
if (null === $currency) {
continue;
}
@@ -315,7 +292,7 @@ class SummaryController extends Controller
foreach ($unpaidAmount as $currencyId => $amount) {
$amount = bcmul($amount, '-1');
$currency = $this->currencyRepos->findNull((int)$currencyId);
$currency = $this->currencyRepos->findNull((int) $currencyId);
if (null === $currency) {
continue;
}
@@ -340,8 +317,8 @@ class SummaryController extends Controller
* @param Carbon $start
* @param Carbon $end
*
* @return array
* @throws Exception
* @return array
*/
private function getLeftToSpendInfo(Carbon $start, Carbon $end): array
{
@@ -360,7 +337,7 @@ class SummaryController extends Controller
$days = $today->diffInDays($end) + 1;
$perDay = '0';
if (0 !== $days && bccomp($leftToSpend, '0') > -1) {
$perDay = bcdiv($leftToSpend, (string)$days);
$perDay = bcdiv($leftToSpend, (string) $days);
}
$return[] = [
@@ -373,14 +350,18 @@ class SummaryController extends Controller
'currency_decimal_places' => $row['currency_decimal_places'],
'value_parsed' => app('amount')->formatFlat($row['currency_symbol'], $row['currency_decimal_places'], $leftToSpend, false),
'local_icon' => 'money',
'sub_title' => (string)trans(
'firefly.box_spend_per_day', ['amount' => app('amount')->formatFlat(
$row['currency_symbol'], $row['currency_decimal_places'], $perDay, false
)]
'sub_title' => (string) trans(
'firefly.box_spend_per_day',
['amount' => app('amount')->formatFlat(
$row['currency_symbol'],
$row['currency_decimal_places'],
$perDay,
false
)]
),
];
}
return $return;
}
@@ -443,5 +424,4 @@ class SummaryController extends Controller
return $return;
}
}

View File

@@ -25,12 +25,13 @@ namespace FireflyIII\Api\V1\Controllers;
use Carbon\Carbon;
use FireflyIII\Api\V1\Requests\DateRequest;
use FireflyIII\Api\V1\Requests\TagUpdateRequest;
use FireflyIII\Api\V1\Requests\TagStoreRequest;
use FireflyIII\Api\V1\Requests\TagUpdateRequest;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\Tag;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use FireflyIII\Support\Http\Api\TransactionFilter;
use FireflyIII\Transformers\AttachmentTransformer;
use FireflyIII\Transformers\TagTransformer;
use FireflyIII\Transformers\TransactionGroupTransformer;
use FireflyIII\User;
@@ -117,7 +118,7 @@ class TagController extends Controller
{
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of budgets. Count it and split it.
$collection = $this->repository->get();
@@ -138,6 +139,36 @@ class TagController extends Controller
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* @param Tag $tag
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function attachments(Tag $tag): JsonResponse
{
$manager = $this->getManager();
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$collection = $this->repository->getAttachments($tag);
$count = $collection->count();
$attachments = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// make paginator:
$paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.tags.attachments', [$tag->id]) . $this->buildParams());
/** @var AttachmentTransformer $transformer */
$transformer = app(AttachmentTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($attachments, $transformer, 'attachments');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* List single resource.
*
@@ -190,7 +221,7 @@ class TagController extends Controller
*/
public function transactions(Request $request, Tag $tag): JsonResponse
{
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$type = $request->get('type') ?? 'default';
$this->parameters->set('type', $type);
@@ -236,7 +267,7 @@ class TagController extends Controller
* Update a rule.
*
* @param TagUpdateRequest $request
* @param Tag $tag
* @param Tag $tag
*
* @return JsonResponse
*/
@@ -288,8 +319,8 @@ class TagController extends Controller
];
/** @var Tag $tag */
foreach ($tags as $tag) {
$earned = (float)$this->repository->earnedInPeriod($tag, $start, $end);
$spent = (float)$this->repository->spentInPeriod($tag, $start, $end);
$earned = (float) $this->repository->earnedInPeriod($tag, $start, $end);
$spent = (float) $this->repository->spentInPeriod($tag, $start, $end);
$size = ($spent * -1) + $earned;
$min = $min ?? $size;
if ($size > 0) {

View File

@@ -110,7 +110,6 @@ class TransactionController extends Controller
$resource = new FractalCollection($attachments, $transformer, 'attachments');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
@@ -153,7 +152,7 @@ class TransactionController extends Controller
*/
public function index(Request $request): JsonResponse
{
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$type = $request->get('type') ?? 'default';
$this->parameters->set('type', $type);
@@ -215,7 +214,6 @@ class TransactionController extends Controller
$resource = new FractalCollection($events, $transformer, 'piggy_bank_events');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
@@ -271,6 +269,7 @@ class TransactionController extends Controller
*
* @param TransactionStoreRequest $request
*
* @throws FireflyException
* @return JsonResponse
*/
public function store(TransactionStoreRequest $request): JsonResponse
@@ -285,7 +284,7 @@ class TransactionController extends Controller
try {
$transactionGroup = $this->groupRepository->store($data);
} catch (DuplicateTransactionException $e) {
Log::warning('Caught a duplicate. Return error message.');
Log::warning('Caught a duplicate transaction. Return error message.');
// return bad validation message.
// TODO use Laravel's internal validation thing to do this.
$response = [
@@ -296,7 +295,7 @@ class TransactionController extends Controller
];
return response()->json($response, 422);
} catch(FireflyException $e) {
} catch (FireflyException $e) {
Log::warning('Caught an exception. Return error message.');
Log::error($e->getMessage());
// return bad validation message.
@@ -304,7 +303,7 @@ class TransactionController extends Controller
$response = [
'message' => 'The given data was invalid.',
'errors' => [
'transactions.0.description' => [sprintf('Internal exception: %s',$e->getMessage())],
'transactions.0.description' => [sprintf('Internal exception: %s', $e->getMessage())],
],
];
@@ -328,7 +327,7 @@ class TransactionController extends Controller
$selectedGroup = $collector->getGroups()->first();
if (null === $selectedGroup) {
throw new NotFoundHttpException(); // @codeCoverageIgnore
throw new FireflyException('Cannot find transaction. Possibly, a rule deleted this transaction after its creation.');
}
/** @var TransactionGroupTransformer $transformer */
$transformer = app(TransactionGroupTransformer::class);
@@ -379,6 +378,5 @@ class TransactionController extends Controller
$resource = new Item($selectedGroup, $transformer, 'transactions');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
}

View File

@@ -105,7 +105,7 @@ class TransactionLinkController extends Controller
$name = $request->get('name');
// types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$linkType = $this->repository->findByName($name);
// get list of transaction links. Count it and split it.
@@ -155,8 +155,8 @@ class TransactionLinkController extends Controller
*
* @param TransactionLinkRequest $request
*
* @return JsonResponse
* @throws FireflyException
* @return JsonResponse
*/
public function store(TransactionLinkRequest $request): JsonResponse
{
@@ -186,8 +186,8 @@ class TransactionLinkController extends Controller
* @param TransactionLinkRequest $request
* @param TransactionJournalLink $journalLink
*
* @return JsonResponse
* @throws FireflyException
* @return JsonResponse
*/
public function update(TransactionLinkRequest $request, TransactionJournalLink $journalLink): JsonResponse
{

View File

@@ -70,9 +70,9 @@ class UserController extends Controller
*
* @param User $user
*
* @return JsonResponse
* @throws FireflyException
* @codeCoverageIgnore
* @return JsonResponse
*/
public function delete(User $user): JsonResponse
{
@@ -95,7 +95,7 @@ class UserController extends Controller
public function index(): JsonResponse
{
// user preferences
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$manager = $this->getManager();
// build collection

View File

@@ -1,6 +1,6 @@
<?php
/**
* IsSandStormUser.php
* ApiDemoUser.php
* Copyright (c) 2019 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
@@ -20,38 +20,40 @@
*/
declare(strict_types=1);
namespace FireflyIII\Http\Middleware;
namespace FireflyIII\Api\V1\Middleware;
use Closure;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
/**
* Class IsSandStormUser.
* Class ApiDemoUser.
*/
class IsSandStormUser
class ApiDemoUser
{
/**
* Handle an incoming request. May not be a limited user (ie. Sandstorm env. or demo user).
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null $guard
* @param Request $request
* @param Closure $next
*
* @return mixed
*/
public function handle(Request $request, Closure $next, $guard = null)
public function handle(Request $request, Closure $next)
{
if (Auth::guard($guard)->guest()) {
// don't care when not logged in, usual stuff applies:
/** @var User $user */
$user = $request->user();
if (null === $user) {
return $next($request);
}
if (1 === (int)getenv('SANDSTORM')) {
app('session')->flash('warning', (string)trans('firefly.sandstorm_not_available'));
/** @var UserRepositoryInterface $repository */
$repository = app(UserRepositoryInterface::class);
return response()->redirectTo(route('index'));
if ($repository->hasRole($user, 'demo')) {
return response('', 403);
}
return $next($request);

View File

@@ -126,7 +126,7 @@ class AccountStoreRequest extends Request
'interest_period' => 'required_if:type,liability|in:daily,monthly,yearly',
'notes' => 'min:0|max:65536',
];
$rules = Location::requestRules($rules);
$rules = Location::requestRules($rules);
return $rules;
}

View File

@@ -105,7 +105,7 @@ class AccountUpdateRequest extends Request
$types = implode(',', array_keys(config('firefly.subTitlesByIdentifier')));
$ccPaymentTypes = implode(',', array_keys(config('firefly.ccTypes')));
$rules = [
$rules = [
'name' => sprintf('min:1|uniqueAccountForUser:%d', $account->id),
'type' => sprintf('in:%s', $types),
'iban' => 'iban|nullable',

View File

@@ -23,9 +23,6 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Models\Bill;
use FireflyIII\Models\ImportJob;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Rules\IsValidAttachmentModel;
/**
@@ -69,14 +66,14 @@ class AttachmentStoreRequest extends Request
*/
public function rules(): array
{
$models = implode(
',',
[
str_replace('FireflyIII\\Models\\', '', Bill::class),
str_replace('FireflyIII\\Models\\', '', ImportJob::class),
str_replace('FireflyIII\\Models\\', '', TransactionJournal::class),
]
$models = config('firefly.valid_attachment_models');
$models = array_map(
static function (string $className) {
return str_replace('FireflyIII\\Models\\', '', $className);
}, $models
);
$models = implode(',', $models);
$model = $this->string('attachable_type');
return [

View File

@@ -64,15 +64,13 @@ class AvailableBudgetRequest extends Request
*/
public function rules(): array
{
$rules = [
return [
'currency_id' => 'numeric|exists:transaction_currencies,id',
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
'amount' => 'required|numeric|more:0',
'amount' => 'required|numeric|gt:0',
'start' => 'required|date|before:end',
'end' => 'required|date|after:start',
];
return $rules;
}

View File

@@ -60,7 +60,7 @@ class BillRequest extends Request
$active = $this->boolean('active');
}
$data = [
return [
'name' => $this->string('name'),
'amount_min' => $this->string('amount_min'),
'amount_max' => $this->string('amount_max'),
@@ -70,10 +70,9 @@ class BillRequest extends Request
'repeat_freq' => $this->string('repeat_freq'),
'skip' => $this->integer('skip'),
'active' => $active,
'order' => $this->integer('order'),
'notes' => $this->nlString('notes'),
];
return $data;
}
/**
@@ -85,13 +84,13 @@ class BillRequest extends Request
public function rules(): array
{
$rules = [
'name' => 'required|between:1,255|uniqueObjectForUser:bills,name',
'amount_min' => 'required|numeric|more:0',
'amount_max' => 'required|numeric|more:0',
'name' => 'between:1,255|uniqueObjectForUser:bills,name',
'amount_min' => 'numeric|gt:0',
'amount_max' => 'numeric|gt:0',
'currency_id' => 'numeric|exists:transaction_currencies,id',
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
'date' => 'required|date',
'repeat_freq' => 'required|in:weekly,monthly,quarterly,half-year,yearly',
'date' => 'date',
'repeat_freq' => 'in:weekly,monthly,quarterly,half-year,yearly',
'skip' => 'between:0,31',
'active' => [new IsBoolean],
'notes' => 'between:1,65536',
@@ -121,10 +120,10 @@ class BillRequest extends Request
$validator->after(
static function (Validator $validator) {
$data = $validator->getData();
$min = (float)($data['amount_min'] ?? 0);
$max = (float)($data['amount_max'] ?? 0);
$min = (float) ($data['amount_min'] ?? 0);
$max = (float) ($data['amount_max'] ?? 0);
if ($min > $max) {
$validator->errors()->add('amount_min', (string)trans('validation.amount_min_over_max'));
$validator->errors()->add('amount_min', (string) trans('validation.amount_min_over_max'));
}
}
);

View File

@@ -70,7 +70,7 @@ class BudgetLimitRequest extends Request
'budget_id' => 'required|exists:budgets,id|belongsToUser:budgets,id',
'start' => 'required|before:end|date',
'end' => 'required|after:start|date',
'amount' => 'required|more:0',
'amount' => 'required|gt:0',
'currency_id' => 'numeric|exists:transaction_currencies,id',
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
];

View File

@@ -0,0 +1,106 @@
<?php
/**
* BudgetStoreRequest.php
* Copyright (c) 2019 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Rules\IsBoolean;
use Illuminate\Validation\Validator;
/**
* Class BudgetStoreRequest
*
* @codeCoverageIgnore
*/
class BudgetStoreRequest extends Request
{
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/**
* Get all data from the request.
*
* @return array
*/
public function getAll(): array
{
$active = true;
if (null !== $this->get('active')) {
$active = $this->boolean('active');
}
return [
'name' => $this->string('name'),
'active' => $active,
'order' => 0,
'auto_budget_type' => $this->string('auto_budget_type'),
'transaction_currency_id' => $this->integer('auto_budget_currency_id'),
'transaction_currency_code' => $this->string('auto_budget_currency_code'),
'auto_budget_amount' => $this->string('auto_budget_amount'),
'auto_budget_period' => $this->string('auto_budget_period'),
];
}
/**
* The rules that the incoming request must be matched against.
*
* @return array
*/
public function rules(): array
{
return [
'name' => 'required|between:1,100|uniqueObjectForUser:budgets,name',
'active' => [new IsBoolean],
'auto_budget_type' => 'in:reset,rollover,none',
'auto_budget_currency_id' => 'exists:transaction_currencies,id',
'auto_budget_currency_code' => 'exists:transaction_currencies,code',
'auto_budget_amount' => 'min:0|max:1000000000',
'auto_budget_period' => 'in:daily,weekly,monthly,quarterly,half_year,yearly',
];
}
/**
* Configure the validator instance with special rules for after the basic validation rules.
*
* @param Validator $validator
*
* @return void
*/
public function withValidator(Validator $validator): void
{
$validator->after(
function (Validator $validator) {
// validate all account info
$this->validateAutoBudgetAmount($validator);
}
);
}
}

View File

@@ -0,0 +1,107 @@
<?php
/**
* BudgetUpdateRequest.php
* Copyright (c) 2019 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Rules\IsBoolean;
use Illuminate\Validation\Validator;
/**
* Class BudgetUpdateRequest
*
* @codeCoverageIgnore
*/
class BudgetUpdateRequest extends Request
{
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/**
* Get all data from the request.
*
* @return array
*/
public function getAll(): array
{
$active = true;
if (null !== $this->get('active')) {
$active = $this->boolean('active');
}
return [
'name' => $this->string('name'),
'active' => $active,
'order' => 0,
'auto_budget_type' => $this->string('auto_budget_type'),
'transaction_currency_id' => $this->integer('auto_budget_currency_id'),
'transaction_currency_code' => $this->string('auto_budget_currency_code'),
'auto_budget_amount' => $this->string('auto_budget_amount'),
'auto_budget_period' => $this->string('auto_budget_period'),
];
}
/**
* The rules that the incoming request must be matched against.
*
* @return array
*/
public function rules(): array
{
$budget = $this->route()->parameter('budget');
return [
'name' => sprintf('required|between:1,100|uniqueObjectForUser:budgets,name,%d', $budget->id),
'active' => [new IsBoolean],
'auto_budget_type' => 'in:reset,rollover,none',
'auto_budget_currency_id' => 'exists:transaction_currencies,id',
'auto_budget_currency_code' => 'exists:transaction_currencies,code',
'auto_budget_amount' => 'min:0|max:1000000000',
'auto_budget_period' => 'in:daily,weekly,monthly,quarterly,half_year,yearly',
];
}
/**
* Configure the validator instance with special rules for after the basic validation rules.
*
* @param Validator $validator
*
* @return void
*/
public function withValidator(Validator $validator): void
{
$validator->after(
function (Validator $validator) {
// validate all account info
$this->validateAutoBudgetAmount($validator);
}
);
}
}

View File

@@ -1,7 +1,7 @@
<?php
/**
* RabobankDescription.php
* Copyright (c) 2019 james@firefly-iii.org
* DataDestroyRequest.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@@ -18,52 +18,49 @@
* 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\Import\Specifics;
namespace FireflyIII\Api\V1\Requests;
/**
* Class RabobankDescription.
*
* @codeCoverageIgnore
* @deprecated
* Class DataDestroyRequest
*/
class RabobankDescription implements SpecificInterface
class DataDestroyRequest extends Request
{
/**
* Description of this specific.
* Authorize logged in users.
*
* @return string
* @codeCoverageIgnore
* @return bool
*/
public static function getDescription(): string
public function authorize(): bool
{
return 'import.specific_rabo_descr';
// Only allow authenticated users
return auth()->check() && !auth()->user()->hasRole('demo');
}
/**
* Name of this specific.
* Get all data from the request.
*
* @return string
* @codeCoverageIgnore
*/
public static function getName(): string
public function getObjects(): string
{
return 'import.specific_rabo_name';
return $this->get('objects') ?? '';
}
/**
* Run the specific.
*
* @param array $row
* The rules that the incoming request must be matched against.
*
* @return array
*
*/
public function run(array $row): array
public function rules(): array
{
$row = array_values($row);
$valid = 'budgets,bills,piggy_banks,rules,recurring,categories,tags,object_groups' .
',accounts,asset_accounts,expense_accounts,revenue_accounts,liabilities,transactions,withdrawals,deposits,transfers';
return $row;
return [
'objects' => sprintf('min:1|string|in:%s', $valid),
];
}
}

View File

@@ -1,6 +1,7 @@
<?php
/**
* BudgetRequest.php
* ObjectGroupUpdateRequest.php
* Copyright (c) 2019 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
@@ -23,17 +24,14 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Models\Budget;
use FireflyIII\Rules\IsBoolean;
/**
* Class BudgetRequest
* Class AccountObjectGroupUpdateRequestUpdateRequest
*
* @codeCoverageIgnore
* TODO AFTER 4.8,0: split this into two request classes.
*/
class BudgetRequest extends Request
class ObjectGroupUpdateRequest extends Request
{
/**
* Authorize logged in users.
*
@@ -46,21 +44,13 @@ class BudgetRequest extends Request
}
/**
* Get all data from the request.
*
* @return array
*/
public function getAll(): array
public function getUpdateData(): array
{
$active = true;
if (null !== $this->get('active')) {
$active = $this->boolean('active');
}
return [
'name' => $this->string('name'),
'active' => $active,
'order' => 0,
'title' => $this->string('title'),
'order' => $this->integer('order'),
];
}
@@ -71,21 +61,11 @@ class BudgetRequest extends Request
*/
public function rules(): array
{
$rules = [
'name' => 'required|between:1,100|uniqueObjectForUser:budgets,name',
'active' => [new IsBoolean],
];
switch ($this->method()) {
default:
break;
case 'PUT':
case 'PATCH':
/** @var Budget $budget */
$budget = $this->route()->parameter('budget');
$rules['name'] = sprintf('required|between:1,100|uniqueObjectForUser:budgets,name,%d', $budget->id);
break;
}
$objectGroup = $this->route()->parameter('objectGroup');
return $rules;
return [
'title' => sprintf('min:1|uniqueObjectGroup:%d', $objectGroup->id),
'order' => 'numeric',
];
}
}

View File

@@ -63,6 +63,7 @@ class PiggyBankRequest extends Request
'startdate' => $this->date('start_date'),
'targetdate' => $this->date('target_date'),
'notes' => $this->nlString('notes'),
'order' => $this->integer('order'),
];
}
@@ -90,7 +91,7 @@ class PiggyBankRequest extends Request
$piggyBank = $this->route()->parameter('piggyBank');
$rules['name'] = 'between:1,255|uniquePiggyBankForUser:' . $piggyBank->id;
$rules['account_id'] = ['belongsToUser:accounts', new IsAssetAccountId];
$rules['target_amount'] = 'numeric|more:0';
$rules['target_amount'] = 'numeric|gt:0';
$rules['current_amount'] = ['numeric', new ZeroOrMore, new LessThanPiggyTarget];
break;
}

View File

@@ -0,0 +1,86 @@
<?php
/**
* PiggyBankStoreRequest.php
* Copyright (c) 2019 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Rules\ZeroOrMore;
/**
*
* Class PiggyBankStoreRequest
*
* @codeCoverageIgnore
*/
class PiggyBankStoreRequest extends Request
{
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/**
* Get all data from the request.
*
* @return array
*/
public function getAll(): array
{
return [
'name' => $this->string('name'),
'account_id' => $this->integer('account_id'),
'targetamount' => $this->string('target_amount'),
'current_amount' => $this->string('current_amount'),
'startdate' => $this->date('start_date'),
'targetdate' => $this->date('target_date'),
'notes' => $this->nlString('notes'),
'object_group_id' => $this->integer('object_group_id'),
'object_group' => $this->string('object_group_name'),
];
}
/**
* The rules that the incoming request must be matched against.
*
* @return array
*/
public function rules(): array
{
return [
'name' => 'required|between:1,255|uniquePiggyBankForUser',
'current_amount' => ['numeric', new ZeroOrMore, 'lte:target_amount'],
'account_id' => 'required|numeric|belongsToUser:accounts,id',
'object_group_id' => 'numeric|belongsToUser:object_groups,id',
'target_amount' => ['numeric', new ZeroOrMore, 'lte:target_amount', 'required'],
'start_date' => 'date|nullable',
'target_date' => 'date|nullable|after:start_date',
'notes' => 'max:65000',
];
}
}

View File

@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Requests;
use Carbon\Carbon;
use FireflyIII\Rules\BelongsUser;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Validation\CurrencyValidation;
use FireflyIII\Validation\RecurrenceValidation;
use FireflyIII\Validation\TransactionValidation;
use Illuminate\Validation\Validator;
@@ -35,7 +36,7 @@ use Illuminate\Validation\Validator;
*/
class RecurrenceStoreRequest extends Request
{
use RecurrenceValidation, TransactionValidation;
use RecurrenceValidation, TransactionValidation, CurrencyValidation;
/**
* Authorize logged in users.
@@ -63,7 +64,8 @@ class RecurrenceStoreRequest extends Request
if (null !== $this->get('apply_rules')) {
$applyRules = $this->boolean('apply_rules');
}
$return = [
return [
'recurrence' => [
'type' => $this->string('type'),
'title' => $this->string('title'),
@@ -77,8 +79,6 @@ class RecurrenceStoreRequest extends Request
'transactions' => $this->getTransactionData(),
'repetitions' => $this->getRepetitionData(),
];
return $return;
}
/**
@@ -104,8 +104,8 @@ class RecurrenceStoreRequest extends Request
'repetitions.*.skip' => 'required|numeric|between:0,31',
'repetitions.*.weekend' => 'required|numeric|min:1|max:4',
'transactions.*.description' => 'required|between:1,255',
'transactions.*.amount' => 'required|numeric|more:0',
'transactions.*.foreign_amount' => 'numeric|more:0',
'transactions.*.amount' => 'required|numeric|gt:0',
'transactions.*.foreign_amount' => 'numeric|gt:0',
'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id',
'transactions.*.currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
'transactions.*.foreign_currency_id' => 'numeric|exists:transaction_currencies,id',
@@ -168,8 +168,8 @@ class RecurrenceStoreRequest extends Request
$return[] = [
'type' => $repetition['type'],
'moment' => $repetition['moment'],
'skip' => (int)$repetition['skip'],
'weekend' => (int)$repetition['weekend'],
'skip' => (int) $repetition['skip'],
'weekend' => (int) $repetition['weekend'],
];
}
@@ -193,29 +193,7 @@ class RecurrenceStoreRequest extends Request
}
/** @var array $transaction */
foreach ($transactions as $transaction) {
$return[] = [
'amount' => $transaction['amount'],
'currency_id' => isset($transaction['currency_id']) ? (int)$transaction['currency_id'] : null,
'currency_code' => $transaction['currency_code'] ?? null,
'foreign_amount' => $transaction['foreign_amount'] ?? null,
'foreign_currency_id' => isset($transaction['foreign_currency_id']) ? (int)$transaction['foreign_currency_id'] : null,
'foreign_currency_code' => $transaction['foreign_currency_code'] ?? null,
'source_id' => isset($transaction['source_id']) ? (int)$transaction['source_id'] : null,
'source_name' => isset($transaction['source_name']) ? (string)$transaction['source_name'] : null,
'destination_id' => isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null,
'destination_name' => isset($transaction['destination_name']) ? (string)$transaction['destination_name'] : null,
'description' => $transaction['description'],
'type' => $this->string('type'),
// new and updated fields:
'piggy_bank_id' => isset($transaction['piggy_bank_id']) ? (int)$transaction['piggy_bank_id'] : null,
'piggy_bank_name' => $transaction['piggy_bank_name'] ?? null,
'tags' => $transaction['tags'] ?? [],
'budget_id' => isset($transaction['budget_id']) ? (int)$transaction['budget_id'] : null,
'budget_name' => $transaction['budget_name'] ?? null,
'category_id' => isset($transaction['category_id']) ? (int)$transaction['category_id'] : null,
'category_name' => $transaction['category_name'] ?? null,
];
$return[] = $this->getSingleRecurrenceData($transaction);
}
return $return;

View File

@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Models\Recurrence;
use FireflyIII\Rules\BelongsUser;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Validation\CurrencyValidation;
use FireflyIII\Validation\RecurrenceValidation;
use FireflyIII\Validation\TransactionValidation;
use Illuminate\Validation\Validator;
@@ -35,7 +36,7 @@ use Illuminate\Validation\Validator;
*/
class RecurrenceUpdateRequest extends Request
{
use RecurrenceValidation, TransactionValidation;
use RecurrenceValidation, TransactionValidation, CurrencyValidation;
/**
* Authorize logged in users.
@@ -63,7 +64,8 @@ class RecurrenceUpdateRequest extends Request
if (null !== $this->get('apply_rules')) {
$applyRules = $this->boolean('apply_rules');
}
$return = [
return [
'recurrence' => [
'type' => $this->nullableString('type'),
'title' => $this->nullableString('title'),
@@ -78,8 +80,6 @@ class RecurrenceUpdateRequest extends Request
'transactions' => $this->getTransactionData(),
'repetitions' => $this->getRepetitionData(),
];
return $return;
}
/**
@@ -107,8 +107,8 @@ class RecurrenceUpdateRequest extends Request
'repetitions.*.weekend' => 'required|numeric|min:1|max:4',
'transactions.*.description' => 'required|between:1,255',
'transactions.*.amount' => 'required|numeric|more:0',
'transactions.*.foreign_amount' => 'numeric|more:0',
'transactions.*.amount' => 'required|numeric|gt:0',
'transactions.*.foreign_amount' => 'numeric|gt:0',
'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id',
'transactions.*.currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
'transactions.*.foreign_currency_id' => 'numeric|exists:transaction_currencies,id',
@@ -141,7 +141,7 @@ class RecurrenceUpdateRequest extends Request
{
$validator->after(
function (Validator $validator) {
$this->validateOneRecurrenceTransactionUpdate($validator);
$this->validateOneRecurrenceTransaction($validator);
$this->validateOneRepetitionUpdate($validator);
$this->validateRecurrenceRepetition($validator);
$this->validateRepetitionMoment($validator);
@@ -170,8 +170,8 @@ class RecurrenceUpdateRequest extends Request
$return[] = [
'type' => $repetition['type'],
'moment' => $repetition['moment'],
'skip' => (int)$repetition['skip'],
'weekend' => (int)$repetition['weekend'],
'skip' => (int) $repetition['skip'],
'weekend' => (int) $repetition['weekend'],
];
}
@@ -195,29 +195,7 @@ class RecurrenceUpdateRequest extends Request
}
/** @var array $transaction */
foreach ($transactions as $transaction) {
$return[] = [
'amount' => $transaction['amount'],
'currency_id' => isset($transaction['currency_id']) ? (int)$transaction['currency_id'] : null,
'currency_code' => $transaction['currency_code'] ?? null,
'foreign_amount' => $transaction['foreign_amount'] ?? null,
'foreign_currency_id' => isset($transaction['foreign_currency_id']) ? (int)$transaction['foreign_currency_id'] : null,
'foreign_currency_code' => $transaction['foreign_currency_code'] ?? null,
'source_id' => isset($transaction['source_id']) ? (int)$transaction['source_id'] : null,
'source_name' => isset($transaction['source_name']) ? (string)$transaction['source_name'] : null,
'destination_id' => isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null,
'destination_name' => isset($transaction['destination_name']) ? (string)$transaction['destination_name'] : null,
'description' => $transaction['description'],
'type' => $this->string('type'),
// new and updated fields:
'piggy_bank_id' => isset($transaction['piggy_bank_id']) ? (int)$transaction['piggy_bank_id'] : null,
'piggy_bank_name' => $transaction['piggy_bank_name'] ?? null,
'tags' => $transaction['tags'] ?? [],
'budget_id' => isset($transaction['budget_id']) ? (int)$transaction['budget_id'] : null,
'budget_name' => $transaction['budget_name'] ?? null,
'category_id' => isset($transaction['category_id']) ? (int)$transaction['category_id'] : null,
'category_name' => $transaction['category_name'] ?? null,
];
$return[] = $this->getSingleRecurrenceData($transaction);
}
return $return;

View File

@@ -34,4 +34,36 @@ use FireflyIII\Http\Requests\Request as FireflyIIIRequest;
*/
class Request extends FireflyIIIRequest
{
/**
* @param array $transaction
*
* @return array
*/
protected function getSingleRecurrenceData(array $transaction): array
{
return [
'amount' => $transaction['amount'],
'currency_id' => isset($transaction['currency_id']) ? (int) $transaction['currency_id'] : null,
'currency_code' => $transaction['currency_code'] ?? null,
'foreign_amount' => $transaction['foreign_amount'] ?? null,
'foreign_currency_id' => isset($transaction['foreign_currency_id']) ? (int) $transaction['foreign_currency_id'] : null,
'foreign_currency_code' => $transaction['foreign_currency_code'] ?? null,
'source_id' => isset($transaction['source_id']) ? (int) $transaction['source_id'] : null,
'source_name' => isset($transaction['source_name']) ? (string) $transaction['source_name'] : null,
'destination_id' => isset($transaction['destination_id']) ? (int) $transaction['destination_id'] : null,
'destination_name' => isset($transaction['destination_name']) ? (string) $transaction['destination_name'] : null,
'description' => $transaction['description'],
'type' => $this->string('type'),
// new and updated fields:
'piggy_bank_id' => isset($transaction['piggy_bank_id']) ? (int) $transaction['piggy_bank_id'] : null,
'piggy_bank_name' => $transaction['piggy_bank_name'] ?? null,
'tags' => $transaction['tags'] ?? [],
'budget_id' => isset($transaction['budget_id']) ? (int) $transaction['budget_id'] : null,
'budget_name' => $transaction['budget_name'] ?? null,
'category_id' => isset($transaction['category_id']) ? (int) $transaction['category_id'] : null,
'category_name' => $transaction['category_name'] ?? null,
];
}
}

View File

@@ -54,7 +54,7 @@ class RuleGroupTestRequest extends Request
*/
public function getTestParameters(): array
{
$return = [
return [
'page' => $this->getPage(),
'start_date' => $this->getDate('start_date'),
'end_date' => $this->getDate('end_date'),
@@ -62,9 +62,6 @@ class RuleGroupTestRequest extends Request
'trigger_limit' => $this->getTriggerLimit(),
'accounts' => $this->getAccounts(),
];
return $return;
}
/**
@@ -80,7 +77,7 @@ class RuleGroupTestRequest extends Request
*/
private function getAccounts(): Collection
{
$accountList = '' === (string)$this->query('accounts') ? [] : explode(',', $this->query('accounts'));
$accountList = '' === (string) $this->query('accounts') ? [] : explode(',', $this->query('accounts'));
$accounts = new Collection;
/** @var AccountRepositoryInterface $accountRepository */
@@ -88,7 +85,7 @@ class RuleGroupTestRequest extends Request
foreach ($accountList as $accountId) {
Log::debug(sprintf('Searching for asset account with id "%s"', $accountId));
$account = $accountRepository->findNull((int)$accountId);
$account = $accountRepository->findNull((int) $accountId);
if ($this->validAccount($account)) {
/** @noinspection NullPointerExceptionInspection */
Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name));
@@ -117,7 +114,7 @@ class RuleGroupTestRequest extends Request
*/
private function getPage(): int
{
return 0 === (int)$this->query('page') ? 1 : (int)$this->query('page');
return 0 === (int) $this->query('page') ? 1 : (int) $this->query('page');
}
@@ -126,7 +123,7 @@ class RuleGroupTestRequest extends Request
*/
private function getSearchLimit(): int
{
return 0 === (int)$this->query('search_limit') ? (int)config('firefly.test-triggers.limit') : (int)$this->query('search_limit');
return 0 === (int) $this->query('search_limit') ? (int) config('firefly.test-triggers.limit') : (int) $this->query('search_limit');
}
/**
@@ -134,7 +131,7 @@ class RuleGroupTestRequest extends Request
*/
private function getTriggerLimit(): int
{
return 0 === (int)$this->query('triggered_limit') ? (int)config('firefly.test-triggers.range') : (int)$this->query('triggered_limit');
return 0 === (int) $this->query('triggered_limit') ? (int) config('firefly.test-triggers.range') : (int) $this->query('triggered_limit');
}
/**

View File

@@ -54,14 +54,11 @@ class RuleGroupTriggerRequest extends Request
*/
public function getTriggerParameters(): array
{
$return = [
return [
'start_date' => $this->getDate('start_date'),
'end_date' => $this->getDate('end_date'),
'accounts' => $this->getAccounts(),
];
return $return;
}
/**
@@ -80,7 +77,7 @@ class RuleGroupTriggerRequest extends Request
*/
private function getAccounts(): Collection
{
$accountList = '' === (string)$this->query('accounts') ? [] : explode(',', $this->query('accounts'));
$accountList = '' === (string) $this->query('accounts') ? [] : explode(',', $this->query('accounts'));
$accounts = new Collection;
/** @var AccountRepositoryInterface $accountRepository */
@@ -88,7 +85,7 @@ class RuleGroupTriggerRequest extends Request
foreach ($accountList as $accountId) {
Log::debug(sprintf('Searching for asset account with id "%s"', $accountId));
$account = $accountRepository->findNull((int)$accountId);
$account = $accountRepository->findNull((int) $accountId);
if ($this->validAccount($account)) {
/** @noinspection NullPointerExceptionInspection */
Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name));

View File

@@ -65,7 +65,7 @@ class RuleStoreRequest extends Request
$stopProcessing = $this->boolean('stop_processing');
}
$data = [
return [
'title' => $this->string('title'),
'description' => $this->string('description'),
'rule_group_id' => $this->integer('rule_group_id'),
@@ -77,8 +77,6 @@ class RuleStoreRequest extends Request
'triggers' => $this->getRuleTriggers(),
'actions' => $this->getRuleActions(),
];
return $data;
}
/**
@@ -94,7 +92,8 @@ class RuleStoreRequest extends Request
// some triggers and actions require text:
$contextTriggers = implode(',', config('firefly.context-rule-triggers'));
$contextActions = implode(',', config('firefly.context-rule-actions'));
$rules = [
return [
'title' => 'required|between:1,100|uniqueObjectForUser:rules,title',
'description' => 'between:1,5000|nullable',
'rule_group_id' => 'required|belongsToUser:rule_groups|required_without:rule_group_title',
@@ -112,8 +111,6 @@ class RuleStoreRequest extends Request
'stop_processing' => [new IsBoolean],
'active' => [new IsBoolean],
];
return $rules;
}
/**
@@ -144,7 +141,7 @@ class RuleStoreRequest extends Request
$actions = $data['actions'] ?? [];
// need at least one trigger
if (0 === count($actions)) {
$validator->errors()->add('title', (string)trans('validation.at_least_one_action'));
$validator->errors()->add('title', (string) trans('validation.at_least_one_action'));
}
}
@@ -159,7 +156,7 @@ class RuleStoreRequest extends Request
$triggers = $data['triggers'] ?? [];
// need at least one trigger
if (0 === count($triggers)) {
$validator->errors()->add('title', (string)trans('validation.at_least_one_trigger'));
$validator->errors()->add('title', (string) trans('validation.at_least_one_trigger'));
}
}
@@ -175,8 +172,8 @@ class RuleStoreRequest extends Request
$return[] = [
'type' => $action['type'],
'value' => $action['value'],
'active' => $this->convertBoolean((string)($action['active'] ?? 'false')),
'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')),
'active' => $this->convertBoolean((string) ($action['active'] ?? 'false')),
'stop_processing' => $this->convertBoolean((string) ($action['stop_processing'] ?? 'false')),
];
}
}
@@ -196,8 +193,8 @@ class RuleStoreRequest extends Request
$return[] = [
'type' => $trigger['type'],
'value' => $trigger['value'],
'active' => $this->convertBoolean((string)($trigger['active'] ?? 'false')),
'stop_processing' => $this->convertBoolean((string)($trigger['stop_processing'] ?? 'false')),
'active' => $this->convertBoolean((string) ($trigger['active'] ?? 'false')),
'stop_processing' => $this->convertBoolean((string) ($trigger['stop_processing'] ?? 'false')),
];
}
}

View File

@@ -54,7 +54,7 @@ class RuleTestRequest extends Request
*/
public function getTestParameters(): array
{
$return = [
return [
'page' => $this->getPage(),
'start_date' => $this->getDate('start_date'),
'end_date' => $this->getDate('end_date'),
@@ -62,9 +62,6 @@ class RuleTestRequest extends Request
'trigger_limit' => $this->getTriggerLimit(),
'accounts' => $this->getAccounts(),
];
return $return;
}
/**
@@ -80,7 +77,7 @@ class RuleTestRequest extends Request
*/
private function getAccounts(): Collection
{
$accountList = '' === (string)$this->query('accounts') ? [] : explode(',', $this->query('accounts'));
$accountList = '' === (string) $this->query('accounts') ? [] : explode(',', $this->query('accounts'));
$accounts = new Collection;
/** @var AccountRepositoryInterface $accountRepository */
@@ -88,7 +85,7 @@ class RuleTestRequest extends Request
foreach ($accountList as $accountId) {
Log::debug(sprintf('Searching for asset account with id "%s"', $accountId));
$account = $accountRepository->findNull((int)$accountId);
$account = $accountRepository->findNull((int) $accountId);
if ($this->validAccount($account)) {
/** @noinspection NullPointerExceptionInspection */
Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name));
@@ -117,7 +114,7 @@ class RuleTestRequest extends Request
*/
private function getPage(): int
{
return 0 === (int)$this->query('page') ? 1 : (int)$this->query('page');
return 0 === (int) $this->query('page') ? 1 : (int) $this->query('page');
}
@@ -126,7 +123,7 @@ class RuleTestRequest extends Request
*/
private function getSearchLimit(): int
{
return 0 === (int)$this->query('search_limit') ? (int)config('firefly.test-triggers.limit') : (int)$this->query('search_limit');
return 0 === (int) $this->query('search_limit') ? (int) config('firefly.test-triggers.limit') : (int) $this->query('search_limit');
}
/**
@@ -134,7 +131,7 @@ class RuleTestRequest extends Request
*/
private function getTriggerLimit(): int
{
return 0 === (int)$this->query('triggered_limit') ? (int)config('firefly.test-triggers.range') : (int)$this->query('triggered_limit');
return 0 === (int) $this->query('triggered_limit') ? (int) config('firefly.test-triggers.range') : (int) $this->query('triggered_limit');
}
/**

View File

@@ -53,14 +53,11 @@ class RuleTriggerRequest extends Request
*/
public function getTriggerParameters(): array
{
$return = [
return [
'start_date' => $this->getDate('start_date'),
'end_date' => $this->getDate('end_date'),
'accounts' => $this->getAccounts(),
];
return $return;
}
/**
@@ -79,7 +76,7 @@ class RuleTriggerRequest extends Request
*/
private function getAccounts(): Collection
{
$accountList = '' === (string)$this->query('accounts') ? [] : explode(',', $this->query('accounts'));
$accountList = '' === (string) $this->query('accounts') ? [] : explode(',', $this->query('accounts'));
$accounts = new Collection;
/** @var AccountRepositoryInterface $accountRepository */
@@ -87,7 +84,7 @@ class RuleTriggerRequest extends Request
foreach ($accountList as $accountId) {
Log::debug(sprintf('Searching for asset account with id "%s"', $accountId));
$account = $accountRepository->findNull((int)$accountId);
$account = $accountRepository->findNull((int) $accountId);
if ($this->validAccount($account)) {
/** @noinspection NullPointerExceptionInspection */
Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name));

View File

@@ -65,7 +65,7 @@ class RuleUpdateRequest extends Request
$stopProcessing = $this->boolean('stop_processing');
}
$data = [
return [
'title' => $this->nullableString('title'),
'description' => $this->nullableString('description'),
'rule_group_id' => $this->nullableInteger('rule_group_id'),
@@ -77,8 +77,6 @@ class RuleUpdateRequest extends Request
'triggers' => $this->getRuleTriggers(),
'actions' => $this->getRuleActions(),
];
return $data;
}
/**
@@ -95,7 +93,8 @@ class RuleUpdateRequest extends Request
// some triggers and actions require text:
$contextTriggers = implode(',', config('firefly.context-rule-triggers'));
$contextActions = implode(',', config('firefly.context-rule-actions'));
$rules = [
return [
'title' => sprintf('between:1,100|uniqueObjectForUser:rules,title,%d', $rule->id),
'description' => 'between:1,5000|nullable',
'rule_group_id' => 'belongsToUser:rule_groups',
@@ -113,8 +112,6 @@ class RuleUpdateRequest extends Request
'stop_processing' => [new IsBoolean],
'active' => [new IsBoolean],
];
return $rules;
}
/**
@@ -145,7 +142,7 @@ class RuleUpdateRequest extends Request
$actions = $data['actions'] ?? null;
// need at least one action
if (is_array($actions) && 0 === count($actions)) {
$validator->errors()->add('title', (string)trans('validation.at_least_one_action'));
$validator->errors()->add('title', (string) trans('validation.at_least_one_action'));
}
}
@@ -160,7 +157,7 @@ class RuleUpdateRequest extends Request
$triggers = $data['triggers'] ?? null;
// need at least one trigger
if (is_array($triggers) && 0 === count($triggers)) {
$validator->errors()->add('title', (string)trans('validation.at_least_one_trigger'));
$validator->errors()->add('title', (string) trans('validation.at_least_one_trigger'));
}
}
@@ -179,8 +176,8 @@ class RuleUpdateRequest extends Request
$return[] = [
'type' => $action['type'],
'value' => $action['value'],
'active' => $this->convertBoolean((string)($action['active'] ?? 'false')),
'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')),
'active' => $this->convertBoolean((string) ($action['active'] ?? 'false')),
'stop_processing' => $this->convertBoolean((string) ($action['stop_processing'] ?? 'false')),
];
}
}
@@ -203,8 +200,8 @@ class RuleUpdateRequest extends Request
$return[] = [
'type' => $trigger['type'],
'value' => $trigger['value'],
'active' => $this->convertBoolean((string)($trigger['active'] ?? 'false')),
'stop_processing' => $this->convertBoolean((string)($trigger['stop_processing'] ?? 'false')),
'active' => $this->convertBoolean((string) ($trigger['active'] ?? 'false')),
'stop_processing' => $this->convertBoolean((string) ($trigger['stop_processing'] ?? 'false')),
];
}
}

View File

@@ -1,7 +1,8 @@
<?php
/**
* TransferRequest.php
* Copyright (c) 2019 james@firefly-iii.org
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@@ -19,8 +20,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Api\V1\Requests\Search;
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Search;
use FireflyIII\Api\V1\Requests\Request;
use FireflyIII\Rules\IsTransferAccount;
@@ -49,10 +51,9 @@ class TransferRequest extends Request
return [
'source' => ['required', new IsTransferAccount],
'destination' => ['required', new IsTransferAccount],
'amount' => 'required|numeric|more:0',
'amount' => 'required|numeric|gt:0',
'description' => 'required|min:1',
'date' => 'required|date',
];
}
}
}

View File

@@ -110,8 +110,8 @@ class TransactionLinkRequest extends Request
$journalRepos->setUser($user);
$data = $validator->getData();
$inwardId = (int)($data['inward_id'] ?? 0);
$outwardId = (int)($data['outward_id'] ?? 0);
$inwardId = (int) ($data['inward_id'] ?? 0);
$outwardId = (int) ($data['outward_id'] ?? 0);
$inward = $journalRepos->findNull($inwardId);
$outward = $journalRepos->findNull($outwardId);

View File

@@ -28,6 +28,8 @@ use FireflyIII\Rules\BelongsUser;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Rules\IsDateOrTime;
use FireflyIII\Support\NullArrayObject;
use FireflyIII\Validation\CurrencyValidation;
use FireflyIII\Validation\GroupValidation;
use FireflyIII\Validation\TransactionValidation;
use Illuminate\Validation\Validator;
use Log;
@@ -37,7 +39,7 @@ use Log;
*/
class TransactionStoreRequest extends Request
{
use TransactionValidation;
use TransactionValidation, GroupValidation, CurrencyValidation;
/**
* Authorize logged in users.
@@ -60,14 +62,13 @@ class TransactionStoreRequest extends Request
public function getAll(): array
{
Log::debug('get all data in TransactionStoreRequest');
$data = [
return [
'group_title' => $this->string('group_title'),
'error_if_duplicate_hash' => $this->boolean('error_if_duplicate_hash'),
'apply_rules' => $this->boolean('apply_rules', true),
'transactions' => $this->getTransactionData(),
];
return $data;
}
/**
@@ -78,7 +79,8 @@ class TransactionStoreRequest extends Request
public function rules(): array
{
Log::debug('Collect rules of TransactionStoreRequest');
$rules = [
return [
// basic fields for group:
'group_title' => 'between:1,1000|nullable',
'error_if_duplicate_hash' => [new IsBoolean],
@@ -96,7 +98,7 @@ class TransactionStoreRequest extends Request
'transactions.*.foreign_currency_code' => 'min:3|max:3|exists:transaction_currencies,code|nullable',
// amount
'transactions.*.amount' => 'required|numeric|more:0',
'transactions.*.amount' => 'required|numeric|gt:0',
'transactions.*.foreign_amount' => 'numeric',
// description
@@ -156,8 +158,6 @@ class TransactionStoreRequest extends Request
'transactions.*.invoice_date' => 'date|nullable',
];
return $rules;
}
@@ -214,63 +214,63 @@ class TransactionStoreRequest extends Request
$return[] = [
'type' => $this->stringFromValue($object['type']),
'date' => $this->dateFromValue($object['date']),
'order' => $this->integerFromValue((string)$object['order']),
'order' => $this->integerFromValue((string) $object['order']),
'currency_id' => $this->integerFromValue((string)$object['currency_id']),
'currency_id' => $this->integerFromValue((string) $object['currency_id']),
'currency_code' => $this->stringFromValue($object['currency_code']),
// foreign currency info:
'foreign_currency_id' => $this->integerFromValue((string)$object['foreign_currency_id']),
'foreign_currency_code' => $this->stringFromValue($object['foreign_currency_code']),
'foreign_currency_id' => $this->integerFromValue((string) $object['foreign_currency_id']),
'foreign_currency_code' => $this->stringFromValue((string) $object['foreign_currency_code']),
// amount and foreign amount. Cannot be 0.
'amount' => $this->stringFromValue((string)$object['amount']),
'foreign_amount' => $this->stringFromValue((string)$object['foreign_amount']),
'amount' => $this->stringFromValue((string) $object['amount']),
'foreign_amount' => $this->stringFromValue((string) $object['foreign_amount']),
// description.
'description' => $this->stringFromValue($object['description']),
// source of transaction. If everything is null, assume cash account.
'source_id' => $this->integerFromValue((string)$object['source_id']),
'source_name' => $this->stringFromValue($object['source_name']),
'source_iban' => $this->stringFromValue($object['source_iban']),
'source_number' => $this->stringFromValue($object['source_number']),
'source_bic' => $this->stringFromValue($object['source_bic']),
'source_id' => $this->integerFromValue((string) $object['source_id']),
'source_name' => $this->stringFromValue((string) $object['source_name']),
'source_iban' => $this->stringFromValue((string) $object['source_iban']),
'source_number' => $this->stringFromValue((string) $object['source_number']),
'source_bic' => $this->stringFromValue((string) $object['source_bic']),
// destination of transaction. If everything is null, assume cash account.
'destination_id' => $this->integerFromValue((string)$object['destination_id']),
'destination_name' => $this->stringFromValue($object['destination_name']),
'destination_iban' => $this->stringFromValue($object['destination_iban']),
'destination_number' => $this->stringFromValue($object['destination_number']),
'destination_bic' => $this->stringFromValue($object['destination_bic']),
'destination_id' => $this->integerFromValue((string) $object['destination_id']),
'destination_name' => $this->stringFromValue((string) $object['destination_name']),
'destination_iban' => $this->stringFromValue((string) $object['destination_iban']),
'destination_number' => $this->stringFromValue((string) $object['destination_number']),
'destination_bic' => $this->stringFromValue((string) $object['destination_bic']),
// budget info
'budget_id' => $this->integerFromValue((string)$object['budget_id']),
'budget_name' => $this->stringFromValue($object['budget_name']),
'budget_id' => $this->integerFromValue((string) $object['budget_id']),
'budget_name' => $this->stringFromValue((string) $object['budget_name']),
// category info
'category_id' => $this->integerFromValue((string)$object['category_id']),
'category_name' => $this->stringFromValue($object['category_name']),
'category_id' => $this->integerFromValue((string) $object['category_id']),
'category_name' => $this->stringFromValue((string) $object['category_name']),
// journal bill reference. Optional. Will only work for withdrawals
'bill_id' => $this->integerFromValue((string)$object['bill_id']),
'bill_name' => $this->stringFromValue($object['bill_name']),
'bill_id' => $this->integerFromValue((string) $object['bill_id']),
'bill_name' => $this->stringFromValue((string) $object['bill_name']),
// piggy bank reference. Optional. Will only work for transfers
'piggy_bank_id' => $this->integerFromValue((string)$object['piggy_bank_id']),
'piggy_bank_name' => $this->stringFromValue($object['piggy_bank_name']),
'piggy_bank_id' => $this->integerFromValue((string) $object['piggy_bank_id']),
'piggy_bank_name' => $this->stringFromValue((string) $object['piggy_bank_name']),
// some other interesting properties
'reconciled' => $this->convertBoolean((string)$object['reconciled']),
'notes' => $this->nlStringFromValue($object['notes']),
'reconciled' => $this->convertBoolean((string) $object['reconciled']),
'notes' => $this->nlStringFromValue((string) $object['notes']),
'tags' => $this->arrayFromValue($object['tags']),
// all custom fields:
'internal_reference' => $this->stringFromValue((string)$object['internal_reference']),
'external_id' => $this->stringFromValue((string)$object['external_id']),
'internal_reference' => $this->stringFromValue((string) $object['internal_reference']),
'external_id' => $this->stringFromValue((string) $object['external_id']),
'original_source' => sprintf('ff3-v%s|api-v%s', config('firefly.version'), config('firefly.api_version')),
'recurrence_id' => $this->integerFromValue($object['recurrence_id']),
'bunq_payment_id' => $this->stringFromValue((string)$object['bunq_payment_id']),
'bunq_payment_id' => $this->stringFromValue((string) $object['bunq_payment_id']),
'sepa_cc' => $this->stringFromValue($object['sepa_cc']),
'sepa_ct_op' => $this->stringFromValue($object['sepa_ct_op']),

View File

@@ -28,6 +28,7 @@ use FireflyIII\Models\TransactionGroup;
use FireflyIII\Rules\BelongsUser;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Rules\IsDateOrTime;
use FireflyIII\Validation\GroupValidation;
use FireflyIII\Validation\TransactionValidation;
use Illuminate\Validation\Validator;
use Log;
@@ -37,7 +38,7 @@ use Log;
*/
class TransactionUpdateRequest extends Request
{
use TransactionValidation;
use TransactionValidation, GroupValidation;
/** @var array Array values. */
private $arrayFields;
@@ -154,7 +155,7 @@ class TransactionUpdateRequest extends Request
*/
public function rules(): array
{
$rules = [
return [
// basic fields for group:
'group_title' => 'between:1,1000',
'apply_rules' => [new IsBoolean],
@@ -171,7 +172,7 @@ class TransactionUpdateRequest extends Request
'transactions.*.foreign_currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
// amount
'transactions.*.amount' => 'numeric|more:0|max:100000000000',
'transactions.*.amount' => 'numeric|gt:0|max:100000000000',
'transactions.*.foreign_amount' => 'numeric|gte:0',
// description
@@ -222,8 +223,6 @@ class TransactionUpdateRequest extends Request
'transactions.*.payment_date' => 'date|nullable',
'transactions.*.invoice_date' => 'date|nullable',
];
return $rules;
}
/**
@@ -264,21 +263,122 @@ class TransactionUpdateRequest extends Request
// TODO if the transaction_journal_id is empty, some fields are mandatory, like the amount!
// all journals must have a description
//$this->validateDescriptions($validator);
// // validate foreign currency info
// $this->validateForeignCurrencyInformation($validator);
//
//
// // make sure all splits have valid source + dest info
// $this->validateSplitAccounts($validator);
// the group must have a description if > 1 journal.
// $this->validateGroupDescription($validator);
}
);
}
/**
* @param array $current
* @param array $transaction
*
* @return array
*/
private function getArrayData(array $current, array $transaction): array
{
foreach ($this->arrayFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->arrayFromValue($transaction[$fieldName]);
}
}
return $current;
}
/**
* @param array $current
* @param array $transaction
*
* @return array
*/
private function getBooleanData(array $current, array $transaction): array
{
foreach ($this->booleanFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->convertBoolean((string) $transaction[$fieldName]);
}
}
return $current;
}
/**
* @param array $current
* @param array $transaction
*
* @return array
*/
private function getDateData(array $current, array $transaction): array
{
foreach ($this->dateFields as $fieldName) {
Log::debug(sprintf('Now at date field %s', $fieldName));
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->dateFromValue((string) $transaction[$fieldName]);
Log::debug(sprintf('New value: "%s"', (string) $transaction[$fieldName]));
}
}
return $current;
}
/**
* For each field, add it to the array if a reference is present in the request:
*
* @param array $current
*
* @return array
*/
private function getIntegerData(array $current, array $transaction): array
{
foreach ($this->integerFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->integerFromValue((string) $transaction[$fieldName]);
}
}
return $current;
}
/**
* @param array $current
* @param array $transaction
*
* @return array
*/
private function getNlStringData(array $current, array $transaction): array
{
foreach ($this->textareaFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->nlStringFromValue((string) $transaction[$fieldName]);
}
}
return $current;
}
/**
* @param array $current
* @param array $transaction
*
* @return array
*/
private function getStringData(array $current, array $transaction): array
{
foreach ($this->stringFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->stringFromValue((string) $transaction[$fieldName]);
}
}
return $current;
}
/**
* Get transaction data.
*
@@ -292,48 +392,15 @@ class TransactionUpdateRequest extends Request
* @var int $index
* @var array $transaction
*/
foreach ($this->get('transactions') as $index => $transaction) {
foreach ($this->get('transactions') as $transaction) {
// default response is to update nothing in the transaction:
$current = [];
// for each field, add it to the array if a reference is present in the request:
foreach ($this->integerFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->integerFromValue((string)$transaction[$fieldName]);
}
}
foreach ($this->stringFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->stringFromValue((string)$transaction[$fieldName]);
}
}
foreach ($this->textareaFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->nlStringFromValue((string)$transaction[$fieldName]);
}
}
foreach ($this->dateFields as $fieldName) {
Log::debug(sprintf('Now at date field %s', $fieldName));
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->dateFromValue((string)$transaction[$fieldName]);
Log::debug(sprintf('New value: "%s"', (string)$transaction[$fieldName]));
}
}
foreach ($this->booleanFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->convertBoolean((string)$transaction[$fieldName]);
}
}
foreach ($this->arrayFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->arrayFromValue($transaction[$fieldName]);
}
}
$current = [];
$current = $this->getIntegerData($current, $transaction);
$current = $this->getStringData($current, $transaction);
$current = $this->getNlStringData($current, $transaction);
$current = $this->getDateData($current, $transaction);
$current = $this->getBooleanData($current, $transaction);
$current = $this->getArrayData($current, $transaction);
$return[] = $current;
}

View File

@@ -69,14 +69,13 @@ class UserStoreRequest extends Request
if (null !== $this->get('blocked')) {
$blocked = $this->boolean('blocked');
}
$data = [
return [
'email' => $this->string('email'),
'blocked' => $blocked,
'blocked_code' => $this->string('blocked_code'),
'role' => $this->string('role'),
];
return $data;
}
/**

View File

@@ -69,14 +69,13 @@ class UserUpdateRequest extends Request
if (null !== $this->get('blocked')) {
$blocked = $this->boolean('blocked');
}
$data = [
return [
'email' => $this->string('email'),
'blocked' => $blocked,
'blocked_code' => $this->string('blocked_code'),
'role' => $this->string('role'),
];
return $data;
}
/**
@@ -86,15 +85,14 @@ class UserUpdateRequest extends Request
*/
public function rules(): array
{
$user = $this->route()->parameter('user');
$rules = [
$user = $this->route()->parameter('user');
return [
'email' => sprintf('email|unique:users,email,%d', $user->id),
'blocked' => [new IsBoolean],
'blocked_code' => 'in:email_changed',
'role' => 'in:owner,demo,',
];
return $rules;
}
}

View File

@@ -30,6 +30,7 @@ use Schema;
/**
* Class CorrectDatabase
*
* @codeCoverageIgnore
*/
class CorrectDatabase extends Command
@@ -73,7 +74,7 @@ class CorrectDatabase extends Command
'firefly-iii:fix-ob-currencies',
'firefly-iii:fix-long-descriptions',
'firefly-iii:fix-recurring-transactions',
'firefly-iii:restore-oauth-keys'
'firefly-iii:restore-oauth-keys',
];
foreach ($commands as $command) {
$this->line(sprintf('Now executing %s', $command));

View File

@@ -1,4 +1,5 @@
<?php
/**
* CorrectOpeningBalanceCurrencies.php
* Copyright (c) 2020 james@firefly-iii.org
@@ -19,6 +20,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Models\Account;
@@ -111,15 +114,12 @@ class CorrectOpeningBalanceCurrencies extends Command
*/
private function getAccount(TransactionJournal $journal): ?Account
{
$excluded = [];
$transactions = $journal->transactions()->with(['account', 'account.accountType'])->get();
/** @var Transaction $transaction */
foreach ($transactions as $transaction) {
$account = $transaction->account;
if (null !== $account) {
if (AccountType::INITIAL_BALANCE !== $account->accountType->type) {
return $account;
}
if ((null !== $account) && AccountType::INITIAL_BALANCE !== $account->accountType->type) {
return $account;
}
}

View File

@@ -50,8 +50,8 @@ class CreateAccessTokens extends Command
/**
* Execute the console command.
*
* @return int
* @throws Exception
* @return int
*/
public function handle(): int
{

View File

@@ -47,7 +47,7 @@ class CreateLinkTypes extends Command
/**
* Execute the console command.
*
* @return mixed
* @return int
*/
public function handle(): int
{

View File

@@ -25,7 +25,6 @@ namespace FireflyIII\Console\Commands\Correction;
use Exception;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Console\Command;
use Log;
@@ -50,16 +49,17 @@ class DeleteEmptyGroups extends Command
/**
* Execute the console command.
*
* @return mixed
* @throws Exception;
*
* @return int
*/
public function handle(): int
{
Log::debug(sprintf('Now in %s', __METHOD__));
$start = microtime(true);
$groupIds =
TransactionGroup
::leftJoin('transaction_journals','transaction_groups.id','=','transaction_journals.transaction_group_id')
$start = microtime(true);
$groupIds
= TransactionGroup
::leftJoin('transaction_journals', 'transaction_groups.id', '=', 'transaction_journals.transaction_group_id')
->whereNull('transaction_journals.id')->get(['transaction_groups.id'])->pluck('id')->toArray();
$total = count($groupIds);

View File

@@ -58,7 +58,6 @@ class DeleteEmptyJournals extends Command
$this->deleteUnevenJournals();
$this->deleteEmptyJournals();
return 0;
}
@@ -101,18 +100,18 @@ class DeleteEmptyJournals extends Command
->get([DB::raw('COUNT(transactions.transaction_journal_id) as the_count'), 'transaction_journal_id']);
$total = 0;
foreach ($set as $row) {
$count = (int)$row->the_count;
$count = (int) $row->the_count;
if (1 === $count % 2) {
// uneven number, delete journal and transactions:
try {
TransactionJournal::find((int)$row->transaction_journal_id)->delete();
TransactionJournal::find((int) $row->transaction_journal_id)->delete();
// @codeCoverageIgnoreStart
} catch (Exception $e) {
Log::info(sprintf('Could not delete journal: %s', $e->getMessage()));
}
// @codeCoverageIgnoreEnd
Transaction::where('transaction_journal_id', (int)$row->transaction_journal_id)->delete();
Transaction::where('transaction_journal_id', (int) $row->transaction_journal_id)->delete();
$this->info(sprintf('Deleted transaction journal #%d because it had an uneven number of transactions.', $row->transaction_journal_id));
$total++;
}

View File

@@ -51,8 +51,8 @@ class DeleteOrphanedTransactions extends Command
/**
* Execute the console command.
*
* @return int
* @throws Exception
* @return int
*/
public function handle(): int
{
@@ -79,7 +79,7 @@ class DeleteOrphanedTransactions extends Command
/** @var Transaction $transaction */
foreach ($set as $transaction) {
// delete journals
$journal = TransactionJournal::find((int)$transaction->transaction_journal_id);
$journal = TransactionJournal::find((int) $transaction->transaction_journal_id);
if ($journal) {
try {
$journal->delete();
@@ -89,10 +89,13 @@ class DeleteOrphanedTransactions extends Command
}
// @codeCoverageIgnoreEnd
}
Transaction::where('transaction_journal_id', (int)$transaction->transaction_journal_id)->delete();
Transaction::where('transaction_journal_id', (int) $transaction->transaction_journal_id)->delete();
$this->line(
sprintf('Deleted transaction journal #%d because account #%d was already deleted.',
$transaction->transaction_journal_id, $transaction->account_id)
sprintf(
'Deleted transaction journal #%d because account #%d was already deleted.',
$transaction->transaction_journal_id,
$transaction->account_id
)
);
$count++;
}
@@ -120,7 +123,7 @@ class DeleteOrphanedTransactions extends Command
);
/** @var stdClass $entry */
foreach ($set as $entry) {
$transaction = Transaction::find((int)$entry->transaction_id);
$transaction = Transaction::find((int) $entry->transaction_id);
$transaction->delete();
$this->info(
sprintf(
@@ -134,6 +137,5 @@ class DeleteOrphanedTransactions extends Command
if (0 === $count) {
$this->info('No orphaned transactions.');
}
}
}

View File

@@ -49,6 +49,7 @@ class DeleteZeroAmount extends Command
/**
* Execute the console command.
*
* @return int
*/
public function handle(): int

View File

@@ -52,7 +52,7 @@ class EnableCurrencies extends Command
/**
* Execute the console command.
*
* @return mixed
* @return int
*/
public function handle(): int
{
@@ -62,28 +62,28 @@ class EnableCurrencies extends Command
/** @var Collection $meta */
$meta = AccountMeta::where('name', 'currency_id')->groupBy('data')->get(['data']);
foreach ($meta as $entry) {
$found[] = (int)$entry->data;
$found[] = (int) $entry->data;
}
// get all from journals:
/** @var Collection $journals */
$journals = TransactionJournal::groupBy('transaction_currency_id')->get(['transaction_currency_id']);
foreach ($journals as $entry) {
$found[] = (int)$entry->transaction_currency_id;
$found[] = (int) $entry->transaction_currency_id;
}
// get all from transactions
/** @var Collection $transactions */
$transactions = Transaction::groupBy('transaction_currency_id')->get(['transaction_currency_id']);
foreach ($transactions as $entry) {
$found[] = (int)$entry->transaction_currency_id;
$found[] = (int) $entry->transaction_currency_id;
}
// get all from budget limits
/** @var Collection $limits */
$limits = BudgetLimit::groupBy('transaction_currency_id')->get(['transaction_currency_id']);
foreach ($limits as $entry) {
$found[] = (int)$entry->transaction_currency_id;
$found[] = (int) $entry->transaction_currency_id;
}
$found = array_unique($found);

View File

@@ -49,20 +49,20 @@ class FixAccountTypes extends Command
* @var string
*/
protected $signature = 'firefly-iii:fix-account-types';
/** @var int */
private $count;
/** @var array */
private $expected;
/** @var AccountFactory */
private $factory;
/** @var array */
private $fixable;
/** @var int */
private $count;
/**
* Execute the console command.
*
* @return int
* @throws FireflyException
* @return int
*/
public function handle(): int
{
@@ -109,23 +109,12 @@ class FixAccountTypes extends Command
return 0;
}
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
* be called from the handle method instead of using the constructor to initialize the command.
*
* @codeCoverageIgnore
*/
private function stupidLaravel(): void
{
$this->count = 0;
}
/**
* @param TransactionJournal $journal
* @param string $type
* @param Transaction $source
* @param Transaction $dest
* @param string $type
* @param Transaction $source
* @param Transaction $dest
*
* @throws FireflyException
*/
private function fixJournal(TransactionJournal $journal, string $type, Transaction $source, Transaction $dest): void
@@ -167,9 +156,12 @@ class FixAccountTypes extends Command
$dest->save();
$this->info(
sprintf(
'Transaction journal #%d, destination account changed from #%d ("%s") to #%d ("%s").', $journal->id,
$oldDest->id, $oldDest->name,
$result->id, $result->name
'Transaction journal #%d, destination account changed from #%d ("%s") to #%d ("%s").',
$journal->id,
$oldDest->id,
$oldDest->name,
$result->id,
$result->name
)
);
$this->inspectJournal($journal);
@@ -184,9 +176,12 @@ class FixAccountTypes extends Command
$source->save();
$this->info(
sprintf(
'Transaction journal #%d, source account changed from #%d ("%s") to #%d ("%s").', $journal->id,
$oldSource->id, $oldSource->name,
$result->id, $result->name
'Transaction journal #%d, source account changed from #%d ("%s") to #%d ("%s").',
$journal->id,
$oldSource->id,
$oldSource->name,
$result->id,
$result->name
)
);
$this->inspectJournal($journal);
@@ -198,7 +193,6 @@ class FixAccountTypes extends Command
break;
}
}
/**
@@ -274,4 +268,15 @@ class FixAccountTypes extends Command
}
}
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
* be called from the handle method instead of using the constructor to initialize the command.
*
* @codeCoverageIgnore
*/
private function stupidLaravel(): void
{
$this->count = 0;
}
}

View File

@@ -0,0 +1,81 @@
<?php
/**
* FixGroupAccounts.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use DB;
use FireflyIII\Events\UpdatedTransactionGroup;
use FireflyIII\Handlers\Events\UpdatedGroupEventHandler;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Console\Command;
/**
* Class FixGroupAccounts
*/
class FixGroupAccounts extends Command
{
/**
* The console command description.
*
* @var string
*/
protected $description = 'Unify the source / destination accounts of split groups.';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'firefly-iii:unify-group-accounts';
/**
* Execute the console command.
*
* @return int
*/
public function handle(): int
{
// select transaction_group_id, count(transaction_group_id) as the_count from transaction_journals group by transaction_group_id having the_count > 1
$groups = [];
$res = TransactionJournal
::groupBy('transaction_group_id')
->get(['transaction_group_id', DB::raw('COUNT(transaction_group_id) as the_count')]);
foreach ($res as $journal) {
if ((int) $journal->the_count > 1) {
$groups[] = (int) $journal->transaction_group_id;
}
}
$handler = new UpdatedGroupEventHandler;
foreach($groups as $groupId) {
$group = TransactionGroup::find($groupId);
$event = new UpdatedTransactionGroup($group);
$handler->unifyAccounts($event);
}
$this->line('Updated inconsistent transaction groups.');
return 0;
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* FixLongDescriptions.php
* Copyright (c) 2020 james@firefly-iii.org
@@ -19,6 +20,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Models\TransactionGroup;
@@ -51,7 +54,7 @@ class FixLongDescriptions extends Command
*/
public function handle(): int
{
$start = microtime(true);
$start = microtime(true);
$journals = TransactionJournal::get(['id', 'description']);
/** @var TransactionJournal $journal */
foreach ($journals as $journal) {
@@ -65,7 +68,7 @@ class FixLongDescriptions extends Command
$groups = TransactionGroup::get(['id', 'title']);
/** @var TransactionGroup $group */
foreach ($groups as $group) {
if (strlen($group->title) > self::MAX_LENGTH) {
if (strlen((string)$group->title) > self::MAX_LENGTH) {
$group->title = substr($group->title, 0, self::MAX_LENGTH);
$group->save();
$this->line(sprintf('Truncated description of transaction group #%d', $group->id));
@@ -73,6 +76,7 @@ class FixLongDescriptions extends Command
}
$end = round(microtime(true) - $start, 2);
$this->info(sprintf('Verified all transaction group and journal title lengths in %s seconds.', $end));
return 0;
}
}

View File

@@ -54,7 +54,7 @@ class FixPiggies extends Command
/**
* Execute the console command.
*
* @return mixed
* @return int
*/
public function handle(): int
{

View File

@@ -1,4 +1,5 @@
<?php
/**
* FixRecurringTransactions.php
* Copyright (c) 2020 james@firefly-iii.org
@@ -19,6 +20,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Models\Recurrence;
@@ -51,22 +54,12 @@ class FixRecurringTransactions extends Command
/** @var UserRepositoryInterface */
private $userRepos;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
* @return int
*/
public function handle()
public function handle(): int
{
$start = microtime(true);
$this->stupidLaravel();

View File

@@ -63,8 +63,8 @@ class FixUnevenAmount extends Command
->get(['transaction_journal_id', DB::raw('SUM(amount) AS the_sum')]);
/** @var stdClass $entry */
foreach ($journals as $entry) {
if (0 !== bccomp((string)$entry->the_sum, '0')) {
$this->fixJournal((int)$entry->transaction_journal_id);
if (0 !== bccomp((string) $entry->the_sum, '0')) {
$this->fixJournal((int) $entry->transaction_journal_id);
$count++;
}
}
@@ -94,7 +94,8 @@ class FixUnevenAmount extends Command
if (null === $source) {
$this->error(
sprintf(
'Journal #%d ("%s") has no source transaction. It will be deleted to maintain database consistency.', $journal->id ?? 0,
'Journal #%d ("%s") has no source transaction. It will be deleted to maintain database consistency.',
$journal->id ?? 0,
$journal->description ?? ''
)
);
@@ -104,7 +105,7 @@ class FixUnevenAmount extends Command
return;
}
$amount = bcmul('-1', (string)$source->amount);
$amount = bcmul('-1', (string) $source->amount);
// fix amount of destination:
/** @var Transaction $destination */
@@ -113,7 +114,8 @@ class FixUnevenAmount extends Command
if (null === $destination) {
$this->error(
sprintf(
'Journal #%d ("%s") has no destination transaction. It will be deleted to maintain database consistency.', $journal->id ?? 0,
'Journal #%d ("%s") has no destination transaction. It will be deleted to maintain database consistency.',
$journal->id ?? 0,
$journal->description ?? ''
)
);

View File

@@ -48,7 +48,7 @@ class RemoveBills extends Command
/**
* Execute the console command.
*
* @return mixed
* @return int
*/
public function handle(): int
{

View File

@@ -1,6 +1,5 @@
<?php
/**
* CreateDatabase.php
* Copyright (c) 2020 james@firefly-iii.org
@@ -21,6 +20,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands;
use Illuminate\Console\Command;
@@ -49,9 +50,9 @@ class CreateDatabase extends Command
/**
* Execute the console command.
*
* @return mixed
* @return int
*/
public function handle()
public function handle(): int
{
if ('mysql' !== env('DB_CONNECTION')) {
$this->info(sprintf('CreateDB does not apply to "%s", skipped.', env('DB_CONNECTION')));

View File

@@ -30,6 +30,7 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Preference;
use Illuminate\Console\Command;
use Illuminate\Contracts\Encryption\DecryptException;
use JsonException;
use Log;
/**
@@ -54,8 +55,8 @@ class DecryptDatabase extends Command
/**
* Execute the console command.
*
* @return int
* @throws FireflyException
* @return int
*/
public function handle(): int
{
@@ -92,11 +93,15 @@ class DecryptDatabase extends Command
// A separate routine for preferences:
if ('preferences' === $table) {
// try to json_decrypt the value.
$value = json_decode($value, true) ?? $value;
try {
$value = json_decode($value, true, 512, JSON_THROW_ON_ERROR) ?? $value;
} catch(JsonException $e) {
Log::error($e->getMessage());
}
Log::debug(sprintf('Decrypted field "%s" "%s" to "%s" in table "%s" (row #%d)', $field, $original, print_r($value, true), $table, $id));
/** @var Preference $object */
$object = Preference::find((int)$id);
$object = Preference::find((int) $id);
if (null !== $object) {
$object->data = $value;
$object->save();
@@ -131,7 +136,7 @@ class DecryptDatabase extends Command
$configName = sprintf('is_decrypted_%s', $table);
$configVar = app('fireflyconfig')->get($configName, false);
if (null !== $configVar) {
return (bool)$configVar->data;
return (bool) $configVar->data;
}
return false;
@@ -142,8 +147,9 @@ class DecryptDatabase extends Command
* Tries to decrypt data. Will only throw an exception when the MAC is invalid.
*
* @param $value
* @return string
*
* @throws FireflyException
* @return string
*/
private function tryDecrypt($value)
{
@@ -153,7 +159,6 @@ class DecryptDatabase extends Command
if ('The MAC is invalid.' === $e->getMessage()) {
throw new FireflyException($e->getMessage()); // @codeCoverageIgnore
}
Log::debug(sprintf('Could not decrypt. %s', $e->getMessage()));
}
return $value;

View File

@@ -1,4 +1,5 @@
<?php
/**
* ExportData.php
* Copyright (c) 2020 james@firefly-iii.org
@@ -19,9 +20,12 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Export;
use Carbon\Carbon;
use Exception;
use FireflyIII\Console\Commands\VerifiesAccessToken;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\AccountType;
@@ -32,6 +36,7 @@ use FireflyIII\User;
use Illuminate\Console\Command;
use Illuminate\Support\Collection;
use InvalidArgumentException;
use League\Csv\CannotInsertRecord;
use Log;
/**
@@ -76,21 +81,12 @@ class ExportData extends Command
/** @var User */
private $user;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
* @throws FireflyException
* @throws CannotInsertRecord
* @return int
*/
public function handle(): int
{
@@ -142,8 +138,12 @@ class ExportData extends Command
$this->exportData($options, $data);
} catch (FireflyException $e) {
$this->error(sprintf('Could not store data: %s', $e->getMessage()));
app('telemetry')->feature('system.command.errored', $this->signature);
return 1;
}
app('telemetry')->feature('system.command.executed', $this->signature);
return 0;
}
@@ -171,8 +171,8 @@ class ExportData extends Command
}
/**
* @return Collection
* @throws FireflyException
* @return Collection
*/
private function getAccountsParameter(): Collection
{
@@ -180,7 +180,7 @@ class ExportData extends Command
$accounts = new Collection;
$accountList = $this->option('accounts');
$types = [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE];
if (null !== $accountList && '' !== (string)$accountList) {
if (null !== $accountList && '' !== (string) $accountList) {
$accountIds = explode(',', $accountList);
$accounts = $this->accountRepository->getAccountsById($accountIds);
}
@@ -204,8 +204,9 @@ class ExportData extends Command
/**
* @param string $field
*
* @return Carbon
* @throws FireflyException
* @throws Exception
* @return Carbon
*/
private function getDateParameter(string $field): Carbon
{
@@ -239,12 +240,13 @@ class ExportData extends Command
}
/**
* @return string
* @throws FireflyException
*
* @return string
*/
private function getExportDirectory(): string
{
$directory = $this->option('export_directory');
$directory = (string) $this->option('export_directory');
if (null === $directory) {
$directory = './';
}
@@ -256,8 +258,8 @@ class ExportData extends Command
}
/**
* @return array
* @throws FireflyException
* @return array
*/
private function parseOptions(): array
{

View File

@@ -1,332 +0,0 @@
<?php
/**
* CreateCSVImport.php
* Copyright (c) 2020 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/>.
*/
/** @noinspection MultipleReturnStatementsInspection */
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Import;
use Exception;
use FireflyIII\Console\Commands\VerifiesAccessToken;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Import\Routine\RoutineInterface;
use FireflyIII\Import\Storage\ImportArrayStorage;
use FireflyIII\Models\ImportJob;
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\User;
use Illuminate\Console\Command;
use Log;
/**
* Class CreateCSVImport.
*/
class CreateCSVImport extends Command
{
use VerifiesAccessToken;
/**
* The console command description.
*
* @var string
*/
protected $description = 'Use this command to create a new CSV file import.';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature
= 'firefly-iii:csv-import
{file? : The CSV file to import.}
{configuration? : The configuration file to use for the import.}
{--user=1 : The user ID that the import should import for.}
{--token= : The user\'s access token.}';
/** @var UserRepositoryInterface */
private $userRepository;
/** @var ImportJobRepositoryInterface */
private $importRepository;
/** @var ImportJob */
private $importJob;
/**
* Run the command.
*/
public function handle(): int
{
$this->stupidLaravel();
// @codeCoverageIgnoreStart
if (!$this->verifyAccessToken()) {
$this->errorLine('Invalid access token.');
return 1;
}
if (!$this->validArguments()) {
$this->errorLine('Invalid arguments.');
return 1;
}
// @codeCoverageIgnoreEnd
/** @var User $user */
$user = $this->userRepository->findNull((int)$this->option('user'));
$file = (string)$this->argument('file');
$configuration = (string)$this->argument('configuration');
$this->importRepository->setUser($user);
$configurationData = json_decode(file_get_contents($configuration), true);
$this->importJob = $this->importRepository->create('file');
// inform user (and log it)
$this->infoLine(sprintf('Import file : %s', $file));
$this->infoLine(sprintf('Configuration file : %s', $configuration));
$this->infoLine(sprintf('User : #%d (%s)', $user->id, $user->email));
$this->infoLine(sprintf('Job : %s', $this->importJob->key));
try {
$this->storeFile($file);
} catch (FireflyException $e) {
$this->errorLine($e->getMessage());
return 1;
}
// job is ready to go
$this->importRepository->setConfiguration($this->importJob, $configurationData);
$this->importRepository->setStatus($this->importJob, 'ready_to_run');
$this->infoLine('The import routine has started. The process is not visible. Please wait.');
Log::debug('Go for import!');
// keep repeating this call until job lands on "provider_finished"
try {
$this->processFile();
} catch (FireflyException $e) {
$this->errorLine($e->getMessage());
return 1;
}
// then store data:
try {
$this->storeData();
} catch (FireflyException $e) {
$this->errorLine($e->getMessage());
return 1;
}
// give feedback:
$this->giveFeedback();
// clear cache for user:
app('preferences')->setForUser($user, 'lastActivity', microtime());
return 0;
}
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
* be called from the handle method instead of using the constructor to initialize the command.
*
* @codeCoverageIgnore
*/
private function stupidLaravel(): void
{
$this->userRepository = app(UserRepositoryInterface::class);
$this->importRepository = app(ImportJobRepositoryInterface::class);
}
/**
* @param string $message
* @param array|null $data
* @codeCoverageIgnore
*/
private function errorLine(string $message, array $data = null): void
{
Log::error($message, $data ?? []);
$this->error($message);
}
/**
* @param string $message
* @param array $data
* @codeCoverageIgnore
*/
private function infoLine(string $message, array $data = null): void
{
Log::info($message, $data ?? []);
$this->line($message);
}
/**
* Verify user inserts correct arguments.
*
* @noinspection MultipleReturnStatementsInspection
* @return bool
* @codeCoverageIgnore
*/
private function validArguments(): bool
{
$file = (string)$this->argument('file');
$configuration = (string)$this->argument('configuration');
$cwd = getcwd();
$enabled = (bool)config('import.enabled.file');
if (false === $enabled) {
$this->errorLine('CSV Provider is not enabled.');
return false;
}
if (!file_exists($file)) {
$this->errorLine(sprintf('Firefly III cannot find file "%s" (working directory: "%s").', $file, $cwd));
return false;
}
if (!file_exists($configuration)) {
$this->errorLine(sprintf('Firefly III cannot find configuration file "%s" (working directory: "%s").', $configuration, $cwd));
return false;
}
$configurationData = json_decode(file_get_contents($configuration), true);
if (null === $configurationData) {
$this->errorLine(sprintf('Firefly III cannot read the contents of configuration file "%s" (working directory: "%s").', $configuration, $cwd));
return false;
}
return true;
}
/**
* Store the supplied file as an attachment to this job.
*
* @param string $file
* @throws FireflyException
*/
private function storeFile(string $file): void
{
// store file as attachment.
if ('' !== $file) {
$messages = $this->importRepository->storeCLIUpload($this->importJob, 'import_file', $file);
if ($messages->count() > 0) {
throw new FireflyException($messages->first());
}
}
}
/**
* Keep repeating import call until job lands on "provider_finished".
*
* @throws FireflyException
*/
private function processFile(): void
{
$className = config('import.routine.file');
$valid = ['provider_finished'];
$count = 0;
while (!in_array($this->importJob->status, $valid, true) && $count < 6) {
Log::debug(sprintf('Now in loop #%d.', $count + 1));
/** @var RoutineInterface $routine */
$routine = app($className);
$routine->setImportJob($this->importJob);
try {
$routine->run();
} catch (FireflyException|Exception $e) {
$message = 'The import routine crashed: ' . $e->getMessage();
Log::error($message);
Log::error($e->getTraceAsString());
// set job errored out:
$this->importRepository->setStatus($this->importJob, 'error');
throw new FireflyException($message);
}
$count++;
}
$this->importRepository->setStatus($this->importJob, 'provider_finished');
$this->importJob->status = 'provider_finished';
}
/**
*
* @throws FireflyException
*/
private function storeData(): void
{
if ('provider_finished' === $this->importJob->status) {
$this->infoLine('Import has finished. Please wait for storage of data.');
// set job to be storing data:
$this->importRepository->setStatus($this->importJob, 'storing_data');
/** @var ImportArrayStorage $storage */
$storage = app(ImportArrayStorage::class);
$storage->setImportJob($this->importJob);
try {
$storage->store();
} catch (FireflyException|Exception $e) {
$message = 'The import routine crashed: ' . $e->getMessage();
Log::error($message);
Log::error($e->getTraceAsString());
// set job errored out:
$this->importRepository->setStatus($this->importJob, 'error');
throw new FireflyException($message);
}
// set storage to be finished:
$this->importRepository->setStatus($this->importJob, 'storage_finished');
}
}
/**
*
*/
private function giveFeedback(): void
{
$this->infoLine('Job has finished.');
if (null !== $this->importJob->tag) {
$this->infoLine(sprintf('%d transaction(s) have been imported.', $this->importJob->tag->transactionJournals->count()));
$this->infoLine(sprintf('You can find your transactions under tag "%s"', $this->importJob->tag->tag));
}
if (null === $this->importJob->tag) {
$this->errorLine('No transactions have been imported :(.');
}
if (count($this->importJob->errors) > 0) {
$this->infoLine(sprintf('%d error(s) occurred:', count($this->importJob->errors)));
foreach ($this->importJob->errors as $err) {
$this->errorLine('- ' . $err);
}
}
}
}

View File

@@ -30,6 +30,7 @@ use Schema;
/**
* Class ReportIntegrity
*
* @codeCoverageIgnore
*/
class ReportIntegrity extends Command

View File

@@ -69,7 +69,7 @@ class ReportSum extends Command
/** @var User $user */
foreach ($userRepository->all() as $user) {
$sum = (string)$user->transactions()->sum('amount');
$sum = (string) $user->transactions()->sum('amount');
if (0 !== bccomp($sum, '0')) {
$message = sprintf('Error: Transactions for user #%d (%s) are off by %s!', $user->id, $user->email, $sum);
$this->error($message);

View File

@@ -1,4 +1,5 @@
<?php
/**
* RestoreOAuthKeys.php
* Copyright (c) 2020 james@firefly-iii.org
@@ -19,12 +20,13 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Integrity;
use Artisan;
use Crypt;
use FireflyIII\Support\System\OAuthKeys;
use Illuminate\Console\Command;
use Log;
/**
* Class RestoreOAuthKeys
@@ -93,7 +95,9 @@ class RestoreOAuthKeys extends Command
*/
private function restoreOAuthKeys(): void
{
Log::debug('Going to restoreOAuthKeys()');
if (!$this->keysInDatabase() && !$this->keysOnDrive()) {
Log::debug('Keys are not in DB and keys are not on the drive.');
$this->generateKeys();
$this->storeKeysInDB();
$this->line('Generated and stored new keys.');
@@ -101,12 +105,14 @@ class RestoreOAuthKeys extends Command
return;
}
if ($this->keysInDatabase() && !$this->keysOnDrive()) {
Log::debug('Keys are in DB and keys are not on the drive. Restore.');
$this->restoreKeysFromDB();
$this->line('Restored OAuth keys from database.');
return;
}
if (!$this->keysInDatabase() && $this->keysOnDrive()) {
Log::debug('Keys are not in DB and keys are on the drive. Save in DB.');
$this->storeKeysInDB();
$this->line('Stored OAuth keys in database.');
@@ -122,4 +128,4 @@ class RestoreOAuthKeys extends Command
{
OAuthKeys::storeKeysInDB();
}
}
}

View File

@@ -63,8 +63,7 @@ class ScanAttachments extends Command
$disk = Storage::disk('upload');
/** @var Attachment $attachment */
foreach ($attachments as $attachment) {
$fileName = $attachment->fileName();
$decryptedContent = '';
$fileName = $attachment->fileName();
try {
$encryptedContent = $disk->get($fileName);
} catch (FileNotFoundException $e) {
@@ -87,6 +86,7 @@ class ScanAttachments extends Command
$this->line(sprintf('Fixed attachment #%d', $attachment->id));
}
app('telemetry')->feature('system.command.executed', $this->signature);
return 0;
}
}

View File

@@ -1,6 +1,5 @@
<?php
/**
* SetLatestVersion.php
* Copyright (c) 2020 james@firefly-iii.org
@@ -21,6 +20,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands;
use Illuminate\Console\Command;
@@ -43,16 +44,6 @@ class SetLatestVersion extends Command
*/
protected $signature = 'firefly-iii:set-latest-version {--james-is-cool}';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
@@ -69,8 +60,7 @@ class SetLatestVersion extends Command
app('fireflyconfig')->set('ff3_version', config('firefly.version'));
$this->line('Updated version.');
//Telemetry::string('db_version', config('firefly.db_version'));
//Telemetry::string('ff3_version', config('firefly.version'));
app('telemetry')->feature('system.command.executed', $this->signature);
return 0;
}

View File

@@ -60,7 +60,7 @@ class ApplyRules extends Command
*/
protected $signature
= 'firefly-iii:apply-rules
{--user=1 : The user ID that the import should import for.}
{--user=1 : The user ID.}
{--token= : The user\'s access token.}
{--accounts= : A comma-separated list of asset accounts or liabilities to apply your rules to.}
{--rule_groups= : A comma-separated list of rule groups to apply. Take the ID\'s of these rule groups from the Firefly III interface.}
@@ -68,35 +68,32 @@ class ApplyRules extends Command
{--all_rules : If set, will overrule both settings and simply apply ALL of your rules.}
{--start_date= : The date of the earliest transaction to be included (inclusive). If omitted, will be your very first transaction ever. Format: YYYY-MM-DD}
{--end_date= : The date of the latest transaction to be included (inclusive). If omitted, will be your latest transaction ever. Format: YYYY-MM-DD}';
/** @var Collection */
private $accounts;
/** @var array */
private $acceptedAccounts;
/** @var Collection */
private $accounts;
/** @var bool */
private $allRules;
/** @var Carbon */
private $endDate;
/** @var Collection */
private $groups;
/** @var RuleGroupRepositoryInterface */
private $ruleGroupRepository;
/** @var array */
private $ruleGroupSelection;
/** @var RuleRepositoryInterface */
private $ruleRepository;
/** @var array */
private $ruleSelection;
/** @var Carbon */
private $startDate;
/** @var Collection */
private $groups;
/** @var bool */
private $allRules;
/** @var RuleRepositoryInterface */
private $ruleRepository;
/** @var RuleGroupRepositoryInterface */
private $ruleGroupRepository;
/**
* Execute the console command.
*
* @return int
* @throws FireflyException
* @return int
*/
public function handle(): int
{
@@ -115,6 +112,7 @@ class ApplyRules extends Command
$result = $this->verifyInput();
if (false === $result) {
app('telemetry')->feature('system.command.errored', $this->signature);
return 1;
}
@@ -132,6 +130,9 @@ class ApplyRules extends Command
$this->warn(' --rules=1,2,...');
$this->warn(' --rule_groups=1,2,...');
$this->warn(' --all_rules');
app('telemetry')->feature('system.command.errored', $this->signature);
return 1;
}
/** @var GroupCollectorInterface $collector */
@@ -166,9 +167,53 @@ class ApplyRules extends Command
$this->line('');
$this->line('Done!');
app('telemetry')->feature('system.command.executed', $this->signature);
return 0;
}
/**
* @return array
*/
private function getRulesToApply(): array
{
$rulesToApply = [];
/** @var RuleGroup $group */
foreach ($this->groups as $group) {
$rules = $this->ruleGroupRepository->getActiveStoreRules($group);
/** @var Rule $rule */
foreach ($rules as $rule) {
// if in rule selection, or group in selection or all rules, it's included.
$test = $this->includeRule($rule, $group);
if (true === $test) {
Log::debug(sprintf('Will include rule #%d "%s"', $rule->id, $rule->title));
$rulesToApply[] = $rule->id;
}
}
}
return $rulesToApply;
}
/**
*/
private function grabAllRules(): void
{
$this->groups = $this->ruleGroupRepository->getActiveGroups();
}
/**
* @param Rule $rule
* @param RuleGroup $group
*
* @return bool
*/
private function includeRule(Rule $rule, RuleGroup $group): bool
{
return in_array($group->id, $this->ruleGroupSelection, true)
|| in_array($rule->id, $this->ruleSelection, true)
|| $this->allRules;
}
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
@@ -189,8 +234,8 @@ class ApplyRules extends Command
}
/**
* @return bool
* @throws FireflyException
* @return bool
*/
private function verifyInput(): bool
{
@@ -212,8 +257,8 @@ class ApplyRules extends Command
}
/**
* @return bool
* @throws FireflyException
* @return bool
*/
private function verifyInputAccounts(): bool
{
@@ -240,7 +285,7 @@ class ApplyRules extends Command
foreach ($accountList as $accountId) {
$accountId = (int)$accountId;
$accountId = (int) $accountId;
$account = $accountRepository->findNull($accountId);
if (null !== $account && in_array($account->accountType->type, $this->acceptedAccounts, true)) {
$finalList->push($account);
@@ -258,66 +303,6 @@ class ApplyRules extends Command
}
/**
* @return bool
*/
private function verifyInputRuleGroups(): bool
{
$ruleGroupString = $this->option('rule_groups');
if (null === $ruleGroupString || '' === $ruleGroupString) {
// can be empty.
return true;
}
$ruleGroupList = explode(',', $ruleGroupString);
// @codeCoverageIgnoreStart
if (0 === count($ruleGroupList)) {
// can be empty.
return true;
}
// @codeCoverageIgnoreEnd
foreach ($ruleGroupList as $ruleGroupId) {
$ruleGroup = $this->ruleGroupRepository->find((int)$ruleGroupId);
if ($ruleGroup->active) {
$this->ruleGroupSelection[] = $ruleGroup->id;
}
if (false === $ruleGroup->active) {
$this->warn(sprintf('Will ignore inactive rule group #%d ("%s")', $ruleGroup->id, $ruleGroup->title));
}
}
return true;
}
/**
* @return bool
*/
private function verifyInputRules(): bool
{
$ruleString = $this->option('rules');
if (null === $ruleString || '' === $ruleString) {
// can be empty.
return true;
}
$ruleList = explode(',', $ruleString);
// @codeCoverageIgnoreStart
if (0 === count($ruleList)) {
// can be empty.
return true;
}
// @codeCoverageIgnoreEnd
foreach ($ruleList as $ruleId) {
$rule = $this->ruleRepository->find((int)$ruleId);
if (null !== $rule && $rule->active) {
$this->ruleSelection[] = $rule->id;
}
}
return true;
}
/**
* @throws FireflyException
*/
@@ -355,44 +340,62 @@ class ApplyRules extends Command
}
/**
*/
private function grabAllRules(): void
{
$this->groups = $this->ruleGroupRepository->getActiveGroups();
}
/**
* @param Rule $rule
* @param RuleGroup $group
* @return bool
*/
private function includeRule(Rule $rule, RuleGroup $group): bool
private function verifyInputRuleGroups(): bool
{
return in_array($group->id, $this->ruleGroupSelection, true) ||
in_array($rule->id, $this->ruleSelection, true) ||
$this->allRules;
}
/**
* @return array
*/
private function getRulesToApply(): array
{
$rulesToApply = [];
/** @var RuleGroup $group */
foreach ($this->groups as $group) {
$rules = $this->ruleGroupRepository->getActiveStoreRules($group);
/** @var Rule $rule */
foreach ($rules as $rule) {
// if in rule selection, or group in selection or all rules, it's included.
$test = $this->includeRule($rule, $group);
if (true === $test) {
Log::debug(sprintf('Will include rule #%d "%s"', $rule->id, $rule->title));
$rulesToApply[] = $rule->id;
}
$ruleGroupString = $this->option('rule_groups');
if (null === $ruleGroupString || '' === $ruleGroupString) {
// can be empty.
return true;
}
$ruleGroupList = explode(',', $ruleGroupString);
// @codeCoverageIgnoreStart
if (0 === count($ruleGroupList)) {
// can be empty.
return true;
}
// @codeCoverageIgnoreEnd
foreach ($ruleGroupList as $ruleGroupId) {
$ruleGroup = $this->ruleGroupRepository->find((int) $ruleGroupId);
if ($ruleGroup->active) {
$this->ruleGroupSelection[] = $ruleGroup->id;
}
if (false === $ruleGroup->active) {
$this->warn(sprintf('Will ignore inactive rule group #%d ("%s")', $ruleGroup->id, $ruleGroup->title));
}
}
return $rulesToApply;
return true;
}
/**
* @return bool
*/
private function verifyInputRules(): bool
{
$ruleString = $this->option('rules');
if (null === $ruleString || '' === $ruleString) {
// can be empty.
return true;
}
$ruleList = explode(',', $ruleString);
// @codeCoverageIgnoreStart
if (0 === count($ruleList)) {
// can be empty.
return true;
}
// @codeCoverageIgnoreEnd
foreach ($ruleList as $ruleId) {
$rule = $this->ruleRepository->find((int) $ruleId);
if (null !== $rule && $rule->active) {
$this->ruleSelection[] = $rule->id;
}
}
return true;
}
}

View File

@@ -27,9 +27,12 @@ namespace FireflyIII\Console\Commands\Tools;
use Carbon\Carbon;
use Exception;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Support\Cronjobs\AutoBudgetCronjob;
use FireflyIII\Support\Cronjobs\RecurringCronjob;
use FireflyIII\Support\Cronjobs\TelemetryCronjob;
use Illuminate\Console\Command;
use InvalidArgumentException;
use Log;
/**
* Class Cron
@@ -56,45 +59,137 @@ class Cron extends Command
/**
* @return int
* @throws Exception
*/
public function handle(): int
{
$date = null;
try {
$date = new Carbon($this->option('date'));
} catch (InvalidArgumentException $e) {
} catch (InvalidArgumentException|Exception $e) {
$this->error(sprintf('"%s" is not a valid date', $this->option('date')));
$e->getMessage();
}
$force = (bool) $this->option('force');
/*
* Fire recurring transaction cron job.
*/
try {
$this->recurringCronJob($force, $date);
} catch (FireflyException $e) {
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
$this->error($e->getMessage());
}
/*
* Fire auto-budget cron job:
*/
try {
$this->autoBudgetCronJob($force, $date);
} catch (FireflyException $e) {
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
$this->error($e->getMessage());
}
/*
* Fire telemetry cron job
*/
try {
$this->telemetryCronJob($force, $date);
} catch (FireflyException $e) {
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
$this->error($e->getMessage());
}
$this->info('More feedback on the cron jobs can be found in the log files.');
app('telemetry')->feature('system.command.executed', $this->signature);
return 0;
}
/**
* @param bool $force
* @param Carbon|null $date
*
* @throws FireflyException
* @throws Exception
*/
private function autoBudgetCronJob(bool $force, ?Carbon $date): void
{
$autoBudget = new AutoBudgetCronjob;
$autoBudget->setForce($force);
// set date in cron job:
if (null !== $date) {
$autoBudget->setDate($date);
}
$result = $autoBudget->fire();
if (false === $result) {
$this->line('The auto budget cron job did not fire.');
}
if (true === $result) {
$this->line('The auto budget cron job fired successfully.');
}
}
/**
* @param bool $force
* @param Carbon|null $date
*
* @throws FireflyException
*/
private function recurringCronJob(bool $force, ?Carbon $date): void
{
$recurring = new RecurringCronjob;
$recurring->setForce($this->option('force'));
$recurring->setForce($force);
// set date in cron job:
if (null !== $date) {
$recurring->setDate($date);
}
try {
$result = $recurring->fire();
} catch (FireflyException $e) {
$this->error($e->getMessage());
$result = $recurring->fire();
return 0;
}
if (false === $result) {
$this->line('The recurring transaction cron job did not fire.');
}
if (true === $result) {
$this->line('The recurring transaction cron job fired successfully.');
}
$this->info('More feedback on the cron jobs can be found in the log files.');
return 0;
}
/**
* @param bool $force
* @param Carbon|null $date
*/
private function telemetryCronJob(bool $force, ?Carbon $date): void
{
if (false === config('firefly.send_telemetry') || false === config('firefly.feature_flags.telemetry')) {
// if not configured to do anything with telemetry, do nothing.
return;
}
$telemetry = new TelemetryCronJob;
$telemetry->setForce($force);
// set date in cron job:
if (null !== $date) {
$telemetry->setDate($date);
}
$result = $telemetry->fire();
if (false === $result) {
$this->line('The telemetry cron job did not fire.');
}
if (true === $result) {
$this->line('The telemetry cron job fired successfully.');
}
}
}

View File

@@ -54,10 +54,10 @@ class AccountCurrencies extends Command
protected $signature = 'firefly-iii:account-currencies {--F|force : Force the execution of this command.}';
/** @var AccountRepositoryInterface */
private $accountRepos;
/** @var UserRepositoryInterface */
private $userRepos;
/** @var int */
private $count;
/** @var UserRepositoryInterface */
private $userRepos;
/**
* Each (asset) account must have a reference to a preferred currency. If the account does not have one, it's forced upon the account.
@@ -87,9 +87,31 @@ class AccountCurrencies extends Command
$this->info(sprintf('Verified and fixed account currencies in %s seconds.', $end));
$this->markAsExecuted();
return 0;
}
/**
* @return bool
*/
private function isExecuted(): bool
{
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
if (null !== $configVar) {
return (bool) $configVar->data;
}
return false; // @codeCoverageIgnore
}
/**
*
*/
private function markAsExecuted(): void
{
app('fireflyconfig')->set(self::CONFIG_NAME, true);
}
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
@@ -105,29 +127,7 @@ class AccountCurrencies extends Command
}
/**
* @return bool
*/
private function isExecuted(): bool
{
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
if (null !== $configVar) {
return (bool)$configVar->data;
}
return false; // @codeCoverageIgnore
}
/**
*
*/
private function markAsExecuted(): void
{
app('fireflyconfig')->set(self::CONFIG_NAME, true);
}
/**
* @param Account $account
* @param Account $account
* @param TransactionCurrency $currency
*/
private function updateAccount(Account $account, TransactionCurrency $currency): void
@@ -135,13 +135,13 @@ class AccountCurrencies extends Command
Log::debug(sprintf('Now in updateAccount(%d, %s)', $account->id, $currency->code));
$this->accountRepos->setUser($account->user);
$accountCurrency = (int)$this->accountRepos->getMetaValue($account, 'currency_id');
$accountCurrency = (int) $this->accountRepos->getMetaValue($account, 'currency_id');
Log::debug(sprintf('Account currency is #%d', $accountCurrency));
$openingBalance = $this->accountRepos->getOpeningBalance($account);
$obCurrency = 0;
$openingBalance = $this->accountRepos->getOpeningBalance($account);
$obCurrency = 0;
if (null !== $openingBalance) {
$obCurrency = (int)$openingBalance->transaction_currency_id;
$obCurrency = (int) $openingBalance->transaction_currency_id;
Log::debug('Account has opening balance.');
}
Log::debug(sprintf('Account OB currency is #%d.', $obCurrency));
@@ -178,7 +178,8 @@ class AccountCurrencies extends Command
static function (Transaction $transaction) use ($accountCurrency) {
$transaction->transaction_currency_id = $accountCurrency;
$transaction->save();
});
}
);
$this->line(sprintf('Account #%d ("%s") now has a correct currency for opening balance.', $account->id, $account->name));
$this->count++;
@@ -194,7 +195,7 @@ class AccountCurrencies extends Command
{
Log::debug('Now in updateAccountCurrencies()');
$users = $this->userRepos->all();
$defaultCurrencyCode = (string)config('firefly.default_currency', 'EUR');
$defaultCurrencyCode = (string) config('firefly.default_currency', 'EUR');
Log::debug(sprintf('Default currency is %s', $defaultCurrencyCode));
foreach ($users as $user) {
$this->updateCurrenciesForUser($user, $defaultCurrencyCode);
@@ -202,7 +203,7 @@ class AccountCurrencies extends Command
}
/**
* @param User $user
* @param User $user
* @param string $systemCurrencyCode
*/
private function updateCurrenciesForUser(User $user, string $systemCurrencyCode): void

View File

@@ -111,9 +111,9 @@ class BackToJournals extends Command
$chunks = array_chunk($transactions, 500);
foreach ($chunks as $chunk) {
$set = DB::table('transactions')
->whereIn('transactions.id', $chunk)
->get(['transaction_journal_id'])->pluck('transaction_journal_id')->toArray();
$set = DB::table('transactions')
->whereIn('transactions.id', $chunk)
->get(['transaction_journal_id'])->pluck('transaction_journal_id')->toArray();
/** @noinspection SlowArrayOperationsInLoopInspection */
$array = array_merge($array, $set);
}
@@ -128,7 +128,7 @@ class BackToJournals extends Command
{
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
if (null !== $configVar) {
return (bool)$configVar->data;
return (bool) $configVar->data;
}
return false; // @codeCoverageIgnore
@@ -141,7 +141,7 @@ class BackToJournals extends Command
{
$configVar = app('fireflyconfig')->get(MigrateToGroups::CONFIG_NAME, false);
if (null !== $configVar) {
return (bool)$configVar->data;
return (bool) $configVar->data;
}
return false; // @codeCoverageIgnore
@@ -212,7 +212,7 @@ class BackToJournals extends Command
// both have a budget, but they don't match.
if (null !== $budget && null !== $journalBudget && $budget->id !== $journalBudget->id) {
// sync to journal:
$journal->budgets()->sync([(int)$budget->id]);
$journal->budgets()->sync([(int) $budget->id]);
return;
}
@@ -220,7 +220,7 @@ class BackToJournals extends Command
// transaction has a budget, but the journal doesn't.
if (null !== $budget && null === $journalBudget) {
// sync to journal:
$journal->budgets()->sync([(int)$budget->id]);
$journal->budgets()->sync([(int) $budget->id]);
}
}
@@ -271,12 +271,12 @@ class BackToJournals extends Command
// both have a category, but they don't match.
if (null !== $category && null !== $journalCategory && $category->id !== $journalCategory->id) {
// sync to journal:
$journal->categories()->sync([(int)$category->id]);
$journal->categories()->sync([(int) $category->id]);
}
// transaction has a category, but the journal doesn't.
if (null !== $category && null === $journalCategory) {
$journal->categories()->sync([(int)$category->id]);
$journal->categories()->sync([(int) $category->id]);
}
}
}

View File

@@ -102,7 +102,7 @@ class BudgetLimitCurrency extends Command
{
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
if (null !== $configVar) {
return (bool)$configVar->data;
return (bool) $configVar->data;
}
return false; // @codeCoverageIgnore

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